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

204 lines
4.5 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
NetManageViewNow.cpp
Abstract:
The app doesnt follow stdcall conventions for the ServiceMain function
it registers with SCM. This is resulting in an AV as the ServiceMain
is not cleaning up the stack on return, after being called by SCM.
We clean up the stack for the app registered ServiceMain by hooking
StartServiceCtrlDispatcher and registering our own ServiceMain routine,
which makes the actual call to the app registered servicemain and then
pop 8 bytes of the stack before returning.
Notes:
This is an app specific shim.
History:
03/08/2001 a-leelat Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(NetManageViewNow)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(StartServiceCtrlDispatcherA)
APIHOOK_ENUM_ENTRY(StartServiceCtrlDispatcherW)
APIHOOK_ENUM_END
//last entry of the service table are supposed to be NULL entries
SERVICE_TABLE_ENTRYA g_SvcTableA[] = { {NULL,NULL},{NULL,NULL} };
SERVICE_TABLE_ENTRYW g_SvcTableW[] = { {NULL,NULL},{NULL,NULL} };
LPSERVICE_MAIN_FUNCTIONA g_pfnActualMainA = NULL;
LPSERVICE_MAIN_FUNCTIONW g_pfnActualMainW = NULL;
VOID WINAPI ServiceMainA(
DWORD dwArgc, // number of arguments
LPSTR *lpszArgv // array of arguments
)
{
//call the actual routine
(g_pfnActualMainA)(dwArgc,lpszArgv);
//pop 8 bytes of stack to compensate for
//the app not following stdcall convention
__asm
{
add esp,8
}
}
VOID WINAPI ServiceMainW(
DWORD dwArgc, // number of arguments
LPWSTR *lpszArgv // array of arguments
)
{
//call the actual routine
(g_pfnActualMainW)(dwArgc,lpszArgv);
//pop 8 bytes of stack to compensate for
//the app not following stdcall convention
__asm
{
add esp, 8
}
}
BOOL APIHOOK(StartServiceCtrlDispatcherA)(
CONST LPSERVICE_TABLE_ENTRYA lpServiceTable // service table
)
{
BOOL bRet = false;
LPSERVICE_TABLE_ENTRYA lpSvcTblToPass = lpServiceTable;
//Allocate buffer to copy the actual service name
g_SvcTableA[0].lpServiceName =
(LPSTR) malloc(_tcslenBytes(lpServiceTable->lpServiceName)+1);
if (!g_SvcTableA[0].lpServiceName)
{
DPFN( eDbgLevelError,
"[StartServiceCtrlDispatcherA] Buffer allocation failure");
}
else
{
//Setup our service table to register with SCM
//Copy the service name as defined by the app
_tcscpy(g_SvcTableA[0].lpServiceName,lpServiceTable->lpServiceName);
//Now put our service routine
g_SvcTableA[0].lpServiceProc = ServiceMainA;
//Save the old servicemain func ptr
g_pfnActualMainA = lpServiceTable->lpServiceProc;
//Set the service table to our table
lpSvcTblToPass = &g_SvcTableA[0];
DPFN( eDbgLevelInfo,
"[StartServiceCtrlDispatcherA] Hooked ServiceMainA");
}
//Call the Original API
bRet = StartServiceCtrlDispatcherA(lpSvcTblToPass);
return bRet;
}
BOOL APIHOOK(StartServiceCtrlDispatcherW)(
CONST LPSERVICE_TABLE_ENTRYW lpServiceTable // service table
)
{
BOOL bRet = false;
LPSERVICE_TABLE_ENTRYW lpSvcTblToPass = lpServiceTable;
//Allocate buffer to copy the actual service name
g_SvcTableW[0].lpServiceName =
(LPWSTR) malloc(wcslen(lpServiceTable->lpServiceName)+1);
if (!g_SvcTableW[0].lpServiceName)
{
DPFN( eDbgLevelError,
"[StartServiceCtrlDispatcherW] Buffer allocation failure");
}
else
{
//Setup our service table to register with SCM
//Copy the service name as defined by the app
wcscpy(g_SvcTableW[0].lpServiceName,lpServiceTable->lpServiceName);
//Now put our service routine
g_SvcTableW[0].lpServiceProc = ServiceMainW;
//Save the old servicemain func ptr
g_pfnActualMainW = lpServiceTable->lpServiceProc;
//Set the service table to our table
lpSvcTblToPass = &g_SvcTableW[0];
DPFN( eDbgLevelInfo,
"[StartServiceCtrlDispatcherW] Hooked ServiceMainW");
}
//Call the Original API
bRet = StartServiceCtrlDispatcherW(lpSvcTblToPass);
return bRet;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(ADVAPI32.DLL, StartServiceCtrlDispatcherA)
APIHOOK_ENTRY(ADVAPI32.DLL, StartServiceCtrlDispatcherW)
HOOK_END
IMPLEMENT_SHIM_END