Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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