Leaked source code of windows server 2003
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.

251 lines
6.9 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. #include <stdio.h>
  5. #include <stdarg.h>
  6. #include "nt.h"
  7. #include "ntrtl.h"
  8. #include "nturtl.h"
  9. #include "windows.h"
  10. #include "delayimp.h"
  11. #include "strsafe.h"
  12. #include "sxsvc2.h"
  13. #define SERVICE_NAME L"sxsvc2"
  14. extern const WCHAR ServiceName[] = SERVICE_NAME L"\0"; // extra nul terminal for REG_MULTI_SZ
  15. typedef struct _SERVICE_CONTEXT {
  16. HANDLE ServiceHandle;
  17. SERVICE_STATUS ServiceStatus;
  18. } SERVICE_CONTEXT, *PSERVICE_CONTEXT;
  19. PVOID MemAlloc(SIZE_T n) { return HeapAlloc(GetProcessHeap(), 0, n); }
  20. VOID MemFree(PVOID p) { HeapFree(GetProcessHeap(), 0, p); }
  21. BOOL
  22. WINAPI
  23. DllEntry(
  24. HINSTANCE hInst,
  25. DWORD dwReason,
  26. PVOID pvReserved
  27. )
  28. {
  29. switch (dwReason)
  30. {
  31. case DLL_PROCESS_ATTACH:
  32. DisableThreadLibraryCalls(hInst);
  33. break;
  34. }
  35. return TRUE;
  36. }
  37. HMODULE GetMyModule(VOID)
  38. {
  39. return (HMODULE)&__ImageBase;
  40. }
  41. void GetMyFullPathW(PWSTR Buffer, DWORD BufferSize)
  42. {
  43. // NOTE: Do not put this is in the registry.
  44. Buffer[0] = 0;
  45. GetModuleFileNameW(GetMyModule(), Buffer, BufferSize);
  46. }
  47. void strcatfW(PWSTR Buffer, SIZE_T n, PCWSTR Format, ...)
  48. {
  49. va_list Args;
  50. va_start(Args, Format);
  51. if (n != 0 && Buffer != NULL && Format != NULL)
  52. {
  53. SIZE_T i = wcslen(Buffer);
  54. if (i < n)
  55. {
  56. SIZE_T j = n - i;
  57. StringCchVPrintfW(Buffer + i, j, Format, Args);
  58. }
  59. Buffer[n - 1] = 0;
  60. }
  61. va_end(Args);
  62. }
  63. const STRING EmptyString = RTL_CONSTANT_STRING("");
  64. const STRING *
  65. DbgServiceControlToString(
  66. DWORD dw
  67. )
  68. {
  69. const STRING * String = &EmptyString;
  70. switch (dw)
  71. {
  72. #define CASE(x) case x: { const static STRING y = RTL_CONSTANT_STRING(#x); String = &y; } break;
  73. CASE(SERVICE_CONTROL_CONTINUE)
  74. CASE(SERVICE_CONTROL_INTERROGATE)
  75. CASE(SERVICE_CONTROL_NETBINDADD)
  76. CASE(SERVICE_CONTROL_NETBINDDISABLE)
  77. CASE(SERVICE_CONTROL_NETBINDENABLE)
  78. CASE(SERVICE_CONTROL_NETBINDREMOVE)
  79. CASE(SERVICE_CONTROL_PARAMCHANGE)
  80. CASE(SERVICE_CONTROL_PAUSE)
  81. CASE(SERVICE_CONTROL_SHUTDOWN)
  82. CASE(SERVICE_CONTROL_STOP)
  83. CASE(SERVICE_CONTROL_DEVICEEVENT)
  84. CASE(SERVICE_CONTROL_HARDWAREPROFILECHANGE)
  85. CASE(SERVICE_CONTROL_POWEREVENT)
  86. CASE(SERVICE_CONTROL_SESSIONCHANGE)
  87. #undef CASE
  88. }
  89. return String;
  90. }
  91. DWORD
  92. WINAPI
  93. ServiceHandlerEx(
  94. DWORD dwControl, // requested control code
  95. DWORD dwEventType, // event type
  96. LPVOID lpEventData, // event data
  97. LPVOID lpContext // user-defined context data
  98. )
  99. {
  100. BOOL CallSetStatus = FALSE;
  101. PSERVICE_CONTEXT ServiceContext = (PSERVICE_CONTEXT)lpContext;
  102. DbgPrint("sxsvc2: %Z\n", DbgServiceControlToString(dwControl));
  103. if (ServiceContext == NULL)
  104. {
  105. DbgPrint("sxsvc2: got null context\n");
  106. return (DWORD)-1;
  107. }
  108. switch (dwControl)
  109. {
  110. case SERVICE_CONTROL_CONTINUE:
  111. ServiceContext->ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  112. CallSetStatus = TRUE;
  113. break;
  114. case SERVICE_CONTROL_INTERROGATE:
  115. CallSetStatus = TRUE;
  116. break;
  117. case SERVICE_CONTROL_NETBINDADD:
  118. break;
  119. case SERVICE_CONTROL_NETBINDDISABLE:
  120. break;
  121. case SERVICE_CONTROL_NETBINDENABLE:
  122. break;
  123. case SERVICE_CONTROL_NETBINDREMOVE:
  124. break;
  125. case SERVICE_CONTROL_PARAMCHANGE:
  126. break;
  127. case SERVICE_CONTROL_PAUSE:
  128. ServiceContext->ServiceStatus.dwCurrentState = SERVICE_PAUSED;
  129. CallSetStatus = TRUE;
  130. break;
  131. case SERVICE_CONTROL_SHUTDOWN:
  132. ServiceContext->ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  133. CallSetStatus = TRUE;
  134. break;
  135. case SERVICE_CONTROL_STOP:
  136. ServiceContext->ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  137. CallSetStatus = TRUE;
  138. break;
  139. case SERVICE_CONTROL_DEVICEEVENT:
  140. break;
  141. case SERVICE_CONTROL_HARDWAREPROFILECHANGE:
  142. break;
  143. case SERVICE_CONTROL_POWEREVENT:
  144. break;
  145. case SERVICE_CONTROL_SESSIONCHANGE:
  146. break;
  147. }
  148. if (CallSetStatus)
  149. {
  150. SetServiceStatus(ServiceContext->ServiceHandle, &ServiceContext->ServiceStatus);
  151. }
  152. return NO_ERROR;
  153. }
  154. VOID
  155. WINAPI
  156. ServiceMain(
  157. DWORD argc,
  158. PWSTR argv[]
  159. )
  160. {
  161. const static WCHAR MyFullPathFormat[] = L"MyFullPath: %ls: ";
  162. HANDLE FileHandle = 0;
  163. SIZE_T Length = 0;
  164. SIZE_T i = 0;
  165. PWSTR MyFullPath = 0;
  166. PWSTR Buffer = 0;
  167. HANDLE CurrentActCtx = 0;
  168. DWORD BytesWritten = 0;
  169. PSERVICE_CONTEXT ServiceContext = 0;
  170. MyFullPath = (PWSTR)MemAlloc(MAX_PATH);
  171. if (MyFullPath == NULL)
  172. goto Exit;
  173. MyFullPath[0] = 0;
  174. GetMyFullPathW(MyFullPath, MAX_PATH);
  175. Length = 0;
  176. if (argc != 0 && argv != NULL)
  177. {
  178. for (i = 0 ; i < argc ; i++ )
  179. {
  180. Length += wcslen(argv[i]) + 1;
  181. }
  182. }
  183. Length += wcslen(MyFullPath) + NUMBER_OF(MyFullPathFormat);
  184. Length += 1;
  185. Buffer = (PWSTR)MemAlloc(Length * sizeof(WCHAR));
  186. if (Buffer == NULL)
  187. {
  188. goto Exit;
  189. }
  190. Buffer[0] = 0;
  191. strcatfW(Buffer, Length, MyFullPathFormat, MyFullPath);
  192. if (argc != 0 && argv != NULL)
  193. {
  194. for (i = 0 ; i < argc ; i++ )
  195. {
  196. strcatfW(Buffer, Length, L"%ls ", argv[i]);
  197. }
  198. }
  199. GetCurrentActCtx(&CurrentActCtx);
  200. #if DBG
  201. DbgPrint("sxsvc2: %ls\n", Buffer);
  202. #endif
  203. ServiceContext = (PSERVICE_CONTEXT)MemAlloc(sizeof(*ServiceContext));
  204. if (ServiceContext == NULL)
  205. {
  206. DbgPrint("sxsvc2: out of memory line %ld\n", (ULONG)__LINE__);
  207. }
  208. RtlZeroMemory(ServiceContext, sizeof(*ServiceContext));
  209. ServiceContext->ServiceHandle = RegisterServiceCtrlHandlerExW(ServiceName, ServiceHandlerEx, ServiceContext);
  210. if (ServiceContext->ServiceHandle == 0)
  211. {
  212. DbgPrint("sxsvc2: RegisterServiceCtrlHandlerExW failed 0x%lx\n", (ULONG)GetLastError());
  213. goto Exit;
  214. }
  215. ServiceContext->ServiceStatus.dwServiceType = ServiceTypeValue;
  216. ServiceContext->ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  217. ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_STOP;
  218. ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
  219. ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
  220. ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_PARAMCHANGE;
  221. ServiceContext->ServiceStatus.dwControlsAccepted |= SERVICE_ACCEPT_SESSIONCHANGE;
  222. ServiceContext->ServiceStatus.dwWin32ExitCode = NO_ERROR;
  223. SetServiceStatus(ServiceContext->ServiceHandle, &ServiceContext->ServiceStatus);
  224. ServiceContext = NULL;
  225. Exit:
  226. MemFree(Buffer);
  227. MemFree(MyFullPath);
  228. MemFree(ServiceContext);
  229. }