|
|
#include "main.h"
const WCHAR g_cOpenBracket = L'['; const WCHAR g_cCloseBracket = L']'; const WCHAR g_cSemiColon = L';';
#define TEMP_LOCATION TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy Objects")
#define REG_EVENT_NAME TEXT("Group Policy registry event name for ")
///////////////////////////////////////////////////////////////////////////////
// //
// CRegistryHive object implementation //
// //
///////////////////////////////////////////////////////////////////////////////
CRegistryHive::CRegistryHive() { m_cRef = 1; InterlockedIncrement(&g_cRefThisDll); m_hKey = NULL; m_hEvent = NULL; m_lpFileName = m_lpKeyName = m_lpEventName = NULL; }
CRegistryHive::~CRegistryHive() { InterlockedDecrement(&g_cRefThisDll); }
///////////////////////////////////////////////////////////////////////////////
// //
// CRegistryHive object implementation (IUnknown) //
// //
///////////////////////////////////////////////////////////////////////////////
HRESULT CRegistryHive::QueryInterface (REFIID riid, void **ppv) { if (IsEqualIID(riid, IID_IUnknown)) { *ppv = (LPUNKNOWN)this; m_cRef++; return S_OK; } else { *ppv = NULL; return E_NOINTERFACE; } }
ULONG CRegistryHive::AddRef (void) { return ++m_cRef; }
ULONG CRegistryHive::Release (void) { if (--m_cRef == 0) {
if (m_hKey) { RegCloseKey (m_hKey);
if (m_lpKeyName) { BOOL bCleanRegistry = TRUE;
//
// We need to decide if the registry keys can be deleted or if
// they are in use by another copy of GPE. To do this, close
// the event we created during initialization and then try to
// open the event again. If the event is successfully opened,
// then another process is using the same registry key and it
// should not be deleted.
//
if (m_hEvent && m_lpEventName) { CloseHandle (m_hEvent);
m_hEvent = OpenEvent (SYNCHRONIZE, FALSE, m_lpEventName);
if (m_hEvent) { bCleanRegistry = FALSE; } }
if (bCleanRegistry) { RegDelnode (HKEY_CURRENT_USER, m_lpKeyName); RegDeleteKey (HKEY_CURRENT_USER, TEMP_LOCATION); } } }
if (m_lpKeyName) { LocalFree (m_lpKeyName); }
if (m_lpFileName) { LocalFree (m_lpFileName); }
if (m_lpEventName) { LocalFree (m_lpEventName); }
if (m_hEvent) { CloseHandle (m_hEvent); }
delete this; return 0; }
return m_cRef; }
///////////////////////////////////////////////////////////////////////////////
// //
// CRegistryHive object implementation (Public functions) //
// //
///////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CRegistryHive::Initialize(LPTSTR lpFileName, LPTSTR lpKeyName) { TCHAR szBuffer[300]; INT i; LONG lResult; DWORD dwDisp; HRESULT hr;
//
// Check for null pointer
//
if (!lpFileName || !(*lpFileName)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Null filename"))); return E_INVALIDARG; }
//
// Make sure this object hasn't been initialized already
//
if (m_hKey || m_lpFileName || m_lpKeyName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Object already initialized"))); return (E_UNEXPECTED); }
//
// Find a temporary registry key to work with
//
hr = StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), TEMP_LOCATION); if (SUCCEEDED(hr)) { hr = StringCchCat (szBuffer, ARRAYSIZE(szBuffer), TEXT("\\")); } if (SUCCEEDED(hr)) { hr = StringCchCat (szBuffer, ARRAYSIZE(szBuffer), lpKeyName); }
if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to copyt registry name with 0x%x"), hr)); return hr; }
lResult = RegCreateKeyEx (HKEY_CURRENT_USER, szBuffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_hKey, &dwDisp);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to open registry key with %d"), lResult)); return (HRESULT_FROM_WIN32(lResult)); }
//
// Store the keyname
//
ULONG ulNoChars;
ulNoChars = lstrlen(szBuffer) + 1; m_lpKeyName = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!m_lpKeyName) { RegCloseKey (m_hKey); m_hKey = NULL; DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to allocate memory for KeyName"))); return (HRESULT_FROM_WIN32(GetLastError())); }
hr = StringCchCopy (m_lpKeyName, ulNoChars, szBuffer); ASSERT(SUCCEEDED(hr));
//
// Store the filename
//
ulNoChars = lstrlen(lpFileName) + 1; m_lpFileName = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!m_lpFileName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to allocate memory for filename"))); return (HRESULT_FROM_WIN32(GetLastError())); }
hr = StringCchCopy (m_lpFileName, ulNoChars, lpFileName); ASSERT(SUCCEEDED(hr));
//
// Store the event name
//
hr = StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), REG_EVENT_NAME); if (SUCCEEDED(hr)) { hr = StringCchCat (szBuffer, ARRAYSIZE(szBuffer), lpKeyName); }
if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to copy event name"))); return hr; }
ulNoChars = lstrlen(szBuffer) + 1; m_lpEventName = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!m_lpEventName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to allocate memory for filename"))); return (HRESULT_FROM_WIN32(GetLastError())); }
hr = StringCchCopy (m_lpEventName, ulNoChars, szBuffer); ASSERT(SUCCEEDED(hr));
//
// Load the file if it exists
//
hr = Load();
if (FAILED(hr)) { return hr; }
//
// Create the registry event
//
m_hEvent = CreateEvent (NULL, FALSE, FALSE, m_lpEventName);
if (!m_hEvent) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Initialize: Failed to create registry event with %d"), GetLastError())); return (HRESULT_FROM_WIN32(GetLastError())); }
return (S_OK); }
STDMETHODIMP CRegistryHive::GetHKey(HKEY *hKey) { HRESULT hr = E_FAIL;
*hKey = NULL;
if (m_hKey) { if (DuplicateHandle (GetCurrentProcess(), (HANDLE)m_hKey, GetCurrentProcess(), (LPHANDLE) hKey, 0, TRUE, DUPLICATE_SAME_ACCESS)) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } }
return hr; }
STDMETHODIMP CRegistryHive::Save(VOID) { HANDLE hFile; HRESULT hr; DWORD dwTemp, dwBytesWritten; LPWSTR lpKeyName;
//
// Check parameters
//
if (!m_hKey || !m_lpFileName || !m_lpKeyName) { return E_INVALIDARG; }
//
// Allocate a buffer to hold the keyname
//
lpKeyName = (LPWSTR) LocalAlloc (LPTR, MAX_KEYNAME_SIZE * sizeof(WCHAR));
if (!lpKeyName) { return (HRESULT_FROM_WIN32(GetLastError())); }
//
// Create the output file
//
DISABLE_32BIT_FILE_REDIRECTION_ON_64BIT(m_lpFileName);
hFile = CreateFile (m_lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ENABLE_32BIT_FILE_REDIRECTION_ON_64BIT;
if (hFile == INVALID_HANDLE_VALUE) { LocalFree (lpKeyName); return (HRESULT_FROM_WIN32(GetLastError())); }
//
// Write the header block
//
// 2 DWORDS, signature (PReg) and version number and 2 newlines
//
dwTemp = REGFILE_SIGNATURE;
if (!WriteFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(dwTemp)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Save: Failed to write signature with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
dwTemp = REGISTRY_FILE_VERSION;
if (!WriteFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(dwTemp)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Save: Failed to write version number with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Exports the values / keys
//
hr = ExportKey (m_hKey, hFile, lpKeyName, MAX_KEYNAME_SIZE);
Exit:
//
// Finished
//
CloseHandle (hFile); LocalFree (lpKeyName);
return hr; }
STDMETHODIMP CRegistryHive::ExportKey(HKEY hKey, HANDLE hFile, LPWSTR lpKeyName, ULONG ulKeySize) { HRESULT hr = S_OK; DWORD dwBytesWritten, dwNameSize, dwDataSize, dwKeySize; DWORD dwIndex, dwTemp1, dwTemp2, dwType, dwKeyCount = 0; LONG lResult; HKEY hSubKey; LPWSTR lpValueName = NULL; LPWSTR lpSubKeyName = NULL; LPBYTE lpValueData = NULL; LPWSTR lpEnd;
//
// Gather information about this key
//
lResult = RegQueryInfoKey (hKey, NULL, NULL, NULL, &dwKeyCount, &dwKeySize, NULL, NULL, &dwNameSize, &dwDataSize, NULL, NULL);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: Failed to query registry key information with %d"), lResult)); return HRESULT_FROM_WIN32(lResult); }
//
// Allocate buffers to work with
//
lpValueName = (LPWSTR) LocalAlloc (LPTR, (dwNameSize + 1) * sizeof(WCHAR));
if (!lpValueName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: Failed to alloc memory with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
lpValueData = (LPBYTE) LocalAlloc (LPTR, dwDataSize);
if (!lpValueData) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: Failed to alloc memory with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Enumerate the values and write them to the file
//
dwIndex = 0;
while (TRUE) { dwTemp1 = dwNameSize + 1; dwTemp2 = dwDataSize; *lpValueName = L'\0';
lResult = RegEnumValueW (hKey, dwIndex, lpValueName, &dwTemp1, NULL, &dwType, lpValueData, &dwTemp2);
if (lResult == ERROR_NO_MORE_ITEMS) break;
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: RegEnumValue failed with %d"), lResult)); hr = HRESULT_FROM_WIN32(lResult); goto Exit; }
hr = WriteValue(hFile, lpKeyName, lpValueName, dwType, dwTemp2, lpValueData);
if (hr != S_OK) goto Exit;
dwIndex++; }
//
// If dwIndex is 0, this is an empty key. We need to special case this
// so the empty key is entered into the registry file when there are
// no subkeys under it.
//
if ((dwIndex == 0) && (dwKeyCount == 0) && (*lpKeyName)) { hr = WriteValue(hFile, lpKeyName, lpValueName, REG_NONE, 0, lpValueData);
if (hr != S_OK) goto Exit; }
LocalFree (lpValueName); lpValueName = NULL;
LocalFree (lpValueData); lpValueData = NULL;
//
// Now process the sub keys
//
lpSubKeyName = (LPWSTR) LocalAlloc (LPTR, (dwKeySize + 1) * sizeof(WCHAR));
if (!lpSubKeyName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: Failed to alloc memory with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
dwIndex = 0;
ULONG ulNoChars; if (*lpKeyName) { lpEnd = CheckSlash (lpKeyName); ulNoChars = ulKeySize - lstrlen(lpKeyName); }
else { lpEnd = lpKeyName; ulNoChars = ulKeySize; } while (TRUE) { dwTemp1 = dwKeySize + 1; lResult = RegEnumKeyEx (hKey, dwIndex, lpSubKeyName, &dwTemp1, NULL, NULL, NULL, NULL);
if (lResult == ERROR_NO_MORE_ITEMS) break;
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: RegEnumKeyEx failed with %d"), lResult)); hr = HRESULT_FROM_WIN32(lResult); goto Exit; }
hr = StringCchCopy (lpEnd, ulNoChars, lpSubKeyName); if (FAILED(hr)) { break; }
lResult = RegOpenKeyEx (hKey, lpSubKeyName, 0, KEY_READ, &hSubKey);
if (lResult == ERROR_SUCCESS) { hr = ExportKey (hSubKey, hFile, lpKeyName, ulKeySize); RegCloseKey (hSubKey);
if (hr != S_OK) break; } else { DebugMsg((DM_WARNING, TEXT("CRegistryHive::ExportKey: RegOpenKeyEx failed with %d"), lResult)); }
dwIndex++; }
Exit:
if (lpValueName) LocalFree (lpValueName);
if (lpValueData) LocalFree (lpValueData);
if (lpSubKeyName) LocalFree (lpSubKeyName);
return hr;
}
STDMETHODIMP CRegistryHive::WriteValue(HANDLE hFile, LPWSTR lpKeyName, LPWSTR lpValueName, DWORD dwType, DWORD dwDataLength, LPBYTE lpData) { HRESULT hr = S_OK; DWORD dwBytesWritten; DWORD dwTemp;
//
// Write the entry to the text file.
//
// Format:
//
// [keyname;valuename;type;datalength;data]
//
// open bracket
if (!WriteFile (hFile, &g_cOpenBracket, sizeof(WCHAR), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(WCHAR)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write open bracket with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// key name
dwTemp = (lstrlen (lpKeyName) + 1) * sizeof (WCHAR); if (!WriteFile (hFile, lpKeyName, dwTemp, &dwBytesWritten, NULL) || dwBytesWritten != dwTemp) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write key name with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// semicolon
if (!WriteFile (hFile, &g_cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(WCHAR)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write semicolon with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// value name
dwTemp = (lstrlen (lpValueName) + 1) * sizeof (WCHAR); if (!WriteFile (hFile, lpValueName, dwTemp, &dwBytesWritten, NULL) || dwBytesWritten != dwTemp) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write value name with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// semicolon
if (!WriteFile (hFile, &g_cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(WCHAR)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write semicolon with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// type
if (!WriteFile (hFile, &dwType, sizeof(DWORD), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(DWORD)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write data type with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// semicolon
if (!WriteFile (hFile, &g_cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(WCHAR)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write semicolon with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// data length
if (!WriteFile (hFile, &dwDataLength, sizeof(DWORD), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(DWORD)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write data type with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// semicolon
if (!WriteFile (hFile, &g_cSemiColon, sizeof(WCHAR), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(WCHAR)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write semicolon with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// data
if (!WriteFile (hFile, lpData, dwDataLength, &dwBytesWritten, NULL) || dwBytesWritten != dwDataLength) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write data with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
// close bracket
if (!WriteFile (hFile, &g_cCloseBracket, sizeof(WCHAR), &dwBytesWritten, NULL) || dwBytesWritten != sizeof(WCHAR)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::WriteValue: Failed to write close bracket with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
DebugMsg((DM_VERBOSE, TEXT("CRegistryHive::WriteValue: Successfully wrote: %s\\%s"), lpKeyName, lpValueName));
Exit:
return hr; }
STDMETHODIMP CRegistryHive::Load(VOID) { HANDLE hFile; HRESULT hr = S_OK; DWORD dwTemp, dwBytesRead, dwType, dwDataLength, dwDisp; LPWSTR lpKeyName, lpValueName, lpTemp; LPBYTE lpData; WCHAR chTemp; HKEY hSubKey; LONG lResult;
//
// Check parameters
//
if (!m_hKey || !m_lpFileName || !m_lpKeyName) { return E_INVALIDARG; }
//
// Open the registry file
//
DISABLE_32BIT_FILE_REDIRECTION_ON_64BIT(m_lpFileName);
hFile = CreateFile (m_lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); ENABLE_32BIT_FILE_REDIRECTION_ON_64BIT;
if (hFile == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { return S_OK; } else { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: CreateFile failed for <%s> with %d"), m_lpFileName, GetLastError())); return (HRESULT_FROM_WIN32(GetLastError())); } }
//
// Allocate buffers to hold the keyname, valuename, and data
//
lpKeyName = (LPWSTR) LocalAlloc (LPTR, MAX_KEYNAME_SIZE * sizeof(WCHAR));
if (!lpKeyName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to allocate memory with %d"), GetLastError())); CloseHandle (hFile); return (HRESULT_FROM_WIN32(GetLastError())); }
lpValueName = (LPWSTR) LocalAlloc (LPTR, MAX_VALUENAME_SIZE * sizeof(WCHAR));
if (!lpValueName) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to allocate memory with %d"), GetLastError())); LocalFree (lpKeyName); CloseHandle (hFile); return (HRESULT_FROM_WIN32(GetLastError())); }
//
// Read the header block
//
// 2 DWORDS, signature (PReg) and version number and 2 newlines
//
if (!ReadFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesRead, NULL) || dwBytesRead != sizeof(dwTemp)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read signature with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
if (dwTemp != REGFILE_SIGNATURE) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Invalid file signature"))); hr = E_FAIL; goto Exit; }
if (!ReadFile (hFile, &dwTemp, sizeof(dwTemp), &dwBytesRead, NULL) || dwBytesRead != sizeof(dwTemp)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read version number with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
if (dwTemp != REGISTRY_FILE_VERSION) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Invalid file version"))); hr = E_FAIL; goto Exit; }
//
// Read the data
//
while (TRUE) {
//
// Read the first character. It will either be a [ or the end
// of the file.
//
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { if (GetLastError() != ERROR_HANDLE_EOF) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read first character with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); } goto Exit; }
if ((dwBytesRead == 0) || (chTemp != L'[')) { goto Exit; }
//
// Read the keyname
//
lpTemp = lpKeyName; DWORD dwTempLen = 0;
while (TRUE) { if ( dwTempLen == MAX_KEYNAME_SIZE ) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Keyname is bigger than MAX_KEYNAME_SIZE (%d)"), MAX_KEYNAME_SIZE)); hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); goto Exit; }
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read keyname character with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
*lpTemp++ = chTemp; dwTempLen++;
if (chTemp == TEXT('\0')) break;
}
//
// Read the semi-colon
//
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { if (GetLastError() != ERROR_HANDLE_EOF) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read first character with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); } goto Exit; }
if ((dwBytesRead == 0) || (chTemp != L';')) { goto Exit; }
//
// Read the valuename
//
lpTemp = lpValueName; dwTempLen = 0;
while (TRUE) { if ( dwTempLen == MAX_VALUENAME_SIZE ) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Valuename is bigger than MAX_VALUENAME_SIZE (%d)"), MAX_VALUENAME_SIZE)); hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); goto Exit; }
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read valuename character with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
*lpTemp++ = chTemp; dwTempLen++;
if (chTemp == TEXT('\0')) break; }
//
// Read the semi-colon
//
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { if (GetLastError() != ERROR_HANDLE_EOF) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read first character with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); } goto Exit; }
if ((dwBytesRead == 0) || (chTemp != L';')) { goto Exit; }
//
// Read the type
//
if (!ReadFile (hFile, &dwType, sizeof(DWORD), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read type with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Skip semicolon
//
if (!ReadFile (hFile, &dwTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to skip semicolon with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Read the data length
//
if (!ReadFile (hFile, &dwDataLength, sizeof(DWORD), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to data length with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Skip semicolon
//
if (!ReadFile (hFile, &dwTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to skip semicolon with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Allocate memory for data
//
lpData = (LPBYTE) LocalAlloc (LPTR, dwDataLength);
if (!lpData) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to allocate memory for data with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Read data
//
if (!ReadFile (hFile, lpData, dwDataLength, &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to read data with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
//
// Skip closing bracket
//
if (!ReadFile (hFile, &chTemp, sizeof(WCHAR), &dwBytesRead, NULL)) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to skip closing bracket with %d"), GetLastError())); hr = HRESULT_FROM_WIN32(GetLastError()); goto Exit; }
if (chTemp != L']') { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Expected to find ], but found %c"), chTemp)); hr = E_FAIL; goto Exit; }
//
// Save registry value
//
lResult = RegCreateKeyEx (m_hKey, lpKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hSubKey, &dwDisp);
if (lResult == ERROR_SUCCESS) {
if ((dwType == REG_NONE) && (dwDataLength == 0) && (*lpValueName == L'\0')) { lResult = ERROR_SUCCESS; } else { lResult = RegSetValueEx (hSubKey, lpValueName, 0, dwType, lpData, dwDataLength); }
RegCloseKey (hSubKey);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to set value <%s> with %d"), lpValueName, lResult)); hr = HRESULT_FROM_WIN32(lResult); LocalFree (lpData); goto Exit; } } else { DebugMsg((DM_WARNING, TEXT("CRegistryHive::Load: Failed to open key <%s> with %d"), lpKeyName, lResult)); hr = HRESULT_FROM_WIN32(lResult); LocalFree (lpData); goto Exit; }
LocalFree (lpData);
}
Exit:
//
// Finished
//
CloseHandle (hFile); LocalFree (lpKeyName); LocalFree (lpValueName);
return hr; }
STDMETHODIMP CRegistryHive::IsRegistryEmpty(BOOL *bEmpty) { HRESULT hr = ERROR_SUCCESS; DWORD dwKeys, dwValues; LONG lResult;
if (!m_hKey) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::IsRegistryEmpty: registry key not open yet"))); return HRESULT_FROM_WIN32(ERROR_NOT_READY); }
lResult = RegQueryInfoKey(m_hKey, NULL, NULL, NULL, &dwKeys, NULL, NULL, &dwValues, NULL, NULL, NULL, NULL);
if (lResult != ERROR_SUCCESS) { DebugMsg((DM_WARNING, TEXT("CRegistryHive::IsRegistryEmpty: RegQueryInfoKey failed with %d"), lResult)); return HRESULT_FROM_WIN32(lResult); }
if ((dwKeys == 0) && (dwValues == 0)) { *bEmpty = TRUE; DebugMsg((DM_VERBOSE, TEXT("CRegistryHive::IsRegistryEmpty: registry key is empty"))); } else { *bEmpty = FALSE; DebugMsg((DM_VERBOSE, TEXT("CRegistryHive::IsRegistryEmpty: registry key is not empty. Keys = %d, Values = %d"), dwKeys, dwValues)); }
return S_OK; }
|