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.

1461 lines
43 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. ea.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to query/set ea/security.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. //
  11. // Forward declarations.
  12. //
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, MRxSmbQueryEaInformation)
  15. #pragma alloc_text(PAGE, MRxSmbSetEaInformation)
  16. #pragma alloc_text(PAGE, MRxSmbQuerySecurityInformation)
  17. #pragma alloc_text(PAGE, MRxSmbSetSecurityInformation)
  18. #pragma alloc_text(PAGE, MRxSmbLoadEaList)
  19. #pragma alloc_text(PAGE, MRxSmbNtGeaListToOs2)
  20. #pragma alloc_text(PAGE, MRxSmbNtGetEaToOs2)
  21. #pragma alloc_text(PAGE, MRxSmbQueryEasFromServer)
  22. #pragma alloc_text(PAGE, MRxSmbNtFullEaSizeToOs2)
  23. #pragma alloc_text(PAGE, MRxSmbNtFullListToOs2)
  24. #pragma alloc_text(PAGE, MRxSmbNtFullEaToOs2)
  25. #pragma alloc_text(PAGE, MRxSmbSetEaList)
  26. #endif
  27. ////
  28. //// The Bug check file id for this module
  29. ////
  30. //
  31. //#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE)
  32. //
  33. // The local debug trace level
  34. //
  35. #define Dbg (DEBUG_TRACE_EA)
  36. //this is the largest EAs that could ever be returned! oh my god!
  37. //this is used to simulate the nt resumable queryEA using the downlevel call
  38. //sigh!
  39. #define EA_QUERY_SIZE 0x0000ffff
  40. //for QueryEA
  41. NTSTATUS
  42. MRxSmbLoadEaList(
  43. IN PRX_CONTEXT RxContext,
  44. IN PUCHAR UserEaList,
  45. IN ULONG UserEaListLength,
  46. OUT PFEALIST *ServerEaList
  47. );
  48. NTSTATUS
  49. MRxSmbQueryEasFromServer(
  50. IN PRX_CONTEXT RxContext,
  51. IN PFEALIST ServerEaList,
  52. IN PVOID Buffer,
  53. IN OUT PULONG BufferLengthRemaining,
  54. IN BOOLEAN ReturnSingleEntry,
  55. IN BOOLEAN UserEaListSupplied
  56. );
  57. //for SetEA
  58. NTSTATUS
  59. MRxSmbSetEaList(
  60. // IN PICB Icb,
  61. // IN PIRP Irp,
  62. IN PRX_CONTEXT RxContext,
  63. IN PFEALIST ServerEaList
  64. );
  65. VOID MRxSmbExtraEaRoutine(LONG i){
  66. RxDbgTrace( 0, Dbg, ("MRxSmbExtraEaRoutine i=%08lx\n", i ));
  67. }
  68. NTSTATUS
  69. MRxSmbQueryEaInformation (
  70. IN OUT PRX_CONTEXT RxContext
  71. )
  72. {
  73. NTSTATUS Status;
  74. RxCaptureFcb;
  75. RxCaptureFobx;
  76. PSMBCEDB_SERVER_ENTRY pServerEntry;
  77. PVOID Buffer = RxContext->Info.Buffer;
  78. PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
  79. PUCHAR UserEaList = RxContext->QueryEa.UserEaList;
  80. ULONG UserEaListLength = RxContext->QueryEa.UserEaListLength;
  81. ULONG UserEaIndex = RxContext->QueryEa.UserEaIndex;
  82. BOOLEAN RestartScan = RxContext->QueryEa.RestartScan;
  83. BOOLEAN ReturnSingleEntry = RxContext->QueryEa.ReturnSingleEntry;
  84. BOOLEAN IndexSpecified = RxContext->QueryEa.IndexSpecified;
  85. PFEALIST ServerEaList = NULL;
  86. PAGED_CODE();
  87. RxDbgTrace(+1, Dbg, ("MRxSmbQueryEaInformation\n"));
  88. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  89. //get rid of nonEA guys right now
  90. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_SUPPORTEA)) {
  91. RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
  92. return((STATUS_NOT_SUPPORTED));
  93. }
  94. Status = MRxSmbDeferredCreate(RxContext);
  95. if (Status!=STATUS_SUCCESS) {
  96. goto FINALLY;
  97. }
  98. Status = MRxSmbLoadEaList( RxContext, UserEaList, UserEaListLength, &ServerEaList );
  99. if (( !NT_SUCCESS( Status ) )||
  100. ( ServerEaList == NULL )) {
  101. goto FINALLY;
  102. }
  103. if (IndexSpecified) {
  104. capFobx->OffsetOfNextEaToReturn = UserEaIndex;
  105. Status = MRxSmbQueryEasFromServer(
  106. RxContext,
  107. ServerEaList,
  108. Buffer,
  109. pLengthRemaining,
  110. ReturnSingleEntry,
  111. (BOOLEAN)(UserEaList != NULL) );
  112. //
  113. // if there are no Ea's on the file, and the user supplied an EA
  114. // index, we want to map the error to STATUS_NONEXISTANT_EA_ENTRY.
  115. //
  116. if ( Status == STATUS_NO_EAS_ON_FILE ) {
  117. Status = STATUS_NONEXISTENT_EA_ENTRY;
  118. }
  119. } else {
  120. if ( ( RestartScan == TRUE ) || (UserEaList != NULL) ){
  121. //
  122. // Ea Indices start at 1, not 0....
  123. //
  124. capFobx->OffsetOfNextEaToReturn = 1;
  125. }
  126. Status = MRxSmbQueryEasFromServer( //it is offensive to have two identical calls but oh, well.....
  127. RxContext,
  128. ServerEaList,
  129. Buffer,
  130. pLengthRemaining,
  131. ReturnSingleEntry,
  132. (BOOLEAN)(UserEaList != NULL) );
  133. }
  134. FINALLY:
  135. if ( ServerEaList != NULL) {
  136. RxFreePool(ServerEaList);
  137. }
  138. RxDbgTrace(-1, Dbg, ("MRxSmbQueryEaInformation st=%08lx\n",Status));
  139. return Status;
  140. }
  141. NTSTATUS
  142. MRxSmbSetEaInformation (
  143. IN OUT struct _RX_CONTEXT * RxContext
  144. )
  145. {
  146. NTSTATUS Status;
  147. RxCaptureFcb; RxCaptureFobx;
  148. PSMBCEDB_SERVER_ENTRY pServerEntry;
  149. PVOID Buffer = RxContext->Info.Buffer;
  150. ULONG Length = RxContext->Info.Length;
  151. PFEALIST ServerEaList = NULL;
  152. ULONG Size;
  153. PAGED_CODE();
  154. RxDbgTrace(+1, Dbg, ("MRxSmbSetEaInformation\n"));
  155. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  156. //get rid of nonEA guys right now
  157. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_SUPPORTEA)) {
  158. RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
  159. return((STATUS_NOT_SUPPORTED));
  160. }
  161. Status = MRxSmbDeferredCreate(RxContext);
  162. if (Status!=STATUS_SUCCESS) {
  163. goto FINALLY;
  164. }
  165. //
  166. // Convert Nt format FEALIST to OS/2 format
  167. //
  168. Size = MRxSmbNtFullEaSizeToOs2 ( Buffer );
  169. if ( Size > 0x0000ffff ) {
  170. Status = STATUS_EA_TOO_LARGE;
  171. goto FINALLY;
  172. }
  173. ServerEaList = RxAllocatePool ( PagedPool, EA_QUERY_SIZE );
  174. if ( ServerEaList == NULL ) {
  175. Status = STATUS_INSUFFICIENT_RESOURCES;
  176. goto FINALLY;
  177. }
  178. MRxSmbNtFullListToOs2 ( Buffer, ServerEaList );
  179. //
  180. // Set EAs on the file/directory; if the error is EA_ERROR then SetEaList
  181. // sets iostatus.information to the offset of the offender
  182. //
  183. Status = MRxSmbSetEaList( RxContext, ServerEaList);
  184. FINALLY:
  185. if ( ServerEaList != NULL) {
  186. RxFreePool(ServerEaList);
  187. }
  188. RxDbgTrace(-1, Dbg, ("MRxSmbSetEaInformation st=%08lx\n",Status));
  189. return Status;
  190. }
  191. NTSTATUS
  192. MRxSmbQuerySecurityInformation (
  193. IN OUT PRX_CONTEXT RxContext
  194. )
  195. /*++
  196. Routine Description:
  197. This routine implements the NtQuerySecurityFile api.
  198. Arguments:
  199. Return Value:
  200. Status - Result of the operation.
  201. --*/
  202. {
  203. RxCaptureFcb;
  204. RxCaptureFobx;
  205. PVOID Buffer = RxContext->Info.Buffer;
  206. PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
  207. PMRX_SMB_SRV_OPEN smbSrvOpen;
  208. PSMBCEDB_SERVER_ENTRY pServerEntry;
  209. NTSTATUS Status;
  210. REQ_QUERY_SECURITY_DESCRIPTOR QuerySecurityRequest;
  211. RESP_QUERY_SECURITY_DESCRIPTOR QuerySecurityResponse;
  212. PBYTE pInputParamBuffer = NULL;
  213. PBYTE pOutputParamBuffer = NULL;
  214. PBYTE pInputDataBuffer = NULL;
  215. PBYTE pOutputDataBuffer = NULL;
  216. ULONG InputParamBufferLength = 0;
  217. ULONG OutputParamBufferLength = 0;
  218. ULONG InputDataBufferLength = 0;
  219. ULONG OutputDataBufferLength = 0;
  220. PAGED_CODE();
  221. RxDbgTrace(+1, Dbg, ("MRxSmbQuerySecurityInformation...\n"));
  222. // Turn away this call from those servers which do not support the NT SMBs
  223. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  224. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  225. RxDbgTrace(-1, Dbg, ("QuerySecurityDescriptor not supported!\n"));
  226. return((STATUS_NOT_SUPPORTED));
  227. }
  228. Status = MRxSmbDeferredCreate(RxContext);
  229. if (Status!=STATUS_SUCCESS) {
  230. goto FINALLY;
  231. }
  232. Status = STATUS_MORE_PROCESSING_REQUIRED;
  233. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  234. ASSERT (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN));
  235. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  236. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  237. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  238. //BOOLEAN printflag;
  239. TransactionOptions.NtTransactFunction = NT_TRANSACT_QUERY_SECURITY_DESC;
  240. //TransactionOptions.Flags |= SMB_XACT_FLAGS_COPY_ON_ERROR;
  241. QuerySecurityRequest.Fid = smbSrvOpen->Fid;
  242. QuerySecurityRequest.Reserved = 0;
  243. QuerySecurityRequest.SecurityInformation = RxContext->QuerySecurity.SecurityInformation;
  244. QuerySecurityResponse.LengthNeeded = 0xbaadbaad;
  245. //printflag = RxDbgTraceDisableGlobally();//this is debug code anyway!
  246. //RxDbgTraceEnableGlobally(FALSE);
  247. Status = SmbCeTransact(
  248. RxContext, // the RXContext for the transaction
  249. &TransactionOptions, // transaction options
  250. NULL, // the setup buffer
  251. 0, // input setup buffer length
  252. NULL, // output setup buffer
  253. 0, // output setup buffer length
  254. &QuerySecurityRequest, // Input Param Buffer
  255. sizeof(QuerySecurityRequest), // Input param buffer length
  256. &QuerySecurityResponse, // Output param buffer
  257. sizeof(QuerySecurityResponse),// output param buffer length
  258. NULL, // Input data buffer
  259. 0, // Input data buffer length
  260. Buffer, // output data buffer
  261. *pLengthRemaining, // output data buffer length
  262. &ResumptionContext // the resumption context
  263. );
  264. //DbgPrint("QSR.len=%x\n", QuerySecurityResponse.LengthNeeded);
  265. if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_TOO_SMALL)) {
  266. ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
  267. RxContext->InformationToReturn = QuerySecurityResponse.LengthNeeded;
  268. RxDbgTrace(0, Dbg, ("MRxSmbQuerySecurityInformation...ReturnedDataCount=%08lx\n",ReturnedDataCount));
  269. ASSERT(ResumptionContext.ParameterBytesReceived == sizeof(RESP_QUERY_SECURITY_DESCRIPTOR));
  270. if (((LONG)(QuerySecurityResponse.LengthNeeded)) > *pLengthRemaining) {
  271. Status = STATUS_BUFFER_OVERFLOW;
  272. }
  273. }
  274. //RxDbgTraceEnableGlobally(printflag);
  275. }
  276. FINALLY:
  277. RxDbgTrace(-1, Dbg, ("MRxSmbQuerySecurityInformation...exit, st=%08lx,info=%08lx\n",
  278. Status, RxContext->InformationToReturn));
  279. return Status;
  280. }
  281. NTSTATUS
  282. MRxSmbSetSecurityInformation (
  283. IN OUT struct _RX_CONTEXT * RxContext
  284. )
  285. {
  286. RxCaptureFcb;
  287. RxCaptureFobx;
  288. PMRX_SMB_SRV_OPEN smbSrvOpen;
  289. PSMBCEDB_SERVER_ENTRY pServerEntry;
  290. NTSTATUS Status;
  291. REQ_SET_SECURITY_DESCRIPTOR SetSecurityRequest;
  292. PAGED_CODE();
  293. RxDbgTrace(+1, Dbg, ("MRxSmbSetSecurityInformation...\n"));
  294. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  295. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  296. RxDbgTrace(-1, Dbg, ("Set Security Descriptor not supported!\n"));
  297. return((STATUS_NOT_SUPPORTED));
  298. }
  299. Status = MRxSmbDeferredCreate(RxContext);
  300. if (Status!=STATUS_SUCCESS) {
  301. goto FINALLY;
  302. }
  303. Status = STATUS_MORE_PROCESSING_REQUIRED;
  304. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  305. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  306. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  307. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  308. ULONG SdLength = RtlLengthSecurityDescriptor(RxContext->SetSecurity.SecurityDescriptor);
  309. TransactionOptions.NtTransactFunction = NT_TRANSACT_SET_SECURITY_DESC;
  310. SetSecurityRequest.Fid = smbSrvOpen->Fid;
  311. SetSecurityRequest.Reserved = 0;
  312. SetSecurityRequest.SecurityInformation = RxContext->SetSecurity.SecurityInformation;
  313. Status = SmbCeTransact(
  314. RxContext, // the RXContext for the transaction
  315. &TransactionOptions, // transaction options
  316. NULL, // the input setup buffer
  317. 0, // input setup buffer length
  318. NULL, // the output setup buffer
  319. 0, // output setup buffer length
  320. &SetSecurityRequest, // Input Param Buffer
  321. sizeof(SetSecurityRequest), // Input param buffer length
  322. NULL, // Output param buffer
  323. 0, // output param buffer length
  324. RxContext->SetSecurity.SecurityDescriptor, // Input data buffer
  325. SdLength, // Input data buffer length
  326. NULL, // output data buffer
  327. 0, // output data buffer length
  328. &ResumptionContext // the resumption context
  329. );
  330. //the old rdr doesn't return any info...................
  331. //RxContext->InformationToReturn = SetSecurityResponse.LengthNeeded;
  332. if ( NT_SUCCESS(Status) ) {
  333. ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
  334. RxDbgTrace(0, Dbg, ("MRxSmbSetSecurityInformation...ReturnedDataCount=%08lx\n",ReturnedDataCount));
  335. ASSERT(ResumptionContext.ParameterBytesReceived == 0);
  336. ASSERT(ResumptionContext.SetupBytesReceived == 0);
  337. ASSERT(ResumptionContext.DataBytesReceived == 0);
  338. }
  339. }
  340. FINALLY:
  341. RxDbgTrace(-1, Dbg, ("MRxSmbSetSecurityInformation...exit, st=%08lx,info=%08lx\n",
  342. Status, RxContext->InformationToReturn));
  343. return Status;
  344. }
  345. NTSTATUS
  346. MRxSmbLoadEaList(
  347. IN PRX_CONTEXT RxContext,
  348. IN PUCHAR UserEaList,
  349. IN ULONG UserEaListLength,
  350. OUT PFEALIST *ServerEaList
  351. )
  352. /*++
  353. Routine Description:
  354. This routine implements the NtQueryEaFile api.
  355. It returns the following information:
  356. Arguments:
  357. IN PUCHAR UserEaList; - Supplies the Ea names required.
  358. IN ULONG UserEaListLength;
  359. OUT PFEALIST *ServerEaList - Eas returned by the server. Caller is responsible for
  360. freeing memory.
  361. Return Value:
  362. Status - Result of the operation.
  363. --*/
  364. {
  365. RxCaptureFobx;
  366. PMRX_SMB_SRV_OPEN smbSrvOpen;
  367. NTSTATUS Status;
  368. USHORT Setup = TRANS2_QUERY_FILE_INFORMATION;
  369. REQ_QUERY_FILE_INFORMATION QueryFileInfoRequest;
  370. RESP_QUERY_FILE_INFORMATION QueryFileInfoResponse;
  371. PBYTE pInputParamBuffer = NULL;
  372. PBYTE pOutputParamBuffer = NULL;
  373. PBYTE pInputDataBuffer = NULL;
  374. PBYTE pOutputDataBuffer = NULL;
  375. ULONG InputParamBufferLength = 0;
  376. ULONG OutputParamBufferLength = 0;
  377. ULONG InputDataBufferLength = 0;
  378. ULONG OutputDataBufferLength = 0;
  379. CLONG OutDataCount = EA_QUERY_SIZE;
  380. CLONG OutSetupCount = 0;
  381. PFEALIST Buffer;
  382. PGEALIST ServerQueryEaList = NULL;
  383. CLONG InDataCount;
  384. PAGED_CODE();
  385. RxDbgTrace(+1, Dbg, ("MRxSmbLoadEaList...\n"));
  386. Status = STATUS_MORE_PROCESSING_REQUIRED;
  387. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  388. //
  389. // Convert the supplied UserEaList to a GEALIST. The server will return just the Eas
  390. // requested by the application.
  391. //
  392. //
  393. // If the application specified a subset of EaNames then convert to OS/2 1.2 format and
  394. // pass that to the server. ie. Use the server to filter out the names.
  395. //
  396. Buffer = RxAllocatePool ( PagedPool, OutDataCount );
  397. if ( Buffer == NULL ) {
  398. Status = STATUS_INSUFFICIENT_RESOURCES;
  399. goto FINALLY;
  400. }
  401. if ( UserEaList != NULL) {
  402. //
  403. // OS/2 format is always a little less than or equal to the NT UserEaList size.
  404. // This code relies on the I/O system verifying the EaList is valid.
  405. //
  406. ServerQueryEaList = RxAllocatePool ( PagedPool, UserEaListLength );
  407. if ( ServerQueryEaList == NULL ) {
  408. Status = STATUS_INSUFFICIENT_RESOURCES;
  409. goto FINALLY;
  410. };
  411. MRxSmbNtGeaListToOs2((PFILE_GET_EA_INFORMATION )UserEaList, UserEaListLength, ServerQueryEaList );
  412. InDataCount = (CLONG)ServerQueryEaList->cbList;
  413. } else {
  414. InDataCount = 0;
  415. }
  416. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  417. PSMB_TRANSACTION_OPTIONS pTransactionOptions = &RxDefaultTransactionOptions;
  418. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  419. QueryFileInfoRequest.Fid = smbSrvOpen->Fid;
  420. if ( UserEaList != NULL) {
  421. QueryFileInfoRequest.InformationLevel = SMB_INFO_QUERY_EAS_FROM_LIST;
  422. } else {
  423. QueryFileInfoRequest.InformationLevel = SMB_INFO_QUERY_ALL_EAS;
  424. }
  425. Status = SmbCeTransact(
  426. RxContext, // the RXContext for the transaction
  427. pTransactionOptions, // transaction options
  428. &Setup, // the setup buffer
  429. sizeof(Setup), // setup buffer length
  430. NULL, // the output setup buffer
  431. 0, // output setup buffer length
  432. &QueryFileInfoRequest, // Input Param Buffer
  433. sizeof(QueryFileInfoRequest), // Input param buffer length
  434. &QueryFileInfoResponse, // Output param buffer
  435. sizeof(QueryFileInfoResponse),// output param buffer length
  436. ServerQueryEaList, // Input data buffer
  437. InDataCount, // Input data buffer length
  438. Buffer, // output data buffer
  439. OutDataCount, // output data buffer length
  440. &ResumptionContext // the resumption context
  441. );
  442. if ( NT_SUCCESS(Status) ) {
  443. ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
  444. RxDbgTrace(0, Dbg, ("MRxSmbLoadEaList...ReturnedDataCount=%08lx\n",ReturnedDataCount));
  445. ASSERT(ResumptionContext.ParameterBytesReceived == sizeof(RESP_QUERY_FILE_INFORMATION));
  446. if ( SmbGetUlong( &((PFEALIST)Buffer)->cbList) != ReturnedDataCount ){
  447. Status = STATUS_EA_CORRUPT_ERROR;
  448. }
  449. if ( ReturnedDataCount == 0 ) {
  450. Status = STATUS_NO_EAS_ON_FILE;
  451. }
  452. }
  453. }
  454. FINALLY:
  455. if ( NT_SUCCESS(Status) ) {
  456. *ServerEaList = Buffer;
  457. } else {
  458. if (Buffer != NULL) {
  459. RxFreePool(Buffer);
  460. }
  461. }
  462. if ( ServerQueryEaList != NULL) {
  463. RxFreePool(ServerQueryEaList);
  464. }
  465. RxDbgTrace(-1, Dbg, ("MRxSmbLoadEaList...exit, st=%08lx\n",Status));
  466. return Status;
  467. }
  468. VOID
  469. MRxSmbNtGeaListToOs2 (
  470. IN PFILE_GET_EA_INFORMATION NtGetEaList,
  471. IN ULONG GeaListLength,
  472. IN PGEALIST GeaList
  473. )
  474. /*++
  475. Routine Description:
  476. Converts a single NT GET EA list to OS/2 GEALIST style. The GEALIST
  477. need not have any particular alignment.
  478. Arguments:
  479. NtGetEaList - An NT style get EA list to be converted to OS/2 format.
  480. GeaListLength - the maximum possible length of the GeaList.
  481. GeaList - Where to place the OS/2 1.2 style GEALIST.
  482. Return Value:
  483. none.
  484. --*/
  485. {
  486. PGEA gea = GeaList->list;
  487. PFILE_GET_EA_INFORMATION ntGetEa = NtGetEaList;
  488. PAGED_CODE();
  489. //
  490. // Copy the Eas up until the last one
  491. //
  492. while ( ntGetEa->NextEntryOffset != 0 ) {
  493. //
  494. // Copy the NT format EA to OS/2 1.2 format and set the gea
  495. // pointer for the next iteration.
  496. //
  497. gea = MRxSmbNtGetEaToOs2( gea, ntGetEa );
  498. ASSERT( (ULONG_PTR)gea <= (ULONG_PTR)GeaList + GeaListLength );
  499. ntGetEa = (PFILE_GET_EA_INFORMATION)((PCHAR)ntGetEa + ntGetEa->NextEntryOffset);
  500. }
  501. // Now copy the last entry.
  502. gea = MRxSmbNtGetEaToOs2( gea, ntGetEa );
  503. ASSERT( (ULONG_PTR)gea <= (ULONG_PTR)GeaList + GeaListLength );
  504. //
  505. // Set the number of bytes in the GEALIST.
  506. //
  507. SmbPutUlong(
  508. &GeaList->cbList,
  509. (ULONG)((PCHAR)gea - (PCHAR)GeaList)
  510. );
  511. UNREFERENCED_PARAMETER( GeaListLength );
  512. }
  513. PGEA
  514. MRxSmbNtGetEaToOs2 (
  515. OUT PGEA Gea,
  516. IN PFILE_GET_EA_INFORMATION NtGetEa
  517. )
  518. /*++
  519. Routine Description:
  520. Converts a single NT Get EA entry to OS/2 GEA style. The GEA need not have
  521. any particular alignment. This routine makes no checks on buffer
  522. overrunning--this is the responsibility of the calling routine.
  523. Arguments:
  524. Gea - a pointer to the location where the OS/2 GEA is to be written.
  525. NtGetEa - a pointer to the NT Get EA.
  526. Return Value:
  527. A pointer to the location after the last byte written.
  528. --*/
  529. {
  530. PCHAR ptr;
  531. PAGED_CODE();
  532. Gea->cbName = NtGetEa->EaNameLength;
  533. ptr = (PCHAR)(Gea) + 1;
  534. RtlCopyMemory( ptr, NtGetEa->EaName, NtGetEa->EaNameLength );
  535. ptr += NtGetEa->EaNameLength;
  536. *ptr++ = '\0';
  537. return ( (PGEA)ptr );
  538. }
  539. NTSTATUS
  540. MRxSmbQueryEasFromServer(
  541. IN PRX_CONTEXT RxContext,
  542. IN PFEALIST ServerEaList,
  543. IN PVOID Buffer,
  544. IN OUT PULONG BufferLengthRemaining,
  545. IN BOOLEAN ReturnSingleEntry,
  546. IN BOOLEAN UserEaListSupplied
  547. )
  548. /*++
  549. Routine Description:
  550. This routine copies the required number of Eas from the ServerEaList
  551. starting from the offset indicated in the Icb. The Icb is also updated
  552. to show the last Ea returned.
  553. Arguments:
  554. IN PFEALIST ServerEaList - Supplies the Ea List in OS/2 format.
  555. IN PVOID Buffer - Supplies where to put the NT format EAs
  556. IN OUT PULONG BufferLengthRemaining - Supplies the user buffer space.
  557. IN BOOLEAN ReturnSingleEntry
  558. IN BOOLEAN UserEaListSupplied - ServerEaList is a subset of the Eas
  559. Return Value:
  560. NTSTATUS - The status for the Irp.
  561. --*/
  562. {
  563. RxCaptureFobx;
  564. ULONG EaIndex = capFobx->OffsetOfNextEaToReturn;
  565. ULONG Index = 1;
  566. ULONG Size;
  567. ULONG OriginalLengthRemaining = *BufferLengthRemaining;
  568. BOOLEAN Overflow = FALSE;
  569. PFEA LastFeaStartLocation;
  570. PFEA Fea = NULL;
  571. PFEA LastFea = NULL;
  572. PFILE_FULL_EA_INFORMATION NtFullEa = Buffer;
  573. PFILE_FULL_EA_INFORMATION LastNtFullEa = Buffer;
  574. PAGED_CODE();
  575. RxDbgTrace(0, Dbg, ("MRxSmbQueryEasFromServer...EaIndex/Buffer/Remaining=%08lx/%08lx/%08lx\n",
  576. EaIndex,Buffer,((BufferLengthRemaining)?*BufferLengthRemaining:0xbadbad)
  577. ));
  578. //
  579. // If there are no Ea's present in the list, return the appropriate
  580. // error.
  581. //
  582. // Os/2 servers indicate that a list is null if cbList==4.
  583. //
  584. if ( SmbGetUlong(&ServerEaList->cbList) == FIELD_OFFSET(FEALIST, list) ) {
  585. return STATUS_NO_EAS_ON_FILE;
  586. }
  587. //
  588. // Find the last location at which an FEA can start.
  589. //
  590. LastFeaStartLocation = (PFEA)( (PCHAR)ServerEaList +
  591. SmbGetUlong( &ServerEaList->cbList ) -
  592. sizeof(FEA) - 1 );
  593. //
  594. // Go through the ServerEaList until we find the entry corresponding to EaIndex
  595. //
  596. for ( Fea = ServerEaList->list;
  597. (Fea <= LastFeaStartLocation) && (Index < EaIndex);
  598. Index+= 1,
  599. Fea = (PFEA)( (PCHAR)Fea + sizeof(FEA) +
  600. Fea->cbName + 1 + SmbGetUshort( &Fea->cbValue ) ) ) {
  601. NOTHING;
  602. }
  603. if ( Index != EaIndex ) {
  604. if ( Index == EaIndex+1 ) {
  605. return STATUS_NO_MORE_EAS;
  606. }
  607. //
  608. // No such index
  609. //
  610. return STATUS_NONEXISTENT_EA_ENTRY;
  611. }
  612. //
  613. // Go through the rest of the FEA list, converting from OS/2 1.2 format to NT
  614. // until we pass the last possible location in which an FEA can start.
  615. //
  616. for ( ;
  617. Fea <= LastFeaStartLocation;
  618. Fea = (PFEA)( (PCHAR)Fea + sizeof(FEA) +
  619. Fea->cbName + 1 + SmbGetUshort( &Fea->cbValue ) ) ) {
  620. PCHAR ptr;
  621. //
  622. // Calculate the size of this Fea when converted to an NT EA structure.
  623. //
  624. // The last field shouldn't be padded.
  625. //
  626. if ((PFEA)((PCHAR)Fea+sizeof(FEA)+Fea->cbName+1+SmbGetUshort(&Fea->cbValue)) < LastFeaStartLocation) {
  627. Size = SmbGetNtSizeOfFea( Fea );
  628. } else {
  629. Size = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
  630. Fea->cbName + 1 + SmbGetUshort(&Fea->cbValue);
  631. }
  632. //
  633. // Will the next Ea fit?
  634. //
  635. if ( *BufferLengthRemaining < Size ) {
  636. if ( LastNtFullEa != NtFullEa ) {
  637. if ( UserEaListSupplied == TRUE ) {
  638. *BufferLengthRemaining = OriginalLengthRemaining;
  639. return STATUS_BUFFER_OVERFLOW;
  640. }
  641. Overflow = TRUE;
  642. break;
  643. } else {
  644. // Not even room for a single EA!
  645. return STATUS_BUFFER_OVERFLOW;
  646. }
  647. } else {
  648. *BufferLengthRemaining -= Size;
  649. }
  650. //
  651. // We are comitted to copy the Os2 Fea to Nt format in the users buffer
  652. //
  653. LastNtFullEa = NtFullEa;
  654. LastFea = Fea;
  655. EaIndex++;
  656. // Create new Nt Ea
  657. NtFullEa->Flags = Fea->fEA;
  658. NtFullEa->EaNameLength = Fea->cbName;
  659. NtFullEa->EaValueLength = SmbGetUshort( &Fea->cbValue );
  660. ptr = NtFullEa->EaName;
  661. RtlCopyMemory( ptr, (PCHAR)(Fea+1), Fea->cbName );
  662. ptr += NtFullEa->EaNameLength;
  663. *ptr++ = '\0';
  664. //
  665. // Copy the EA value to the NT full EA.
  666. //
  667. RtlCopyMemory(
  668. ptr,
  669. (PCHAR)(Fea+1) + NtFullEa->EaNameLength + 1,
  670. NtFullEa->EaValueLength
  671. );
  672. ptr += NtFullEa->EaValueLength;
  673. //
  674. // Longword-align ptr to determine the offset to the next location
  675. // for an NT full EA.
  676. //
  677. ptr = (PCHAR)( ((ULONG_PTR)ptr + 3) & ~3 );
  678. NtFullEa->NextEntryOffset = (ULONG)( ptr - (PCHAR)NtFullEa );
  679. NtFullEa = (PFILE_FULL_EA_INFORMATION)ptr;
  680. if ( ReturnSingleEntry == TRUE ) {
  681. break;
  682. }
  683. }
  684. //
  685. // Set the NextEntryOffset field of the last full EA to 0 to indicate
  686. // the end of the list.
  687. //
  688. LastNtFullEa->NextEntryOffset = 0;
  689. //
  690. // Record position the default start position for the next query
  691. //
  692. capFobx->OffsetOfNextEaToReturn = EaIndex;
  693. if ( Overflow == FALSE ) {
  694. return STATUS_SUCCESS;
  695. } else {
  696. return STATUS_BUFFER_OVERFLOW;
  697. }
  698. }
  699. ULONG
  700. MRxSmbNtFullEaSizeToOs2 (
  701. IN PFILE_FULL_EA_INFORMATION NtFullEa
  702. )
  703. /*++
  704. Routine Description:
  705. Get the number of bytes that would be required to represent the
  706. NT full EA list in OS/2 1.2 style. This routine assumes that
  707. at least one EA is present in the buffer.
  708. Arguments:
  709. NtFullEa - a pointer to the list of NT EAs.
  710. Return Value:
  711. ULONG - number of bytes required to hold the EAs in OS/2 1.2 format.
  712. --*/
  713. {
  714. ULONG size;
  715. PAGED_CODE();
  716. //
  717. // Walk through the EAs, adding up the total size required to
  718. // hold them in OS/2 format.
  719. //
  720. for ( size = FIELD_OFFSET(FEALIST, list[0]);
  721. NtFullEa->NextEntryOffset != 0;
  722. NtFullEa = (PFILE_FULL_EA_INFORMATION)(
  723. (PCHAR)NtFullEa + NtFullEa->NextEntryOffset ) ) {
  724. size += SmbGetOs2SizeOfNtFullEa( NtFullEa );
  725. }
  726. size += SmbGetOs2SizeOfNtFullEa( NtFullEa );
  727. return size;
  728. }
  729. VOID
  730. MRxSmbNtFullListToOs2 (
  731. IN PFILE_FULL_EA_INFORMATION NtEaList,
  732. IN PFEALIST FeaList
  733. )
  734. /*++
  735. Routine Description:
  736. Converts a single NT FULL EA list to OS/2 FEALIST style. The FEALIST
  737. need not have any particular alignment.
  738. It is the callers responsibility to ensure that FeaList is large enough.
  739. Arguments:
  740. NtEaList - An NT style get EA list to be converted to OS/2 format.
  741. FeaList - Where to place the OS/2 1.2 style FEALIST.
  742. Return Value:
  743. none.
  744. --*/
  745. {
  746. PFEA fea = FeaList->list;
  747. PFILE_FULL_EA_INFORMATION ntFullEa = NtEaList;
  748. PAGED_CODE();
  749. //
  750. // Copy the Eas up until the last one
  751. //
  752. while ( ntFullEa->NextEntryOffset != 0 ) {
  753. //
  754. // Copy the NT format EA to OS/2 1.2 format and set the fea
  755. // pointer for the next iteration.
  756. //
  757. fea = MRxSmbNtFullEaToOs2( fea, ntFullEa );
  758. ntFullEa = (PFILE_FULL_EA_INFORMATION)((PCHAR)ntFullEa + ntFullEa->NextEntryOffset);
  759. }
  760. // Now copy the last entry.
  761. fea = MRxSmbNtFullEaToOs2( fea, ntFullEa );
  762. //
  763. // Set the number of bytes in the FEALIST.
  764. //
  765. SmbPutUlong(
  766. &FeaList->cbList,
  767. (ULONG)((PCHAR)fea - (PCHAR)FeaList)
  768. );
  769. }
  770. PVOID
  771. MRxSmbNtFullEaToOs2 (
  772. OUT PFEA Fea,
  773. IN PFILE_FULL_EA_INFORMATION NtFullEa
  774. )
  775. /*++
  776. Routine Description:
  777. Converts a single NT full EA to OS/2 FEA style. The FEA need not have
  778. any particular alignment. This routine makes no checks on buffer
  779. overrunning--this is the responsibility of the calling routine.
  780. Arguments:
  781. Fea - a pointer to the location where the OS/2 FEA is to be written.
  782. NtFullEa - a pointer to the NT full EA.
  783. Return Value:
  784. A pointer to the location after the last byte written.
  785. --*/
  786. {
  787. PCHAR ptr;
  788. PAGED_CODE();
  789. Fea->fEA = (UCHAR)NtFullEa->Flags;
  790. Fea->cbName = NtFullEa->EaNameLength;
  791. SmbPutUshort( &Fea->cbValue, NtFullEa->EaValueLength );
  792. ptr = (PCHAR)(Fea + 1);
  793. RtlCopyMemory( ptr, NtFullEa->EaName, NtFullEa->EaNameLength );
  794. ptr += NtFullEa->EaNameLength;
  795. *ptr++ = '\0';
  796. RtlCopyMemory(
  797. ptr,
  798. NtFullEa->EaName + NtFullEa->EaNameLength + 1,
  799. NtFullEa->EaValueLength
  800. );
  801. return (ptr + NtFullEa->EaValueLength);
  802. }
  803. NTSTATUS
  804. MRxSmbSetEaList(
  805. IN PRX_CONTEXT RxContext,
  806. IN PFEALIST ServerEaList
  807. )
  808. /*++
  809. Routine Description:
  810. This routine implements the NtQueryEaFile api.
  811. It returns the following information:
  812. Arguments:
  813. IN PFEALIST ServerEaList - Eas to be sent to the server.
  814. Return Value:
  815. Status - Result of the operation.
  816. --*/
  817. {
  818. RxCaptureFobx;
  819. PMRX_SMB_SRV_OPEN smbSrvOpen;
  820. NTSTATUS Status;
  821. USHORT Setup = TRANS2_SET_FILE_INFORMATION;
  822. REQ_SET_FILE_INFORMATION SetFileInfoRequest;
  823. RESP_SET_FILE_INFORMATION SetFileInfoResponse;
  824. PBYTE pInputParamBuffer = NULL;
  825. PBYTE pOutputParamBuffer = NULL;
  826. PBYTE pInputDataBuffer = NULL;
  827. PBYTE pOutputDataBuffer = NULL;
  828. ULONG InputParamBufferLength = 0;
  829. ULONG OutputParamBufferLength = 0;
  830. ULONG InputDataBufferLength = 0;
  831. ULONG OutputDataBufferLength = 0;
  832. PAGED_CODE();
  833. RxDbgTrace(+1, Dbg, ("MRxSmbSetEaList...\n"));
  834. Status = STATUS_MORE_PROCESSING_REQUIRED;
  835. SetFileInfoResponse.EaErrorOffset = 0;
  836. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  837. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  838. PSMB_TRANSACTION_OPTIONS pTransactionOptions = &RxDefaultTransactionOptions;
  839. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  840. SetFileInfoRequest.Fid = smbSrvOpen->Fid;
  841. SetFileInfoRequest.InformationLevel = SMB_INFO_SET_EAS;
  842. SetFileInfoRequest.Flags = 0;
  843. Status = SmbCeTransact(
  844. RxContext, // the RXContext for the transaction
  845. pTransactionOptions, // transaction options
  846. &Setup, // the setup buffer
  847. sizeof(Setup), // setup buffer length
  848. NULL, // the output setup buffer
  849. 0, // output setup buffer length
  850. &SetFileInfoRequest, // Input Param Buffer
  851. sizeof(SetFileInfoRequest), // Input param buffer length
  852. &SetFileInfoResponse, // Output param buffer
  853. sizeof(SetFileInfoResponse), // output param buffer length
  854. ServerEaList, // Input data buffer
  855. SmbGetUlong(&ServerEaList->cbList), // Input data buffer length
  856. NULL, // output data buffer
  857. 0, // output data buffer length
  858. &ResumptionContext // the resumption context
  859. );
  860. }
  861. if (!NT_SUCCESS(Status)) {
  862. USHORT EaErrorOffset = SetFileInfoResponse.EaErrorOffset;
  863. RxDbgTrace( 0, Dbg, ("MRxSmbSetEaList: Failed .. returning %lx/%lx\n",Status,EaErrorOffset));
  864. RxContext->InformationToReturn = (EaErrorOffset);
  865. }
  866. RxDbgTrace(-1, Dbg, ("MRxSmbSetEaList...exit\n"));
  867. return Status;
  868. }
  869. NTSTATUS
  870. MRxSmbQueryQuotaInformation(
  871. IN OUT PRX_CONTEXT RxContext)
  872. {
  873. RxCaptureFobx;
  874. PMRX_SMB_SRV_OPEN smbSrvOpen;
  875. NTSTATUS Status;
  876. USHORT Setup = NT_TRANSACT_QUERY_QUOTA;
  877. PSID StartSid;
  878. ULONG StartSidLength;
  879. REQ_NT_QUERY_FS_QUOTA_INFO QueryQuotaInfoRequest;
  880. RESP_NT_QUERY_FS_QUOTA_INFO QueryQuotaInfoResponse;
  881. PBYTE pInputParamBuffer = NULL;
  882. PBYTE pOutputParamBuffer = NULL;
  883. PBYTE pInputDataBuffer = NULL;
  884. PBYTE pOutputDataBuffer = NULL;
  885. ULONG InputParamBufferLength = 0;
  886. ULONG OutputParamBufferLength = 0;
  887. ULONG InputDataBufferLength = 0;
  888. ULONG OutputDataBufferLength = 0;
  889. PAGED_CODE();
  890. RxDbgTrace(+1, Dbg, ("MRxSmbQueryQuotaInformation...\n"));
  891. Status = STATUS_MORE_PROCESSING_REQUIRED;
  892. if (capFobx != NULL) {
  893. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  894. }
  895. if ((capFobx == NULL) ||
  896. (smbSrvOpen == NULL)) {
  897. Status = STATUS_INVALID_PARAMETER;
  898. }
  899. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  900. StartSid = RxContext->QueryQuota.StartSid;
  901. if (StartSid != NULL) {
  902. StartSidLength = RtlLengthRequiredSid(((PISID)StartSid)->SubAuthorityCount);
  903. } else {
  904. StartSidLength = 0;
  905. }
  906. QueryQuotaInfoRequest.Fid = smbSrvOpen->Fid;
  907. QueryQuotaInfoRequest.ReturnSingleEntry = RxContext->QueryQuota.ReturnSingleEntry;
  908. QueryQuotaInfoRequest.RestartScan = RxContext->QueryQuota.RestartScan;
  909. QueryQuotaInfoRequest.SidListLength = RxContext->QueryQuota.SidListLength;
  910. QueryQuotaInfoRequest.StartSidOffset = ROUND_UP_COUNT(
  911. RxContext->QueryQuota.SidListLength,
  912. sizeof(ULONG));
  913. QueryQuotaInfoRequest.StartSidLength = StartSidLength;
  914. // The input data buffer to be supplied to the server consists of two pieces
  915. // of information the start sid and the sid list. Currently the I/O
  916. // subsystem allocates them in contigous memory. In such cases we avoid
  917. // another allocation by reusing the same buffer. If this condition is
  918. // not satisfied we allocate a buffer large enough for both the
  919. // components and copy them over.
  920. InputDataBufferLength = ROUND_UP_COUNT(
  921. RxContext->QueryQuota.SidListLength,
  922. sizeof(ULONG)) +
  923. StartSidLength;
  924. QueryQuotaInfoRequest.StartSidLength = StartSidLength;
  925. if (((PBYTE)RxContext->QueryQuota.SidList +
  926. ROUND_UP_COUNT(RxContext->QueryQuota.SidListLength,sizeof(ULONG))) !=
  927. RxContext->QueryQuota.StartSid) {
  928. pInputDataBuffer = RxAllocatePoolWithTag(
  929. PagedPool,
  930. InputDataBufferLength,
  931. MRXSMB_MISC_POOLTAG);
  932. if (pInputDataBuffer != NULL) {
  933. RtlCopyMemory(
  934. pInputDataBuffer ,
  935. RxContext->QueryQuota.SidList,
  936. RxContext->QueryQuota.SidListLength);
  937. RtlCopyMemory(
  938. pInputDataBuffer + QueryQuotaInfoRequest.StartSidOffset,
  939. StartSid,
  940. StartSidLength);
  941. } else {
  942. Status = STATUS_INSUFFICIENT_RESOURCES;
  943. }
  944. } else {
  945. pInputDataBuffer = (PBYTE)RxContext->QueryQuota.SidList;
  946. }
  947. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  948. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  949. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  950. TransactionOptions.NtTransactFunction = NT_TRANSACT_QUERY_QUOTA;
  951. pOutputDataBuffer = RxContext->Info.Buffer;
  952. OutputDataBufferLength = RxContext->Info.LengthRemaining;
  953. Status = SmbCeTransact(
  954. RxContext, // the RXContext for the transaction
  955. &TransactionOptions, // transaction options
  956. &Setup, // the setup buffer
  957. sizeof(Setup), // setup buffer length
  958. NULL, // the output setup buffer
  959. 0, // output setup buffer length
  960. &QueryQuotaInfoRequest, // Input Param Buffer
  961. sizeof(QueryQuotaInfoRequest), // Input param buffer length
  962. &QueryQuotaInfoResponse, // Output param buffer
  963. sizeof(QueryQuotaInfoResponse), // output param buffer length
  964. pInputDataBuffer, // Input data buffer
  965. InputDataBufferLength, // Input data buffer length
  966. pOutputDataBuffer, // output data buffer
  967. OutputDataBufferLength, // output data buffer length
  968. &ResumptionContext // the resumption context
  969. );
  970. }
  971. if ((pInputDataBuffer != NULL) &&
  972. (pInputDataBuffer != (PBYTE)RxContext->QueryQuota.SidList)) {
  973. RxFreePool(pInputDataBuffer);
  974. }
  975. }
  976. if (!NT_SUCCESS(Status)) {
  977. RxContext->InformationToReturn = 0;
  978. } else {
  979. RxContext->InformationToReturn = QueryQuotaInfoResponse.Length;
  980. }
  981. RxDbgTrace(-1, Dbg, ("MRxSmbQueryQuotaInformation...exit\n"));
  982. return Status;
  983. }
  984. NTSTATUS
  985. MRxSmbSetQuotaInformation(
  986. IN OUT PRX_CONTEXT RxContext)
  987. {
  988. RxCaptureFobx;
  989. PMRX_SMB_SRV_OPEN smbSrvOpen;
  990. NTSTATUS Status;
  991. USHORT Setup = NT_TRANSACT_SET_QUOTA;
  992. REQ_NT_SET_FS_QUOTA_INFO SetQuotaInfoRequest;
  993. PBYTE pInputParamBuffer = NULL;
  994. PBYTE pOutputParamBuffer = NULL;
  995. PBYTE pInputDataBuffer = NULL;
  996. PBYTE pOutputDataBuffer = NULL;
  997. ULONG InputParamBufferLength = 0;
  998. ULONG OutputParamBufferLength = 0;
  999. ULONG InputDataBufferLength = 0;
  1000. ULONG OutputDataBufferLength = 0;
  1001. PAGED_CODE();
  1002. RxDbgTrace(+1, Dbg, ("MRxSmbSetQuotaInformation...\n"));
  1003. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1004. if (capFobx != NULL) {
  1005. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1006. }
  1007. if ((capFobx == NULL) ||
  1008. (smbSrvOpen == NULL)) {
  1009. Status = STATUS_INVALID_PARAMETER;
  1010. }
  1011. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1012. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  1013. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1014. TransactionOptions.NtTransactFunction = NT_TRANSACT_SET_QUOTA;
  1015. SetQuotaInfoRequest.Fid = smbSrvOpen->Fid;
  1016. pInputDataBuffer = RxContext->Info.Buffer;
  1017. InputDataBufferLength = RxContext->Info.LengthRemaining;
  1018. Status = SmbCeTransact(
  1019. RxContext, // the RXContext for the transaction
  1020. &TransactionOptions, // transaction options
  1021. &Setup, // the setup buffer
  1022. sizeof(Setup), // setup buffer length
  1023. NULL, // the output setup buffer
  1024. 0, // output setup buffer length
  1025. &SetQuotaInfoRequest, // Input Param Buffer
  1026. sizeof(SetQuotaInfoRequest), // Input param buffer length
  1027. pOutputParamBuffer, // Output param buffer
  1028. OutputParamBufferLength, // output param buffer length
  1029. pInputDataBuffer, // Input data buffer
  1030. InputDataBufferLength, // Input data buffer length
  1031. pOutputDataBuffer, // output data buffer
  1032. OutputDataBufferLength, // output data buffer length
  1033. &ResumptionContext // the resumption context
  1034. );
  1035. }
  1036. RxDbgTrace(-1, Dbg, ("MRxSmbSetQuotaInformation...exit\n"));
  1037. return Status;
  1038. }