/**
 * @file 
 * @author George Mount
 *
 * @brief Mock Windows Registry functions
 *
 * Copyright (c) 2009 NVIDIA Corporation. All rights reserved.
 *
 * NVIDIA Corporation and its licensors retain all intellectual property and 
 * proprietary rights in and to this software, related documentation and any 
 * modifications thereto. Any use, reproduction, disclosure or distribution of 
 * this software and related documentation without express license agreement 
 * from NVIDIA Corporation is strictly prohibited.
 */

#pragma once
#include <windows.h>
#include <shlwapi.h>
#include <map>
#include <vector>
#include <tstd.h>
#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>

namespace Nvidia
{
    namespace Logging
    {
        namespace Test
        {
            struct RegistryValue
            {
                unsigned long             Type;
                size_t                    BufLength;
                boost::shared_array<char> Buf;
            };

            struct RegistryEntry
            {
                typedef std::map<std::tstring, RegistryValue> ValuesMap;
                typedef std::map<std::tstring, boost::shared_ptr<RegistryEntry> > SubKeysMap;
                HKEY       Key;
                ValuesMap  Values;
                SubKeysMap SubKeys;
            };

            class MockWinApi
            {
            public:
                typedef std::map<HKEY, boost::shared_ptr<RegistryEntry> > RegistryMap;
                static RegistryMap m_registry;
                static long m_returnCode;
                static DWORD m_createFileFlags;

            private:
                MockWinApi();

            public:
                static LSTATUS RegOpenCurrentUser(
                    __in REGSAM samDesired,
                    __out PHKEY phkResult
                    );

                static LSTATUS RegCreateKeyEx (
                    __in HKEY hKey,
                    __in LPCTSTR lpSubKey,
                    __reserved DWORD Reserved,
                    __in_opt LPTSTR lpClass,
                    __in DWORD dwOptions,
                    __in REGSAM samDesired,
                    __in_opt CONST LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                    __out PHKEY phkResult,
                    __out_opt LPDWORD lpdwDisposition
                    );
                static LSTATUS RegOpenKeyEx (
                    __in HKEY hKey,
                    __in_opt LPCTSTR lpSubKey,
                    __in_opt DWORD ulOptions,
                    __in REGSAM samDesired,
                    __out PHKEY phkResult
                    );
                static LSTATUS STDAPICALLTYPE SHDeleteKey (
                    __in HKEY hKey,
                    __in LPCTSTR lpSubKey
                    );
                static LSTATUS RegDeleteValue (
                    __in HKEY hKey,
                    __in_opt LPCTSTR lpValueName
                    );
                static LSTATUS RegSetValueEx (
                    __in HKEY hKey,
                    __in_opt LPCTSTR lpValueName,
                    __reserved DWORD Reserved,
                    __in DWORD dwType,
                    __in_bcount_opt(cbData) CONST BYTE* lpData,
                    __in DWORD cbData
                    );
                static LSTATUS RegEnumValue (
                    __in HKEY hKey,
                    __in DWORD dwIndex,
                    __out_ecount_part_opt(*lpcchValueName, *lpcchValueName + 1) LPTSTR lpValueName,
                    __inout LPDWORD lpcchValueName,
                    __reserved LPDWORD lpReserved,
                    __out_opt LPDWORD lpType,
                    __out_bcount_part_opt(*lpcbData, *lpcbData) __out_data_source(REGISTRY) LPBYTE lpData,
                    __inout_opt LPDWORD lpcbData
                    );
                static LSTATUS RegQueryValueEx (
                    __in HKEY hKey,
                    __in_opt LPCTSTR lpValueName,
                    __reserved LPDWORD lpReserved,
                    __out_opt LPDWORD lpType,
                    __out_bcount_part_opt(*lpcbData, *lpcbData) __out_data_source(REGISTRY) LPBYTE lpData,
                    __inout_opt LPDWORD lpcbData
                    );
                static LSTATUS RegEnumKeyEx (
                    __in HKEY hKey,
                    __in DWORD dwIndex,
                    __out_ecount_part_opt(*lpcchName, *lpcchName + 1) LPTSTR lpName,
                    __inout LPDWORD lpcchName,
                    __reserved LPDWORD lpReserved,
                    __out_ecount_part_opt(*lpcchClass,*lpcchClass + 1) LPTSTR lpClass,
                    __inout_opt LPDWORD lpcchClass,
                    __out_opt PFILETIME lpftLastWriteTime
                    );

                static LSTATUS RegQueryInfoKey (
                    __in HKEY hKey,
                    __out_ecount_part_opt(*lpcchClass, *lpcchClass + 1) LPTSTR lpClass,
                    __inout_opt LPDWORD lpcchClass,
                    __reserved LPDWORD lpReserved,
                    __out_opt LPDWORD lpcSubKeys,
                    __out_opt LPDWORD lpcbMaxSubKeyLen,
                    __out_opt LPDWORD lpcbMaxClassLen,
                    __out_opt LPDWORD lpcValues,
                    __out_opt LPDWORD lpcbMaxValueNameLen,
                    __out_opt LPDWORD lpcbMaxValueLen,
                    __out_opt LPDWORD lpcbSecurityDescriptor,
                    __out_opt PFILETIME lpftLastWriteTime
                    );

                static LSTATUS MockWinApi::RegCloseKey (
                    __in HKEY hKey
                    );

                static HANDLE CreateFile(
                    __in     LPCTSTR lpFileName,
                    __in     DWORD dwDesiredAccess,
                    __in     DWORD dwShareMode,
                    __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
                    __in     DWORD dwCreationDisposition,
                    __in     DWORD dwFlagsAndAttributes,
                    __in_opt HANDLE hTemplateFile
                    );
                static LSTATUS RegNotifyChangeKeyValue (
                    __in HKEY hKey,
                    __in BOOL bWatchSubtree,
                    __in DWORD dwNotifyFilter,
                    __in_opt HANDLE hEvent,
                    __in BOOL fAsynchronous
                    );
            private:
                static std::vector<std::tstring> SubKeys(const std::tstring &subkey);
                static size_t GetClosestKey(boost::shared_ptr<RegistryEntry> &key, const std::vector<std::tstring> &subkeys);
            };
        }
    }
}

#define MOCK_WINAPI Nvidia::Logging::Test::MockWinApi