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.

1046 lines
32 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ApiSvc.c
  5. Abstract:
  6. This module contains individual API handlers for the NetService APIs.
  7. SUPPORTED : NetServicControl, NetServiceEnum, NetServiceGetInfo,
  8. NetServiceInstall.
  9. Author:
  10. Shanku Niyogi (w-shanku) 26-Feb-1991
  11. Revision History:
  12. --*/
  13. #include "XactSrvP.h"
  14. #define XACTSRV_CONVERT_SVC_EXITCODE(ob) \
  15. { \
  16. PSERVICE_INFO_2 ss = (PSERVICE_INFO_2) ob; \
  17. if ((unsigned short) ss->svci2_code == ERROR_SERVICE_SPECIFIC_ERROR) { \
  18. ss->svci2_code = (ss->svci2_code & 0xffff0000) | (unsigned short) ss->svci2_specific_error;\
  19. } \
  20. }
  21. //
  22. // Declaration of descriptor strings.
  23. //
  24. STATIC const LPDESC Desc16_service_info_0 = REM16_service_info_0;
  25. STATIC const LPDESC Desc32_service_info_0 = REM32_service_info_0;
  26. STATIC const LPDESC Desc16_service_info_1 = REM16_service_info_1;
  27. STATIC const LPDESC Desc32_service_info_1 = REM32_service_info_1;
  28. STATIC const LPDESC Desc16_service_info_2 = REM16_service_info_2;
  29. STATIC const LPDESC Desc32_service_info_2 = REM32_service_info_2;
  30. NTSTATUS
  31. XsNetServiceControl (
  32. API_HANDLER_PARAMETERS
  33. )
  34. /*++
  35. Routine Description:
  36. This routine handles a call to NetServiceControl.
  37. Arguments:
  38. API_HANDLER_PARAMETERS - information about the API call. See
  39. XsTypes.h for details.
  40. Return Value:
  41. NTSTATUS - STATUS_SUCCESS or reason for failure.
  42. --*/
  43. {
  44. NET_API_STATUS status;
  45. PXS_NET_SERVICE_CONTROL parameters = Parameters;
  46. LPTSTR nativeService = NULL; // Native parameters
  47. LPVOID outBuffer = NULL;
  48. LPVOID newOutBuffer = NULL;
  49. LPSERVICE_INFO_2 serviceInfo2;
  50. LPBYTE stringLocation = NULL; // Conversion variables
  51. DWORD bytesRequired = 0;
  52. DWORD installState;
  53. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  54. IF_DEBUG(SERVICE) {
  55. NetpKdPrint(( "XsNetServiceControl: header at %lx, params at %lx\n",
  56. Header, parameters ));
  57. }
  58. try {
  59. //
  60. // Translate parameters, check for errors.
  61. //
  62. XsConvertTextParameter(
  63. nativeService,
  64. (LPSTR)XsSmbGetPointer( &parameters->Service )
  65. );
  66. //
  67. // Make the local call. We need to mask off the upper bytes of
  68. // both the opcode and the arg parameters since the client is
  69. // putting some garbage on the high byte. The valid values for
  70. // both are 1-255.
  71. //
  72. status = NetServiceControl(
  73. NULL,
  74. XS_MAP_SERVICE_NAME( nativeService ),
  75. (DWORD)( parameters->OpCode & 0x00FF ),
  76. (DWORD)( parameters->Arg & 0x00FF ),
  77. (LPBYTE *)&outBuffer
  78. );
  79. if ( !XsApiSuccess( status )) {
  80. IF_DEBUG(API_ERRORS) {
  81. NetpKdPrint(( "XsNetServiceControl: NetServiceControl failed: "
  82. "%X\n", status ));
  83. }
  84. Header->Status = (WORD)status;
  85. goto cleanup;
  86. }
  87. //
  88. // Convert nt service name to os/2 name
  89. //
  90. status = NetpTranslateNamesInServiceArray(
  91. 2, // level 2 by def
  92. outBuffer,
  93. 1, // 1 entry
  94. FALSE,
  95. &newOutBuffer
  96. );
  97. if ( !XsApiSuccess( status )) {
  98. IF_DEBUG(API_ERRORS) {
  99. NetpKdPrint(( "XsNetServiceControl: NetpTranslateNamesInServiceArray failed: "
  100. "%X\n", status ));
  101. }
  102. Header->Status = NERR_InternalError;
  103. goto cleanup;
  104. }
  105. //
  106. // If the status indicates INSTALL or UNINSTALL PENDING, and if the
  107. // wait hint is greater than 0xFF then the wait hint sent to downlevel
  108. // must be set the maximum SERVICE_MAXTIME (0xFF).
  109. //
  110. serviceInfo2 = (LPSERVICE_INFO_2)newOutBuffer;
  111. installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
  112. if ((installState == SERVICE_INSTALL_PENDING) ||
  113. (installState == SERVICE_UNINSTALL_PENDING)) {
  114. if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
  115. serviceInfo2->svci2_code |= UPPER_HINT_MASK;
  116. serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
  117. }
  118. }
  119. else {
  120. //
  121. // NT version has code and specific_error while downlevel
  122. // version only has code. Convert the info from the extra
  123. // NT specific_error field.
  124. //
  125. XACTSRV_CONVERT_SVC_EXITCODE(newOutBuffer);
  126. }
  127. //
  128. // Convert the structure returned by the 32-bit call to a 16-bit
  129. // structure. The last possible location for variable data is
  130. // calculated from buffer location and length.
  131. //
  132. stringLocation = (LPBYTE)( XsSmbGetPointer( &parameters->Buffer )
  133. + SmbGetUshort( &parameters->BufLen ) );
  134. status = RapConvertSingleEntry(
  135. newOutBuffer,
  136. Desc32_service_info_2,
  137. FALSE,
  138. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  139. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  140. Desc16_service_info_2,
  141. TRUE,
  142. &stringLocation,
  143. &bytesRequired,
  144. Response,
  145. NativeToRap
  146. );
  147. if ( status != NERR_Success ) {
  148. IF_DEBUG(ERRORS) {
  149. NetpKdPrint(( "XsNetServiceControl: RapConvertSingleEntry failed: "
  150. "%X\n", status ));
  151. }
  152. Header->Status = NERR_InternalError;
  153. goto cleanup;
  154. }
  155. IF_DEBUG(SERVICE ) {
  156. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
  157. newOutBuffer, SmbGetUlong( &parameters->Buffer ),
  158. bytesRequired ));
  159. }
  160. //
  161. // Determine return code based on the size of the buffer.
  162. // SERVICE_INFO_x structures have no variable data to pack.
  163. //
  164. if ( !XsCheckBufferSize(
  165. SmbGetUshort( &parameters->BufLen ),
  166. Desc16_service_info_2,
  167. FALSE // not in native format
  168. )) {
  169. IF_DEBUG(ERRORS) {
  170. NetpKdPrint(( "XsNetServiceControl: Buffer too small.\n" ));
  171. }
  172. Header->Status = NERR_BufTooSmall;
  173. }
  174. cleanup:
  175. ;
  176. } except( EXCEPTION_EXECUTE_HANDLER ) {
  177. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  178. }
  179. NetpMemoryFree( nativeService );
  180. NetApiBufferFree( outBuffer );
  181. NetApiBufferFree( newOutBuffer );
  182. //
  183. // Determine return buffer size.
  184. //
  185. XsSetDataCount(
  186. &parameters->BufLen,
  187. Desc16_service_info_2,
  188. Header->Converter,
  189. 1,
  190. Header->Status
  191. );
  192. return STATUS_SUCCESS;
  193. } // XsNetServiceControl
  194. NTSTATUS
  195. XsNetServiceEnum (
  196. API_HANDLER_PARAMETERS
  197. )
  198. /*++
  199. Routine Description:
  200. This routine handles a call to NetServiceEnum.
  201. Arguments:
  202. API_HANDLER_PARAMETERS - information about the API call. See
  203. XsTypes.h for details.
  204. Return Value:
  205. NTSTATUS - STATUS_SUCCESS or reason for failure.
  206. --*/
  207. {
  208. NET_API_STATUS status;
  209. PXS_NET_SERVICE_ENUM parameters = Parameters;
  210. LPVOID outBuffer = NULL; // Native parameters
  211. LPVOID newOutBuffer = NULL;
  212. DWORD entriesRead;
  213. DWORD totalEntries;
  214. DWORD entriesFilled = 0; // Conversion variables
  215. DWORD bytesRequired = 0;
  216. LPDESC nativeStructureDesc;
  217. DWORD level;
  218. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  219. IF_DEBUG(SERVICE) {
  220. NetpKdPrint(( "XsNetServiceEnum: header at %lx, params at %lx, "
  221. "level %ld, buf size %ld\n",
  222. Header, parameters, SmbGetUshort( &parameters->Level ),
  223. SmbGetUshort( &parameters->BufLen )));
  224. }
  225. try {
  226. //
  227. // Check for errors.
  228. //
  229. if ( XsWordParamOutOfRange( parameters->Level, 0, 2 )) {
  230. Header->Status = ERROR_INVALID_LEVEL;
  231. goto cleanup;
  232. }
  233. //
  234. // Make the local call.
  235. //
  236. level = (DWORD)SmbGetUshort( &parameters->Level );
  237. status = NetServiceEnum(
  238. NULL,
  239. level,
  240. (LPBYTE *)&outBuffer,
  241. XsNativeBufferSize( SmbGetUshort( &parameters->BufLen )),
  242. &entriesRead,
  243. &totalEntries,
  244. NULL
  245. );
  246. if ( !XsApiSuccess( status )) {
  247. IF_DEBUG(API_ERRORS) {
  248. NetpKdPrint(( "XsNetServiceEnum: NetServiceEnum failed: %X\n",
  249. status ));
  250. }
  251. Header->Status = (WORD)status;
  252. goto cleanup;
  253. }
  254. IF_DEBUG(SERVICE) {
  255. NetpKdPrint(( "XsNetServiceEnum: received %ld entries at %lx\n",
  256. entriesRead, outBuffer ));
  257. }
  258. //
  259. // Convert nt service names to os/2 name
  260. //
  261. status = NetpTranslateNamesInServiceArray(
  262. level,
  263. outBuffer,
  264. entriesRead,
  265. FALSE,
  266. &newOutBuffer
  267. );
  268. if ( !XsApiSuccess( status )) {
  269. IF_DEBUG(API_ERRORS) {
  270. NetpKdPrint(( "XsNetServiceEnum: NetpTranslateNamesInServiceArray failed: "
  271. "%X\n", status ));
  272. }
  273. Header->Status = NERR_InternalError;
  274. goto cleanup;
  275. }
  276. //
  277. // Use the requested level to determine the format of the
  278. // data structure.
  279. //
  280. switch ( level ) {
  281. case 0:
  282. nativeStructureDesc = Desc32_service_info_0;
  283. StructureDesc = Desc16_service_info_0;
  284. break;
  285. case 1:
  286. nativeStructureDesc = Desc32_service_info_1;
  287. StructureDesc = Desc16_service_info_1;
  288. {
  289. DWORD i;
  290. DWORD installState;
  291. PSERVICE_INFO_1 serviceInfo1 = (PSERVICE_INFO_1) newOutBuffer;
  292. for (i = 0; i < entriesRead; i++, serviceInfo1++) {
  293. //
  294. // If the status indicates INSTALL or UNINSTALL PENDING,
  295. // and if the wait hint is greater than 0xFF then the
  296. // wait hint sent to downlevel must be set the
  297. // maximum SERVICE_MAXTIME (0xFF).
  298. //
  299. installState = (serviceInfo1[i]).svci1_status & SERVICE_INSTALL_STATE;
  300. if ((installState == SERVICE_INSTALL_PENDING) ||
  301. (installState == SERVICE_UNINSTALL_PENDING)) {
  302. if (SERVICE_NT_WAIT_GET(serviceInfo1->svci1_code) > SERVICE_MAXTIME) {
  303. serviceInfo1->svci1_code |= UPPER_HINT_MASK;
  304. serviceInfo1->svci1_code &= SERVICE_RESRV_MASK;
  305. }
  306. }
  307. }
  308. }
  309. break;
  310. case 2:
  311. nativeStructureDesc = Desc32_service_info_2;
  312. StructureDesc = Desc16_service_info_2;
  313. {
  314. DWORD i;
  315. DWORD installState;
  316. PSERVICE_INFO_2 serviceInfo2 = (PSERVICE_INFO_2) newOutBuffer;
  317. for (i = 0; i < entriesRead; i++, serviceInfo2++) {
  318. //
  319. // If the status indicates INSTALL or UNINSTALL PENDING,
  320. // and if the wait hint is greater than 0xFF then the
  321. // wait hint sent to downlevel must be set the
  322. // maximum SERVICE_MAXTIME (0xFF).
  323. //
  324. installState = (serviceInfo2[i]).svci2_status & SERVICE_INSTALL_STATE;
  325. if ((installState == SERVICE_INSTALL_PENDING) ||
  326. (installState == SERVICE_UNINSTALL_PENDING)) {
  327. if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
  328. serviceInfo2->svci2_code |= UPPER_HINT_MASK;
  329. serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
  330. }
  331. }
  332. else {
  333. //
  334. // NT version has code and specific_error while downlevel
  335. // version only has code. Convert the info from the extra
  336. // NT specific_error field.
  337. //
  338. XACTSRV_CONVERT_SVC_EXITCODE(serviceInfo2);
  339. }
  340. }
  341. }
  342. break;
  343. }
  344. //
  345. // Do the actual conversion from the 32-bit structures to 16-bit
  346. // structures.
  347. //
  348. XsFillEnumBuffer(
  349. newOutBuffer,
  350. entriesRead,
  351. nativeStructureDesc,
  352. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  353. (LPVOID)XsSmbGetPointer( &parameters->Buffer ),
  354. SmbGetUshort( &parameters->BufLen ),
  355. StructureDesc,
  356. NULL, // verify function
  357. &bytesRequired,
  358. &entriesFilled,
  359. NULL
  360. );
  361. IF_DEBUG(SERVICE) {
  362. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR,"
  363. " Entries %ld of %ld\n",
  364. newOutBuffer, SmbGetUlong( &parameters->Buffer ),
  365. bytesRequired, entriesFilled, totalEntries ));
  366. }
  367. //
  368. // If all the entries could not be filled, return ERROR_MORE_DATA.
  369. // SERVICE_INFO_x structures have no variable data to pack.
  370. //
  371. if ( entriesFilled < totalEntries ) {
  372. Header->Status = ERROR_MORE_DATA;
  373. }
  374. //
  375. // Set up the response parameters.
  376. //
  377. SmbPutUshort( &parameters->EntriesRead, (WORD)entriesFilled );
  378. SmbPutUshort( &parameters->TotalAvail, (WORD)totalEntries );
  379. cleanup:
  380. ;
  381. } except( EXCEPTION_EXECUTE_HANDLER ) {
  382. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  383. }
  384. NetApiBufferFree( outBuffer );
  385. NetApiBufferFree( newOutBuffer );
  386. //
  387. // Determine return buffer size.
  388. //
  389. XsSetDataCount(
  390. &parameters->BufLen,
  391. StructureDesc,
  392. Header->Converter,
  393. entriesFilled,
  394. Header->Status
  395. );
  396. return STATUS_SUCCESS;
  397. } // XsNetServiceEnum
  398. NTSTATUS
  399. XsNetServiceGetInfo (
  400. API_HANDLER_PARAMETERS
  401. )
  402. /*++
  403. Routine Description:
  404. This routine handles a call to NetServiceGetInfo.
  405. Arguments:
  406. API_HANDLER_PARAMETERS - information about the API call. See
  407. XsTypes.h for details.
  408. Return Value:
  409. NTSTATUS - STATUS_SUCCESS or reason for failure.
  410. --*/
  411. {
  412. NET_API_STATUS status;
  413. PXS_NET_SERVICE_GET_INFO parameters = Parameters;
  414. LPTSTR nativeService = NULL; // Native parameters
  415. LPVOID outBuffer = NULL;
  416. LPVOID newOutBuffer = NULL;
  417. LPBYTE stringLocation = NULL; // Conversion variables
  418. DWORD bytesRequired = 0;
  419. LPDESC nativeStructureDesc;
  420. DWORD level;
  421. LPSERVICE_INFO_2 serviceInfo2;
  422. LPSERVICE_INFO_1 serviceInfo1;
  423. DWORD installState;
  424. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  425. IF_DEBUG(SERVICE) {
  426. NetpKdPrint(( "XsNetServiceGetInfo: header at %lx, "
  427. "params at %lx, level %d\n",
  428. Header, parameters, SmbGetUshort( &parameters->Level )));
  429. }
  430. try {
  431. //
  432. // Translate parameters, check for errors.
  433. //
  434. if ( XsWordParamOutOfRange( parameters->Level, 0, 2 )) {
  435. Header->Status = ERROR_INVALID_LEVEL;
  436. goto cleanup;
  437. }
  438. XsConvertTextParameter(
  439. nativeService,
  440. (LPSTR)XsSmbGetPointer( &parameters->Service )
  441. );
  442. if (nativeService == NULL) {
  443. Header->Status = ERROR_INVALID_PARAMETER;
  444. goto cleanup;
  445. }
  446. //
  447. // Make the local call.
  448. //
  449. level = (DWORD)SmbGetUshort( &parameters->Level );
  450. status = NetServiceGetInfo(
  451. NULL,
  452. XS_MAP_SERVICE_NAME( nativeService ),
  453. level,
  454. (LPBYTE *)&outBuffer
  455. );
  456. if ( !XsApiSuccess( status )) {
  457. IF_DEBUG(API_ERRORS) {
  458. NetpKdPrint(( "XsNetServiceGetInfo: NetServiceGetInfo failed: "
  459. "%X\n", status ));
  460. }
  461. Header->Status = (WORD)status;
  462. goto cleanup;
  463. }
  464. //
  465. // Convert nt service name to os/2 name
  466. //
  467. status = NetpTranslateNamesInServiceArray(
  468. level,
  469. outBuffer,
  470. 1,
  471. FALSE,
  472. &newOutBuffer
  473. );
  474. if ( !XsApiSuccess( status )) {
  475. IF_DEBUG(API_ERRORS) {
  476. NetpKdPrint(( "XsNetServiceGetInfo: NetpTranslateNamesInServiceArray failed: "
  477. "%X\n", status ));
  478. }
  479. Header->Status = NERR_InternalError;
  480. goto cleanup;
  481. }
  482. //
  483. // Use the requested level to determine the format of the
  484. // data structure.
  485. //
  486. switch ( level ) {
  487. case 0:
  488. nativeStructureDesc = Desc32_service_info_0;
  489. StructureDesc = Desc16_service_info_0;
  490. break;
  491. case 1:
  492. nativeStructureDesc = Desc32_service_info_1;
  493. StructureDesc = Desc16_service_info_1;
  494. //
  495. // If the status indicates INSTALL or UNINSTALL PENDING, and if the
  496. // wait hint is greater than 0xFF then the wait hint sent to downlevel
  497. // must be set the maximum SERVICE_MAXTIME (0xFF).
  498. //
  499. serviceInfo1 = (LPSERVICE_INFO_1)newOutBuffer;
  500. installState = serviceInfo1->svci1_status & SERVICE_INSTALL_STATE;
  501. if ((installState == SERVICE_INSTALL_PENDING) ||
  502. (installState == SERVICE_UNINSTALL_PENDING)) {
  503. if (SERVICE_NT_WAIT_GET(serviceInfo1->svci1_code) > SERVICE_MAXTIME) {
  504. serviceInfo1->svci1_code |= UPPER_HINT_MASK;
  505. serviceInfo1->svci1_code &= SERVICE_RESRV_MASK;
  506. }
  507. }
  508. break;
  509. case 2:
  510. nativeStructureDesc = Desc32_service_info_2;
  511. StructureDesc = Desc16_service_info_2;
  512. //
  513. // If the status indicates INSTALL or UNINSTALL PENDING, and if the
  514. // wait hint is greater than 0xFF then the wait hint sent to downlevel
  515. // must be set the maximum SERVICE_MAXTIME (0xFF).
  516. //
  517. serviceInfo2 = (LPSERVICE_INFO_2)newOutBuffer;
  518. installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
  519. if ((installState == SERVICE_INSTALL_PENDING) ||
  520. (installState == SERVICE_UNINSTALL_PENDING)) {
  521. if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
  522. serviceInfo2->svci2_code |= UPPER_HINT_MASK;
  523. serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
  524. }
  525. }
  526. else {
  527. //
  528. // NT version has code and specific_error while downlevel
  529. // version only has code. Convert the info from the extra
  530. // NT specific_error field.
  531. //
  532. XACTSRV_CONVERT_SVC_EXITCODE(newOutBuffer);
  533. }
  534. break;
  535. }
  536. //
  537. // Convert the structure returned by the 32-bit call to a 16-bit
  538. // structure. The last possible location for variable data is
  539. // calculated from buffer location and length.
  540. //
  541. stringLocation = (LPBYTE)( XsSmbGetPointer( &parameters->Buffer )
  542. + SmbGetUshort( &parameters->BufLen ) );
  543. status = RapConvertSingleEntry(
  544. newOutBuffer,
  545. nativeStructureDesc,
  546. FALSE,
  547. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  548. (LPBYTE)XsSmbGetPointer( &parameters->Buffer ),
  549. StructureDesc,
  550. TRUE,
  551. &stringLocation,
  552. &bytesRequired,
  553. Response,
  554. NativeToRap
  555. );
  556. if ( status != NERR_Success ) {
  557. IF_DEBUG(ERRORS) {
  558. NetpKdPrint(( "XsNetServiceGetInfo: RapConvertSingleEntry failed: "
  559. "%X\n", status ));
  560. }
  561. Header->Status = NERR_InternalError;
  562. goto cleanup;
  563. }
  564. IF_DEBUG(SERVICE ) {
  565. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
  566. newOutBuffer, SmbGetUlong( &parameters->Buffer ),
  567. bytesRequired ));
  568. }
  569. //
  570. // Determine return code based on the size of the buffer.
  571. // SERVICE_INFO_x structures have no variable data to pack.
  572. //
  573. if ( !XsCheckBufferSize(
  574. SmbGetUshort( &parameters->BufLen ),
  575. StructureDesc,
  576. FALSE // not in native format
  577. )) {
  578. IF_DEBUG(ERRORS) {
  579. NetpKdPrint(( "XsNetServiceGetInfo: Buffer too small.\n" ));
  580. }
  581. Header->Status = NERR_BufTooSmall;
  582. }
  583. //
  584. // Set up the response parameters.
  585. //
  586. SmbPutUshort( &parameters->TotalAvail, (WORD)bytesRequired );
  587. cleanup:
  588. ;
  589. } except( EXCEPTION_EXECUTE_HANDLER ) {
  590. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  591. }
  592. NetApiBufferFree( newOutBuffer );
  593. NetApiBufferFree( outBuffer );
  594. NetpMemoryFree( nativeService );
  595. //
  596. // Determine return buffer size.
  597. //
  598. XsSetDataCount(
  599. &parameters->BufLen,
  600. StructureDesc,
  601. Header->Converter,
  602. 1,
  603. Header->Status
  604. );
  605. return STATUS_SUCCESS;
  606. } // XsNetServiceGetInfo
  607. NTSTATUS
  608. XsNetServiceInstall (
  609. API_HANDLER_PARAMETERS
  610. )
  611. /*++
  612. Routine Description:
  613. This routine handles a call to NetServiceInstall.
  614. Arguments:
  615. API_HANDLER_PARAMETERS - information about the API call. See
  616. XsTypes.h for details.
  617. Return Value:
  618. NTSTATUS - STATUS_SUCCESS or reason for failure.
  619. --*/
  620. {
  621. NET_API_STATUS status;
  622. PXS_NET_SERVICE_INSTALL parameters = Parameters;
  623. LPTSTR nativeService = NULL; // Native parameters
  624. DWORD argc;
  625. LPTSTR * argv = NULL;
  626. LPVOID outBuffer = NULL;
  627. LPVOID newOutBuffer = NULL;
  628. LPBYTE stringLocation = NULL; // Conversion variables
  629. DWORD bytesRequired = 0;
  630. LPTSTR nativeRcvBuffer = NULL;
  631. LPSTR srcBuffer = NULL;
  632. LPTSTR destBuffer = NULL;
  633. DWORD bufSize;
  634. DWORD i;
  635. DWORD installState;
  636. LPSERVICE_INFO_2 serviceInfo2;
  637. API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
  638. IF_DEBUG(SERVICE) {
  639. NetpKdPrint(( "XsNetServiceInstall: header at %lx, "
  640. "params at %lx, service %s\n",
  641. Header, parameters,
  642. (LPSTR)XsSmbGetPointer( &parameters->Service ) ));
  643. }
  644. try {
  645. //
  646. // Translate parameters, check for errors.
  647. //
  648. XsConvertTextParameter(
  649. nativeService,
  650. (LPSTR)XsSmbGetPointer( &parameters->Service )
  651. );
  652. //
  653. // Convert buffer. First, find number of arguments and buffer size.
  654. //
  655. srcBuffer = (LPSTR)XsSmbGetPointer( &parameters->RcvBuffer );
  656. if ( srcBuffer ) {
  657. bufSize = 0;
  658. for ( argc = 0; strlen( srcBuffer ) > 0; argc++ ) {
  659. bufSize += ( strlen( srcBuffer ) + 1 );
  660. srcBuffer += ( strlen( srcBuffer ) + 1 );
  661. }
  662. } else {
  663. bufSize = 0;
  664. argc = 0;
  665. }
  666. if ( argc ) {
  667. //
  668. // Allocate an argument vector.
  669. //
  670. argv = NetpMemoryAllocate( argc * sizeof(LPTSTR) );
  671. if ( argv == NULL ) {
  672. Header->Status = NERR_NoRoom;
  673. goto cleanup;
  674. }
  675. //
  676. // If we are Unicode, allocate room for converted buffer.
  677. // Otherwise, use the receive buffer to fill argv.
  678. //
  679. #ifdef UNICODE
  680. nativeRcvBuffer = NetpMemoryAllocate( STRING_SPACE_REQD( bufSize + 1 ));
  681. if ( nativeRcvBuffer == NULL ) {
  682. Header->Status = NERR_NoRoom;
  683. goto cleanup;
  684. }
  685. srcBuffer = (LPSTR)XsSmbGetPointer( &parameters->RcvBuffer );
  686. #else
  687. nativeRcvBuffer = (LPTSTR)XsSmbGetPointer( &parameters->RcvBuffer );
  688. #endif
  689. }
  690. //
  691. // Go through buffer, filling in argv vector, and optionally converting
  692. // to Unicode.
  693. //
  694. destBuffer = nativeRcvBuffer;
  695. for ( i = 0; i < argc; i++ ) {
  696. #ifdef UNICODE
  697. NetpCopyStrToTStr( destBuffer, srcBuffer );
  698. srcBuffer += ( strlen( srcBuffer ) + 1 );
  699. #endif
  700. argv[i] = destBuffer;
  701. destBuffer += ( STRLEN( destBuffer ) + 1 );
  702. }
  703. //
  704. // Make the local call.
  705. //
  706. status = NetServiceInstall(
  707. NULL,
  708. XS_MAP_SERVICE_NAME( nativeService ),
  709. argc,
  710. argv,
  711. (LPBYTE *)&outBuffer
  712. );
  713. if ( !XsApiSuccess( status )) {
  714. IF_DEBUG(API_ERRORS) {
  715. NetpKdPrint(( "XsNetServiceInstall: NetServiceInstall failed: "
  716. "%X\n", status ));
  717. }
  718. Header->Status = (WORD)status;
  719. goto cleanup;
  720. }
  721. //
  722. // Convert nt service name to os/2 name
  723. //
  724. status = NetpTranslateNamesInServiceArray(
  725. 2, // level 2 by def
  726. outBuffer,
  727. 1, // 1 entry
  728. FALSE,
  729. &newOutBuffer
  730. );
  731. if ( !XsApiSuccess( status )) {
  732. IF_DEBUG(API_ERRORS) {
  733. NetpKdPrint(( "XsNetServiceInstall: NetpTranslateNamesInServiceArray failed: "
  734. "%X\n", status ));
  735. }
  736. Header->Status = NERR_InternalError;
  737. goto cleanup;
  738. }
  739. //
  740. // If the status indicates INSTALL or UNINSTALL PENDING, and if the
  741. // wait hint is greater than 0xFF then the wait hint sent to downlevel
  742. // must be set the maximum SERVICE_MAXTIME (0xFF).
  743. //
  744. serviceInfo2 = (LPSERVICE_INFO_2)newOutBuffer;
  745. installState = serviceInfo2->svci2_status & SERVICE_INSTALL_STATE;
  746. if ((installState == SERVICE_INSTALL_PENDING) ||
  747. (installState == SERVICE_UNINSTALL_PENDING)) {
  748. if (SERVICE_NT_WAIT_GET(serviceInfo2->svci2_code) > SERVICE_MAXTIME) {
  749. serviceInfo2->svci2_code |= UPPER_HINT_MASK;
  750. serviceInfo2->svci2_code &= SERVICE_RESRV_MASK;
  751. }
  752. }
  753. else {
  754. //
  755. // NT version has code and specific_error while downlevel
  756. // version only has code. Convert the info from the extra
  757. // NT specific_error field.
  758. //
  759. XACTSRV_CONVERT_SVC_EXITCODE(newOutBuffer);
  760. }
  761. //
  762. // Convert the structure returned by the 32-bit call to a 16-bit
  763. // structure. The "return buffer" is actually a byte array in the
  764. // parameter area.
  765. //
  766. stringLocation = parameters->RetBuffer + sizeof( parameters->RetBuffer );
  767. status = RapConvertSingleEntry(
  768. newOutBuffer,
  769. Desc32_service_info_2,
  770. FALSE,
  771. parameters->RetBuffer,
  772. parameters->RetBuffer,
  773. Desc16_service_info_2,
  774. TRUE,
  775. &stringLocation,
  776. &bytesRequired,
  777. Response,
  778. NativeToRap
  779. );
  780. if ( status != NERR_Success ) {
  781. IF_DEBUG(ERRORS) {
  782. NetpKdPrint(( "XsNetServiceInstall: RapConvertSingleEntry failed: "
  783. "%X\n", status ));
  784. }
  785. Header->Status = NERR_InternalError;
  786. goto cleanup;
  787. }
  788. IF_DEBUG(SERVICE) {
  789. NetpKdPrint(( "32-bit data at %lx, 16-bit data at %lx, %ld BR\n",
  790. newOutBuffer, &parameters->RetBuffer, bytesRequired ));
  791. }
  792. //
  793. // There should have been enough memory to make this call, because
  794. // buffer length is checked locally on the client, and an 88 byte
  795. // receive buffer is always provided.
  796. //
  797. NetpAssert( bytesRequired <= sizeof( parameters->RetBuffer ));
  798. cleanup:
  799. ;
  800. } except( EXCEPTION_EXECUTE_HANDLER ) {
  801. Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
  802. }
  803. NetApiBufferFree( outBuffer );
  804. NetApiBufferFree( newOutBuffer );
  805. NetpMemoryFree( nativeService );
  806. NetpMemoryFree( argv );
  807. #ifdef UNICODE
  808. NetpMemoryFree( nativeRcvBuffer );
  809. #endif // def UNICODE
  810. return STATUS_SUCCESS;
  811. } // XsNetServiceInstall