Leaked source code of windows server 2003
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.

1577 lines
41 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. SCANSI.CXX
  5. Abstract:
  6. This file contains ansi wrappers for the Service Controller API
  7. functions.
  8. Author:
  9. Dan Lafferty (danl) 04-Feb-1992
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. 05-Nov-1992 Danl
  14. Added DisplayName Changes & new API.
  15. 28-May-1992 JohnRo
  16. RAID 9829: winsvc.h and related file cleanup.
  17. 14-Apr-1992 JohnRo
  18. We should not return password from any of our APIs.
  19. 04-Feb-1992 danl
  20. Created
  21. --*/
  22. #include "precomp.hxx"
  23. #include <sclib.h> // ScConvertToUnicode, ScConvertToAnsi
  24. #include <scwow.h> // 32/64-bit interop structures
  25. DWORD
  26. ROpenSCManagerA(
  27. IN LPSTR lpMachineName,
  28. IN LPSTR lpDatabaseName OPTIONAL,
  29. IN DWORD dwDesiredAccess,
  30. OUT LPSC_RPC_HANDLE lpScHandle
  31. )
  32. /*++
  33. Routine Description:
  34. Arguments:
  35. lpMachineName -
  36. lpDatabaseName -
  37. dwDesiredAccess -
  38. lpScHandle -
  39. Return Value:
  40. Note:
  41. --*/
  42. {
  43. DWORD status;
  44. LPWSTR lpDatabaseNameW = NULL;
  45. //
  46. // This parameter got us to the server side and is uninteresting
  47. // once we get here.
  48. //
  49. UNREFERENCED_PARAMETER(lpMachineName);
  50. //
  51. // Create a unicode version of lpDatabaseName
  52. //
  53. if (ARGUMENT_PRESENT(lpDatabaseName)) {
  54. if(!ScConvertToUnicode(&lpDatabaseNameW, lpDatabaseName)) {
  55. SC_LOG(ERROR,"ROpenSCManagerA:ScConvertToUnicode failed\n",0);
  56. return(ERROR_NOT_ENOUGH_MEMORY);
  57. }
  58. }
  59. status = ROpenSCManagerW (
  60. NULL,
  61. lpDatabaseNameW,
  62. dwDesiredAccess,
  63. lpScHandle);
  64. if (ARGUMENT_PRESENT(lpDatabaseName)) {
  65. LocalFree(lpDatabaseNameW);
  66. }
  67. return(status);
  68. }
  69. DWORD
  70. ROpenServiceA(
  71. IN SC_RPC_HANDLE hSCManager,
  72. IN LPSTR lpServiceName,
  73. IN DWORD dwDesiredAccess,
  74. OUT LPSC_RPC_HANDLE phService
  75. )
  76. /*++
  77. Routine Description:
  78. Returns a handle to the service. This handle is actually a pointer
  79. to a data structure that contains a pointer to the service record.
  80. Arguments:
  81. hSCManager - This is a handle to this service controller. It is an
  82. RPC context handle, and has allowed the request to get this far.
  83. lpServiceName - This is a pointer to a string containing the name of
  84. the service
  85. dwDesiredAccess - This is an access mask that contains a description
  86. of the access that is desired for this service.
  87. phService - This is a pointer to the location where the handle to the
  88. service is to be placed.
  89. Return Value:
  90. NO_ERROR - The operation was successful.
  91. ERROR_INVALID_HANDLE - The specified handle is invalid.
  92. ERROR_SERVICE_DOES_NOT_EXIST - The specified service does not exist
  93. in the database.
  94. ERROR_NOT_ENOUGH_MEMORY - The memory allocation for the handle structure
  95. failed.
  96. Note:
  97. --*/
  98. {
  99. DWORD status;
  100. LPWSTR lpServiceNameW;
  101. //
  102. // Create a unicode version of lpServiceName
  103. //
  104. if(!ScConvertToUnicode(&lpServiceNameW, lpServiceName)) {
  105. SC_LOG(ERROR,"ROpenServiceA:ScConvertToUnicode failed\n",0);
  106. return(ERROR_NOT_ENOUGH_MEMORY);
  107. }
  108. status = ROpenServiceW (
  109. hSCManager,
  110. lpServiceNameW,
  111. dwDesiredAccess,
  112. phService);
  113. LocalFree(lpServiceNameW);
  114. return(status);
  115. }
  116. DWORD
  117. RStartServiceA(
  118. IN SC_RPC_HANDLE hService,
  119. IN DWORD NumArgs,
  120. IN LPSTRING_PTRSA CmdArgs
  121. )
  122. /*++
  123. Routine Description:
  124. This function begins the execution of a service.
  125. Arguments:
  126. hService - A handle which is a pointer to a service handle structure.
  127. dwNumServiceArgs - This indicates the number of argument vectors.
  128. lpServiceArgVectors - This is a pointer to an array of string pointers.
  129. Return Value:
  130. NO_ERROR - The operation was completely successful.
  131. ERROR_ACCESS_DENIED - The specified handle was not opened with
  132. SERVICE_START access.
  133. ERROR_INVALID_HANDLE - The specified handle was invalid.
  134. ERROR_SERVICE_WAS_STARTED - An instance of the service is already running.
  135. ERROR_SERVICE_REQUEST_TIMEOUT - The service did not respond to the start
  136. request in a timely fashion.
  137. ERROR_SERVICE_NO_THREAD - A thread could not be created for the Win32
  138. service.
  139. ERROR_PATH_NOT_FOUND - The image file name could not be found in
  140. the configuration database (registry), or the image file name
  141. failed in a unicode/ansi conversion.
  142. --*/
  143. {
  144. DWORD status = NO_ERROR;
  145. LPWSTR *CmdArgsW = NULL;
  146. DWORD bufferSize=0;
  147. DWORD i;
  148. LPSTR *cmdArgs;
  149. if (NumArgs > 0)
  150. {
  151. //
  152. // If there are command args, create a unicode version of them.
  153. //
  154. if (CmdArgs == NULL)
  155. {
  156. return ERROR_INVALID_PARAMETER;
  157. }
  158. //
  159. // Allocate a buffer for the unicode command arg pointers.
  160. //
  161. bufferSize = NumArgs * sizeof(LPWSTR);
  162. CmdArgsW = (LPWSTR *)LocalAlloc(LMEM_ZEROINIT, (UINT) bufferSize);
  163. if (CmdArgsW == NULL)
  164. {
  165. SC_LOG(ERROR,"RStartServicesA: LocalAlloc Failed\n",0);
  166. return(ERROR_NOT_ENOUGH_MEMORY);
  167. }
  168. __try {
  169. //
  170. // For each command Arg, allocate a string and convert the
  171. // unicode version of the string into it.
  172. //
  173. cmdArgs = (LPSTR *)CmdArgs;
  174. for (i=0; i<NumArgs; i++)
  175. {
  176. if (cmdArgs[i] == NULL)
  177. {
  178. SC_LOG1(ERROR, "RStartServicesA: cmdArgs[%d] NULL!\n", i);
  179. status = ERROR_INVALID_PARAMETER;
  180. break;
  181. }
  182. if(!ScConvertToUnicode(&(CmdArgsW[i]), cmdArgs[i])) {
  183. SC_LOG(ERROR,
  184. "RStartServicesA: LocalAlloc (convert) Failed\n",0);
  185. status = ERROR_NOT_ENOUGH_MEMORY;
  186. break;
  187. }
  188. }
  189. }
  190. __except (EXCEPTION_EXECUTE_HANDLER) {
  191. status = GetExceptionCode();
  192. if (status != EXCEPTION_ACCESS_VIOLATION) {
  193. SC_LOG(ERROR,
  194. "RStartServicesA: Unexpected Exception 0x%lx\n",status);
  195. }
  196. }
  197. //
  198. // If any errors occured in the conversion process. Abort and
  199. // return the error to the caller.
  200. //
  201. if (status != NO_ERROR) {
  202. goto CleanExit;
  203. }
  204. }
  205. status = RStartServiceW(
  206. hService,
  207. NumArgs,
  208. (LPSTRING_PTRSW)CmdArgsW);
  209. CleanExit:
  210. if (NumArgs > 0) {
  211. //
  212. // If there were unicode versions of the arguments created for
  213. // this function, release the memory that was allocated.
  214. //
  215. for(i = 0; i < NumArgs; i++) {
  216. if (CmdArgsW[i] != NULL) {
  217. LocalFree(CmdArgsW[i]);
  218. }
  219. }
  220. LocalFree(CmdArgsW);
  221. }
  222. return(status);
  223. }
  224. DWORD
  225. REnumServicesStatusA (
  226. IN SC_RPC_HANDLE hSCManager,
  227. IN DWORD dwServiceType,
  228. IN DWORD dwServiceState,
  229. OUT PBYTE lpBuffer,
  230. IN DWORD cbBufSize,
  231. OUT LPDWORD pcbBytesNeeded,
  232. OUT LPDWORD lpServicesReturned,
  233. IN OUT LPDWORD lpResumeIndex OPTIONAL
  234. )
  235. /*++
  236. Routine Description:
  237. This function lists the services installed in the Service Controllers
  238. database. The status of each service is returned with the name of
  239. the service.
  240. Arguments:
  241. hSCManager - This is a handle to the service controller.
  242. dwServiceType - Value to select the type of services to enumerate.
  243. It must be one of the bitwise OR of the following values:
  244. SERVICE_WIN32 - enumerate Win32 services only.
  245. SERVICE_DRIVER - enumerate Driver services only.
  246. dwServiceState - Value so select the services to enumerate based on the
  247. running state. It must be one or the bitwise OR of the following
  248. values:
  249. SERVICE_ACTIVE - enumerate services that have started.
  250. SERVICE_INACTIVE - enumerate services that are stopped.
  251. lpBuffer - A pointer to a buffer to receive an array of enum status
  252. (or service) entries.
  253. cbBufSize - Size of the buffer in bytes pointed to by lpBuffer.
  254. pcbBytesNeeded - A pointer to a location where the number of bytes
  255. left (to be enumerated) is to be placed. This indicates to the
  256. caller how large the buffer must be in order to complete the
  257. enumeration with the next call.
  258. lpServicesReturned - A pointer to a variable to receive the number of
  259. of service entries returned.
  260. lpResumeIndex - A pointer to a variable which on input specifies the
  261. index of a service entry to begin enumeration. An index of 0
  262. indicates to start at the beginning. On output, if this function
  263. returns ERROR_MORE_DATA, the index returned is the next service
  264. entry to resume the enumeration. The returned index is 0 if this
  265. function returns a NO_ERROR.
  266. Return Value:
  267. NO_ERROR - The operation was successful.
  268. ERROR_MORE_DATA - Not all of the data in the active database could be
  269. returned due to the size of the user's buffer. pcbBytesNeeded
  270. contains the number of bytes required to get the remaining
  271. entries.
  272. ERROR_INVALID_PARAMETER - An illegal parameter value was passed in.
  273. (such as dwServiceType).
  274. ERROR_INVALID_HANDLE - The specified handle was invalid.
  275. Note:
  276. It is expected that the RPC Stub functions will find the following
  277. parameter problems:
  278. Bad pointers for lpBuffer, pcbReturned, pcbBytesNeeded,
  279. lpBuffer, ReturnedServerName, and lpResumeIndex.
  280. --*/
  281. {
  282. DWORD status;
  283. LPENUM_SERVICE_STATUS_WOW64 pEnumRec;
  284. LPWSTR pServiceName;
  285. LPWSTR pDisplayName;
  286. DWORD i;
  287. //
  288. // Initialize entries returned because we convert the buffer on
  289. // output based on the number of returned entries.
  290. //
  291. *lpServicesReturned = 0;
  292. status = REnumServicesStatusW (
  293. hSCManager,
  294. dwServiceType,
  295. dwServiceState,
  296. lpBuffer,
  297. cbBufSize,
  298. pcbBytesNeeded,
  299. lpServicesReturned,
  300. lpResumeIndex);
  301. if (*lpServicesReturned > 0)
  302. {
  303. //
  304. // Convert the returned unicode structures to Ansi.
  305. //
  306. pEnumRec = (LPENUM_SERVICE_STATUS_WOW64) lpBuffer;
  307. for (i = 0; i < *lpServicesReturned; i++)
  308. {
  309. //
  310. // Note: in these conversions, the pointers to the names are
  311. // stored as offsets at this point.
  312. //
  313. pServiceName = (LPWSTR) (lpBuffer + pEnumRec[i].dwServiceNameOffset);
  314. pDisplayName = (LPWSTR) (lpBuffer + pEnumRec[i].dwDisplayNameOffset);
  315. if (!ScConvertToAnsi((LPSTR) pServiceName, pServiceName))
  316. {
  317. SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
  318. status = ERROR_NOT_ENOUGH_MEMORY;
  319. *lpServicesReturned = 0;
  320. break;
  321. }
  322. //
  323. // Convert the Display Name.
  324. //
  325. if (!ScConvertToAnsi((LPSTR)pDisplayName, pDisplayName)) {
  326. SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
  327. status = ERROR_NOT_ENOUGH_MEMORY;
  328. *lpServicesReturned = 0;
  329. break;
  330. }
  331. }
  332. }
  333. return(status);
  334. }
  335. DWORD
  336. REnumServicesStatusExA (
  337. IN SC_RPC_HANDLE hSCManager,
  338. IN SC_ENUM_TYPE InfoLevel,
  339. IN DWORD dwServiceType,
  340. IN DWORD dwServiceState,
  341. OUT PBYTE lpBuffer,
  342. IN DWORD cbBufSize,
  343. OUT LPDWORD pcbBytesNeeded,
  344. OUT LPDWORD lpServicesReturned,
  345. IN OUT LPDWORD lpResumeIndex OPTIONAL,
  346. IN LPCSTR pszGroupNameAnsi
  347. )
  348. /*++
  349. Routine Description:
  350. This function is analogous to REnumServicesStatusA, with the data
  351. being enumerated being dependent upon the InfoLevel parameter
  352. Arguments:
  353. InfoLevel - An enumerated type that determines what service attributes
  354. are enumerated:
  355. SC_ENUM_ALL_INFO - Enumerates all the service information from
  356. REnumServicesStatusW plus the service's PID and flags
  357. pszGroupName - Only enumerate services belonging to the given group.
  358. If this parameter is the empty string, services not belonging to
  359. a group are enumerated. If this parameter is NULL, no attention
  360. is paid to group.
  361. Return Value:
  362. NO_ERROR - The operation was successful.
  363. ERROR_MORE_DATA - Not all of the data in the active database could be
  364. returned due to the size of the user's buffer. pcbBytesNeeded
  365. contains the number of bytes required to get the remaining
  366. entries.
  367. ERROR_INVALID_PARAMETER - An illegal parameter value was passed in.
  368. (such as dwServiceType).
  369. ERROR_INVALID_HANDLE - The specified handle was invalid.
  370. ERROR_INVALID_LEVEL - The specified InfoLevel is invalid
  371. Note:
  372. It is expected that the RPC Stub functions will find the following
  373. parameter problems:
  374. Bad pointers for lpBuffer, pcbReturned, pcbBytesNeeded,
  375. lpBuffer, ReturnedServerName, and lpResumeIndex.
  376. --*/
  377. {
  378. DWORD status;
  379. LPENUM_SERVICE_STATUS_PROCESS_WOW64 pEnumRec;
  380. LPWSTR pServiceName;
  381. LPWSTR pDisplayName;
  382. LPWSTR pszGroupName = NULL;
  383. DWORD i;
  384. //
  385. // Initialize entries returned because we convert the buffer on
  386. // output based on the number of returned entries.
  387. //
  388. *lpServicesReturned = 0;
  389. if (ARGUMENT_PRESENT(pszGroupNameAnsi)) {
  390. if (!ScConvertToUnicode(&pszGroupName, pszGroupNameAnsi)) {
  391. SC_LOG(ERROR,"EnumServicesStatusExA: ScConvertToUnicode failed\n",0);
  392. return ERROR_NOT_ENOUGH_MEMORY;
  393. }
  394. }
  395. status = REnumServicesStatusExW (
  396. hSCManager,
  397. InfoLevel,
  398. dwServiceType,
  399. dwServiceState,
  400. lpBuffer,
  401. cbBufSize,
  402. pcbBytesNeeded,
  403. lpServicesReturned,
  404. lpResumeIndex,
  405. (LPCWSTR)pszGroupName);
  406. if (*lpServicesReturned > 0)
  407. {
  408. //
  409. // Convert the returned unicode structures to Ansi.
  410. //
  411. pEnumRec = (LPENUM_SERVICE_STATUS_PROCESS_WOW64) lpBuffer;
  412. for (i = 0; i < *lpServicesReturned; i++) {
  413. //
  414. // Note: in these conversions, the pointers to the names are
  415. // stored as offsets at this point.
  416. //
  417. pServiceName = (LPWSTR) (lpBuffer + pEnumRec[i].dwServiceNameOffset);
  418. pDisplayName = (LPWSTR) (lpBuffer + pEnumRec[i].dwDisplayNameOffset);
  419. if (!ScConvertToAnsi((LPSTR)pServiceName, pServiceName)) {
  420. SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
  421. status = ERROR_NOT_ENOUGH_MEMORY;
  422. *lpServicesReturned = 0;
  423. break;
  424. }
  425. //
  426. // Convert the Display Name.
  427. //
  428. if (!ScConvertToAnsi((LPSTR)pDisplayName, pDisplayName)) {
  429. SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
  430. status = ERROR_NOT_ENOUGH_MEMORY;
  431. *lpServicesReturned = 0;
  432. break;
  433. }
  434. }
  435. }
  436. LocalFree(pszGroupName);
  437. return(status);
  438. }
  439. DWORD
  440. RChangeServiceConfigA(
  441. IN SC_RPC_HANDLE hService,
  442. IN DWORD dwServiceType,
  443. IN DWORD dwStartType,
  444. IN DWORD dwErrorControl,
  445. IN LPSTR lpBinaryPathName,
  446. IN LPSTR lpLoadOrderGroup,
  447. OUT LPDWORD lpdwTagId,
  448. IN LPBYTE lpDependencies,
  449. IN DWORD dwDependSize,
  450. IN LPSTR lpServiceStartName,
  451. IN LPBYTE EncryptedPassword,
  452. IN DWORD PasswordSize,
  453. IN LPSTR lpDisplayName
  454. )
  455. /*++
  456. Routine Description:
  457. Arguments:
  458. lpDependencies - A buffer of size dwDependSize which already contains
  459. Unicode strings.
  460. Return Value:
  461. Note:
  462. --*/
  463. {
  464. DWORD status;
  465. LPWSTR lpDisplayNameW = NULL;
  466. LPWSTR lpBinaryPathNameW = NULL;
  467. LPWSTR lpLoadOrderGroupW = NULL;
  468. LPWSTR lpServiceStartNameW = NULL;
  469. //
  470. // Create a unicode version of lpBinaryPathName
  471. //
  472. if (ARGUMENT_PRESENT(lpBinaryPathName)) {
  473. if(!ScConvertToUnicode(&lpBinaryPathNameW, lpBinaryPathName)) {
  474. SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
  475. status = ERROR_NOT_ENOUGH_MEMORY;
  476. goto CleanExit;
  477. }
  478. }
  479. //
  480. // Create a unicode version of lpLoadOrderGroup
  481. //
  482. if (ARGUMENT_PRESENT(lpLoadOrderGroup)) {
  483. if(!ScConvertToUnicode(&lpLoadOrderGroupW, lpLoadOrderGroup)) {
  484. SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
  485. status = ERROR_NOT_ENOUGH_MEMORY;
  486. goto CleanExit;
  487. }
  488. }
  489. //
  490. // Create a unicode version of lpServiceStartName
  491. //
  492. if (ARGUMENT_PRESENT(lpServiceStartName)) {
  493. if(!ScConvertToUnicode(&lpServiceStartNameW, lpServiceStartName)) {
  494. SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
  495. status = ERROR_NOT_ENOUGH_MEMORY;
  496. goto CleanExit;
  497. }
  498. }
  499. //
  500. // Create a unicode version of lpDisplayName
  501. //
  502. if (ARGUMENT_PRESENT(lpDisplayName)) {
  503. if(!ScConvertToUnicode(&lpDisplayNameW, lpDisplayName)) {
  504. SC_LOG(ERROR,"ChangeServiceConfigA:ScConvertToUnicode failed\n",0);
  505. status = ERROR_NOT_ENOUGH_MEMORY;
  506. goto CleanExit;
  507. }
  508. }
  509. //
  510. // Make the Unicode API Call
  511. //
  512. status = RChangeServiceConfigW(
  513. (SC_RPC_HANDLE)hService,
  514. dwServiceType,
  515. dwStartType,
  516. dwErrorControl,
  517. lpBinaryPathNameW,
  518. lpLoadOrderGroupW,
  519. lpdwTagId,
  520. lpDependencies,
  521. dwDependSize,
  522. lpServiceStartNameW,
  523. EncryptedPassword,
  524. PasswordSize,
  525. lpDisplayNameW);
  526. CleanExit:
  527. LocalFree(lpBinaryPathNameW);
  528. LocalFree(lpLoadOrderGroupW);
  529. LocalFree(lpServiceStartNameW);
  530. LocalFree(lpDisplayNameW);
  531. return(status);
  532. }
  533. DWORD
  534. RChangeServiceConfig2A(
  535. IN SC_RPC_HANDLE hService,
  536. IN SC_RPC_CONFIG_INFOA Info
  537. )
  538. /*++
  539. Routine Description:
  540. Arguments:
  541. Return Value:
  542. Note:
  543. --*/
  544. {
  545. DWORD status = NO_ERROR;
  546. //
  547. // Make a Unicode version of the arguments to pass to the Unicode function
  548. //
  549. union
  550. {
  551. SERVICE_DESCRIPTIONW sd;
  552. SERVICE_FAILURE_ACTIONSW sfa;
  553. } Buffer;
  554. SC_RPC_CONFIG_INFOW InfoW = { Info.dwInfoLevel, &Buffer.sd };
  555. switch (Info.dwInfoLevel)
  556. {
  557. case SERVICE_CONFIG_DESCRIPTION:
  558. Buffer.sd.lpDescription = NULL;
  559. if (Info.psd == NULL)
  560. {
  561. InfoW.psd = NULL;
  562. break;
  563. }
  564. if (Info.psd->lpDescription != NULL)
  565. {
  566. if (!ScConvertToUnicode(&Buffer.sd.lpDescription,
  567. Info.psd->lpDescription))
  568. {
  569. SC_LOG0(ERROR, "RChangeServiceConfig2A: ScConvertToUnicode failed\n");
  570. status = ERROR_NOT_ENOUGH_MEMORY;
  571. goto CleanExit;
  572. }
  573. }
  574. break;
  575. case SERVICE_CONFIG_FAILURE_ACTIONS:
  576. RtlCopyMemory(&Buffer.sfa, Info.psfa, sizeof(SERVICE_FAILURE_ACTIONS));
  577. Buffer.sfa.lpRebootMsg = NULL;
  578. Buffer.sfa.lpCommand = NULL;
  579. if (Info.psfa == NULL)
  580. {
  581. InfoW.psfa = NULL;
  582. break;
  583. }
  584. if (Info.psfa->lpRebootMsg != NULL)
  585. {
  586. if (!ScConvertToUnicode(&Buffer.sfa.lpRebootMsg,
  587. Info.psfa->lpRebootMsg))
  588. {
  589. SC_LOG0(ERROR, "RChangeServiceConfig2A: ScConvertToUnicode failed\n");
  590. status = ERROR_NOT_ENOUGH_MEMORY;
  591. goto CleanExit;
  592. }
  593. }
  594. if (Info.psfa->lpCommand != NULL)
  595. {
  596. if (!ScConvertToUnicode(&Buffer.sfa.lpCommand,
  597. Info.psfa->lpCommand))
  598. {
  599. SC_LOG0(ERROR, "RChangeServiceConfig2A: ScConvertToUnicode failed\n");
  600. status = ERROR_NOT_ENOUGH_MEMORY;
  601. goto CleanExit;
  602. }
  603. }
  604. break;
  605. }
  606. //
  607. // Call the Unicode function
  608. //
  609. status = RChangeServiceConfig2W(hService,
  610. InfoW);
  611. CleanExit:
  612. //
  613. // Free the temporary Unicode strings
  614. //
  615. switch (Info.dwInfoLevel)
  616. {
  617. case SERVICE_CONFIG_DESCRIPTION:
  618. LocalFree(Buffer.sd.lpDescription);
  619. break;
  620. case SERVICE_CONFIG_FAILURE_ACTIONS:
  621. LocalFree(Buffer.sfa.lpRebootMsg);
  622. LocalFree(Buffer.sfa.lpCommand);
  623. break;
  624. }
  625. return status;
  626. }
  627. DWORD
  628. RCreateServiceA(
  629. IN SC_RPC_HANDLE hSCManager,
  630. IN LPSTR lpServiceName,
  631. IN LPSTR lpDisplayName,
  632. IN DWORD dwDesiredAccess,
  633. IN DWORD dwServiceType,
  634. IN DWORD dwStartType,
  635. IN DWORD dwErrorControl,
  636. IN LPSTR lpBinaryPathName,
  637. IN LPSTR lpLoadOrderGroup,
  638. OUT LPDWORD lpdwTagId,
  639. IN LPBYTE lpDependencies,
  640. IN DWORD dwDependSize,
  641. IN LPSTR lpServiceStartName,
  642. IN LPBYTE EncryptedPassword,
  643. IN DWORD PasswordSize,
  644. IN OUT LPSC_RPC_HANDLE lpServiceHandle
  645. )
  646. /*++
  647. Routine Description:
  648. Arguments:
  649. lpDependencies - A buffer of size dwDependSize which already contains
  650. Unicode strings.
  651. Return Value:
  652. Note:
  653. --*/
  654. {
  655. DWORD status;
  656. LPWSTR lpServiceNameW = NULL;
  657. LPWSTR lpDisplayNameW = NULL;
  658. LPWSTR lpBinaryPathNameW = NULL;
  659. LPWSTR lpLoadOrderGroupW = NULL;
  660. LPWSTR lpServiceStartNameW = NULL;
  661. //
  662. // Create a unicode version of lpServiceName
  663. //
  664. if (ARGUMENT_PRESENT(lpServiceName)) {
  665. if(!ScConvertToUnicode(&lpServiceNameW, lpServiceName)) {
  666. SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
  667. status = ERROR_NOT_ENOUGH_MEMORY;
  668. goto CleanExit;
  669. }
  670. }
  671. //
  672. // Create a unicode version of lpDisplayName
  673. //
  674. if (ARGUMENT_PRESENT(lpDisplayName)) {
  675. if(!ScConvertToUnicode(&lpDisplayNameW, lpDisplayName)) {
  676. SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
  677. status = ERROR_NOT_ENOUGH_MEMORY;
  678. goto CleanExit;
  679. }
  680. }
  681. //
  682. // Create a unicode version of lpBinaryPathName
  683. //
  684. if (ARGUMENT_PRESENT(lpBinaryPathName)) {
  685. if(!ScConvertToUnicode(&lpBinaryPathNameW, lpBinaryPathName)) {
  686. SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
  687. status = ERROR_NOT_ENOUGH_MEMORY;
  688. goto CleanExit;
  689. }
  690. }
  691. //
  692. // Create a unicode version of lpLoadOrderGroup
  693. //
  694. if (ARGUMENT_PRESENT(lpLoadOrderGroup)) {
  695. if(!ScConvertToUnicode(&lpLoadOrderGroupW, lpLoadOrderGroup)) {
  696. SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
  697. status = ERROR_NOT_ENOUGH_MEMORY;
  698. goto CleanExit;
  699. }
  700. }
  701. //
  702. // Create a unicode version of lpServiceStartName
  703. //
  704. if (ARGUMENT_PRESENT(lpServiceStartName)) {
  705. if(!ScConvertToUnicode(&lpServiceStartNameW, lpServiceStartName)) {
  706. SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
  707. status = ERROR_NOT_ENOUGH_MEMORY;
  708. goto CleanExit;
  709. }
  710. }
  711. //
  712. // Make the Unicode API Call
  713. //
  714. status = RCreateServiceW (
  715. (SC_RPC_HANDLE)hSCManager,
  716. lpServiceNameW,
  717. lpDisplayNameW,
  718. dwDesiredAccess,
  719. dwServiceType,
  720. dwStartType,
  721. dwErrorControl,
  722. lpBinaryPathNameW,
  723. lpLoadOrderGroupW,
  724. lpdwTagId,
  725. lpDependencies,
  726. dwDependSize,
  727. lpServiceStartNameW,
  728. EncryptedPassword,
  729. PasswordSize,
  730. lpServiceHandle);
  731. CleanExit:
  732. LocalFree(lpServiceNameW);
  733. LocalFree(lpDisplayNameW);
  734. LocalFree(lpBinaryPathNameW);
  735. LocalFree(lpLoadOrderGroupW);
  736. LocalFree(lpServiceStartNameW);
  737. return(status);
  738. }
  739. DWORD
  740. REnumDependentServicesA(
  741. IN SC_RPC_HANDLE hService,
  742. IN DWORD dwServiceState,
  743. OUT LPBYTE lpBuffer,
  744. IN DWORD cbBufSize,
  745. OUT LPDWORD pcbBytesNeeded,
  746. OUT LPDWORD lpServicesReturned
  747. )
  748. /*++
  749. Routine Description:
  750. Arguments:
  751. Return Value:
  752. Note:
  753. --*/
  754. {
  755. DWORD status;
  756. LPENUM_SERVICE_STATUS_WOW64 pEnumRec;
  757. LPWSTR pServiceName;
  758. LPWSTR pDisplayName;
  759. DWORD i;
  760. //
  761. // Initialize entries returned because we convert the buffer on
  762. // output based on the number of returned entries.
  763. //
  764. *lpServicesReturned = 0;
  765. status = REnumDependentServicesW(
  766. hService,
  767. dwServiceState,
  768. lpBuffer,
  769. cbBufSize,
  770. pcbBytesNeeded,
  771. lpServicesReturned);
  772. if (*lpServicesReturned > 0) {
  773. //
  774. // Convert the returned unicode structures to Ansi.
  775. //
  776. pEnumRec = (LPENUM_SERVICE_STATUS_WOW64) lpBuffer;
  777. for (i=0; i<*lpServicesReturned; i++) {
  778. //
  779. // Note: in these conversions, the pointers to the names are
  780. // stored as offsets at this point.
  781. //
  782. pServiceName = (LPWSTR) (lpBuffer + (DWORD_PTR)(pEnumRec[i].dwServiceNameOffset));
  783. pDisplayName = (LPWSTR) (lpBuffer + (DWORD_PTR)(pEnumRec[i].dwDisplayNameOffset));
  784. if (!ScConvertToAnsi((LPSTR)pServiceName, pServiceName)) {
  785. SC_LOG(ERROR,"REnumDependendServicesA:ScConvertToAnsi failed\n",0);
  786. status = ERROR_NOT_ENOUGH_MEMORY;
  787. *lpServicesReturned = 0;
  788. break;
  789. }
  790. //
  791. // Convert the Display Name.
  792. //
  793. if (!ScConvertToAnsi((LPSTR)pDisplayName, pDisplayName)) {
  794. SC_LOG(ERROR,"REnumServicesStatusA:ScConvertToAnsi failed\n",0);
  795. status = ERROR_NOT_ENOUGH_MEMORY;
  796. *lpServicesReturned = 0;
  797. break;
  798. }
  799. }
  800. }
  801. return(status);
  802. }
  803. DWORD
  804. RQueryServiceConfigA(
  805. IN SC_RPC_HANDLE hService,
  806. OUT LPQUERY_SERVICE_CONFIGA lpServiceConfig,
  807. IN DWORD cbBufSize,
  808. OUT LPDWORD pcbBytesNeeded
  809. )
  810. /*++
  811. Routine Description:
  812. Arguments:
  813. Return Value:
  814. Note:
  815. --*/
  816. {
  817. DWORD status;
  818. //
  819. // Call the Unicode version of the API.
  820. //
  821. status = RQueryServiceConfigW(
  822. (SC_RPC_HANDLE)hService,
  823. (LPQUERY_SERVICE_CONFIGW)lpServiceConfig,
  824. cbBufSize,
  825. pcbBytesNeeded);
  826. //
  827. // If successful, convert the QUERY_SERVICE_CONFIG structure to
  828. // ansi.
  829. //
  830. if (status == NO_ERROR) {
  831. //
  832. // Convert lpBinaryPathName to Ansi
  833. //
  834. if (lpServiceConfig->lpBinaryPathName != NULL) {
  835. if(!ScConvertToAnsi(
  836. lpServiceConfig->lpBinaryPathName,
  837. ((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpBinaryPathName)) {
  838. SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
  839. status = ERROR_NOT_ENOUGH_MEMORY;
  840. }
  841. }
  842. //
  843. // Convert lpDisplayName to Ansi
  844. //
  845. if (lpServiceConfig->lpDisplayName != NULL) {
  846. if(!ScConvertToAnsi(
  847. lpServiceConfig->lpDisplayName,
  848. ((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpDisplayName)) {
  849. SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
  850. status = ERROR_NOT_ENOUGH_MEMORY;
  851. }
  852. }
  853. //
  854. // Convert lpLoadOrderGroup to Ansi
  855. //
  856. if (lpServiceConfig->lpLoadOrderGroup != NULL) {
  857. if(!ScConvertToAnsi(
  858. lpServiceConfig->lpLoadOrderGroup,
  859. ((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpLoadOrderGroup)) {
  860. SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
  861. status = ERROR_NOT_ENOUGH_MEMORY;
  862. }
  863. }
  864. //
  865. // Convert lpDependencies to Ansi
  866. //
  867. if (lpServiceConfig->lpDependencies != NULL) {
  868. if(!ScConvertToAnsi(
  869. lpServiceConfig->lpDependencies,
  870. ((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpDependencies)) {
  871. SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
  872. status = ERROR_NOT_ENOUGH_MEMORY;
  873. }
  874. }
  875. //
  876. // Convert lpServiceStartName to Ansi
  877. //
  878. if (lpServiceConfig->lpServiceStartName != NULL) {
  879. if(!ScConvertToAnsi(
  880. lpServiceConfig->lpServiceStartName,
  881. ((LPQUERY_SERVICE_CONFIGW)lpServiceConfig)->lpServiceStartName)) {
  882. SC_LOG(ERROR,"RQueryServiceConfigA:ScConvertToAnsi failed\n",0);
  883. status = ERROR_NOT_ENOUGH_MEMORY;
  884. }
  885. }
  886. }
  887. return(status);
  888. }
  889. DWORD
  890. RQueryServiceConfig2A(
  891. IN SC_RPC_HANDLE hService,
  892. IN DWORD dwInfoLevel,
  893. OUT LPBYTE lpBuffer,
  894. IN DWORD cbBufSize,
  895. OUT LPDWORD pcbBytesNeeded
  896. )
  897. /*++
  898. Routine Description:
  899. Arguments:
  900. Return Value:
  901. Note:
  902. --*/
  903. {
  904. DWORD status;
  905. DWORD StringOffset;
  906. //
  907. // Call the Unicode version of the API, using the same buffer.
  908. // Then convert the strings in the buffer to Ansi.
  909. //
  910. status = RQueryServiceConfig2W(
  911. hService,
  912. dwInfoLevel,
  913. lpBuffer,
  914. cbBufSize,
  915. pcbBytesNeeded
  916. );
  917. if (status == NO_ERROR)
  918. {
  919. switch (dwInfoLevel)
  920. {
  921. case SERVICE_CONFIG_DESCRIPTION:
  922. {
  923. StringOffset = ((LPSERVICE_DESCRIPTION_WOW64) lpBuffer)->dwDescriptionOffset;
  924. if (StringOffset != 0)
  925. {
  926. if(!ScConvertToAnsi(
  927. (LPSTR) (lpBuffer + StringOffset),
  928. (LPWSTR) (lpBuffer + StringOffset)
  929. ))
  930. {
  931. SC_LOG0(ERROR,"RQueryServiceConfig2A:ScConvertToAnsi failed\n");
  932. status = ERROR_NOT_ENOUGH_MEMORY;
  933. }
  934. }
  935. }
  936. break;
  937. case SERVICE_CONFIG_FAILURE_ACTIONS:
  938. {
  939. StringOffset = ((LPSERVICE_FAILURE_ACTIONS_WOW64) lpBuffer)->dwRebootMsgOffset;
  940. if (StringOffset != 0)
  941. {
  942. if(!ScConvertToAnsi(
  943. (LPSTR) (lpBuffer + StringOffset),
  944. (LPWSTR) (lpBuffer + StringOffset)
  945. ))
  946. {
  947. SC_LOG0(ERROR,"RQueryServiceConfig2A:ScConvertToAnsi failed\n");
  948. status = ERROR_NOT_ENOUGH_MEMORY;
  949. break;
  950. }
  951. }
  952. StringOffset = ((LPSERVICE_FAILURE_ACTIONS_WOW64) lpBuffer)->dwCommandOffset;
  953. if (StringOffset != 0)
  954. {
  955. if(!ScConvertToAnsi(
  956. (LPSTR) (lpBuffer + StringOffset),
  957. (LPWSTR) (lpBuffer + StringOffset)
  958. ))
  959. {
  960. SC_LOG0(ERROR,"RQueryServiceConfig2A:ScConvertToAnsi failed\n");
  961. status = ERROR_NOT_ENOUGH_MEMORY;
  962. }
  963. }
  964. }
  965. break;
  966. default:
  967. SC_ASSERT(0);
  968. break;
  969. }
  970. }
  971. return status;
  972. }
  973. DWORD
  974. RQueryServiceLockStatusA(
  975. IN SC_RPC_HANDLE hSCManager,
  976. OUT LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
  977. IN DWORD cbBufSize,
  978. OUT LPDWORD pcbBytesNeeded
  979. )
  980. /*++
  981. Routine Description:
  982. Arguments:
  983. Return Value:
  984. Note:
  985. --*/
  986. {
  987. DWORD status;
  988. //
  989. // Call the Unicode version of the API
  990. //
  991. status = RQueryServiceLockStatusW(
  992. (SC_RPC_HANDLE)hSCManager,
  993. (LPQUERY_SERVICE_LOCK_STATUSW)lpLockStatus,
  994. cbBufSize,
  995. pcbBytesNeeded
  996. );
  997. //
  998. // If successful, convert the QUERY_SERVICE_LOCK_STATUS structure to
  999. // ansi.
  1000. //
  1001. if (status == NO_ERROR) {
  1002. //
  1003. // Convert lpLockOwner to Ansi
  1004. //
  1005. if (lpLockStatus->lpLockOwner != NULL) {
  1006. if(!ScConvertToAnsi(
  1007. lpLockStatus->lpLockOwner,
  1008. ((LPQUERY_SERVICE_LOCK_STATUSW)lpLockStatus)->lpLockOwner)) {
  1009. SC_LOG(ERROR,"RQueryServiceLockStatusA:ScConvertToAnsi failed\n",0);
  1010. status = ERROR_NOT_ENOUGH_MEMORY;
  1011. }
  1012. }
  1013. }
  1014. return(status);
  1015. }
  1016. DWORD
  1017. RGetServiceDisplayNameA(
  1018. SC_RPC_HANDLE hSCManager,
  1019. LPSTR lpServiceName,
  1020. LPSTR lpDisplayName,
  1021. LPDWORD lpcchBuffer
  1022. )
  1023. /*++
  1024. Routine Description:
  1025. This function returns the display name for a service that is identified
  1026. by its key name (ServiceName).
  1027. Arguments:
  1028. hSCManager - This is the handle to the Service Controller Manager that
  1029. is expected to return the display name.
  1030. lpServiceName - This is the ServiceName (which is actually a key
  1031. name) that identifies the service.
  1032. lpDisplayName - This is a pointer to a buffer that is to receive the
  1033. DisplayName string.
  1034. lpcchBuffer - This is a pointer to the size (in characters) of the
  1035. buffer that is to receive the DisplayName string. If the buffer
  1036. is not large enough to receive the entire string, then the required
  1037. buffer size is returned in this location. (NOTE: Ansi Characters,
  1038. including DBCS, are assumed to be 8 bits).
  1039. Return Value:
  1040. --*/
  1041. {
  1042. DWORD status;
  1043. LPWSTR lpServiceNameW = NULL;
  1044. DWORD numChars = 0;
  1045. DWORD numBytes = 0;
  1046. LPSTR tempBuffer=NULL;
  1047. //
  1048. // Create a unicode version of lpServiceName
  1049. //
  1050. if (ARGUMENT_PRESENT(lpServiceName)) {
  1051. if(!ScConvertToUnicode(&lpServiceNameW, lpServiceName)) {
  1052. SC_LOG(ERROR,"RCreateServiceA:ScConvertToUnicode failed\n",0);
  1053. status = ERROR_NOT_ENOUGH_MEMORY;
  1054. goto CleanExit;
  1055. }
  1056. }
  1057. //
  1058. // Because of DBCS, we can't predict what the proper buffer size should
  1059. // be. So we allocate a temporary buffer that will hold as many
  1060. // unicode characters as the original buffer would hold single byte
  1061. // characters.
  1062. //
  1063. numChars = *lpcchBuffer;
  1064. numBytes = (*lpcchBuffer) * sizeof(WCHAR);
  1065. tempBuffer = (LPSTR) LocalAlloc(LMEM_FIXED, numBytes);
  1066. if (tempBuffer == NULL)
  1067. {
  1068. status = GetLastError();
  1069. goto CleanExit;
  1070. }
  1071. //
  1072. // Make the Unicode API Call
  1073. //
  1074. status = RGetServiceDisplayNameW (
  1075. hSCManager,
  1076. lpServiceNameW,
  1077. (LPWSTR) tempBuffer,
  1078. &numChars);
  1079. if (status == NO_ERROR)
  1080. {
  1081. //
  1082. // Convert the returned Unicode string and string size back to
  1083. // ansi.
  1084. //
  1085. if (!ScConvertToAnsi(tempBuffer, (LPWSTR) tempBuffer)) {
  1086. SC_LOG0(ERROR, "RGetServiceDisplayNameA: ConvertToAnsi Failed\n");
  1087. }
  1088. numBytes = (DWORD) strlen(tempBuffer);
  1089. if ((numBytes+1) > *lpcchBuffer)
  1090. {
  1091. status = ERROR_INSUFFICIENT_BUFFER;
  1092. *lpcchBuffer = numBytes;
  1093. }
  1094. else
  1095. {
  1096. strcpy (lpDisplayName, tempBuffer);
  1097. }
  1098. }
  1099. else if (status == ERROR_INSUFFICIENT_BUFFER)
  1100. {
  1101. //
  1102. // Adjust the required buffer size for ansi.
  1103. //
  1104. *lpcchBuffer = numChars * sizeof(WCHAR);
  1105. }
  1106. CleanExit:
  1107. //
  1108. // Free up any resources that were allocated by this function.
  1109. //
  1110. LocalFree(tempBuffer);
  1111. LocalFree(lpServiceNameW);
  1112. return(status);
  1113. }
  1114. DWORD
  1115. RGetServiceKeyNameA(
  1116. SC_RPC_HANDLE hSCManager,
  1117. LPSTR lpDisplayName,
  1118. LPSTR lpServiceName,
  1119. LPDWORD lpcchBuffer
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Arguments:
  1124. Return Value:
  1125. --*/
  1126. {
  1127. DWORD status;
  1128. LPWSTR lpDisplayNameW = NULL;
  1129. DWORD numChars = 0;
  1130. DWORD numBytes = 0;
  1131. LPSTR tempBuffer=NULL;
  1132. //
  1133. // Create a unicode version of lpDisplayName
  1134. //
  1135. if (ARGUMENT_PRESENT(lpDisplayName))
  1136. {
  1137. if(!ScConvertToUnicode(&lpDisplayNameW, lpDisplayName))
  1138. {
  1139. SC_LOG(ERROR,"RGetServiceKeyNameA:ScConvertToUnicode failed\n",0);
  1140. status = ERROR_NOT_ENOUGH_MEMORY;
  1141. goto CleanExit;
  1142. }
  1143. }
  1144. //
  1145. // Because of DBCS, we can't predict what the proper buffer size should
  1146. // be. So we allocate a temporary buffer that will hold as many
  1147. // unicode characters as the original buffer would hold single byte
  1148. // characters.
  1149. //
  1150. numChars = *lpcchBuffer;
  1151. numBytes = (*lpcchBuffer) * sizeof(WCHAR);
  1152. tempBuffer = (LPSTR) LocalAlloc(LMEM_FIXED, numBytes);
  1153. if (tempBuffer == NULL)
  1154. {
  1155. status = GetLastError();
  1156. goto CleanExit;
  1157. }
  1158. //
  1159. // Make the Unicode API Call
  1160. //
  1161. status = RGetServiceKeyNameW (
  1162. hSCManager,
  1163. lpDisplayNameW,
  1164. (LPWSTR)tempBuffer,
  1165. &numChars);
  1166. if (status == NO_ERROR)
  1167. {
  1168. //
  1169. // Convert the returned Unicode string and string size back to
  1170. // ansi.
  1171. //
  1172. if (!ScConvertToAnsi(tempBuffer, (LPWSTR)tempBuffer))
  1173. {
  1174. SC_LOG0(ERROR, "RGetServiceKeyNameA: ConvertToAnsi Failed\n");
  1175. }
  1176. numBytes = (DWORD) strlen(tempBuffer);
  1177. if ((numBytes+1) > *lpcchBuffer)
  1178. {
  1179. status = ERROR_INSUFFICIENT_BUFFER;
  1180. *lpcchBuffer = numBytes;
  1181. }
  1182. else
  1183. {
  1184. strcpy (lpServiceName, tempBuffer);
  1185. }
  1186. }
  1187. else if (status == ERROR_INSUFFICIENT_BUFFER)
  1188. {
  1189. //
  1190. // Adjust the required buffer size for ansi.
  1191. //
  1192. *lpcchBuffer = numChars * sizeof(WCHAR);
  1193. }
  1194. CleanExit:
  1195. //
  1196. // Free up any resources that were allocated by this function.
  1197. //
  1198. LocalFree(tempBuffer);
  1199. LocalFree(lpDisplayNameW);
  1200. return(status);
  1201. }