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.

604 lines
17 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. SvcStub.c (was scstub.c)
  5. Abstract:
  6. These are the Service Controller API RPC client stubs.
  7. These stubs contain RPC work-around code due to the fact that RPC
  8. does not support unions yet. Therefore, a remote entry point must be
  9. created for every info-level. This results in messy looking switch
  10. statements that are used to determine which entry point to call.
  11. These switch statements include default paths that can currently cause
  12. an error. When unions are available, the case statements will be
  13. removed, and this side of the API will not make any assumptions as to
  14. what a valid info level is for a given API.
  15. Author:
  16. Dan Lafferty (danl) 06-Feb-1991
  17. Environment:
  18. User Mode - Win32
  19. Revision History:
  20. 06-Feb-1991 Danl
  21. Created
  22. 12-Sep-1991 JohnRo
  23. Downlevel NetService APIs.
  24. 06-Nov-1991 JohnRo
  25. RAID 4186: Fix assert in RxNetShareAdd and other MIPS problems.
  26. Use NetpRpcStatusToApiStatus, not NetpNtStatusToApiStatus.
  27. Make sure API name is in every debug message.
  28. 08-Nov-1991 JohnRo
  29. RAID 4186: assert in RxNetShareAdd and other DLL stub problems.
  30. 30-Mar-1992 JohnRo
  31. Extracted DanL's code from /nt/private project back to NET project.
  32. 29-Apr-1992 JohnRo
  33. Use FORMAT_ equates where possible.
  34. 08-May-1992 JohnRo
  35. Translate service names on the fly.
  36. 14-May-1992 JohnRo
  37. winsvc.h and related file cleanup.
  38. 06-Aug-1992 JohnRo
  39. RAID 3021: NetService APIs don't always translate svc names.
  40. 09-Sep-1992 JohnRo
  41. RAID 1090: net start/stop "" causes assertion.
  42. Oops, NetServiceControl forgot to translate one more svc name.
  43. 05-Nov-1992 JohnRo
  44. RAID 7780: Corrected error code for invalid level.
  45. Also fixed overactive assert in NetServiceEnum with no services.
  46. Also fixed rare memory leaks.
  47. --*/
  48. //
  49. // INCLUDES
  50. //
  51. #define NOSERVICE // Avoid <winsvc.h> vs. <lmsvc.h> conflicts.
  52. #include <windows.h> // DWORD, etc.
  53. #include <lmcons.h> // NET_API_STATUS
  54. #include <rpcutil.h> // NetRpc utils, GENERIC_ENUM_STRUC, etc.
  55. #include <netdebug.h> // Needed by NetRpc.h; FORMAT_ equates.
  56. #include <lmapibuf.h> // NetApiBufferAllocate(), etc.
  57. #include <lmerr.h> // NetError codes
  58. #include <lmremutl.h> // NetRemoteComputerSupports(), SUPPORTS_RPC
  59. #include <lmsvc.h>
  60. #include <rxsvc.h> // RxNetService routines.
  61. #include <netlib.h> // NetpTranslateServiceName().
  62. #include <svcdebug.h> // SCC_LOG
  63. #include <svcmap.h> // MapService() routines.
  64. //
  65. // Globals
  66. //
  67. #ifdef SC_DEBUG
  68. DWORD SvcctrlDebugLevel = DEBUG_ALL;
  69. #else
  70. DWORD SvcctrlDebugLevel = DEBUG_ERROR;
  71. #endif
  72. DBGSTATIC BOOL
  73. MachineSupportsNt(
  74. IN LPWSTR UncServerName OPTIONAL
  75. );
  76. NET_API_STATUS NET_API_FUNCTION
  77. NetServiceControl (
  78. IN LPCWSTR servername OPTIONAL,
  79. IN LPCWSTR service,
  80. IN DWORD opcode,
  81. IN DWORD arg,
  82. OUT LPBYTE *bufptr
  83. )
  84. /*++
  85. Routine Description:
  86. This is the DLL entrypoint for NetServiceControl.
  87. Arguments:
  88. servername - Pointer to a string containing the name of the computer
  89. that is to execute the API function.
  90. service - Pointer to a string containing the name of the service
  91. that is to receive the control request.
  92. opcode - The control request code.
  93. arg - An additional (user defined) code that will be passed to the
  94. service.
  95. bufptr - pointer to a location where the service status is to
  96. be returned. If this pointer is invalid, it will be set to NULL
  97. upon return.
  98. Return Value:
  99. The returned InfoStruct2 structure is valid as long as the returned
  100. error is NOT NERR_ServiceNotInstalled or NERR_ServiceBadServiceName.
  101. NERR_Success - The operation was successful.
  102. NERR_InternalError - LocalAlloc or TransactNamedPipe failed, or
  103. TransactNamedPipe returned fewer bytes than expected.
  104. NERR_ServiceNotInstalled - The service record was not found in the
  105. installed list.
  106. NERR_BadServiceName - The service name pointer was NULL.
  107. NERR_ServiceCtlTimeout - The service did not respond with a status
  108. message within the fixed timeout limit (RESPONSE_WAIT_TIMEOUT).
  109. NERR_ServiceKillProcess - The service process had to be killed because
  110. it wouldn't terminate when requested.
  111. NERR_ServiceNotCtrl - The service cannot accept control messages.
  112. The install state indicates that start-up or shut-down is pending.
  113. NERR_ServiceCtrlNotValid - The request is not valid for this service.
  114. For instance, a PAUSE request is not valid for a service that
  115. lists itself as NOT_PAUSABLE.
  116. ERROR_ACCESS_DENIED - This is a status response from the service
  117. security check.
  118. --*/
  119. {
  120. NET_API_STATUS apiStatus;
  121. LPWSTR translatedServiceName;
  122. LPBYTE untranslatedBuffer = NULL;
  123. if (MachineSupportsNt( (LPWSTR) servername )) {
  124. apiStatus = NetpTranslateServiceName(
  125. (LPWSTR) service, // untranslated.
  126. TRUE, // yes, we want new style name
  127. & translatedServiceName );
  128. NetpAssert( apiStatus == NO_ERROR );
  129. apiStatus = MapServiceControl (
  130. (LPWSTR) servername,
  131. (LPWSTR) service,
  132. opcode,
  133. arg,
  134. & untranslatedBuffer);
  135. } else {
  136. apiStatus = NetpTranslateServiceName(
  137. (LPWSTR) service, // untranslated.
  138. FALSE, // no, we don't want new style name
  139. & translatedServiceName );
  140. NetpAssert( apiStatus == NO_ERROR );
  141. //
  142. // Call downlevel...
  143. //
  144. apiStatus = RxNetServiceControl(
  145. (LPWSTR) servername,
  146. translatedServiceName,
  147. opcode,
  148. arg,
  149. & untranslatedBuffer);
  150. }
  151. //
  152. // Translate service name in returned buffer.
  153. //
  154. if (apiStatus == NO_ERROR) {
  155. NetpAssert( untranslatedBuffer != NULL );
  156. apiStatus = NetpTranslateNamesInServiceArray(
  157. 2, // level 2 by definition
  158. untranslatedBuffer,
  159. 1, // only one entry
  160. TRUE, // yes, caller wants new style names
  161. (LPVOID *) (LPVOID) bufptr);
  162. }
  163. if (untranslatedBuffer != NULL) {
  164. (VOID) NetApiBufferFree( untranslatedBuffer );
  165. }
  166. return(apiStatus);
  167. }
  168. NET_API_STATUS NET_API_FUNCTION
  169. NetServiceEnum (
  170. IN LPCWSTR servername OPTIONAL,
  171. IN DWORD level,
  172. OUT LPBYTE *bufptr,
  173. IN DWORD prefmaxlen,
  174. OUT LPDWORD entriesread,
  175. OUT LPDWORD totalentries,
  176. IN OUT LPDWORD resume_handle OPTIONAL
  177. )
  178. /*++
  179. Routine Description:
  180. This is the DLL entrypoint for NetSeviceEnum.
  181. Arguments:
  182. servername - Pointer to a string containing the name of the computer
  183. that is to execute the API function.
  184. level - This indicates the level of information that is desired.
  185. bufptr - A pointer to the location where the pointer to the returned
  186. array of info structures is to be placed.
  187. prefmaxlen - Indicates a maximum size limit that the caller will allow
  188. for the return buffer.
  189. entriesread - A pointer to the location where the number of entries
  190. (data structures)read is to be returned.
  191. totalentries - A pointer to the location which upon return indicates
  192. the total number of entries in the "active" database.
  193. resumehandle - Pointer to a value that indicates where to resume
  194. enumerating data.
  195. Return Value:
  196. Nerr_Success - The operation was successful.
  197. ERROR_MORE_DATA - Not all of the data in the active database could be
  198. returned.
  199. ERROR_INVALID_LEVEL - An illegal info Level was passed in.
  200. Note:
  201. --*/
  202. {
  203. NET_API_STATUS apiStatus;
  204. LPBYTE untranslatedBuffer = NULL;
  205. if (MachineSupportsNt( (LPWSTR) servername )) {
  206. apiStatus = MapServiceEnum (
  207. (LPWSTR) servername,
  208. level,
  209. & untranslatedBuffer,
  210. prefmaxlen,
  211. entriesread,
  212. totalentries,
  213. resume_handle);
  214. } else {
  215. //
  216. // Call downlevel...
  217. //
  218. apiStatus = RxNetServiceEnum(
  219. (LPWSTR) servername,
  220. level,
  221. & untranslatedBuffer,
  222. prefmaxlen,
  223. entriesread,
  224. totalentries,
  225. resume_handle);
  226. }
  227. //
  228. // Translate service names in returned buffer.
  229. //
  230. if ( (apiStatus == NO_ERROR) || (apiStatus == ERROR_MORE_DATA) ) {
  231. if ( (*entriesread) > 0 ) { // One or more services returned.
  232. NetpAssert( untranslatedBuffer != NULL );
  233. NetpAssert( (*totalentries) > 0 );
  234. apiStatus = NetpTranslateNamesInServiceArray(
  235. level,
  236. untranslatedBuffer,
  237. *entriesread,
  238. TRUE, // yes, caller wants new style names
  239. (LPVOID *) (LPVOID) bufptr);
  240. } else { // Zero services returned.
  241. NetpAssert( untranslatedBuffer == NULL );
  242. // Note: total entries may be > 0, if this is ERROR_MORE_DATA...
  243. *bufptr = NULL;
  244. }
  245. }
  246. if (untranslatedBuffer != NULL) {
  247. (VOID) NetApiBufferFree( untranslatedBuffer );
  248. }
  249. return(apiStatus);
  250. } // NetServiceEnum
  251. NET_API_STATUS NET_API_FUNCTION
  252. NetServiceGetInfo (
  253. IN LPCWSTR servername OPTIONAL,
  254. IN LPCWSTR service,
  255. IN DWORD level,
  256. OUT LPBYTE *bufptr
  257. )
  258. /*++
  259. Routine Description:
  260. This is the DLL entrypoint for NetServiceGetInfo.
  261. Arguments:
  262. servername - Pointer to a string containing the name of the computer
  263. that is to execute the API function. Since this function is
  264. executing on that computer, this information is not useful
  265. by the time it gets here. It is really only useful on the RPC
  266. client side.
  267. service - Pointer to a string containing the name of the service
  268. for which information is desired.
  269. level - This indicates the level of information that is desired.
  270. bufptr - Pointer to a Location where the pointer to the returned
  271. information structure is to be placed.
  272. Return Value:
  273. NERR_Success - The operation was successful.
  274. NERR_ServiceNotInstalled - if the service record was not found in
  275. either the installed or uninstalled lists.
  276. NERR_BadServiceName - The service name pointer was NULL.
  277. ERROR_INVALID_LEVEL - An illegal info level was passed in.
  278. ERROR_NOT_ENOUGH_MEMORY - The memory allocation for the returned
  279. Info Record failed.
  280. other - Any error returned by the following base API:
  281. RPC Runtime API
  282. --*/
  283. {
  284. NET_API_STATUS apiStatus;
  285. LPWSTR translatedServiceName;
  286. LPBYTE untranslatedBuffer = NULL;
  287. if (MachineSupportsNt( (LPWSTR) servername )) {
  288. apiStatus = NetpTranslateServiceName(
  289. (LPWSTR) service, // untranslated.
  290. TRUE, // yes, we want new style name
  291. & translatedServiceName );
  292. NetpAssert( apiStatus == NO_ERROR );
  293. apiStatus = MapServiceGetInfo (
  294. (LPWSTR) servername,
  295. (LPWSTR) service,
  296. level,
  297. & untranslatedBuffer);
  298. } else {
  299. apiStatus = NetpTranslateServiceName(
  300. (LPWSTR) service, // untranslated.
  301. FALSE, // no, we don't want new style name
  302. & translatedServiceName );
  303. NetpAssert( apiStatus == NO_ERROR );
  304. //
  305. // Call downlevel...
  306. //
  307. apiStatus = RxNetServiceGetInfo(
  308. (LPWSTR) servername,
  309. translatedServiceName,
  310. level,
  311. & untranslatedBuffer);
  312. }
  313. //
  314. // Translate service name in returned buffer.
  315. //
  316. if (apiStatus == NO_ERROR) {
  317. NetpAssert( untranslatedBuffer != NULL );
  318. apiStatus = NetpTranslateNamesInServiceArray(
  319. level,
  320. untranslatedBuffer,
  321. 1, // only one entry
  322. TRUE, // yes, caller wants new style names
  323. (LPVOID *) (LPVOID) bufptr);
  324. }
  325. if (untranslatedBuffer != NULL) {
  326. (VOID) NetApiBufferFree( untranslatedBuffer );
  327. }
  328. return(apiStatus);
  329. }
  330. NET_API_STATUS NET_API_FUNCTION
  331. NetServiceInstall (
  332. IN LPCWSTR servername OPTIONAL,
  333. IN LPCWSTR service,
  334. IN DWORD argc,
  335. IN LPCWSTR argv[],
  336. OUT LPBYTE *bufptr
  337. )
  338. /*++
  339. Routine Description:
  340. This is the DLL entrypoint for NetServiceInstall.
  341. Arguments:
  342. servername - Points to a string containing the name of the computer
  343. that is to execute the API function.
  344. service- Points to a string containing the name of the service
  345. that is to be started.
  346. argc - Indicates the number or argument vectors in argv.
  347. argv - A pointer to an array of pointers to strings. These
  348. are command line arguments that are to be passed to the service.
  349. bufptr - This is the address where a pointer to the service's
  350. information buffer (SERVICE_INFO_2) is to be placed.
  351. Return Value:
  352. NERR_Success - The operation was successful
  353. NERR_InternalError - There is a bug in this program somewhere.
  354. NERR_ServiceInstalled - The service is already running - we do not
  355. yet allow multiple instances of the same service.
  356. NERR_CfgCompNotFound - The configuration component could not be found.
  357. The Image File could not be found for this service.
  358. NERR_ServiceTableFull - The maximum number of running services has
  359. already been reached.
  360. NERR_ServiceCtlTimeout - The service program did not respond to the
  361. start-up request within the timeout period. If this was the
  362. only service in the service process, the service process was
  363. killed.
  364. ERROR_NOT_ENOUGH_MEMORY - If this error occurs early in the
  365. start-up procedure, the start-up will fail. If it occurs at the
  366. end (allocating the return status buffer), the service will still
  367. be started and allowed to run.
  368. other - Any error returned by the following base API:
  369. CreateNamedPipe
  370. ConnectNamedPipe
  371. CreateProcess
  372. TransactNamedPipe
  373. RPC Runtime API
  374. --*/
  375. {
  376. NET_API_STATUS apiStatus;
  377. LPWSTR translatedServiceName;
  378. LPBYTE untranslatedBuffer = NULL;
  379. if (MachineSupportsNt( (LPWSTR) servername )) {
  380. apiStatus = NetpTranslateServiceName(
  381. (LPWSTR) service, // untranslated.
  382. TRUE, // yes, we want new style name
  383. & translatedServiceName );
  384. NetpAssert( apiStatus == NO_ERROR );
  385. apiStatus = MapServiceInstall (
  386. (LPWSTR) servername,
  387. (LPWSTR) service,
  388. argc,
  389. (LPWSTR *) argv,
  390. & untranslatedBuffer);
  391. } else {
  392. apiStatus = NetpTranslateServiceName(
  393. (LPWSTR) service, // untranslated.
  394. FALSE, // no, we don't want new style name
  395. & translatedServiceName );
  396. NetpAssert( apiStatus == NO_ERROR );
  397. //
  398. // Call downlevel....
  399. //
  400. apiStatus = RxNetServiceInstall(
  401. (LPWSTR) servername,
  402. translatedServiceName,
  403. argc,
  404. (LPWSTR *) argv,
  405. & untranslatedBuffer);
  406. }
  407. //
  408. // Translate service name in returned buffer.
  409. //
  410. if (apiStatus == NO_ERROR) {
  411. NetpAssert( untranslatedBuffer != NULL );
  412. apiStatus = NetpTranslateNamesInServiceArray(
  413. 2, // level 2 by definition
  414. untranslatedBuffer,
  415. 1, // only one entry
  416. TRUE, // yes, caller wants new style names
  417. (LPVOID *) (LPVOID) bufptr);
  418. }
  419. if (untranslatedBuffer != NULL) {
  420. (VOID) NetApiBufferFree( untranslatedBuffer );
  421. }
  422. return(apiStatus);
  423. }
  424. DBGSTATIC BOOL
  425. MachineSupportsNt(
  426. IN LPWSTR UncServerName OPTIONAL
  427. )
  428. {
  429. NET_API_STATUS ApiStatus;
  430. DWORD ActualSupports;
  431. ApiStatus = NetRemoteComputerSupports(
  432. UncServerName,
  433. SUPPORTS_RPC, // Set SUPPORT_ bits wanted.
  434. & ActualSupports );
  435. if (ApiStatus != NO_ERROR) {
  436. return (FALSE); // Error; say it doesn't support NT, and someone else
  437. // will set the correct error code.
  438. }
  439. if (ActualSupports & SUPPORTS_RPC) {
  440. return (TRUE);
  441. }
  442. return (FALSE);
  443. } // MachineSupportsNt