Source code of Windows XP (NT5)
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.

203 lines
4.5 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. NetManageViewNow.cpp
  5. Abstract:
  6. The app doesnt follow stdcall conventions for the ServiceMain function
  7. it registers with SCM. This is resulting in an AV as the ServiceMain
  8. is not cleaning up the stack on return, after being called by SCM.
  9. We clean up the stack for the app registered ServiceMain by hooking
  10. StartServiceCtrlDispatcher and registering our own ServiceMain routine,
  11. which makes the actual call to the app registered servicemain and then
  12. pop 8 bytes of the stack before returning.
  13. Notes:
  14. This is an app specific shim.
  15. History:
  16. 03/08/2001 a-leelat Created
  17. --*/
  18. #include "precomp.h"
  19. IMPLEMENT_SHIM_BEGIN(NetManageViewNow)
  20. #include "ShimHookMacro.h"
  21. APIHOOK_ENUM_BEGIN
  22. APIHOOK_ENUM_ENTRY(StartServiceCtrlDispatcherA)
  23. APIHOOK_ENUM_ENTRY(StartServiceCtrlDispatcherW)
  24. APIHOOK_ENUM_END
  25. //last entry of the service table are supposed to be NULL entries
  26. SERVICE_TABLE_ENTRYA g_SvcTableA[] = { {NULL,NULL},{NULL,NULL} };
  27. SERVICE_TABLE_ENTRYW g_SvcTableW[] = { {NULL,NULL},{NULL,NULL} };
  28. LPSERVICE_MAIN_FUNCTIONA g_pfnActualMainA = NULL;
  29. LPSERVICE_MAIN_FUNCTIONW g_pfnActualMainW = NULL;
  30. VOID WINAPI ServiceMainA(
  31. DWORD dwArgc, // number of arguments
  32. LPSTR *lpszArgv // array of arguments
  33. )
  34. {
  35. //call the actual routine
  36. (g_pfnActualMainA)(dwArgc,lpszArgv);
  37. //pop 8 bytes of stack to compensate for
  38. //the app not following stdcall convention
  39. __asm
  40. {
  41. add esp,8
  42. }
  43. }
  44. VOID WINAPI ServiceMainW(
  45. DWORD dwArgc, // number of arguments
  46. LPWSTR *lpszArgv // array of arguments
  47. )
  48. {
  49. //call the actual routine
  50. (g_pfnActualMainW)(dwArgc,lpszArgv);
  51. //pop 8 bytes of stack to compensate for
  52. //the app not following stdcall convention
  53. __asm
  54. {
  55. add esp, 8
  56. }
  57. }
  58. BOOL APIHOOK(StartServiceCtrlDispatcherA)(
  59. CONST LPSERVICE_TABLE_ENTRYA lpServiceTable // service table
  60. )
  61. {
  62. BOOL bRet = false;
  63. LPSERVICE_TABLE_ENTRYA lpSvcTblToPass = lpServiceTable;
  64. //Allocate buffer to copy the actual service name
  65. g_SvcTableA[0].lpServiceName =
  66. (LPSTR) malloc(_tcslenBytes(lpServiceTable->lpServiceName)+1);
  67. if (!g_SvcTableA[0].lpServiceName)
  68. {
  69. DPFN( eDbgLevelError,
  70. "[StartServiceCtrlDispatcherA] Buffer allocation failure");
  71. }
  72. else
  73. {
  74. //Setup our service table to register with SCM
  75. //Copy the service name as defined by the app
  76. _tcscpy(g_SvcTableA[0].lpServiceName,lpServiceTable->lpServiceName);
  77. //Now put our service routine
  78. g_SvcTableA[0].lpServiceProc = ServiceMainA;
  79. //Save the old servicemain func ptr
  80. g_pfnActualMainA = lpServiceTable->lpServiceProc;
  81. //Set the service table to our table
  82. lpSvcTblToPass = &g_SvcTableA[0];
  83. DPFN( eDbgLevelInfo,
  84. "[StartServiceCtrlDispatcherA] Hooked ServiceMainA");
  85. }
  86. //Call the Original API
  87. bRet = StartServiceCtrlDispatcherA(lpSvcTblToPass);
  88. return bRet;
  89. }
  90. BOOL APIHOOK(StartServiceCtrlDispatcherW)(
  91. CONST LPSERVICE_TABLE_ENTRYW lpServiceTable // service table
  92. )
  93. {
  94. BOOL bRet = false;
  95. LPSERVICE_TABLE_ENTRYW lpSvcTblToPass = lpServiceTable;
  96. //Allocate buffer to copy the actual service name
  97. g_SvcTableW[0].lpServiceName =
  98. (LPWSTR) malloc(wcslen(lpServiceTable->lpServiceName)+1);
  99. if (!g_SvcTableW[0].lpServiceName)
  100. {
  101. DPFN( eDbgLevelError,
  102. "[StartServiceCtrlDispatcherW] Buffer allocation failure");
  103. }
  104. else
  105. {
  106. //Setup our service table to register with SCM
  107. //Copy the service name as defined by the app
  108. wcscpy(g_SvcTableW[0].lpServiceName,lpServiceTable->lpServiceName);
  109. //Now put our service routine
  110. g_SvcTableW[0].lpServiceProc = ServiceMainW;
  111. //Save the old servicemain func ptr
  112. g_pfnActualMainW = lpServiceTable->lpServiceProc;
  113. //Set the service table to our table
  114. lpSvcTblToPass = &g_SvcTableW[0];
  115. DPFN( eDbgLevelInfo,
  116. "[StartServiceCtrlDispatcherW] Hooked ServiceMainW");
  117. }
  118. //Call the Original API
  119. bRet = StartServiceCtrlDispatcherW(lpSvcTblToPass);
  120. return bRet;
  121. }
  122. /*++
  123. Register hooked functions
  124. --*/
  125. HOOK_BEGIN
  126. APIHOOK_ENTRY(ADVAPI32.DLL, StartServiceCtrlDispatcherA)
  127. APIHOOK_ENTRY(ADVAPI32.DLL, StartServiceCtrlDispatcherW)
  128. HOOK_END
  129. IMPLEMENT_SHIM_END