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.

545 lines
15 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h> // DbgPrint prototype
  3. #include <nturtl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <windows.h>
  7. #include <winsvc.h>
  8. #include <winsvcp.h>
  9. #include <winuser.h>
  10. #include <dbt.h>
  11. #include <crtdbg.h>
  12. #include <wtsapi32.h>
  13. #include <tchar.h>
  14. #include <logmsg.h>
  15. //
  16. // Definitions
  17. //
  18. #define MAKARP_LOG0(string) \
  19. (VOID) DbgPrint(string); \
  20. LOGMESSAGE0(string);
  21. #define MAKARP_LOG1(string, var) \
  22. (VOID) DbgPrint(string, var); \
  23. LOGMESSAGE1(string, var);
  24. #define MAKARP_LOG2(string, var1, var2) \
  25. (VOID) DbgPrint(string, var1, var2); \
  26. LOGMESSAGE2(string, var1, var2);
  27. #define LOG0(string) \
  28. #define LOG1(string, var) \
  29. #define LOG2(string, var1, var2) \
  30. //
  31. // Test fix for bug #106110
  32. //
  33. // #define FLOOD_PIPE
  34. //
  35. //
  36. // Test fix for bug #120359
  37. //
  38. static const GUID GUID_NDIS_LAN_CLASS =
  39. {0xad498944,0x762f,0x11d0,{0x8d,0xcb,0x00,0xc0,0x4f,0xc3,0x35,0x8c}};
  40. //
  41. // Globals
  42. //
  43. SERVICE_STATUS ssService;
  44. SERVICE_STATUS_HANDLE hssService;
  45. HANDLE g_hEvent;
  46. BOOL IsUserLoggedOn(DWORD dwSessionId)
  47. {
  48. LPTSTR pBuffer = NULL;
  49. DWORD dwBytesReturned;
  50. if (WTSQuerySessionInformation(
  51. WTS_CURRENT_SERVER_HANDLE,
  52. dwSessionId,
  53. WTSUserName,
  54. &pBuffer,
  55. &dwBytesReturned
  56. ))
  57. {
  58. if (pBuffer)
  59. {
  60. MAKARP_LOG1("Logged on user is %s\n", pBuffer);
  61. }
  62. else
  63. {
  64. MAKARP_LOG0("Logged on user is NULL\n");
  65. }
  66. }
  67. else
  68. {
  69. MAKARP_LOG0("WTSQuerySessionInformation failed\n");
  70. }
  71. return TRUE;
  72. }
  73. void PrintNotification(DWORD dwEventType, PWTSSESSION_NOTIFICATION pConsoleNotification)
  74. {
  75. TCHAR szString[1024];
  76. DWORD dwBytesReturned;
  77. LPTSTR pBuffer = NULL;
  78. int i = 0;
  79. i += sprintf(szString + i, "------------* Start Received console switch notification *-----------\n");
  80. switch (dwEventType)
  81. {
  82. case WTS_CONSOLE_CONNECT:
  83. i += sprintf(szString + i, "Event = WTS_CONSOLE_CONNECT\n");
  84. break;
  85. case WTS_CONSOLE_DISCONNECT:
  86. i += sprintf(szString + i, "Event = WTS_CONSOLE_DISCONNECT\n");
  87. break;
  88. case WTS_REMOTE_CONNECT:
  89. i += sprintf(szString + i, "Event = WTS_REMOTE_CONNECT\n");
  90. break;
  91. case WTS_REMOTE_DISCONNECT:
  92. i += sprintf(szString + i, "Event = WTS_REMOTE_DISCONNECT\n");
  93. break;
  94. case WTS_SESSION_LOGON:
  95. i += sprintf(szString + i, "Event = WTS_SESSION_LOGON\n");
  96. break;
  97. case WTS_SESSION_LOGOFF:
  98. i += sprintf(szString + i, "Event = WTS_SESSION_LOGOFF\n");
  99. break;
  100. default:
  101. ASSERT(WTS_CONSOLE_DISCONNECT == dwEventType); // ASSERT(FALSE);
  102. i += sprintf(szString + i, "Event = UNKNOWN\n");
  103. break;
  104. }
  105. if (WTSQuerySessionInformation(
  106. WTS_CURRENT_SERVER_HANDLE,
  107. pConsoleNotification->dwSessionId,
  108. WTSUserName,
  109. &pBuffer,
  110. &dwBytesReturned
  111. ))
  112. {
  113. if (pBuffer)
  114. {
  115. i += sprintf(szString + i, "Logged on user is %s\n", pBuffer);
  116. }
  117. else
  118. {
  119. i += sprintf(szString + i, "Logged on user is NULL\n");
  120. }
  121. }
  122. else
  123. {
  124. i += sprintf(szString + i, "WTSQuerySessionInformation failed\n");
  125. }
  126. WTSFreeMemory(pBuffer);
  127. i += sprintf(szString + i, "Size = %ld\n", pConsoleNotification->cbSize);
  128. i += sprintf(szString + i, "Session = %ld\n", pConsoleNotification->dwSessionId);
  129. i += sprintf(szString + i, "------------* End Received console switch notification *-----------\n");
  130. MAKARP_LOG1("%s", szString);
  131. }
  132. VOID WINAPI
  133. ServiceStart(
  134. DWORD /*argc */,
  135. LPTSTR * /*argv*/
  136. );
  137. DWORD WINAPI
  138. ServiceCtrlHandler(
  139. DWORD Opcode,
  140. DWORD dwEventType,
  141. PVOID EventData,
  142. PVOID /*pData*/ )
  143. {
  144. PWTSSESSION_NOTIFICATION pConsoleNotification;
  145. switch(Opcode)
  146. {
  147. case SERVICE_CONTROL_SESSIONCHANGE:
  148. pConsoleNotification = (PWTSSESSION_NOTIFICATION) EventData;
  149. PrintNotification(dwEventType, pConsoleNotification);
  150. break;
  151. case SERVICE_CONTROL_PAUSE:
  152. ssService.dwCurrentState = SERVICE_PAUSED;
  153. LOG0("Service paused\n");
  154. break;
  155. case SERVICE_CONTROL_CONTINUE:
  156. ssService.dwCurrentState = SERVICE_RUNNING;
  157. LOG0("Service continuing\n");
  158. break;
  159. case SERVICE_CONTROL_SHUTDOWN:
  160. LOG0("Shutdown command received\n");
  161. //
  162. // Fall through to STOP case
  163. //
  164. case SERVICE_CONTROL_STOP:
  165. ssService.dwWin32ExitCode = 0;
  166. ssService.dwCurrentState = SERVICE_STOP_PENDING;
  167. ssService.dwCheckPoint = 0;
  168. ssService.dwWaitHint = 0;
  169. break;
  170. case SERVICE_CONTROL_INTERROGATE:
  171. LOG0("Service interrogated\n");
  172. break;
  173. case 251:
  174. {
  175. DWORD dwError;
  176. DWORD dwTest = 0xabcdefab;
  177. //
  178. // Try a bad address
  179. //
  180. dwError = I_ScSendTSMessage(SERVICE_CONTROL_SESSIONCHANGE,
  181. 0,
  182. 0,
  183. NULL);
  184. LOG1("I_ScSendTSMessage with NULL pointer returned %d\n", dwError);
  185. //
  186. // Try a bad control
  187. //
  188. dwError = I_ScSendTSMessage(SERVICE_CONTROL_STOP,
  189. 0,
  190. sizeof(DWORD),
  191. (LPBYTE) &dwTest);
  192. LOG1("I_ScSendTSMessage for SERVICE_CONTROL_STOP returned %d\n", dwError);
  193. //
  194. // Now try for real
  195. //
  196. dwError = I_ScSendTSMessage(SERVICE_CONTROL_SESSIONCHANGE,
  197. 0,
  198. sizeof(DWORD),
  199. (LPBYTE) &dwTest);
  200. LOG1("I_ScSendTSMessage (real call) returned %d\n", dwError);
  201. break;
  202. }
  203. case 252:
  204. {
  205. DEV_BROADCAST_DEVICEINTERFACE dbdPnpFilter;
  206. //
  207. // Test fix for bug #120359
  208. //
  209. ssService.dwCurrentState = SERVICE_STOPPED;
  210. //
  211. // Eventlog's SERVICE_STATUS_HANDLE when I checked
  212. //
  213. if (!SetServiceStatus((SERVICE_STATUS_HANDLE)0x96df8, &ssService))
  214. {
  215. LOG1("Fix works -- SetServiceStatus error %ld\n", GetLastError());
  216. }
  217. else
  218. {
  219. LOG0("ERROR -- SetServiceStatus call succeeded!\n");
  220. }
  221. //
  222. // Eventlog's LPSERVICE_RECORD when I checked
  223. //
  224. if (!SetServiceStatus((SERVICE_STATUS_HANDLE)0x4844e8, &ssService))
  225. {
  226. LOG1("Fix works -- SetServiceStatus error %ld\n", GetLastError());
  227. }
  228. else
  229. {
  230. LOG0("ERROR -- SetServiceStatus call succeeded!\n");
  231. }
  232. //
  233. // SERVICE_STATUS_HANDLE again
  234. //
  235. ZeroMemory (&dbdPnpFilter, sizeof(dbdPnpFilter));
  236. dbdPnpFilter.dbcc_size = sizeof(dbdPnpFilter);
  237. dbdPnpFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  238. dbdPnpFilter.dbcc_classguid = GUID_NDIS_LAN_CLASS;
  239. if (!RegisterDeviceNotification((SERVICE_STATUS_HANDLE)0x96df8,
  240. &dbdPnpFilter,
  241. DEVICE_NOTIFY_SERVICE_HANDLE))
  242. {
  243. LOG1("Fix works -- RegisterDeviceNotification error %ld\n", GetLastError());
  244. }
  245. else
  246. {
  247. LOG0("ERROR -- RegisterDeviceNotification call succeeded!\n");
  248. }
  249. ssService.dwCurrentState = SERVICE_RUNNING;
  250. break;
  251. }
  252. case 253:
  253. {
  254. //
  255. // Test fix for bug #36395. Make sure that we inherited the
  256. // environment block of the user, not the system. NOTE this
  257. // assumes the service is running in an account AND the
  258. // variable we're looking for is in the user's environment.
  259. //
  260. CHAR cTemp[1];
  261. /*DWORD dwCount = */ GetEnvironmentVariable("User_specific_variable",
  262. cTemp,
  263. sizeof(cTemp));
  264. LOG1("GetEnvironmentVariable on User_specific_variable %ws\n",
  265. (dwCount == 0 ? L"FAILED!" : L"succeeded"));
  266. break;
  267. }
  268. case 254:
  269. {
  270. //
  271. // Test client-side API for #120359 fix
  272. //
  273. WCHAR wszServiceName[256 + 1];
  274. DWORD dwError;
  275. dwError = I_ScPnPGetServiceName(hssService, wszServiceName, 256);
  276. if (dwError == NO_ERROR)
  277. {
  278. LOG0("I_ScPnPGetServiceName succeeded for valid handle\n");
  279. LOG1("ServiceName is %ws\n", wszServiceName);
  280. }
  281. else
  282. {
  283. LOG0("I_ScPnPGetServiceName failed for valid handle!\n");
  284. LOG1("Error was %d\n", dwError);
  285. }
  286. dwError = I_ScPnPGetServiceName(NULL, wszServiceName, 256);
  287. if (dwError == NO_ERROR)
  288. {
  289. LOG0("I_ScPnPGetServiceName succeeded for NULL handle!\n");
  290. LOG1("ServiceName is %ws\n", wszServiceName);
  291. }
  292. else
  293. {
  294. LOG0("I_ScPnPGetServiceName failed for NULL handle!\n");
  295. LOG1("Error was %d\n", dwError);
  296. }
  297. break;
  298. }
  299. case 255:
  300. //
  301. // Print controls to the debugger
  302. //
  303. LOG0("Controls supported:\n");
  304. LOG0("\t251:\tTry calling I_ScSendTSMessage\n");
  305. LOG0("\t252:\tTry calling SetServiceStatus with a bogus status handle\n");
  306. LOG0("\t253:\tCheck service environment for %%User_specific_variable%%\n");
  307. LOG0("\t254:\tTest I_ScPnPGetServiceName on valid and invalid handles\n");
  308. break;
  309. default:
  310. LOG1("Unrecognized opcode %ld\n", Opcode);
  311. }
  312. if (!SetServiceStatus(hssService, &ssService))
  313. {
  314. LOG1("SetServiceStatus error %ld\n", GetLastError());
  315. }
  316. if (Opcode == SERVICE_CONTROL_STOP || Opcode == SERVICE_CONTROL_SHUTDOWN)
  317. {
  318. SetEvent(g_hEvent);
  319. }
  320. return NO_ERROR;
  321. }
  322. VOID WINAPI
  323. ServiceStart(
  324. DWORD /*argc */,
  325. LPTSTR * /*argv*/
  326. )
  327. {
  328. LOGMESSAGEINIT(_T("c:\\temp\\consrv.log"), _T("consrv"));
  329. g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  330. if (g_hEvent == NULL)
  331. {
  332. LOG1("CreateEvent error = %d\n", GetLastError());
  333. return;
  334. }
  335. ssService.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  336. ssService.dwCurrentState = SERVICE_START_PENDING;
  337. ssService.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  338. SERVICE_ACCEPT_SHUTDOWN |
  339. SERVICE_ACCEPT_POWEREVENT |
  340. SERVICE_ACCEPT_SESSIONCHANGE;
  341. ssService.dwWin32ExitCode = 0;
  342. ssService.dwServiceSpecificExitCode = 0;
  343. ssService.dwCheckPoint = 0;
  344. ssService.dwWaitHint = 0;
  345. hssService = RegisterServiceCtrlHandlerEx(TEXT("simservice"),
  346. ServiceCtrlHandler,
  347. (LPVOID) 0xdeadbeef);
  348. if (hssService == (SERVICE_STATUS_HANDLE)0)
  349. {
  350. LOG1("RegisterServiceCtrlHandler failed %d\n", GetLastError());
  351. return;
  352. }
  353. //
  354. // Initialization complete - report running status.
  355. //
  356. ssService.dwCurrentState = SERVICE_RUNNING;
  357. ssService.dwCheckPoint = 0;
  358. ssService.dwWaitHint = 0;
  359. LOG0("Initialized and running\n");
  360. LOG1("PID is %d\n", GetCurrentProcessId());
  361. LOG1("TID is %d\n", GetCurrentThreadId());
  362. if (!SetServiceStatus (hssService, &ssService))
  363. {
  364. LOG1("SetServiceStatus error %ld\n", GetLastError());
  365. }
  366. WaitForSingleObject(g_hEvent, INFINITE);
  367. ssService.dwCurrentState = SERVICE_STOPPED;
  368. ssService.dwCheckPoint = 0;
  369. ssService.dwWaitHint = 0;
  370. if (!SetServiceStatus (hssService, &ssService))
  371. {
  372. LOG1("SetServiceStatus error %ld\n", GetLastError());
  373. }
  374. LOG0("Returning the Main Thread\n");
  375. return;
  376. }
  377. int __cdecl main( int argc, char *argv[])
  378. {
  379. if (argc == 2 && _stricmp(argv[1], "install") == 0)
  380. {
  381. SC_HANDLE hSCMgr = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);
  382. if (hSCMgr)
  383. {
  384. SC_HANDLE hService = CreateService(
  385. hSCMgr, // handle to SCM database
  386. "ConSrvName", // name of service to start
  387. "ConSrvDisplayName", // display name
  388. SERVICE_ALL_ACCESS, // type of access to service
  389. SERVICE_WIN32_OWN_PROCESS, // type of service
  390. SERVICE_DEMAND_START, // when to start service
  391. SERVICE_ERROR_IGNORE, // severity of service failure
  392. "d:\\winnt\\system32\\consrv.exe", // name of binary file
  393. NULL, // name of load ordering group
  394. NULL, // tag identifier
  395. NULL, // array of dependency names
  396. NULL, // account name
  397. NULL // account password
  398. );
  399. if (hService)
  400. {
  401. MAKARP_LOG0("Service Installed Ok.\n");
  402. }
  403. else
  404. {
  405. MAKARP_LOG1("CreateService failed, error = %ld", GetLastError());
  406. }
  407. }
  408. else
  409. {
  410. MAKARP_LOG1("OpenSCManager failed, error %ld\n", GetLastError());
  411. }
  412. }
  413. else
  414. {
  415. SERVICE_TABLE_ENTRY DispatchTable[] =
  416. {
  417. { TEXT("simservice"), ServiceStart },
  418. { NULL, NULL }
  419. };
  420. #ifdef FLOOD_PIPE
  421. LOG1("Service PID is %d\n", GetCurrentProcessId());
  422. LOG0("Sleeping for 20 seconds\n");
  423. Sleep(20000);
  424. #endif // FLOOD_PIPE
  425. if (!StartServiceCtrlDispatcher(DispatchTable))
  426. {
  427. LOG1("StartServiceCtrlDispatcher error = %d\n", GetLastError());
  428. }
  429. return 0;
  430. }
  431. }