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.

677 lines
14 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. tsec.c
  5. Abstract:
  6. Test for the security functionality in service controller.
  7. Author:
  8. Rita Wong (ritaw) 16-Mar-1992
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include <stdio.h>
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <windef.h> // IN, BOOL, LPTSTR, etc.
  18. #include <winbase.h>
  19. #ifndef UNICODE
  20. #define UNICODE
  21. #endif
  22. #include <winsvc.h> // Win32 service control APIs
  23. DWORD
  24. TestOpenService(
  25. IN SC_HANDLE hScManager,
  26. OUT LPSC_HANDLE hService,
  27. IN LPWSTR ServiceName,
  28. IN DWORD DesiredAccess,
  29. IN DWORD ExpectedError
  30. );
  31. DWORD
  32. TestOpenSCManager(
  33. OUT LPSC_HANDLE hScManager,
  34. IN LPWSTR DatabaseName,
  35. IN DWORD DesiredAccess,
  36. IN DWORD ExpectedError
  37. );
  38. DWORD
  39. TestEnumServicesStatus(
  40. IN SC_HANDLE hSCManager,
  41. IN DWORD ExpectedError
  42. );
  43. DWORD
  44. TestQueryServiceStatus(
  45. IN SC_HANDLE hService,
  46. IN DWORD ExpectedError
  47. );
  48. DWORD
  49. TestControlService(
  50. IN SC_HANDLE hService,
  51. IN DWORD ControlCode,
  52. IN DWORD ExpectedError
  53. );
  54. DWORD
  55. TestStartService(
  56. IN SC_HANDLE hService,
  57. IN DWORD ExpectedError
  58. );
  59. VOID
  60. DisplayStatus(
  61. IN LPWSTR ServiceName OPTIONAL,
  62. IN LPSERVICE_STATUS ServiceStatus
  63. );
  64. BYTE WorkBuffer[1024];
  65. VOID __cdecl
  66. main(
  67. void
  68. )
  69. {
  70. DWORD status;
  71. SC_HANDLE hScManager;
  72. SC_HANDLE hService;
  73. PSECURITY_DESCRIPTOR lpSecurity = (PSECURITY_DESCRIPTOR) WorkBuffer;
  74. DWORD BytesRequired;
  75. //
  76. // Bad database name
  77. //
  78. (void) TestOpenSCManager(
  79. &hScManager,
  80. L"Bogus",
  81. 0,
  82. ERROR_INVALID_NAME
  83. );
  84. //
  85. // Failed database name
  86. //
  87. (void) TestOpenSCManager(
  88. &hScManager,
  89. L"SERVICESFAILED",
  90. 0,
  91. ERROR_DATABASE_DOES_NOT_EXIST
  92. );
  93. //
  94. // Active database name
  95. //
  96. if (TestOpenSCManager(
  97. &hScManager,
  98. L"SERVICESactive",
  99. 0,
  100. NO_ERROR
  101. ) == NO_ERROR) {
  102. (void) CloseServiceHandle(hScManager);
  103. }
  104. //
  105. // Invalid desired access
  106. //
  107. (void) TestOpenSCManager(
  108. &hScManager,
  109. NULL,
  110. 0xff00,
  111. ERROR_ACCESS_DENIED
  112. );
  113. //
  114. // Valid desired access
  115. //
  116. if (TestOpenSCManager(
  117. &hScManager,
  118. NULL,
  119. SC_MANAGER_CONNECT,
  120. NO_ERROR
  121. ) == NO_ERROR) {
  122. //
  123. // Invalid operation follows
  124. //
  125. (void) TestEnumServicesStatus(
  126. hScManager,
  127. ERROR_ACCESS_DENIED
  128. );
  129. (void) TestOpenService(
  130. hScManager,
  131. &hService,
  132. L"Lumpy",
  133. 0xf000,
  134. ERROR_ACCESS_DENIED
  135. );
  136. (void) TestOpenService(
  137. hScManager,
  138. &hService,
  139. L"Lu mpy",
  140. SERVICE_QUERY_STATUS,
  141. ERROR_INVALID_NAME
  142. );
  143. (void) TestOpenService(
  144. hScManager,
  145. &hService,
  146. L"\\Lumpy",
  147. SERVICE_QUERY_STATUS,
  148. ERROR_INVALID_NAME
  149. );
  150. (void) TestOpenService(
  151. hScManager,
  152. &hService,
  153. L"Lum/py",
  154. SERVICE_QUERY_STATUS,
  155. ERROR_INVALID_NAME
  156. );
  157. (void) TestOpenService(
  158. hScManager,
  159. &hService,
  160. L"Lump",
  161. SERVICE_QUERY_STATUS,
  162. ERROR_SERVICE_DOES_NOT_EXIST
  163. );
  164. //
  165. // Service handle opened with only query access
  166. //
  167. status = TestOpenService(
  168. hScManager,
  169. &hService,
  170. L"Lumpy",
  171. SERVICE_QUERY_STATUS,
  172. NO_ERROR
  173. );
  174. if (status == NO_ERROR) {
  175. (void) TestControlService(
  176. hService,
  177. SERVICE_CONTROL_PAUSE,
  178. ERROR_ACCESS_DENIED
  179. );
  180. (void) TestStartService(
  181. hService,
  182. ERROR_ACCESS_DENIED
  183. );
  184. (void) TestQueryServiceStatus(
  185. hService,
  186. NO_ERROR
  187. );
  188. (void) CloseServiceHandle(hService);
  189. }
  190. //
  191. // Test QueryServiceObjectSecurity and SetServiceObjectSecurity
  192. //
  193. status = TestOpenService(
  194. hScManager,
  195. &hService,
  196. L"Lumpy",
  197. READ_CONTROL | WRITE_DAC,
  198. NO_ERROR
  199. );
  200. if (status == NO_ERROR) {
  201. if (QueryServiceObjectSecurity(
  202. hService,
  203. DACL_SECURITY_INFORMATION,
  204. lpSecurity,
  205. sizeof(WorkBuffer),
  206. &BytesRequired
  207. )) {
  208. printf("QueryServiceObjectSecurity: OK. BytesRequired=%lu\n",
  209. BytesRequired);
  210. if (SetServiceObjectSecurity(
  211. hService,
  212. DACL_SECURITY_INFORMATION,
  213. lpSecurity
  214. )) {
  215. printf("SetServiceObjectSecurity: OK.\n");
  216. }
  217. else {
  218. printf("SetServiceObjectSecurity: Failed=%lu\n", GetLastError());
  219. }
  220. }
  221. else {
  222. printf("QueryServiceObjectSecurity: Failed=%lu\n", GetLastError());
  223. }
  224. (void) CloseServiceHandle(hService);
  225. }
  226. (void) CloseServiceHandle(hScManager);
  227. }
  228. //
  229. // Try MAXIMUM_ALLOWED desired access
  230. //
  231. status = TestOpenSCManager(
  232. &hScManager,
  233. NULL,
  234. MAXIMUM_ALLOWED,
  235. NO_ERROR
  236. );
  237. if (status == NO_ERROR) {
  238. (void) TestEnumServicesStatus(
  239. hScManager,
  240. NO_ERROR
  241. );
  242. (void) CloseServiceHandle(hScManager);
  243. }
  244. }
  245. DWORD
  246. TestOpenSCManager(
  247. OUT LPSC_HANDLE hScManager,
  248. IN LPWSTR DatabaseName,
  249. IN DWORD DesiredAccess,
  250. IN DWORD ExpectedError
  251. )
  252. {
  253. DWORD status = NO_ERROR;
  254. if (DatabaseName != NULL) {
  255. printf("OpenSCManager: DatabaseName=%ws, DesiredAccess=%08lx\n",
  256. DatabaseName, DesiredAccess);
  257. }
  258. else {
  259. printf("OpenSCManager: DatabaseName=(null), DesiredAccess=%08lx\n",
  260. DesiredAccess);
  261. }
  262. *hScManager = OpenSCManager(
  263. NULL,
  264. DatabaseName,
  265. DesiredAccess
  266. );
  267. if (*hScManager == (SC_HANDLE) NULL) {
  268. status = GetLastError();
  269. if (ExpectedError != status) {
  270. printf(" FAILED. Expected %lu, got %lu\n",
  271. ExpectedError, status);
  272. return status;
  273. }
  274. }
  275. else {
  276. if (ExpectedError != NO_ERROR) {
  277. printf(" FAILED. Expected %lu, got NO_ERROR\n",
  278. ExpectedError);
  279. return NO_ERROR;
  280. }
  281. }
  282. printf(" Got %lu as expected\n", status);
  283. return status;
  284. }
  285. DWORD
  286. TestOpenService(
  287. IN SC_HANDLE hScManager,
  288. OUT LPSC_HANDLE hService,
  289. IN LPWSTR ServiceName,
  290. IN DWORD DesiredAccess,
  291. IN DWORD ExpectedError
  292. )
  293. {
  294. DWORD status = NO_ERROR;
  295. printf("OpenService: ServiceName=%ws, DesiredAccess=%08lx\n",
  296. ServiceName, DesiredAccess);
  297. *hService = OpenService(
  298. hScManager,
  299. ServiceName,
  300. DesiredAccess
  301. );
  302. if (*hService == (SC_HANDLE) NULL) {
  303. status = GetLastError();
  304. if (ExpectedError != status) {
  305. printf(" FAILED. Expected %lu, got %lu\n",
  306. ExpectedError, status);
  307. return status;
  308. }
  309. }
  310. else {
  311. if (ExpectedError != NO_ERROR) {
  312. printf(" FAILED. Expected %lu, got NO_ERROR\n",
  313. ExpectedError);
  314. return NO_ERROR;
  315. }
  316. }
  317. printf(" Got %lu as expected\n", status);
  318. return status;
  319. }
  320. DWORD
  321. TestEnumServicesStatus(
  322. IN SC_HANDLE hSCManager,
  323. IN DWORD ExpectedError
  324. )
  325. {
  326. DWORD status = NO_ERROR;
  327. BYTE OutputBuffer[1024];
  328. LPENUM_SERVICE_STATUS EnumBuffer = (LPENUM_SERVICE_STATUS) OutputBuffer;
  329. DWORD BytesNeeded;
  330. DWORD EntriesRead;
  331. DWORD i;
  332. if (! EnumServicesStatus(
  333. hSCManager,
  334. SERVICE_TYPE_ALL,
  335. SERVICE_STATE_ALL,
  336. EnumBuffer,
  337. 1024,
  338. &BytesNeeded,
  339. &EntriesRead,
  340. NULL
  341. )) {
  342. status = GetLastError();
  343. }
  344. if (ExpectedError != status) {
  345. printf(" FAILED. Expected %lu, got %lu\n",
  346. ExpectedError, status);
  347. return status;
  348. }
  349. else {
  350. printf(" Got %lu as expected\n", status);
  351. }
  352. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA)) {
  353. for (i = 0; i < EntriesRead; i++) {
  354. for (i = 0; i < EntriesRead; i++) {
  355. DisplayStatus(
  356. EnumBuffer->lpServiceName,
  357. &(EnumBuffer->ServiceStatus));
  358. EnumBuffer++;
  359. }
  360. }
  361. }
  362. return status;
  363. }
  364. DWORD
  365. TestQueryServiceStatus(
  366. IN SC_HANDLE hService,
  367. IN DWORD ExpectedError
  368. )
  369. {
  370. DWORD status = NO_ERROR;
  371. SERVICE_STATUS ServiceStatus;
  372. printf("QueryService: \n");
  373. if (! QueryServiceStatus(
  374. hService,
  375. &ServiceStatus
  376. )) {
  377. status = GetLastError();
  378. }
  379. if (ExpectedError != status) {
  380. printf(" FAILED. Expected %lu, got %lu\n",
  381. ExpectedError, status);
  382. return status;
  383. }
  384. if (status == NO_ERROR) {
  385. DisplayStatus(NULL, &ServiceStatus);
  386. }
  387. printf(" Got %lu as expected\n", status);
  388. return status;
  389. }
  390. DWORD
  391. TestControlService(
  392. IN SC_HANDLE hService,
  393. IN DWORD ControlCode,
  394. IN DWORD ExpectedError
  395. )
  396. {
  397. DWORD status = NO_ERROR;
  398. SERVICE_STATUS ServiceStatus;
  399. printf("ControlService: Control=%08lx\n", ControlCode);
  400. if (! ControlService(
  401. hService,
  402. ControlCode,
  403. &ServiceStatus
  404. )) {
  405. status = GetLastError();
  406. }
  407. if (ExpectedError != status) {
  408. printf(" FAILED. Expected %lu, got %lu\n",
  409. ExpectedError, status);
  410. return status;
  411. }
  412. if (status == NO_ERROR) {
  413. DisplayStatus(NULL, &ServiceStatus);
  414. }
  415. printf(" Got %lu as expected\n", status);
  416. return status;
  417. }
  418. DWORD
  419. TestStartService(
  420. IN SC_HANDLE hService,
  421. IN DWORD ExpectedError
  422. )
  423. {
  424. DWORD status = NO_ERROR;
  425. printf("StartService: \n");
  426. if (! StartService(
  427. hService,
  428. 0,
  429. NULL
  430. )) {
  431. status = GetLastError();
  432. }
  433. if (ExpectedError != status) {
  434. printf(" FAILED. Expected %lu, got %lu\n",
  435. ExpectedError, status);
  436. return status;
  437. }
  438. printf(" Got %lu as expected\n", status);
  439. return status;
  440. }
  441. VOID
  442. DisplayStatus(
  443. IN LPWSTR ServiceName OPTIONAL,
  444. IN LPSERVICE_STATUS ServiceStatus
  445. )
  446. /*++
  447. Routine Description:
  448. Displays the service name and the service status.
  449. |
  450. |SERVICE_NAME: messenger
  451. | TYPE : WIN32
  452. | STATE : ACTIVE SERVICE_STOPPABLE SERVICE_PAUSABLE
  453. | EXIT_CODE : 0xC002001
  454. | CHECKPOINT : 0x00000001
  455. | WAIT_HINT : 0x00003f21
  456. |
  457. Arguments:
  458. ServiceName - This is a pointer to a string containing the name of
  459. the service.
  460. ServiceStatus - This is a pointer to a SERVICE_STATUS structure from
  461. which information is to be displayed.
  462. Return Value:
  463. none.
  464. --*/
  465. {
  466. if (ARGUMENT_PRESENT(ServiceName)) {
  467. printf("\nSERVICE_NAME: %ws\n", ServiceName);
  468. }
  469. printf(" TYPE : %lx ", ServiceStatus->dwServiceType);
  470. switch(ServiceStatus->dwServiceType){
  471. case SERVICE_WIN32:
  472. printf("WIN32 \n");
  473. break;
  474. case SERVICE_DRIVER:
  475. printf("DRIVER \n");
  476. break;
  477. default:
  478. printf(" ERROR \n");
  479. }
  480. printf(" STATE : %lx ", ServiceStatus->dwCurrentState);
  481. switch(ServiceStatus->dwCurrentState){
  482. case SERVICE_STOPPED:
  483. printf("STOPPED ");
  484. break;
  485. case SERVICE_START_PENDING:
  486. printf("START_PENDING ");
  487. break;
  488. case SERVICE_STOP_PENDING:
  489. printf("STOP_PENDING ");
  490. break;
  491. case SERVICE_RUNNING:
  492. printf("RUNNING ");
  493. break;
  494. case SERVICE_CONTINUE_PENDING:
  495. printf("CONTINUE_PENDING ");
  496. break;
  497. case SERVICE_PAUSE_PENDING:
  498. printf("PAUSE_PENDING ");
  499. break;
  500. case SERVICE_PAUSED:
  501. printf("PAUSED ");
  502. break;
  503. default:
  504. printf(" ERROR ");
  505. }
  506. //
  507. // Print Controls Accepted Information
  508. //
  509. if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_STOP) {
  510. printf(" (STOPPABLE,");
  511. }
  512. else {
  513. printf(" (NOT_STOPPABLE,");
  514. }
  515. if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) {
  516. printf("PAUSABLE )\n");
  517. }
  518. else {
  519. printf("NOT_PAUSABLE )\n");
  520. }
  521. //
  522. // Print Exit Code
  523. //
  524. printf(" WIN32_EXIT_CODE : 0x%lx\n", ServiceStatus->dwWin32ExitCode );
  525. printf(" SERVICE_EXIT_CODE : 0x%lx\n",
  526. ServiceStatus->dwServiceSpecificExitCode );
  527. //
  528. // Print CheckPoint & WaitHint Information
  529. //
  530. printf(" CHECKPOINT : 0x%lx\n", ServiceStatus->dwCheckPoint);
  531. printf(" WAIT_HINT : 0x%lx\n", ServiceStatus->dwWaitHint );
  532. return;
  533. }