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.

2062 lines
55 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. XsSubs.c
  5. Abstract:
  6. This module contains various subroutines for XACTSRV.
  7. Author:
  8. David Treadwell (davidtr) 07-Jan-1991
  9. Revision History:
  10. 05-Oct-1992 JohnRo
  11. RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. (4&5 too.)
  12. (Fixed XsFillAuxEnumBuffer.)
  13. --*/
  14. #include "XactSrvP.h"
  15. #include <WinBase.h> // GetCurrentProcessId prototype
  16. #include <align.h>
  17. VOID
  18. SmbCapturePtr(
  19. LPBYTE PointerDestination,
  20. LPBYTE PointerSource
  21. );
  22. DWORD
  23. XsBytesForConvertedStructure (
  24. IN LPBYTE InStructure,
  25. IN LPDESC InStructureDesc,
  26. IN LPDESC OutStructureDesc,
  27. IN RAP_CONVERSION_MODE Mode,
  28. IN BOOL MeaninglessInputPointers
  29. )
  30. /*++
  31. Routine Description:
  32. This routine determines the number of bytes that would be required
  33. to hold the input structure when converted to the structure
  34. described by OutStructureDesc.
  35. Arguments:
  36. InStructure - a pointer to the actual input structure.
  37. InStructureDesc - a pointer to an ASCIIZ describing the format of the
  38. input structure.
  39. OutStructureDesc - a pointer to an ASCIIZ describing the format of the
  40. output structure.
  41. Mode - indicates mode of conversion (native to RAP or vice versa).
  42. Return Value:
  43. DWORD - The number of bytes required to hold the converted structure.
  44. --*/
  45. {
  46. NET_API_STATUS status;
  47. DWORD bytesRequired = 0;
  48. //
  49. // Use RapConvertSingleEntry to get the size that the input structure
  50. // will take when converted to the format specified in the output
  51. // structure description. That routine should not actually write
  52. // anything--it should simply appear that there is no room to
  53. // write more data into, just as if an Enum buffer is full.
  54. //
  55. //
  56. // Should handle errors from RapConvertSingleEntry.
  57. // But the way this is used, existing code probably
  58. // won't break if we just ignore them.
  59. //
  60. status = RapConvertSingleEntry(
  61. InStructure,
  62. InStructureDesc,
  63. MeaninglessInputPointers,
  64. NULL,
  65. NULL,
  66. OutStructureDesc,
  67. FALSE,
  68. NULL,
  69. &bytesRequired,
  70. Response,
  71. Mode
  72. );
  73. //
  74. // For native structures, we should make sure the buffer is an even amount,
  75. // to allow an even boundary for strings, as in Unicode.
  76. //
  77. if ( Mode == RapToNative ) {
  78. bytesRequired = ROUND_UP_COUNT( bytesRequired, ALIGN_DWORD );
  79. }
  80. return bytesRequired;
  81. } // XsBytesForConvertedStructure
  82. LPVOID
  83. XsCaptureParameters (
  84. IN LPTRANSACTION Transaction,
  85. OUT LPDESC *AuxDescriptor
  86. )
  87. /*++
  88. Routine Description:
  89. This routine captures all input parameters from the transaction block
  90. and puts them into a consistent structure that API handlers can access.
  91. It allocates memory to hold this structure. This memory should be
  92. freed by XsSetParameters after the API handler has done its work.
  93. Arguments:
  94. Transaction - a pointer to the transaction block describing the
  95. request.
  96. AuxDescriptor - a pointer to a LPDESC which will hold a pointer to
  97. the auxiliary descriptor string if there is one, or NULL if there
  98. is not.
  99. Return Value:
  100. LPVOID - a pointer to a buffer containing the captured parameters.
  101. --*/
  102. {
  103. LPDESC descriptorString;
  104. LPDESC descriptor;
  105. LPBYTE inParams;
  106. DWORD outParamsLength;
  107. LPBYTE outParams;
  108. LPBYTE outParamsPtr;
  109. WORD rcvBufferLength;
  110. //
  111. // The first two bytes of the parameter section are the API number,
  112. // then comes the descriptor string.
  113. //
  114. descriptorString = Transaction->InParameters + 2;
  115. //
  116. // Find the actual parameter data in the input.
  117. //
  118. inParams = XsFindParameters( Transaction );
  119. //
  120. // Find out how much space to allocate to hold the parameters.
  121. //
  122. outParamsLength = RapStructureSize( descriptorString, Response, FALSE );
  123. //
  124. // Allocate space to hold the output parameters.
  125. // In addition when the request fails the current APIs set the buflen field
  126. // In order to account for this additional buffer space is allocated. Since
  127. // this field is not located at the same offset we need to compute the
  128. // additional space reqd. to be the maximum of all the offsets. Currently
  129. // the 16 byte offset seems to suffice. When modifying apiparam.h ensure
  130. // that this is the case.
  131. //
  132. outParams = NetpMemoryAllocate( sizeof(XS_PARAMETER_HEADER)
  133. + outParamsLength +
  134. sizeof(DWORD) * 4);
  135. if ( outParams == NULL ) {
  136. IF_DEBUG(ERRORS) {
  137. NetpKdPrint(( "XsCaptureParameters: unable to allocate %ld bytes\n",
  138. outParamsLength ));
  139. }
  140. return NULL;
  141. }
  142. //
  143. // Zero out the parameters and set outParamsPtr to the start of the
  144. // actual parameters.
  145. //
  146. RtlZeroMemory( outParams, sizeof(XS_PARAMETER_HEADER) + outParamsLength );
  147. outParamsPtr = outParams + sizeof(XS_PARAMETER_HEADER);
  148. //
  149. // For each character in the descriptor string, fill in the output
  150. // parameters as appropriate.
  151. //
  152. for ( descriptor = descriptorString; *descriptor != '\0'; ) {
  153. switch ( *descriptor++ ) {
  154. case REM_ASCIZ:
  155. //
  156. // The parameter is a pointer to a string. The actual string
  157. // is in the parameter data, so put a pointer to it in the
  158. // output structure.
  159. //
  160. // String parameters just get passed as is. It
  161. // is up to the API handler to convert the actual data.
  162. //
  163. //
  164. // !!! Parameter string descriptors may not have maximum length
  165. // counts.
  166. //
  167. if( isdigit( *descriptor ) ) {
  168. NetpMemoryFree( outParams );
  169. return NULL;
  170. }
  171. SmbCapturePtr( outParamsPtr, inParams );
  172. //
  173. // Update pointers -- move inParams past end of string.
  174. //
  175. inParams += ( strlen( inParams ) + 1 );
  176. outParamsPtr += sizeof(LPSTR);
  177. break;
  178. case REM_BYTE_PTR:
  179. case REM_FILL_BYTES:
  180. //
  181. // The parameter is a pointer to a byte or array of bytes.
  182. //
  183. SmbCapturePtr( outParamsPtr, inParams );
  184. inParams += sizeof(BYTE) * RapDescArrayLength( descriptor );
  185. outParamsPtr += sizeof(LPBYTE);
  186. break;
  187. case REM_DWORD:
  188. //
  189. // The parameter is a dword or array of dwords.
  190. //
  191. // !!! This assumes that an array of words will never be passed
  192. // as a parameter.
  193. if( isdigit( *descriptor ) ) {
  194. NetpMemoryFree( outParams );
  195. return NULL;
  196. }
  197. //
  198. // Copy over the double word and update pointers.
  199. //
  200. SmbPutUlong(
  201. (LPDWORD)outParamsPtr,
  202. SmbGetUlong( (LPDWORD)inParams )
  203. );
  204. inParams += sizeof(DWORD);
  205. outParamsPtr += sizeof(DWORD);
  206. break;
  207. case REM_ENTRIES_READ:
  208. case REM_RCV_WORD_PTR:
  209. //
  210. // Count of entries read (e) or receive word pointer (h).
  211. // This is an output parameter, so just zero it and
  212. // increment the output parameter pointer.
  213. //
  214. SmbPutUshort( (LPWORD)outParamsPtr, 0 );
  215. outParamsPtr += sizeof(WORD);
  216. break;
  217. case REM_RCV_DWORD_PTR:
  218. //
  219. // Count of receive dword pointer (i).
  220. // This is an output parameter, so just zero it and
  221. // increment the output parameter pointer.
  222. //
  223. SmbPutUlong( (LPDWORD)outParamsPtr, 0 );
  224. outParamsPtr += sizeof(DWORD);
  225. break;
  226. case REM_NULL_PTR:
  227. //
  228. // Null pointer. Set output parameter to NULL, and increment
  229. // pointers.
  230. //
  231. SmbCapturePtr( outParamsPtr, NULL );
  232. outParamsPtr += sizeof(LPSTR);
  233. break;
  234. case REM_RCV_BUF_LEN:
  235. //
  236. // The length of the receive buffer (r).
  237. //
  238. rcvBufferLength = SmbGetUshort( (LPWORD)inParams );
  239. //
  240. // If the indicated buffer length is greater than the max
  241. // data count on the transaction, somebody messed up. Set
  242. // the length to MaxDataCount.
  243. //
  244. if ( rcvBufferLength > (WORD)Transaction->MaxDataCount ) {
  245. IF_DEBUG(ERRORS) {
  246. NetpKdPrint(( "XsCaptureParameters: OutBufLen %lx greater than MaxDataCount %lx.\n",
  247. rcvBufferLength, Transaction->MaxDataCount ));
  248. }
  249. rcvBufferLength = (WORD)Transaction->MaxDataCount;
  250. }
  251. //
  252. // Put the max output data length in the output parameters.
  253. //
  254. SmbPutUshort( (LPWORD)outParamsPtr, rcvBufferLength );
  255. //
  256. // Fill in the receive buffer with zeroes for security.
  257. //
  258. RtlZeroMemory( Transaction->OutData, (DWORD)rcvBufferLength );
  259. inParams += sizeof(WORD);
  260. outParamsPtr += sizeof(WORD);
  261. break;
  262. case REM_RCV_BUF_PTR:
  263. //
  264. // A pointer to a receive data buffer. There is nothing in
  265. // the transaction corresponding to this, but set a longword
  266. // in the output parameters to point to the data output
  267. // section of the transaction.
  268. //
  269. SmbCapturePtr(
  270. outParamsPtr,
  271. Transaction->OutData
  272. );
  273. outParamsPtr += sizeof(LPBYTE);
  274. break;
  275. case REM_RCV_BYTE_PTR:
  276. //
  277. // Return bytes, so just increment output parameter pointer.
  278. //
  279. outParamsPtr += sizeof(BYTE) * RapDescArrayLength( descriptor );
  280. break;
  281. case REM_SEND_BUF_LEN:
  282. //
  283. // The size of an input data buffer. Put the size of the
  284. // received data in the output structure.
  285. //
  286. SmbPutUshort(
  287. (LPWORD)outParamsPtr,
  288. (WORD)Transaction->DataCount
  289. );
  290. outParamsPtr += sizeof(WORD);
  291. break;
  292. case REM_SEND_BUF_PTR:
  293. //
  294. // A pointer to a send data buffer. There is nothing in the
  295. // transaction corresponding to this, but set a longword in
  296. // the output parameters to point to the data input section
  297. // of the transaction.
  298. //
  299. SmbCapturePtr( outParamsPtr, Transaction->InData );
  300. outParamsPtr += sizeof(LPBYTE);
  301. break;
  302. case REM_WORD:
  303. case REM_PARMNUM:
  304. //
  305. // The parameter is a word.
  306. //
  307. // !!! This assumes that an array of words will never be passed
  308. // as a parameter.
  309. if( isdigit( *descriptor ) ) {
  310. NetpMemoryFree( outParams );
  311. return NULL;
  312. }
  313. //
  314. // Copy over the word and update pointers.
  315. //
  316. SmbPutUshort(
  317. (LPWORD)outParamsPtr,
  318. SmbGetUshort( (LPWORD)inParams )
  319. );
  320. inParams += sizeof(WORD);
  321. outParamsPtr += sizeof(WORD);
  322. break;
  323. default:
  324. IF_DEBUG(ERRORS) {
  325. NetpKdPrint(( "XsCaptureParameters: unsupported character at %lx: "
  326. "%c\n", descriptor - 1, *( descriptor - 1 ) ));
  327. NetpBreakPoint( );
  328. }
  329. }
  330. }
  331. //
  332. // Examine the data descriptor string to see if an auxiliary descriptor
  333. // string exists. If it does, the string starts right after the end
  334. // of the parameters.
  335. //
  336. *AuxDescriptor = XsAuxiliaryDescriptor( ++descriptor, inParams );
  337. return outParams;
  338. } // XsCaptureParameters
  339. BOOL
  340. XsCheckBufferSize (
  341. IN WORD BufferLength,
  342. IN LPDESC Descriptor,
  343. IN BOOL NativeFormat
  344. )
  345. /*++
  346. Routine Description:
  347. This routine determines if there is enough room in the buffer for the
  348. fixed component of at least one entry of the described structure.
  349. Arguments:
  350. BufferLength - the length of the buffer to test.
  351. Descriptor - the format of the structure in the buffer.
  352. NativeFormat - TRUE iff the buffer is in native (as opposed to RAP) format.
  353. Return Value:
  354. BOOL - True if there is enough room, false if there isn't.
  355. --*/
  356. {
  357. if ( (DWORD)BufferLength
  358. >= RapStructureSize( Descriptor, Response, NativeFormat )) {
  359. return TRUE;
  360. } else {
  361. return FALSE;
  362. }
  363. } // XsCheckBufferSize
  364. BOOL
  365. XsCheckSmbDescriptor(
  366. IN LPDESC SmbDescriptor,
  367. IN LPDESC ActualDescriptor
  368. )
  369. /*++
  370. Routine Description:
  371. This routine checks whether a descriptor passed in the SMB matches
  372. the actual descriptor expected, taking into account that the actual
  373. descriptor may have ignore fields which have no corresponding field in
  374. the SMB descriptor, and that the SMB descriptor may have null pointer
  375. fields instead of normal pointer fields. However, array-type fields
  376. have to be of the same length in both descriptors.
  377. Arguments:
  378. SmbDescriptor - the descriptor to be validated.
  379. ActualDescriptor - the descriptor expected. Does not have to be an
  380. exact match - see the description above.
  381. Return Value:
  382. BOOL - TRUE if the descriptor is valid,
  383. FALSE otherwise.
  384. --*/
  385. {
  386. DESC_CHAR smbField;
  387. DESC_CHAR expField;
  388. DWORD smbFieldSize;
  389. DWORD expFieldSize;
  390. CHAR nullParam = '\0';
  391. if( ActualDescriptor == NULL )
  392. {
  393. ActualDescriptor = &nullParam;
  394. }
  395. while (( smbField = *SmbDescriptor++ ) != '\0' ) {
  396. smbFieldSize = RapDescArrayLength( SmbDescriptor );
  397. //
  398. // Skip over ignore fields.
  399. //
  400. while ( *ActualDescriptor == REM_IGNORE ) {
  401. ActualDescriptor++;
  402. }
  403. //
  404. // There should be a corresponding field expected.
  405. //
  406. if (( expField = *ActualDescriptor++ ) == '\0' ) {
  407. return FALSE;
  408. }
  409. expFieldSize = RapDescArrayLength( ActualDescriptor );
  410. //
  411. // If both are actual data fields, they must be the same type and of
  412. // same length.
  413. //
  414. if (( !RapIsPointer( expField ) || smbField != REM_NULL_PTR ) &&
  415. ( smbField != expField || smbFieldSize != expFieldSize )) {
  416. return FALSE;
  417. }
  418. //
  419. // SMB provides a null pointer field, we are expecting any pointer.
  420. // This is OK, as long as there is no input array length.
  421. //
  422. if ( smbField == REM_NULL_PTR &&
  423. ( !RapIsPointer( expField ) || smbFieldSize != 1 )) {
  424. return FALSE;
  425. }
  426. }
  427. while ( *ActualDescriptor == REM_IGNORE ) {
  428. ActualDescriptor++;
  429. }
  430. //
  431. // Validate that the entire descriptor was present!
  432. //
  433. if( (*ActualDescriptor) != '\0' )
  434. {
  435. return FALSE;
  436. }
  437. return TRUE;
  438. } // XsCheckSmbDescriptor
  439. NET_API_STATUS
  440. XsConvertSetInfoBuffer(
  441. IN LPBYTE InBuffer,
  442. IN WORD BufferLength,
  443. IN WORD ParmNum,
  444. IN BOOL ConvertStrings,
  445. IN BOOL MeaninglessInputPointers,
  446. IN LPDESC InStructureDesc,
  447. IN LPDESC OutStructureDesc,
  448. IN LPDESC InSetInfoDesc,
  449. IN LPDESC OutSetInfoDesc,
  450. OUT LPBYTE * OutBuffer,
  451. OUT LPDWORD OutBufferLength OPTIONAL
  452. )
  453. /*++
  454. Routine Description:
  455. This routine converts data for a SetInfo call based on the parameter
  456. number (ParmNum) value. The ParmNum indicates the field in the whole
  457. structure which has to be changed, and may be 0.
  458. Arguments:
  459. InBuffer - a pointer to the input buffer in 16-bit format.
  460. BufferLength - the length of the input buffer.
  461. ParmNum - the parameter number.
  462. ConvertStrings - a boolean indicating whether string parameter data
  463. should be converted to a pointer form. If TRUE, the return data
  464. buffer will have a pointer to another place in the buffer where
  465. the string will be. If FALSE, the data buffer will have only the
  466. physical string.
  467. InStructureDesc - the exact descriptor of the input buffer.
  468. OutStructureDesc - the descriptor of the 32-bit output data, as found
  469. in RemDef.h.
  470. InSetInfoDesc - the setinfo-specific descriptor of the input structure
  471. format, as found in RemDef.h.
  472. OutSetInfoDesc - the setinfo-specific descriptor of the output structure
  473. format, as found in RemDef.h.
  474. OutBuffer - a pointer to an LPBYTE which will get a pointer to the
  475. resulting output buffer.
  476. OutBufferLength - an optional pointer to a DWORD which will get the
  477. length of the resulting output buffer.
  478. Return Value:
  479. NET_API_STATUS - NERR_Success if conversion was successful; otherwise
  480. the appropriate status to return to the user. The only exception is
  481. ERROR_NOT_SUPPORTED, which indicates that the particular parameter
  482. number is valid, but not on NT.
  483. --*/
  484. {
  485. LPDESC fieldDesc = NULL;
  486. DWORD stringLength;
  487. LPDESC subDesc = NULL;
  488. LPDESC subDesc2 = NULL;
  489. DWORD bufferSize;
  490. LPBYTE stringLocation;
  491. DWORD bytesRequired = 0;
  492. LPDESC OutDescCopy = OutStructureDesc;
  493. NET_API_STATUS status = NERR_Success;
  494. //
  495. // The buffer length should be greater than 0.
  496. //
  497. if ( BufferLength == 0 ) {
  498. return NERR_BufTooSmall;
  499. }
  500. if ( ParmNum != PARMNUM_ALL ) {
  501. //
  502. // Check 16-bit parameter to see if it could be changed in OS/2.
  503. //
  504. fieldDesc = RapParmNumDescriptor( InSetInfoDesc, (DWORD)ParmNum,
  505. Both, FALSE );
  506. if ( fieldDesc == NULL ) {
  507. return NERR_NoRoom;
  508. }
  509. if ( fieldDesc[0] == REM_UNSUPPORTED_FIELD ) {
  510. status = ERROR_INVALID_PARAMETER;
  511. goto cleanup;
  512. } else {
  513. InStructureDesc = RapParmNumDescriptor( InStructureDesc,
  514. (DWORD)ParmNum, Both, FALSE );
  515. }
  516. NetpMemoryFree( fieldDesc );
  517. //
  518. // Check 32-bit parameter to see if it is valid in NT.
  519. //
  520. fieldDesc = RapParmNumDescriptor( OutSetInfoDesc, (DWORD)ParmNum,
  521. Both, TRUE );
  522. if ( fieldDesc == NULL ) {
  523. return NERR_NoRoom;
  524. }
  525. if ( fieldDesc[0] == REM_IGNORE ) {
  526. status = ERROR_NOT_SUPPORTED;
  527. goto cleanup;
  528. } else {
  529. OutStructureDesc = RapParmNumDescriptor( OutStructureDesc,
  530. (DWORD)ParmNum, Both, TRUE );
  531. }
  532. //
  533. // Filter out strings that are too long for LM2.x.
  534. //
  535. if ( InStructureDesc[0] == REM_ASCIZ
  536. || InStructureDesc[0] == REM_ASCIZ_TRUNCATABLE ) {
  537. subDesc = InStructureDesc + 1;
  538. stringLength = RapDescStringLength( subDesc );
  539. subDesc = NULL;
  540. if ( stringLength && strlen( InBuffer ) >= stringLength ) {
  541. switch( InStructureDesc[0] ) {
  542. case REM_ASCIZ:
  543. status = ERROR_INVALID_PARAMETER;
  544. goto cleanup;
  545. case REM_ASCIZ_TRUNCATABLE:
  546. InBuffer[stringLength - 1] = '\0';
  547. }
  548. }
  549. }
  550. //
  551. // If a descriptor is a string pointer, the data is the actual
  552. // string, rather than a pointer. Find the length of the string,
  553. // and create a descriptor.
  554. //
  555. // Assuming all these arrays are string data, we
  556. // use available macros to generate an array big
  557. // enough to hold the converted string.
  558. if ( InStructureDesc[0] == REM_ASCIZ
  559. || InStructureDesc[0] == REM_ASCIZ_TRUNCATABLE ) {
  560. if (( subDesc = NetpMemoryAllocate( MAX_DESC_SUBSTRING + 1 ))
  561. == NULL ) {
  562. status = NERR_NoRoom;
  563. goto cleanup;
  564. }
  565. stringLength = strlen( InBuffer ) + 1;
  566. subDesc[0] = REM_BYTE;
  567. _ltoa( stringLength, &subDesc[1], 10 );
  568. InStructureDesc = subDesc;
  569. }
  570. //
  571. // If output descriptor is a string pointer, and we are asked to keep
  572. // strings inline, make the target data an array of bytes. We find out
  573. // the length required by "walking" the input descriptor, and then
  574. // allocate memory to hold a similar descriptor.
  575. //
  576. // Assuming all these arrays are string data, we
  577. // use available macros to generate an array big
  578. // enough to hold the converted string. Because of the way
  579. // RAP works, if the destination string is Unicode, the destination
  580. // array will be exactly twice as long, and RAP will automatically
  581. // do the Unicode conversion.
  582. //
  583. if (( OutStructureDesc[0] == REM_ASCIZ
  584. || OutStructureDesc[0] == REM_ASCIZ_TRUNCATABLE )
  585. && !ConvertStrings ) {
  586. OutDescCopy = OutStructureDesc;
  587. subDesc2 = InStructureDesc + 1;
  588. stringLength = RapDescArrayLength( subDesc2 );
  589. if (( subDesc2 = NetpMemoryAllocate( MAX_DESC_SUBSTRING + 1 ))
  590. == NULL ) {
  591. status = NERR_NoRoom;
  592. goto cleanup;
  593. }
  594. subDesc2[0] = REM_BYTE;
  595. _ltoa( STRING_SPACE_REQD( stringLength ), &subDesc2[1], 10 ) ;
  596. OutStructureDesc = subDesc2;
  597. }
  598. }
  599. if ( !XsCheckBufferSize( BufferLength, InStructureDesc, FALSE )) {
  600. status = NERR_BufTooSmall;
  601. goto cleanup;
  602. }
  603. //
  604. // Find out how big a 32-bit data buffer we need.
  605. //
  606. bufferSize = XsBytesForConvertedStructure(
  607. InBuffer,
  608. InStructureDesc,
  609. OutStructureDesc,
  610. RapToNative,
  611. MeaninglessInputPointers
  612. );
  613. //
  614. // Allocate enough memory to hold the converted native buffer.
  615. //
  616. *OutBuffer = NetpMemoryAllocate( bufferSize );
  617. if ( *OutBuffer == NULL ) {
  618. status = NERR_NoRoom;
  619. goto cleanup;
  620. }
  621. //
  622. // Convert 16-bit data into 32-bit data and store it in the native
  623. // buffer.
  624. //
  625. stringLocation = *OutBuffer + bufferSize;
  626. bytesRequired = 0;
  627. status = RapConvertSingleEntry(
  628. InBuffer,
  629. InStructureDesc,
  630. MeaninglessInputPointers,
  631. *OutBuffer,
  632. *OutBuffer,
  633. OutStructureDesc,
  634. FALSE,
  635. &stringLocation,
  636. &bytesRequired,
  637. Response,
  638. RapToNative
  639. );
  640. if ( status != NERR_Success ) {
  641. IF_DEBUG(ERRORS) {
  642. NetpKdPrint(( "XsConvertSetInfoBuffer: RapConvertSingleEntry "
  643. "failed %X\n", status ));
  644. }
  645. status = NERR_InternalError;
  646. goto cleanup;
  647. }
  648. cleanup:
  649. //
  650. // Free buffers.
  651. //
  652. NetpMemoryFree( subDesc );
  653. NetpMemoryFree( subDesc2 );
  654. NetpMemoryFree( fieldDesc );
  655. if ( OutBufferLength != NULL ) {
  656. *OutBufferLength = bytesRequired;
  657. }
  658. return status;
  659. } // XsConvertSetInfoBuffer
  660. NET_API_STATUS
  661. XsDefaultEnumVerifyFunction (
  662. NET_API_STATUS ConvertStatus,
  663. PBYTE ConvertedEntry,
  664. PBYTE BaseAddress
  665. )
  666. /*++
  667. Routine Description:
  668. This is the default routine called by XsFillEnumBuffer to determine
  669. whether each converted entry should be retained or discarded. This
  670. routine directs XsFillEnumBuffer to discard any entry which
  671. RapConvertSingleEntry encountered an error trying to convert.
  672. Parameters:
  673. ConvertStatus - the status which RapConvertSingleEntry encountered
  674. trying to convert this entry.
  675. ConvertedEntry - a pointer to the buffer containing the converted entry.
  676. BaseAddress - A pointer to the base used to calculate offsets.
  677. Return Value:
  678. NET_API_STATUS - NERR_Success if the entry should be retained,
  679. or an error code if the entry should be discarded.
  680. --*/
  681. {
  682. UNREFERENCED_PARAMETER(ConvertedEntry);
  683. UNREFERENCED_PARAMETER(BaseAddress);
  684. return ConvertStatus;
  685. }
  686. VOID
  687. XsFillAuxEnumBuffer (
  688. IN LPBYTE InBuffer,
  689. IN DWORD NumberOfEntries,
  690. IN LPDESC InStructureDesc,
  691. IN LPDESC InAuxStructureDesc,
  692. IN OUT LPBYTE OutBuffer,
  693. IN LPBYTE OutBufferStart,
  694. IN DWORD OutBufferLength,
  695. IN LPDESC OutStructureDesc,
  696. IN LPDESC OutAuxStructureDesc,
  697. IN PXACTSRV_ENUM_VERIFY_FUNCTION VerifyFunction OPTIONAL,
  698. OUT LPDWORD BytesRequired,
  699. OUT LPDWORD EntriesFilled,
  700. OUT LPDWORD InvalidEntries OPTIONAL
  701. )
  702. /*++
  703. Routine Description:
  704. This routine copies all Enum structures which have auxiliary data
  705. from 32-bit format to 16-bit format. As many complete entries as
  706. possible are copied, then possibly some incomplete entries.
  707. All pointer fields are converted to offsets so that this buffer
  708. may be returned directly to the requesting client.
  709. Enum buffers with auxiliary data have one or more auxiliary
  710. structures, with possible variable data, after each entry.
  711. Arguments:
  712. InBuffer - a pointer to the input information in 32-bit format.
  713. NumberOfEntries - the count of fixed structures in the input buffer.
  714. InStructureDesc - description of the input fixed structure.
  715. InAuxStructureDesc - description of the input auxiliary structure.
  716. OutBuffer - a pointer to where to write the 16-bit buffer.
  717. OutBufferStart - a pointer to the actual start of the 16-bit buffer.
  718. Used to calculate offsets for all pointers in structures.
  719. OutBufferLength - length of the output buffer.
  720. OutStructureDesc - description of the output fixed structure.
  721. OutAuxStructureDesc - description of the output fixed structure.
  722. VerifyFunction - a pointer to a function which is be called after
  723. each enum record is converted in order to determine whether
  724. the record should be retained or discarded. The function
  725. is passed the return code from RapConvertSingleEntry and
  726. a pointer to the converted entry. It must return NERR_SUCCESS
  727. if the entry is to be retained, or any error code if the entry
  728. is to be discarded. If no function is supplied, a default function
  729. is used, which discards an entry only if RapConvertSingleEntry
  730. returned an error trying to convert it.
  731. BytesRequired - a pointer to a DWORD to receive the total number of
  732. bytes that would be required to hold the entire output buffer.
  733. EntriesFilled - a pointer to a DWORD to receive the total number of
  734. entries that could be put in the buffer given.
  735. InvalidEntries - an optional pointer to a DWORD to receive the total
  736. number of entries discarded by the verify function. If NULL, this
  737. value will be not be available to the caller.
  738. Return Value:
  739. None.
  740. --*/
  741. {
  742. NET_API_STATUS status;
  743. DWORD currentEntry;
  744. LPBYTE currentInEntryPtr;
  745. LPBYTE currentOutEntryPtr;
  746. LPBYTE outputStringLocation;
  747. LPBYTE oldStringLocation;
  748. DWORD inputStructureSize;
  749. DWORD inputAuxStructureSize;
  750. DWORD outputStructureSize;
  751. DWORD outputAuxStructureSize;
  752. DWORD inputAuxCount;
  753. DWORD currentAux;
  754. DWORD outputAuxOffset;
  755. DWORD newBytesRequired;
  756. DWORD auxBytesRequired;
  757. DWORD remainingSize;
  758. DWORD invalidEntries = 0;
  759. //
  760. // In degenerate case, just call FillEnumBuffer.
  761. //
  762. if ( InAuxStructureDesc == NULL || OutAuxStructureDesc == NULL ) {
  763. XsFillEnumBuffer (
  764. InBuffer,
  765. NumberOfEntries,
  766. InStructureDesc,
  767. OutBuffer,
  768. OutBufferStart,
  769. OutBufferLength,
  770. OutStructureDesc,
  771. VerifyFunction,
  772. BytesRequired,
  773. EntriesFilled,
  774. InvalidEntries
  775. );
  776. return;
  777. }
  778. if ( VerifyFunction == NULL ) {
  779. VerifyFunction = &XsDefaultEnumVerifyFunction;
  780. }
  781. //
  782. // Set up sizes of input and output structures.
  783. //
  784. inputStructureSize = RapStructureSize( InStructureDesc, Response, TRUE );
  785. inputAuxStructureSize
  786. = RapStructureSize( InAuxStructureDesc, Response, TRUE );
  787. outputStructureSize = RapStructureSize( OutStructureDesc, Response, FALSE );
  788. outputAuxStructureSize
  789. = RapStructureSize( OutAuxStructureDesc, Response, FALSE );
  790. outputAuxOffset = RapAuxDataCountOffset( InStructureDesc, Response, TRUE );
  791. outputStringLocation = (LPBYTE)OutBuffer + OutBufferLength;
  792. *BytesRequired = 0;
  793. //
  794. // Check if one fixed entry will fit.
  795. //
  796. if ( inputStructureSize > OutBufferLength ) {
  797. *EntriesFilled = 0;
  798. goto cleanup;
  799. }
  800. //
  801. // Loop through the entries, converting along the way.
  802. //
  803. currentInEntryPtr = InBuffer;
  804. currentOutEntryPtr = OutBuffer;
  805. *EntriesFilled = 0;
  806. for ( currentEntry = 0; currentEntry < NumberOfEntries; currentEntry++ ) {
  807. //
  808. // If there wasn't enough room for the conversion, we can quit now.
  809. //
  810. if ( currentOutEntryPtr + outputStructureSize > outputStringLocation ) {
  811. break;
  812. }
  813. newBytesRequired = *BytesRequired;
  814. oldStringLocation = outputStringLocation;
  815. //
  816. // Get the auxiliary number count.
  817. //
  818. inputAuxCount = RapAuxDataCount(
  819. currentInEntryPtr,
  820. InStructureDesc,
  821. Response,
  822. TRUE
  823. );
  824. NetpAssert( inputAuxCount != NO_AUX_DATA );
  825. //
  826. // Convert the fixed entry.
  827. //
  828. status = RapConvertSingleEntry(
  829. currentInEntryPtr,
  830. InStructureDesc,
  831. FALSE,
  832. OutBufferStart,
  833. currentOutEntryPtr,
  834. OutStructureDesc,
  835. TRUE,
  836. &outputStringLocation,
  837. &newBytesRequired,
  838. Response,
  839. NativeToRap
  840. );
  841. //
  842. // Check if the entry is valid. If it is not, fix up pointers,
  843. // and start with the next entry in the list.
  844. // If there are more than 65536 auxiliary structures (which
  845. // probably never happens anyway), this entry is automatically
  846. // invalid.
  847. //
  848. status = (*VerifyFunction)(
  849. status,
  850. currentOutEntryPtr,
  851. OutBufferStart
  852. );
  853. if ( status != NERR_Success || inputAuxCount > 0xFFFF ) {
  854. invalidEntries++;
  855. currentInEntryPtr += inputStructureSize
  856. + inputAuxCount * inputAuxStructureSize;
  857. outputStringLocation = oldStringLocation;
  858. continue;
  859. }
  860. //
  861. // Prepare pointers for converting the auxiliary structures.
  862. //
  863. currentInEntryPtr += inputStructureSize;
  864. currentOutEntryPtr += outputStructureSize;
  865. //
  866. // Try to add the auxiliary structures.
  867. //
  868. for ( currentAux = 0; currentAux < inputAuxCount; currentAux++ ) {
  869. remainingSize = (DWORD)(outputStringLocation - currentOutEntryPtr);
  870. auxBytesRequired = 0;
  871. status = RapConvertSingleEntry(
  872. currentInEntryPtr,
  873. InAuxStructureDesc,
  874. FALSE,
  875. OutBufferStart,
  876. currentOutEntryPtr,
  877. OutAuxStructureDesc,
  878. TRUE,
  879. &outputStringLocation,
  880. &auxBytesRequired,
  881. Response,
  882. NativeToRap
  883. );
  884. //
  885. // Did this aux. entry fit? If all the aux. entries do not fit,
  886. // we are going to play it safe and say the main entry did not
  887. // fit.
  888. //
  889. if ( status != NERR_Success || auxBytesRequired > remainingSize ) {
  890. goto cleanup;
  891. }
  892. currentInEntryPtr += inputAuxStructureSize;
  893. currentOutEntryPtr += outputAuxStructureSize;
  894. newBytesRequired += auxBytesRequired;
  895. }
  896. *BytesRequired = newBytesRequired;
  897. *EntriesFilled += 1;
  898. }
  899. cleanup:
  900. if ( InvalidEntries != NULL ) {
  901. *InvalidEntries = invalidEntries;
  902. }
  903. return;
  904. } // XsFillAuxEnumBuffer
  905. VOID
  906. XsFillEnumBuffer (
  907. IN LPBYTE InBuffer,
  908. IN DWORD NumberOfEntries,
  909. IN LPDESC InStructureDesc,
  910. IN OUT LPBYTE OutBuffer,
  911. IN LPBYTE OutBufferStart,
  912. IN DWORD OutBufferLength,
  913. IN LPDESC OutStructureDesc,
  914. IN PXACTSRV_ENUM_VERIFY_FUNCTION VerifyFunction OPTIONAL,
  915. OUT LPDWORD BytesRequired,
  916. OUT LPDWORD EntriesFilled,
  917. OUT LPDWORD InvalidEntries OPTIONAL
  918. )
  919. /*++
  920. Routine Description:
  921. This routine copies all Enum structures from 32-bit format to
  922. 16-bit format. As many complete entries as possible are copied,
  923. then possibly some incomplete entries. All pointer fields
  924. are converted to offsets so that this buffer may be returned
  925. directly to the requesting client.
  926. Arguments:
  927. InBuffer - a pointer to the input information in 32-bit format.
  928. NumberOfEntries - the count of fixed structures in the input buffer.
  929. InStructureDesc - description of the input fixed structure.
  930. OutBuffer - a pointer to where to write the 16-bit buffer.
  931. OutBufferStart - a pointer to the actual start of the 16-bit buffer.
  932. Used to calculate offsets for all pointers in structures.
  933. OutBufferLength - length of the output buffer.
  934. OutStructureDesc - description of the output fixed structure.
  935. VerifyFunction - a pointer to a function which is be called after
  936. each enum record is converted in order to determine whether
  937. the record should be retained or discarded. The function
  938. is passed the return code from RapConvertSingleEntry and
  939. a pointer to the converted entry. It must return NERR_SUCCESS
  940. if the entry is to be retained, or any error code if the entry
  941. is to be discarded. If no function is supplied, a default function
  942. is used, which discards an entry only if RapConvertSingleEntry
  943. returned an error trying to convert it.
  944. BytesRequired - a pointer to a DWORD to receive the total number of
  945. bytes that would be required to hold the entire output buffer.
  946. EntriesFilled - a pointer to a DWORD to receive the total number of
  947. entries that could be put in the buffer given.
  948. InvalidEntries - an optional pointer to a DWORD to receive the total
  949. number of entries discarded by the verify function. If NULL, this
  950. value will be not be available to the caller.
  951. Return Value:
  952. None.
  953. --*/
  954. {
  955. NET_API_STATUS status;
  956. DWORD currentEntry;
  957. LPBYTE currentInEntryPtr;
  958. LPBYTE currentOutEntryPtr;
  959. LPBYTE outputStringLocation;
  960. LPBYTE oldStringLocation;
  961. DWORD inputStructureSize;
  962. DWORD outputStructureSize;
  963. DWORD newBytesRequired;
  964. DWORD invalidEntries = 0;
  965. if ( VerifyFunction == NULL ) {
  966. VerifyFunction = &XsDefaultEnumVerifyFunction;
  967. }
  968. //
  969. // Set up sizes of input and output structures.
  970. //
  971. inputStructureSize = RapStructureSize( InStructureDesc, Response, TRUE );
  972. outputStructureSize = RapStructureSize( OutStructureDesc, Response, FALSE );
  973. outputStringLocation = (LPBYTE)OutBuffer + OutBufferLength;
  974. *BytesRequired = 0;
  975. //
  976. // Check if one fixed entry will fit.
  977. //
  978. if ( inputStructureSize > OutBufferLength ) {
  979. *EntriesFilled = 0;
  980. goto cleanup;
  981. }
  982. //
  983. // Loop through the entries, converting along the way.
  984. //
  985. currentInEntryPtr = InBuffer;
  986. currentOutEntryPtr = OutBuffer;
  987. *EntriesFilled = 0;
  988. for ( currentEntry = 0; currentEntry < NumberOfEntries; currentEntry++ ) {
  989. //
  990. // If there wasn't enough room for the conversion, we can quit now.
  991. //
  992. if ( currentOutEntryPtr + outputStructureSize > outputStringLocation ) {
  993. break;
  994. }
  995. newBytesRequired = *BytesRequired;
  996. oldStringLocation = outputStringLocation;
  997. status = RapConvertSingleEntry(
  998. currentInEntryPtr,
  999. InStructureDesc,
  1000. FALSE,
  1001. OutBufferStart,
  1002. currentOutEntryPtr,
  1003. OutStructureDesc,
  1004. TRUE,
  1005. &outputStringLocation,
  1006. &newBytesRequired,
  1007. Response,
  1008. NativeToRap
  1009. );
  1010. //
  1011. // If the conversion was successful, increment the buffer pointers,
  1012. // the count of bytes required, and the number of converted entries.
  1013. //
  1014. status = (*VerifyFunction)(
  1015. status,
  1016. currentOutEntryPtr,
  1017. OutBufferStart
  1018. );
  1019. if ( status == NERR_Success ) {
  1020. currentInEntryPtr += inputStructureSize;
  1021. currentOutEntryPtr += outputStructureSize;
  1022. *BytesRequired = newBytesRequired;
  1023. *EntriesFilled += 1;
  1024. } else {
  1025. invalidEntries++;
  1026. currentInEntryPtr += inputStructureSize;
  1027. outputStringLocation = oldStringLocation;
  1028. }
  1029. }
  1030. cleanup:
  1031. if ( InvalidEntries != NULL ) {
  1032. *InvalidEntries = invalidEntries;
  1033. }
  1034. return;
  1035. } // XsFillEnumBuffer
  1036. LPBYTE
  1037. XsFindParameters (
  1038. IN LPTRANSACTION Transaction
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This routine finds the start of the parameters section in the
  1043. transaction block of a remote down-level API request.
  1044. Arguments:
  1045. Transaction - a pointer to a transaction block containing information
  1046. about the API to process.
  1047. Return Value:
  1048. None.
  1049. --*/
  1050. {
  1051. LPBYTE s;
  1052. //
  1053. // Skip over the API number and parameters description string.
  1054. //
  1055. for ( s = Transaction->InParameters + 2; *s != '\0'; s++ );
  1056. //
  1057. // Skip over the zero terminator and the data description string.
  1058. //
  1059. for ( s++; *s != '\0'; s++ );
  1060. //
  1061. // Return a pointer to the location after the zero terminator.
  1062. //
  1063. return s + 1;
  1064. } // XsFindParameters
  1065. WORD
  1066. XsPackReturnData (
  1067. IN LPVOID Buffer,
  1068. IN WORD BufferLength,
  1069. IN LPDESC Descriptor,
  1070. IN DWORD EntriesRead
  1071. )
  1072. /*++
  1073. Routine Description:
  1074. This routine, called by get info and enum API handlers, packs the
  1075. output data so that no unused data is returned to the client. This
  1076. is necessary because buffers are filled with variable-length data
  1077. starting at the end, thereby leaving potentially large gaps of
  1078. unused space between the end of fixed structures and the beginning
  1079. of variable-length data.
  1080. Arguments:
  1081. Buffer - a pointer to the buffer to pack.
  1082. BufferLength - the length of this buffer.
  1083. Descriptor - a pointer to a string which describes the fixed structures
  1084. in the buffer.
  1085. EntriesRead - the count of fixed structures in the buffer.
  1086. Return Value:
  1087. WORD - the "converter word" which informs the client how much
  1088. to adjust pointers in the fixed structures so that they are
  1089. meaningful.
  1090. --*/
  1091. {
  1092. DWORD structureSize;
  1093. LPBYTE lastFixedStructure;
  1094. LPBYTE endOfFixedStructures;
  1095. DWORD lastPointerOffset;
  1096. DWORD beginningOfVariableData;
  1097. //
  1098. // If there is no data, return immediately.
  1099. //
  1100. if ( EntriesRead == 0 ) {
  1101. return 0;
  1102. }
  1103. //
  1104. // Find the size of a single fixed-length structure.
  1105. //
  1106. structureSize = RapStructureSize( Descriptor, Response, FALSE );
  1107. //
  1108. // Use this and the number of entries to find the location of the
  1109. // last fixed structure and where the fixed structures end.
  1110. //
  1111. endOfFixedStructures = (LPBYTE)Buffer + EntriesRead * structureSize;
  1112. lastFixedStructure = endOfFixedStructures - structureSize;
  1113. //
  1114. // Find the offset into the fixed structure of the last pointer
  1115. // to variable data. The value stored at this offset in the last
  1116. // structure is the offset to the first variable data.
  1117. //
  1118. lastPointerOffset = RapLastPointerOffset( Descriptor, Response, FALSE );
  1119. //
  1120. // If there are no pointers, there is obviously no data to pack.
  1121. //
  1122. if ( lastPointerOffset == NO_POINTER_IN_STRUCTURE ) {
  1123. return 0;
  1124. }
  1125. beginningOfVariableData =
  1126. SmbGetUlong( (LPDWORD)(lastFixedStructure + lastPointerOffset) );
  1127. //
  1128. // If this offset is NULL, then the data overflowed, hence the buffer
  1129. // is nearly full. Don't do any packing.
  1130. //
  1131. // Also, if the gap is less than MAXIMUM_ALLOWABLE_DATA_GAP then it
  1132. // isn't worth doing the packing because of the time involved in
  1133. // the data copy.
  1134. //
  1135. if ( beginningOfVariableData == (DWORD)0 ||
  1136. (DWORD_PTR)Buffer + beginningOfVariableData -
  1137. (DWORD_PTR)endOfFixedStructures <= MAXIMUM_ALLOWABLE_DATA_GAP ) {
  1138. return 0;
  1139. }
  1140. //
  1141. // Move the variable data up to follow the fixed structures.
  1142. //
  1143. RtlMoveMemory(
  1144. endOfFixedStructures,
  1145. (LPBYTE)Buffer + beginningOfVariableData,
  1146. BufferLength - beginningOfVariableData
  1147. );
  1148. //
  1149. // Return the distance we moved the variable data.
  1150. //
  1151. return (WORD)( (DWORD_PTR)Buffer + beginningOfVariableData -
  1152. (DWORD_PTR)endOfFixedStructures );
  1153. } // XsPackReturnData
  1154. VOID
  1155. XsSetDataCount(
  1156. IN OUT LPWORD DataCount,
  1157. IN LPDESC Descriptor,
  1158. IN WORD Converter,
  1159. IN DWORD EntriesRead,
  1160. IN WORD ReturnStatus
  1161. )
  1162. /*++
  1163. Routine Description:
  1164. This routine calculates the return data count based on a number
  1165. of characteristics of the return data. This routine will examine
  1166. the buffer size, the number of entries placed in the buffer,
  1167. whether the data was packed, and what the return code was to
  1168. determine the return data size. The following assumptions are made
  1169. about the data: only calls with ReturnCode = NERR_Success or
  1170. ERROR_MORE_DATA return any data to the client; and if there is
  1171. no pointer in the fixed entries, then there is no variable data.
  1172. Handlers which cannot assure these two assumptions must determine
  1173. the data count manually.
  1174. Arguments:
  1175. DataCount - a pointer to a short word indicating the maximum
  1176. return data count (usually the BufLen parameter). On return,
  1177. this word will hold the actual return data count.
  1178. Descriptor - a string describing the structure of the fixed
  1179. entries in the buffer.
  1180. Converter - The adjustment value for pointers in data. A non-zero
  1181. value indicates data in the buffer is packed.
  1182. EntriesRead - Number of entries placed in the buffer. Used to
  1183. determine data count for buffers with no variable data.
  1184. ReturnStatus - Return status of the API call, as it will be returned
  1185. to the client (in other words, converted to a WORD).
  1186. Return Value:
  1187. None.
  1188. --*/
  1189. {
  1190. if (( ReturnStatus != NERR_Success )
  1191. && ( ReturnStatus != ERROR_MORE_DATA)) {
  1192. //
  1193. // If the return status is not NERR_Success or ERROR_MORE_DATA, then
  1194. // the return data count is 0.
  1195. SmbPutUshort( DataCount, 0 );
  1196. return;
  1197. }
  1198. if ( RapLastPointerOffset( Descriptor, Response, FALSE )
  1199. == NO_POINTER_IN_STRUCTURE ) {
  1200. //
  1201. // If there is no variable data, the return data count is the size
  1202. // of the fixed structures.
  1203. SmbPutUshort( DataCount,
  1204. (WORD)(RapStructureSize( Descriptor, Response, FALSE )
  1205. * EntriesRead ));
  1206. return;
  1207. }
  1208. SmbPutUshort( DataCount, SmbGetUshort( DataCount ) - Converter );
  1209. return;
  1210. } // XsSetDataCount
  1211. VOID
  1212. XsSetParameters (
  1213. IN LPTRANSACTION Transaction,
  1214. IN LPXS_PARAMETER_HEADER Header,
  1215. IN LPVOID Parameters
  1216. )
  1217. /*++
  1218. Routine Description:
  1219. This routine takes parameters from the structure allocated by
  1220. XsCaptureParameters and uses the descriptor string to place them in
  1221. the correct format in the transaction block. It also frees the
  1222. buffer holding the parameter structure.
  1223. Arguments:
  1224. Transaction - a pointer to the transaction block describing the
  1225. request.
  1226. Header - a pointer to the parameter header, which contains information
  1227. from the API handler such as the converter word and return status.
  1228. Parameters - a pointer to the parameter structure.
  1229. Return Value:
  1230. None.
  1231. --*/
  1232. {
  1233. LPBYTE inParams = Parameters;
  1234. LPBYTE outParams = Transaction->OutParameters;
  1235. LPDESC descriptorString;
  1236. LPDESC descriptor;
  1237. LPBYTE outParamsMax = outParams + Transaction->MaxParameterCount;
  1238. //
  1239. // The first two bytes of the parameter section are the API number,
  1240. // then comes the descriptor string.
  1241. //
  1242. descriptorString = Transaction->InParameters + 2;
  1243. //
  1244. // Set up the first part of the output parameters from the parameter
  1245. // header.
  1246. //
  1247. if( outParams + sizeof(WORD) > outParamsMax ) goto insuff_buffer;
  1248. SmbPutUshort( (LPWORD)outParams, Header->Status );
  1249. outParams += sizeof(WORD);
  1250. if( outParams + sizeof(WORD) > outParamsMax ) goto insuff_buffer;
  1251. SmbPutUshort( (LPWORD)outParams, Header->Converter );
  1252. outParams += sizeof(WORD);
  1253. //
  1254. // Initially set the size of the return data to 0. If there is a
  1255. // receive buffer for this call, the API handler has changed the
  1256. // buffer length parameter to the count of data returned, which
  1257. // will be transferred to the DataCount variable later.
  1258. //
  1259. Transaction->DataCount = 0;
  1260. //
  1261. // Walk through the descriptor string, converting from the total
  1262. // parameter set to the smaller set passed back to the client. In
  1263. // general, only information the client does not already know is
  1264. // passed back as parameters.
  1265. //
  1266. for ( descriptor = descriptorString; *descriptor != '\0'; ) {
  1267. switch ( *descriptor++ ) {
  1268. case REM_ASCIZ:
  1269. case REM_NULL_PTR:
  1270. //
  1271. // !!! Parameter string descriptors may not have maximum length
  1272. // counts.
  1273. //
  1274. NetpAssert( !isdigit( *descriptor ));
  1275. //
  1276. // The parameter is a pointer to a string, which is
  1277. // not returned to the client.
  1278. //
  1279. inParams += sizeof(LPSTR);
  1280. break;
  1281. case REM_BYTE_PTR:
  1282. case REM_FILL_BYTES:
  1283. //
  1284. // Array of bytes, doesn't get sent back.
  1285. //
  1286. //
  1287. // Skip over any numeric characters in descriptor.
  1288. //
  1289. RapAsciiToDecimal( &descriptor );
  1290. inParams += sizeof(LPBYTE);
  1291. break;
  1292. case REM_DWORD:
  1293. //
  1294. // The parameter is a input word not returned to the client.
  1295. //
  1296. // !!! This assumes that an array of dwords will never be passed
  1297. // as a parameter.
  1298. NetpAssert( !isdigit( *descriptor ));
  1299. inParams += sizeof(DWORD);
  1300. break;
  1301. case REM_ENTRIES_READ:
  1302. case REM_RCV_WORD_PTR:
  1303. //
  1304. // Count of entries read (e) or receive word pointer (h).
  1305. // This is an output parameter, so copy over the word.
  1306. //
  1307. if( outParams + sizeof(WORD) > outParamsMax ) goto insuff_buffer;
  1308. SmbPutUshort(
  1309. (LPWORD)outParams,
  1310. SmbGetUshort( (LPWORD)inParams )
  1311. );
  1312. inParams += sizeof(WORD);
  1313. outParams += sizeof(WORD);
  1314. break;
  1315. case REM_RCV_DWORD_PTR:
  1316. //
  1317. // Count of receive dword pointer (h).
  1318. // This is an output parameter, so copy over the word.
  1319. //
  1320. if( outParams + sizeof(DWORD) > outParamsMax ) goto insuff_buffer;
  1321. SmbPutUlong(
  1322. (LPDWORD)outParams,
  1323. SmbGetUlong( (LPDWORD)inParams )
  1324. );
  1325. inParams += sizeof(DWORD);
  1326. outParams += sizeof(DWORD);
  1327. break;
  1328. case REM_RCV_BUF_LEN:
  1329. //
  1330. // The length of the receive buffer (r). The parameter is not
  1331. // returned to the client, but it is used to set the return
  1332. // data count.
  1333. //
  1334. Transaction->DataCount = (DWORD)SmbGetUshort( (LPWORD)inParams );
  1335. inParams += sizeof(WORD);
  1336. break;
  1337. case REM_RCV_BUF_PTR:
  1338. case REM_SEND_BUF_PTR:
  1339. //
  1340. // A pointer to a data buffer. This is not returned to the
  1341. // client.
  1342. //
  1343. inParams += sizeof(LPBYTE);
  1344. break;
  1345. case REM_RCV_BYTE_PTR: {
  1346. //
  1347. // The parameter indicates return bytes.
  1348. //
  1349. DWORD arraySize;
  1350. arraySize = sizeof(BYTE) * RapDescArrayLength( descriptor );
  1351. if( outParams + arraySize > outParamsMax ) goto insuff_buffer;
  1352. RtlCopyMemory( outParams, inParams, arraySize );
  1353. outParams += arraySize;
  1354. inParams += arraySize;
  1355. break;
  1356. }
  1357. case REM_SEND_BUF_LEN:
  1358. case REM_WORD:
  1359. case REM_PARMNUM:
  1360. //
  1361. // The parameter is a input word not returned to the client.
  1362. //
  1363. // !!! This assumes that an array of words will never be passed
  1364. // as a parameter.
  1365. NetpAssert( !isdigit( *descriptor ));
  1366. inParams += sizeof(WORD);
  1367. break;
  1368. default:
  1369. IF_DEBUG(ERRORS) {
  1370. NetpKdPrint(( "XsSetParameters: unsupported character at %lx: %c\n",
  1371. descriptor - 1, *( descriptor - 1 )));
  1372. NetpBreakPoint( );
  1373. }
  1374. }
  1375. }
  1376. //
  1377. // Indicate the number of response parameter bytes.
  1378. //
  1379. Transaction->ParameterCount =
  1380. (DWORD)((DWORD_PTR)outParams - (DWORD_PTR)(Transaction->OutParameters) );
  1381. //
  1382. // Free the parameter buffer allocated by XsCaptureParameters.
  1383. //
  1384. NetpMemoryFree( Header );
  1385. return;
  1386. insuff_buffer:
  1387. Header->Status = NERR_BufTooSmall;
  1388. return;
  1389. } // XsSetParameters
  1390. NET_API_STATUS
  1391. XsValidateShareName(
  1392. IN LPSTR ShareName
  1393. )
  1394. /*++
  1395. Routine Description:
  1396. This routine determines whether the supplied string is a valid share
  1397. name of the format \\computer\share, with both computer name and
  1398. share name no longer than permitted by LanMan 2.0. It does not
  1399. attempt to determine whether the share actually exists.
  1400. Arguments:
  1401. ShareName - The share name to be validated (an ASCII string)
  1402. Return Value:
  1403. NET_API_STATUS - NERR_Success if the share name is valid,
  1404. ERROR_INVALID_PARAMETER otherwise.
  1405. --*/
  1406. {
  1407. DWORD componentLength;
  1408. NET_API_STATUS status = NERR_Success;
  1409. if ( ShareName == NULL ) { // NULL is OK
  1410. return NERR_Success;
  1411. }
  1412. componentLength = 0;
  1413. while ( *ShareName == '\\' ) {
  1414. componentLength++;
  1415. ShareName++;
  1416. }
  1417. if ( componentLength != 2 ) {
  1418. status = ERROR_INVALID_PARAMETER;
  1419. goto cleanup;
  1420. }
  1421. componentLength = 0;
  1422. while (( *ShareName != '\\' ) && ( *ShareName != '\0' )) {
  1423. componentLength++;
  1424. ShareName++;
  1425. }
  1426. if (( *ShareName == '\0' ) ||
  1427. ( componentLength < 1 ) || ( componentLength > MAX_PATH )) {
  1428. status = ERROR_INVALID_PARAMETER;
  1429. goto cleanup;
  1430. }
  1431. componentLength = 0;
  1432. while ( *ShareName == '\\' ) {
  1433. componentLength++;
  1434. ShareName++;
  1435. }
  1436. if ( componentLength != 1 ) {
  1437. status = ERROR_INVALID_PARAMETER;
  1438. goto cleanup;
  1439. }
  1440. componentLength = 0;
  1441. while (( *ShareName != '\\' ) && ( *ShareName != '\0' )) {
  1442. componentLength++;
  1443. ShareName++;
  1444. }
  1445. if (( *ShareName == '\\' ) ||
  1446. ( componentLength < 1 ) || ( componentLength > MAX_PATH )) {
  1447. status = ERROR_INVALID_PARAMETER;
  1448. goto cleanup;
  1449. }
  1450. cleanup:
  1451. return status;
  1452. }
  1453. VOID
  1454. SmbCapturePtr(
  1455. LPBYTE PointerDestination,
  1456. LPBYTE PointerValue
  1457. )
  1458. /*++
  1459. Routine Description:
  1460. This routine captures a pointer from the supplied buffer and places it
  1461. into the destination buffer.
  1462. Arguments:
  1463. PointerDestination - A pointer to the pointer value destination.
  1464. PointerSource - A pointer to the pointer value source.
  1465. Return Value:
  1466. None.
  1467. --*/
  1468. {
  1469. XsSmbPutPointer( PointerDestination, PointerValue );
  1470. }