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.

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