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.

637 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ts3.c
  5. Abstract:
  6. This is a test program for exercising the service controller. This
  7. program acts like a service and exercises the Service Controller API
  8. that can be called from a service:
  9. SetServiceStatus
  10. StartServiceCtrlDispatcher
  11. RegisterServiceCtrlHandler
  12. Author:
  13. Dan Lafferty (danl) 2 Apr-1992
  14. Environment:
  15. User Mode -Win32
  16. Revision History:
  17. --*/
  18. //
  19. // Includes
  20. //
  21. #include <nt.h> // DbgPrint prototype
  22. #include <ntrtl.h> // DbgPrint prototype
  23. #include <nturtl.h> // needed for winbase.h
  24. #include <windows.h>
  25. #include <winsvc.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <fcntl.h> // OpenFile
  29. #include <sys\types.h> // OpenFile
  30. #include <sys\stat.h> // OpenFile
  31. #include <io.h> // OpenFile
  32. #include <tstr.h> // Unicode string macros
  33. #include <rpc.h>
  34. //
  35. // Defines
  36. //
  37. #define INFINITE_WAIT_TIME 0xffffffff
  38. #define NULL_STRING TEXT("");
  39. //
  40. // Globals
  41. //
  42. SERVICE_STATUS SingleStatus;
  43. HANDLE SingleDoneEvent;
  44. SERVICE_STATUS_HANDLE SingleStatusHandle;
  45. //
  46. // Function Prototypes
  47. //
  48. VOID
  49. SingleStart (
  50. DWORD argc,
  51. LPTSTR *argv
  52. );
  53. VOID
  54. SingleCtrlHandler (
  55. IN DWORD opcode
  56. );
  57. DWORD
  58. GetIntlFormat(
  59. LPWSTR type,
  60. LPWSTR string,
  61. DWORD numChars);
  62. VOID
  63. GetTime(
  64. LPWSTR *time
  65. );
  66. /****************************************************************************/
  67. VOID __cdecl
  68. main(void)
  69. {
  70. DWORD status;
  71. SERVICE_TABLE_ENTRY DispatchTable[] = {
  72. { TEXT("single"), SingleStart },
  73. { TEXT("single1"), SingleStart }, // this entry should be ignored.
  74. { NULL, NULL }
  75. };
  76. if (!StartServiceCtrlDispatcher( DispatchTable)) {
  77. status = GetLastError();
  78. DbgPrint("[ts3]StartServiceCtrlDispatcher failed %d \n",status);
  79. if (status = ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
  80. printf("Failed to connect to service controller, this "
  81. "program should be started with the Services Control Panel Applet, "
  82. "or at the command line with Net Start <ServiceName>");
  83. }
  84. }
  85. DbgPrint("[ts3]The Service Process is Terminating....)\n");
  86. ExitProcess(0);
  87. }
  88. /****************************************************************************/
  89. //
  90. // Single will take a long time to respond to pause
  91. //
  92. //
  93. VOID
  94. SingleStart (
  95. DWORD argc,
  96. LPTSTR *argv
  97. )
  98. {
  99. DWORD status;
  100. DWORD i;
  101. NETRESOURCEW netResource;
  102. DbgPrint(" [SINGLE] Inside the Single Service Thread\n");
  103. for (i=0; i<argc; i++) {
  104. DbgPrint(" [SINGLE] CommandArg%d = %s\n", i,argv[i]);
  105. }
  106. SingleDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
  107. //
  108. // Fill in this services status structure
  109. //
  110. DbgPrint(" [SINGLE] Send status with ServiceType = SERVICE_WIN32\n"
  111. " This should not overwrite the copy that SC maintains\n"
  112. " which should be SERVICE_WIN32_OWN_PROCESS\n");
  113. SingleStatus.dwServiceType = SERVICE_WIN32;
  114. SingleStatus.dwCurrentState = SERVICE_RUNNING;
  115. SingleStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  116. SERVICE_ACCEPT_PAUSE_CONTINUE;
  117. SingleStatus.dwWin32ExitCode = 0;
  118. SingleStatus.dwServiceSpecificExitCode = 0;
  119. SingleStatus.dwCheckPoint = 0;
  120. SingleStatus.dwWaitHint = 0;
  121. //
  122. // Register the Control Handler routine.
  123. //
  124. DbgPrint(" [SINGLE] Getting Ready to call RegisterServiceCtrlHandler\n");
  125. SingleStatusHandle = RegisterServiceCtrlHandler(
  126. TEXT("single"),
  127. SingleCtrlHandler);
  128. if (SingleStatusHandle == (SERVICE_STATUS_HANDLE)0) {
  129. DbgPrint(" [SINGLE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
  130. }
  131. //
  132. // Return the status
  133. //
  134. if (!SetServiceStatus (SingleStatusHandle, &SingleStatus)) {
  135. status = GetLastError();
  136. DbgPrint(" [SINGLE] SetServiceStatus error %ld\n",status);
  137. }
  138. //================================
  139. // SPECIAL TEST GOES HERE.
  140. //================================
  141. #define TEST_USE_ADD
  142. #ifdef TEST_USE_ADD
  143. netResource.lpRemoteName = L"\\\\Kernel\\scratch";
  144. netResource.lpLocalName = L"z:";
  145. netResource.lpProvider = NULL;
  146. netResource.dwType = RESOURCETYPE_DISK;
  147. status = WNetAddConnection2W(&netResource, NULL, NULL, 0L);
  148. if (status != NO_ERROR) {
  149. DbgPrint("WNetAddConnection (z:) Failed %d\n",status);
  150. }
  151. netResource.lpRemoteName = L"\\\\popcorn\\public";
  152. netResource.lpLocalName = L"p:";
  153. netResource.lpProvider = NULL;
  154. netResource.dwType = RESOURCETYPE_DISK;
  155. status = WNetAddConnection2W(&netResource, NULL, NULL, 0L);
  156. if (status != NO_ERROR) {
  157. DbgPrint("WNetAddConnection (p:) Failed %d\n",status);
  158. }
  159. #endif
  160. {
  161. UUID Uuid;
  162. RPC_STATUS rpcstatus;
  163. rpcstatus = UuidCreate(&Uuid);
  164. if (rpcstatus != NO_ERROR) {
  165. DbgPrint("UuidCreate Failed %d \n",rpcstatus);
  166. }
  167. }
  168. //
  169. // Wait forever until we are told to terminate.
  170. //
  171. {
  172. //
  173. // This portion of the code determines that the working directory
  174. // is the system32 directory.
  175. //
  176. LPSTR String = GetEnvironmentStrings();
  177. DWORD rc;
  178. Sleep(1000);
  179. while (*String != 0) {
  180. DbgPrint("%s\n",String);
  181. String += (strlen(String) + 1);
  182. }
  183. rc = _open("DansFile.txt",O_CREAT | O_BINARY,S_IREAD | S_IWRITE);
  184. if (rc == -1) {
  185. DbgPrint("OpenFile Failed\n");
  186. }
  187. }
  188. status = WaitForSingleObject (
  189. SingleDoneEvent,
  190. INFINITE_WAIT_TIME);
  191. status = WNetCancelConnectionW(L"z:",FALSE);
  192. if (status != NO_ERROR) {
  193. DbgPrint("WNetCancelConnection (z:) Failed %d\n",status);
  194. }
  195. status = WNetCancelConnectionW(L"p:",FALSE);
  196. if (status != NO_ERROR) {
  197. DbgPrint("WNetCancelConnection (p:) Failed %d\n",status);
  198. }
  199. DbgPrint(" [SINGLE] Leaving the single service\n");
  200. ExitThread(NO_ERROR);
  201. return;
  202. }
  203. /****************************************************************************/
  204. VOID
  205. SingleCtrlHandler (
  206. IN DWORD Opcode
  207. )
  208. {
  209. DWORD status;
  210. LPWSTR time;
  211. HANDLE enumHandle;
  212. DWORD numElements;
  213. DWORD bufferSize;
  214. LPNETRESOURCE pNetResource;
  215. DWORD i;
  216. DbgPrint(" [SINGLE] opcode = %ld\n", Opcode);
  217. //
  218. // Find and operate on the request.
  219. //
  220. switch(Opcode) {
  221. case SERVICE_CONTROL_PAUSE:
  222. DbgPrint("[SINGLE] Sleep 1 minute before responding to pause request\n");
  223. Sleep(60000); // 1 minute
  224. SingleStatus.dwCurrentState = SERVICE_PAUSED;
  225. break;
  226. case SERVICE_CONTROL_CONTINUE:
  227. SingleStatus.dwCurrentState = SERVICE_RUNNING;
  228. break;
  229. case SERVICE_CONTROL_STOP:
  230. SingleStatus.dwWin32ExitCode = 0;
  231. SingleStatus.dwCurrentState = SERVICE_STOPPED;
  232. SetEvent(SingleDoneEvent);
  233. break;
  234. case SERVICE_CONTROL_INTERROGATE:
  235. status = WNetOpenEnumW(
  236. RESOURCE_CONNECTED,
  237. RESOURCETYPE_DISK,
  238. 0,
  239. NULL,
  240. &enumHandle);
  241. if (status != WN_SUCCESS) {
  242. DbgPrint("WNetOpenEnum failed %d\n",status);
  243. }
  244. else {
  245. //
  246. // Attempt to allow for 10 connections
  247. //
  248. bufferSize = (10*sizeof(NETRESOURCE))+1024;
  249. pNetResource = (LPNETRESOURCE) LocalAlloc(LPTR, bufferSize);
  250. if (pNetResource == NULL) {
  251. DbgPrint("TestEnum:LocalAlloc Failed %d\n",GetLastError);
  252. break;
  253. }
  254. numElements = 0xffffffff;
  255. status = WNetEnumResourceW(
  256. enumHandle,
  257. &numElements,
  258. pNetResource,
  259. &bufferSize);
  260. if ( status != WN_SUCCESS) {
  261. DbgPrint("WNetEnumResource failed %d\n",status);
  262. //
  263. // If there is an extended error, display it.
  264. //
  265. if (status == WN_EXTENDED_ERROR) {
  266. DbgPrint("Extended Error\n");
  267. }
  268. WNetCloseEnum(enumHandle);
  269. LocalFree(pNetResource);
  270. }
  271. else {
  272. if (numElements == 0) {
  273. DbgPrint("No Connections to Enumerate\n");
  274. }
  275. for (i=0; i < numElements ;i++ ) {
  276. DbgPrint("%ws is connected to %ws\n",
  277. pNetResource[i].lpLocalName,
  278. pNetResource[i].lpRemoteName);
  279. }
  280. WNetCloseEnum(enumHandle);
  281. LocalFree(pNetResource);
  282. }
  283. }
  284. GetTime(&time);
  285. DbgPrint(" [SINGLE] time = %ws\n",time);
  286. break;
  287. default:
  288. DbgPrint(" [SINGLE] Unrecognized opcode %ld\n", Opcode);
  289. }
  290. //
  291. // Send a status response.
  292. //
  293. if (!SetServiceStatus (SingleStatusHandle, &SingleStatus)) {
  294. status = GetLastError();
  295. DbgPrint(" [SINGLE] SetServiceStatus error %ld\n",status);
  296. }
  297. return;
  298. }
  299. //************************************************************************
  300. //
  301. // TEST CODE
  302. //
  303. //************************************************************************
  304. #define PARSE_SIZE 80
  305. #define TIME_SEP_SIZE 2
  306. VOID
  307. GetTime(
  308. LPWSTR *time
  309. )
  310. {
  311. WCHAR czParseString[PARSE_SIZE];
  312. WCHAR czTimeString[PARSE_SIZE];
  313. LPWSTR pCurLoc;
  314. LPWSTR pTime;
  315. DWORD numChars;
  316. SYSTEMTIME SysTime;
  317. LPWSTR AMPMString=L"";
  318. WCHAR TimeSep[TIME_SEP_SIZE];
  319. BOOL TwelveHour=TRUE;
  320. BOOL LeadingZero=FALSE;
  321. DWORD i,dateType;
  322. DWORD numSame;
  323. //-----------------------------------------
  324. // Get the Current Time and Date.
  325. //-----------------------------------------
  326. GetLocalTime(&SysTime);
  327. #ifdef CL_DEBUG
  328. printf("Year=%d,Month=%d,Day=%d,Hour=%d,Minute=%d\n",
  329. SysTime.wYear,
  330. SysTime.wMonth,
  331. SysTime.wDay,
  332. SysTime.wHour,
  333. SysTime.wMinute);
  334. #endif
  335. //-----------------------------------------
  336. // Get the Date Format (M/d/yy)
  337. //-----------------------------------------
  338. numChars = GetIntlFormat(L"sShortDate",czParseString,PARSE_SIZE);
  339. if (numChars == 0) {
  340. //
  341. // No data, use the default.
  342. //
  343. wcscpy(czParseString, L"M/d/yy");
  344. }
  345. //-----------------------------------------
  346. // Fill in the date string
  347. //-----------------------------------------
  348. pCurLoc = czTimeString;
  349. for (i=0; i<numChars; i++ ) {
  350. dateType = i;
  351. numSame = 1;
  352. //
  353. // Find out how many characters are the same.
  354. // (MM or M, dd or d, yy or yyyy)
  355. //
  356. while (czParseString[i] == czParseString[i+1]) {
  357. numSame++;
  358. i++;
  359. }
  360. //
  361. // i is the offset to the last character in the date type.
  362. //
  363. switch (czParseString[dateType]) {
  364. case L'M':
  365. case L'm':
  366. //
  367. // If we have a single digit month, but require 2 digits,
  368. // then add a leading zero.
  369. //
  370. if ((numSame == 2) && (SysTime.wMonth < 10)) {
  371. *pCurLoc = L'0';
  372. pCurLoc++;
  373. }
  374. ultow(SysTime.wMonth, pCurLoc, 10);
  375. pCurLoc += wcslen(pCurLoc);
  376. break;
  377. case L'D':
  378. case L'd':
  379. //
  380. // If we have a single digit day, but require 2 digits,
  381. // then add a leading zero.
  382. //
  383. if ((numSame == 2) && (SysTime.wDay < 10)) {
  384. *pCurLoc = L'0';
  385. pCurLoc++;
  386. }
  387. ultow(SysTime.wDay, pCurLoc, 10);
  388. pCurLoc += wcslen(pCurLoc);
  389. break;
  390. case L'Y':
  391. case L'y':
  392. ultow(SysTime.wYear, pCurLoc, 10);
  393. //
  394. // If we are only to show 2 digits, take the
  395. // 3rd and 4th, and move them into the first two
  396. // locations.
  397. //
  398. if (numSame == 2) {
  399. pCurLoc[0] = pCurLoc[2];
  400. pCurLoc[1] = pCurLoc[3];
  401. pCurLoc[2] = L'\0';
  402. }
  403. pCurLoc += wcslen(pCurLoc);
  404. break;
  405. default:
  406. printf("Default case: Unrecognized time character - "
  407. "We Should never get here\n");
  408. break;
  409. }
  410. //
  411. // Increment the index beyond the last character in the data type.
  412. // If not at the end of the buffer, add the separator character.
  413. // Otherwise, add the trailing NUL.
  414. //
  415. i++;
  416. if ( i<numChars ) {
  417. *pCurLoc = czParseString[i];
  418. pCurLoc++;
  419. }
  420. else {
  421. *pCurLoc='\0';
  422. }
  423. }
  424. //-----------------------------------------
  425. // 12 or 24 hour format?
  426. //-----------------------------------------
  427. numChars = GetIntlFormat(L"iTime",czParseString,PARSE_SIZE);
  428. if (numChars > 0) {
  429. if (*czParseString == L'1'){
  430. TwelveHour = FALSE;
  431. }
  432. }
  433. //-----------------------------------------
  434. // Is there a Leading Zero?
  435. //-----------------------------------------
  436. if (GetProfileIntW(L"intl",L"iTLZero",0) == 1) {
  437. LeadingZero = TRUE;
  438. }
  439. //-----------------------------------------
  440. // Get the Time Separator character.
  441. //-----------------------------------------
  442. numChars = GetIntlFormat(L"sTime",TimeSep,TIME_SEP_SIZE);
  443. if (numChars == 0) {
  444. //
  445. // No data, use the default.
  446. //
  447. TimeSep[0] = L':';
  448. TimeSep[1] = L'\0';
  449. }
  450. //-------------------------------------------------
  451. // If running a 12 hour clock, Get the AMPM string.
  452. //-------------------------------------------------
  453. if (TwelveHour) {
  454. if (SysTime.wHour > 11) {
  455. numChars = GetIntlFormat(L"s2359",czParseString,PARSE_SIZE);
  456. }
  457. else {
  458. numChars = GetIntlFormat(L"s1159",czParseString,PARSE_SIZE);
  459. }
  460. if (numChars > 0) {
  461. AMPMString = LocalAlloc(LMEM_FIXED,wcslen(czParseString)+sizeof(WCHAR));
  462. if (AMPMString != NULL) {
  463. wcscpy(AMPMString,czParseString);
  464. }
  465. }
  466. }
  467. //
  468. // Build the time string
  469. //
  470. pTime = czTimeString + (wcslen(czTimeString) + 1);
  471. if ((TwelveHour) && (SysTime.wHour > 12)) {
  472. SysTime.wHour -= 12;
  473. }
  474. //
  475. // If the time is a single digit, and we need a leading zero,
  476. // than add the leading zero.
  477. //
  478. if ((SysTime.wHour < 10) && (LeadingZero)) {
  479. *pTime = L'0';
  480. pTime++;
  481. }
  482. ultow(SysTime.wHour, pTime, 10);
  483. pTime += wcslen(pTime);
  484. *pTime = *TimeSep;
  485. pTime++;
  486. if (SysTime.wMinute < 10) {
  487. *pTime = L'0';
  488. pTime++;
  489. }
  490. ultow(SysTime.wMinute, pTime, 10);
  491. wcscat(pTime,AMPMString);
  492. pTime = czTimeString + (wcslen(czTimeString) + 1);
  493. #ifdef CL_DEBUG
  494. printf("Time = %ws, Date = %ws\n",pTime,czTimeString);
  495. #endif
  496. *(--pTime) = L' ';
  497. printf("\n %ws\n", czTimeString);
  498. *time = czTimeString;
  499. }
  500. DWORD
  501. GetIntlFormat(
  502. LPWSTR type,
  503. LPWSTR string,
  504. DWORD numChars)
  505. {
  506. DWORD num;
  507. num = GetProfileStringW(L"intl",type,L"",string,numChars);
  508. #ifdef CL_DEBUG
  509. if (num > 0) {
  510. printf("%ws string from ini file = %ws\n",type, string);
  511. }
  512. else {
  513. printf("%ws string from ini file = (empty)\n",type);
  514. }
  515. #endif
  516. return(num);
  517. }