Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1202 lines
32 KiB

#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;
}