windows-nt/Source/XPSP1/NT/windows/appcompat/shims/layer/handlewvsprintfexceptions.cpp
2020-09-26 16:20:57 +08:00

177 lines
3.7 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
HandleWvsprintfExceptions.cpp
Abstract:
This fix provides a facility to fix argument list from LPSTR into va_list.
Some native Win9x app use LPSTR (pointer of string) instead of
va_list (pointer to pointer of string).
Without properly checking the return value, these apps assume that it is safe
to use wvsprintf like that because it doesn't cause AV.
In NT, this will cause AV.
This shim takes one command line: "arglistfix" (case insensitive).
By default - if there is no command line - it will do exactly
what Win9x's wvsprintfA has :
Do nothing inside the exception handler if there is an exception occurs.
If arglistfix specified in command line, it will try to fix the argument
list (va_list).
History:
09/29/2000 andyseti Created
11/28/2000 jdoherty Converted to framework version 2
03/15/2001 robkenny Converted to CString
--*/
#include "precomp.h"
int g_iWorkMode = 0;
enum
{
WIN9X_MODE = 0,
ARGLISTFIX_MODE
} TEST;
IMPLEMENT_SHIM_BEGIN(HandleWvsprintfExceptions)
#include "ShimHookMacro.h"
//
// Add APIs that you wish to hook to this macro construction.
//
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(wvsprintfA)
APIHOOK_ENUM_END
int Fix_wvsprintf_ArgList(
LPSTR lpOut,
LPCSTR lpFmt,
...)
{
int iRet;
va_list argptr;
va_start( argptr, lpFmt );
iRet = ORIGINAL_API(wvsprintfA)(
lpOut,
lpFmt,
argptr);
va_end( argptr );
return iRet;
}
int
APIHOOK(wvsprintfA)(
LPSTR lpOut,
LPCSTR lpFmt,
va_list arglist)
{
int iRet = 0;
__try {
iRet = ORIGINAL_API(wvsprintfA)(
lpOut,
lpFmt,
arglist);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
if (g_iWorkMode == ARGLISTFIX_MODE)
{
DPFN( eDbgLevelInfo,
"Exception occurs in wvsprintfA. \narglist contains pointer to string: %s.\n" , arglist);
iRet = Fix_wvsprintf_ArgList(lpOut,lpFmt,arglist);
}
else
{
// Copied from Win9x's wvsprintfA
__try {
// tie off the output
*lpOut = 0;
}
__except( EXCEPTION_EXECUTE_HANDLER) {
// Do nothing
}
iRet = 0;
}
}
return iRet;
}
void ParseCommandLine()
{
CString csCmdLine(COMMAND_LINE);
if (csCmdLine.CompareNoCase(L"arglistfix") == 0)
{
DPFN( eDbgLevelInfo,
"HandleWvsprintfExceptions called with argument: %S.\n", csCmdLine.Get());
DPFN( eDbgLevelInfo,
"HandleWvsprintfExceptions mode: Argument List Fix.\n");
g_iWorkMode = ARGLISTFIX_MODE;
}
else
{
DPFN( eDbgLevelInfo,
"HandleWvsprintfExceptions called with no argument.\n");
DPFN( eDbgLevelInfo,
"HandleWvsprintfExceptions mode: Win9x.\n");
g_iWorkMode = WIN9X_MODE;
}
}
/*++
Handle DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH in your notify function
to do initialization and uninitialization.
IMPORTANT: Make sure you ONLY call NTDLL, KERNEL32 and MSVCRT APIs during
DLL_PROCESS_ATTACH notification. No other DLLs are initialized at that
point.
--*/
BOOL
NOTIFY_FUNCTION(
DWORD fdwReason)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
DPFN( eDbgLevelInfo, "HandleWvsprintfExceptions initialized.");
ParseCommandLine();
}
return TRUE;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(USER32.DLL, wvsprintfA)
CALL_NOTIFY_FUNCTION
HOOK_END
IMPLEMENT_SHIM_END