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.

5250 lines
131 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. scwrap.c
  5. Abstract:
  6. These are the Service Controller API RPC client wrapper routines.
  7. These are the entry points that are exported by the dll.
  8. ControlService
  9. EnumServicesStatusW
  10. EnumServicesStatusA
  11. EnumServicesStatusExW
  12. EnumServicesStatusExA
  13. EnumServiceGroupW
  14. OpenServiceW
  15. CloseServiceHandle
  16. OpenSCManagerW
  17. QueryServiceStatus
  18. QueryServiceStatusEx
  19. StartServiceW
  20. SetServiceStatus
  21. I_ScSetServiceBitsW
  22. I_ScSetServiceBitsA
  23. I_ScGetCurrentGroupStateW
  24. I_ScSendTSMessage
  25. SetServiceBits
  26. OpenSCManagerA
  27. OpenServiceA
  28. StartServiceA
  29. QueryServiceObjectSecurity
  30. SetServiceObjectSecurity
  31. ScConvertOffsetsW
  32. ScConvertOffsetsA
  33. ScConvertOffsetsExW
  34. ScConvertOffsetsExA
  35. ScConvertOffsets64
  36. ChangeServiceConfigA
  37. ChangeServiceConfigW
  38. ChangeServiceConfig2A
  39. ChangeServiceConfig2W
  40. CreateServiceA
  41. CreateServiceW
  42. DeleteService
  43. EnumDependentServicesA
  44. EnumDependentServicesW
  45. GetServiceDisplayNameA
  46. GetServiceDisplayNameW
  47. GetServiceKeyNameA
  48. GetServiceKeyNameW
  49. LockServiceDatabase
  50. QueryServiceConfigA
  51. QueryServiceConfigW
  52. QueryServiceConfig2A
  53. QueryServiceConfig2W
  54. QueryServiceLockStatusA
  55. QueryServiceLockStatusW
  56. UnlockServiceDatabase
  57. NotifyBootConfigStatus
  58. Author:
  59. Dan Lafferty (danl) 03-Feb-1992
  60. Environment:
  61. User Mode - Win32
  62. Revision History:
  63. 07-May-1998 jschwart
  64. Added QueryServiceStatusEx and EnumServicesStatusEx
  65. 11-Oct-1996 AnirudhS
  66. Added ChangeServiceConfig2 and QueryServiceConfig2.
  67. 14-Feb-1996 AnirudhS
  68. Added EnumServiceGroupW.
  69. 22-Sep-1995 AnirudhS
  70. ScWaitForStart: Fixed race condition - OpenEvent needs to be tried
  71. a second time after CreateEvent.
  72. 15-Aug-1995 AnirudhS
  73. Added I_ScGetCurrentGroupStateW.
  74. 05-Nov-1992 Danl
  75. Added display name changes (CreateService, ChangeServiceConfig) and
  76. new api (GetServiceDisplayName, GetServiceKeyName).
  77. 13-Oct-1992 Danl
  78. Allow 0 length buffers to be passed into EnumServicesStatus and
  79. EnumDependentServices.
  80. 04-Aug-1992 Danl
  81. Allow 0 length buffers to be passed into QueryServiceConfig and
  82. QueryServiceLockStatus.
  83. 28-May-1992 JohnRo
  84. RAID 9829: winsvc.h and related file cleanup.
  85. 14-Apr-1992 JohnRo
  86. Enable Lock and Unlock APIs.
  87. 03-Feb-1992 Danl
  88. Created
  89. --*/
  90. //
  91. // INCLUDES
  92. //
  93. extern "C"
  94. {
  95. #include <nt.h> // DbgPrint prototype
  96. #include <ntrtl.h> // DbgPrint prototype
  97. #include <nturtl.h> // needed when we include windows.h
  98. }
  99. #include <rpc.h> // DataTypes and runtime APIs
  100. #include <windows.h> // NO_ERROR
  101. #include <svcctl.h> // generated by the MIDL compiler
  102. #include <lmcons.h> // for lmserver.h
  103. #include <srvann.h> // MS-internal functions
  104. #include <winsvcp.h> // MS-internal functions
  105. #include <rpcasync.h> // I_RpcExceptionFilter
  106. #include <string.h> // needed by strarray.h
  107. #include <scdebug.h> // SCC_LOG
  108. #include <sccrypt.h> // ScEncryptPassword
  109. #include <sclib.h> // ScConvertToUnicode
  110. #include <strarray.h> // ScWStrArraySize
  111. #include <lmerr.h> // for lmserver.h
  112. #include <lmserver.h> // SV_TYPE_WORKSTATION ...
  113. #include <scseclib.h> // ScCreateStartEventSD
  114. #include <scwow.h> // 32/64-bit interop structures
  115. //
  116. // DEFINES
  117. //
  118. #define SC_START_TIMEOUT 180000 // 3 minute timeout
  119. #define RESERVED_BITS (SV_TYPE_WORKSTATION | \
  120. SV_TYPE_SERVER | \
  121. SV_TYPE_DOMAIN_CTRL | \
  122. SV_TYPE_DOMAIN_BAKCTRL | \
  123. SV_TYPE_TIME_SOURCE | \
  124. SV_TYPE_AFP | \
  125. SV_TYPE_DOMAIN_MEMBER | \
  126. SV_TYPE_PRINTQ_SERVER | \
  127. SV_TYPE_DIALIN_SERVER | \
  128. SV_TYPE_XENIX_SERVER | \
  129. SV_TYPE_SERVER_UNIX | \
  130. SV_TYPE_NT | \
  131. SV_TYPE_WFW | \
  132. SV_TYPE_POTENTIAL_BROWSER | \
  133. SV_TYPE_BACKUP_BROWSER | \
  134. SV_TYPE_MASTER_BROWSER | \
  135. SV_TYPE_DOMAIN_MASTER | \
  136. SV_TYPE_LOCAL_LIST_ONLY | \
  137. SV_TYPE_DOMAIN_ENUM)
  138. //
  139. // LOCAL FUNCTIONS
  140. //
  141. VOID
  142. ScConvertOffsetsW(
  143. LPENUM_SERVICE_STATUSW lpServices,
  144. DWORD NumStructs
  145. );
  146. VOID
  147. ScConvertOffsetsA(
  148. LPENUM_SERVICE_STATUSA lpServices,
  149. DWORD NumStructs
  150. );
  151. VOID
  152. ScConvertOffsetsExW(
  153. LPENUM_SERVICE_STATUS_PROCESSW lpServices,
  154. DWORD NumStructs
  155. );
  156. VOID
  157. ScConvertOffsetsExA(
  158. LPENUM_SERVICE_STATUS_PROCESSA lpServices,
  159. DWORD NumStructs
  160. );
  161. #ifdef _WIN64
  162. //
  163. // API numbers for ScConvertOffsets64
  164. //
  165. typedef enum
  166. {
  167. SC_API_ENUM_W = 0,
  168. SC_API_ENUM_A,
  169. SC_API_ENUM_GROUP,
  170. SC_API_ENUM_DEPEND_W,
  171. SC_API_ENUM_DEPEND_A,
  172. SC_API_ENUM_PROCESS_W,
  173. SC_API_ENUM_PROCESS_A,
  174. SC_API_QUERY_DESCRIPTION_W,
  175. SC_API_QUERY_DESCRIPTION_A,
  176. SC_API_QUERY_FAILURE_ACTIONS_W,
  177. SC_API_QUERY_FAILURE_ACTIONS_A,
  178. SC_API_MAX
  179. }
  180. SC_API_NUMBER;
  181. BOOL
  182. ScConvertOffsets64(
  183. SC_API_NUMBER scApi,
  184. SC_HANDLE hSCManager,
  185. DWORD dwServiceType,
  186. DWORD dwServiceState,
  187. LPBYTE lpServices,
  188. DWORD cbBufSize,
  189. LPDWORD pcbBytesNeeded,
  190. LPDWORD lpServicesReturned,
  191. LPDWORD lpResumeIndex,
  192. LPVOID pszGroupName,
  193. LPDWORD lpdwError
  194. );
  195. #endif // _WIN64
  196. DWORD
  197. ScMapRpcError(
  198. IN DWORD RpcError,
  199. IN DWORD BadContextError
  200. );
  201. DWORD
  202. ScWaitForStart(
  203. VOID
  204. );
  205. //
  206. // Globals
  207. //
  208. extern "C"
  209. {
  210. void
  211. SccInit(
  212. DWORD dwReason
  213. )
  214. {
  215. return;
  216. }
  217. }
  218. BOOL
  219. WINAPI
  220. ControlService(
  221. IN SC_HANDLE hService,
  222. IN DWORD dwControl,
  223. OUT LPSERVICE_STATUS lpServiceStatus
  224. )
  225. /*++
  226. Routine Description:
  227. This is the DLL entrypoint for Control Service
  228. Arguments:
  229. Return Value:
  230. --*/
  231. {
  232. DWORD status;
  233. RpcTryExcept {
  234. status = RControlService (
  235. (SC_RPC_HANDLE)hService,
  236. dwControl,
  237. lpServiceStatus);
  238. }
  239. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  240. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  241. }
  242. RpcEndExcept
  243. if (status != NO_ERROR){
  244. SetLastError(status);
  245. return(FALSE);
  246. }
  247. return(TRUE);
  248. }
  249. BOOL
  250. WINAPI
  251. EnumServicesStatusW(
  252. IN SC_HANDLE hSCManager,
  253. IN DWORD dwServiceType,
  254. IN DWORD dwServiceState,
  255. OUT LPENUM_SERVICE_STATUSW lpServices,
  256. IN DWORD cbBufSize,
  257. OUT LPDWORD pcbBytesNeeded,
  258. OUT LPDWORD lpServicesReturned,
  259. IN OUT LPDWORD lpResumeIndex
  260. )
  261. /*++
  262. Routine Description:
  263. This is the DLL entrypoint for EnumServicesStatusW
  264. Arguments:
  265. Return Value:
  266. Note:
  267. --*/
  268. {
  269. return EnumServiceGroupW(
  270. hSCManager,
  271. dwServiceType,
  272. dwServiceState,
  273. lpServices,
  274. cbBufSize,
  275. pcbBytesNeeded,
  276. lpServicesReturned,
  277. lpResumeIndex,
  278. NULL);
  279. }
  280. BOOL
  281. WINAPI
  282. EnumServicesStatusExW(
  283. IN SC_HANDLE hSCManager,
  284. IN SC_ENUM_TYPE InfoLevel,
  285. IN DWORD dwServiceType,
  286. IN DWORD dwServiceState,
  287. OUT LPBYTE lpServices,
  288. IN DWORD cbBufSize,
  289. OUT LPDWORD pcbBytesNeeded,
  290. OUT LPDWORD lpServicesReturned,
  291. IN OUT LPDWORD lpResumeIndex,
  292. IN LPCWSTR pszGroupName
  293. )
  294. /*++
  295. Routine Description:
  296. This is the DLL entrypoint for EnumServicesStatusExW
  297. Arguments:
  298. Return Value:
  299. Note:
  300. --*/
  301. {
  302. DWORD status;
  303. LPENUM_SERVICE_STATUS_PROCESSW pEnumBuf;
  304. ENUM_SERVICE_STATUS_PROCESSW enumBuf;
  305. DWORD tempBufSize;
  306. #ifdef _WIN64
  307. DWORD dwOldResumeIndex = 0;
  308. if (lpResumeIndex != NULL)
  309. {
  310. dwOldResumeIndex = *lpResumeIndex;
  311. }
  312. #endif // _WIN64
  313. //
  314. // Make sure we were passed a valid InfoLevel
  315. //
  316. if (InfoLevel != SC_ENUM_PROCESS_INFO)
  317. {
  318. SetLastError(ERROR_INVALID_LEVEL);
  319. return FALSE;
  320. }
  321. tempBufSize = cbBufSize;
  322. //
  323. // Create a dummy buffer that is at least the size of the structure.
  324. // This way RPC should at least send the request to the server side.
  325. // The server should recognize that the buffer is to small for any
  326. // strings, and put the correct size in the BytesNeeded parameter,
  327. // and fail the call.
  328. //
  329. if (cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW) || (lpServices == NULL)) {
  330. pEnumBuf = &enumBuf;
  331. tempBufSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW);
  332. }
  333. else {
  334. pEnumBuf = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
  335. }
  336. RpcTryExcept {
  337. status = REnumServicesStatusExW (
  338. hSCManager,
  339. InfoLevel,
  340. dwServiceType,
  341. dwServiceState,
  342. (LPBYTE)pEnumBuf,
  343. tempBufSize,
  344. pcbBytesNeeded,
  345. lpServicesReturned,
  346. lpResumeIndex,
  347. pszGroupName);
  348. }
  349. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  350. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  351. }
  352. RpcEndExcept
  353. //
  354. // If data is returned, convert Offsets in the Enum buffer to pointers.
  355. //
  356. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA))
  357. {
  358. if ((*lpServicesReturned) > 0)
  359. {
  360. #ifdef _WIN64
  361. DWORD dwError;
  362. if (!ScConvertOffsets64(SC_API_ENUM_PROCESS_W,
  363. hSCManager,
  364. dwServiceType,
  365. dwServiceState,
  366. (LPBYTE) lpServices,
  367. cbBufSize,
  368. pcbBytesNeeded,
  369. lpServicesReturned,
  370. &dwOldResumeIndex,
  371. (LPVOID) pszGroupName,
  372. &dwError))
  373. {
  374. status = dwError;
  375. if (lpResumeIndex != NULL)
  376. {
  377. *lpResumeIndex = dwOldResumeIndex;
  378. }
  379. }
  380. #else // ndef _WIN64
  381. ScConvertOffsetsExW((LPENUM_SERVICE_STATUS_PROCESSW) lpServices,
  382. *lpServicesReturned);
  383. #endif // _WIN64
  384. }
  385. #ifdef _WIN64
  386. //
  387. // The byte count returned is the size needed to hold all of
  388. // the 32-bit structures rather than the 64-bit ones. Assume
  389. // a buffer full of fixed-length structures (i.e., no variable-
  390. // length data) and scale from 32- to 64-bit sizes to get the
  391. // minimum guaranteed size for all the 64-bit structures.
  392. //
  393. *pcbBytesNeeded = *pcbBytesNeeded
  394. * sizeof(ENUM_SERVICE_STATUS_PROCESSW)
  395. / sizeof(ENUM_SERVICE_STATUS_PROCESS_WOW64);
  396. #endif // _WIN64
  397. }
  398. if (status != NO_ERROR)
  399. {
  400. SetLastError(status);
  401. return FALSE;
  402. }
  403. return TRUE;
  404. }
  405. BOOL
  406. WINAPI
  407. EnumServiceGroupW(
  408. IN SC_HANDLE hSCManager,
  409. IN DWORD dwServiceType,
  410. IN DWORD dwServiceState,
  411. OUT LPENUM_SERVICE_STATUSW lpServices,
  412. IN DWORD cbBufSize,
  413. OUT LPDWORD pcbBytesNeeded,
  414. OUT LPDWORD lpServicesReturned,
  415. IN OUT LPDWORD lpResumeIndex,
  416. IN LPCWSTR pszGroupName
  417. )
  418. /*++
  419. Routine Description:
  420. This is the DLL entrypoint for EnumServiceGroupW
  421. Arguments:
  422. Return Value:
  423. Note:
  424. --*/
  425. {
  426. DWORD status;
  427. LPENUM_SERVICE_STATUSW pEnumBuf;
  428. ENUM_SERVICE_STATUSW enumBuf;
  429. DWORD tempBufSize;
  430. #ifdef _WIN64
  431. DWORD dwOldResumeIndex = 0;
  432. if (lpResumeIndex != NULL)
  433. {
  434. dwOldResumeIndex = *lpResumeIndex;
  435. }
  436. #endif // _WIN64
  437. tempBufSize = cbBufSize;
  438. //
  439. // Create a dummy buffer that is at least the size of the structure.
  440. // This way RPC should at least send the request to the server side.
  441. // The server should recognize that the buffer is to small for any
  442. // strings, and put the correct size in the BytesNeeded parameter,
  443. // and fail the call.
  444. //
  445. if (cbBufSize < sizeof(ENUM_SERVICE_STATUSW) || (lpServices == NULL)) {
  446. pEnumBuf = &enumBuf;
  447. tempBufSize = sizeof(ENUM_SERVICE_STATUSW);
  448. }
  449. else {
  450. pEnumBuf = lpServices;
  451. }
  452. RpcTryExcept {
  453. if (pszGroupName == NULL) {
  454. //
  455. // Call the downlevel API, so that the call will work on targeted
  456. // machines running Windows NT 3.51 or earlier
  457. //
  458. status = REnumServicesStatusW (
  459. (SC_RPC_HANDLE)hSCManager,
  460. dwServiceType,
  461. dwServiceState,
  462. (LPBYTE)pEnumBuf,
  463. tempBufSize,
  464. pcbBytesNeeded,
  465. lpServicesReturned,
  466. lpResumeIndex);
  467. }
  468. else {
  469. status = REnumServiceGroupW (
  470. (SC_RPC_HANDLE)hSCManager,
  471. dwServiceType,
  472. dwServiceState,
  473. (LPBYTE)pEnumBuf,
  474. tempBufSize,
  475. pcbBytesNeeded,
  476. lpServicesReturned,
  477. lpResumeIndex,
  478. pszGroupName);
  479. }
  480. }
  481. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  482. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  483. }
  484. RpcEndExcept
  485. //
  486. // If data is returned, convert Offsets in the Enum buffer to pointers.
  487. //
  488. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA))
  489. {
  490. if ((*lpServicesReturned) > 0)
  491. {
  492. #ifdef _WIN64
  493. DWORD dwError;
  494. if (!ScConvertOffsets64(pszGroupName ? SC_API_ENUM_GROUP :
  495. SC_API_ENUM_W,
  496. hSCManager,
  497. dwServiceType,
  498. dwServiceState,
  499. (LPBYTE) lpServices,
  500. cbBufSize,
  501. pcbBytesNeeded,
  502. lpServicesReturned,
  503. &dwOldResumeIndex,
  504. (LPVOID) pszGroupName,
  505. &dwError))
  506. {
  507. status = dwError;
  508. if (lpResumeIndex != NULL)
  509. {
  510. *lpResumeIndex = dwOldResumeIndex;
  511. }
  512. }
  513. #else // ndef _WIN64
  514. ScConvertOffsetsW(lpServices, *lpServicesReturned);
  515. #endif // _WIN64
  516. }
  517. #ifdef _WIN64
  518. //
  519. // The byte count returned is the size needed to hold all of
  520. // the 32-bit structures rather than the 64-bit ones. Assume
  521. // a buffer full of fixed-length structures (i.e., no variable-
  522. // length data) and scale from 32- to 64-bit sizes to get the
  523. // minimum guaranteed size for all the 64-bit structures.
  524. //
  525. *pcbBytesNeeded = *pcbBytesNeeded
  526. * sizeof(ENUM_SERVICE_STATUSW)
  527. / sizeof(ENUM_SERVICE_STATUS_WOW64);
  528. #endif // _WIN64
  529. }
  530. if (status != NO_ERROR)
  531. {
  532. SetLastError(status);
  533. return(FALSE);
  534. }
  535. return(TRUE);
  536. }
  537. SC_HANDLE
  538. WINAPI
  539. OpenServiceW(
  540. IN SC_HANDLE hSCManager,
  541. IN LPCWSTR lpServiceName,
  542. IN DWORD dwDesiredAccess
  543. )
  544. /*++
  545. Routine Description:
  546. Arguments:
  547. Return Value:
  548. --*/
  549. {
  550. DWORD status;
  551. SC_RPC_HANDLE hService=NULL;
  552. RpcTryExcept {
  553. status = ROpenServiceW (
  554. (SC_RPC_HANDLE)hSCManager,
  555. (LPWSTR) lpServiceName,
  556. dwDesiredAccess,
  557. &hService);
  558. }
  559. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  560. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  561. }
  562. RpcEndExcept
  563. if (status != NO_ERROR){
  564. SetLastError(status);
  565. return(NULL);
  566. }
  567. return (SC_HANDLE)hService;
  568. }
  569. BOOL
  570. WINAPI
  571. CloseServiceHandle(
  572. IN SC_HANDLE hSCObject
  573. )
  574. /*++
  575. Routine Description:
  576. Arguments:
  577. Return Value:
  578. --*/
  579. {
  580. DWORD status;
  581. RpcTryExcept {
  582. status = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject);
  583. }
  584. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  585. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  586. }
  587. RpcEndExcept
  588. if (status != NO_ERROR){
  589. SetLastError(status);
  590. return(FALSE);
  591. }
  592. return(TRUE);
  593. }
  594. SC_HANDLE
  595. WINAPI
  596. OpenSCManagerW(
  597. IN LPCWSTR lpMachineName,
  598. IN LPCWSTR lpDatabaseName OPTIONAL,
  599. IN DWORD dwDesiredAccess
  600. )
  601. /*++
  602. Routine Description:
  603. Arguments:
  604. Return Value:
  605. --*/
  606. {
  607. DWORD status;
  608. SC_RPC_HANDLE ScHandle=NULL;
  609. //
  610. // Check to see if the local Service Controller is started yet.
  611. // If not, then wait for it to start (or timeout).
  612. //
  613. status = ScWaitForStart();
  614. if (status != NO_ERROR) {
  615. SetLastError(status);
  616. return(NULL);
  617. }
  618. RpcTryExcept {
  619. status = ROpenSCManagerW (
  620. (LPWSTR) lpMachineName,
  621. (LPWSTR) lpDatabaseName,
  622. dwDesiredAccess,
  623. &ScHandle);
  624. }
  625. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  626. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  627. }
  628. RpcEndExcept
  629. if (status != NO_ERROR){
  630. SetLastError(status);
  631. return(NULL);
  632. }
  633. return (SC_HANDLE)ScHandle;
  634. }
  635. BOOL
  636. WINAPI
  637. QueryServiceStatus(
  638. IN SC_HANDLE hService,
  639. OUT LPSERVICE_STATUS lpServiceStatus
  640. )
  641. /*++
  642. Routine Description:
  643. This is the DLL entrypoint for QueryServiceStatus.
  644. Arguments:
  645. Return Value:
  646. --*/
  647. {
  648. DWORD status;
  649. RpcTryExcept {
  650. status = RQueryServiceStatus (
  651. (SC_RPC_HANDLE)hService,
  652. lpServiceStatus);
  653. }
  654. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  655. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  656. }
  657. RpcEndExcept
  658. if (status != NO_ERROR){
  659. SetLastError(status);
  660. return(FALSE);
  661. }
  662. return(TRUE);
  663. }
  664. BOOL
  665. WINAPI
  666. QueryServiceStatusEx(
  667. IN SC_HANDLE hService,
  668. IN SC_STATUS_TYPE InfoLevel,
  669. OUT LPBYTE lpBuffer,
  670. IN DWORD cbBufSize,
  671. OUT LPDWORD pcbBytesNeeded
  672. )
  673. /*++
  674. Routine Description:
  675. This is the DLL entrypoint for QueryServiceStatusEx.
  676. Arguments:
  677. Return Value:
  678. Note:
  679. --*/
  680. {
  681. DWORD status;
  682. switch (InfoLevel) {
  683. case SC_STATUS_PROCESS_INFO:
  684. if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS)) {
  685. //
  686. // The buffer is too small -- since the structure is a fixed
  687. // size, we can handle this error on the client side
  688. //
  689. *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
  690. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  691. return FALSE;
  692. }
  693. break;
  694. default:
  695. SetLastError(ERROR_INVALID_LEVEL);
  696. return FALSE;
  697. }
  698. RpcTryExcept {
  699. status = RQueryServiceStatusEx (
  700. (SC_RPC_HANDLE)hService,
  701. InfoLevel,
  702. lpBuffer,
  703. cbBufSize,
  704. pcbBytesNeeded);
  705. }
  706. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  707. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  708. }
  709. RpcEndExcept
  710. if (status != NO_ERROR) {
  711. SetLastError(status);
  712. return FALSE;
  713. }
  714. return TRUE;
  715. }
  716. BOOL
  717. WINAPI
  718. StartServiceW(
  719. IN SC_HANDLE hService,
  720. IN DWORD dwNumServiceArgs,
  721. IN LPCWSTR *lpServiceArgVectors
  722. )
  723. /*++
  724. Routine Description:
  725. This is the DLL entrypoint for StartServiceW
  726. Arguments:
  727. servername - Points to a string containing the name of the computer
  728. that is to execute the API function.
  729. service- Points to a string containing the name of the service
  730. that is to be started.
  731. argc - Indicates the number or argument vectors in argv.
  732. argv - A pointer to an array of pointers to strings. These
  733. are command line arguments that are to be passed to the service.
  734. bufptr - This is the address where a pointer to the service's
  735. information buffer (SERVICE_INFO_2) is to be placed.
  736. Return Value:
  737. --*/
  738. {
  739. DWORD status;
  740. RpcTryExcept {
  741. status = RStartServiceW (
  742. (SC_RPC_HANDLE)hService,
  743. dwNumServiceArgs,
  744. (LPSTRING_PTRSW)lpServiceArgVectors);
  745. }
  746. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  747. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  748. }
  749. RpcEndExcept
  750. if (status != NO_ERROR){
  751. SetLastError(status);
  752. return(FALSE);
  753. }
  754. return(TRUE);
  755. }
  756. BOOL
  757. WINAPI
  758. SetServiceStatus(
  759. IN SERVICE_STATUS_HANDLE hServiceStatus,
  760. IN LPSERVICE_STATUS lpServiceStatus
  761. )
  762. /*++
  763. Routine Description:
  764. This is the DLL entrypoint for SetServiceStatus. It is called from
  765. a service when that service changes its state or receives a control.
  766. The status is maintained by the service controller.
  767. Arguments:
  768. hServiceStatus - This is a handle that was obtained from calling
  769. the RegisterControlHandler function.
  770. lpServiceStatus - This is a pointer to a service status structure.
  771. Return Value:
  772. --*/
  773. {
  774. DWORD status;
  775. //
  776. // Do the RPC call with an exception handler since RPC will raise an
  777. // exception if anything fails. It is up to us to figure out what
  778. // to do once the exception is raised.
  779. //
  780. RpcTryExcept {
  781. status = RSetServiceStatus (
  782. (SC_HANDLE)hServiceStatus,
  783. lpServiceStatus);
  784. }
  785. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  786. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  787. }
  788. RpcEndExcept
  789. if (status != NO_ERROR){
  790. SetLastError(status);
  791. return(FALSE);
  792. }
  793. if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED) {
  794. //
  795. // Service is stopping -- close the handle we opened
  796. // in StartServiceCtrlDispatcher when the service started
  797. //
  798. CloseServiceHandle((SC_HANDLE)hServiceStatus);
  799. }
  800. return(TRUE);
  801. }
  802. BOOL
  803. I_ScSetServiceBitsA(
  804. IN SERVICE_STATUS_HANDLE hServiceStatus,
  805. IN DWORD dwServiceBits,
  806. IN BOOL bSetBitsOn,
  807. IN BOOL bUpdateImmediately,
  808. IN LPSTR pszTransportName
  809. )
  810. /*++
  811. Routine Description:
  812. This is an internal routine that sets the Server Announcement bits
  813. in the service controller.
  814. Arguments:
  815. hServiceStatus -
  816. dwServiceBits -
  817. Return Value:
  818. Note:
  819. --*/
  820. {
  821. DWORD status;
  822. DWORD setBitsOnFlag=0;
  823. DWORD updateImmediatelyFlag=0;
  824. if(bSetBitsOn) {
  825. setBitsOnFlag = 1;
  826. }
  827. if(bUpdateImmediately) {
  828. updateImmediatelyFlag = 1;
  829. }
  830. //
  831. // Do the RPC call with an exception handler since RPC will raise an
  832. // exception if anything fails. It is up to us to figure out what
  833. // to do once the exception is raised.
  834. //
  835. RpcTryExcept {
  836. status = RI_ScSetServiceBitsA (
  837. (SC_HANDLE)hServiceStatus,
  838. dwServiceBits,
  839. setBitsOnFlag,
  840. updateImmediatelyFlag,
  841. pszTransportName);
  842. }
  843. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  844. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  845. }
  846. RpcEndExcept
  847. if (status != NO_ERROR){
  848. SetLastError(status);
  849. return(FALSE);
  850. }
  851. return(TRUE);
  852. }
  853. BOOL
  854. I_ScSetServiceBitsW(
  855. IN SERVICE_STATUS_HANDLE hServiceStatus,
  856. IN DWORD dwServiceBits,
  857. IN BOOL bSetBitsOn,
  858. IN BOOL bUpdateImmediately,
  859. IN LPWSTR pszTransportName
  860. )
  861. /*++
  862. Routine Description:
  863. This is an internal routine that sets the Server Announcement bits
  864. in the service controller.
  865. Arguments:
  866. hServiceStatus -
  867. dwServiceBits -
  868. Return Value:
  869. Note:
  870. --*/
  871. {
  872. DWORD status;
  873. DWORD setBitsOnFlag=0;
  874. DWORD updateImmediatelyFlag=0;
  875. if(bSetBitsOn) {
  876. setBitsOnFlag = 1;
  877. }
  878. if(bUpdateImmediately) {
  879. updateImmediatelyFlag = 1;
  880. }
  881. //
  882. // Do the RPC call with an exception handler since RPC will raise an
  883. // exception if anything fails. It is up to us to figure out what
  884. // to do once the exception is raised.
  885. //
  886. RpcTryExcept {
  887. status = RI_ScSetServiceBitsW (
  888. (SC_HANDLE)hServiceStatus,
  889. dwServiceBits,
  890. setBitsOnFlag,
  891. updateImmediatelyFlag,
  892. pszTransportName);
  893. }
  894. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  895. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  896. }
  897. RpcEndExcept
  898. if (status != NO_ERROR){
  899. SetLastError(status);
  900. return(FALSE);
  901. }
  902. return(TRUE);
  903. }
  904. DWORD
  905. I_ScGetCurrentGroupStateW(
  906. IN SC_HANDLE hSCManager,
  907. IN LPWSTR pszGroupName,
  908. OUT LPDWORD pdwCurrentState
  909. )
  910. /*++
  911. Routine Description:
  912. This is obsolete but some (MS) apps still statically link to it.
  913. --*/
  914. {
  915. return ERROR_NOT_SUPPORTED;
  916. }
  917. extern "C" {
  918. DWORD
  919. I_ScSendTSMessage(
  920. DWORD OpCode,
  921. DWORD dwEvent,
  922. DWORD cbData,
  923. LPBYTE lpData
  924. )
  925. /*++
  926. Routine Description:
  927. Private entrypoint for Terminal Server to tell the SCM to send
  928. console switch notification to services that are interested.
  929. --*/
  930. {
  931. DWORD status;
  932. SC_HANDLE hSCManager;
  933. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  934. if (hSCManager == NULL)
  935. {
  936. return GetLastError();
  937. }
  938. //
  939. // Do the RPC call with an exception handler since RPC will raise an
  940. // exception if anything fails. It is up to us to figure out what
  941. // to do once the exception is raised.
  942. //
  943. RpcTryExcept
  944. {
  945. status = RI_ScSendTSMessage(hSCManager,
  946. OpCode,
  947. dwEvent,
  948. cbData,
  949. lpData);
  950. }
  951. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  952. {
  953. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  954. }
  955. RpcEndExcept
  956. CloseServiceHandle(hSCManager);
  957. return status;
  958. }
  959. } // extern "C"
  960. BOOL
  961. SetServiceBits(
  962. IN SERVICE_STATUS_HANDLE hServiceStatus,
  963. IN DWORD dwServiceBits,
  964. IN BOOL bSetBitsOn,
  965. IN BOOL bUpdateImmediately
  966. )
  967. /*++
  968. Routine Description:
  969. This is an internal routine that sets the Server Announcement bits
  970. in the service controller.
  971. Arguments:
  972. hServiceStatus -
  973. dwServiceBits -
  974. Return Value:
  975. Note:
  976. --*/
  977. {
  978. if (dwServiceBits & RESERVED_BITS) {
  979. SetLastError(ERROR_INVALID_DATA);
  980. return(FALSE);
  981. }
  982. return(I_ScSetServiceBitsW(
  983. hServiceStatus,
  984. dwServiceBits,
  985. bSetBitsOn,
  986. bUpdateImmediately,
  987. (LPWSTR)NULL));
  988. }
  989. SC_HANDLE
  990. WINAPI
  991. OpenSCManagerA(
  992. IN LPCSTR lpMachineName,
  993. IN LPCSTR lpDatabaseName OPTIONAL,
  994. IN DWORD dwDesiredAccess
  995. )
  996. /*++
  997. Routine Description:
  998. Arguments:
  999. Return Value:
  1000. --*/
  1001. {
  1002. DWORD status;
  1003. SC_RPC_HANDLE ScHandle=NULL;
  1004. //
  1005. // Check to see if the local Service Controller is started yet.
  1006. // If not, then wait for it to start (or timeout).
  1007. //
  1008. status = ScWaitForStart();
  1009. if (status != NO_ERROR) {
  1010. SetLastError(status);
  1011. return(NULL);
  1012. };
  1013. RpcTryExcept {
  1014. status = ROpenSCManagerA (
  1015. (LPSTR) lpMachineName,
  1016. (LPSTR) lpDatabaseName,
  1017. dwDesiredAccess,
  1018. &ScHandle);
  1019. }
  1020. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1021. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1022. }
  1023. RpcEndExcept
  1024. if (status != NO_ERROR){
  1025. SetLastError(status);
  1026. return(NULL);
  1027. }
  1028. return (SC_HANDLE)ScHandle;
  1029. }
  1030. SC_HANDLE
  1031. WINAPI
  1032. OpenServiceA(
  1033. IN SC_HANDLE hSCManager,
  1034. IN LPCSTR lpServiceName,
  1035. IN DWORD dwDesiredAccess
  1036. )
  1037. /*++
  1038. Routine Description:
  1039. Arguments:
  1040. Return Value:
  1041. --*/
  1042. {
  1043. DWORD status;
  1044. SC_RPC_HANDLE hService=NULL;
  1045. RpcTryExcept {
  1046. status = ROpenServiceA (
  1047. (SC_RPC_HANDLE)hSCManager,
  1048. (LPSTR) lpServiceName,
  1049. dwDesiredAccess,
  1050. &hService);
  1051. }
  1052. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1053. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1054. }
  1055. RpcEndExcept
  1056. if (status != NO_ERROR){
  1057. SetLastError(status);
  1058. return(NULL);
  1059. }
  1060. return (SC_HANDLE)hService;
  1061. }
  1062. BOOL
  1063. WINAPI
  1064. StartServiceA(
  1065. IN SC_HANDLE hService,
  1066. IN DWORD dwNumServiceArgs,
  1067. IN LPCSTR *lpServiceArgVectors
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. Arguments:
  1072. servername - Points to a string containing the name of the computer
  1073. that is to execute the API function.
  1074. service- Points to a string containing the name of the service
  1075. that is to be started.
  1076. argc - Indicates the number or argument vectors in argv.
  1077. argv - A pointer to an array of pointers to strings. These
  1078. are command line arguments that are to be passed to the service.
  1079. bufptr - This is the address where a pointer to the service's
  1080. information buffer (SERVICE_INFO_2) is to be placed.
  1081. Return Value:
  1082. --*/
  1083. {
  1084. DWORD status;
  1085. RpcTryExcept {
  1086. status = RStartServiceA (
  1087. (SC_RPC_HANDLE)hService,
  1088. dwNumServiceArgs,
  1089. (LPSTRING_PTRSA)lpServiceArgVectors);
  1090. }
  1091. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1092. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1093. }
  1094. RpcEndExcept
  1095. if (status != NO_ERROR){
  1096. SetLastError(status);
  1097. return(FALSE);
  1098. }
  1099. return(TRUE);
  1100. }
  1101. BOOL
  1102. WINAPI
  1103. EnumServicesStatusA(
  1104. IN SC_HANDLE hSCManager,
  1105. IN DWORD dwServiceType,
  1106. IN DWORD dwServiceState,
  1107. OUT LPENUM_SERVICE_STATUSA lpServices,
  1108. IN DWORD cbBufSize,
  1109. OUT LPDWORD pcbBytesNeeded,
  1110. OUT LPDWORD lpServicesReturned,
  1111. IN OUT LPDWORD lpResumeIndex
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. Arguments:
  1116. Return Value:
  1117. --*/
  1118. {
  1119. DWORD status;
  1120. LPENUM_SERVICE_STATUSA pEnumBuf;
  1121. ENUM_SERVICE_STATUSA enumBuf;
  1122. DWORD tempBufSize;
  1123. #ifdef _WIN64
  1124. DWORD dwOldResumeIndex = 0;
  1125. if (lpResumeIndex != NULL)
  1126. {
  1127. dwOldResumeIndex = *lpResumeIndex;
  1128. }
  1129. #endif // _WIN64
  1130. tempBufSize = cbBufSize;
  1131. //
  1132. // Create a dummy buffer that is at least the size of the structure.
  1133. // This way RPC should at least send the request to the server side.
  1134. // The server should recognize that the buffer is to small for any
  1135. // strings, and put the correct size in the BytesNeeded parameter,
  1136. // and fail the call.
  1137. //
  1138. if (cbBufSize < sizeof(ENUM_SERVICE_STATUSA) || (lpServices == NULL)) {
  1139. pEnumBuf = &enumBuf;
  1140. tempBufSize = sizeof(ENUM_SERVICE_STATUSA);
  1141. }
  1142. else {
  1143. pEnumBuf = lpServices;
  1144. }
  1145. RpcTryExcept {
  1146. status = REnumServicesStatusA (
  1147. (SC_RPC_HANDLE)hSCManager,
  1148. dwServiceType,
  1149. dwServiceState,
  1150. (LPBYTE)pEnumBuf,
  1151. tempBufSize,
  1152. pcbBytesNeeded,
  1153. lpServicesReturned,
  1154. lpResumeIndex);
  1155. }
  1156. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1157. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1158. }
  1159. RpcEndExcept
  1160. //
  1161. // If data is returned, convert Offsets in the Enum buffer to pointers.
  1162. //
  1163. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA))
  1164. {
  1165. if ((*lpServicesReturned) > 0)
  1166. {
  1167. #ifdef _WIN64
  1168. DWORD dwError;
  1169. if (!ScConvertOffsets64(SC_API_ENUM_A,
  1170. hSCManager,
  1171. dwServiceType,
  1172. dwServiceState,
  1173. (LPBYTE) lpServices,
  1174. cbBufSize,
  1175. pcbBytesNeeded,
  1176. lpServicesReturned,
  1177. &dwOldResumeIndex,
  1178. NULL,
  1179. &dwError))
  1180. {
  1181. status = dwError;
  1182. if (lpResumeIndex != NULL)
  1183. {
  1184. *lpResumeIndex = dwOldResumeIndex;
  1185. }
  1186. }
  1187. #else // ndef _WIN64
  1188. ScConvertOffsetsA(lpServices, *lpServicesReturned);
  1189. #endif // _WIN64
  1190. }
  1191. #ifdef _WIN64
  1192. //
  1193. // The byte count returned is the size needed to hold all of
  1194. // the 32-bit structures rather than the 64-bit ones. Assume
  1195. // a buffer full of fixed-length structures (i.e., no variable-
  1196. // length data) and scale from 32- to 64-bit sizes to get the
  1197. // minimum guaranteed size for all the 64-bit structures.
  1198. //
  1199. *pcbBytesNeeded = *pcbBytesNeeded
  1200. * sizeof(ENUM_SERVICE_STATUSA)
  1201. / sizeof(ENUM_SERVICE_STATUS_WOW64);
  1202. #endif // _WIN64
  1203. }
  1204. if (status != NO_ERROR)
  1205. {
  1206. SetLastError(status);
  1207. return(FALSE);
  1208. }
  1209. return(TRUE);
  1210. }
  1211. BOOL
  1212. WINAPI
  1213. EnumServicesStatusExA(
  1214. IN SC_HANDLE hSCManager,
  1215. IN SC_ENUM_TYPE InfoLevel,
  1216. IN DWORD dwServiceType,
  1217. IN DWORD dwServiceState,
  1218. OUT LPBYTE lpServices,
  1219. IN DWORD cbBufSize,
  1220. OUT LPDWORD pcbBytesNeeded,
  1221. OUT LPDWORD lpServicesReturned,
  1222. IN OUT LPDWORD lpResumeIndex,
  1223. IN LPCTSTR pszGroupName
  1224. )
  1225. /*++
  1226. Routine Description:
  1227. Arguments:
  1228. Return Value:
  1229. --*/
  1230. {
  1231. DWORD status;
  1232. LPENUM_SERVICE_STATUS_PROCESSA pEnumBuf;
  1233. ENUM_SERVICE_STATUS_PROCESSA enumBuf;
  1234. DWORD tempBufSize;
  1235. #ifdef _WIN64
  1236. DWORD dwOldResumeIndex = 0;
  1237. if (lpResumeIndex != NULL)
  1238. {
  1239. dwOldResumeIndex = *lpResumeIndex;
  1240. }
  1241. #endif // _WIN64
  1242. //
  1243. // Make sure we were passed a valid InfoLevel
  1244. //
  1245. if (InfoLevel != SC_ENUM_PROCESS_INFO)
  1246. {
  1247. SetLastError(ERROR_INVALID_LEVEL);
  1248. return FALSE;
  1249. }
  1250. tempBufSize = cbBufSize;
  1251. //
  1252. // Create a dummy buffer that is at least the size of the structure.
  1253. // This way RPC should at least send the request to the server side.
  1254. // The server should recognize that the buffer is to small for any
  1255. // strings, and put the correct size in the BytesNeeded parameter,
  1256. // and fail the call.
  1257. //
  1258. if (cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA) || (lpServices == NULL)) {
  1259. pEnumBuf = &enumBuf;
  1260. tempBufSize = sizeof(ENUM_SERVICE_STATUS_PROCESSA);
  1261. }
  1262. else {
  1263. pEnumBuf = (LPENUM_SERVICE_STATUS_PROCESSA) lpServices;
  1264. }
  1265. RpcTryExcept {
  1266. status = REnumServicesStatusExA (
  1267. (SC_RPC_HANDLE)hSCManager,
  1268. InfoLevel,
  1269. dwServiceType,
  1270. dwServiceState,
  1271. (LPBYTE)pEnumBuf,
  1272. tempBufSize,
  1273. pcbBytesNeeded,
  1274. lpServicesReturned,
  1275. lpResumeIndex,
  1276. pszGroupName);
  1277. }
  1278. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1279. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1280. }
  1281. RpcEndExcept
  1282. //
  1283. // If data is returned, convert Offsets in the Enum buffer to pointers.
  1284. //
  1285. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA))
  1286. {
  1287. if ((*lpServicesReturned) > 0)
  1288. {
  1289. #ifdef _WIN64
  1290. DWORD dwError;
  1291. if (!ScConvertOffsets64(SC_API_ENUM_PROCESS_A,
  1292. hSCManager,
  1293. dwServiceType,
  1294. dwServiceState,
  1295. (LPBYTE) lpServices,
  1296. cbBufSize,
  1297. pcbBytesNeeded,
  1298. lpServicesReturned,
  1299. &dwOldResumeIndex,
  1300. (LPVOID) pszGroupName,
  1301. &dwError))
  1302. {
  1303. status = dwError;
  1304. if (lpResumeIndex != NULL)
  1305. {
  1306. *lpResumeIndex = dwOldResumeIndex;
  1307. }
  1308. }
  1309. #else // ndef _WIN64
  1310. ScConvertOffsetsExA((LPENUM_SERVICE_STATUS_PROCESSA) lpServices,
  1311. *lpServicesReturned);
  1312. #endif // _WIN64
  1313. }
  1314. #ifdef _WIN64
  1315. //
  1316. // The byte count returned is the size needed to hold all of
  1317. // the 32-bit structures rather than the 64-bit ones. Assume
  1318. // a buffer full of fixed-length structures (i.e., no variable-
  1319. // length data) and scale from 32- to 64-bit sizes to get the
  1320. // minimum guaranteed size for all the 64-bit structures.
  1321. //
  1322. *pcbBytesNeeded = *pcbBytesNeeded
  1323. * sizeof(ENUM_SERVICE_STATUS_PROCESSA)
  1324. / sizeof(ENUM_SERVICE_STATUS_PROCESS_WOW64);
  1325. #endif // _WIN64
  1326. }
  1327. if (status != NO_ERROR)
  1328. {
  1329. SetLastError(status);
  1330. return FALSE;
  1331. }
  1332. return TRUE;
  1333. }
  1334. BOOL
  1335. WINAPI
  1336. QueryServiceObjectSecurity(
  1337. IN SC_HANDLE hService,
  1338. IN SECURITY_INFORMATION dwSecurityInformation,
  1339. OUT PSECURITY_DESCRIPTOR lpSecurityDescriptor,
  1340. IN DWORD cbBufSize,
  1341. OUT LPDWORD pcbBytesNeeded
  1342. )
  1343. /*++
  1344. Routine Description:
  1345. This is the DLL entrypoint for the QueryServiceObjectSecurity API.
  1346. This function returns to the caller requested security information
  1347. currently assigned to an object.
  1348. Based on the caller's access rights this procedure
  1349. will return a security descriptor containing any or all of the
  1350. object's owner ID, group ID, discretionary ACL or system ACL. To
  1351. read the owner ID, group ID, or the discretionary ACL the caller
  1352. must be granted READ_CONTROL access to the object. To read the
  1353. system ACL the caller must be granted ACCESS_SYSTEM_SECURITY
  1354. access.
  1355. Arguments:
  1356. hService - Supplies a handle to an existing service object.
  1357. dwSecurityInformation - Supplies a value describing which pieces of
  1358. security information are being queried.
  1359. lpSecurityInformation - Supplies the output buffer from the user
  1360. which security descriptor information will be written to on
  1361. return.
  1362. cbBufSize - Supplies the size of lpSecurityInformation buffer.
  1363. pcbBytesNeeded - Returns the number of bytes needed of the
  1364. lpSecurityInformation buffer to get all the requested
  1365. information.
  1366. Return Value:
  1367. NO_ERROR - The operation was successful.
  1368. ERROR_INVALID_HANDLE - The specified handle was invalid.
  1369. ERROR_ACCESS_DENIED - The specified handle was not opened for
  1370. either READ_CONTROL or ACCESS_SYSTEM_SECURITY
  1371. access.
  1372. ERROR_INVALID_PARAMETER - The dwSecurityInformation parameter is
  1373. invalid.
  1374. ERROR_INSUFFICIENT_BUFFER - The specified output buffer is smaller
  1375. than the required size returned in pcbBytesNeeded. None of
  1376. the security descriptor is returned.
  1377. --*/
  1378. {
  1379. DWORD status;
  1380. RpcTryExcept {
  1381. status = RQueryServiceObjectSecurity(
  1382. (SC_RPC_HANDLE) hService,
  1383. (DWORD) dwSecurityInformation,
  1384. (LPBYTE) lpSecurityDescriptor,
  1385. cbBufSize,
  1386. pcbBytesNeeded
  1387. );
  1388. }
  1389. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1390. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1391. }
  1392. RpcEndExcept
  1393. if (status != NO_ERROR){
  1394. SetLastError(status);
  1395. return(FALSE);
  1396. }
  1397. return(TRUE);
  1398. }
  1399. BOOL
  1400. WINAPI
  1401. SetServiceObjectSecurity(
  1402. IN SC_HANDLE hService,
  1403. IN SECURITY_INFORMATION dwSecurityInformation,
  1404. IN PSECURITY_DESCRIPTOR lpSecurityDescriptor
  1405. )
  1406. /*++
  1407. Routine Description:
  1408. This is the DLL entrypoint for the SetServiceObjectSecurity API.
  1409. This function takes a well-formed Security Descriptor provided by the
  1410. caller and assigns specified portions of it to an existing service
  1411. object. Based on the flags set in the SecurityInformation
  1412. parameter and the caller's access rights, this procedure will
  1413. replace any or all of the security information associated with an
  1414. object.
  1415. This is the only function available to users and applications for
  1416. changing security information, including the owner ID, group ID, and
  1417. the discretionary and system ACLs of an object. The caller must
  1418. have WRITE_OWNER access to the object to change the owner or primary
  1419. group of the object. The caller must have WRITE_DAC access to the
  1420. object to change the discretionary ACL. The caller must have
  1421. ACCESS_SYSTEM_SECURITY access to an object to assign a system ACL
  1422. to the object.
  1423. Parameters:
  1424. hService - Supplies a handle to an existing service object.
  1425. dwSecurityInformation - Supplies a value describing which pieces of
  1426. security information are being set.
  1427. lpSecurityInformation - Supplies a pointer to a well-formed security
  1428. descriptor.
  1429. Return Values:
  1430. NO_ERROR - The operation was successful.
  1431. ERROR_INVALID_HANDLE - The specified handle was invalid.
  1432. ERROR_ACCESS_DENIED - The specified handle was not opened for
  1433. either WRITE_OWNER, WRITE_DAC, or ACCESS_SYSTEM_SECURITY
  1434. access.
  1435. ERROR_INVALID_PARAMETER - The lpSecurityDescriptor or dwSecurityInformation
  1436. parameter is invalid.
  1437. ERROR_NOT_ENOUGH_MEMORY - Not enough memory to complete the API call.
  1438. --*/
  1439. {
  1440. DWORD status;
  1441. NTSTATUS ntstatus;
  1442. DWORD UserSdSize = 0;
  1443. PSECURITY_DESCRIPTOR SelfRelativeSd;
  1444. //
  1445. // Find out the length of the user supplied security descriptor
  1446. //
  1447. ntstatus = RtlMakeSelfRelativeSD(
  1448. lpSecurityDescriptor,
  1449. NULL,
  1450. &UserSdSize
  1451. );
  1452. if (ntstatus != STATUS_BUFFER_TOO_SMALL) {
  1453. //
  1454. // lpSecurityDescriptor is invalid
  1455. //
  1456. SetLastError(ERROR_INVALID_PARAMETER);
  1457. return(FALSE);
  1458. }
  1459. SelfRelativeSd = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_ZEROINIT, (UINT) UserSdSize);
  1460. if (SelfRelativeSd == NULL) {
  1461. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1462. return(FALSE);
  1463. }
  1464. //
  1465. // Make a self-relative security descriptor for the RPC call
  1466. //
  1467. ntstatus = RtlMakeSelfRelativeSD(
  1468. lpSecurityDescriptor,
  1469. SelfRelativeSd,
  1470. &UserSdSize
  1471. );
  1472. if (! NT_SUCCESS(ntstatus)) {
  1473. LocalFree(SelfRelativeSd);
  1474. SetLastError(RtlNtStatusToDosError(ntstatus));
  1475. return(FALSE);
  1476. }
  1477. //
  1478. // Call the server
  1479. //
  1480. RpcTryExcept {
  1481. status = RSetServiceObjectSecurity(
  1482. (SC_RPC_HANDLE) hService,
  1483. (DWORD) dwSecurityInformation,
  1484. (LPBYTE) SelfRelativeSd,
  1485. UserSdSize
  1486. );
  1487. }
  1488. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1489. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1490. }
  1491. RpcEndExcept
  1492. (void) LocalFree(SelfRelativeSd);
  1493. if (status != NO_ERROR){
  1494. SetLastError(status);
  1495. return(FALSE);
  1496. }
  1497. return(TRUE);
  1498. }
  1499. VOID
  1500. ScConvertOffsetsW(
  1501. LPENUM_SERVICE_STATUSW lpServices,
  1502. DWORD NumStructs
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. Arguments:
  1507. Return Value:
  1508. --*/
  1509. {
  1510. LPBYTE pBuffer;
  1511. DWORD i;
  1512. pBuffer = (LPBYTE)lpServices;
  1513. for (i=0; i<NumStructs; i++ ) {
  1514. lpServices[i].lpServiceName = (LPWSTR)(pBuffer +
  1515. (DWORD)(ULONG_PTR)(lpServices[i].lpServiceName));
  1516. lpServices[i].lpDisplayName = (LPWSTR)(pBuffer +
  1517. (DWORD)(ULONG_PTR)(lpServices[i].lpDisplayName));
  1518. }
  1519. }
  1520. VOID
  1521. ScConvertOffsetsA(
  1522. LPENUM_SERVICE_STATUSA lpServices,
  1523. DWORD NumStructs
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. Arguments:
  1528. Return Value:
  1529. --*/
  1530. {
  1531. LPBYTE pBuffer;
  1532. DWORD i;
  1533. pBuffer = (LPBYTE)lpServices;
  1534. for (i=0; i<NumStructs; i++ ) {
  1535. lpServices[i].lpServiceName = (LPSTR)(pBuffer +
  1536. (DWORD)(ULONG_PTR)(lpServices[i].lpServiceName));
  1537. lpServices[i].lpDisplayName = (LPSTR)(pBuffer +
  1538. (DWORD)(ULONG_PTR)(lpServices[i].lpDisplayName));
  1539. }
  1540. }
  1541. VOID
  1542. ScConvertOffsetsExW(
  1543. LPENUM_SERVICE_STATUS_PROCESSW lpServices,
  1544. DWORD NumStructs
  1545. )
  1546. /*++
  1547. Routine Description:
  1548. Arguments:
  1549. Return Value:
  1550. --*/
  1551. {
  1552. LPBYTE pBuffer;
  1553. DWORD i;
  1554. pBuffer = (LPBYTE)lpServices;
  1555. for (i=0; i<NumStructs; i++ ) {
  1556. lpServices[i].lpServiceName = (LPWSTR)(pBuffer +
  1557. (DWORD)(ULONG_PTR)(lpServices[i].lpServiceName));
  1558. lpServices[i].lpDisplayName = (LPWSTR)(pBuffer +
  1559. (DWORD)(ULONG_PTR)(lpServices[i].lpDisplayName));
  1560. }
  1561. }
  1562. VOID
  1563. ScConvertOffsetsExA(
  1564. LPENUM_SERVICE_STATUS_PROCESSA lpServices,
  1565. DWORD NumStructs
  1566. )
  1567. /*++
  1568. Routine Description:
  1569. Arguments:
  1570. Return Value:
  1571. --*/
  1572. {
  1573. LPBYTE pBuffer;
  1574. DWORD i;
  1575. pBuffer = (LPBYTE)lpServices;
  1576. for (i=0; i<NumStructs; i++ ) {
  1577. lpServices[i].lpServiceName = (LPSTR)(pBuffer +
  1578. (DWORD)(ULONG_PTR)(lpServices[i].lpServiceName));
  1579. lpServices[i].lpDisplayName = (LPSTR)(pBuffer +
  1580. (DWORD)(ULONG_PTR)(lpServices[i].lpDisplayName));
  1581. }
  1582. }
  1583. #ifdef _WIN64
  1584. BOOL
  1585. ScConvertOffsets64(
  1586. SC_API_NUMBER scApi,
  1587. SC_HANDLE hSCManager,
  1588. DWORD dwServiceType,
  1589. DWORD dwServiceState,
  1590. LPBYTE lpServices,
  1591. DWORD cbBufSize,
  1592. LPDWORD pcbBytesNeeded,
  1593. LPDWORD lpServicesReturned,
  1594. LPDWORD lpResumeIndex,
  1595. LPVOID pszGroupName,
  1596. LPDWORD lpdwError
  1597. )
  1598. /*++
  1599. Routine Description:
  1600. Perform API-specific offset-to-pointer conversions for the
  1601. client side of the SCM APIs on 64-bit clients.
  1602. Arguments:
  1603. Return Value:
  1604. TRUE if the conversion succeeded, FALSE otherwise (with lpdwError
  1605. holding the true error).
  1606. --*/
  1607. {
  1608. switch (scApi)
  1609. {
  1610. case SC_API_ENUM_W:
  1611. case SC_API_ENUM_A:
  1612. case SC_API_ENUM_GROUP:
  1613. case SC_API_ENUM_PROCESS_W:
  1614. case SC_API_ENUM_PROCESS_A:
  1615. case SC_API_ENUM_DEPEND_W:
  1616. case SC_API_ENUM_DEPEND_A:
  1617. {
  1618. //
  1619. // Convert buffer returned by EnumServicesStatusW
  1620. //
  1621. LPBYTE lpIter = lpServices;
  1622. LPBYTE lpConverted;
  1623. DWORD dwCount64;
  1624. DWORD dwTotalVarData = 0;
  1625. DWORD dwSize64 = 0;
  1626. DWORD dwStatusSize;
  1627. DWORD dwStrucSize64;
  1628. DWORD dwStrucSizeWOW;
  1629. if (scApi == SC_API_ENUM_PROCESS_W || scApi == SC_API_ENUM_PROCESS_A)
  1630. {
  1631. dwStrucSize64 = sizeof(ENUM_SERVICE_STATUS_PROCESSW);
  1632. dwStrucSizeWOW = sizeof(ENUM_SERVICE_STATUS_PROCESS_WOW64);
  1633. dwStatusSize = sizeof(SERVICE_STATUS_PROCESS);
  1634. }
  1635. else
  1636. {
  1637. dwStrucSize64 = sizeof(ENUM_SERVICE_STATUSW);
  1638. dwStrucSizeWOW = sizeof(ENUM_SERVICE_STATUS_WOW64);
  1639. dwStatusSize = sizeof(SERVICE_STATUS);
  1640. }
  1641. for (dwCount64 = 0;
  1642. dwCount64 < *lpServicesReturned;
  1643. dwCount64++, lpIter += dwStrucSizeWOW)
  1644. {
  1645. DWORD dwCurrentVarData;
  1646. DWORD dwOffset;
  1647. //
  1648. // Compute size of this record's variable-length data
  1649. //
  1650. dwOffset = ((LPENUM_SERVICE_STATUS_WOW64) lpIter)->dwDisplayNameOffset;
  1651. dwCurrentVarData = cbBufSize - dwOffset - dwTotalVarData;
  1652. //
  1653. // Is there room to expand the current record to 64-bit pointers?
  1654. //
  1655. if (dwSize64 + dwStrucSize64 + dwCurrentVarData > cbBufSize)
  1656. {
  1657. //
  1658. // Nope.
  1659. //
  1660. break;
  1661. }
  1662. //
  1663. // Update the total number of variable-length data bytes
  1664. // in the post-conversion buffer
  1665. //
  1666. dwTotalVarData += dwCurrentVarData;
  1667. dwSize64 += dwStrucSize64 + dwCurrentVarData;
  1668. }
  1669. //
  1670. // Set up the pointer to the last soon-to-be-converted structure.
  1671. // Cast to INT to sign-extend the offset to 64 bits (required
  1672. // when (dwCount64 == 0) or else the sum gets bizarre).
  1673. //
  1674. lpIter = lpServices + (INT) (dwStrucSizeWOW * (dwCount64 - 1));
  1675. lpConverted = lpServices + (INT) (dwStrucSize64 * (dwCount64 - 1));
  1676. for ( ;
  1677. lpIter >= lpServices;
  1678. lpIter -= dwStrucSizeWOW, lpConverted -= dwStrucSize64)
  1679. {
  1680. LPENUM_SERVICE_STATUSW lpEnum = (LPENUM_SERVICE_STATUSW) lpConverted;
  1681. LPENUM_SERVICE_STATUS_WOW64 lpEnumWOW = (LPENUM_SERVICE_STATUS_WOW64) lpIter;
  1682. //
  1683. // Copy fields individually in reverse order in case there's overlap
  1684. //
  1685. RtlMoveMemory(&lpEnum->ServiceStatus,
  1686. &lpEnumWOW->ServiceStatus,
  1687. dwStatusSize);
  1688. //
  1689. // Do the offset-to-pointer conversion. Can do straight addition
  1690. // since we didn't move the variable length data.
  1691. //
  1692. lpEnum->lpDisplayName = (LPWSTR) (lpServices + lpEnumWOW->dwDisplayNameOffset);
  1693. lpEnum->lpServiceName = (LPWSTR) (lpServices + lpEnumWOW->dwServiceNameOffset);
  1694. }
  1695. ASSERT(lpIter < lpServices && lpConverted < lpServices);
  1696. if (*lpServicesReturned != dwCount64)
  1697. {
  1698. //
  1699. // Not enough room to fit all the records returned. Update
  1700. // all the OUT parameters. Add on the size of the overwritten
  1701. // records' variable-length data first.
  1702. //
  1703. *pcbBytesNeeded += (cbBufSize
  1704. - dwTotalVarData
  1705. - *lpServicesReturned * dwStrucSizeWOW);
  1706. //
  1707. // And now do the fixed-length data. Use the 32-bit structures
  1708. // and the caller will multiply it up to 64-bit lengths.
  1709. //
  1710. *pcbBytesNeeded += (*lpServicesReturned - dwCount64)
  1711. * dwStrucSizeWOW;
  1712. //
  1713. // Update the count of services returned
  1714. //
  1715. *lpServicesReturned = dwCount64;
  1716. if (scApi == SC_API_ENUM_DEPEND_W || scApi == SC_API_ENUM_DEPEND_A)
  1717. {
  1718. *lpdwError = ERROR_MORE_DATA;
  1719. return FALSE;
  1720. }
  1721. //
  1722. // And now things get ugly. We need to update the resume index
  1723. // since we removed some services from the buffer. However,
  1724. // there's no easy way to get the resume index of a particular
  1725. // service from the server side. So we have to build up an
  1726. // enum buffer that's just small enough to hold only the records
  1727. // we're going to return and enum again just to get the RI.
  1728. //
  1729. LPBYTE lpTemp;
  1730. DWORD status;
  1731. DWORD dwTempBytes;
  1732. DWORD dwTempCount;
  1733. DWORD dwTempSize = dwCount64 * dwStrucSizeWOW + dwTotalVarData;
  1734. lpTemp = (LPBYTE) LocalAlloc(LMEM_FIXED, dwTempSize);
  1735. if (lpTemp == NULL)
  1736. {
  1737. *lpdwError = ERROR_NOT_ENOUGH_MEMORY;
  1738. return FALSE;
  1739. }
  1740. RpcTryExcept
  1741. {
  1742. switch (scApi)
  1743. {
  1744. case SC_API_ENUM_W:
  1745. status = REnumServicesStatusW (
  1746. (SC_RPC_HANDLE) hSCManager,
  1747. dwServiceType,
  1748. dwServiceState,
  1749. (LPBYTE) lpTemp,
  1750. dwTempSize,
  1751. &dwTempBytes,
  1752. &dwTempCount,
  1753. lpResumeIndex);
  1754. break;
  1755. case SC_API_ENUM_A:
  1756. status = REnumServicesStatusA (
  1757. (SC_RPC_HANDLE) hSCManager,
  1758. dwServiceType,
  1759. dwServiceState,
  1760. (LPBYTE) lpTemp,
  1761. dwTempSize,
  1762. &dwTempBytes,
  1763. &dwTempCount,
  1764. lpResumeIndex);
  1765. break;
  1766. case SC_API_ENUM_GROUP:
  1767. status = REnumServiceGroupW (
  1768. (SC_RPC_HANDLE) hSCManager,
  1769. dwServiceType,
  1770. dwServiceState,
  1771. (LPBYTE) lpTemp,
  1772. dwTempSize,
  1773. &dwTempBytes,
  1774. &dwTempCount,
  1775. lpResumeIndex,
  1776. (LPCWSTR) pszGroupName);
  1777. break;
  1778. case SC_API_ENUM_PROCESS_W:
  1779. status = REnumServicesStatusExW (
  1780. hSCManager,
  1781. SC_ENUM_PROCESS_INFO,
  1782. dwServiceType,
  1783. dwServiceState,
  1784. (LPBYTE) lpTemp,
  1785. dwTempSize,
  1786. &dwTempBytes,
  1787. &dwTempCount,
  1788. lpResumeIndex,
  1789. (LPCWSTR) pszGroupName);
  1790. break;
  1791. case SC_API_ENUM_PROCESS_A:
  1792. status = REnumServicesStatusExA (
  1793. hSCManager,
  1794. SC_ENUM_PROCESS_INFO,
  1795. dwServiceType,
  1796. dwServiceState,
  1797. (LPBYTE) lpTemp,
  1798. dwTempSize,
  1799. &dwTempBytes,
  1800. &dwTempCount,
  1801. lpResumeIndex,
  1802. (LPCSTR) pszGroupName);
  1803. break;
  1804. default:
  1805. ASSERT(FALSE && "Unsupported API in ScConvertOffsets64 enum path");
  1806. status = ERROR_NOT_SUPPORTED;
  1807. }
  1808. }
  1809. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  1810. {
  1811. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  1812. }
  1813. RpcEndExcept
  1814. LocalFree(lpTemp);
  1815. //
  1816. // We had to overwrite at least one structure so we need
  1817. // to return some form of error, even if it's ERROR_MORE_DATA.
  1818. //
  1819. *lpdwError = status;
  1820. return FALSE;
  1821. }
  1822. return TRUE;
  1823. break;
  1824. }
  1825. case SC_API_QUERY_DESCRIPTION_W:
  1826. case SC_API_QUERY_DESCRIPTION_A:
  1827. {
  1828. DWORD dwBytesNeeded = *pcbBytesNeeded;
  1829. DWORD dwSizeDiff = sizeof(SERVICE_DESCRIPTIONW) - sizeof(SERVICE_DESCRIPTION_WOW64);
  1830. LPSERVICE_DESCRIPTION_WOW64 psdWOW = (LPSERVICE_DESCRIPTION_WOW64) lpServices;
  1831. LPSERVICE_DESCRIPTIONW psd = (LPSERVICE_DESCRIPTIONW) lpServices;
  1832. //
  1833. // *pcbBytesNeeded is filled in on success or "buffer too small"
  1834. // failure, so update it with the 64-bit size.
  1835. //
  1836. *pcbBytesNeeded += dwSizeDiff;
  1837. if (*pcbBytesNeeded > cbBufSize)
  1838. {
  1839. return FALSE;
  1840. }
  1841. //
  1842. // We have room -- move the variable-length data
  1843. //
  1844. RtlMoveMemory(psd + 1,
  1845. psdWOW + 1,
  1846. dwBytesNeeded - sizeof(SERVICE_DESCRIPTION_WOW64));
  1847. //
  1848. // Resize the offset from 4 to 8 bytes.
  1849. //
  1850. if (psdWOW->dwDescriptionOffset == 0)
  1851. {
  1852. psd->lpDescription = NULL;
  1853. }
  1854. else
  1855. {
  1856. psd->lpDescription = (LPWSTR) UlongToPtr(psdWOW->dwDescriptionOffset + dwSizeDiff);
  1857. }
  1858. return TRUE;
  1859. }
  1860. case SC_API_QUERY_FAILURE_ACTIONS_W:
  1861. case SC_API_QUERY_FAILURE_ACTIONS_A:
  1862. {
  1863. DWORD dwBytesNeeded = *pcbBytesNeeded;
  1864. DWORD dwSizeDiff = sizeof(SERVICE_FAILURE_ACTIONSW) - sizeof(SERVICE_FAILURE_ACTIONS_WOW64);
  1865. LPSERVICE_FAILURE_ACTIONS_WOW64 psfaWOW = (LPSERVICE_FAILURE_ACTIONS_WOW64) lpServices;
  1866. LPSERVICE_FAILURE_ACTIONSW psfa = (LPSERVICE_FAILURE_ACTIONSW) lpServices;
  1867. //
  1868. // *pcbBytesNeeded is filled in on success or "buffer too small"
  1869. // failure, so update it with the 64-bit size.
  1870. //
  1871. *pcbBytesNeeded += dwSizeDiff;
  1872. if (*pcbBytesNeeded > cbBufSize)
  1873. {
  1874. return FALSE;
  1875. }
  1876. //
  1877. // We have room -- move the variable-length data
  1878. //
  1879. RtlMoveMemory(psfa + 1,
  1880. psfaWOW + 1,
  1881. dwBytesNeeded - sizeof(SERVICE_FAILURE_ACTIONS_WOW64));
  1882. //
  1883. // Resize the offsets from 4 to 8 bytes. Do this in reverse field order
  1884. // to avoid trampling over any still-to-be-converted offsets.
  1885. //
  1886. if (psfaWOW->dwsaActionsOffset == 0)
  1887. {
  1888. psfa->lpsaActions = NULL;
  1889. }
  1890. else
  1891. {
  1892. psfa->lpsaActions = (SC_ACTION *) UlongToPtr(psfaWOW->dwsaActionsOffset + dwSizeDiff);
  1893. }
  1894. psfa->cActions = psfaWOW->cActions;
  1895. if (psfaWOW->dwCommandOffset == 0)
  1896. {
  1897. psfa->lpCommand = NULL;
  1898. }
  1899. else
  1900. {
  1901. psfa->lpCommand = (LPWSTR) UlongToPtr(psfaWOW->dwCommandOffset + dwSizeDiff);
  1902. }
  1903. if (psfaWOW->dwRebootMsgOffset == 0)
  1904. {
  1905. psfa->lpRebootMsg = NULL;
  1906. }
  1907. else
  1908. {
  1909. psfa->lpRebootMsg = (LPWSTR) UlongToPtr(psfaWOW->dwRebootMsgOffset + dwSizeDiff);
  1910. }
  1911. psfa->dwResetPeriod = psfaWOW->dwResetPeriod;
  1912. return TRUE;
  1913. }
  1914. default:
  1915. ASSERT(FALSE && "Unsupported API passed to ScConvertOffsets64");
  1916. *lpdwError = ERROR_NOT_SUPPORTED;
  1917. return FALSE;
  1918. }
  1919. }
  1920. #endif // _WIN64
  1921. BOOL
  1922. WINAPI
  1923. ChangeServiceConfigA(
  1924. IN SC_HANDLE hService,
  1925. IN DWORD dwServiceType,
  1926. IN DWORD dwStartType,
  1927. IN DWORD dwErrorControl,
  1928. IN LPCSTR lpBinaryPathName,
  1929. IN LPCSTR lpLoadOrderGroup,
  1930. OUT LPDWORD lpdwTagId,
  1931. IN LPCSTR lpDependencies,
  1932. IN LPCSTR lpServiceStartName,
  1933. IN LPCSTR lpPassword,
  1934. IN LPCSTR lpDisplayName
  1935. )
  1936. /*++
  1937. Routine Description:
  1938. This is the DLL entry point for the ChangeServiceConfig function.
  1939. ChangeServiceConfig changes the service configuration kept in the
  1940. Service Control Manager database. This configuration information
  1941. was first set in the database via the CreateService API, and can
  1942. be queried (exept for the password parameter) using the
  1943. QueryServiceConfig API.
  1944. Arguments:
  1945. hService - Handle obtained from a previous OpenService call.
  1946. dwServiceType - Value to indicate the type of service this is.
  1947. dwStartType - Value to specify when to start the service.
  1948. dwErrorControl - Value to specify the severity of the error if this
  1949. service fails to start during boot so that the appropriate action
  1950. can be taken.
  1951. lpBinaryPathName - Fully-qualified path name to the service binary file.
  1952. lpLoadOrderGroup - Name of the load ordering group which this service
  1953. is a member of. Groups of services are started based on the group
  1954. order list specified in the registry at
  1955. HKEY_LOCAL_SYSTEM\Control\Service_Group_Order.
  1956. lpdwTagId - On output this pointer receives a unique tag identification
  1957. number within the group. If this parameter is specified (non-NULL)
  1958. but lpLoadOrderGroup is not specified, ERROR_INVALID_PARAMETER
  1959. will be returned.
  1960. lpDependencies - NULL-separated names of services which must be
  1961. running before this service can run. An empty string means that
  1962. this service has no dependencies.
  1963. lpServiceStartName - If service type is SERVICE_WIN32, this name is
  1964. the account name in the form of "DomainName\Username" which the
  1965. service process will be logged on as when it runs. If service
  1966. type is SERVICE_DRIVER, this name must be the NT driver object
  1967. name (e.g. \FileSystem\LanManRedirector or \Driver\Xns) which
  1968. the I/O system uses to load the device driver.
  1969. lpPassword - Password to the account name specified by
  1970. lpServiceStartName if service type is SERVICE_WIN32. This
  1971. password will be changed periodically by the Service Control
  1972. Manager so that it will not expire. If service type is
  1973. SERVICE_DRIVER, this parameter is ignored.
  1974. lpDisplayName - This is the internationalized name that is used for
  1975. display purposes only.
  1976. Return Value:
  1977. Note:
  1978. --*/
  1979. {
  1980. DWORD status;
  1981. LPWSTR lpPasswordW;
  1982. LPBYTE EncryptedPassword = NULL;
  1983. DWORD PasswordSize = 0;
  1984. LPSTR Ptr;
  1985. LPWSTR DependBuffer = NULL;
  1986. DWORD DependSize = 0;
  1987. RpcTryExcept {
  1988. //
  1989. // Create a unicode version of lpPassword, and then encrypt it.
  1990. //
  1991. if (ARGUMENT_PRESENT(lpPassword)) {
  1992. if (! ScConvertToUnicode(&lpPasswordW, lpPassword)) {
  1993. SCC_LOG0(ERROR,"ChangeServiceConfigA: convert password to Unicode failed\n");
  1994. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1995. return(FALSE);
  1996. }
  1997. status = ScEncryptPassword(
  1998. (SC_RPC_HANDLE)hService,
  1999. lpPasswordW,
  2000. &EncryptedPassword,
  2001. &PasswordSize
  2002. );
  2003. (void) LocalFree(lpPasswordW);
  2004. if (status != NO_ERROR) {
  2005. SCC_LOG0(ERROR,"ChangeServiceConfigA: ScEncryptPassword failed\n");
  2006. SetLastError(status);
  2007. return(FALSE);
  2008. }
  2009. }
  2010. if (ARGUMENT_PRESENT(lpDependencies)) {
  2011. DependSize = ScAStrArraySize((LPSTR) lpDependencies) / sizeof(CHAR) * sizeof(WCHAR);
  2012. if ((DependBuffer = (LPWSTR)LocalAlloc(
  2013. LMEM_ZEROINIT,
  2014. (UINT) DependSize)) == NULL) {
  2015. SCC_LOG1(ERROR,
  2016. "ChangeServiceConfigA: LocalAlloc of DependBuffer failed "
  2017. FORMAT_DWORD "\n", GetLastError());
  2018. status = ERROR_NOT_ENOUGH_MEMORY;
  2019. }
  2020. if (DependSize > sizeof(WCHAR)) {
  2021. //
  2022. // There is at least one dependency entry.
  2023. //
  2024. Ptr = (LPSTR) lpDependencies;
  2025. //
  2026. // Convert each dependency into Unicode, and append it to the
  2027. // DependBuffer.
  2028. //
  2029. while (*Ptr != 0) {
  2030. LPWSTR ConvertedDependency = NULL;
  2031. if (! ScConvertToUnicode(&ConvertedDependency, Ptr)) {
  2032. SCC_LOG0(ERROR,
  2033. "ChangeServiceConfigA: convert dependency to Unicode failed\n");
  2034. status = ERROR_NOT_ENOUGH_MEMORY;
  2035. goto CleanExit;
  2036. }
  2037. ScAddWStrToWStrArray(DependBuffer, ConvertedDependency);
  2038. (void) LocalFree(ConvertedDependency);
  2039. Ptr = ScNextAStrArrayEntry(Ptr);
  2040. }
  2041. }
  2042. }
  2043. status = RChangeServiceConfigA(
  2044. (SC_RPC_HANDLE)hService,
  2045. dwServiceType,
  2046. dwStartType,
  2047. dwErrorControl,
  2048. (LPSTR) lpBinaryPathName,
  2049. (LPSTR) lpLoadOrderGroup,
  2050. lpdwTagId,
  2051. (LPBYTE) DependBuffer,
  2052. DependSize,
  2053. (LPSTR) lpServiceStartName,
  2054. EncryptedPassword,
  2055. PasswordSize,
  2056. (LPSTR)lpDisplayName);
  2057. }
  2058. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2059. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2060. }
  2061. RpcEndExcept
  2062. CleanExit:
  2063. if (EncryptedPassword != NULL) {
  2064. (void) LocalFree(EncryptedPassword);
  2065. }
  2066. if (DependBuffer != NULL) {
  2067. (void) LocalFree(DependBuffer);
  2068. }
  2069. if (status != NO_ERROR){
  2070. SetLastError(status);
  2071. return(FALSE);
  2072. }
  2073. return(TRUE);
  2074. }
  2075. BOOL
  2076. WINAPI
  2077. ChangeServiceConfigW(
  2078. IN SC_HANDLE hService,
  2079. IN DWORD dwServiceType,
  2080. IN DWORD dwStartType,
  2081. IN DWORD dwErrorControl,
  2082. IN LPCWSTR lpBinaryPathName,
  2083. IN LPCWSTR lpLoadOrderGroup,
  2084. OUT LPDWORD lpdwTagId,
  2085. IN LPCWSTR lpDependencies,
  2086. IN LPCWSTR lpServiceStartName,
  2087. IN LPCWSTR lpPassword,
  2088. IN LPCWSTR lpDisplayName
  2089. )
  2090. /*++
  2091. Routine Description:
  2092. see ChangeServiceConfigA
  2093. Arguments:
  2094. Return Value:
  2095. Note:
  2096. --*/
  2097. {
  2098. DWORD status;
  2099. LPBYTE EncryptedPassword = NULL;
  2100. DWORD PasswordSize = 0;
  2101. DWORD DependSize = 0;
  2102. RpcTryExcept {
  2103. //
  2104. // Create a unicode version of lpPassword, and then encrypt it.
  2105. //
  2106. if (ARGUMENT_PRESENT(lpPassword)) {
  2107. status = ScEncryptPassword(
  2108. (SC_RPC_HANDLE)hService,
  2109. (LPWSTR) lpPassword,
  2110. &EncryptedPassword,
  2111. &PasswordSize
  2112. );
  2113. if (status != NO_ERROR) {
  2114. SCC_LOG0(ERROR,"ChangeServiceConfigW: ScEncryptPassword failed\n");
  2115. SetLastError(status);
  2116. return(FALSE);
  2117. }
  2118. }
  2119. if (ARGUMENT_PRESENT(lpDependencies)) {
  2120. DependSize = ScWStrArraySize((LPWSTR) lpDependencies);
  2121. }
  2122. status = RChangeServiceConfigW(
  2123. (SC_RPC_HANDLE)hService,
  2124. dwServiceType,
  2125. dwStartType,
  2126. dwErrorControl,
  2127. (LPWSTR) lpBinaryPathName,
  2128. (LPWSTR) lpLoadOrderGroup,
  2129. lpdwTagId,
  2130. (LPBYTE) lpDependencies,
  2131. DependSize,
  2132. (LPWSTR) lpServiceStartName,
  2133. EncryptedPassword,
  2134. PasswordSize,
  2135. (LPWSTR)lpDisplayName);
  2136. }
  2137. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2138. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2139. }
  2140. RpcEndExcept
  2141. if (EncryptedPassword != NULL) {
  2142. (void) LocalFree(EncryptedPassword);
  2143. }
  2144. if (status != NO_ERROR){
  2145. SetLastError(status);
  2146. return(FALSE);
  2147. }
  2148. return(TRUE);
  2149. }
  2150. BOOL
  2151. WINAPI
  2152. ChangeServiceConfig2A(
  2153. IN SC_HANDLE hService,
  2154. IN DWORD dwInfoLevel,
  2155. IN LPVOID lpInfo
  2156. )
  2157. /*++
  2158. Routine Description:
  2159. Arguments:
  2160. Return Value:
  2161. Note:
  2162. --*/
  2163. {
  2164. DWORD status;
  2165. // Transform the parameters into a union that RPC likes
  2166. SC_RPC_CONFIG_INFOA RpcInfo = { dwInfoLevel,
  2167. (LPSERVICE_DESCRIPTIONA) lpInfo };
  2168. RpcTryExcept
  2169. {
  2170. status = RChangeServiceConfig2A(
  2171. (SC_RPC_HANDLE) hService,
  2172. RpcInfo
  2173. );
  2174. }
  2175. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  2176. {
  2177. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2178. }
  2179. RpcEndExcept
  2180. if (status == RPC_S_INVALID_TAG)
  2181. {
  2182. status = ERROR_INVALID_LEVEL;
  2183. }
  2184. if (status != NO_ERROR)
  2185. {
  2186. SetLastError(status);
  2187. return FALSE;
  2188. }
  2189. return TRUE;
  2190. }
  2191. BOOL
  2192. WINAPI
  2193. ChangeServiceConfig2W(
  2194. IN SC_HANDLE hService,
  2195. IN DWORD dwInfoLevel,
  2196. IN LPVOID lpInfo
  2197. )
  2198. /*++
  2199. Routine Description:
  2200. Arguments:
  2201. Return Value:
  2202. Note:
  2203. --*/
  2204. {
  2205. DWORD status;
  2206. // Transform the parameters into a union that RPC likes
  2207. SC_RPC_CONFIG_INFOW RpcInfo = { dwInfoLevel,
  2208. (LPSERVICE_DESCRIPTIONW) lpInfo };
  2209. RpcTryExcept
  2210. {
  2211. status = RChangeServiceConfig2W(
  2212. (SC_RPC_HANDLE) hService,
  2213. RpcInfo
  2214. );
  2215. }
  2216. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  2217. {
  2218. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2219. }
  2220. RpcEndExcept
  2221. if (status == RPC_S_INVALID_TAG)
  2222. {
  2223. status = ERROR_INVALID_LEVEL;
  2224. }
  2225. if (status != NO_ERROR)
  2226. {
  2227. SetLastError(status);
  2228. return FALSE;
  2229. }
  2230. return TRUE;
  2231. }
  2232. SC_HANDLE
  2233. WINAPI
  2234. CreateServiceA(
  2235. IN SC_HANDLE hSCManager,
  2236. IN LPCSTR lpServiceName,
  2237. IN LPCSTR lpDisplayName,
  2238. IN DWORD dwDesiredAccess,
  2239. IN DWORD dwServiceType,
  2240. IN DWORD dwStartType,
  2241. IN DWORD dwErrorControl,
  2242. IN LPCSTR lpBinaryPathName,
  2243. IN LPCSTR lpLoadOrderGroup,
  2244. OUT LPDWORD lpdwTagId,
  2245. IN LPCSTR lpDependencies,
  2246. IN LPCSTR lpServiceStartName,
  2247. IN LPCSTR lpPassword
  2248. )
  2249. /*++
  2250. Routine Description:
  2251. This function is the DLL entry point for the ansi version
  2252. of CreateService. On the server side, this function will create
  2253. a service object and add it to the Service Control Manager database.
  2254. Arguments:
  2255. hSCManager - Handle obtained from a previous OpenSCManager call.
  2256. lpServiceName - Name of the service to install.
  2257. lpDisplayName - This is the internationalized name that is used for
  2258. display purposes only.
  2259. dwDesiredAccess - Access types desired to access the service.
  2260. dwServiceType - Value to indicate the type of service this is.
  2261. dwStartType - Value to specify when to start the service.
  2262. dwErrorControl - Value to specify the severity of the error if this
  2263. service fails to start during boot so that the appropriate action
  2264. can be taken.
  2265. lpBinaryPathName - Fully-qualified path name to the service binary file.
  2266. lpLoadOrderGroup - Name of the load ordering group which this service
  2267. is a member of. Groups of services are started based on the group
  2268. order list specified in the registry at
  2269. HKEY_LOCAL_SYSTEM\Control\Service_Group_Order.
  2270. lpdwTagId - On output this pointer receives a unique tag identification
  2271. number within the group. If this parameter is specified (non-NULL)
  2272. but lpLoadOrderGroup is not specified, ERROR_INVALID_PARAMETER
  2273. will be returned.
  2274. lpDependencies - Space-separated names of services which must be
  2275. running before this service can run. An empty string means that
  2276. this service has no dependencies.
  2277. lpServiceStartName - If service type is SERVICE_WIN32, this name is
  2278. the account name in the form of "DomainName\Username" which the
  2279. service process will be logged on as when it runs. If service
  2280. type is SERVICE_DRIVER, this name must be the NT driver object
  2281. name (e.g. \FileSystem\LanManRedirector or \Driver\Xns) which
  2282. the I/O system uses to load the device driver.
  2283. lpPassword - Password to the account name specified by
  2284. lpServiceStartName if service type is SERVICE_WIN32. This
  2285. password will be changed periodically by the Service Control
  2286. Manager so that it will not expire. If service type is
  2287. SERVICE_DRIVER, this parameter is ignored.
  2288. Return Value:
  2289. Note:
  2290. --*/
  2291. {
  2292. DWORD status;
  2293. SC_RPC_HANDLE hService=NULL;
  2294. LPWSTR lpPasswordW;
  2295. LPBYTE EncryptedPassword = NULL;
  2296. DWORD PasswordSize = 0;
  2297. LPSTR Ptr;
  2298. LPWSTR DependBuffer = NULL;
  2299. DWORD DependSize = 0;
  2300. RpcTryExcept {
  2301. //
  2302. // Create a unicode version of lpPassword, and then encrypt it.
  2303. //
  2304. if (ARGUMENT_PRESENT(lpPassword)) {
  2305. if (! ScConvertToUnicode(&lpPasswordW, lpPassword)) {
  2306. SCC_LOG0(ERROR,"CreateServiceA: convert password to Unicode failed\n");
  2307. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2308. return(NULL);
  2309. }
  2310. status = ScEncryptPassword(
  2311. (SC_RPC_HANDLE)hSCManager,
  2312. lpPasswordW,
  2313. &EncryptedPassword,
  2314. &PasswordSize
  2315. );
  2316. (void) LocalFree(lpPasswordW);
  2317. if (status != NO_ERROR) {
  2318. SCC_LOG0(ERROR,"CreateServiceA: ScEncryptPassword failed\n");
  2319. SetLastError(status);
  2320. return(NULL);
  2321. }
  2322. }
  2323. if (ARGUMENT_PRESENT(lpDependencies)) {
  2324. DependSize = ScAStrArraySize((LPSTR) lpDependencies) / sizeof(CHAR) * sizeof(WCHAR);
  2325. if ((DependBuffer = (LPWSTR)LocalAlloc(
  2326. LMEM_ZEROINIT,
  2327. (UINT) DependSize)) == NULL) {
  2328. SCC_LOG1(ERROR,
  2329. "CreateServiceA: LocalAlloc of DependBuffer failed "
  2330. FORMAT_DWORD "\n", GetLastError());
  2331. status = ERROR_NOT_ENOUGH_MEMORY;
  2332. goto CleanExit;
  2333. }
  2334. if (DependSize > sizeof(WCHAR)) {
  2335. //
  2336. // There is at least one dependency entry.
  2337. //
  2338. Ptr = (LPSTR) lpDependencies;
  2339. //
  2340. // Convert each dependency into Unicode, and append it to the
  2341. // DependBuffer.
  2342. //
  2343. while (*Ptr != 0) {
  2344. LPWSTR ConvertedDependency = NULL;
  2345. if (! ScConvertToUnicode(&ConvertedDependency, Ptr)) {
  2346. SCC_LOG0(ERROR,
  2347. "CreateServiceA: convert dependency to Unicode failed\n");
  2348. status = ERROR_NOT_ENOUGH_MEMORY;
  2349. goto CleanExit;
  2350. }
  2351. ScAddWStrToWStrArray(DependBuffer, ConvertedDependency);
  2352. (void) LocalFree(ConvertedDependency);
  2353. Ptr = ScNextAStrArrayEntry(Ptr);
  2354. }
  2355. }
  2356. }
  2357. status = RCreateServiceA (
  2358. (SC_RPC_HANDLE)hSCManager,
  2359. (LPSTR) lpServiceName,
  2360. (LPSTR) lpDisplayName,
  2361. dwDesiredAccess,
  2362. dwServiceType,
  2363. dwStartType,
  2364. dwErrorControl,
  2365. (LPSTR) lpBinaryPathName,
  2366. (LPSTR) lpLoadOrderGroup,
  2367. lpdwTagId,
  2368. (LPBYTE) DependBuffer,
  2369. DependSize,
  2370. (LPSTR) lpServiceStartName,
  2371. EncryptedPassword,
  2372. PasswordSize,
  2373. &hService);
  2374. }
  2375. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2376. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2377. }
  2378. RpcEndExcept
  2379. CleanExit:
  2380. if (DependBuffer != NULL) {
  2381. (void) LocalFree(DependBuffer);
  2382. }
  2383. if (EncryptedPassword != NULL) {
  2384. (void) LocalFree(EncryptedPassword);
  2385. }
  2386. if (status != NO_ERROR){
  2387. SetLastError(status);
  2388. return(NULL);
  2389. }
  2390. return (SC_HANDLE)hService;
  2391. }
  2392. SC_HANDLE
  2393. WINAPI
  2394. CreateServiceW(
  2395. IN SC_HANDLE hSCManager,
  2396. IN LPCWSTR lpServiceName,
  2397. IN LPCWSTR lpDisplayName,
  2398. IN DWORD dwDesiredAccess,
  2399. IN DWORD dwServiceType,
  2400. IN DWORD dwStartType,
  2401. IN DWORD dwErrorControl,
  2402. IN LPCWSTR lpBinaryPathName,
  2403. IN LPCWSTR lpLoadOrderGroup,
  2404. OUT LPDWORD lpdwTagId,
  2405. IN LPCWSTR lpDependencies,
  2406. IN LPCWSTR lpServiceStartName,
  2407. IN LPCWSTR lpPassword
  2408. )
  2409. /*++
  2410. Routine Description:
  2411. see CreateServiceA
  2412. Arguments:
  2413. Return Value:
  2414. Note:
  2415. --*/
  2416. {
  2417. DWORD status;
  2418. SC_RPC_HANDLE hService = NULL;
  2419. LPBYTE EncryptedPassword = NULL;
  2420. DWORD PasswordSize = 0;
  2421. DWORD DependSize = 0;
  2422. RpcTryExcept {
  2423. if (ARGUMENT_PRESENT(lpPassword)) {
  2424. status = ScEncryptPassword(
  2425. (SC_RPC_HANDLE)hSCManager,
  2426. (LPWSTR) lpPassword,
  2427. &EncryptedPassword,
  2428. &PasswordSize
  2429. );
  2430. if (status != NO_ERROR) {
  2431. SCC_LOG0(ERROR,"CreateServiceW: ScEncryptPassword failed\n");
  2432. SetLastError(status);
  2433. return NULL;
  2434. }
  2435. }
  2436. if (ARGUMENT_PRESENT(lpDependencies)) {
  2437. DependSize = ScWStrArraySize((LPWSTR) lpDependencies);
  2438. }
  2439. status = RCreateServiceW (
  2440. (SC_RPC_HANDLE)hSCManager,
  2441. (LPWSTR) lpServiceName,
  2442. (LPWSTR) lpDisplayName,
  2443. dwDesiredAccess,
  2444. dwServiceType,
  2445. dwStartType,
  2446. dwErrorControl,
  2447. (LPWSTR) lpBinaryPathName,
  2448. (LPWSTR) lpLoadOrderGroup,
  2449. lpdwTagId,
  2450. (LPBYTE) lpDependencies,
  2451. DependSize,
  2452. (LPWSTR) lpServiceStartName,
  2453. EncryptedPassword,
  2454. PasswordSize,
  2455. &hService);
  2456. }
  2457. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2458. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2459. }
  2460. RpcEndExcept
  2461. if (EncryptedPassword != NULL) {
  2462. LocalFree(EncryptedPassword);
  2463. }
  2464. if (status != NO_ERROR){
  2465. SetLastError(status);
  2466. return NULL;
  2467. }
  2468. return (SC_HANDLE)hService;
  2469. }
  2470. BOOL
  2471. WINAPI
  2472. DeleteService(
  2473. IN SC_HANDLE hService
  2474. )
  2475. /*++
  2476. Routine Description:
  2477. This is the DLL entry point for the DeleteService function.
  2478. DeleteService removes the service from the Service Control
  2479. Manager's database.
  2480. Arguments:
  2481. hService - Handle obtained from a previous CreateService or
  2482. OpenService call.
  2483. Return Value:
  2484. Note:
  2485. --*/
  2486. {
  2487. DWORD status;
  2488. SCC_LOG1(TRACE,
  2489. "---------DeleteService called (%ws)\n",
  2490. GetCommandLineW());
  2491. RpcTryExcept {
  2492. status = RDeleteService ((SC_RPC_HANDLE)hService);
  2493. }
  2494. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2495. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2496. }
  2497. RpcEndExcept
  2498. if (status != NO_ERROR){
  2499. SCC_LOG2(TRACE,
  2500. "---------DeleteService FAILED, %ld (%ws)\n",
  2501. status,
  2502. GetCommandLineW());
  2503. SetLastError(status);
  2504. return(FALSE);
  2505. }
  2506. SCC_LOG1(TRACE,
  2507. "---------DeleteService SUCCESS (%ws)\n",
  2508. GetCommandLineW());
  2509. return TRUE;
  2510. }
  2511. BOOL
  2512. WINAPI
  2513. EnumDependentServicesA(
  2514. IN SC_HANDLE hService,
  2515. IN DWORD dwServiceState,
  2516. OUT LPENUM_SERVICE_STATUSA lpServices,
  2517. IN DWORD cbBufSize,
  2518. OUT LPDWORD pcbBytesNeeded,
  2519. OUT LPDWORD lpServicesReturned
  2520. )
  2521. /*++
  2522. Routine Description:
  2523. This function lists the services which depend on the specified
  2524. service to be running before they can run. The returned
  2525. services entries are ordered in the reverse order of start
  2526. dependencies with group order taken into account. Services can
  2527. be stopped in the proper order based on the order of entries
  2528. written to the output buffer.
  2529. Arguments:
  2530. hService - Handle obtained from a previous OpenService call.
  2531. dwServiceState - Value to select the services to enumerate based on
  2532. the running state.
  2533. lpServices - A pointer to a buffer to receive an array of service
  2534. entries; each entry is the ENUM_SERVICE_STATUS information
  2535. structure. The services returned in the buffer is ordered by
  2536. the reverse dependency order.
  2537. cbBufSize - Size of the buffer in bytes pointed to by lpServices.
  2538. pcbBytesNeeded - A pointer to a variable to receive the number of
  2539. bytes needed to fit the remaining service entries.
  2540. lpServicesReturned - A pointer to a variable to receive the number
  2541. of service entries returned.
  2542. Return Value:
  2543. TRUE - if all Services are successfully written into the supplied
  2544. output buffer.
  2545. FALSE - If an error has occured - Use GetLastError to determine the
  2546. cause of the failure.
  2547. --*/
  2548. {
  2549. DWORD status;
  2550. LPENUM_SERVICE_STATUSA pEnumBuf;
  2551. ENUM_SERVICE_STATUSA enumBuf;
  2552. DWORD tempBufSize;
  2553. tempBufSize = cbBufSize;
  2554. //
  2555. // Create a dummy buffer that is at least the size of the structure.
  2556. // This way RPC should at least send the request to the server side.
  2557. // The server should recognize that the buffer is to small for any
  2558. // strings, and put the correct size in the BytesNeeded parameter,
  2559. // and fail the call.
  2560. //
  2561. if (cbBufSize < sizeof(ENUM_SERVICE_STATUSA) || (lpServices == NULL)) {
  2562. pEnumBuf = &enumBuf;
  2563. tempBufSize = sizeof(ENUM_SERVICE_STATUSA);
  2564. }
  2565. else {
  2566. pEnumBuf = lpServices;
  2567. }
  2568. RpcTryExcept {
  2569. status = REnumDependentServicesA(
  2570. (SC_RPC_HANDLE)hService,
  2571. dwServiceState,
  2572. (LPBYTE)pEnumBuf,
  2573. tempBufSize,
  2574. pcbBytesNeeded,
  2575. lpServicesReturned);
  2576. }
  2577. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2578. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2579. }
  2580. RpcEndExcept
  2581. //
  2582. // If data is returned, convert Offsets in the Enum buffer to pointers.
  2583. //
  2584. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA))
  2585. {
  2586. if ((*lpServicesReturned) > 0)
  2587. {
  2588. #ifdef _WIN64
  2589. DWORD dwError;
  2590. if (!ScConvertOffsets64(SC_API_ENUM_DEPEND_A,
  2591. NULL, // no hSCManager
  2592. 0, // no service type
  2593. 0, // no service state
  2594. (LPBYTE) lpServices,
  2595. cbBufSize,
  2596. pcbBytesNeeded,
  2597. lpServicesReturned,
  2598. NULL, // no old resume index
  2599. NULL, // no group name
  2600. &dwError))
  2601. {
  2602. status = dwError;
  2603. }
  2604. }
  2605. //
  2606. // Scale required size up to the minimum size guaranteed to
  2607. // succeed with 64-bit structures.
  2608. //
  2609. *pcbBytesNeeded = *pcbBytesNeeded
  2610. * sizeof(ENUM_SERVICE_STATUSA)
  2611. / sizeof(ENUM_SERVICE_STATUS_WOW64);
  2612. #else // ndef _WIN64
  2613. ScConvertOffsetsA(lpServices, *lpServicesReturned);
  2614. }
  2615. #endif // _WIN64
  2616. }
  2617. if (status != NO_ERROR)
  2618. {
  2619. SetLastError(status);
  2620. return(FALSE);
  2621. }
  2622. return(TRUE);
  2623. }
  2624. BOOL
  2625. WINAPI
  2626. EnumDependentServicesW(
  2627. IN SC_HANDLE hService,
  2628. IN DWORD dwServiceState,
  2629. OUT LPENUM_SERVICE_STATUSW lpServices,
  2630. IN DWORD cbBufSize,
  2631. OUT LPDWORD pcbBytesNeeded,
  2632. OUT LPDWORD lpServicesReturned
  2633. )
  2634. /*++
  2635. Routine Description:
  2636. This function lists the services which depend on the specified
  2637. service to be running before they can run. The returned
  2638. services entries are ordered in the reverse order of start
  2639. dependencies with group order taken into account. Services can
  2640. be stopped in the proper order based on the order of entries
  2641. written to the output buffer.
  2642. Arguments:
  2643. hService - Handle obtained from a previous OpenService call.
  2644. dwServiceState - Value to select the services to enumerate based on
  2645. the running state.
  2646. lpServices - A pointer to a buffer to receive an array of service
  2647. entries; each entry is the ENUM_SERVICE_STATUS information
  2648. structure. The services returned in the buffer is ordered by
  2649. the reverse dependency order.
  2650. cbBufSize - Size of the buffer in bytes pointed to by lpServices.
  2651. pcbBytesNeeded - A pointer to a variable to receive the number of
  2652. bytes needed to fit the remaining service entries.
  2653. lpServicesReturned - A pointer to a variable to receive the number
  2654. of service entries returned.
  2655. Return Value:
  2656. TRUE - if all Services are successfully written into the supplied
  2657. output buffer.
  2658. FALSE - If an error has occured - Use GetLastError to determine the
  2659. cause of the failure.
  2660. --*/
  2661. {
  2662. DWORD status;
  2663. LPENUM_SERVICE_STATUSW pEnumBuf;
  2664. ENUM_SERVICE_STATUSW enumBuf;
  2665. DWORD tempBufSize;
  2666. tempBufSize = cbBufSize;
  2667. //
  2668. // Create a dummy buffer that is at least the size of the structure.
  2669. // This way RPC should at least send the request to the server side.
  2670. // The server should recognize that the buffer is to small for any
  2671. // strings, and put the correct size in the BytesNeeded parameter,
  2672. // and fail the call.
  2673. //
  2674. if (cbBufSize < sizeof(ENUM_SERVICE_STATUSW) || (lpServices == NULL)) {
  2675. pEnumBuf = &enumBuf;
  2676. tempBufSize = sizeof(ENUM_SERVICE_STATUSW);
  2677. }
  2678. else {
  2679. pEnumBuf = lpServices;
  2680. }
  2681. RpcTryExcept {
  2682. status = REnumDependentServicesW(
  2683. (SC_RPC_HANDLE)hService,
  2684. dwServiceState,
  2685. (LPBYTE)pEnumBuf,
  2686. tempBufSize,
  2687. pcbBytesNeeded,
  2688. lpServicesReturned);
  2689. }
  2690. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2691. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2692. }
  2693. RpcEndExcept
  2694. //
  2695. // If data is returned, convert Offsets in the Enum buffer to pointers.
  2696. //
  2697. if ((status == NO_ERROR) || (status == ERROR_MORE_DATA))
  2698. {
  2699. if ((*lpServicesReturned) > 0)
  2700. {
  2701. #ifdef _WIN64
  2702. DWORD dwError;
  2703. if (!ScConvertOffsets64(SC_API_ENUM_DEPEND_W,
  2704. NULL, // no hSCManager
  2705. 0, // no service type
  2706. 0, // no service state
  2707. (LPBYTE) lpServices,
  2708. cbBufSize,
  2709. pcbBytesNeeded,
  2710. lpServicesReturned,
  2711. NULL, // no old resume index
  2712. NULL, // no group name
  2713. &dwError))
  2714. {
  2715. status = dwError;
  2716. }
  2717. }
  2718. //
  2719. // Scale required size up to the minimum size guaranteed to
  2720. // succeed with 64-bit structures.
  2721. //
  2722. *pcbBytesNeeded = *pcbBytesNeeded
  2723. * sizeof(ENUM_SERVICE_STATUSA)
  2724. / sizeof(ENUM_SERVICE_STATUS_WOW64);
  2725. #else // ndef _WIN64
  2726. ScConvertOffsetsW(lpServices, *lpServicesReturned);
  2727. }
  2728. #endif // _WIN64
  2729. }
  2730. if (status != NO_ERROR)
  2731. {
  2732. SetLastError(status);
  2733. return(FALSE);
  2734. }
  2735. return(TRUE);
  2736. }
  2737. BOOL
  2738. WINAPI
  2739. GetServiceDisplayNameA(
  2740. SC_HANDLE hSCManager,
  2741. LPCSTR lpServiceName,
  2742. LPSTR lpDisplayName,
  2743. LPDWORD lpcchBuffer
  2744. )
  2745. /*++
  2746. Routine Description:
  2747. This function returns the display name for a service that is identified
  2748. by its key name (ServiceName).
  2749. Arguments:
  2750. hSCManager - This is the handle to the Service Controller Manager that
  2751. is expected to return the display name.
  2752. lpServiceName - This is the ServiceName (which is actually a key
  2753. name) that identifies the service.
  2754. lpDisplayName - This is a pointer to a buffer that is to receive the
  2755. DisplayName string.
  2756. lpcchBuffer - This is a pointer to the size (in characters) of the
  2757. buffer that is to receive the DisplayName string. If the buffer
  2758. is not large enough to receive the entire string, then the required
  2759. buffer size is returned in this location. (NOTE: Ansi Characters,
  2760. including DBCS, are assumed to be 8 bits).
  2761. Return Value:
  2762. --*/
  2763. {
  2764. DWORD status;
  2765. LPSTR bufPtr;
  2766. CHAR tempString[] = "";
  2767. //
  2768. // Create a dummy buffer that is at least the size of a CHAR.
  2769. // This way RPC should at least send the request to the server side.
  2770. // The server should recognize that the buffer is to small for any
  2771. // strings, and put the correct size in the BytesNeeded parameter,
  2772. // and fail the call.
  2773. //
  2774. RpcTryExcept {
  2775. if ((*lpcchBuffer < sizeof(CHAR)) || (lpDisplayName == NULL)){
  2776. bufPtr = tempString;
  2777. *lpcchBuffer = sizeof(CHAR);
  2778. }
  2779. else {
  2780. bufPtr = (LPSTR)lpDisplayName;
  2781. }
  2782. status = RGetServiceDisplayNameA(
  2783. (SC_RPC_HANDLE)hSCManager,
  2784. (LPSTR)lpServiceName,
  2785. bufPtr,
  2786. lpcchBuffer);
  2787. }
  2788. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2789. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2790. }
  2791. RpcEndExcept
  2792. if (status != NO_ERROR) {
  2793. SetLastError(status);
  2794. return(FALSE);
  2795. }
  2796. return(TRUE);
  2797. }
  2798. BOOL
  2799. WINAPI
  2800. GetServiceDisplayNameW(
  2801. SC_HANDLE hSCManager,
  2802. LPCWSTR lpServiceName,
  2803. LPWSTR lpDisplayName,
  2804. LPDWORD lpcchBuffer
  2805. )
  2806. /*++
  2807. Routine Description:
  2808. Arguments:
  2809. Return Value:
  2810. --*/
  2811. {
  2812. DWORD status;
  2813. LPWSTR bufPtr;
  2814. WCHAR tempString[]=L"";
  2815. //
  2816. // Create a dummy buffer that is at least the size of a WCHAR.
  2817. // This way RPC should at least send the request to the server side.
  2818. // The server should recognize that the buffer is to small for any
  2819. // strings, and put the correct size in the BytesNeeded parameter,
  2820. // and fail the call.
  2821. //
  2822. RpcTryExcept {
  2823. if ((*lpcchBuffer < sizeof(WCHAR)) || (lpDisplayName == NULL)) {
  2824. bufPtr = tempString;
  2825. *lpcchBuffer = sizeof(WCHAR);
  2826. }
  2827. else {
  2828. bufPtr = (LPWSTR)lpDisplayName;
  2829. }
  2830. status = RGetServiceDisplayNameW(
  2831. (SC_RPC_HANDLE)hSCManager,
  2832. (LPWSTR)lpServiceName,
  2833. bufPtr,
  2834. lpcchBuffer);
  2835. }
  2836. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2837. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2838. }
  2839. RpcEndExcept
  2840. if (status != NO_ERROR) {
  2841. SetLastError(status);
  2842. return(FALSE);
  2843. }
  2844. return(TRUE);
  2845. }
  2846. BOOL
  2847. WINAPI
  2848. GetServiceKeyNameA(
  2849. SC_HANDLE hSCManager,
  2850. LPCSTR lpDisplayName,
  2851. LPSTR lpServiceName,
  2852. LPDWORD lpcchBuffer
  2853. )
  2854. /*++
  2855. Routine Description:
  2856. Arguments:
  2857. hSCManager - This is the handle to the Service Controller Manager that
  2858. is expected to return the service name (key name).
  2859. lpServiceName - This is the Service Display Name that identifies
  2860. the service.
  2861. lpServiceName - This is a pointer to a buffer that is to receive the
  2862. Service Key Name string.
  2863. lpcchBuffer - This is a pointer to the size of the buffer that is
  2864. to receive the Service Key Name string. If the buffer is not large
  2865. enough to receive the entire string, then the required buffer size
  2866. is returned in this location.
  2867. Return Value:
  2868. --*/
  2869. {
  2870. DWORD status;
  2871. LPSTR bufPtr;
  2872. CHAR tempString[]="";
  2873. //
  2874. // Create a dummy buffer that is at least the size of a CHAR.
  2875. // This way RPC should at least send the request to the server side.
  2876. // The server should recognize that the buffer is to small for any
  2877. // strings, and put the correct size in the BytesNeeded parameter,
  2878. // and fail the call.
  2879. //
  2880. RpcTryExcept {
  2881. if ((*lpcchBuffer < sizeof(CHAR)) || (lpServiceName == NULL)) {
  2882. bufPtr = tempString;
  2883. *lpcchBuffer = sizeof(CHAR);
  2884. }
  2885. else {
  2886. bufPtr = (LPSTR)lpServiceName;
  2887. }
  2888. status = RGetServiceKeyNameA(
  2889. (SC_RPC_HANDLE)hSCManager,
  2890. (LPSTR)lpDisplayName,
  2891. bufPtr,
  2892. lpcchBuffer);
  2893. }
  2894. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2895. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2896. }
  2897. RpcEndExcept
  2898. if (status != NO_ERROR) {
  2899. SetLastError(status);
  2900. return(FALSE);
  2901. }
  2902. return(TRUE);
  2903. }
  2904. BOOL
  2905. WINAPI
  2906. GetServiceKeyNameW(
  2907. SC_HANDLE hSCManager,
  2908. LPCWSTR lpDisplayName,
  2909. LPWSTR lpServiceName,
  2910. LPDWORD lpcchBuffer
  2911. )
  2912. /*++
  2913. Routine Description:
  2914. Arguments:
  2915. Return Value:
  2916. --*/
  2917. {
  2918. DWORD status = NO_ERROR;
  2919. LPWSTR bufPtr;
  2920. WCHAR tempString[]=L"";
  2921. //
  2922. // Create a dummy buffer that is at least the size of a WCHAR.
  2923. // This way RPC should at least send the request to the server side.
  2924. // The server should recognize that the buffer is to small for any
  2925. // strings, and put the correct size in the BytesNeeded parameter,
  2926. // and fail the call.
  2927. //
  2928. RpcTryExcept {
  2929. if ((*lpcchBuffer < sizeof(WCHAR)) || (lpServiceName == NULL)) {
  2930. bufPtr = tempString;
  2931. *lpcchBuffer = sizeof(WCHAR);
  2932. }
  2933. else {
  2934. bufPtr = (LPWSTR)lpServiceName;
  2935. }
  2936. status = RGetServiceKeyNameW(
  2937. (SC_RPC_HANDLE)hSCManager,
  2938. (LPWSTR)lpDisplayName,
  2939. bufPtr,
  2940. lpcchBuffer);
  2941. }
  2942. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2943. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2944. }
  2945. RpcEndExcept
  2946. if (status != NO_ERROR) {
  2947. SetLastError(status);
  2948. return(FALSE);
  2949. }
  2950. return(TRUE);
  2951. }
  2952. SC_LOCK
  2953. WINAPI
  2954. LockServiceDatabase(
  2955. IN SC_HANDLE hSCManager
  2956. )
  2957. /*++
  2958. Routine Description:
  2959. This is the DLL entry point for the LockServiceDatabase function.
  2960. This function acquires a lock on the database that was opened from
  2961. a previous OpenSCManager call. There can only be one lock
  2962. outstanding on a database for a given time.
  2963. Arguments:
  2964. hSCManager - Handle obtained from a previous OpenSCManager call
  2965. which specifies the database to lock.
  2966. Return Value:
  2967. --*/
  2968. {
  2969. DWORD status;
  2970. SC_RPC_LOCK lock = NULL;
  2971. RpcTryExcept {
  2972. status = RLockServiceDatabase(
  2973. (SC_RPC_HANDLE)hSCManager,
  2974. &lock);
  2975. }
  2976. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2977. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  2978. }
  2979. RpcEndExcept
  2980. if (status != NO_ERROR){
  2981. SetLastError(status);
  2982. return(NULL);
  2983. }
  2984. return((SC_LOCK)lock);
  2985. }
  2986. BOOL
  2987. WINAPI
  2988. QueryServiceConfigA(
  2989. IN SC_HANDLE hService,
  2990. OUT LPQUERY_SERVICE_CONFIGA lpServiceConfig,
  2991. IN DWORD cbBufSize,
  2992. OUT LPDWORD pcbBytesNeeded
  2993. )
  2994. /*++
  2995. Routine Description:
  2996. This is the DLL entry point for the QueryServiceConfig function.
  2997. QueryServiceConfig obtains the service configuration information
  2998. stored in the Service Control Manager database. This configuration
  2999. information was first set in the database via the CreateService API,
  3000. and may have been updated via the ChangeServiceConfig API.
  3001. Arguments:
  3002. hService - Handle obtained from a previous CreateService or
  3003. OpenService call.
  3004. lpServiceConfig - A pointer to a buffer to receive a
  3005. QUERY_SERVICE_CONFIG information structure.
  3006. cbBufSize - Size of the buffer in bytes pointed to by lpServiceConfig.
  3007. pcbBytesNeeded - A pointer to a variable to receive the number of
  3008. bytes needed to fit the entire QUERY_SERVICE_CONFIG information
  3009. structure.
  3010. Return Value:
  3011. Note:
  3012. --*/
  3013. {
  3014. DWORD status;
  3015. LPSTR pDepend;
  3016. LPQUERY_SERVICE_CONFIGA pConfigBuf;
  3017. QUERY_SERVICE_CONFIGA configBuf;
  3018. DWORD tempBufSize;
  3019. tempBufSize = cbBufSize;
  3020. //
  3021. // Create a dummy buffer that is at least the size of the structure.
  3022. // This way RPC should at least send the request to the server side.
  3023. // The server should recognize that the buffer is to small for any
  3024. // strings, and put the correct size in the BytesNeeded parameter,
  3025. // and fail the call.
  3026. //
  3027. if (cbBufSize < sizeof(QUERY_SERVICE_CONFIGA))
  3028. {
  3029. pConfigBuf = &configBuf;
  3030. tempBufSize = sizeof(QUERY_SERVICE_CONFIGA);
  3031. }
  3032. else
  3033. {
  3034. pConfigBuf = lpServiceConfig;
  3035. }
  3036. RpcTryExcept
  3037. {
  3038. status = RQueryServiceConfigA(
  3039. (SC_RPC_HANDLE)hService,
  3040. pConfigBuf,
  3041. tempBufSize,
  3042. pcbBytesNeeded);
  3043. }
  3044. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3045. {
  3046. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3047. }
  3048. RpcEndExcept
  3049. if (status != NO_ERROR)
  3050. {
  3051. #ifdef _WIN64
  3052. //
  3053. // pcbBytesNeeded isn't filled in if the byte count is too
  3054. // small (returned when the buffer size is large enough to
  3055. // hold the 32-bit structure but too small to hold the
  3056. // 64-bit structure. Get the necessary (32-bit) size.
  3057. //
  3058. if (status == RPC_X_BYTE_COUNT_TOO_SMALL)
  3059. {
  3060. RpcTryExcept
  3061. {
  3062. status = RQueryServiceConfigA(
  3063. (SC_RPC_HANDLE)hService,
  3064. pConfigBuf,
  3065. sizeof(QUERY_SERVICE_CONFIGA),
  3066. pcbBytesNeeded);
  3067. }
  3068. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3069. {
  3070. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3071. }
  3072. RpcEndExcept
  3073. }
  3074. //
  3075. // Since the ACF file specifies byte_count for this API, we're
  3076. // responsible for managing the count of bytes needed by the
  3077. // caller. For 64-bit clients calling 32-bit servers, the
  3078. // returned buffer size is too small because of differing
  3079. // pointer sizes. Add on the minimum number of bytes that
  3080. // will guarantee enough space in the buffer for the next
  3081. // call.
  3082. //
  3083. if (status == ERROR_INSUFFICIENT_BUFFER)
  3084. {
  3085. //
  3086. // 5 embedded pointers in the structure and max
  3087. // space required for alignment.
  3088. //
  3089. *pcbBytesNeeded += 5 * (sizeof(PVOID) - sizeof(ULONG) + sizeof(PVOID));
  3090. }
  3091. #endif // _WIN64
  3092. SetLastError(status);
  3093. return(FALSE);
  3094. }
  3095. else
  3096. {
  3097. //
  3098. // Replace the '/' separator characters by NULLs. We used
  3099. // separator characters in the double NULL terminated set of
  3100. // strings so that RPC could treat it as a single string.
  3101. //
  3102. if ((pDepend = lpServiceConfig->lpDependencies) != NULL) {
  3103. while (*pDepend != '\0') {
  3104. if (*pDepend == '/') {
  3105. *pDepend = '\0';
  3106. }
  3107. pDepend++;
  3108. }
  3109. }
  3110. }
  3111. return(TRUE);
  3112. }
  3113. BOOL
  3114. WINAPI
  3115. QueryServiceConfigW(
  3116. IN SC_HANDLE hService,
  3117. OUT LPQUERY_SERVICE_CONFIGW lpServiceConfig,
  3118. IN DWORD cbBufSize,
  3119. OUT LPDWORD pcbBytesNeeded
  3120. )
  3121. /*++
  3122. Routine Description:
  3123. see QueryServiceConfigA
  3124. Arguments:
  3125. Return Value:
  3126. Note:
  3127. --*/
  3128. {
  3129. DWORD status;
  3130. LPWSTR pDepend;
  3131. LPQUERY_SERVICE_CONFIGW pConfigBuf;
  3132. QUERY_SERVICE_CONFIGW configBuf;
  3133. DWORD tempBufSize;
  3134. tempBufSize = cbBufSize;
  3135. //
  3136. // Create a dummy buffer that is at least the size of the structure.
  3137. // This way RPC should at least send the request to the server side.
  3138. // The server should recognize that the buffer is to small for any
  3139. // strings, and put the correct size in the BytesNeeded parameter,
  3140. // and fail the call.
  3141. //
  3142. if (cbBufSize < sizeof(QUERY_SERVICE_CONFIGW))
  3143. {
  3144. pConfigBuf = &configBuf;
  3145. tempBufSize = sizeof(QUERY_SERVICE_CONFIGW);
  3146. }
  3147. else
  3148. {
  3149. pConfigBuf = lpServiceConfig;
  3150. }
  3151. RpcTryExcept
  3152. {
  3153. status = RQueryServiceConfigW(
  3154. (SC_RPC_HANDLE)hService,
  3155. pConfigBuf,
  3156. tempBufSize,
  3157. pcbBytesNeeded);
  3158. }
  3159. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3160. {
  3161. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3162. }
  3163. RpcEndExcept
  3164. if (status != NO_ERROR)
  3165. {
  3166. #ifdef _WIN64
  3167. //
  3168. // pcbBytesNeeded isn't filled in if the byte count is too
  3169. // small (returned when the buffer size is large enough to
  3170. // hold the 32-bit structure but too small to hold the
  3171. // 64-bit structure. Get the necessary (32-bit) size.
  3172. //
  3173. if (status == RPC_X_BYTE_COUNT_TOO_SMALL)
  3174. {
  3175. RpcTryExcept
  3176. {
  3177. status = RQueryServiceConfigW(
  3178. (SC_RPC_HANDLE)hService,
  3179. pConfigBuf,
  3180. sizeof(QUERY_SERVICE_CONFIGW),
  3181. pcbBytesNeeded);
  3182. }
  3183. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3184. {
  3185. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3186. }
  3187. RpcEndExcept
  3188. }
  3189. //
  3190. // Since the ACF file specifies byte_count for this API, we're
  3191. // responsible for managing the count of bytes needed by the
  3192. // caller. For 64-bit clients calling 32-bit servers, the
  3193. // returned buffer size is too small because of differing
  3194. // pointer sizes. Add on the minimum number of bytes that
  3195. // will guarantee enough space in the buffer for the next
  3196. // call.
  3197. //
  3198. if (status == ERROR_INSUFFICIENT_BUFFER)
  3199. {
  3200. //
  3201. // 5 embedded pointers in the structure and max
  3202. // space required for alignment.
  3203. //
  3204. *pcbBytesNeeded += 5 * (sizeof(PVOID) - sizeof(ULONG) + sizeof(PVOID));
  3205. }
  3206. #endif // _WIN64
  3207. SetLastError(status);
  3208. return(FALSE);
  3209. }
  3210. else
  3211. {
  3212. //
  3213. // Replace the '/' separator characters by NULLs. We used
  3214. // separator characters in the double NULL terminated set of
  3215. // strings so that RPC could treat it as a single string.
  3216. //
  3217. if ((pDepend = lpServiceConfig->lpDependencies) != NULL) {
  3218. while (*pDepend != L'\0') {
  3219. if (*pDepend == L'/') {
  3220. *pDepend = L'\0';
  3221. }
  3222. pDepend++;
  3223. }
  3224. }
  3225. }
  3226. return(TRUE);
  3227. }
  3228. BOOL
  3229. WINAPI
  3230. QueryServiceConfig2A(
  3231. IN SC_HANDLE hService,
  3232. IN DWORD dwInfoLevel,
  3233. OUT LPBYTE lpBuffer,
  3234. IN DWORD cbBufSize,
  3235. OUT LPDWORD pcbBytesNeeded
  3236. )
  3237. /*++
  3238. Routine Description:
  3239. Arguments:
  3240. Return Value:
  3241. Note:
  3242. --*/
  3243. {
  3244. DWORD status;
  3245. LPBYTE lpTempBuffer;
  3246. SERVICE_DESCRIPTIONA sdDescription;
  3247. SERVICE_FAILURE_ACTIONSA sfaActions;
  3248. DWORD tempBufSize;
  3249. BOOL fDummyBuffer = FALSE;
  3250. tempBufSize = cbBufSize;
  3251. lpTempBuffer = lpBuffer;
  3252. //
  3253. // Create a dummy buffer that is at least the size of the structure.
  3254. // This way RPC should at least send the request to the server side.
  3255. // The server should recognize that the buffer is to small for any
  3256. // strings, put the correct size in the BytesNeeded parameter, and
  3257. // fail the call.
  3258. //
  3259. switch(dwInfoLevel) {
  3260. case SERVICE_CONFIG_DESCRIPTION:
  3261. if (cbBufSize < sizeof(SERVICE_DESCRIPTION_WOW64)) {
  3262. lpTempBuffer = (LPBYTE) &sdDescription;
  3263. tempBufSize = sizeof(SERVICE_DESCRIPTION_WOW64);
  3264. fDummyBuffer = TRUE;
  3265. }
  3266. break;
  3267. case SERVICE_CONFIG_FAILURE_ACTIONS:
  3268. if (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONS_WOW64)) {
  3269. lpTempBuffer = (LPBYTE) &sfaActions;
  3270. tempBufSize = sizeof(SERVICE_FAILURE_ACTIONS_WOW64);
  3271. fDummyBuffer = TRUE;
  3272. }
  3273. break;
  3274. default:
  3275. SetLastError(ERROR_INVALID_LEVEL);
  3276. return FALSE;
  3277. }
  3278. RpcTryExcept
  3279. {
  3280. status = RQueryServiceConfig2A(
  3281. (SC_RPC_HANDLE) hService,
  3282. dwInfoLevel,
  3283. lpTempBuffer,
  3284. tempBufSize,
  3285. pcbBytesNeeded);
  3286. }
  3287. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3288. {
  3289. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3290. }
  3291. RpcEndExcept
  3292. #ifdef _WIN64
  3293. //
  3294. // 64-bit needs more space than the 32-bit-oriented structure
  3295. // coming from the server. Make sure we have it. Do this
  3296. // even if fDummyBuffer is TRUE since ScConvertOffsets64 will
  3297. // update *pcbBytesNeeded appropriately.
  3298. //
  3299. if (status == NO_ERROR || status == ERROR_INSUFFICIENT_BUFFER)
  3300. {
  3301. if (!ScConvertOffsets64(dwInfoLevel == SERVICE_CONFIG_DESCRIPTION ?
  3302. SC_API_QUERY_DESCRIPTION_A :
  3303. SC_API_QUERY_FAILURE_ACTIONS_A,
  3304. NULL,
  3305. 0,
  3306. 0,
  3307. lpTempBuffer,
  3308. tempBufSize,
  3309. pcbBytesNeeded,
  3310. NULL,
  3311. NULL,
  3312. NULL,
  3313. NULL))
  3314. {
  3315. status = ERROR_INSUFFICIENT_BUFFER;
  3316. }
  3317. }
  3318. #endif // _WIN64
  3319. if (status != NO_ERROR)
  3320. {
  3321. SetLastError(status);
  3322. return FALSE;
  3323. }
  3324. //
  3325. // Catch the case where the RPC call succeeded even though we used
  3326. // a dummy buffer (e.g., SERVICE_FAILURE_ACTIONS on a service with
  3327. // no command line or reboot message). Note that the server side
  3328. // of this API fills in pcbBytesNeeded even on success
  3329. //
  3330. if (fDummyBuffer)
  3331. {
  3332. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  3333. return FALSE;
  3334. }
  3335. //
  3336. // Convert offsets to pointers in the returned structure
  3337. //
  3338. switch (dwInfoLevel)
  3339. {
  3340. case SERVICE_CONFIG_DESCRIPTION:
  3341. {
  3342. LPSERVICE_DESCRIPTIONA psd =
  3343. (LPSERVICE_DESCRIPTIONA) lpBuffer;
  3344. if (psd->lpDescription != NULL)
  3345. {
  3346. psd->lpDescription = (LPSTR)
  3347. (lpBuffer + (DWORD)(ULONG_PTR)psd->lpDescription);
  3348. }
  3349. }
  3350. break;
  3351. case SERVICE_CONFIG_FAILURE_ACTIONS:
  3352. {
  3353. LPSERVICE_FAILURE_ACTIONSA psfa =
  3354. (LPSERVICE_FAILURE_ACTIONSA) lpBuffer;
  3355. if (psfa->lpRebootMsg != NULL)
  3356. {
  3357. psfa->lpRebootMsg = (LPSTR)
  3358. (lpBuffer + (DWORD)(ULONG_PTR)psfa->lpRebootMsg);
  3359. }
  3360. if (psfa->lpCommand != NULL)
  3361. {
  3362. psfa->lpCommand = (LPSTR)
  3363. (lpBuffer + (DWORD)(ULONG_PTR)psfa->lpCommand);
  3364. }
  3365. if (psfa->lpsaActions != NULL)
  3366. {
  3367. psfa->lpsaActions = (SC_ACTION *)
  3368. (lpBuffer + (DWORD)(ULONG_PTR)psfa->lpsaActions);
  3369. }
  3370. }
  3371. break;
  3372. }
  3373. return TRUE;
  3374. }
  3375. BOOL
  3376. WINAPI
  3377. QueryServiceConfig2W(
  3378. IN SC_HANDLE hService,
  3379. IN DWORD dwInfoLevel,
  3380. OUT LPBYTE lpBuffer,
  3381. IN DWORD cbBufSize,
  3382. OUT LPDWORD pcbBytesNeeded
  3383. )
  3384. /*++
  3385. Routine Description:
  3386. Arguments:
  3387. Return Value:
  3388. Note:
  3389. --*/
  3390. {
  3391. DWORD status;
  3392. LPBYTE lpTempBuffer;
  3393. SERVICE_DESCRIPTIONW sdDescription;
  3394. SERVICE_FAILURE_ACTIONSW sfaActions;
  3395. DWORD tempBufSize;
  3396. BOOL fDummyBuffer = FALSE;
  3397. tempBufSize = cbBufSize;
  3398. lpTempBuffer = lpBuffer;
  3399. //
  3400. // Create a dummy buffer that is at least the size of the structure.
  3401. // This way RPC should at least send the request to the server side.
  3402. // The server should recognize that the buffer is to small for any
  3403. // strings, put the correct size in the BytesNeeded parameter, and
  3404. // fail the call.
  3405. //
  3406. switch(dwInfoLevel) {
  3407. case SERVICE_CONFIG_DESCRIPTION:
  3408. if (cbBufSize < sizeof(SERVICE_DESCRIPTIONW)) {
  3409. lpTempBuffer = (LPBYTE) &sdDescription;
  3410. tempBufSize = sizeof(SERVICE_DESCRIPTIONW);
  3411. fDummyBuffer = TRUE;
  3412. }
  3413. break;
  3414. case SERVICE_CONFIG_FAILURE_ACTIONS:
  3415. if (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW)) {
  3416. lpTempBuffer = (LPBYTE) &sfaActions;
  3417. tempBufSize = sizeof(SERVICE_FAILURE_ACTIONSW);
  3418. fDummyBuffer = TRUE;
  3419. }
  3420. break;
  3421. default:
  3422. SetLastError(ERROR_INVALID_LEVEL);
  3423. return FALSE;
  3424. }
  3425. RpcTryExcept
  3426. {
  3427. status = RQueryServiceConfig2W(
  3428. (SC_RPC_HANDLE) hService,
  3429. dwInfoLevel,
  3430. lpTempBuffer,
  3431. tempBufSize,
  3432. pcbBytesNeeded);
  3433. }
  3434. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3435. {
  3436. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3437. }
  3438. RpcEndExcept
  3439. #ifdef _WIN64
  3440. //
  3441. // 64-bit needs more space than the 32-bit-oriented structure
  3442. // coming from the server. Make sure we have it. Do this
  3443. // even if fDummyBuffer is TRUE since ScConvertOffsets64 will
  3444. // update *pcbBytesNeeded appropriately.
  3445. //
  3446. if (status == NO_ERROR || status == ERROR_INSUFFICIENT_BUFFER)
  3447. {
  3448. if (!ScConvertOffsets64(dwInfoLevel == SERVICE_CONFIG_DESCRIPTION ?
  3449. SC_API_QUERY_DESCRIPTION_W :
  3450. SC_API_QUERY_FAILURE_ACTIONS_W,
  3451. NULL,
  3452. 0,
  3453. 0,
  3454. lpTempBuffer,
  3455. tempBufSize,
  3456. pcbBytesNeeded,
  3457. NULL,
  3458. NULL,
  3459. NULL,
  3460. NULL))
  3461. {
  3462. status = ERROR_INSUFFICIENT_BUFFER;
  3463. }
  3464. }
  3465. #endif // _WIN64
  3466. if (status != NO_ERROR)
  3467. {
  3468. SetLastError(status);
  3469. return FALSE;
  3470. }
  3471. //
  3472. // Catch the case where the RPC call succeeded even though we used
  3473. // a dummy buffer (e.g., SERVICE_FAILURE_ACTIONS on a service with
  3474. // no command line or reboot message). Note that the server side
  3475. // of this API fills in pcbBytesNeeded even on success
  3476. //
  3477. if (fDummyBuffer)
  3478. {
  3479. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  3480. return FALSE;
  3481. }
  3482. //
  3483. // Convert offsets to pointers in the returned structure
  3484. //
  3485. switch (dwInfoLevel)
  3486. {
  3487. case SERVICE_CONFIG_DESCRIPTION:
  3488. {
  3489. LPSERVICE_DESCRIPTIONW psd =
  3490. (LPSERVICE_DESCRIPTIONW) lpBuffer;
  3491. if (psd->lpDescription != NULL)
  3492. {
  3493. psd->lpDescription = (LPWSTR)
  3494. (lpBuffer + (DWORD)(ULONG_PTR) psd->lpDescription);
  3495. }
  3496. }
  3497. break;
  3498. case SERVICE_CONFIG_FAILURE_ACTIONS:
  3499. {
  3500. LPSERVICE_FAILURE_ACTIONSW psfa =
  3501. (LPSERVICE_FAILURE_ACTIONSW) lpBuffer;
  3502. if (psfa->lpRebootMsg != NULL)
  3503. {
  3504. psfa->lpRebootMsg = (LPWSTR)
  3505. (lpBuffer + (DWORD)(ULONG_PTR) psfa->lpRebootMsg);
  3506. }
  3507. if (psfa->lpCommand != NULL)
  3508. {
  3509. psfa->lpCommand = (LPWSTR)
  3510. (lpBuffer + (DWORD)(ULONG_PTR) psfa->lpCommand);
  3511. }
  3512. if (psfa->lpsaActions != NULL)
  3513. {
  3514. psfa->lpsaActions = (SC_ACTION *)
  3515. (lpBuffer + (DWORD)(ULONG_PTR) psfa->lpsaActions);
  3516. }
  3517. }
  3518. break;
  3519. }
  3520. return TRUE;
  3521. }
  3522. BOOL
  3523. WINAPI
  3524. QueryServiceLockStatusA(
  3525. SC_HANDLE hSCManager,
  3526. LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
  3527. DWORD cbBufSize,
  3528. LPDWORD pcbBytesNeeded
  3529. )
  3530. /*++
  3531. Routine Description:
  3532. This is the DLL entry point for the QueryServiceLockStatus function.
  3533. This function returns lock status information on a Service Control
  3534. Manager database.
  3535. Arguments:
  3536. hSCManager - Handled obtained from a previous call to OpenSCManager
  3537. call.
  3538. lpLockStatus - A pointer to a buffer to receive a
  3539. QUERY_SERVICE_LOCK_STATUS information structure.
  3540. Return Value:
  3541. Note:
  3542. --*/
  3543. {
  3544. DWORD status;
  3545. LPQUERY_SERVICE_LOCK_STATUSA pStatusBuf;
  3546. QUERY_SERVICE_LOCK_STATUSA statusBuf;
  3547. DWORD tempBufSize;
  3548. tempBufSize = cbBufSize;
  3549. //
  3550. // Create a dummy buffer that is at least the size of the structure.
  3551. // This way RPC should at least send the request to the server side.
  3552. // The server should recognize that the buffer is to small for any
  3553. // strings, and put the correct size in the BytesNeeded parameter,
  3554. // and fail the call.
  3555. //
  3556. if (cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
  3557. {
  3558. pStatusBuf = &statusBuf;
  3559. tempBufSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
  3560. }
  3561. else
  3562. {
  3563. pStatusBuf = lpLockStatus;
  3564. }
  3565. RpcTryExcept
  3566. {
  3567. status = RQueryServiceLockStatusA(
  3568. (SC_RPC_HANDLE)hSCManager,
  3569. pStatusBuf,
  3570. tempBufSize,
  3571. pcbBytesNeeded);
  3572. }
  3573. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3574. {
  3575. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3576. }
  3577. RpcEndExcept
  3578. if (status != NO_ERROR)
  3579. {
  3580. #ifdef _WIN64
  3581. //
  3582. // pcbBytesNeeded isn't filled in if the byte count is too
  3583. // small (returned when the buffer size is large enough to
  3584. // hold the 32-bit structure but too small to hold the
  3585. // 64-bit structure. Get the necessary (32-bit) size.
  3586. //
  3587. if (status == RPC_X_BYTE_COUNT_TOO_SMALL)
  3588. {
  3589. RpcTryExcept
  3590. {
  3591. status = RQueryServiceLockStatusA(
  3592. (SC_RPC_HANDLE)hSCManager,
  3593. pStatusBuf,
  3594. sizeof(QUERY_SERVICE_LOCK_STATUSA),
  3595. pcbBytesNeeded);
  3596. }
  3597. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3598. {
  3599. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3600. }
  3601. RpcEndExcept
  3602. }
  3603. //
  3604. // Since the ACF file specifies byte_count for this API, we're
  3605. // responsible for managing the count of bytes needed by the
  3606. // caller. For 64-bit clients calling 32-bit servers, the
  3607. // returned buffer size is too small because of differing
  3608. // pointer sizes. Add on the minimum number of bytes that
  3609. // will guarantee enough space in the buffer for the next
  3610. // call.
  3611. //
  3612. if (status == ERROR_INSUFFICIENT_BUFFER)
  3613. {
  3614. //
  3615. // 1 embedded pointer in the structure and max
  3616. // space required for alignment.
  3617. //
  3618. *pcbBytesNeeded += (sizeof(PVOID) - sizeof(ULONG) + sizeof(PVOID));
  3619. }
  3620. else if (status == RPC_X_BYTE_COUNT_TOO_SMALL)
  3621. {
  3622. //
  3623. // We get here if we called a 32-bit server where the lock
  3624. // was unowned and we used a buffer size smaller than
  3625. // sizeof(QUERY_SERVICE_LOCK_STATUSA).
  3626. //
  3627. *pcbBytesNeeded = sizeof(QUERY_SERVICE_LOCK_STATUSA) + sizeof(WCHAR);
  3628. status = ERROR_INSUFFICIENT_BUFFER;
  3629. }
  3630. #endif // _WIN64
  3631. SetLastError(status);
  3632. return(FALSE);
  3633. }
  3634. return(TRUE);
  3635. }
  3636. BOOL
  3637. WINAPI
  3638. QueryServiceLockStatusW(
  3639. SC_HANDLE hSCManager,
  3640. LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
  3641. DWORD cbBufSize,
  3642. LPDWORD pcbBytesNeeded
  3643. )
  3644. /*++
  3645. Routine Description:
  3646. see QueryServiceLockStatusA
  3647. Arguments:
  3648. Return Value:
  3649. Note:
  3650. --*/
  3651. {
  3652. DWORD status;
  3653. LPQUERY_SERVICE_LOCK_STATUSW pStatusBuf;
  3654. QUERY_SERVICE_LOCK_STATUSW statusBuf;
  3655. DWORD tempBufSize;
  3656. tempBufSize = cbBufSize;
  3657. //
  3658. // Create a dummy buffer that is at least the size of the structure.
  3659. // This way RPC should at least send the request to the server side.
  3660. // The server should recognize that the buffer is to small for any
  3661. // strings, and put the correct size in the BytesNeeded parameter,
  3662. // and fail the call.
  3663. //
  3664. if (cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
  3665. {
  3666. pStatusBuf = &statusBuf;
  3667. tempBufSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
  3668. }
  3669. else
  3670. {
  3671. pStatusBuf = lpLockStatus;
  3672. }
  3673. RpcTryExcept
  3674. {
  3675. status = RQueryServiceLockStatusW(
  3676. (SC_RPC_HANDLE)hSCManager,
  3677. pStatusBuf,
  3678. tempBufSize,
  3679. pcbBytesNeeded);
  3680. }
  3681. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3682. {
  3683. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3684. }
  3685. RpcEndExcept
  3686. if (status != NO_ERROR)
  3687. {
  3688. #ifdef _WIN64
  3689. //
  3690. // pcbBytesNeeded isn't filled in if the byte count is too
  3691. // small (returned when the buffer size is large enough to
  3692. // hold the 32-bit structure but too small to hold the
  3693. // 64-bit structure. Get the necessary (32-bit) size.
  3694. //
  3695. if (status == RPC_X_BYTE_COUNT_TOO_SMALL)
  3696. {
  3697. RpcTryExcept
  3698. {
  3699. status = RQueryServiceLockStatusW(
  3700. (SC_RPC_HANDLE)hSCManager,
  3701. pStatusBuf,
  3702. sizeof(QUERY_SERVICE_LOCK_STATUSW),
  3703. pcbBytesNeeded);
  3704. }
  3705. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  3706. {
  3707. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3708. }
  3709. RpcEndExcept
  3710. }
  3711. //
  3712. // Since the ACF file specifies byte_count for this API, we're
  3713. // responsible for managing the count of bytes needed by the
  3714. // caller. For 64-bit clients calling 32-bit servers, the
  3715. // returned buffer size is too small because of differing
  3716. // pointer sizes. Add on the minimum number of bytes that
  3717. // will guarantee enough space in the buffer for the next
  3718. // call.
  3719. //
  3720. if (status == ERROR_INSUFFICIENT_BUFFER)
  3721. {
  3722. //
  3723. // 1 embedded pointer in the structure and max
  3724. // space required for alignment.
  3725. //
  3726. *pcbBytesNeeded += (sizeof(PVOID) - sizeof(ULONG) + sizeof(PVOID));
  3727. }
  3728. else if (status == RPC_X_BYTE_COUNT_TOO_SMALL)
  3729. {
  3730. //
  3731. // We get here if we called a 32-bit server where the lock
  3732. // was unowned and we used a buffer size smaller than
  3733. // sizeof(QUERY_SERVICE_LOCK_STATUSW).
  3734. //
  3735. *pcbBytesNeeded = sizeof(QUERY_SERVICE_LOCK_STATUSW) + sizeof(WCHAR);
  3736. status = ERROR_INSUFFICIENT_BUFFER;
  3737. }
  3738. #endif // _WIN64
  3739. SetLastError(status);
  3740. return(FALSE);
  3741. }
  3742. return(TRUE);
  3743. }
  3744. BOOL
  3745. WINAPI
  3746. UnlockServiceDatabase(
  3747. IN SC_LOCK ScLock
  3748. )
  3749. /*++
  3750. Routine Description:
  3751. This is the DLL entry point for the UnlockServiceDatabase function.
  3752. This function releases a lock on a Service Control Manager database.
  3753. Arguments:
  3754. ScLock - Lock obtained from a previous LockServiceDatabase call.
  3755. Return Value:
  3756. --*/
  3757. {
  3758. DWORD status;
  3759. UNREFERENCED_PARAMETER(ScLock);
  3760. RpcTryExcept {
  3761. status = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
  3762. }
  3763. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3764. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_SERVICE_LOCK);
  3765. }
  3766. RpcEndExcept
  3767. if (status != NO_ERROR){
  3768. SetLastError(status);
  3769. return(FALSE);
  3770. }
  3771. return(TRUE);
  3772. }
  3773. BOOL
  3774. WINAPI
  3775. NotifyBootConfigStatus(
  3776. IN BOOL BootAcceptable
  3777. )
  3778. /*++
  3779. Routine Description:
  3780. If we are not currently booted with Last Known Good, this function
  3781. will revert to Last Known Good if the boot is not acceptable. Or it
  3782. will save the boot configuration that we last booted from as the
  3783. Last Known Good. This is the configuration that we will fall back
  3784. to if a future boot fails.
  3785. Arguments:
  3786. BootAcceptable - This indicates whether or not the boot was acceptable.
  3787. Return Value:
  3788. TRUE - This is only returned if the boot is acceptable, and we
  3789. successfully replaced Last Known Good with the current boot
  3790. configuration.
  3791. FALSE - This is returned if an error occured when attempting to replace
  3792. Last Known Good or if the system is currently booted from Last
  3793. Known Good.
  3794. --*/
  3795. {
  3796. DWORD status;
  3797. RpcTryExcept {
  3798. status = RNotifyBootConfigStatus(
  3799. NULL, // A Local Call Only.
  3800. (DWORD)BootAcceptable);
  3801. }
  3802. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3803. status = ScMapRpcError(RpcExceptionCode(), ERROR_INVALID_HANDLE);
  3804. }
  3805. RpcEndExcept
  3806. if (status != NO_ERROR){
  3807. SetLastError(status);
  3808. return(FALSE);
  3809. }
  3810. return(TRUE);
  3811. }
  3812. DWORD
  3813. ScWaitForStart(
  3814. VOID
  3815. )
  3816. /*++
  3817. Routine Description:
  3818. This routine waits until the SC_INTERNAL_START_EVENT is set or until
  3819. a timeout occurs. Then it returns.
  3820. Arguments:
  3821. none
  3822. Return Value:
  3823. none
  3824. --*/
  3825. {
  3826. DWORD status;
  3827. HANDLE ScStartEvent = NULL;
  3828. //
  3829. // Try opening the event first because it will work most of the
  3830. // time.
  3831. //
  3832. ScStartEvent = OpenEventW(
  3833. SYNCHRONIZE,
  3834. FALSE,
  3835. SC_INTERNAL_START_EVENT );
  3836. if (ScStartEvent == NULL) {
  3837. status = GetLastError();
  3838. if (status == ERROR_FILE_NOT_FOUND) {
  3839. //
  3840. // Only if we can't find the event do we attempt to create
  3841. // it here.
  3842. //
  3843. SCC_LOG0(ERROR,
  3844. "ScWaitForStart: Event does not exist -- attempting to create it\n");
  3845. //
  3846. // Create the event that the OpenSCManager will use to wait on the
  3847. // service controller with.
  3848. //
  3849. SECURITY_ATTRIBUTES SecurityAttributes;
  3850. PSECURITY_DESCRIPTOR SecurityDescriptor=NULL;
  3851. status = ScCreateStartEventSD(&SecurityDescriptor);
  3852. if (status != NO_ERROR) {
  3853. SCC_LOG0(ERROR,"ScGetStartEvent: Couldn't allocate for SecurityDesc\n");
  3854. return status;
  3855. }
  3856. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  3857. SecurityAttributes.bInheritHandle = FALSE;
  3858. SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
  3859. ScStartEvent = CreateEventW(
  3860. &SecurityAttributes,
  3861. TRUE, // Must be manually reset
  3862. FALSE, // The event is initially not signalled
  3863. SC_INTERNAL_START_EVENT );
  3864. status = GetLastError(); // must do this before LocalFree
  3865. LocalFree(SecurityDescriptor);
  3866. if (ScStartEvent == NULL) {
  3867. //
  3868. // Failed to create StartEvent.
  3869. //
  3870. // If we failed to create it because someone else created
  3871. // it between our calls to OpenEvent and CreateEvent, try
  3872. // to open it once more.
  3873. //
  3874. if (status == ERROR_ALREADY_EXISTS) {
  3875. ScStartEvent = OpenEventW(
  3876. SYNCHRONIZE,
  3877. FALSE,
  3878. SC_INTERNAL_START_EVENT );
  3879. if (ScStartEvent == NULL) {
  3880. status = GetLastError();
  3881. SCC_LOG1(ERROR,"ScWaitForStart: OpenEvent (StartEvent) failed "
  3882. FORMAT_DWORD " on second attempt\n", status);
  3883. return status;
  3884. }
  3885. }
  3886. else {
  3887. SCC_LOG1(ERROR,"ScWaitForStart: CreateEvent (StartEvent) Failed "
  3888. FORMAT_DWORD "\n", status);
  3889. return status;
  3890. }
  3891. }
  3892. }
  3893. else {
  3894. //
  3895. // Could not open the event for some unknown reason. Give up.
  3896. //
  3897. SCC_LOG1(ERROR,"ScWaitForStart: OpenEvent (StartEvent) Failed "
  3898. FORMAT_DWORD "\n", status);
  3899. return status;
  3900. }
  3901. }
  3902. SCC_LOG0(TRACE,"Beginning wait for ScStartEvent\n");
  3903. status = WaitForSingleObject(ScStartEvent, SC_START_TIMEOUT);
  3904. CloseHandle(ScStartEvent);
  3905. if (status == WAIT_TIMEOUT) {
  3906. SCC_LOG0(ERROR,"ScWaitForStart: TIMEOUT waiting for StartEvent\n");
  3907. return ERROR_TIMEOUT;
  3908. }
  3909. return NO_ERROR;
  3910. }
  3911. DWORD
  3912. ScMapRpcError(
  3913. IN DWORD RpcError,
  3914. IN DWORD BadContextError
  3915. )
  3916. /*++
  3917. Routine Description:
  3918. This routine maps the RPC error into a more meaningful error
  3919. for the caller.
  3920. Arguments:
  3921. RpcError - Supplies the exception error raised by RPC
  3922. BadContextError - Supplies the error code to return whenever an error
  3923. which indicates invalid context is received. In some cases, this
  3924. value is ERROR_INVALID_HANDLE; in others, it is ERROR_INVALID_SERVICE_LOCK.
  3925. Return Value:
  3926. Returns the mapped error.
  3927. --*/
  3928. {
  3929. switch (RpcError)
  3930. {
  3931. case RPC_S_INVALID_BINDING:
  3932. case RPC_X_SS_IN_NULL_CONTEXT:
  3933. case RPC_X_SS_CONTEXT_DAMAGED:
  3934. case RPC_X_SS_HANDLES_MISMATCH:
  3935. case ERROR_INVALID_HANDLE:
  3936. return BadContextError;
  3937. case RPC_X_NULL_REF_POINTER:
  3938. case EXCEPTION_ACCESS_VIOLATION:
  3939. return ERROR_INVALID_ADDRESS;
  3940. case RPC_S_INVALID_TAG:
  3941. return ERROR_INVALID_LEVEL;
  3942. case RPC_S_PROCNUM_OUT_OF_RANGE:
  3943. return ERROR_CALL_NOT_IMPLEMENTED;
  3944. default:
  3945. return RpcError;
  3946. }
  3947. }