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.

412 lines
11 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h> // DbgPrint prototype
  3. #include <nturtl.h>
  4. #include <stdlib.h>
  5. #include <windows.h>
  6. #include <winsvc.h>
  7. #include <winsvcp.h>
  8. #include <winuser.h>
  9. #include <dbt.h>
  10. #include <malloc.h> // _alloca()
  11. #include <crtdbg.h>
  12. //
  13. // Definitions
  14. //
  15. #define LOG0(string) \
  16. (VOID) DbgPrint(" [SCM] " string);
  17. #define LOG1(string, var) \
  18. (VOID) DbgPrint(" [SCM] " string,var);
  19. #define LOG2(string, var1, var2) \
  20. (VOID) DbgPrint(" [SCM] " string,var1,var2);
  21. //
  22. // Test fix for bug #106110
  23. //
  24. // #define FLOOD_PIPE
  25. //
  26. //
  27. // Test fix for bug #120359
  28. //
  29. static const GUID GUID_NDIS_LAN_CLASS =
  30. {0xad498944,0x762f,0x11d0,{0x8d,0xcb,0x00,0xc0,0x4f,0xc3,0x35,0x8c}};
  31. //
  32. // Globals
  33. //
  34. SERVICE_STATUS ssService;
  35. SERVICE_STATUS_HANDLE hssService;
  36. HANDLE g_hEvent;
  37. VOID WINAPI
  38. ServiceStart(
  39. DWORD argc,
  40. LPTSTR *argv
  41. );
  42. VOID
  43. OverflowStackBuffer(
  44. VOID
  45. );
  46. VOID WINAPI
  47. ServiceCtrlHandler(
  48. DWORD Opcode
  49. )
  50. {
  51. switch(Opcode)
  52. {
  53. case SERVICE_CONTROL_SESSIONCHANGE:
  54. break;
  55. case SERVICE_CONTROL_PAUSE:
  56. ssService.dwCurrentState = SERVICE_PAUSED;
  57. LOG0("Service paused\n");
  58. break;
  59. case SERVICE_CONTROL_CONTINUE:
  60. ssService.dwCurrentState = SERVICE_RUNNING;
  61. LOG0("Service continuing\n");
  62. break;
  63. case SERVICE_CONTROL_SHUTDOWN:
  64. LOG0("Shutdown command received\n");
  65. //
  66. // Fall through to STOP case
  67. //
  68. case SERVICE_CONTROL_STOP:
  69. ssService.dwWin32ExitCode = 0;
  70. ssService.dwCurrentState = SERVICE_STOP_PENDING;
  71. ssService.dwCheckPoint = 0;
  72. ssService.dwWaitHint = 0;
  73. break;
  74. case SERVICE_CONTROL_INTERROGATE:
  75. LOG0("Service interrogated\n");
  76. break;
  77. case 249:
  78. {
  79. PVOID pStack;
  80. LOG0("Testing _alloca of 0\n");
  81. pStack = _alloca(0);
  82. LOG1("pStack is %p\n", pStack);
  83. break;
  84. }
  85. case 250:
  86. LOG0("Testing buffer overflow checking\n");
  87. OverflowStackBuffer();
  88. LOG0("post-OverflowStackBuffer call -- shouldn't get here\n");
  89. break;
  90. case 251:
  91. {
  92. DWORD dwError;
  93. DWORD dwTest = 0xabcdefab;
  94. //
  95. // Try a bad address
  96. //
  97. dwError = I_ScSendTSMessage(SERVICE_CONTROL_SESSIONCHANGE,
  98. 0,
  99. 0,
  100. NULL);
  101. LOG1("I_ScSendTSMessage with NULL pointer returned %d\n", dwError);
  102. //
  103. // Try a bad control
  104. //
  105. dwError = I_ScSendTSMessage(SERVICE_CONTROL_STOP,
  106. 0,
  107. sizeof(DWORD),
  108. (LPBYTE) &dwTest);
  109. LOG1("I_ScSendTSMessage for SERVICE_CONTROL_STOP returned %d\n", dwError);
  110. //
  111. // Now try for real
  112. //
  113. dwError = I_ScSendTSMessage(SERVICE_CONTROL_SESSIONCHANGE,
  114. 0,
  115. sizeof(DWORD),
  116. (LPBYTE) &dwTest);
  117. LOG1("I_ScSendTSMessage (real call) returned %d\n", dwError);
  118. break;
  119. }
  120. case 252:
  121. {
  122. DEV_BROADCAST_DEVICEINTERFACE dbdPnpFilter;
  123. //
  124. // Test fix for bug #120359
  125. //
  126. ssService.dwCurrentState = SERVICE_STOPPED;
  127. //
  128. // Eventlog's SERVICE_STATUS_HANDLE when I checked
  129. //
  130. if (!SetServiceStatus((SERVICE_STATUS_HANDLE)0x96df8, &ssService))
  131. {
  132. LOG1("Fix works -- SetServiceStatus error %ld\n", GetLastError());
  133. }
  134. else
  135. {
  136. LOG0("ERROR -- SetServiceStatus call succeeded!\n");
  137. }
  138. //
  139. // Eventlog's LPSERVICE_RECORD when I checked
  140. //
  141. if (!SetServiceStatus((SERVICE_STATUS_HANDLE)0x4844e8, &ssService))
  142. {
  143. LOG1("Fix works -- SetServiceStatus error %ld\n", GetLastError());
  144. }
  145. else
  146. {
  147. LOG0("ERROR -- SetServiceStatus call succeeded!\n");
  148. }
  149. //
  150. // SERVICE_STATUS_HANDLE again
  151. //
  152. ZeroMemory (&dbdPnpFilter, sizeof(dbdPnpFilter));
  153. dbdPnpFilter.dbcc_size = sizeof(dbdPnpFilter);
  154. dbdPnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  155. dbdPnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  156. if (!RegisterDeviceNotification((SERVICE_STATUS_HANDLE)0x96df8,
  157. &dbdPnpFilter,
  158. DEVICE_NOTIFY_SERVICE_HANDLE))
  159. {
  160. LOG1("Fix works -- RegisterDeviceNotification error %ld\n", GetLastError());
  161. }
  162. else
  163. {
  164. LOG0("ERROR -- RegisterDeviceNotification call succeeded!\n");
  165. }
  166. ssService.dwCurrentState = SERVICE_RUNNING;
  167. break;
  168. }
  169. case 253:
  170. {
  171. //
  172. // Test fix for bug #36395. Make sure that we inherited the
  173. // environment block of the user, not the system. NOTE this
  174. // assumes the service is running in an account AND the
  175. // variable we're looking for is in the user's environment.
  176. //
  177. WCHAR wcTemp[1];
  178. DWORD dwCount = GetEnvironmentVariable(L"User_specific_variable",
  179. wcTemp,
  180. sizeof(wcTemp));
  181. LOG1("GetEnvironmentVariable on User_specific_variable %ws\n",
  182. (dwCount == 0 ? L"FAILED!" : L"succeeded"));
  183. break;
  184. }
  185. case 254:
  186. {
  187. //
  188. // Test client-side API for #120359 fix
  189. //
  190. WCHAR wszServiceName[256 + 1];
  191. DWORD dwError;
  192. dwError = I_ScPnPGetServiceName(hssService, wszServiceName, 256);
  193. if (dwError == NO_ERROR)
  194. {
  195. LOG0("I_ScPnPGetServiceName succeeded for valid handle\n");
  196. LOG1("ServiceName is %ws\n", wszServiceName);
  197. }
  198. else
  199. {
  200. LOG0("I_ScPnPGetServiceName failed for valid handle!\n");
  201. LOG1("Error was %d\n", dwError);
  202. }
  203. dwError = I_ScPnPGetServiceName(NULL, wszServiceName, 256);
  204. if (dwError == NO_ERROR)
  205. {
  206. LOG0("I_ScPnPGetServiceName succeeded for NULL handle!\n");
  207. LOG1("ServiceName is %ws\n", wszServiceName);
  208. }
  209. else
  210. {
  211. LOG0("I_ScPnPGetServiceName failed for NULL handle!\n");
  212. LOG1("Error was %d\n", dwError);
  213. }
  214. break;
  215. }
  216. case 255:
  217. //
  218. // Print controls to the debugger
  219. //
  220. LOG0("Controls supported:\n");
  221. LOG0("\t249:\tTest _alloca of 0\n");
  222. LOG0("\t250:\tOverflow a stack buffer\n");
  223. LOG0("\t251:\tTry calling I_ScSendTSMessage\n");
  224. LOG0("\t252:\tTry calling SetServiceStatus with a bogus status handle\n");
  225. LOG0("\t253:\tCheck service environment for %%User_specific_variable%%\n");
  226. LOG0("\t254:\tTest I_ScPnPGetServiceName on valid and invalid handles\n");
  227. break;
  228. default:
  229. LOG1("Unrecognized opcode %ld\n", Opcode);
  230. }
  231. if (!SetServiceStatus(hssService, &ssService))
  232. {
  233. LOG1("SetServiceStatus error %ld\n", GetLastError());
  234. }
  235. if (Opcode == SERVICE_CONTROL_STOP || Opcode == SERVICE_CONTROL_SHUTDOWN)
  236. {
  237. SetEvent(g_hEvent);
  238. }
  239. return;
  240. }
  241. VOID WINAPI
  242. ServiceStart(
  243. DWORD argc,
  244. LPTSTR *argv
  245. )
  246. {
  247. g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  248. if (g_hEvent == NULL)
  249. {
  250. LOG1("CreateEvent error = %d\n", GetLastError());
  251. return;
  252. }
  253. ssService.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  254. ssService.dwCurrentState = SERVICE_START_PENDING;
  255. ssService.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  256. SERVICE_ACCEPT_SHUTDOWN |
  257. SERVICE_ACCEPT_POWEREVENT |
  258. SERVICE_ACCEPT_HARDWAREPROFILECHANGE |
  259. SERVICE_ACCEPT_SESSIONCHANGE;
  260. ssService.dwWin32ExitCode = 0;
  261. ssService.dwServiceSpecificExitCode = 0;
  262. ssService.dwCheckPoint = 0;
  263. ssService.dwWaitHint = 0;
  264. hssService = RegisterServiceCtrlHandler(TEXT("simservice"),
  265. ServiceCtrlHandler);
  266. if (hssService == (SERVICE_STATUS_HANDLE)0)
  267. {
  268. LOG1("RegisterServiceCtrlHandler failed %d\n", GetLastError());
  269. return;
  270. }
  271. //
  272. // Initialization complete - report running status.
  273. //
  274. ssService.dwCurrentState = SERVICE_RUNNING;
  275. ssService.dwCheckPoint = 0;
  276. ssService.dwWaitHint = 0;
  277. LOG0("Initialized and running\n");
  278. LOG1("PID is %d\n", GetCurrentProcessId());
  279. LOG1("TID is %d\n", GetCurrentThreadId());
  280. if (!SetServiceStatus (hssService, &ssService))
  281. {
  282. LOG1("SetServiceStatus error %ld\n", GetLastError());
  283. }
  284. WaitForSingleObject(g_hEvent, INFINITE);
  285. ssService.dwCurrentState = SERVICE_STOPPED;
  286. ssService.dwCheckPoint = 0;
  287. ssService.dwWaitHint = 0;
  288. if (!SetServiceStatus (hssService, &ssService))
  289. {
  290. LOG1("SetServiceStatus error %ld\n", GetLastError());
  291. }
  292. LOG0("Returning the Main Thread\n");
  293. return;
  294. }
  295. VOID
  296. OverflowStackBuffer(
  297. VOID
  298. )
  299. {
  300. CHAR lpBuffer[100];
  301. ZeroMemory(lpBuffer, 200);
  302. strcpy(lpBuffer, "This buffer's already toast\n");
  303. DbgPrint(lpBuffer);
  304. //
  305. // Should generate an overrun "exception" here
  306. //
  307. return;
  308. }
  309. int __cdecl main( )
  310. {
  311. SERVICE_TABLE_ENTRY DispatchTable[] =
  312. {
  313. { TEXT("simservice"), ServiceStart },
  314. { NULL, NULL }
  315. };
  316. #ifdef FLOOD_PIPE
  317. LOG1("Service PID is %d\n", GetCurrentProcessId());
  318. LOG0("Sleeping for 20 seconds\n");
  319. Sleep(20000);
  320. #endif // FLOOD_PIPE
  321. if (!StartServiceCtrlDispatcher(DispatchTable))
  322. {
  323. LOG1("StartServiceCtrlDispatcher error = %d\n", GetLastError());
  324. }
  325. return 0;
  326. }