191 lines
5.1 KiB
C++
191 lines
5.1 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2000-2002 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
MoveWinInitRenameToReg.cpp
|
||
|
|
||
|
Abstract:
|
||
|
This shim hooks ExitWindowsEx as well as waits for DLL_PROCESS_DETACH
|
||
|
and then moves the contents of the [Rename] section of wininit.ini
|
||
|
into the registry via MoveFileEx().
|
||
|
|
||
|
History:
|
||
|
|
||
|
07/24/2000 t-adams Created
|
||
|
02/12/2002 mnikkel Modified calls to GetPrivateProfileStringW so default was a
|
||
|
null string, not NULL. Also put in loop for retrieving key values
|
||
|
that increased buffer till value fit instead of using MAX_PATH.
|
||
|
|
||
|
--*/
|
||
|
#include "precomp.h"
|
||
|
|
||
|
#define SIZE_STEP MAX_PATH
|
||
|
|
||
|
IMPLEMENT_SHIM_BEGIN(MoveWinInitRenameToReg)
|
||
|
#include "ShimHookMacro.h"
|
||
|
|
||
|
APIHOOK_ENUM_BEGIN
|
||
|
APIHOOK_ENUM_ENTRY(ExitWindowsEx)
|
||
|
APIHOOK_ENUM_END
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Abstract:
|
||
|
Moves the entries in the Rename section of WinInit.ini into
|
||
|
the registry via MoveFileEx().
|
||
|
|
||
|
--*/
|
||
|
void MoveWinInitRenameToReg(void)
|
||
|
{
|
||
|
LPWSTR szKeys = NULL;
|
||
|
LPWSTR szFrom = NULL;
|
||
|
DWORD dwKeysSize = 0;
|
||
|
LPWSTR pszTo = NULL;
|
||
|
|
||
|
CString csWinInit;
|
||
|
CString csWinInitBak;
|
||
|
|
||
|
// Construct the paths to wininit.ini and wininit.bak
|
||
|
csWinInit.GetWindowsDirectoryW();
|
||
|
csWinInitBak.GetWindowsDirectoryW();
|
||
|
|
||
|
csWinInit.AppendPath(L"\\wininit.ini");
|
||
|
csWinInitBak.AppendPath(L"\\wininit.bak");
|
||
|
|
||
|
// Make sure wininit.ini exists.
|
||
|
if( GetFileAttributesW(csWinInit) != INVALID_FILE_ATTRIBUTES)
|
||
|
{
|
||
|
// Copy wininit.ini to wininit.bak because we will be destroying
|
||
|
// wininit.ini as we read through its keys and can't simply rename
|
||
|
// it to wininit.bak later. If the backup fails we can still continue.
|
||
|
CopyFileW(csWinInit, csWinInitBak, FALSE);
|
||
|
|
||
|
// Read the "key" names.
|
||
|
// Since we can't know how big the list of keys is going to be,
|
||
|
// continue to try to get the list until GetPrivateProfile string
|
||
|
// returns something other than dwKeysSize-2 (indicating too small
|
||
|
// of a buffer).
|
||
|
do
|
||
|
{
|
||
|
if( NULL != szKeys )
|
||
|
{
|
||
|
free(szKeys);
|
||
|
}
|
||
|
dwKeysSize += SIZE_STEP;
|
||
|
szKeys = (LPWSTR) malloc(dwKeysSize * sizeof(WCHAR));
|
||
|
if( NULL == szKeys )
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
while(GetPrivateProfileStringW(L"Rename", NULL, L"", szKeys, dwKeysSize, csWinInit)
|
||
|
== dwKeysSize - 2);
|
||
|
|
||
|
// Traverse through the keys. If there are no keys, szKeys will be a null terminator.
|
||
|
// Delete each key after we read it so that if there are multiple "NUL" keys,
|
||
|
// our calls to GetPrivateProfileStringA won't continue to return only the
|
||
|
// first NUL key's associated value.
|
||
|
pszTo = szKeys;
|
||
|
while(*pszTo != NULL)
|
||
|
{
|
||
|
DWORD dwFromSize = 0;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if( NULL != szFrom )
|
||
|
{
|
||
|
free(szFrom);
|
||
|
}
|
||
|
dwFromSize += SIZE_STEP;
|
||
|
szFrom = (LPWSTR) malloc(dwFromSize * sizeof(WCHAR));
|
||
|
if( NULL == szFrom )
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
while(GetPrivateProfileStringW(L"Rename", pszTo, L"", szFrom, MAX_PATH, csWinInit)
|
||
|
== dwKeysSize - 1);
|
||
|
|
||
|
WritePrivateProfileStringW(L"Rename", pszTo, NULL, csWinInit);
|
||
|
|
||
|
// If pszTo is "NUL", then the intention is to delete the szFrom file, so pass
|
||
|
// NULL to MoveFileExA(). If the move fails we still wish to continue.
|
||
|
if( wcscmp(pszTo, L"NUL") == 0 )
|
||
|
{
|
||
|
MoveFileExW(szFrom, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MoveFileExW(szFrom, pszTo, MOVEFILE_DELAY_UNTIL_REBOOT);
|
||
|
}
|
||
|
|
||
|
// Move to the next file (key)
|
||
|
pszTo += wcslen(pszTo) + 1;
|
||
|
}
|
||
|
|
||
|
// delete WinInit.ini
|
||
|
DeleteFileW(csWinInit);
|
||
|
}
|
||
|
|
||
|
Exit:
|
||
|
if( NULL != szKeys )
|
||
|
{
|
||
|
free(szKeys);
|
||
|
}
|
||
|
if( NULL != szFrom )
|
||
|
{
|
||
|
free(szFrom);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Abstract:
|
||
|
Hook ExitWindowsEx in case the program resets the machine, keeping
|
||
|
us from receiving the DLL_PROCESS_DETACH message. (Shim originally
|
||
|
written for an uninstall program that caused a reset.)
|
||
|
|
||
|
--*/
|
||
|
BOOL
|
||
|
APIHOOK(ExitWindowsEx)(
|
||
|
UINT uFlags,
|
||
|
DWORD dwReserved)
|
||
|
{
|
||
|
MoveWinInitRenameToReg();
|
||
|
return ORIGINAL_API(ExitWindowsEx)(uFlags, dwReserved);
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Register hooked functions
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
NOTIFY_FUNCTION(
|
||
|
DWORD fdwReason)
|
||
|
{
|
||
|
if (fdwReason == DLL_PROCESS_DETACH)
|
||
|
{
|
||
|
MoveWinInitRenameToReg();
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
HOOK_BEGIN
|
||
|
|
||
|
APIHOOK_ENTRY(USER32.DLL, ExitWindowsEx )
|
||
|
|
||
|
CALL_NOTIFY_FUNCTION
|
||
|
|
||
|
HOOK_END
|
||
|
|
||
|
IMPLEMENT_SHIM_END
|
||
|
|