Windows2003-3790/windows/appcompat/shims/layer/emulateenvironmentblock.cpp
2020-09-30 16:53:55 +02:00

241 lines
4.7 KiB
C++

/*++
Copyright (c) 2000-2002 Microsoft Corporation
Module Name:
EmulateEnvironmentBlock.cpp
Abstract:
Shrink the enviroment strings to avoid memory corruption experienced by
some apps when they get a larger than expected enviroment.
Notes:
This is a general purpose shim.
History:
01/19/2001 linstev Created
02/18/2002 mnikkel modified to use strsafe routines.
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(EmulateEnvironmentBlock)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(GetEnvironmentStrings)
APIHOOK_ENUM_ENTRY(GetEnvironmentStringsA)
APIHOOK_ENUM_ENTRY(GetEnvironmentStringsW)
APIHOOK_ENUM_ENTRY(FreeEnvironmentStringsA)
APIHOOK_ENUM_ENTRY(FreeEnvironmentStringsW)
APIHOOK_ENUM_END
#define MAX_ENV 1024
CHAR g_szBlockA[MAX_ENV];
WCHAR g_szBlockW[MAX_ENV];
WCHAR *g_szEnv[] = {
L"TMP=%TMP%",
L"TEMP=%TEMP%",
L"PROMPT=%PROMPT%",
L"winbootdir=%WINDIR%",
L"PATH=%WINDIR%",
L"COMSPEC=%COMSPEC%",
L"WINDIR=%WINDIR%",
NULL
};
/*++
Build a reasonable looking environment block
--*/
BOOL BuildEnvironmentStrings()
{
WCHAR *pPtr = g_szBlockW;
WCHAR szTmp[MAX_PATH];
DWORD dwSize = 0; DWORD i = 0;
DPFN( eDbgLevelError, "Building Environment Block");
// Calculate the remaining block size, subtract one so we can add extra null
// terminator after all variables are added.
DWORD dwRemainingBlockSize = ARRAYSIZE(g_szBlockW)-1;
//
// Run g_szEnv, expand all the strings and cat them together to form the
// new block. pPtr points to current location to write to in g_szBlockW.
//
while (g_szEnv[i])
{
// Expand the environment string, Note: dwSize DOES include the null terminator.
dwSize = ExpandEnvironmentStringsW(g_szEnv[i], szTmp, MAX_PATH);
if ((dwSize > 0) && (dwSize <= MAX_PATH))
{
// If expansion was successful add the string to our environment block
// if there is room.
if (dwSize <= dwRemainingBlockSize &&
S_OK == StringCchCopy(pPtr, dwRemainingBlockSize, szTmp))
{
// update the block size remaining and move the location pointer.
dwRemainingBlockSize -= dwSize;
pPtr += dwSize;
DPFN( eDbgLevelError, "\tAdding: %S", szTmp);
}
else
{
DPFN( eDbgLevelError, "Enviroment > %08lx, ignoring %S", MAX_ENV, szTmp);
}
}
i++;
}
//
// Add the extra null terminator and calculate size of env block.
//
*pPtr = L'\0';
pPtr++;
dwSize = pPtr - g_szBlockW;
//
// ANSI conversion for the A functions
//
WideCharToMultiByte(
CP_ACP,
0,
(LPWSTR) g_szBlockW,
dwSize,
(LPSTR) g_szBlockA,
dwSize,
0,
0);
return TRUE;
}
/*++
Return our block
--*/
LPVOID
APIHOOK(GetEnvironmentStrings)()
{
return (LPVOID) g_szBlockA;
}
/*++
Return our block
--*/
LPVOID
APIHOOK(GetEnvironmentStringsA)()
{
return (LPVOID) g_szBlockA;
}
/*++
Return our block
--*/
LPVOID
APIHOOK(GetEnvironmentStringsW)()
{
return (LPVOID) g_szBlockW;
}
/*++
Check for our block.
--*/
BOOL
APIHOOK(FreeEnvironmentStringsA)(
LPSTR lpszEnvironmentBlock
)
{
if ((lpszEnvironmentBlock == (LPSTR)&g_szBlockA[0]) ||
(lpszEnvironmentBlock == (LPSTR)&g_szBlockW[0]))
{
return TRUE;
}
else
{
return ORIGINAL_API(FreeEnvironmentStringsA)(lpszEnvironmentBlock);
}
}
/*++
Check for our block.
--*/
BOOL
APIHOOK(FreeEnvironmentStringsW)(
LPWSTR lpszEnvironmentBlock
)
{
if ((lpszEnvironmentBlock == (LPWSTR)&g_szBlockA[0]) ||
(lpszEnvironmentBlock == (LPWSTR)&g_szBlockW[0]))
{
return TRUE;
}
else
{
return ORIGINAL_API(FreeEnvironmentStringsW)(lpszEnvironmentBlock);
}
}
/*++
Register hooked functions
--*/
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason
)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
return BuildEnvironmentStrings();
}
return TRUE;
}
HOOK_BEGIN
CALL_NOTIFY_FUNCTION
APIHOOK_ENTRY(KERNEL32.DLL, GetEnvironmentStrings)
APIHOOK_ENTRY(KERNEL32.DLL, GetEnvironmentStringsA)
APIHOOK_ENTRY(KERNEL32.DLL, GetEnvironmentStringsW)
APIHOOK_ENTRY(KERNEL32.DLL, FreeEnvironmentStringsA)
APIHOOK_ENTRY(KERNEL32.DLL, FreeEnvironmentStringsW)
HOOK_END
IMPLEMENT_SHIM_END