Source code of Windows XP (NT5)
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.

3951 lines
109 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. smbopen.c
  5. Abstract:
  6. This module contains routines for processing the following SMBs:
  7. Open
  8. Open and X
  9. Create
  10. Create New
  11. Create Temporary
  12. *** The SearchAttributes field in open/create SMBs is always
  13. ignored. This duplicates the LM 2.0 server behavior.
  14. Author:
  15. David Treadwell (davidtr) 23-Nov-1989
  16. Manny Weiser (mannyw) 15-Apr-1991 (oplock support)
  17. Revision History:
  18. 16-Apr-1991 mannyw
  19. --*/
  20. #include "precomp.h"
  21. #include "smbopen.tmh"
  22. #pragma hdrstop
  23. #define BugCheckFileId SRV_FILE_SMBOPEN
  24. //
  25. // in smbtrans.c
  26. //
  27. SMB_STATUS SRVFASTCALL
  28. ExecuteTransaction (
  29. IN OUT PWORK_CONTEXT WorkContext
  30. );
  31. //
  32. // Local functions
  33. //
  34. VOID
  35. SetEofToMatchAllocation (
  36. IN HANDLE FileHandle,
  37. IN ULONG AllocationSize
  38. );
  39. VOID SRVFASTCALL
  40. RestartOpen (
  41. PWORK_CONTEXT WorkContext
  42. );
  43. SMB_PROCESSOR_RETURN_TYPE
  44. GenerateOpenResponse (
  45. PWORK_CONTEXT WorkContext,
  46. NTSTATUS OpenStatus
  47. );
  48. VOID SRVFASTCALL
  49. RestartOpenAndX (
  50. PWORK_CONTEXT WorkContext
  51. );
  52. SMB_PROCESSOR_RETURN_TYPE
  53. GenerateOpenAndXResponse (
  54. PWORK_CONTEXT WorkContext,
  55. NTSTATUS OpenStatus
  56. );
  57. VOID SRVFASTCALL
  58. RestartOpen2 (
  59. PWORK_CONTEXT WorkContext
  60. );
  61. SMB_TRANS_STATUS
  62. GenerateOpen2Response (
  63. PWORK_CONTEXT WorkContext,
  64. NTSTATUS OpenStatus
  65. );
  66. VOID SRVFASTCALL
  67. RestartNtCreateAndX (
  68. PWORK_CONTEXT WorkContext
  69. );
  70. SMB_PROCESSOR_RETURN_TYPE
  71. GenerateNtCreateAndXResponse (
  72. PWORK_CONTEXT WorkContext,
  73. NTSTATUS OpenStatus
  74. );
  75. VOID SRVFASTCALL
  76. RestartCreateWithSdOrEa (
  77. PWORK_CONTEXT WorkContext
  78. );
  79. SMB_TRANS_STATUS
  80. GenerateCreateWithSdOrEaResponse (
  81. PWORK_CONTEXT WorkContext,
  82. NTSTATUS OpenStatus
  83. );
  84. VOID SRVFASTCALL
  85. RestartSmbCreate(
  86. IN PWORK_CONTEXT WorkContext
  87. );
  88. SMB_PROCESSOR_RETURN_TYPE
  89. GenerateCreateResponse(
  90. PWORK_CONTEXT WorkContext,
  91. NTSTATUS CreateStatus
  92. );
  93. #ifdef ALLOC_PRAGMA
  94. #pragma alloc_text( PAGE, SrvSmbOpen )
  95. #pragma alloc_text( PAGE, RestartOpen )
  96. #pragma alloc_text( PAGE, GenerateOpenResponse )
  97. #pragma alloc_text( PAGE, SrvSmbOpenAndX )
  98. #pragma alloc_text( PAGE, RestartOpenAndX )
  99. #pragma alloc_text( PAGE, GenerateOpenAndXResponse )
  100. #pragma alloc_text( PAGE, SrvSmbOpen2 )
  101. #pragma alloc_text( PAGE, RestartOpen2 )
  102. #pragma alloc_text( PAGE, GenerateOpen2Response )
  103. #pragma alloc_text( PAGE, SrvSmbNtCreateAndX )
  104. #pragma alloc_text( PAGE, RestartNtCreateAndX )
  105. #pragma alloc_text( PAGE, GenerateNtCreateAndXResponse )
  106. #pragma alloc_text( PAGE, SrvSmbCreateWithSdOrEa )
  107. #pragma alloc_text( PAGE, RestartCreateWithSdOrEa )
  108. #pragma alloc_text( PAGE, GenerateCreateWithSdOrEaResponse )
  109. #pragma alloc_text( PAGE, SrvSmbCreate )
  110. #pragma alloc_text( PAGE, SrvSmbCreateTemporary )
  111. #pragma alloc_text( PAGE, SetEofToMatchAllocation )
  112. #pragma alloc_text( PAGE, RestartSmbCreate )
  113. #pragma alloc_text( PAGE, GenerateCreateResponse )
  114. #endif
  115. SMB_PROCESSOR_RETURN_TYPE
  116. SrvSmbOpen (
  117. SMB_PROCESSOR_PARAMETERS
  118. )
  119. /*++
  120. Routine Description:
  121. Processes an Open SMB. (This is the 'core' Open.)
  122. Arguments:
  123. SMB_PROCESSOR_PARAMETERS - See smbprocs.h for a description
  124. of the parameters to SMB processor routines.
  125. Return Value:
  126. SMB_PROCESSOR_RETURN_TYPE - See smbprocs.h
  127. --*/
  128. {
  129. PREQ_OPEN request;
  130. NTSTATUS status = STATUS_SUCCESS;
  131. USHORT access;
  132. SMB_STATUS SmbStatus = SmbStatusInProgress;
  133. PAGED_CODE( );
  134. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  135. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN;
  136. SrvWmiStartContext(WorkContext);
  137. IF_SMB_DEBUG(OPEN_CLOSE1) {
  138. KdPrint(( "Open file request header at 0x%p, response header at 0x%p\n",
  139. WorkContext->RequestHeader,
  140. WorkContext->ResponseHeader ));
  141. KdPrint(( "Open file request parameters at 0x%p, response parameters at 0x%p\n",
  142. WorkContext->RequestParameters,
  143. WorkContext->ResponseParameters ));
  144. }
  145. request = (PREQ_OPEN)WorkContext->RequestParameters;
  146. access = SmbGetUshort( &request->DesiredAccess );
  147. status = SrvCreateFile(
  148. WorkContext,
  149. (USHORT)(access & ~SMB_DA_WRITE_THROUGH), // Allow write behind
  150. (USHORT)0, // SmbFileAttributes
  151. SMB_OFUN_OPEN_OPEN | SMB_OFUN_CREATE_FAIL,
  152. (ULONG)0, // SmbAllocationSize
  153. (PCHAR)(request->Buffer + 1),
  154. END_OF_REQUEST_SMB( WorkContext ),
  155. NULL,
  156. 0L,
  157. NULL,
  158. (WorkContext->RequestHeader->Flags & SMB_FLAGS_OPLOCK_NOTIFY_ANY) != 0 ?
  159. OplockTypeBatch :
  160. (WorkContext->RequestHeader->Flags & SMB_FLAGS_OPLOCK) != 0 ?
  161. OplockTypeExclusive : OplockTypeServerBatch,
  162. RestartOpen
  163. );
  164. if (status == STATUS_OPLOCK_BREAK_IN_PROGRESS) {
  165. // The open is blocked (waiting for a comm device or an oplock
  166. // break), do not send a response.
  167. //
  168. SmbStatus = SmbStatusInProgress;
  169. } else if ( WorkContext->Parameters2.Open.TemporaryOpen ) {
  170. // The initial open failed due to a sharing violation, possibly
  171. // caused by an batch oplock. Requeue the open to a blocking
  172. // thread.
  173. //
  174. WorkContext->FspRestartRoutine = SrvRestartSmbReceived;
  175. SrvQueueWorkToBlockingThread( WorkContext );
  176. SmbStatus = SmbStatusInProgress;
  177. } else {
  178. // The open has completed. Generate and send the reply.
  179. //
  180. SmbStatus = GenerateOpenResponse( WorkContext, status );
  181. }
  182. SrvWmiEndContext(WorkContext);
  183. return SmbStatus;
  184. } // SrvSmbOpen
  185. VOID SRVFASTCALL
  186. RestartOpen (
  187. IN PWORK_CONTEXT WorkContext
  188. )
  189. /*++
  190. Routine Description:
  191. Completes processing of an Open SMB. (This is the 'core' Open.)
  192. Arguments:
  193. WorkContext - A pointer to the work context block for this SMB.
  194. Return Value:
  195. None.
  196. --*/
  197. {
  198. SMB_PROCESSOR_RETURN_LOCAL smbStatus = SmbStatusInProgress;
  199. NTSTATUS openStatus = STATUS_SUCCESS;
  200. PAGED_CODE( );
  201. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  202. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN;
  203. SrvWmiStartContext(WorkContext);
  204. openStatus = SrvCheckOplockWaitState( WorkContext->WaitForOplockBreak );
  205. if ( NT_SUCCESS( openStatus ) ) {
  206. openStatus = WorkContext->Irp->IoStatus.Status;
  207. } else {
  208. //
  209. // This open was waiting for an oplock break to occur, but
  210. // timed out. Close our handle to this file, then fail the open.
  211. //
  212. SrvCloseRfcb( WorkContext->Parameters2.Open.Rfcb );
  213. }
  214. WorkContext->Irp->IoStatus.Information = WorkContext->Parameters2.Open.IosbInformation;
  215. smbStatus = GenerateOpenResponse(
  216. WorkContext,
  217. openStatus
  218. );
  219. SrvEndSmbProcessing( WorkContext, smbStatus );
  220. SrvWmiEndContext(WorkContext);
  221. return;
  222. } // RestartOpen
  223. SMB_PROCESSOR_RETURN_TYPE
  224. GenerateOpenResponse (
  225. PWORK_CONTEXT WorkContext,
  226. NTSTATUS OpenStatus
  227. )
  228. /*++
  229. Routine Description:
  230. Generates a response to an Open SMB. (This is the 'core' Open.)
  231. Arguments:
  232. WorkContext -
  233. Status - The status of the open operation.
  234. Return Value:
  235. The status of the SMB processing.
  236. --*/
  237. {
  238. PRESP_OPEN response;
  239. PREQ_OPEN request;
  240. NTSTATUS status;
  241. SRV_FILE_INFORMATION_ABBREVIATED srvFileInformation;
  242. PRFCB rfcb;
  243. USHORT access;
  244. PAGED_CODE( );
  245. //
  246. // If the open failed, send an error response.
  247. //
  248. if ( !NT_SUCCESS( OpenStatus ) ) {
  249. SrvSetSmbError( WorkContext, OpenStatus );
  250. return SmbStatusSendResponse;
  251. }
  252. rfcb = WorkContext->Rfcb;
  253. response = (PRESP_OPEN)WorkContext->ResponseParameters;
  254. request = (PREQ_OPEN)WorkContext->RequestParameters;
  255. access = SmbGetUshort( &request->DesiredAccess ); // save for later use
  256. //
  257. // Get the additional information that needs to be returned in the
  258. // response SMB. We always open with FILE_READ_ATTRIBUTES, so no
  259. // access check is required.
  260. //
  261. status = SrvQueryInformationFileAbbreviated(
  262. rfcb->Lfcb->FileHandle,
  263. rfcb->Lfcb->FileObject,
  264. &srvFileInformation,
  265. FALSE,
  266. WorkContext->TreeConnect->Share->ShareType
  267. );
  268. if ( !NT_SUCCESS(status) ) {
  269. IF_DEBUG(ERRORS) {
  270. KdPrint(( "GenerateOpenResponse: SrvQueryInformationFile failed: %X\n",
  271. status ));
  272. }
  273. SrvCloseRfcb( rfcb );
  274. SrvSetSmbError( WorkContext, status );
  275. return SmbStatusSendResponse;
  276. }
  277. rfcb->Mfcb->NonpagedMfcb->OpenFileSize = srvFileInformation.DataSize;
  278. //
  279. // Give the smart card a chance to get into the act
  280. //
  281. if( WorkContext->Endpoint->IsConnectionless && SrvIpxSmartCard.Open != NULL ) {
  282. PVOID handle;
  283. IF_DEBUG( SIPX ) {
  284. KdPrint(( "Trying the smart card for %wZ\n", &rfcb->Mfcb->FileName ));
  285. }
  286. if( SrvIpxSmartCard.Open(
  287. WorkContext->RequestBuffer->Buffer,
  288. rfcb->Lfcb->FileObject,
  289. &rfcb->Mfcb->FileName,
  290. &(WorkContext->ClientAddress->IpxAddress.Address[0].Address[0]),
  291. rfcb->Lfcb->FileObject->Flags & FO_CACHE_SUPPORTED,
  292. &handle
  293. ) == TRUE ) {
  294. IF_DEBUG( SIPX ) {
  295. KdPrint(( "%wZ handled by Smart Card. Handle %p\n",
  296. &rfcb->Mfcb->FileName, handle ));
  297. }
  298. rfcb->PagedRfcb->IpxSmartCardContext = handle;
  299. }
  300. }
  301. //
  302. // Set up fields of response SMB. Note that we copy the desired
  303. // access to the granted access in the response. They must be the
  304. // same, else the request would have failed.
  305. //
  306. // !!! This will not be the case for compatibility mode and FCB opens!
  307. //
  308. response->WordCount = 7;
  309. SmbPutUshort( &response->Fid, rfcb->Fid );
  310. SmbPutUshort( &response->FileAttributes, srvFileInformation.Attributes );
  311. SmbPutUlong(
  312. &response->LastWriteTimeInSeconds,
  313. srvFileInformation.LastWriteTimeInSeconds
  314. );
  315. SmbPutUlong( &response->DataSize, srvFileInformation.DataSize.LowPart );
  316. SmbPutUshort(
  317. &response->GrantedAccess,
  318. access );
  319. SmbPutUshort( &response->ByteCount, 0 );
  320. WorkContext->ResponseParameters = NEXT_LOCATION( response, RESP_OPEN, 0 );
  321. IF_DEBUG(TRACE2) KdPrint(( "GenerateOpenResponse complete.\n" ));
  322. return SmbStatusSendResponse;
  323. } // GenerateOpenResponse
  324. SMB_PROCESSOR_RETURN_TYPE
  325. SrvSmbOpenAndX (
  326. SMB_PROCESSOR_PARAMETERS
  327. )
  328. /*++
  329. Routine Description:
  330. Processes an OpenAndX SMB.
  331. Arguments:
  332. SMB_PROCESSOR_PARAMETERS - See smbprocs.h for a description
  333. of the parameters to SMB processor routines.
  334. Return Value:
  335. SMB_PROCESSOR_RETURN_TYPE - See smbprocs.h
  336. --*/
  337. {
  338. PREQ_OPEN_ANDX request;
  339. NTSTATUS status = STATUS_SUCCESS;
  340. USHORT access;
  341. SMB_STATUS smbStatus = SmbStatusInProgress;
  342. PAGED_CODE( );
  343. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  344. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN_AND_X;
  345. SrvWmiStartContext(WorkContext);
  346. IF_SMB_DEBUG(OPEN_CLOSE1) {
  347. KdPrint(( "Open file and X request header at 0x%p, response header at 0x%p\n",
  348. WorkContext->RequestHeader,
  349. WorkContext->ResponseHeader ));
  350. KdPrint(( "Open file and X request parameters at 0x%p, response parameters at 0x%p\n",
  351. WorkContext->RequestParameters,
  352. WorkContext->ResponseParameters ));
  353. }
  354. //
  355. // If we are not on a blocking thread and we don't have a license
  356. // from the license server, shift the request over to the blocking work
  357. // queue since acquiring a license is an expensive operation and we don't
  358. // want to congest our nonblocking worker threads
  359. //
  360. if( WorkContext->UsingBlockingThread == 0 ) {
  361. PSESSION session;
  362. PTREE_CONNECT treeConnect;
  363. status = SrvVerifyUidAndTid(
  364. WorkContext,
  365. &session,
  366. &treeConnect,
  367. ShareTypeWild
  368. );
  369. if ( !NT_SUCCESS(status) ) {
  370. IF_DEBUG(SMB_ERRORS) {
  371. KdPrint(( "SrvSmbOpenAndX: Invalid UID or TID\n" ));
  372. }
  373. smbStatus = GenerateOpenAndXResponse( WorkContext, status );
  374. goto Cleanup;
  375. }
  376. if( session->IsLSNotified == FALSE ) {
  377. //
  378. // Insert the work item at the tail of the blocking work queue.
  379. //
  380. SrvInsertWorkQueueTail(
  381. &SrvBlockingWorkQueue,
  382. (PQUEUEABLE_BLOCK_HEADER)WorkContext
  383. );
  384. smbStatus = SmbStatusInProgress;
  385. goto Cleanup;
  386. }
  387. }
  388. request = (PREQ_OPEN_ANDX)WorkContext->RequestParameters;
  389. access = SmbGetUshort( &request->DesiredAccess ); // save for later use
  390. status = SrvCreateFile(
  391. WorkContext,
  392. access,
  393. SmbGetUshort( &request->FileAttributes ),
  394. SmbGetUshort( &request->OpenFunction ),
  395. SmbGetUlong( &request->AllocationSize ),
  396. (PCHAR)request->Buffer,
  397. END_OF_REQUEST_SMB( WorkContext ),
  398. NULL,
  399. 0L,
  400. NULL,
  401. (SmbGetUshort(&request->Flags) & SMB_OPEN_OPBATCH) != 0 ?
  402. OplockTypeBatch :
  403. (SmbGetUshort(&request->Flags) & SMB_OPEN_OPLOCK) != 0 ?
  404. OplockTypeExclusive : OplockTypeServerBatch,
  405. RestartOpenAndX
  406. );
  407. if ( status == STATUS_OPLOCK_BREAK_IN_PROGRESS ) {
  408. //
  409. // The open is blocked (waiting for a comm device or an oplock
  410. // break), do not send a reply.
  411. //
  412. smbStatus = SmbStatusInProgress;
  413. } else if ( WorkContext->Parameters2.Open.TemporaryOpen ) {
  414. //
  415. // The initial open failed due to a sharing violation, possibly
  416. // caused by an batch oplock. Requeue the open to a blocking
  417. // thread.
  418. //
  419. WorkContext->FspRestartRoutine = SrvRestartSmbReceived;
  420. SrvQueueWorkToBlockingThread( WorkContext );
  421. smbStatus = SmbStatusInProgress;
  422. } else {
  423. //
  424. // The open has completed. Generate and send the reply.
  425. //
  426. smbStatus = GenerateOpenAndXResponse( WorkContext, status );
  427. }
  428. Cleanup:
  429. SrvWmiEndContext(WorkContext);
  430. return smbStatus;
  431. } // SrvSmbOpenAndX
  432. VOID SRVFASTCALL
  433. RestartOpenAndX (
  434. PWORK_CONTEXT WorkContext
  435. )
  436. /*++
  437. Routine Description:
  438. Completes processing of an Open and X SMB.
  439. Arguments:
  440. WorkContext - Work context block for the operation.
  441. Return Value:
  442. None.
  443. --*/
  444. {
  445. SMB_PROCESSOR_RETURN_LOCAL smbStatus = SmbStatusInProgress;
  446. NTSTATUS openStatus = STATUS_SUCCESS;
  447. PAGED_CODE( );
  448. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  449. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN_AND_X;
  450. SrvWmiStartContext(WorkContext);
  451. openStatus = SrvCheckOplockWaitState( WorkContext->WaitForOplockBreak );
  452. if ( NT_SUCCESS( openStatus ) ) {
  453. openStatus = WorkContext->Irp->IoStatus.Status;
  454. if( NT_SUCCESS( openStatus ) ) {
  455. //
  456. // It's obvious that the file already existed, because we've
  457. // been working on an oplock break. So set the
  458. // IoStatus.Information field correctly.
  459. //
  460. WorkContext->Irp->IoStatus.Information = FILE_OPENED;
  461. }
  462. } else {
  463. //
  464. // This open was waiting for an oplock break to occur, but
  465. // timed out. Close our handle to this file, then fail the open.
  466. //
  467. SrvCloseRfcb( WorkContext->Parameters2.Open.Rfcb );
  468. }
  469. WorkContext->Irp->IoStatus.Information = WorkContext->Parameters2.Open.IosbInformation;
  470. smbStatus = GenerateOpenAndXResponse(
  471. WorkContext,
  472. openStatus
  473. );
  474. if ( smbStatus == SmbStatusMoreCommands ) {
  475. SrvProcessSmb( WorkContext );
  476. } else {
  477. SrvEndSmbProcessing( WorkContext, SmbStatusSendResponse );
  478. }
  479. SrvWmiEndContext(WorkContext);
  480. return;
  481. } // RestartOpenAndX
  482. SMB_PROCESSOR_RETURN_TYPE
  483. GenerateOpenAndXResponse (
  484. PWORK_CONTEXT WorkContext,
  485. NTSTATUS OpenStatus
  486. )
  487. /*++
  488. Routine Description:
  489. Generates a response to an Open and X SMB and setup for furthur
  490. SMB processing.
  491. Arguments:
  492. WorkContext - Work context block for the operation.
  493. OpenStatus - The status of the open operation.
  494. Return Value:
  495. None.
  496. --*/
  497. {
  498. PREQ_OPEN_ANDX request;
  499. PRESP_OPEN_ANDX response;
  500. SRV_FILE_INFORMATION_ABBREVIATED srvFileInformation;
  501. BOOLEAN reqAdditionalInformation;
  502. BOOLEAN reqExtendedResponse;
  503. PRFCB rfcb;
  504. PLFCB lfcb;
  505. PIO_STATUS_BLOCK ioStatusBlock;
  506. UCHAR nextCommand;
  507. USHORT reqAndXOffset;
  508. USHORT access;
  509. USHORT action = 0;
  510. OPLOCK_TYPE oplockType;
  511. NTSTATUS status;
  512. PAGED_CODE( );
  513. //
  514. // If the open failed, send an error response.
  515. //
  516. if ( !NT_SUCCESS( OpenStatus ) ) {
  517. SrvSetSmbError( WorkContext, OpenStatus );
  518. //
  519. // Remap the error if it is ERROR_ALREADY_EXISTS
  520. //
  521. if ( !CLIENT_CAPABLE_OF(NT_STATUS, WorkContext->Connection) &&
  522. SmbGetUshort( &WorkContext->ResponseHeader->Error ) ==
  523. ERROR_ALREADY_EXISTS ) {
  524. SmbPutUshort(
  525. &WorkContext->ResponseHeader->Error,
  526. ERROR_FILE_EXISTS
  527. );
  528. }
  529. return SmbStatusSendResponse;
  530. }
  531. request = (PREQ_OPEN_ANDX)WorkContext->RequestParameters;
  532. response = (PRESP_OPEN_ANDX)WorkContext->ResponseParameters;
  533. access = SmbGetUshort( &request->DesiredAccess ); // save for later use
  534. rfcb = WorkContext->Rfcb;
  535. lfcb = rfcb->Lfcb;
  536. reqExtendedResponse = (BOOLEAN)( (SmbGetUshort(&request->Flags) &
  537. SMB_OPEN_EXTENDED_RESPONSE) != 0);
  538. //
  539. // Attempt to acquire the oplock.
  540. //
  541. if ( WorkContext->TreeConnect->Share->ShareType != ShareTypePrint ) {
  542. if ( (SmbGetUshort( &request->Flags ) & SMB_OPEN_OPBATCH) != 0 ) {
  543. oplockType = OplockTypeBatch;
  544. } else if ( (SmbGetUshort( &request->Flags ) & SMB_OPEN_OPLOCK) != 0 ) {
  545. oplockType = OplockTypeExclusive;
  546. } else {
  547. oplockType = OplockTypeServerBatch;
  548. }
  549. if ( SrvRequestOplock( WorkContext, &oplockType, FALSE ) ) {
  550. //
  551. // The oplock was granted. Save in action so that we tell
  552. // the client he has an oplock and update statistics.
  553. //
  554. action = SMB_OACT_OPLOCK;
  555. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksGranted );
  556. } else {
  557. //
  558. // The oplock request was denied. Update statistics.
  559. //
  560. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksDenied );
  561. }
  562. }
  563. //
  564. // If the file was created, set the EOF location to be the same as
  565. // the size of the file. This is necessary for compatibility with
  566. // OS/2, which only has EOF, not a separate allocation size.
  567. //
  568. ioStatusBlock = &WorkContext->Irp->IoStatus;
  569. if ( (ioStatusBlock->Information == FILE_CREATED) ||
  570. (ioStatusBlock->Information == FILE_OVERWRITTEN) ) {
  571. //
  572. // Extending EOF is only legal if the client has write access
  573. // to the file. If the client doesn't have write access, don't
  574. // extend the file.
  575. //
  576. // *** This is an incompatibility with OS/2.
  577. if ( rfcb->WriteAccessGranted || rfcb->AppendAccessGranted ) {
  578. SetEofToMatchAllocation(
  579. lfcb->FileHandle,
  580. SmbGetUlong( &request->AllocationSize )
  581. );
  582. } else {
  583. SrvStatistics.GrantedAccessErrors++;
  584. }
  585. }
  586. //
  587. // If the consumer requested additional information, find it now.
  588. //
  589. reqAdditionalInformation = (BOOLEAN)( (SmbGetUshort(&request->Flags) &
  590. SMB_OPEN_QUERY_INFORMATION) != 0);
  591. if ( reqAdditionalInformation ||
  592. ( !rfcb->WriteAccessGranted && rfcb->AppendAccessGranted) ) {
  593. //
  594. // We always open with at least FILE_READ_ATTRIBUTES, so no
  595. // access check is needed.
  596. //
  597. status = SrvQueryInformationFileAbbreviated(
  598. lfcb->FileHandle,
  599. lfcb->FileObject,
  600. &srvFileInformation,
  601. reqExtendedResponse,
  602. WorkContext->TreeConnect->Share->ShareType
  603. );
  604. if ( !NT_SUCCESS(status) ) {
  605. IF_DEBUG(ERRORS) {
  606. KdPrint(( "SrvSmbOpenAndX: SrvQueryInformationFile failed: "
  607. "%X\n", status ));
  608. }
  609. SrvCloseRfcb( rfcb );
  610. SrvSetSmbError( WorkContext, status );
  611. return SmbStatusSendResponse;
  612. }
  613. rfcb->Mfcb->NonpagedMfcb->OpenFileSize = srvFileInformation.DataSize;
  614. }
  615. //
  616. // Give the smart card a chance to get into the act
  617. //
  618. if( WorkContext->Endpoint->IsConnectionless && SrvIpxSmartCard.Open != NULL ) {
  619. PVOID handle;
  620. IF_DEBUG( SIPX ) {
  621. KdPrint(( "Trying the smart card for %wZ\n", &rfcb->Mfcb->FileName ));
  622. }
  623. if( SrvIpxSmartCard.Open(
  624. WorkContext->RequestBuffer->Buffer,
  625. rfcb->Lfcb->FileObject,
  626. &rfcb->Mfcb->FileName,
  627. &(WorkContext->ClientAddress->IpxAddress.Address[0].Address[0]),
  628. rfcb->Lfcb->FileObject->Flags & FO_CACHE_SUPPORTED,
  629. &handle
  630. ) == TRUE ) {
  631. IF_DEBUG( SIPX ) {
  632. KdPrint(( "%wZ handled by Smart Card. Handle %p\n",
  633. &rfcb->Mfcb->FileName, handle ));
  634. }
  635. rfcb->PagedRfcb->IpxSmartCardContext = handle;
  636. }
  637. }
  638. //
  639. // Set up response SMB.
  640. //
  641. nextCommand = request->AndXCommand;
  642. reqAndXOffset = SmbGetUshort( &request->AndXOffset );
  643. if (reqExtendedResponse) {
  644. NTSTATUS ExtendedResponseStatus;
  645. PRESP_EXTENDED_OPEN_ANDX ExtendedResponse;
  646. ExtendedResponse = (PRESP_EXTENDED_OPEN_ANDX)response;
  647. ExtendedResponseStatus = SrvUpdateMaximalAccessRightsInResponse(
  648. WorkContext,
  649. &ExtendedResponse->MaximalAccessRights,
  650. &ExtendedResponse->GuestMaximalAccessRights);
  651. // Fall back to regular response if there was an error in obtainaing
  652. // the maximal access rights
  653. reqExtendedResponse = (ExtendedResponseStatus == STATUS_SUCCESS);
  654. }
  655. response->AndXCommand = nextCommand;
  656. response->AndXReserved = 0;
  657. if (!reqExtendedResponse) {
  658. SmbPutUshort(
  659. &response->AndXOffset,
  660. GET_ANDX_OFFSET(
  661. WorkContext->ResponseHeader,
  662. WorkContext->ResponseParameters,
  663. RESP_OPEN_ANDX,
  664. 0
  665. )
  666. );
  667. response->WordCount = 15;
  668. } else {
  669. SmbPutUshort(
  670. &response->AndXOffset,
  671. GET_ANDX_OFFSET(
  672. WorkContext->ResponseHeader,
  673. WorkContext->ResponseParameters,
  674. RESP_EXTENDED_OPEN_ANDX,
  675. 0
  676. )
  677. );
  678. response->WordCount = 19;
  679. }
  680. SmbPutUshort( &response->Fid, rfcb->Fid );
  681. //
  682. // If the consumer requested additional information, set appropiate
  683. // fields, else set the fields to zero.
  684. //
  685. if ( reqAdditionalInformation ) {
  686. SmbPutUshort(
  687. &response->FileAttributes,
  688. srvFileInformation.Attributes
  689. );
  690. SmbPutUlong(
  691. &response->LastWriteTimeInSeconds,
  692. srvFileInformation.LastWriteTimeInSeconds
  693. );
  694. SmbPutUlong( &response->DataSize, srvFileInformation.DataSize.LowPart );
  695. access &= SMB_DA_SHARE_MASK;
  696. if( rfcb->ReadAccessGranted && (rfcb->WriteAccessGranted || rfcb->AppendAccessGranted) ) {
  697. access |= SMB_DA_ACCESS_READ_WRITE;
  698. } else if( rfcb->ReadAccessGranted ) {
  699. access |= SMB_DA_ACCESS_READ;
  700. } else if( rfcb->WriteAccessGranted || rfcb->AppendAccessGranted ) {
  701. access |= SMB_DA_ACCESS_WRITE;
  702. }
  703. SmbPutUshort( &response->GrantedAccess, access );
  704. SmbPutUshort( &response->FileType, srvFileInformation.Type );
  705. SmbPutUshort( &response->DeviceState, srvFileInformation.HandleState );
  706. } else {
  707. RtlZeroMemory( (PVOID)&response->FileAttributes, 16 );
  708. }
  709. //
  710. // Bit field mapping of Action:
  711. //
  712. // Lrrr rrrr rrrr rrOO
  713. //
  714. // where:
  715. //
  716. // L - Lock (single-user total file lock status)
  717. // 0 - file opened by another user
  718. // 1 - file is opened only by this user at the present time
  719. //
  720. // O - Open (action taken on open)
  721. // 1 - the file existed and was opened
  722. // 2 - the file did not exist but was created
  723. // 3 - the file existed and was truncated
  724. //
  725. switch ( ioStatusBlock->Information ) {
  726. case FILE_OPENED:
  727. action |= SMB_OACT_OPENED;
  728. break;
  729. case FILE_CREATED:
  730. action |= SMB_OACT_CREATED;
  731. break;
  732. case FILE_OVERWRITTEN:
  733. action |= SMB_OACT_TRUNCATED;
  734. break;
  735. default:
  736. IF_DEBUG(ERRORS) {
  737. KdPrint(( "Unknown Information value in IO status block: 0x%p\n",
  738. (PVOID)(ioStatusBlock->Information) ));
  739. }
  740. }
  741. SmbPutUshort( &response->Action, action );
  742. SmbPutUlong( &response->ServerFid, (ULONG)0 );
  743. SmbPutUshort( &response->Reserved, 0 );
  744. SmbPutUshort( &response->ByteCount, 0 );
  745. WorkContext->ResponseParameters = (PCHAR)WorkContext->ResponseHeader +
  746. SmbGetUshort( &response->AndXOffset );
  747. //
  748. // Test for legal followon command.
  749. //
  750. switch ( nextCommand ) {
  751. case SMB_COM_NO_ANDX_COMMAND:
  752. break;
  753. case SMB_COM_READ:
  754. case SMB_COM_READ_ANDX:
  755. case SMB_COM_IOCTL:
  756. //
  757. // Make sure the AndX command is still within the received SMB
  758. //
  759. if( (PCHAR)WorkContext->RequestHeader + reqAndXOffset <=
  760. END_OF_REQUEST_SMB( WorkContext ) ) {
  761. break;
  762. }
  763. /* Falls Through */
  764. default: // Illegal followon command
  765. IF_DEBUG(SMB_ERRORS) {
  766. KdPrint(( "SrvSmbOpenAndX: Illegal followon command: 0x%lx\n",
  767. nextCommand ));
  768. }
  769. //
  770. // Return an error indicating that the followon command was bad.
  771. // Note that the open is still considered successful, so the
  772. // file remains open.
  773. //
  774. SrvSetSmbError( WorkContext, STATUS_INVALID_SMB );
  775. return SmbStatusSendResponse;
  776. }
  777. //
  778. // If there is an AndX command, set up to process it. Otherwise,
  779. // indicate completion to the caller.
  780. //
  781. if ( nextCommand != SMB_COM_NO_ANDX_COMMAND ) {
  782. WorkContext->NextCommand = nextCommand;
  783. WorkContext->RequestParameters = (PCHAR)WorkContext->RequestHeader +
  784. reqAndXOffset;
  785. return SmbStatusMoreCommands;
  786. }
  787. IF_DEBUG(TRACE2) KdPrint(( "SrvSmbOpenAndX complete.\n" ));
  788. return SmbStatusSendResponse;
  789. } // GenerateOpenAndXResponse
  790. SMB_TRANS_STATUS
  791. SrvSmbOpen2 (
  792. IN OUT PWORK_CONTEXT WorkContext
  793. )
  794. /*++
  795. Routine Description:
  796. Processes an Open2 SMB. This request arrives in a Transaction2 SMB.
  797. Arguments:
  798. WorkContext - Supplies the address of a Work Context Block
  799. describing the current request. See smbtypes.h for a more
  800. complete description of the valid fields.
  801. Return Value:
  802. BOOLEAN - Indicates whether an error occurred. See smbtypes.h for a
  803. more complete description.
  804. --*/
  805. {
  806. PREQ_OPEN2 request;
  807. PRESP_OPEN2 response;
  808. NTSTATUS status = STATUS_SUCCESS;
  809. SMB_TRANS_STATUS SmbStatus = SmbTransStatusInProgress;
  810. USHORT access;
  811. PTRANSACTION transaction;
  812. ULONG eaErrorOffset = 0;
  813. USHORT os2EaErrorOffset = 0;
  814. PFILE_FULL_EA_INFORMATION ntFullEa;
  815. ULONG ntFullEaBufferLength;
  816. PFEALIST feaList;
  817. PAGED_CODE( );
  818. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  819. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN2;
  820. SrvWmiStartContext(WorkContext);
  821. transaction = WorkContext->Parameters.Transaction;
  822. request = (PREQ_OPEN2)transaction->InParameters;
  823. response = (PRESP_OPEN2)transaction->OutParameters;
  824. //
  825. // Verify that enough parameter bytes were sent and that we're allowed
  826. // to return enough parameter bytes.
  827. //
  828. if ( (transaction->ParameterCount < sizeof(REQ_OPEN2)) ||
  829. (transaction->MaxParameterCount < sizeof(RESP_OPEN2)) ) {
  830. //
  831. // Not enough parameter bytes were sent.
  832. //
  833. IF_DEBUG(SMB_ERRORS)
  834. KdPrint(( "SrvSmbOpen2: bad parameter byte counts: %ld %ld\n",
  835. transaction->ParameterCount,
  836. transaction->MaxParameterCount ));
  837. SrvLogInvalidSmb( WorkContext );
  838. SrvSetSmbError2( WorkContext, STATUS_INVALID_SMB, TRUE );
  839. status = STATUS_INVALID_SMB;
  840. goto err_exit;
  841. }
  842. //
  843. // Convert the EA list to NT style.
  844. //
  845. eaErrorOffset = 0;
  846. feaList = (PFEALIST)transaction->InData;
  847. //
  848. // Make sure that the value in Fealist->cbList is legitimate and that
  849. // there is at least sufficient data for a single EA.
  850. //
  851. // This code will fail if no EA list is indicated. Don't know
  852. // if this is correct, but it was the previous behavior so
  853. // it's been enforced.
  854. //
  855. if ( transaction->DataCount <= sizeof(FEALIST) ||
  856. SmbGetUlong( &feaList->cbList ) <= sizeof(FEALIST) ||
  857. SmbGetUlong( &feaList->cbList ) > transaction->DataCount) {
  858. IF_DEBUG(SMB_ERRORS) {
  859. KdPrint(( "EA list size bad: size = %ld, data sent was %ld\n",
  860. SmbGetUlong( &feaList->cbList ), transaction->DataCount ));
  861. }
  862. SrvSetSmbError2( WorkContext, STATUS_OS2_EA_LIST_INCONSISTENT, TRUE );
  863. status = STATUS_OS2_EA_LIST_INCONSISTENT;
  864. goto err_exit;
  865. }
  866. //
  867. // Convert the FEALIST to NT style.
  868. //
  869. status = SrvOs2FeaListToNt(
  870. feaList,
  871. &ntFullEa,
  872. &ntFullEaBufferLength,
  873. &os2EaErrorOffset
  874. );
  875. if ( !NT_SUCCESS(status) ) {
  876. SrvSetSmbError2( WorkContext, status, TRUE );
  877. goto err_exit;
  878. }
  879. access = SmbGetUshort( &request->DesiredAccess ); // save for later use
  880. status = SrvCreateFile(
  881. WorkContext,
  882. access,
  883. SmbGetUshort( &request->FileAttributes ),
  884. SmbGetUshort( &request->OpenFunction ),
  885. SmbGetUlong( &request->AllocationSize ),
  886. (PCHAR)request->Buffer,
  887. END_OF_TRANSACTION_PARAMETERS( transaction ),
  888. ntFullEa,
  889. ntFullEaBufferLength,
  890. &eaErrorOffset,
  891. (SmbGetUshort(&request->Flags) & SMB_OPEN_OPBATCH) != 0 ?
  892. OplockTypeBatch :
  893. (SmbGetUshort(&request->Flags) & SMB_OPEN_OPLOCK) != 0 ?
  894. OplockTypeExclusive : OplockTypeServerBatch,
  895. RestartOpen2
  896. );
  897. if ( status == STATUS_OPLOCK_BREAK_IN_PROGRESS ) {
  898. //
  899. // The open is blocked (waiting for a comm device or an oplock
  900. // break), do not send a reply.
  901. //
  902. //
  903. // Save a pointer to the full ea structure
  904. //
  905. WorkContext->Parameters2.Open.NtFullEa = ntFullEa;
  906. WorkContext->Parameters2.Open.EaErrorOffset = eaErrorOffset;
  907. SmbStatus = SmbTransStatusInProgress;
  908. goto Cleanup;
  909. } else if ( WorkContext->Parameters2.Open.TemporaryOpen ) {
  910. //
  911. // The initial open failed due to a sharing violation, possibly
  912. // caused by an batch oplock. Requeue the open to a blocking
  913. // thread.
  914. //
  915. // We need to free the EA buffer in this case.
  916. //
  917. DEALLOCATE_NONPAGED_POOL(ntFullEa);
  918. WorkContext->FspRestartRoutine = (PRESTART_ROUTINE)ExecuteTransaction;
  919. SrvQueueWorkToBlockingThread( WorkContext );
  920. SmbStatus = SmbStatusInProgress;
  921. goto Cleanup;
  922. } else {
  923. //
  924. // Save a pointer to the full ea structure
  925. //
  926. WorkContext->Parameters2.Open.NtFullEa = ntFullEa;
  927. WorkContext->Parameters2.Open.EaErrorOffset = eaErrorOffset;
  928. //
  929. // The open has completed. Generate and send the reply.
  930. //
  931. SmbStatus = GenerateOpen2Response( WorkContext, status );
  932. goto Cleanup;
  933. }
  934. err_exit:
  935. RtlZeroMemory( (PVOID)&response->Fid, 24 );
  936. SmbPutUshort( &response->EaErrorOffset, os2EaErrorOffset );
  937. SmbPutUlong( &response->EaLength, 0 );
  938. transaction->SetupCount = 0;
  939. transaction->ParameterCount = sizeof(RESP_OPEN2);
  940. transaction->DataCount = 0;
  941. SmbStatus = SmbTransStatusErrorWithData;
  942. Cleanup:
  943. SrvWmiEndContext(WorkContext);
  944. return SmbStatus;
  945. } // SrvSmbOpen2
  946. VOID SRVFASTCALL
  947. RestartOpen2 (
  948. PWORK_CONTEXT WorkContext
  949. )
  950. /*++
  951. Routine Description:
  952. Completes processing of an Open2 SMB.
  953. Arguments:
  954. WorkContext - Work context block for the operation.
  955. Return Value:
  956. None.
  957. --*/
  958. {
  959. SMB_TRANS_STATUS smbStatus = SmbTransStatusInProgress;
  960. NTSTATUS openStatus = STATUS_SUCCESS;
  961. PAGED_CODE( );
  962. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  963. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN2;
  964. SrvWmiStartContext(WorkContext);
  965. openStatus = SrvCheckOplockWaitState( WorkContext->WaitForOplockBreak );
  966. if ( NT_SUCCESS( openStatus ) ) {
  967. openStatus = WorkContext->Irp->IoStatus.Status;
  968. if( NT_SUCCESS( openStatus ) ) {
  969. //
  970. // It's obvious that the file already existed, because we've
  971. // been working on an oplock break. So set the
  972. // IoStatus.Information field correctly.
  973. //
  974. WorkContext->Irp->IoStatus.Information = FILE_OPENED;
  975. }
  976. } else {
  977. //
  978. // This open was waiting for an oplock break to occur, but
  979. // timed out. Close our handle to this file, then fail the open.
  980. //
  981. SrvCloseRfcb( WorkContext->Parameters2.Open.Rfcb );
  982. }
  983. WorkContext->Irp->IoStatus.Information = WorkContext->Parameters2.Open.IosbInformation;
  984. smbStatus = GenerateOpen2Response(
  985. WorkContext,
  986. openStatus
  987. );
  988. SrvCompleteExecuteTransaction( WorkContext, smbStatus );
  989. SrvWmiEndContext(WorkContext);
  990. return;
  991. } // RestartOpen2
  992. SMB_TRANS_STATUS
  993. GenerateOpen2Response (
  994. PWORK_CONTEXT WorkContext,
  995. NTSTATUS OpenStatus
  996. )
  997. /*++
  998. Routine Description:
  999. Generates a response to an Open and X SMB and setup for furthur
  1000. SMB processing.
  1001. Arguments:
  1002. WorkContext - Work context block for the operation.
  1003. OpenStatus - The status of the open operation.
  1004. Return Value:
  1005. None.
  1006. --*/
  1007. {
  1008. PREQ_OPEN2 request;
  1009. PRESP_OPEN2 response;
  1010. PRFCB rfcb;
  1011. PLFCB lfcb;
  1012. NTSTATUS status;
  1013. BOOLEAN reqAdditionalInformation;
  1014. SRV_FILE_INFORMATION_ABBREVIATED srvFileInformation;
  1015. BOOLEAN reqEaLength;
  1016. FILE_EA_INFORMATION fileEaInformation;
  1017. USHORT access;
  1018. USHORT action = 0;
  1019. PTRANSACTION transaction;
  1020. ULONG eaErrorOffset = 0;
  1021. USHORT os2EaErrorOffset = 0;
  1022. PFILE_FULL_EA_INFORMATION ntFullEa;
  1023. PFEALIST feaList;
  1024. OPLOCK_TYPE oplockType;
  1025. PAGED_CODE( );
  1026. transaction = WorkContext->Parameters.Transaction;
  1027. request = (PREQ_OPEN2)transaction->InParameters;
  1028. response = (PRESP_OPEN2)transaction->OutParameters;
  1029. feaList = (PFEALIST)transaction->InData;
  1030. ntFullEa = WorkContext->Parameters2.Open.NtFullEa;
  1031. eaErrorOffset = WorkContext->Parameters2.Open.EaErrorOffset;
  1032. access = SmbGetUshort( &request->DesiredAccess ); // save for later use
  1033. //
  1034. // If the open failed, send an error response.
  1035. //
  1036. if ( !NT_SUCCESS( OpenStatus ) ) {
  1037. SrvSetSmbError( WorkContext, OpenStatus );
  1038. //
  1039. // Remap the error if it is ERROR_ALREADY_EXISTS.
  1040. //
  1041. if ( !CLIENT_CAPABLE_OF(NT_STATUS,WorkContext->Connection) &&
  1042. SmbGetUshort( &WorkContext->ResponseHeader->Error ) ==
  1043. ERROR_ALREADY_EXISTS ) {
  1044. SmbPutUshort(
  1045. &WorkContext->ResponseHeader->Error,
  1046. ERROR_FILE_EXISTS
  1047. );
  1048. }
  1049. //
  1050. // If an EA error offset was returned, convert it from an offset
  1051. // into the NT full EA list to an offset in the OS/2 1.2 FEALIST.
  1052. //
  1053. if ( eaErrorOffset != 0 ) {
  1054. os2EaErrorOffset = SrvGetOs2FeaOffsetOfError(
  1055. eaErrorOffset,
  1056. ntFullEa,
  1057. feaList
  1058. );
  1059. }
  1060. DEALLOCATE_NONPAGED_POOL( ntFullEa );
  1061. goto err_exit;
  1062. }
  1063. DEALLOCATE_NONPAGED_POOL( ntFullEa );
  1064. //
  1065. // If the file was created, set the EOF location to be the same as
  1066. // the size of the file. This is necessary for compatibility with
  1067. // OS/2, which only has EOF, not a separate allocation size.
  1068. //
  1069. rfcb = WorkContext->Rfcb;
  1070. lfcb = rfcb->Lfcb;
  1071. if ( (WorkContext->Irp->IoStatus.Information == FILE_CREATED) ||
  1072. (WorkContext->Irp->IoStatus.Information == FILE_OVERWRITTEN) ) {
  1073. //
  1074. // Extending EOF is only legal if the client has write access
  1075. // to the file. If the client doesn't have write access, don't
  1076. // extend the file.
  1077. //
  1078. // *** This is an incompatibility with OS/2.
  1079. if ( rfcb->WriteAccessGranted || rfcb->AppendAccessGranted ) {
  1080. SetEofToMatchAllocation(
  1081. lfcb->FileHandle,
  1082. SmbGetUlong( &request->AllocationSize )
  1083. );
  1084. } else {
  1085. SrvStatistics.GrantedAccessErrors++;
  1086. }
  1087. }
  1088. //
  1089. // If the consumer requested additional information, find it now.
  1090. //
  1091. reqAdditionalInformation =
  1092. (BOOLEAN)((SmbGetUshort( &request->Flags ) &
  1093. SMB_OPEN_QUERY_INFORMATION) != 0);
  1094. reqEaLength =
  1095. (BOOLEAN)((SmbGetUshort( &request->Flags ) &
  1096. SMB_OPEN_QUERY_EA_LENGTH) != 0);
  1097. if ( reqAdditionalInformation ||
  1098. (!rfcb->WriteAccessGranted && rfcb->AppendAccessGranted) ) {
  1099. //
  1100. // We always open with at least FILE_READ_ATTRIBUTES, so no
  1101. // access check is needed.
  1102. //
  1103. status = SrvQueryInformationFileAbbreviated(
  1104. lfcb->FileHandle,
  1105. lfcb->FileObject,
  1106. &srvFileInformation,
  1107. FALSE,
  1108. WorkContext->TreeConnect->Share->ShareType
  1109. );
  1110. if ( !NT_SUCCESS(status) ) {
  1111. IF_DEBUG(ERRORS) {
  1112. KdPrint(( "SrvSmbOpen2: SrvQueryInformationFile failed: "
  1113. "%X\n", status ));
  1114. }
  1115. SrvCloseRfcb( rfcb );
  1116. SrvSetSmbError2( WorkContext, status, TRUE );
  1117. goto err_exit;
  1118. }
  1119. rfcb->Mfcb->NonpagedMfcb->OpenFileSize = srvFileInformation.DataSize;
  1120. }
  1121. if ( reqEaLength ) {
  1122. IO_STATUS_BLOCK eaIoStatusBlock;
  1123. status = NtQueryInformationFile(
  1124. lfcb->FileHandle,
  1125. &eaIoStatusBlock,
  1126. &fileEaInformation,
  1127. sizeof(FILE_EA_INFORMATION),
  1128. FileEaInformation
  1129. );
  1130. if ( NT_SUCCESS(status) ) {
  1131. status = eaIoStatusBlock.Status;
  1132. }
  1133. if ( !NT_SUCCESS(status) ) {
  1134. INTERNAL_ERROR(
  1135. ERROR_LEVEL_UNEXPECTED,
  1136. "SrvSmbOpen2: NtQueryInformationFile (file information)"
  1137. "returned %X",
  1138. status,
  1139. NULL
  1140. );
  1141. SrvCloseRfcb( rfcb );
  1142. SrvSetSmbError2( WorkContext, status, TRUE );
  1143. goto err_exit;
  1144. } else {
  1145. //
  1146. // Adjust the EA size. If there are no EAs, OS/2 expects
  1147. // EA size = 4.
  1148. //
  1149. if (fileEaInformation.EaSize == 0) {
  1150. fileEaInformation.EaSize = 4;
  1151. }
  1152. }
  1153. } else {
  1154. fileEaInformation.EaSize = 0;
  1155. }
  1156. //
  1157. // Attempt to acquire the oplock.
  1158. //
  1159. if ( WorkContext->TreeConnect->Share->ShareType != ShareTypePrint ) {
  1160. if ( (SmbGetUshort( &request->Flags ) & SMB_OPEN_OPBATCH) != 0 ) {
  1161. oplockType = OplockTypeBatch;
  1162. } else if ( (SmbGetUshort( &request->Flags ) & SMB_OPEN_OPLOCK) != 0 ) {
  1163. oplockType = OplockTypeExclusive;
  1164. } else {
  1165. oplockType = OplockTypeServerBatch;
  1166. }
  1167. if ( SrvRequestOplock( WorkContext, &oplockType, FALSE ) ) {
  1168. action = SMB_OACT_OPLOCK;
  1169. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksGranted );
  1170. } else {
  1171. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksDenied );
  1172. }
  1173. }
  1174. //
  1175. // Set up response SMB.
  1176. //
  1177. SmbPutUshort( &response->Fid, rfcb->Fid );
  1178. //
  1179. // If the consumer requested additional information, set appropiate
  1180. // fields, else set the fields to zero.
  1181. //
  1182. if ( reqAdditionalInformation ) {
  1183. SmbPutUshort(
  1184. &response->FileAttributes,
  1185. srvFileInformation.Attributes
  1186. );
  1187. SmbPutUlong( &response->DataSize, srvFileInformation.DataSize.LowPart );
  1188. SmbPutUshort( &response->GrantedAccess, access );
  1189. SmbPutUshort( &response->FileType, srvFileInformation.Type );
  1190. SmbPutUshort( &response->DeviceState, srvFileInformation.HandleState );
  1191. } else {
  1192. RtlZeroMemory( (PVOID)&response->FileAttributes, 16 );
  1193. }
  1194. //
  1195. // Bit field mapping of Action:
  1196. //
  1197. // Lrrr rrrr rrrr rrOO
  1198. //
  1199. // where:
  1200. //
  1201. // L - Lock (single-user total file lock status)
  1202. // 0 - file opened by another user
  1203. // 1 - file is opened only by this user at the present time
  1204. //
  1205. // O - Open (action taken on open)
  1206. // 1 - the file existed and was opened
  1207. // 2 - the file did not exist but was created
  1208. // 3 - the file existed and was truncated
  1209. //
  1210. switch ( WorkContext->Irp->IoStatus.Information ) {
  1211. case FILE_OPENED:
  1212. action |= SMB_OACT_OPENED;
  1213. break;
  1214. case FILE_CREATED:
  1215. action |= SMB_OACT_CREATED;
  1216. break;
  1217. case FILE_OVERWRITTEN:
  1218. action |= SMB_OACT_TRUNCATED;
  1219. break;
  1220. default:
  1221. INTERNAL_ERROR(
  1222. ERROR_LEVEL_UNEXPECTED,
  1223. "SrvSmbOpen2: Unknown Information value in IO status"
  1224. "block: 0x%lx\n",
  1225. WorkContext->Irp->IoStatus.Information,
  1226. NULL
  1227. );
  1228. SrvLogServiceFailure( SRV_SVC_IO_CREATE_FILE,
  1229. (ULONG)WorkContext->Irp->IoStatus.Information );
  1230. }
  1231. SmbPutUshort( &response->Action, action );
  1232. SmbPutUlong( &response->ServerFid, (ULONG)0 );
  1233. SmbPutUshort( &response->EaErrorOffset, 0 );
  1234. SmbPutUlong( &response->EaLength, fileEaInformation.EaSize );
  1235. transaction->SetupCount = 0;
  1236. transaction->ParameterCount = sizeof(RESP_OPEN2);
  1237. transaction->DataCount = 0;
  1238. IF_DEBUG(TRACE2) KdPrint(( "SrvSmbOpen2 complete.\n" ));
  1239. return SmbTransStatusSuccess;
  1240. err_exit:
  1241. RtlZeroMemory( (PVOID)&response->Fid, 24 );
  1242. SmbPutUshort( &response->EaErrorOffset, os2EaErrorOffset );
  1243. SmbPutUlong( &response->EaLength, 0 );
  1244. transaction->SetupCount = 0;
  1245. transaction->ParameterCount = sizeof(RESP_OPEN2);
  1246. transaction->DataCount = 0;
  1247. return SmbTransStatusErrorWithData;
  1248. } // GenerateOpen2Response
  1249. SMB_PROCESSOR_RETURN_TYPE
  1250. SrvSmbNtCreateAndX (
  1251. SMB_PROCESSOR_PARAMETERS
  1252. )
  1253. /*++
  1254. Routine Description:
  1255. Processes an NtCreateAndX SMB.
  1256. Arguments:
  1257. SMB_PROCESSOR_PARAMETERS - See smbprocs.h for a description
  1258. of the parameters to SMB processor routines.
  1259. Return Value:
  1260. SMB_PROCESSOR_RETURN_TYPE - See smbprocs.h
  1261. --*/
  1262. {
  1263. PREQ_NT_CREATE_ANDX request;
  1264. #ifdef INCLUDE_SMB_IFMODIFIED
  1265. PREQ_NT_CREATE_IF_MODIFIED_ANDX requestIfModified = NULL;
  1266. BOOLEAN ifModifiedCheck = FALSE;
  1267. #endif
  1268. ULONG flags;
  1269. NTSTATUS status = STATUS_SUCCESS;
  1270. SMB_STATUS SmbStatus = SmbStatusInProgress;
  1271. LARGE_INTEGER allocationSize;
  1272. UNICODE_STRING fileName;
  1273. PUCHAR name;
  1274. USHORT nameLength;
  1275. SECURITY_QUALITY_OF_SERVICE qualityOfService;
  1276. BOOLEAN isUnicode;
  1277. PAGED_CODE( );
  1278. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  1279. WorkContext->PreviousSMB = EVENT_TYPE_SMB_NT_CREATE_AND_X;
  1280. SrvWmiStartContext(WorkContext);
  1281. IF_SMB_DEBUG(OPEN_CLOSE1) {
  1282. KdPrint(( "Create file and X request header at 0x%p, response header at 0x%p\n",
  1283. WorkContext->RequestHeader,
  1284. WorkContext->ResponseHeader ));
  1285. KdPrint(( "Create file and X request parameters at 0x%p, response parameters at 0x%p\n",
  1286. WorkContext->RequestParameters,
  1287. WorkContext->ResponseParameters ));
  1288. }
  1289. request = (PREQ_NT_CREATE_ANDX)WorkContext->RequestParameters;
  1290. allocationSize.HighPart = SmbGetUlong( &request->AllocationSize.HighPart );
  1291. allocationSize.LowPart = SmbGetUlong( &request->AllocationSize.LowPart );
  1292. flags = SmbGetUlong( &request->Flags );
  1293. #ifdef INCLUDE_SMB_IFMODIFIED
  1294. if (IS_POSTNT5_DIALECT( WorkContext->Connection->SmbDialect )) {
  1295. ifModifiedCheck = ((flags & NT_CREATE_IFMODIFIED_REQUEST) != 0 );
  1296. if (ifModifiedCheck) {
  1297. requestIfModified = (PREQ_NT_CREATE_IF_MODIFIED_ANDX) request;
  1298. }
  1299. }
  1300. #endif
  1301. //
  1302. // First verify that the file path name does not extend beyond the
  1303. // end of the SMB.
  1304. //
  1305. isUnicode = SMB_IS_UNICODE( WorkContext );
  1306. //
  1307. // if this request has IfModifiedSince fields, the request is of a
  1308. // slightly different format, the Name field is lower.
  1309. //
  1310. #ifdef INCLUDE_SMB_IFMODIFIED
  1311. if (requestIfModified != NULL) {
  1312. name = (PUCHAR)requestIfModified->Buffer;
  1313. } else {
  1314. name = (PUCHAR)request->Buffer;
  1315. }
  1316. #else
  1317. name = (PUCHAR)request->Buffer;
  1318. #endif
  1319. if ( isUnicode ) {
  1320. name = ALIGN_SMB_WSTR( name );
  1321. }
  1322. nameLength = SmbGetUshort( &request->NameLength );
  1323. if ( name + nameLength > ( END_OF_REQUEST_SMB( WorkContext ) + 1 ) ) {
  1324. status = STATUS_INVALID_SMB;
  1325. SmbStatus = GenerateNtCreateAndXResponse( WorkContext, STATUS_INVALID_SMB );
  1326. goto Cleanup;
  1327. }
  1328. //
  1329. // Convert the file name to a Unicode string.
  1330. //
  1331. status = SrvMakeUnicodeString(
  1332. isUnicode,
  1333. &fileName,
  1334. name,
  1335. &nameLength
  1336. );
  1337. if ( !NT_SUCCESS( status ) ) {
  1338. status = STATUS_INSUFF_SERVER_RESOURCES;
  1339. SmbStatus = GenerateNtCreateAndXResponse(
  1340. WorkContext,
  1341. STATUS_INSUFF_SERVER_RESOURCES
  1342. );
  1343. goto Cleanup;
  1344. }
  1345. //
  1346. // *** We always ask for STATIC tracking, not DYNAMIC, because we
  1347. // don't support dynamic tracking over the net yet.
  1348. //
  1349. // !!! Note that once we support dynamic tracking, we MUST CHANGE
  1350. // THE NAMED PIPE PROCESSING to not do writes/transceives at DPC
  1351. // level, because the NPFS needs to call SeCreateClientSecurity
  1352. // on every write when dynamic tracking is selected!
  1353. //
  1354. qualityOfService.Length = sizeof( qualityOfService );
  1355. qualityOfService.ImpersonationLevel =
  1356. SmbGetUlong( &request->ImpersonationLevel );
  1357. qualityOfService.ContextTrackingMode = FALSE;
  1358. //qualityOfService.ContextTrackingMode = (BOOLEAN)
  1359. // (request->SecurityFlags & SMB_SECURITY_DYNAMIC_TRACKING);
  1360. qualityOfService.EffectiveOnly = (BOOLEAN)
  1361. (request->SecurityFlags & SMB_SECURITY_EFFECTIVE_ONLY);
  1362. status = SrvNtCreateFile(
  1363. WorkContext,
  1364. SmbGetUlong( &request->RootDirectoryFid ),
  1365. SmbGetUlong( &request->DesiredAccess ),
  1366. allocationSize,
  1367. SmbGetUlong( &request->FileAttributes ),
  1368. SmbGetUlong( &request->ShareAccess ),
  1369. SmbGetUlong( &request->CreateDisposition ),
  1370. SmbGetUlong( &request->CreateOptions),
  1371. NULL,
  1372. &fileName,
  1373. NULL,
  1374. 0,
  1375. NULL,
  1376. flags,
  1377. &qualityOfService,
  1378. #ifdef INCLUDE_SMB_IFMODIFIED
  1379. (flags & NT_CREATE_REQUEST_OPBATCH) != 0 ?
  1380. OplockTypeBatch :
  1381. (flags & NT_CREATE_REQUEST_OPLOCK) != 0 ?
  1382. #else
  1383. (request->Flags & NT_CREATE_REQUEST_OPBATCH) != 0 ?
  1384. OplockTypeBatch :
  1385. (request->Flags & NT_CREATE_REQUEST_OPLOCK) != 0 ?
  1386. #endif
  1387. OplockTypeExclusive : OplockTypeServerBatch,
  1388. RestartNtCreateAndX
  1389. );
  1390. //
  1391. // Free the unicode file name buffer if it has been allocated.
  1392. //
  1393. if ( !isUnicode ) {
  1394. RtlFreeUnicodeString( &fileName );
  1395. }
  1396. if ( status == STATUS_OPLOCK_BREAK_IN_PROGRESS ) {
  1397. //
  1398. // The open is blocked (waiting for a comm device or an oplock
  1399. // break), do not send a reply.
  1400. //
  1401. SmbStatus = SmbStatusInProgress;
  1402. } else if ( WorkContext->Parameters2.Open.TemporaryOpen ) {
  1403. //
  1404. // The initial open failed due to a sharing violation, possibly
  1405. // caused by an batch oplock. Requeue the open to a blocking
  1406. // thread.
  1407. //
  1408. WorkContext->FspRestartRoutine = SrvRestartSmbReceived;
  1409. SrvQueueWorkToBlockingThread( WorkContext );
  1410. SmbStatus = SmbStatusInProgress;
  1411. } else {
  1412. //
  1413. // The open has completed. Generate and send the reply.
  1414. //
  1415. SmbStatus = GenerateNtCreateAndXResponse( WorkContext, status );
  1416. }
  1417. Cleanup:
  1418. SrvWmiEndContext(WorkContext);
  1419. return SmbStatus;
  1420. } // SrvSmbNtCreateAndX
  1421. VOID SRVFASTCALL
  1422. RestartNtCreateAndX (
  1423. PWORK_CONTEXT WorkContext
  1424. )
  1425. /*++
  1426. Routine Description:
  1427. Completes processing of an Nt Create and X SMB.
  1428. Arguments:
  1429. WorkContext - Work context block for the operation.
  1430. Return Value:
  1431. None.
  1432. --*/
  1433. {
  1434. SMB_PROCESSOR_RETURN_LOCAL smbStatus = SmbStatusInProgress;
  1435. NTSTATUS openStatus = STATUS_SUCCESS;
  1436. PAGED_CODE( );
  1437. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  1438. WorkContext->PreviousSMB = EVENT_TYPE_SMB_NT_CREATE_AND_X;
  1439. SrvWmiStartContext(WorkContext);
  1440. openStatus = SrvCheckOplockWaitState( WorkContext->WaitForOplockBreak );
  1441. if ( NT_SUCCESS( openStatus ) ) {
  1442. openStatus = WorkContext->Irp->IoStatus.Status;
  1443. } else {
  1444. //
  1445. // This open was waiting for an oplock break to occur, but
  1446. // timed out. Close our handle to this file, then fail the open.
  1447. //
  1448. SrvCloseRfcb( WorkContext->Parameters2.Open.Rfcb );
  1449. }
  1450. WorkContext->Irp->IoStatus.Information = WorkContext->Parameters2.Open.IosbInformation;
  1451. smbStatus = GenerateNtCreateAndXResponse(
  1452. WorkContext,
  1453. openStatus
  1454. );
  1455. if ( smbStatus == SmbStatusMoreCommands ) {
  1456. SrvProcessSmb( WorkContext );
  1457. } else {
  1458. #ifdef INCLUDE_SMB_IFMODIFIED
  1459. SrvEndSmbProcessing( WorkContext, smbStatus );
  1460. #else
  1461. SrvEndSmbProcessing( WorkContext, SmbStatusSendResponse );
  1462. #endif
  1463. }
  1464. SrvWmiEndContext(WorkContext);
  1465. return;
  1466. } // RestartNtCreateAndX
  1467. SMB_PROCESSOR_RETURN_TYPE
  1468. GenerateNtCreateAndXResponse (
  1469. PWORK_CONTEXT WorkContext,
  1470. NTSTATUS OpenStatus
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. Generates a response to an Nt Create and X SMB and setup for furthur
  1475. SMB processing.
  1476. Arguments:
  1477. WorkContext - Work context block for the operation.
  1478. OpenStatus - The status of the open operation.
  1479. Return Value:
  1480. None.
  1481. Notes:
  1482. --*/
  1483. {
  1484. PREQ_NT_CREATE_ANDX request;
  1485. PRESP_NT_CREATE_ANDX response;
  1486. #ifdef INCLUDE_SMB_IFMODIFIED
  1487. PREQ_NT_CREATE_IF_MODIFIED_ANDX requestIfModified = NULL;
  1488. BOOLEAN GenerateExtendedResponse2 = FALSE;
  1489. BOOLEAN extendedRequested2 = FALSE;
  1490. BOOLEAN ifModifiedCheck = FALSE;
  1491. #ifdef INCLUDE_SMB_PERSISTENT
  1492. BOOLEAN persistentHandle = FALSE;
  1493. #endif
  1494. ULONG flags;
  1495. BOOLEAN byteCountSet = FALSE;
  1496. LARGE_INTEGER ourFileRefNumber;
  1497. LARGE_INTEGER ourUsnValue;
  1498. #endif
  1499. SMB_PROCESSOR_RETURN_LOCAL rc;
  1500. BOOLEAN GenerateExtendedResponse = FALSE;
  1501. SRV_NT_FILE_INFORMATION srvNtFileInformation;
  1502. PRFCB rfcb;
  1503. PIO_STATUS_BLOCK ioStatusBlock;
  1504. UCHAR nextCommand;
  1505. USHORT reqAndXOffset;
  1506. OPLOCK_TYPE oplockType;
  1507. UCHAR oplockLevel;
  1508. BOOLEAN allowLevelII;
  1509. BOOLEAN extendedRequested;
  1510. ULONG CreateAction = (ULONG)WorkContext->Irp->IoStatus.Information;
  1511. ULONG desiredAccess;
  1512. NTSTATUS status;
  1513. PAGED_CODE( );
  1514. //
  1515. // If the open failed, send an error response.
  1516. //
  1517. if ( !NT_SUCCESS( OpenStatus ) ) {
  1518. SrvSetSmbError( WorkContext, OpenStatus );
  1519. //
  1520. // Remap the error if it is ERROR_ALREADY_EXISTS
  1521. //
  1522. if ( !CLIENT_CAPABLE_OF(NT_STATUS, WorkContext->Connection) &&
  1523. SmbGetUshort( &WorkContext->ResponseHeader->Error ) ==
  1524. ERROR_ALREADY_EXISTS ) {
  1525. SmbPutUshort(
  1526. &WorkContext->ResponseHeader->Error,
  1527. ERROR_FILE_EXISTS
  1528. );
  1529. }
  1530. return SmbStatusSendResponse;
  1531. }
  1532. request = (PREQ_NT_CREATE_ANDX)WorkContext->RequestParameters;
  1533. response = (PRESP_NT_CREATE_ANDX)WorkContext->ResponseParameters;
  1534. #ifdef INCLUDE_SMB_IFMODIFIED
  1535. //
  1536. // these are the USN journal values for this file iff we need them.
  1537. //
  1538. ourFileRefNumber.QuadPart = 0;
  1539. ourUsnValue.QuadPart = 0;
  1540. flags = SmbGetUlong( &request->Flags );
  1541. //
  1542. // Does the client want extended info in the response?
  1543. //
  1544. extendedRequested = ((flags & NT_CREATE_REQUEST_EXTENDED_RESPONSE) != 0 );
  1545. if (IS_POSTNT5_DIALECT( WorkContext->Connection->SmbDialect )) {
  1546. extendedRequested2 = ((flags & NT_CREATE_REQUEST_EXTENDED_RESPONSE2) != 0 );
  1547. #ifdef INCLUDE_SMB_PERSISTENT
  1548. persistentHandle = ((flags & NT_CREATE_PERSISTANT_HANDLE) != 0 );
  1549. #endif
  1550. ifModifiedCheck = ((flags & NT_CREATE_IFMODIFIED_REQUEST) != 0 );
  1551. if (ifModifiedCheck) {
  1552. requestIfModified = (PREQ_NT_CREATE_IF_MODIFIED_ANDX) request;
  1553. }
  1554. }
  1555. #else
  1556. //
  1557. // Does the client want extended info in the response?
  1558. //
  1559. extendedRequested = ((request->Flags & NT_CREATE_REQUEST_EXTENDED_RESPONSE) != 0 );
  1560. #endif
  1561. desiredAccess = SmbGetUlong( &request->DesiredAccess );
  1562. rfcb = WorkContext->Rfcb;
  1563. //
  1564. // Attempt to acquire the oplock.
  1565. //
  1566. if ( desiredAccess != DELETE &&
  1567. !(request->CreateOptions & FILE_DIRECTORY_FILE) ) {
  1568. if ( request->Flags & NT_CREATE_REQUEST_OPLOCK ) {
  1569. allowLevelII = CLIENT_CAPABLE_OF( LEVEL_II_OPLOCKS, WorkContext->Connection );
  1570. if ( request->Flags & NT_CREATE_REQUEST_OPBATCH ) {
  1571. oplockType = OplockTypeBatch;
  1572. oplockLevel = SMB_OPLOCK_LEVEL_BATCH;
  1573. } else {
  1574. oplockType = OplockTypeExclusive;
  1575. oplockLevel = SMB_OPLOCK_LEVEL_EXCLUSIVE;
  1576. }
  1577. } else {
  1578. allowLevelII = FALSE;
  1579. oplockType = OplockTypeServerBatch;
  1580. oplockLevel = SMB_OPLOCK_LEVEL_NONE;
  1581. }
  1582. if( SrvRequestOplock( WorkContext, &oplockType, allowLevelII ) ) {
  1583. //
  1584. // The oplock was granted. Check to see if it was a level 2.
  1585. //
  1586. if ( oplockType == OplockTypeShareRead ) {
  1587. oplockLevel = SMB_OPLOCK_LEVEL_II;
  1588. }
  1589. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksGranted );
  1590. } else {
  1591. //
  1592. // The oplock request was denied.
  1593. //
  1594. oplockLevel = SMB_OPLOCK_LEVEL_NONE;
  1595. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksDenied );
  1596. }
  1597. } else {
  1598. oplockLevel = SMB_OPLOCK_LEVEL_NONE;
  1599. }
  1600. //
  1601. // If the file was created, set the EOF location to be the same as
  1602. // the size of the file. This is necessary for compatibility with
  1603. // OS/2, which only has EOF, not a separate allocation size.
  1604. //
  1605. ioStatusBlock = &WorkContext->Irp->IoStatus;
  1606. //
  1607. // We always open with at least FILE_READ_ATTRIBUTES, so no
  1608. // access check is needed.
  1609. //
  1610. status = SrvQueryNtInformationFile(
  1611. rfcb->Lfcb->FileHandle,
  1612. rfcb->Lfcb->FileObject,
  1613. rfcb->ShareType,
  1614. extendedRequested,
  1615. &srvNtFileInformation
  1616. );
  1617. if ( !NT_SUCCESS(status) ) {
  1618. IF_DEBUG(ERRORS) {
  1619. KdPrint(( "SrvSmbNtCreateAndX: SrvQueryNtInformationFile failed: "
  1620. "%X\n", status ));
  1621. }
  1622. SrvCloseRfcb( rfcb );
  1623. SrvSetSmbError( WorkContext, status );
  1624. return SmbStatusSendResponse;
  1625. }
  1626. //
  1627. // Save parts of the file info in the MFCB for fast tests on Compressed
  1628. // operations.
  1629. //
  1630. rfcb->Mfcb->NonpagedMfcb->OpenFileSize.QuadPart =
  1631. srvNtFileInformation.NwOpenInfo.EndOfFile.QuadPart;
  1632. rfcb->Mfcb->NonpagedMfcb->OpenFileAttributes =
  1633. srvNtFileInformation.NwOpenInfo.FileAttributes;
  1634. //
  1635. // if the client is doing an "IfModifiedSince" open, then we need to check
  1636. // the following fields out of the request:
  1637. //
  1638. // CreationTime
  1639. // LastWriteTime
  1640. // ChangeTime
  1641. // EndOfFile
  1642. // FileAttributes
  1643. // UsnValue / USN file reference number
  1644. //
  1645. // if they all match with what is currently set for the file, we close
  1646. // the file and return STATUS_FILE_CLOSED.
  1647. //
  1648. #ifdef INCLUDE_SMB_IFMODIFIED
  1649. if (ifModifiedCheck) {
  1650. LARGE_INTEGER usnValue;
  1651. LARGE_INTEGER fileRefNumber;
  1652. LARGE_INTEGER endOfFile;
  1653. TIME creationTime;
  1654. TIME lastWriteTime;
  1655. TIME changeTime;
  1656. ULONG fileAttributes;
  1657. ULONG ourAttributes;
  1658. endOfFile.HighPart = SmbGetUlong( &requestIfModified->EndOfFile.HighPart );
  1659. endOfFile.LowPart = SmbGetUlong( &requestIfModified->EndOfFile.LowPart );
  1660. creationTime.HighPart = SmbGetUlong( &requestIfModified->CreationTime.HighPart );
  1661. creationTime.LowPart = SmbGetUlong( &requestIfModified->CreationTime.LowPart );
  1662. lastWriteTime.HighPart = SmbGetUlong( &requestIfModified->LastWriteTime.HighPart );
  1663. lastWriteTime.LowPart = SmbGetUlong( &requestIfModified->LastWriteTime.LowPart );
  1664. changeTime.HighPart = SmbGetUlong( &requestIfModified->ChangeTime.HighPart );
  1665. changeTime.LowPart = SmbGetUlong( &requestIfModified->ChangeTime.LowPart );
  1666. usnValue.HighPart = SmbGetUlong( &requestIfModified->UsnValue.HighPart );
  1667. usnValue.LowPart = SmbGetUlong( &requestIfModified->UsnValue.LowPart );
  1668. fileRefNumber.HighPart = SmbGetUlong( &requestIfModified->FileReferenceNumber.HighPart );
  1669. fileRefNumber.LowPart = SmbGetUlong( &requestIfModified->FileReferenceNumber.LowPart );
  1670. //
  1671. // we ignore the NORMAL and ARCHIVE attributes because the client
  1672. // doesn't care if the these attributes have changed.
  1673. //
  1674. fileAttributes = SmbGetUlong( &requestIfModified->FileAttributes );
  1675. fileAttributes &= ~FILE_ATTRIBUTE_NORMAL;
  1676. fileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
  1677. ourAttributes = srvNtFileInformation.NwOpenInfo.FileAttributes;
  1678. ourAttributes &= ~FILE_ATTRIBUTE_NORMAL;
  1679. ourAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
  1680. if ( usnValue.QuadPart != 0 || fileRefNumber.QuadPart != 0 ) {
  1681. status = SrvIssueQueryUsnInfoRequest( rfcb,
  1682. FALSE,
  1683. &ourUsnValue,
  1684. &ourFileRefNumber );
  1685. if (! NT_SUCCESS(status)) {
  1686. IF_DEBUG(ERRORS) {
  1687. KdPrint(( "SrvSmbNtCreateAndX: Query USN info (1) failed: 0x%X for handle %u\n",
  1688. status, rfcb->Lfcb->FileObject ));
  1689. }
  1690. }
  1691. }
  1692. if (creationTime.QuadPart == srvNtFileInformation.NwOpenInfo.CreationTime.QuadPart &&
  1693. lastWriteTime.QuadPart == srvNtFileInformation.NwOpenInfo.LastWriteTime.QuadPart &&
  1694. changeTime.QuadPart == srvNtFileInformation.NwOpenInfo.ChangeTime.QuadPart &&
  1695. endOfFile.QuadPart == srvNtFileInformation.NwOpenInfo.EndOfFile.QuadPart &&
  1696. usnValue.QuadPart == ourUsnValue.QuadPart &&
  1697. fileRefNumber.QuadPart == ourFileRefNumber.QuadPart &&
  1698. fileAttributes == ourAttributes ) {
  1699. //
  1700. // the client has the current version of this file, so he wants
  1701. // the open to fail.
  1702. //
  1703. // KdPrint(( "SmbNtCreateAndX IfModified worked. Closing file.\n" ));
  1704. IF_DEBUG(ERRORS) {
  1705. KdPrint(( "SrvSmbNtCreateAndX: File doesn't pass IfModifiedSince clause.\n" ));
  1706. }
  1707. SrvCloseRfcb( rfcb );
  1708. SrvSetSmbError( WorkContext, STATUS_FILE_CLOSED );
  1709. return SmbStatusSendResponse;
  1710. }
  1711. // KdPrint(( "SmbNtCreateAndX IfModified ignored, opened the file.\n" ));
  1712. }
  1713. #endif
  1714. // If the extended response is required then
  1715. if ( extendedRequested ) {
  1716. NTSTATUS ExtendedResponseStatus;
  1717. PRESP_EXTENDED_NT_CREATE_ANDX pExtendedResponse;
  1718. pExtendedResponse = (PRESP_EXTENDED_NT_CREATE_ANDX)response;
  1719. ExtendedResponseStatus = SrvUpdateMaximalAccessRightsInResponse(
  1720. WorkContext,
  1721. &pExtendedResponse->MaximalAccessRights,
  1722. &pExtendedResponse->GuestMaximalAccessRights);
  1723. GenerateExtendedResponse = (ExtendedResponseStatus == STATUS_SUCCESS);
  1724. }
  1725. //
  1726. // Set up response SMB.
  1727. //
  1728. nextCommand = request->AndXCommand;
  1729. reqAndXOffset = SmbGetUshort( &request->AndXOffset );
  1730. response->AndXCommand = nextCommand;
  1731. response->AndXReserved = 0;
  1732. if (GenerateExtendedResponse) {
  1733. #ifdef INCLUDE_SMB_IFMODIFIED
  1734. PRESP_EXTENDED_NT_CREATE_ANDX pExtendedResponse;
  1735. pExtendedResponse = (PRESP_EXTENDED_NT_CREATE_ANDX)response;
  1736. #endif
  1737. SmbPutUshort(
  1738. &response->AndXOffset,
  1739. GET_ANDX_OFFSET(
  1740. WorkContext->ResponseHeader,
  1741. WorkContext->ResponseParameters,
  1742. RESP_EXTENDED_NT_CREATE_ANDX,
  1743. 0
  1744. )
  1745. );
  1746. response->WordCount = 42;
  1747. #ifdef INCLUDE_SMB_IFMODIFIED
  1748. SmbPutUshort( &pExtendedResponse->ByteCount, 0 );
  1749. byteCountSet = TRUE;
  1750. if (extendedRequested2 && (nextCommand == SMB_COM_NO_ANDX_COMMAND)) {
  1751. IO_STATUS_BLOCK ioStatus;
  1752. PFILE_NAME_INFORMATION fileNameInfo;
  1753. ULONG infoLength;
  1754. PRESP_EXTENDED_NT_CREATE_ANDX2 extendedResponse2;
  1755. ULONG bufLength;
  1756. extendedResponse2 = (PRESP_EXTENDED_NT_CREATE_ANDX2) request;
  1757. if (ourUsnValue.QuadPart == 0 && ourFileRefNumber.QuadPart == 0) {
  1758. status = SrvIssueQueryUsnInfoRequest( rfcb,
  1759. FALSE,
  1760. &ourUsnValue,
  1761. &ourFileRefNumber );
  1762. if (! NT_SUCCESS(status)) {
  1763. IF_DEBUG(ERRORS) {
  1764. KdPrint(( "SrvSmbNtCreateAndX: Query USN info (2) failed: 0x%X for handle %u\n",
  1765. status, rfcb->Lfcb->FileObject ));
  1766. }
  1767. }
  1768. }
  1769. //
  1770. // Put in the short and long file name values here for CSC. It's
  1771. // a RESP_EXTENDED_NT_CREATE_ANDX2 response. These requests
  1772. // cannot currently be compounded because the file names will
  1773. // overwrite the next command.
  1774. //
  1775. // get the short name to put in the buffer
  1776. fileNameInfo = (PFILE_NAME_INFORMATION) ALIGN_UP( &extendedResponse2->Buffer[0], ULONG );
  1777. //
  1778. // the buffer length we can use is all that remains in the
  1779. // receive buffer.
  1780. //
  1781. ASSERT( WorkContext->RequestBuffer == WorkContext->ResponseBuffer );
  1782. bufLength = min( WorkContext->RequestBuffer->BufferLength,
  1783. WorkContext->Connection->MaximumSendSize );
  1784. infoLength = (ULONG) ( bufLength -
  1785. ( (PCHAR) fileNameInfo -
  1786. (PCHAR) (WorkContext->RequestBuffer->Buffer) ));
  1787. infoLength -= sizeof(ULONG); // for alignment issues
  1788. status = NtQueryInformationFile(
  1789. rfcb->Lfcb->FileHandle,
  1790. &ioStatus,
  1791. (PVOID)fileNameInfo,
  1792. infoLength,
  1793. FileAlternateNameInformation
  1794. );
  1795. if (NT_SUCCESS(status)) {
  1796. if (fileNameInfo->FileNameLength <
  1797. (SMB_SHORT_NAME_LENGTH * sizeof(WCHAR))) {
  1798. ULONG fileNameLength = fileNameInfo->FileNameLength;
  1799. RtlZeroMemory( &extendedResponse2->ShortName[0],
  1800. sizeof(WCHAR) * SMB_SHORT_NAME_LENGTH );
  1801. RtlCopyMemory( &extendedResponse2->ShortName[0],
  1802. fileNameInfo->FileName,
  1803. fileNameLength
  1804. );
  1805. // null terminate the name
  1806. extendedResponse2->ShortName[fileNameLength/sizeof(WCHAR)] = L'\0';
  1807. } else {
  1808. IF_DEBUG(ERRORS) {
  1809. KdPrint(( "SrvSmbNtCreateAndX: QueryInfoFile for short name returned length of %X\n", fileNameInfo->FileNameLength ));
  1810. }
  1811. extendedResponse2->ShortName[0] = L'\0';
  1812. }
  1813. } else {
  1814. IF_DEBUG(ERRORS) {
  1815. KdPrint(( "SrvSmbNtCreateAndX: QueryInfoFile for short name failed: "
  1816. "%X\n", status ));
  1817. }
  1818. extendedResponse2->ShortName[0] = L'\0';
  1819. }
  1820. status = NtQueryInformationFile(
  1821. rfcb->Lfcb->FileHandle,
  1822. &ioStatus,
  1823. (PVOID)fileNameInfo,
  1824. infoLength,
  1825. FileNameInformation
  1826. );
  1827. if (NT_SUCCESS(status)) {
  1828. ULONG fileNameLength = 0;
  1829. //
  1830. // Use RtlMoveMemory as the source and destination will
  1831. // possibly overlap.
  1832. //
  1833. if (fileNameInfo->FileNameLength > 0) {
  1834. // only copy over the last component of the name.
  1835. PWCHAR lastBackSlash = &fileNameInfo->FileName[((fileNameInfo->FileNameLength)/sizeof(WCHAR))-1];
  1836. while (*lastBackSlash != UNICODE_DIR_SEPARATOR_CHAR &&
  1837. lastBackSlash > &fileNameInfo->FileName[0]) {
  1838. fileNameLength += sizeof(WCHAR);
  1839. lastBackSlash--;
  1840. }
  1841. lastBackSlash++;
  1842. RtlMoveMemory( &extendedResponse2->Buffer[0],
  1843. lastBackSlash,
  1844. fileNameLength
  1845. );
  1846. }
  1847. // null terminate the name
  1848. extendedResponse2->Buffer[fileNameLength/sizeof(WCHAR)] = L'\0';
  1849. SmbPutUshort( &extendedResponse2->ByteCount,
  1850. LOWORD(fileNameLength) + sizeof(WCHAR) );
  1851. byteCountSet = TRUE;
  1852. SmbPutUlong( &extendedResponse2->UsnValue.HighPart, ourUsnValue.HighPart );
  1853. SmbPutUlong( &extendedResponse2->UsnValue.LowPart, ourUsnValue.LowPart );
  1854. SmbPutUlong( &extendedResponse2->FileReferenceNumber.HighPart, ourFileRefNumber.HighPart );
  1855. SmbPutUlong( &extendedResponse2->FileReferenceNumber.LowPart, ourFileRefNumber.LowPart );
  1856. SmbPutUshort(
  1857. &response->AndXOffset,
  1858. GET_ANDX_OFFSET(
  1859. WorkContext->ResponseHeader,
  1860. WorkContext->ResponseParameters,
  1861. RESP_EXTENDED_NT_CREATE_ANDX2,
  1862. LOWORD(fileNameLength) + sizeof(WCHAR)
  1863. )
  1864. );
  1865. response->WordCount = SMB_RESP_EXTENDED_NT_CREATE_ANDX2_WORK_COUNT;
  1866. } else {
  1867. //
  1868. // if we couldn't get the name for some reason, let's not fail
  1869. // the whole open. Just leave the response as a
  1870. // RESP_EXTENDED_NT_CREATE_ANDX
  1871. //
  1872. IF_DEBUG(ERRORS) {
  1873. KdPrint(( "SrvSmbNtCreateAndX: QueryInfoFile for long name failed: "
  1874. "%X\n", status ));
  1875. }
  1876. status = STATUS_SUCCESS;
  1877. //
  1878. // reset the byte count in case the CrcValue was set
  1879. // and overwrote it.
  1880. //
  1881. SmbPutUshort( &pExtendedResponse->ByteCount, 0 );
  1882. byteCountSet = TRUE;
  1883. }
  1884. }
  1885. #endif
  1886. } else {
  1887. SmbPutUshort(
  1888. &response->AndXOffset,
  1889. GET_ANDX_OFFSET(
  1890. WorkContext->ResponseHeader,
  1891. WorkContext->ResponseParameters,
  1892. RESP_NT_CREATE_ANDX,
  1893. 0
  1894. )
  1895. );
  1896. response->WordCount = 34;
  1897. }
  1898. response->OplockLevel = oplockLevel;
  1899. SmbPutUshort( &response->Fid, rfcb->Fid );
  1900. SmbPutUlong( &response->CreateAction, CreateAction );
  1901. SmbPutUlong(
  1902. &response->CreationTime.HighPart,
  1903. srvNtFileInformation.NwOpenInfo.CreationTime.HighPart
  1904. );
  1905. SmbPutUlong(
  1906. &response->CreationTime.LowPart,
  1907. srvNtFileInformation.NwOpenInfo.CreationTime.LowPart
  1908. );
  1909. SmbPutUlong(
  1910. &response->LastAccessTime.HighPart,
  1911. srvNtFileInformation.NwOpenInfo.LastAccessTime.HighPart
  1912. );
  1913. SmbPutUlong(
  1914. &response->LastAccessTime.LowPart,
  1915. srvNtFileInformation.NwOpenInfo.LastAccessTime.LowPart
  1916. );
  1917. SmbPutUlong(
  1918. &response->LastWriteTime.HighPart,
  1919. srvNtFileInformation.NwOpenInfo.LastWriteTime.HighPart
  1920. );
  1921. SmbPutUlong(
  1922. &response->LastWriteTime.LowPart,
  1923. srvNtFileInformation.NwOpenInfo.LastWriteTime.LowPart
  1924. );
  1925. SmbPutUlong(
  1926. &response->ChangeTime.HighPart,
  1927. srvNtFileInformation.NwOpenInfo.ChangeTime.HighPart
  1928. );
  1929. SmbPutUlong(
  1930. &response->ChangeTime.LowPart,
  1931. srvNtFileInformation.NwOpenInfo.ChangeTime.LowPart
  1932. );
  1933. SmbPutUlong( &response->FileAttributes, srvNtFileInformation.NwOpenInfo.FileAttributes );
  1934. SmbPutUlong(
  1935. &response->AllocationSize.HighPart,
  1936. srvNtFileInformation.NwOpenInfo.AllocationSize.HighPart
  1937. );
  1938. SmbPutUlong(
  1939. &response->AllocationSize.LowPart,
  1940. srvNtFileInformation.NwOpenInfo.AllocationSize.LowPart
  1941. );
  1942. SmbPutUlong(
  1943. &response->EndOfFile.HighPart,
  1944. srvNtFileInformation.NwOpenInfo.EndOfFile.HighPart
  1945. );
  1946. SmbPutUlong(
  1947. &response->EndOfFile.LowPart,
  1948. srvNtFileInformation.NwOpenInfo.EndOfFile.LowPart
  1949. );
  1950. SmbPutUshort( &response->FileType, srvNtFileInformation.Type );
  1951. SmbPutUshort( &response->DeviceState, srvNtFileInformation.HandleState );
  1952. response->Directory = (srvNtFileInformation.NwOpenInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TRUE : FALSE;
  1953. #ifdef INCLUDE_SMB_IFMODIFIED
  1954. if (byteCountSet == FALSE) {
  1955. //
  1956. // if we haven't already put the bytecount into the extended response,
  1957. // do so now.
  1958. //
  1959. #endif
  1960. SmbPutUshort( &response->ByteCount, 0 );
  1961. #ifdef INCLUDE_SMB_IFMODIFIED
  1962. }
  1963. #endif
  1964. WorkContext->ResponseParameters = (PCHAR)WorkContext->ResponseHeader +
  1965. SmbGetUshort( &response->AndXOffset );
  1966. //
  1967. // Test for legal followon command.
  1968. //
  1969. switch ( nextCommand ) {
  1970. case SMB_COM_NO_ANDX_COMMAND:
  1971. break;
  1972. case SMB_COM_READ:
  1973. case SMB_COM_READ_ANDX:
  1974. case SMB_COM_IOCTL:
  1975. //
  1976. // Make sure the AndX command is still within the received SMB
  1977. //
  1978. if( (PCHAR)WorkContext->RequestHeader + reqAndXOffset <=
  1979. END_OF_REQUEST_SMB( WorkContext ) ) {
  1980. break;
  1981. }
  1982. /* Falls Through */
  1983. default: // Illegal followon command
  1984. IF_DEBUG(SMB_ERRORS) {
  1985. KdPrint(( "SrvSmbNtCreateAndX: Illegal followon command: 0x%lx\n",
  1986. nextCommand ));
  1987. }
  1988. //
  1989. // Return an error indicating that the followon command was bad.
  1990. // Note that the open is still considered successful, so the
  1991. // file remains open.
  1992. //
  1993. SrvSetSmbError( WorkContext, STATUS_INVALID_SMB );
  1994. return SmbStatusSendResponse;
  1995. }
  1996. #ifdef INCLUDE_SMB_PERSISTENT
  1997. if (persistentHandle && rfcb->Lfcb->TreeConnect->Share->AllowPersistentHandles) {
  1998. rfcb->PersistentHandle = TRUE;
  1999. } else {
  2000. persistentHandle = rfcb->PersistentHandle = FALSE;
  2001. }
  2002. #endif
  2003. //
  2004. // If there is an AndX command, set up to process it. Otherwise,
  2005. // indicate completion to the caller.
  2006. //
  2007. if ( nextCommand != SMB_COM_NO_ANDX_COMMAND ) {
  2008. WorkContext->NextCommand = nextCommand;
  2009. WorkContext->RequestParameters = (PCHAR)WorkContext->RequestHeader +
  2010. reqAndXOffset;
  2011. #ifdef INCLUDE_SMB_PERSISTENT
  2012. if (persistentHandle) {
  2013. rc = SrvPostPersistentOpen( WorkContext, SmbStatusMoreCommands );
  2014. } else {
  2015. rc = SmbStatusMoreCommands;
  2016. }
  2017. return rc;
  2018. #else
  2019. return SmbStatusMoreCommands;
  2020. #endif
  2021. }
  2022. #ifdef INCLUDE_SMB_PERSISTENT
  2023. if (persistentHandle) {
  2024. rc = SrvPostPersistentOpen( WorkContext, SmbStatusSendResponse );
  2025. } else {
  2026. rc = SmbStatusSendResponse;
  2027. }
  2028. #else
  2029. rc = SmbStatusSendResponse;
  2030. #endif
  2031. IF_DEBUG(TRACE2) KdPrint(( "SrvSmbNtCreateAndX complete.\n" ));
  2032. return rc;
  2033. } // GenerateNtCreateAndXResponse
  2034. SMB_TRANS_STATUS
  2035. SrvSmbCreateWithSdOrEa (
  2036. IN OUT PWORK_CONTEXT WorkContext
  2037. )
  2038. /*++
  2039. Routine Description:
  2040. Processes an Create with SD or EA SMB. This request arrives in an
  2041. Nt Transaction SMB.
  2042. Arguments:
  2043. WorkContext - Supplies the address of a Work Context Block
  2044. describing the current request. See smbtypes.h for a more
  2045. complete description of the valid fields.
  2046. Return Value:
  2047. BOOLEAN - Indicates whether an error occurred. See smbtypes.h for a
  2048. more complete description.
  2049. --*/
  2050. {
  2051. PREQ_CREATE_WITH_SD_OR_EA request;
  2052. PRESP_CREATE_WITH_SD_OR_EA response;
  2053. NTSTATUS status;
  2054. PTRANSACTION transaction;
  2055. ULONG eaErrorOffset = 0;
  2056. LARGE_INTEGER allocationSize;
  2057. PVOID securityDescriptorBuffer;
  2058. ULONG sdLength;
  2059. ULONG eaLength;
  2060. PVOID eaBuffer;
  2061. UNICODE_STRING fileName;
  2062. PUCHAR name;
  2063. USHORT nameLength;
  2064. BOOLEAN isUnicode;
  2065. SECURITY_QUALITY_OF_SERVICE qualityOfService;
  2066. PAGED_CODE( );
  2067. transaction = WorkContext->Parameters.Transaction;
  2068. request = (PREQ_CREATE_WITH_SD_OR_EA)transaction->InParameters;
  2069. response = (PRESP_CREATE_WITH_SD_OR_EA)transaction->OutParameters;
  2070. //
  2071. // Verify that enough parameter bytes were sent and that we're allowed
  2072. // to return enough parameter bytes.
  2073. //
  2074. if ( (transaction->ParameterCount < sizeof(REQ_CREATE_WITH_SD_OR_EA)) ||
  2075. (transaction->MaxParameterCount < sizeof(RESP_CREATE_WITH_SD_OR_EA)) ) {
  2076. //
  2077. // Not enough parameter bytes were sent.
  2078. //
  2079. IF_DEBUG(SMB_ERRORS)
  2080. KdPrint(( "SrvSmbCreateWithSdOrEa: bad parameter byte counts: %ld %ld\n",
  2081. transaction->ParameterCount,
  2082. transaction->MaxParameterCount ));
  2083. SrvLogInvalidSmb( WorkContext );
  2084. return GenerateCreateWithSdOrEaResponse(
  2085. WorkContext,
  2086. STATUS_INVALID_SMB
  2087. );
  2088. }
  2089. eaErrorOffset = 0;
  2090. allocationSize.HighPart = SmbGetUlong( &request->AllocationSize.HighPart );
  2091. allocationSize.LowPart = SmbGetUlong( &request->AllocationSize.LowPart );
  2092. //
  2093. // First verify that the file path name doesnot extend beyond the
  2094. // end of the SMB.
  2095. //
  2096. isUnicode = SMB_IS_UNICODE( WorkContext );
  2097. name = (PUCHAR)request->Buffer;
  2098. if ( isUnicode ) {
  2099. name = ALIGN_SMB_WSTR( name );
  2100. }
  2101. nameLength = (USHORT)SmbGetUshort( &request->NameLength );
  2102. if ( name + nameLength > ((PCHAR)request + transaction->ParameterCount) ) {
  2103. IF_DEBUG(SMB_ERRORS) {
  2104. KdPrint(( "SrvSmbCreateWithSdOrEa: failed at line %u\n", __LINE__ ));
  2105. }
  2106. SrvLogInvalidSmb( WorkContext );
  2107. return GenerateCreateWithSdOrEaResponse(
  2108. WorkContext,
  2109. STATUS_INVALID_SMB
  2110. );
  2111. }
  2112. //
  2113. // Convert the file name to a Unicode string.
  2114. //
  2115. status = SrvMakeUnicodeString(
  2116. isUnicode,
  2117. &fileName,
  2118. name,
  2119. &nameLength
  2120. );
  2121. if ( !NT_SUCCESS( status ) ) {
  2122. return GenerateCreateWithSdOrEaResponse( WorkContext, status );
  2123. }
  2124. sdLength = SmbGetUlong( &request->SecurityDescriptorLength );
  2125. eaLength = SmbGetUlong( &request->EaLength );
  2126. securityDescriptorBuffer = transaction->InData;
  2127. eaBuffer = (PCHAR)securityDescriptorBuffer + ((sdLength + 3) & ~ 3);
  2128. if( eaLength > transaction->DataCount ||
  2129. sdLength > transaction->DataCount ||
  2130. (PCHAR)securityDescriptorBuffer + eaLength + sdLength >
  2131. (PCHAR)transaction->InData + transaction->DataCount ||
  2132. ((sdLength != 0) && !RtlValidSecurityDescriptor(securityDescriptorBuffer))) {
  2133. IF_DEBUG( SMB_ERRORS ) {
  2134. KdPrint(( "SrvSmbCreateWithSdOrEa: failed at line %u\n", __LINE__ ));
  2135. KdPrint(( " eaLength %u, sdLength %u, DataCount %u\n",
  2136. eaLength, sdLength, transaction->DataCount ));
  2137. }
  2138. SrvLogInvalidSmb( WorkContext );
  2139. if ( !isUnicode ) {
  2140. RtlFreeUnicodeString( &fileName );
  2141. }
  2142. return GenerateCreateWithSdOrEaResponse(
  2143. WorkContext,
  2144. STATUS_INVALID_SECURITY_DESCR
  2145. );
  2146. }
  2147. //
  2148. // *** We always ask for STATIC tracking, not DYNAMIC, because we
  2149. // don't support dynamic tracking over the net yet.
  2150. //
  2151. // !!! Note that once we support dynamic tracking, we MUST CHANGE
  2152. // THE NAMED PIPE PROCESSING to not do writes/transceives at DPC
  2153. // level, because the NPFS needs to call SeCreateClientSecurity
  2154. // on every write when dynamic tracking is selected!
  2155. //
  2156. qualityOfService.Length = sizeof( qualityOfService );
  2157. qualityOfService.ImpersonationLevel =
  2158. SmbGetUlong( &request->ImpersonationLevel );
  2159. qualityOfService.ContextTrackingMode = FALSE;
  2160. //qualityOfService.ContextTrackingMode = (BOOLEAN)
  2161. // (request->SecurityFlags & SMB_SECURITY_DYNAMIC_TRACKING);
  2162. qualityOfService.EffectiveOnly = (BOOLEAN)
  2163. (request->SecurityFlags & SMB_SECURITY_EFFECTIVE_ONLY);
  2164. status = SrvNtCreateFile(
  2165. WorkContext,
  2166. SmbGetUlong( &request->RootDirectoryFid ),
  2167. SmbGetUlong( &request->DesiredAccess ),
  2168. allocationSize,
  2169. SmbGetUlong( &request->FileAttributes ),
  2170. SmbGetUlong( &request->ShareAccess ),
  2171. SmbGetUlong( &request->CreateDisposition ),
  2172. SmbGetUlong( &request->CreateOptions ),
  2173. (sdLength == 0) ? NULL : securityDescriptorBuffer,
  2174. &fileName,
  2175. (eaLength == 0) ? NULL : eaBuffer,
  2176. eaLength,
  2177. &eaErrorOffset,
  2178. SmbGetUlong( &request->Flags ),
  2179. &qualityOfService,
  2180. (request->Flags & NT_CREATE_REQUEST_OPBATCH) != 0 ?
  2181. OplockTypeBatch :
  2182. (request->Flags & NT_CREATE_REQUEST_OPLOCK) != 0 ?
  2183. OplockTypeExclusive : OplockTypeServerBatch,
  2184. RestartCreateWithSdOrEa
  2185. );
  2186. //
  2187. // Free the unicode file name buffer if it has been allocated.
  2188. //
  2189. if ( !isUnicode ) {
  2190. RtlFreeUnicodeString( &fileName );
  2191. }
  2192. if ( status == STATUS_OPLOCK_BREAK_IN_PROGRESS ) {
  2193. //
  2194. // The open is blocked (waiting for a comm device or an oplock
  2195. // break), do not send a reply.
  2196. //
  2197. //
  2198. // Save the ea error offset
  2199. //
  2200. WorkContext->Parameters2.Open.EaErrorOffset = eaErrorOffset;
  2201. return SmbTransStatusInProgress;
  2202. } else if ( WorkContext->Parameters2.Open.TemporaryOpen ) {
  2203. //
  2204. // The initial open failed due to a sharing violation, possibly
  2205. // caused by an batch oplock. Requeue the open to a blocking
  2206. // thread.
  2207. //
  2208. WorkContext->FspRestartRoutine = (PRESTART_ROUTINE)ExecuteTransaction;
  2209. SrvQueueWorkToBlockingThread( WorkContext );
  2210. return SmbStatusInProgress;
  2211. } else {
  2212. //
  2213. // Save the ea error offset
  2214. //
  2215. WorkContext->Parameters2.Open.EaErrorOffset = eaErrorOffset;
  2216. //
  2217. // The open has completed. Generate and send the reply.
  2218. //
  2219. return GenerateCreateWithSdOrEaResponse( WorkContext, status );
  2220. }
  2221. } // SrvSmbCreateWithSdOrEa
  2222. VOID SRVFASTCALL
  2223. RestartCreateWithSdOrEa (
  2224. PWORK_CONTEXT WorkContext
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. Completes processing of an Open2 SMB.
  2229. Arguments:
  2230. WorkContext - Work context block for the operation.
  2231. Return Value:
  2232. None.
  2233. --*/
  2234. {
  2235. SMB_TRANS_STATUS smbStatus;
  2236. NTSTATUS openStatus;
  2237. PAGED_CODE( );
  2238. openStatus = SrvCheckOplockWaitState( WorkContext->WaitForOplockBreak );
  2239. if ( NT_SUCCESS( openStatus ) ) {
  2240. openStatus = WorkContext->Irp->IoStatus.Status;
  2241. if( NT_SUCCESS( openStatus ) ) {
  2242. //
  2243. // It's obvious that the file already existed, because we've
  2244. // been working on an oplock break. So set the
  2245. // IoStatus.Information field correctly.
  2246. //
  2247. WorkContext->Irp->IoStatus.Information = FILE_OPENED;
  2248. }
  2249. } else {
  2250. //
  2251. // This open was waiting for an oplock break to occur, but
  2252. // timed out. Close our handle to this file, then fail the open.
  2253. //
  2254. SrvCloseRfcb( WorkContext->Parameters2.Open.Rfcb );
  2255. }
  2256. WorkContext->Irp->IoStatus.Information = WorkContext->Parameters2.Open.IosbInformation;
  2257. smbStatus = GenerateCreateWithSdOrEaResponse( WorkContext, openStatus );
  2258. SrvCompleteExecuteTransaction( WorkContext, smbStatus );
  2259. return;
  2260. } // RestartCreateWithSdOrEa
  2261. SMB_TRANS_STATUS
  2262. GenerateCreateWithSdOrEaResponse (
  2263. PWORK_CONTEXT WorkContext,
  2264. NTSTATUS OpenStatus
  2265. )
  2266. /*++
  2267. Routine Description:
  2268. Generates a response to an Create With SD or EA SMB and setup for furthur
  2269. SMB processing.
  2270. Arguments:
  2271. WorkContext - Work context block for the operation.
  2272. OpenStatus - The status of the open operation.
  2273. Return Value:
  2274. None.
  2275. --*/
  2276. {
  2277. PREQ_CREATE_WITH_SD_OR_EA request;
  2278. PRESP_CREATE_WITH_SD_OR_EA response;
  2279. PRFCB rfcb;
  2280. NTSTATUS status;
  2281. SRV_NT_FILE_INFORMATION srvNtFileInformation;
  2282. PTRANSACTION transaction;
  2283. OPLOCK_TYPE oplockType;
  2284. UCHAR oplockLevel;
  2285. BOOLEAN allowLevelII;
  2286. BOOLEAN SendExtendedResponse = FALSE;
  2287. ACCESS_MASK MaximalAccessRights;
  2288. ACCESS_MASK GuestMaximalAccessRights;
  2289. ULONG eaErrorOffset;
  2290. BOOLEAN extendedRequested;
  2291. ULONG CreateAction = (ULONG)WorkContext->Irp->IoStatus.Information;
  2292. PAGED_CODE( );
  2293. transaction = WorkContext->Parameters.Transaction;
  2294. request = (PREQ_CREATE_WITH_SD_OR_EA)transaction->InParameters;
  2295. response = (PRESP_CREATE_WITH_SD_OR_EA)transaction->OutParameters;
  2296. extendedRequested = ((request->Flags & NT_CREATE_REQUEST_EXTENDED_RESPONSE) != 0 );
  2297. rfcb = WorkContext->Rfcb;
  2298. eaErrorOffset = WorkContext->Parameters2.Open.EaErrorOffset;
  2299. //
  2300. // If the open failed, send an error response.
  2301. //
  2302. if ( !NT_SUCCESS( OpenStatus ) ) {
  2303. SrvSetSmbError2( WorkContext, OpenStatus, TRUE );
  2304. //
  2305. // Remap the error if it is ERROR_ALREADY_EXISTS
  2306. //
  2307. if ( !CLIENT_CAPABLE_OF(NT_STATUS,WorkContext->Connection) &&
  2308. SmbGetUshort( &WorkContext->ResponseHeader->Error ) ==
  2309. ERROR_ALREADY_EXISTS ) {
  2310. SmbPutUshort(
  2311. &WorkContext->ResponseHeader->Error,
  2312. ERROR_FILE_EXISTS
  2313. );
  2314. }
  2315. goto err_exit;
  2316. }
  2317. //
  2318. // We always open with at least FILE_READ_ATTRIBUTES, so no
  2319. // access check is needed.
  2320. //
  2321. status = SrvQueryNtInformationFile(
  2322. rfcb->Lfcb->FileHandle,
  2323. rfcb->Lfcb->FileObject,
  2324. rfcb->ShareType,
  2325. extendedRequested,
  2326. &srvNtFileInformation
  2327. );
  2328. if ( !NT_SUCCESS(status) ) {
  2329. IF_DEBUG(ERRORS) {
  2330. KdPrint(( "GenerateCreateWithSdOrEaResponse: "
  2331. "SrvQueryNtInformationFile failed: %X\n", status ));
  2332. }
  2333. SrvCloseRfcb( rfcb );
  2334. SrvSetSmbError2( WorkContext, status, TRUE );
  2335. goto err_exit;
  2336. }
  2337. //
  2338. // Attempt to acquire the oplock.
  2339. //
  2340. if ( !(request->CreateOptions & FILE_DIRECTORY_FILE) ) {
  2341. if ( request->Flags & NT_CREATE_REQUEST_OPLOCK ) {
  2342. allowLevelII = CLIENT_CAPABLE_OF( LEVEL_II_OPLOCKS, WorkContext->Connection );
  2343. if ( request->Flags & NT_CREATE_REQUEST_OPBATCH ) {
  2344. oplockType = OplockTypeBatch;
  2345. oplockLevel = SMB_OPLOCK_LEVEL_BATCH;
  2346. } else {
  2347. oplockType = OplockTypeExclusive;
  2348. oplockLevel = SMB_OPLOCK_LEVEL_EXCLUSIVE;
  2349. }
  2350. } else {
  2351. allowLevelII = FALSE;
  2352. oplockType = OplockTypeServerBatch;
  2353. oplockLevel = SMB_OPLOCK_LEVEL_NONE;
  2354. }
  2355. if ( SrvRequestOplock( WorkContext, &oplockType, allowLevelII ) ) {
  2356. //
  2357. // The oplock was granted. Check to see if it was a level 2.
  2358. //
  2359. if ( oplockType == OplockTypeShareRead ) {
  2360. oplockLevel = SMB_OPLOCK_LEVEL_II;
  2361. }
  2362. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksGranted );
  2363. } else {
  2364. //
  2365. // The oplock request was denied.
  2366. //
  2367. oplockLevel = SMB_OPLOCK_LEVEL_NONE;
  2368. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOplocksDenied );
  2369. }
  2370. } else {
  2371. oplockLevel = SMB_OPLOCK_LEVEL_NONE;
  2372. }
  2373. if ( extendedRequested ) {
  2374. NTSTATUS ExtendedResponseStatus;
  2375. PRESP_EXTENDED_CREATE_WITH_SD_OR_EA ExtendedResponse;
  2376. ExtendedResponse = (PRESP_EXTENDED_CREATE_WITH_SD_OR_EA)response;
  2377. ExtendedResponseStatus = SrvUpdateMaximalAccessRightsInResponse(
  2378. WorkContext,
  2379. &ExtendedResponse->MaximalAccessRights,
  2380. &ExtendedResponse->GuestMaximalAccessRights);
  2381. SendExtendedResponse = (ExtendedResponseStatus == STATUS_SUCCESS);
  2382. }
  2383. //
  2384. // Set up response SMB.
  2385. //
  2386. response->OplockLevel = oplockLevel;
  2387. if (SendExtendedResponse) {
  2388. response->ExtendedResponse = 1;
  2389. } else {
  2390. response->ExtendedResponse = 0;
  2391. }
  2392. SmbPutUshort( &response->Fid, rfcb->Fid );
  2393. SmbPutUlong( &response->EaErrorOffset, eaErrorOffset );
  2394. SmbPutUlong( &response->CreateAction, CreateAction );
  2395. SmbPutUshort( &response->FileType, srvNtFileInformation.Type );
  2396. SmbPutUshort( &response->DeviceState, srvNtFileInformation.HandleState );
  2397. SmbPutUlong(
  2398. &response->CreationTime.HighPart,
  2399. srvNtFileInformation.NwOpenInfo.CreationTime.HighPart
  2400. );
  2401. SmbPutUlong(
  2402. &response->CreationTime.LowPart,
  2403. srvNtFileInformation.NwOpenInfo.CreationTime.LowPart
  2404. );
  2405. SmbPutUlong(
  2406. &response->LastAccessTime.HighPart,
  2407. srvNtFileInformation.NwOpenInfo.LastAccessTime.HighPart
  2408. );
  2409. SmbPutUlong(
  2410. &response->LastAccessTime.LowPart,
  2411. srvNtFileInformation.NwOpenInfo.LastAccessTime.LowPart
  2412. );
  2413. SmbPutUlong(
  2414. &response->LastWriteTime.HighPart,
  2415. srvNtFileInformation.NwOpenInfo.LastWriteTime.HighPart
  2416. );
  2417. SmbPutUlong(
  2418. &response->LastWriteTime.LowPart,
  2419. srvNtFileInformation.NwOpenInfo.LastWriteTime.LowPart
  2420. );
  2421. SmbPutUlong(
  2422. &response->ChangeTime.HighPart,
  2423. srvNtFileInformation.NwOpenInfo.ChangeTime.HighPart
  2424. );
  2425. SmbPutUlong(
  2426. &response->ChangeTime.LowPart,
  2427. srvNtFileInformation.NwOpenInfo.ChangeTime.LowPart
  2428. );
  2429. SmbPutUlong( &response->FileAttributes, srvNtFileInformation.NwOpenInfo.FileAttributes );
  2430. SmbPutUlong(
  2431. &response->AllocationSize.HighPart,
  2432. srvNtFileInformation.NwOpenInfo.AllocationSize.HighPart
  2433. );
  2434. SmbPutUlong(
  2435. &response->AllocationSize.LowPart,
  2436. srvNtFileInformation.NwOpenInfo.AllocationSize.LowPart
  2437. );
  2438. SmbPutUlong(
  2439. &response->EndOfFile.HighPart,
  2440. srvNtFileInformation.NwOpenInfo.EndOfFile.HighPart
  2441. );
  2442. SmbPutUlong(
  2443. &response->EndOfFile.LowPart,
  2444. srvNtFileInformation.NwOpenInfo.EndOfFile.LowPart
  2445. );
  2446. response->Directory = (srvNtFileInformation.NwOpenInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? TRUE : FALSE;
  2447. if (SendExtendedResponse) {
  2448. transaction->ParameterCount = sizeof(RESP_EXTENDED_CREATE_WITH_SD_OR_EA);
  2449. } else {
  2450. transaction->ParameterCount = sizeof(RESP_CREATE_WITH_SD_OR_EA);
  2451. }
  2452. transaction->SetupCount = 0;
  2453. transaction->DataCount = 0;
  2454. IF_DEBUG(TRACE2) KdPrint(( "SrvSmbOpen2 complete.\n" ));
  2455. return SmbTransStatusSuccess;
  2456. err_exit:
  2457. RtlZeroMemory( (PVOID)response, sizeof(RESP_CREATE_WITH_SD_OR_EA) );
  2458. SmbPutUlong( &response->EaErrorOffset, eaErrorOffset );
  2459. transaction->SetupCount = 0;
  2460. transaction->ParameterCount = sizeof(RESP_CREATE_WITH_SD_OR_EA);
  2461. transaction->DataCount = 0;
  2462. return SmbTransStatusErrorWithData;
  2463. } // GenerateCreateWithSdOrEaResponse
  2464. SMB_PROCESSOR_RETURN_TYPE
  2465. SrvSmbCreate (
  2466. SMB_PROCESSOR_PARAMETERS
  2467. )
  2468. /*++
  2469. Routine Description:
  2470. Processes the Create and Create New SMBs.
  2471. Arguments:
  2472. SMB_PROCESSOR_PARAMETERS - See smbprocs.h for a description
  2473. of the parameters to SMB processor routines.
  2474. Return Value:
  2475. SMB_PROCESSOR_RETURN_TYPE - See smbprocs.h
  2476. --*/
  2477. {
  2478. PREQ_CREATE request;
  2479. UCHAR command;
  2480. NTSTATUS status = STATUS_SUCCESS;
  2481. SMB_STATUS SmbStatus = SmbStatusInProgress;
  2482. PAGED_CODE( );
  2483. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  2484. WorkContext->PreviousSMB = EVENT_TYPE_SMB_CREATE;
  2485. SrvWmiStartContext(WorkContext);
  2486. IF_SMB_DEBUG(OPEN_CLOSE1) {
  2487. KdPrint(( "Create file request header at 0x%p, response header at 0x%p\n",
  2488. WorkContext->RequestHeader,
  2489. WorkContext->ResponseHeader ));
  2490. KdPrint(( "Create file request parameters at 0x%p, response parameters at 0x%p\n",
  2491. WorkContext->RequestParameters,
  2492. WorkContext->ResponseParameters ));
  2493. }
  2494. request = (PREQ_CREATE)WorkContext->RequestParameters;
  2495. command = WorkContext->RequestHeader->Command;
  2496. //
  2497. // Open the file in compatibility mode, obtaining read/write access
  2498. // for this FID.
  2499. //
  2500. status = SrvCreateFile(
  2501. WorkContext,
  2502. SMB_DA_SHARE_COMPATIBILITY | SMB_DA_ACCESS_READ_WRITE,
  2503. SmbGetUshort( &request->FileAttributes ),
  2504. (USHORT) ( ( command == SMB_COM_CREATE ?
  2505. SMB_OFUN_OPEN_TRUNCATE : SMB_OFUN_OPEN_FAIL )
  2506. | SMB_OFUN_CREATE_CREATE ),
  2507. 0, // SmbAllocationSize
  2508. (PCHAR)(request->Buffer + 1),
  2509. END_OF_REQUEST_SMB( WorkContext ),
  2510. NULL,
  2511. 0L,
  2512. NULL,
  2513. (WorkContext->RequestHeader->Flags & SMB_FLAGS_OPLOCK_NOTIFY_ANY) != 0 ?
  2514. OplockTypeBatch :
  2515. (WorkContext->RequestHeader->Flags & SMB_FLAGS_OPLOCK) != 0 ?
  2516. OplockTypeExclusive : OplockTypeServerBatch,
  2517. RestartSmbCreate
  2518. );
  2519. if( status == STATUS_OPLOCK_BREAK_IN_PROGRESS ) {
  2520. //
  2521. // The open is blocked, perhaps because some other client had this
  2522. // file open and is holding onto the handle with a batch oplock.
  2523. //
  2524. SmbStatus = SmbStatusInProgress;
  2525. } else {
  2526. SmbStatus = GenerateCreateResponse( WorkContext, status );
  2527. }
  2528. SrvWmiEndContext(WorkContext);
  2529. return SmbStatus;
  2530. }
  2531. VOID SRVFASTCALL
  2532. RestartSmbCreate(
  2533. IN PWORK_CONTEXT WorkContext
  2534. )
  2535. /*++
  2536. Routine Description:
  2537. Completes processing of a Create SMB.
  2538. Arguments:
  2539. WorkContext - A pointer to the work context block for this SMB.
  2540. Return Value:
  2541. None.
  2542. --*/
  2543. {
  2544. SMB_PROCESSOR_RETURN_LOCAL smbStatus = SmbStatusInProgress;
  2545. NTSTATUS createStatus = STATUS_SUCCESS;
  2546. PAGED_CODE();
  2547. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  2548. WorkContext->PreviousSMB = EVENT_TYPE_SMB_CREATE;
  2549. SrvWmiStartContext(WorkContext);
  2550. createStatus = SrvCheckOplockWaitState( WorkContext->WaitForOplockBreak );
  2551. if( NT_SUCCESS( createStatus ) ) {
  2552. createStatus = WorkContext->Irp->IoStatus.Status;
  2553. } else {
  2554. //
  2555. // The create was waiting for an oplock break to occur, but
  2556. // timed out. Close our handle to this file, then fail the create.
  2557. //
  2558. SrvCloseRfcb( WorkContext->Parameters2.Open.Rfcb );
  2559. }
  2560. WorkContext->Irp->IoStatus.Information = WorkContext->Parameters2.Open.IosbInformation;
  2561. smbStatus = GenerateCreateResponse( WorkContext, createStatus );
  2562. SrvEndSmbProcessing( WorkContext, smbStatus );
  2563. SrvWmiEndContext(WorkContext);
  2564. }
  2565. SMB_PROCESSOR_RETURN_TYPE
  2566. GenerateCreateResponse(
  2567. PWORK_CONTEXT WorkContext,
  2568. NTSTATUS CreateStatus
  2569. )
  2570. /*++
  2571. Routine Description:
  2572. Generates a response to a Create SMB
  2573. Arguments:
  2574. WorkContext -
  2575. Status - The status of the create operation
  2576. Return Value:
  2577. The status of the SMB processing.
  2578. --*/
  2579. {
  2580. PREQ_CREATE request;
  2581. PRESP_CREATE response;
  2582. PRFCB rfcb;
  2583. PAGED_CODE();
  2584. request = (PREQ_CREATE)WorkContext->RequestParameters;
  2585. response = (PRESP_CREATE)WorkContext->ResponseParameters;
  2586. //
  2587. // If the open failed, send an error response.
  2588. //
  2589. if ( !NT_SUCCESS(CreateStatus) ) {
  2590. SrvSetSmbError( WorkContext, CreateStatus );
  2591. //
  2592. // Remap the error if it is ERROR_ALREADY_EXISTS. In OS/2
  2593. // ERROR_ALREADY_EXISTS is used for resources like Semaphores.
  2594. // This cannot be passed back to the downlevel client and has
  2595. // to be remapped to ERROR_FILE_EXISTS
  2596. //
  2597. if ( !CLIENT_CAPABLE_OF(NT_STATUS,WorkContext->Connection) &&
  2598. SmbGetUshort( &WorkContext->ResponseHeader->Error ) ==
  2599. ERROR_ALREADY_EXISTS ) {
  2600. SmbPutUshort(
  2601. &WorkContext->ResponseHeader->Error,
  2602. ERROR_FILE_EXISTS
  2603. );
  2604. }
  2605. return SmbStatusSendResponse;
  2606. }
  2607. //
  2608. // Set the time on the file.
  2609. //
  2610. // !!! Should we do anything with the return code?
  2611. rfcb = WorkContext->Rfcb;
  2612. #ifdef INCLUDE_SMB_IFMODIFIED
  2613. (VOID)SrvSetLastWriteTime(
  2614. rfcb,
  2615. SmbGetUlong( &request->CreationTimeInSeconds ),
  2616. rfcb->Lfcb->GrantedAccess,
  2617. FALSE
  2618. );
  2619. #else
  2620. (VOID)SrvSetLastWriteTime(
  2621. rfcb,
  2622. SmbGetUlong( &request->CreationTimeInSeconds ),
  2623. rfcb->Lfcb->GrantedAccess
  2624. );
  2625. #endif
  2626. //
  2627. // Give the smart card a chance to get into the act
  2628. //
  2629. if( WorkContext->Endpoint->IsConnectionless && SrvIpxSmartCard.Open != NULL ) {
  2630. PVOID handle;
  2631. IF_DEBUG( SIPX ) {
  2632. KdPrint(( "Trying the smart card for %wZ\n", &rfcb->Mfcb->FileName ));
  2633. }
  2634. if( SrvIpxSmartCard.Open(
  2635. WorkContext->RequestBuffer->Buffer,
  2636. rfcb->Lfcb->FileObject,
  2637. &rfcb->Mfcb->FileName,
  2638. &(WorkContext->ClientAddress->IpxAddress.Address[0].Address[0]),
  2639. rfcb->Lfcb->FileObject->Flags & FO_CACHE_SUPPORTED,
  2640. &handle
  2641. ) == TRUE ) {
  2642. IF_DEBUG( SIPX ) {
  2643. KdPrint(( "%wZ handled by Smart Card. Handle %p\n",
  2644. &rfcb->Mfcb->FileName, handle ));
  2645. }
  2646. rfcb->PagedRfcb->IpxSmartCardContext = handle;
  2647. }
  2648. }
  2649. //
  2650. // Set up response SMB.
  2651. //
  2652. response->WordCount = 1;
  2653. SmbPutUshort( &response->Fid, rfcb->Fid );
  2654. SmbPutUshort( &response->ByteCount, 0 );
  2655. WorkContext->ResponseParameters = NEXT_LOCATION(
  2656. response,
  2657. RESP_CREATE,
  2658. 0
  2659. );
  2660. IF_DEBUG(TRACE2) KdPrint(( "SrvSmbCreate complete.\n" ));
  2661. return SmbStatusSendResponse;
  2662. } // SrvSmbCreate
  2663. SMB_PROCESSOR_RETURN_TYPE
  2664. SrvSmbCreateTemporary (
  2665. SMB_PROCESSOR_PARAMETERS
  2666. )
  2667. /*++
  2668. Routine Description:
  2669. Processes a Create Temporary SMB.
  2670. Arguments:
  2671. SMB_PROCESSOR_PARAMETERS - See smbprocs.h for a description
  2672. of the parameters to SMB processor routines.
  2673. Return Value:
  2674. SMB_PROCESSOR_RETURN_TYPE - See smbprocs.h
  2675. --*/
  2676. {
  2677. PREQ_CREATE_TEMPORARY request;
  2678. PRESP_CREATE_TEMPORARY response;
  2679. PRFCB rfcb;
  2680. NTSTATUS status = STATUS_OBJECT_NAME_COLLISION;
  2681. SMB_STATUS SmbStatus = SmbStatusInProgress;
  2682. CLONG nameCounter;
  2683. USHORT i;
  2684. PSZ nameStart, ep;
  2685. CHAR name[9];
  2686. PAGED_CODE( );
  2687. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  2688. WorkContext->PreviousSMB = EVENT_TYPE_SMB_CREATE_TEMPORARY;
  2689. SrvWmiStartContext(WorkContext);
  2690. IF_SMB_DEBUG(OPEN_CLOSE1) {
  2691. KdPrint(( "Create temporary file request header at 0x%p, response header at 0x%p\n",
  2692. WorkContext->RequestHeader,
  2693. WorkContext->ResponseHeader ));
  2694. KdPrint(( "Create temporary file request parameters at 0x%p, response parameters at 0x%p\n",
  2695. WorkContext->RequestParameters,
  2696. WorkContext->ResponseParameters ));
  2697. }
  2698. request = (PREQ_CREATE_TEMPORARY)WorkContext->RequestParameters;
  2699. response = (PRESP_CREATE_TEMPORARY)WorkContext->ResponseParameters;
  2700. //
  2701. // Find out where in the buffer the directory pathname ends. We will
  2702. // write the filename after this.
  2703. //
  2704. ep = END_OF_REQUEST_SMB( WorkContext );
  2705. for( nameStart = (PSZ)request->Buffer; nameStart <= ep && *nameStart; nameStart++ ) {
  2706. ;
  2707. }
  2708. //
  2709. // If we didn't find a NULL, or we don't have room to add in the last part of the
  2710. // temporary filename, then we give up
  2711. //
  2712. if( *nameStart ||
  2713. WorkContext->RequestBuffer->BufferLength - WorkContext->RequestBuffer->DataLength < 9 ) {
  2714. //
  2715. // We did not find a valid pathname!
  2716. //
  2717. SrvSetSmbError( WorkContext, STATUS_INVALID_SMB );
  2718. status = STATUS_INVALID_SMB;
  2719. SmbStatus = SmbStatusSendResponse;
  2720. goto Cleanup;
  2721. }
  2722. //
  2723. // The temporary file will be created with a name like SRVxxxxx, where
  2724. // xxxxx is a hex integer. We first try to create SRV00000, and if it
  2725. // exists increment xxxxx until xxxxx = 0xFFFFF;
  2726. //
  2727. // !!! We may want to maintain a "last name" counter, to try to
  2728. // reduce the number of retries we need. We may also want to
  2729. // have an explicit bound the number of tries, like 16 or 32, or
  2730. // 293.
  2731. //
  2732. name[0] = 'S';
  2733. name[1] = 'R';
  2734. name[2] = 'V';
  2735. name[8] = '\0';
  2736. // *** for SrvCanonicalizePathName
  2737. WorkContext->RequestBuffer->DataLength += 9;
  2738. for ( nameCounter = 0;
  2739. status == STATUS_OBJECT_NAME_COLLISION &&
  2740. nameCounter < (CLONG)0xFFFFF;
  2741. nameCounter++ ) {
  2742. CCHAR j;
  2743. PSZ s;
  2744. name[3] = SrvHexChars[ (nameCounter & (CLONG)0xF0000) >> 16 ];
  2745. name[4] = SrvHexChars[ (nameCounter & (CLONG)0xF000) >> 12 ];
  2746. name[5] = SrvHexChars[ (nameCounter & (CLONG)0xF00) >> 8 ];
  2747. name[6] = SrvHexChars[ (nameCounter & (CLONG)0xF0) >> 4 ];
  2748. name[7] = SrvHexChars[ (nameCounter & (CLONG)0xF) ];
  2749. // *** We could get rid of this loop and the name[9] variable
  2750. // if we could put the name directly into the SMB buffer.
  2751. for ( j = 0, s = nameStart; j < 9; j++, s++ ) {
  2752. *s = name[j];
  2753. }
  2754. //
  2755. // Open the file in compatibility mode, obtaining read/write
  2756. // access for this FID.
  2757. //
  2758. status = SrvCreateFile(
  2759. WorkContext,
  2760. SMB_DA_SHARE_COMPATIBILITY | SMB_DA_ACCESS_READ_WRITE,
  2761. 0, // SmbFileAttributes (normal)
  2762. SMB_OFUN_OPEN_FAIL | SMB_OFUN_CREATE_CREATE,
  2763. 0, // SmbAllocationSize
  2764. (PCHAR)(request->Buffer + 1),
  2765. END_OF_REQUEST_SMB( WorkContext ),
  2766. NULL,
  2767. 0L,
  2768. NULL,
  2769. (WorkContext->RequestHeader->Flags & SMB_FLAGS_OPLOCK_NOTIFY_ANY) != 0 ?
  2770. OplockTypeBatch :
  2771. (WorkContext->RequestHeader->Flags & SMB_FLAGS_OPLOCK) != 0 ?
  2772. OplockTypeExclusive : OplockTypeServerBatch,
  2773. NULL
  2774. );
  2775. ASSERT ( status != STATUS_OPLOCK_BREAK_IN_PROGRESS );
  2776. //
  2777. // If the open failed, send an error response.
  2778. //
  2779. if ( !NT_SUCCESS(status) && status != STATUS_OBJECT_NAME_COLLISION ) {
  2780. SrvSetSmbError( WorkContext, status );
  2781. SmbStatus = SmbStatusSendResponse;
  2782. goto Cleanup;
  2783. }
  2784. }
  2785. if ( nameCounter == (CLONG)0xFFFFF ) {
  2786. //
  2787. // This will probably never happen, and if it did, it would take
  2788. // a *long* time to attempt to open FFFFF == 1,048,575 files.
  2789. //
  2790. SmbStatus = SmbStatusSendResponse;
  2791. goto Cleanup;
  2792. }
  2793. //
  2794. // Set up response SMB.
  2795. //
  2796. rfcb = WorkContext->Rfcb;
  2797. rfcb->IsCacheable = FALSE;
  2798. response->WordCount = 1;
  2799. SmbPutUshort( &response->Fid, rfcb->Fid );
  2800. for ( i = 0; i < 9; i++ ) {
  2801. request->Buffer[i] = nameStart[i];
  2802. }
  2803. SmbPutUshort( &response->ByteCount, 9 );
  2804. WorkContext->ResponseParameters = NEXT_LOCATION(
  2805. response,
  2806. RESP_CREATE_TEMPORARY,
  2807. 9
  2808. );
  2809. SmbStatus = SmbStatusSendResponse;
  2810. IF_DEBUG(TRACE2) KdPrint(( "SrvSmbCreateTemporary complete.\n" ));
  2811. Cleanup:
  2812. SrvWmiEndContext(WorkContext);
  2813. return SmbStatus;
  2814. } // SrvSmbCreateTemporary
  2815. VOID
  2816. SetEofToMatchAllocation (
  2817. IN HANDLE FileHandle,
  2818. IN ULONG AllocationSize
  2819. )
  2820. /*++
  2821. Routine Description:
  2822. Sets the EOF location for a file to match the size allocated when
  2823. the file was created. This routine is necessary in order to gain
  2824. compatibility with OS/2, which does not have separate concepts of
  2825. EOF and allocation size. When the server creates a file for an OS/2
  2826. client, if the allocation size is greater than 0, the server sets
  2827. the EOF to match that size.
  2828. This routine was created to allow the server to pass variations 17
  2829. and 18 of the filio003 test.
  2830. Arguments:
  2831. SMB_PROCESSOR_PARAMETERS - See smbtypes.h for a description
  2832. of the parameters to SMB processor routines.
  2833. Return Value:
  2834. SMB_PROCESSOR_RETURN_TYPE - See smbtypes.h
  2835. --*/
  2836. {
  2837. NTSTATUS status;
  2838. IO_STATUS_BLOCK iosb;
  2839. FILE_END_OF_FILE_INFORMATION newEndOfFile;
  2840. PAGED_CODE( );
  2841. //
  2842. // Don't bother doing this if the allocated size is zero.
  2843. //
  2844. if ( AllocationSize != 0 ) {
  2845. newEndOfFile.EndOfFile.QuadPart = AllocationSize;
  2846. status = NtSetInformationFile(
  2847. FileHandle,
  2848. &iosb,
  2849. &newEndOfFile,
  2850. sizeof( newEndOfFile ),
  2851. FileEndOfFileInformation
  2852. );
  2853. if ( !NT_SUCCESS(status) ) {
  2854. INTERNAL_ERROR(
  2855. ERROR_LEVEL_EXPECTED,
  2856. "SetEofToMatchAllocation: SetInformationFile returned %X",
  2857. status,
  2858. NULL
  2859. );
  2860. SrvLogServiceFailure( SRV_SVC_NT_SET_INFO_FILE, status );
  2861. }
  2862. }
  2863. return;
  2864. } // SetEofToMatchAllocation
  2865. #ifdef INCLUDE_SMB_IFMODIFIED
  2866. #if 0
  2867. NTSTATUS
  2868. SrvGetUsnInfoForFile(
  2869. IN PWORK_CONTEXT WorkContext,
  2870. IN PRFCB Rfcb,
  2871. IN BOOLEAN SubmitClose,
  2872. OUT PLARGE_INTEGER Usn,
  2873. OUT PLARGE_INTEGER FileRefNumber
  2874. )
  2875. {
  2876. PIRP irp;
  2877. ULONG fsControl;
  2878. Usn->QuadPart = 0;
  2879. FileRefNumber->QuadPart = 0;
  2880. if (! Rfcb->Lfcb->TreeConnect->Share->UsnCapable) {
  2881. return STATUS_SUCCESS;
  2882. }
  2883. // if the client opened the file with the short name, we could end up
  2884. // having a buffer that's woefully too small. We'll bump the
  2885. // allocation up to a large amount so that we don't have to
  2886. // go back and do it again.
  2887. sizeRequired = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
  2888. sizeRequired += sizeof( USN_RECORD );
  2889. sizeRequired = QuadAlign( sizeRequired );
  2890. usnRecord = ALLOCATE_NONPAGED_POOL( sizeRequired, BlockTypeDataBuffer );
  2891. if ( usnRecord == NULL) {
  2892. // IF_DEBUG(ERRORS) {
  2893. KdPrint(( "SrvGetUsnInfoForFile: unable to alloc block of size %u for handle 0x%x\n",
  2894. sizeRequired, Rfcb->Lfcb->FileObject ));
  2895. // }
  2896. return STATUS_INSUFF_SERVER_RESOURCES;
  2897. }
  2898. fsControl = SubmitClose ? FSCTL_WRITE_USN_CLOSE_RECORD : FSCTL_READ_FILE_USN_DATA;
  2899. //
  2900. // get the current USN number for this file.
  2901. //
  2902. irp = SrvBuildIoControlRequest(
  2903. NULL, // input IRP address
  2904. Rfcb->Lfcb->FileObject, // target file object address
  2905. WorkContext, // context
  2906. IRP_MJ_FILE_SYSTEM_CONTROL, // major function
  2907. fsControl, // minor function
  2908. NULL, // input buffer address
  2909. 0, // input buffer length
  2910. usnRecord, // output buffer address
  2911. sizeRequired, // output buffer length
  2912. NULL, // MDL address
  2913. SrvMdlCompletionRoutine // completion routine
  2914. );
  2915. if (irp != NULL) {
  2916. status = IoCallDriver( Rfcb->Lfcb->DeviceObject, irp );
  2917. // if ( !NT_SUCCESS(status) ) {
  2918. ASSERT( status != STATUS_MORE_PROCESSING_REQUIRED );
  2919. ASSERT( status != STATUS_PENDING );
  2920. IF_DEBUG(ERRORS) {
  2921. KdPrint(( "SrvGetUsnInfoForFile: Query USN info failed: 0x%X for handle %u\n",
  2922. status, Rfcb->Lfcb->FileObject ));
  2923. // }
  2924. } else {
  2925. Usn->QuadPart = usnRecord->Usn;
  2926. FileRefNumber->QuadPart = usnRecord->FileReferenceNumber;
  2927. }
  2928. IoFreeIrp( irp );
  2929. } else {
  2930. IF_DEBUG(ERRORS) {
  2931. KdPrint(( "SrvGetUsnInfoForFile: unable to alloc irp for handle 0x%x\n",
  2932. Rfcb->Lfcb->FileObject ));
  2933. }
  2934. status = STATUS_INSUFF_SERVER_RESOURCES;
  2935. }
  2936. DEALLOCATE_NONPAGED_POOL( usnRecord );
  2937. return status;
  2938. }
  2939. #endif
  2940. #endif // def INCLUDE_SMB_IFMODIFIED