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.

3658 lines
111 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. Create.c
  5. Abstract:
  6. This module implements the File Create routine for the NetWare
  7. redirector called by the dispatch driver.
  8. Author:
  9. Colin Watson [ColinW] 19-Dec-1992
  10. Manny Weiser [MannyW] 15-Feb-1993
  11. Revision History:
  12. --*/
  13. #include "Procs.h"
  14. NTSTATUS
  15. NwCommonCreate (
  16. IN PIRP_CONTEXT IrpContext
  17. );
  18. IO_STATUS_BLOCK
  19. OpenRedirector(
  20. IN PIRP_CONTEXT IrpContext,
  21. ULONG DesiredAccess,
  22. ULONG ShareAccess,
  23. PFILE_OBJECT FileObject
  24. );
  25. IO_STATUS_BLOCK
  26. CreateRemoteFile(
  27. IN PIRP_CONTEXT IrpContext,
  28. IN PUNICODE_STRING DriveName
  29. );
  30. IO_STATUS_BLOCK
  31. ChangeDirectory(
  32. PIRP_CONTEXT IrpContext,
  33. PVCB Vcb,
  34. PICB Icb
  35. );
  36. IO_STATUS_BLOCK
  37. CreateDir(
  38. PIRP_CONTEXT IrpContext,
  39. PVCB Vcb,
  40. PICB Icb
  41. );
  42. NTSTATUS
  43. FileOrDirectoryExists(
  44. IN PIRP_CONTEXT IrpContext,
  45. IN PVCB Vcb,
  46. IN PICB Icb,
  47. PUNICODE_STRING Name,
  48. OUT PBOOLEAN IsAFile
  49. );
  50. IO_STATUS_BLOCK
  51. OpenFile(
  52. IN PIRP_CONTEXT IrpContext,
  53. IN PVCB Vcb,
  54. IN PICB Icb,
  55. IN BYTE SearchFlags,
  56. IN BYTE ShareFlags
  57. );
  58. IO_STATUS_BLOCK
  59. CreateNewFile(
  60. IN PIRP_CONTEXT IrpContext,
  61. IN PVCB Vcb,
  62. IN PICB Icb,
  63. IN BYTE SearchFlags,
  64. IN BYTE ShareFlags
  65. );
  66. IO_STATUS_BLOCK
  67. CreateOrOverwriteFile(
  68. IN PIRP_CONTEXT IrpContext,
  69. IN PVCB Vcb,
  70. IN PICB Icb,
  71. IN BYTE CreateAttributes,
  72. IN BYTE OpenFlags,
  73. IN BOOLEAN CreateOperation
  74. );
  75. IO_STATUS_BLOCK
  76. OpenRenameTarget(
  77. IN PIRP_CONTEXT IrpContext,
  78. IN PVCB Vcb,
  79. IN PDCB Dcb,
  80. IN PICB* Icb
  81. );
  82. IO_STATUS_BLOCK
  83. CreatePrintJob(
  84. PIRP_CONTEXT IrpContext,
  85. PVCB Vcb,
  86. PICB Icb,
  87. PUNICODE_STRING DriveName
  88. );
  89. VOID
  90. CloseFile(
  91. PIRP_CONTEXT pIrpContext,
  92. PICB pIcb
  93. );
  94. BOOLEAN
  95. MmDisableModifiedWriteOfSection (
  96. IN PSECTION_OBJECT_POINTERS SectionObjectPointer
  97. );
  98. //
  99. // The debug trace level
  100. //
  101. #define Dbg (DEBUG_TRACE_CREATE)
  102. #ifdef ALLOC_PRAGMA
  103. #pragma alloc_text( PAGE, NwFsdCreate )
  104. #pragma alloc_text( PAGE, NwCommonCreate )
  105. #pragma alloc_text( PAGE, ReadAttachEas )
  106. #pragma alloc_text( PAGE, OpenRedirector )
  107. #pragma alloc_text( PAGE, CreateRemoteFile )
  108. #pragma alloc_text( PAGE, ChangeDirectory )
  109. #pragma alloc_text( PAGE, CreateDir )
  110. #pragma alloc_text( PAGE, FileOrDirectoryExists )
  111. #pragma alloc_text( PAGE, OpenFile )
  112. #pragma alloc_text( PAGE, CreateNewFile )
  113. #pragma alloc_text( PAGE, CreateOrOverwriteFile )
  114. #pragma alloc_text( PAGE, OpenRenameTarget )
  115. #pragma alloc_text( PAGE, CreatePrintJob )
  116. #pragma alloc_text( PAGE, CloseFile )
  117. #endif
  118. NTSTATUS
  119. NwFsdCreate (
  120. IN PDEVICE_OBJECT DeviceObject,
  121. IN PIRP Irp
  122. )
  123. /*++
  124. Routine Description:
  125. This routine implements the FSD part of the NtCreateFile and NtOpenFile
  126. API calls.
  127. Arguments:
  128. DeviceObject - Supplies the device object for the redirector.
  129. Irp - Supplies the Irp being processed
  130. Return Value:
  131. NTSTATUS - The Fsd status for the Irp
  132. --*/
  133. {
  134. NTSTATUS Status;
  135. PIRP_CONTEXT IrpContext = NULL;
  136. BOOLEAN TopLevel;
  137. PAGED_CODE();
  138. TimerStart(Dbg);
  139. DebugTrace(+1, Dbg, "NwFsdCreate\n", 0);
  140. //
  141. // Call the common create routine, with block allowed if the operation
  142. // is synchronous.
  143. //
  144. FsRtlEnterFileSystem();
  145. TopLevel = NwIsIrpTopLevel( Irp );
  146. try {
  147. IrpContext = AllocateIrpContext( Irp );
  148. Status = NwCommonCreate( IrpContext );
  149. } except( NwExceptionFilter( Irp, GetExceptionInformation() )) {
  150. if ( IrpContext == NULL ) {
  151. //
  152. // If we couldn't allocate an irp context, just complete
  153. // irp without any fanfare.
  154. //
  155. Status = STATUS_INSUFFICIENT_RESOURCES;
  156. Irp->IoStatus.Status = Status;
  157. Irp->IoStatus.Information = 0;
  158. IoCompleteRequest ( Irp, IO_NETWORK_INCREMENT );
  159. } else {
  160. //
  161. // We had some trouble trying to perform the requested
  162. // operation, so we'll abort the I/O request with
  163. // the error Status that we get back from the
  164. // execption code
  165. //
  166. Status = NwProcessException( IrpContext, GetExceptionCode() );
  167. }
  168. }
  169. if ( IrpContext ) {
  170. NwDequeueIrpContext( IrpContext, FALSE );
  171. NwCompleteRequest( IrpContext, Status );
  172. }
  173. if ( TopLevel ) {
  174. NwSetTopLevelIrp( NULL );
  175. }
  176. FsRtlExitFileSystem();
  177. //
  178. // And return to our caller
  179. //
  180. DebugTrace(-1, Dbg, "NwFsdCreate -> %08lx\n", Status );
  181. TimerStop(Dbg,"NwFsdCreate");
  182. return Status;
  183. UNREFERENCED_PARAMETER(DeviceObject);
  184. }
  185. NTSTATUS
  186. NwCommonCreate (
  187. IN PIRP_CONTEXT IrpContext
  188. )
  189. /*++
  190. Routine Description:
  191. This is the common routine for creating/opening a file called by
  192. both the fsd and fsp threads.
  193. Arguments:
  194. IrpContext - Supplies the context information for the IRP to process
  195. Return Value:
  196. NTSTATUS - the return status for the operation
  197. --*/
  198. {
  199. IO_STATUS_BLOCK Iosb;
  200. PIRP Irp;
  201. PIO_STACK_LOCATION IrpSp;
  202. PFILE_OBJECT FileObject;
  203. ACCESS_MASK DesiredAccess;
  204. USHORT ShareAccess;
  205. ULONG Options;
  206. BOOLEAN CreateTreeConnection;
  207. BOOLEAN DeleteOnClose;
  208. BOOLEAN DeferredLogon;
  209. BOOLEAN DereferenceCodeSection = FALSE;
  210. BOOLEAN OpenedTreeHandle = FALSE;
  211. BOOLEAN fNDSLookupFirst = FALSE;
  212. USHORT iBufferIndex = 0;
  213. DWORD dwSlashCount = 0;
  214. UNICODE_STRING CreateFileName;
  215. UNICODE_STRING Drive;
  216. UNICODE_STRING Server;
  217. UNICODE_STRING Volume;
  218. UNICODE_STRING Path;
  219. UNICODE_STRING FileName;
  220. UNICODE_STRING UserName, Password;
  221. ULONG ShareType;
  222. WCHAR DriveLetter;
  223. DWORD dwExtendedCreate = FALSE;
  224. PSCB Scb = NULL;
  225. PICB Icb;
  226. UNICODE_STRING DefaultServer;
  227. SECURITY_SUBJECT_CONTEXT SubjectContext;
  228. PAGED_CODE();
  229. //
  230. // Get the current IRP stack location
  231. //
  232. Irp = IrpContext->pOriginalIrp;
  233. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  234. //
  235. // tommye - MS bug 30091 / MCS 262 - added some safety nets around those pointers
  236. // containing pointers so we don't bugcheck in the debug code.
  237. //
  238. DebugTrace(+1, Dbg, "NwCommonCreate\n", 0 );
  239. DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
  240. DebugTrace( 0, Dbg, "->Flags = %08lx\n", Irp->Flags );
  241. DebugTrace( 0, Dbg, "->FileObject = %08lx\n", IrpSp->FileObject );
  242. if (IrpSp->FileObject) {
  243. DebugTrace( 0, Dbg, " ->RelatedFileObject = %08lx\n", IrpSp->FileObject->RelatedFileObject );
  244. DebugTrace( 0, Dbg, " ->FileName = \"%wZ\"\n", &IrpSp->FileObject->FileName );
  245. }
  246. DebugTrace( 0, Dbg, "->AllocationSize.LowPart = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
  247. DebugTrace( 0, Dbg, "->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
  248. DebugTrace( 0, Dbg, "->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
  249. DebugTrace( 0, Dbg, "->IrpSp->Flags = %08lx\n", IrpSp->Flags );
  250. if (IrpSp->Parameters.Create.SecurityContext) {
  251. DebugTrace( 0, Dbg, "->DesiredAccess = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
  252. }
  253. DebugTrace( 0, Dbg, "->Options = %08lx\n", IrpSp->Parameters.Create.Options );
  254. DebugTrace( 0, Dbg, "->Disposition = %08lx\n", (IrpSp->Parameters.Create.Options >> 24) & 0x000000ff);
  255. DebugTrace( 0, Dbg, "->FileAttributes = %04x\n", IrpSp->Parameters.Create.FileAttributes );
  256. DebugTrace( 0, Dbg, "->ShareAccess = %04x\n", IrpSp->Parameters.Create.ShareAccess );
  257. DebugTrace( 0, Dbg, "->EaLength = %08lx\n", IrpSp->Parameters.Create.EaLength );
  258. CreateFileName = IrpSp->FileObject->FileName;
  259. Options = IrpSp->Parameters.Create.Options;
  260. DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
  261. ShareAccess = IrpSp->Parameters.Create.ShareAccess;
  262. CreateTreeConnection = BooleanFlagOn( Options, FILE_CREATE_TREE_CONNECTION );
  263. DeleteOnClose = BooleanFlagOn( Options, FILE_DELETE_ON_CLOSE );
  264. DefaultServer.Buffer = NULL;
  265. //
  266. // Make sure the input large integer is valid
  267. //
  268. if (Irp->Overlay.AllocationSize.HighPart != 0) {
  269. DebugTrace(-1, Dbg, "NwCommonCreate -> STATUS_INVALID_PARAMETER\n", 0);
  270. return STATUS_INVALID_PARAMETER;
  271. }
  272. //
  273. // Fail requests that don't have the proper impersonation level.
  274. //
  275. /* This test is overly restrictive and unnecessary
  276. if ( IrpSp->Parameters.Create.SecurityContext ) {
  277. if ( IrpSp->Parameters.Create.SecurityContext->SecurityQos ) {
  278. if ( IrpSp->Parameters.Create.SecurityContext->SecurityQos->ImpersonationLevel <
  279. SecurityImpersonation ) {
  280. DebugTrace(-1, Dbg, "NwCommonCreate -> Insufficient impersation level.\n", 0);
  281. return STATUS_ACCESS_DENIED;
  282. }
  283. }
  284. }
  285. */
  286. Iosb.Status = STATUS_SUCCESS;
  287. FileObject = IrpSp->FileObject;
  288. IrpContext->pNpScb = NULL;
  289. IrpContext->Specific.Create.UserUid =
  290. GetUid(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
  291. try {
  292. if ( IrpSp->FileObject->RelatedFileObject != NULL ) {
  293. //
  294. // If we open a handle then the DereferenceCodeSection flag
  295. // will be set to false. The dereference will eventually
  296. // happen when the file is closed.
  297. //
  298. NwReferenceUnlockableCodeSection();
  299. DereferenceCodeSection = TRUE;
  300. //
  301. // Record the relative file name for this open.
  302. //
  303. IrpContext->Specific.Create.FullPathName = CreateFileName;
  304. Iosb = CreateRemoteFile( IrpContext, NULL );
  305. //
  306. // If we succeeded, we want to keep the code section
  307. // referenced because we have opened a handle.
  308. //
  309. if ( NT_SUCCESS( Iosb.Status ) ) {
  310. DereferenceCodeSection = FALSE;
  311. }
  312. try_return( Iosb.Status );
  313. }
  314. Iosb.Status = CrackPath (
  315. &CreateFileName,
  316. &Drive,
  317. &DriveLetter,
  318. &Server,
  319. &Volume,
  320. &Path,
  321. &FileName,
  322. NULL );
  323. if ( !NT_SUCCESS(Iosb.Status)) {
  324. try_return(Iosb.Status);
  325. }
  326. //
  327. // Remember this good info.
  328. //
  329. IrpContext->Specific.Create.VolumeName = Volume;
  330. IrpContext->Specific.Create.PathName = Path;
  331. IrpContext->Specific.Create.DriveLetter = DriveLetter;
  332. IrpContext->Specific.Create.FileName = FileName;
  333. IrpContext->Specific.Create.FullPathName = CreateFileName;
  334. RtlInitUnicodeString( &IrpContext->Specific.Create.UidConnectName, NULL );
  335. //
  336. // For now assume default username and password
  337. //
  338. ShareType = RESOURCETYPE_ANY;
  339. RtlInitUnicodeString( &UserName, NULL );
  340. RtlInitUnicodeString( &Password, NULL );
  341. if ((Server.Length == 0) && (CreateFileName.Length == 0)) {
  342. //
  343. // Opened the redirector itself
  344. //
  345. Iosb = OpenRedirector(
  346. IrpContext,
  347. DesiredAccess,
  348. ShareAccess,
  349. FileObject );
  350. } else if ( Server.Length == Volume.Length - sizeof( WCHAR ) ) {
  351. if (IpxHandle == 0 ) {
  352. //
  353. // We're not bound to the transport and the user is not
  354. // opening the redirector to tell us to bind so return failed.
  355. //
  356. try_return( Iosb.Status = STATUS_REDIRECTOR_NOT_STARTED );
  357. }
  358. NwReferenceUnlockableCodeSection();
  359. DereferenceCodeSection = TRUE;
  360. //
  361. // If the only requested access is FILE_LIST_DIRECTORY,
  362. // defer the logon. This will allow all CreateScb to
  363. // succeed with when the user or password is invalid, so
  364. // that the user can see volumes, or enumerate servers
  365. // on the server.
  366. //
  367. if ( (DesiredAccess & ~( FILE_LIST_DIRECTORY | SYNCHRONIZE ) ) == 0 ) {
  368. DeferredLogon = TRUE;
  369. } else {
  370. DeferredLogon = FALSE;
  371. }
  372. //
  373. // Server = "Server", Volume = "\Server"
  374. //
  375. if ( Server.Length == sizeof(WCHAR) && Server.Buffer[0] == L'*') {
  376. //
  377. // Attempt to open \\*, open a handle to the preferred
  378. // server
  379. //
  380. PLOGON Logon;
  381. NwAcquireExclusiveRcb( &NwRcb, TRUE );
  382. Logon = FindUser( &IrpContext->Specific.Create.UserUid, FALSE);
  383. ASSERT( Logon != NULL );
  384. //
  385. // Capture the name to avoid holding Rcb or referencing
  386. // the logon structure.
  387. //
  388. Iosb.Status = DuplicateUnicodeStringWithString (
  389. &DefaultServer,
  390. &Logon->ServerName,
  391. PagedPool);
  392. NwReleaseRcb( &NwRcb );
  393. if (!NT_SUCCESS(Iosb.Status)) {
  394. try_return( Iosb.Status );
  395. }
  396. //
  397. // If the user specified a preferred server and we managed
  398. // to capture the name, try and connect to it.
  399. //
  400. if (DefaultServer.Length != 0) {
  401. Iosb.Status = CreateScb(
  402. &Scb,
  403. IrpContext,
  404. &DefaultServer,
  405. NULL,
  406. NULL,
  407. NULL,
  408. DeferredLogon,
  409. FALSE );
  410. } else {
  411. //
  412. // Record that we could not get to the server specified
  413. // in the login structure and that we should attempt to
  414. // use the nearest server.
  415. //
  416. Iosb.Status = STATUS_BAD_NETWORK_PATH;
  417. }
  418. if ( !NT_SUCCESS(Iosb.Status)) {
  419. PNONPAGED_SCB NpScb;
  420. //
  421. // First dequeue the IRP context, in case it was left
  422. // on an SCB queue.
  423. //
  424. NwDequeueIrpContext( IrpContext, FALSE );
  425. //
  426. // Cannot get to the Preferred server so use any
  427. // server we have a connection to.
  428. //
  429. NpScb = SelectConnection( NULL );
  430. if (NpScb != NULL ) {
  431. Scb = NpScb->pScb;
  432. Iosb.Status = CreateScb(
  433. &Scb,
  434. IrpContext,
  435. &NpScb->ServerName,
  436. NULL,
  437. NULL,
  438. NULL,
  439. DeferredLogon,
  440. FALSE );
  441. //
  442. // Release the SCB reference we obtained from
  443. // SelectConnection().
  444. //
  445. NwDereferenceScb( NpScb );
  446. }
  447. }
  448. if ( !NT_SUCCESS(Iosb.Status)) {
  449. //
  450. // First dequeue the IRP context, in case it was left
  451. // on an SCB queue.
  452. //
  453. NwDequeueIrpContext( IrpContext, FALSE );
  454. //
  455. // Let CreateScb try and find a nearest server to talk
  456. // to.
  457. //
  458. Iosb.Status = CreateScb(
  459. &Scb,
  460. IrpContext,
  461. NULL,
  462. NULL,
  463. NULL,
  464. NULL,
  465. DeferredLogon,
  466. FALSE );
  467. }
  468. if ( !NT_SUCCESS(Iosb.Status)) {
  469. try_return( Iosb.Status );
  470. }
  471. } else {
  472. //
  473. // On handle opens to a server or tree we support the concept
  474. // of an open with supplemental credentials. In this case, we return
  475. // a handle to the server or a dir server using the provided
  476. // credentials regardless of whether or not there are existing
  477. // connections to the resource. This is primarily for admin
  478. // tools like OleDs.
  479. //
  480. ReadAttachEas( Irp, &UserName, &Password, &ShareType, &dwExtendedCreate );
  481. if ( dwExtendedCreate ) {
  482. ASSERT( UserName.Length > 0 );
  483. IrpContext->Specific.Create.fExCredentialCreate = TRUE;
  484. IrpContext->Specific.Create.puCredentialName = &UserName;
  485. //
  486. // Reference the credentials before doing the create so
  487. // we are guaranteed not to lose them. This call will
  488. // create a credential shell if none exists. This keeps
  489. // our reference counting consistent. We track the
  490. // credentials pointer in the irp context specific data.
  491. //
  492. Iosb.Status = ExCreateReferenceCredentials( IrpContext, &Server );
  493. if ( !NT_SUCCESS( Iosb.Status ) ) {
  494. try_return( Iosb.Status );
  495. }
  496. }
  497. if (PreferNDSBrowsing) {
  498. //
  499. // Attempt to open \\TREE
  500. //
  501. Iosb.Status = NdsCreateTreeScb( IrpContext,
  502. &Scb, // dest scb
  503. &Server, // tree we want
  504. &UserName,
  505. &Password,
  506. DeferredLogon,
  507. DeleteOnClose );
  508. if ( NT_SUCCESS( Iosb.Status ) ) {
  509. OpenedTreeHandle = TRUE;
  510. }
  511. if ( ( Iosb.Status == STATUS_REMOTE_NOT_LISTENING ) ||
  512. ( Iosb.Status == STATUS_BAD_NETWORK_PATH ) ||
  513. ( Iosb.Status == STATUS_UNSUCCESSFUL ) ) {
  514. //
  515. // If we couldn't find the server or something
  516. // inexplicable occurred, attempt to open \\server
  517. //
  518. Iosb.Status = CreateScb(
  519. &Scb,
  520. IrpContext,
  521. &Server,
  522. NULL,
  523. &UserName,
  524. &Password,
  525. DeferredLogon,
  526. DeleteOnClose );
  527. }
  528. }else{
  529. //
  530. // Attempt to open \\server
  531. //
  532. Iosb.Status = CreateScb(
  533. &Scb,
  534. IrpContext,
  535. &Server,
  536. NULL,
  537. &UserName,
  538. &Password,
  539. DeferredLogon,
  540. DeleteOnClose );
  541. if ( ( Iosb.Status == STATUS_REMOTE_NOT_LISTENING ) ||
  542. ( Iosb.Status == STATUS_BAD_NETWORK_PATH ) ||
  543. ( Iosb.Status == STATUS_UNSUCCESSFUL ) ) {
  544. //
  545. // If we couldn't find the server or something
  546. // inexplicable occurred, attempt to open \\tree.
  547. //
  548. Iosb.Status = NdsCreateTreeScb( IrpContext,
  549. &Scb, // dest scb
  550. &Server, // tree we want
  551. &UserName,
  552. &Password,
  553. DeferredLogon,
  554. DeleteOnClose );
  555. if ( NT_SUCCESS( Iosb.Status ) ) {
  556. OpenedTreeHandle = TRUE;
  557. }
  558. }
  559. }
  560. // if( IsTerminalServer() ) clause below has been shifted down as we are more
  561. // likely to be opening a tree or server than a pserver.
  562. // so we need to check there first.
  563. if (IsTerminalServer()) {
  564. /*
  565. * This is an attempt to get GUEST to work for printman.
  566. * I.E. If you have no connection, try the guest
  567. * connection.
  568. */
  569. if ( ( !NT_SUCCESS(Iosb.Status) ) &&
  570. ( Iosb.Status == STATUS_NO_SUCH_USER ) &&
  571. ( !CreateTreeConnection ) &&
  572. ( !DeferredLogon ) ) {
  573. DebugTrace( -1, Dbg, " Attempting default GUEST logon for %wZ\n", &Server );
  574. Iosb.Status = CreateScb(
  575. &Scb,
  576. IrpContext,
  577. &Server,
  578. NULL,
  579. &Guest.UserName,
  580. &Guest.PassWord,
  581. DeferredLogon,
  582. DeleteOnClose );
  583. }
  584. }
  585. if ( !NT_SUCCESS( Iosb.Status ) ) {
  586. //
  587. // If we failed to get the bindery server for
  588. // some legitimate reason, bail out now.
  589. //
  590. try_return( Iosb.Status );
  591. }
  592. //
  593. // We must have a connection at this point. We don't tree
  594. // connect the dir server since it's virtual.
  595. //
  596. if ( !OpenedTreeHandle && CreateTreeConnection && !DeleteOnClose ) {
  597. TreeConnectScb( Scb );
  598. }
  599. }
  600. //
  601. // Now create the ICB.
  602. //
  603. ASSERT( Iosb.Status == STATUS_SUCCESS );
  604. ASSERT( Scb != NULL );
  605. Icb = NwCreateIcb( NW_NTC_ICB_SCB, Scb );
  606. Icb->FileObject = FileObject;
  607. NwSetFileObject( FileObject, NULL, Icb );
  608. //
  609. // Indicate that the SCB was opened.
  610. //
  611. Icb->State = ICB_STATE_OPENED;
  612. //
  613. // Is this a tree handle?
  614. //
  615. Icb->IsTreeHandle = OpenedTreeHandle;
  616. //
  617. // If this was an extended create, associate this handle
  618. // with its extended credentials so that we can cleanup
  619. // when all the handles are closed.
  620. //
  621. if ( IrpContext->Specific.Create.fExCredentialCreate ) {
  622. ASSERT( IrpContext->Specific.Create.pExCredentials != NULL );
  623. Icb->pContext = IrpContext->Specific.Create.pExCredentials;
  624. Icb->IsExCredentialHandle = TRUE;
  625. }
  626. } else {
  627. NwReferenceUnlockableCodeSection();
  628. DereferenceCodeSection = TRUE;
  629. DeferredLogon = FALSE;
  630. if ( CreateTreeConnection ) {
  631. //
  632. // We ignore the extended create attribute here because
  633. // we DO NOT support extended credential creates to random
  634. // files and directories!
  635. //
  636. ReadAttachEas( Irp, &UserName, &Password, &ShareType, NULL );
  637. if ( DeleteOnClose ) {
  638. //
  639. // Opening a directory to delete a volume. Do not
  640. // force logon.
  641. //
  642. DeferredLogon = TRUE;
  643. }
  644. }
  645. IrpContext->Specific.Create.ShareType = ShareType;
  646. IrpContext->Specific.Create.NdsCreate = FALSE;
  647. //
  648. // Check to see if this is an NDS object, if so set the flag to check NDS first.
  649. // The only way a DOT can be in the Volume name is if it is an NDS Object,
  650. // between the third and fourth slashes.
  651. //
  652. fNDSLookupFirst = FALSE;
  653. for (iBufferIndex=0; iBufferIndex < (USHORT)(Volume.Length/sizeof(WCHAR)); iBufferIndex++ ) {
  654. if (Volume.Buffer[iBufferIndex] == L'\\')
  655. dwSlashCount++;
  656. if (dwSlashCount > 3) {
  657. fNDSLookupFirst = FALSE;
  658. break;
  659. }
  660. if (Volume.Buffer[iBufferIndex] == L'.') {
  661. fNDSLookupFirst = TRUE;
  662. break;
  663. }
  664. }
  665. if (fNDSLookupFirst) {
  666. IrpContext->Specific.Create.NdsCreate = TRUE;
  667. IrpContext->Specific.Create.NeedNdsData = TRUE;
  668. Iosb.Status = NdsCreateTreeScb( IrpContext,
  669. &Scb,
  670. &Server,
  671. &UserName,
  672. &Password,
  673. DeferredLogon,
  674. DeleteOnClose );
  675. if ( Iosb.Status == STATUS_REMOTE_NOT_LISTENING ||
  676. Iosb.Status == STATUS_BAD_NETWORK_PATH ||
  677. Iosb.Status == STATUS_UNSUCCESSFUL ) {
  678. //
  679. // Not found, do a bindery lookup
  680. //
  681. IrpContext->Specific.Create.NdsCreate = FALSE;
  682. IrpContext->Specific.Create.NeedNdsData = FALSE;
  683. Iosb.Status = CreateScb(
  684. &Scb,
  685. IrpContext,
  686. &Server,
  687. NULL,
  688. &UserName,
  689. &Password,
  690. DeferredLogon,
  691. DeleteOnClose );
  692. }
  693. }else {
  694. //
  695. // Object appears to be bindery, check there first.
  696. //
  697. Iosb.Status = CreateScb(
  698. &Scb,
  699. IrpContext,
  700. &Server,
  701. NULL,
  702. &UserName,
  703. &Password,
  704. DeferredLogon,
  705. DeleteOnClose );
  706. if ( Iosb.Status == STATUS_REMOTE_NOT_LISTENING ||
  707. Iosb.Status == STATUS_BAD_NETWORK_PATH ||
  708. Iosb.Status == STATUS_UNSUCCESSFUL ) {
  709. //
  710. // If we couldn't find the server or something
  711. // inexplicable occurred, attempt to open \\tree.
  712. //
  713. IrpContext->Specific.Create.NdsCreate = TRUE;
  714. IrpContext->Specific.Create.NeedNdsData = TRUE;
  715. Iosb.Status = NdsCreateTreeScb( IrpContext,
  716. &Scb,
  717. &Server,
  718. &UserName,
  719. &Password,
  720. DeferredLogon,
  721. DeleteOnClose );
  722. }
  723. }
  724. //
  725. // If we have success, then there's a volume to connect.
  726. //
  727. if ( NT_SUCCESS( Iosb.Status ) ) {
  728. NTSTATUS CreateScbStatus;
  729. ASSERT( Scb != NULL );
  730. //
  731. // Remember the status from create SCB, since it might
  732. // be an interesting warning.
  733. //
  734. CreateScbStatus = Iosb.Status;
  735. //
  736. // We catch this exception in case we have to retry the
  737. // create on the NDS path. This is horrable, as does the
  738. // exception structure in this code right now, but it's
  739. // legacy and now is not the time to change it.
  740. //
  741. try {
  742. Iosb = CreateRemoteFile(
  743. IrpContext,
  744. &Drive );
  745. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  746. Iosb.Status = GetExceptionCode();
  747. }
  748. //
  749. // If this is a server whose name is the same as the tree
  750. // that it is a member of, and the create was marked as
  751. // non-nds and it failed, retry an nds create.
  752. //
  753. if ( ( !NT_SUCCESS( Iosb.Status) ) &&
  754. ( !(IrpContext->Specific.Create.NdsCreate) ) &&
  755. ( RtlEqualUnicodeString( &(Scb->pNpScb->ServerName),
  756. &(Scb->NdsTreeName),
  757. TRUE ) ) ) {
  758. IrpContext->Specific.Create.NdsCreate = TRUE;
  759. IrpContext->Specific.Create.NeedNdsData = TRUE;
  760. Iosb = CreateRemoteFile(
  761. IrpContext,
  762. &Drive );
  763. //
  764. // If this fails, it will raise status before setting IOSB
  765. // and we'll return the status from the original create,
  766. // which is the more interesting one.
  767. //
  768. }
  769. //
  770. // If we successfully open the remote file, return the
  771. // CreateScb status instead.
  772. //
  773. if ( NT_SUCCESS( Iosb.Status ) ) {
  774. Iosb.Status = CreateScbStatus;
  775. }
  776. }
  777. }
  778. //
  779. // If we succeeded, we want to keep the code section
  780. // referenced because we have opened a handle.
  781. //
  782. if ( NT_SUCCESS( Iosb.Status ) ) {
  783. DereferenceCodeSection = FALSE;
  784. }
  785. try_exit: NOTHING;
  786. } finally {
  787. //
  788. // Track the Scb in the IrpContext, not in the local Scb
  789. // variable since we may have been routed to another server
  790. // in process.
  791. //
  792. if (( Scb != NULL ) && ( IrpContext->pNpScb != NULL )) {
  793. NwDereferenceScb( IrpContext->pNpScb );
  794. }
  795. if ( DefaultServer.Buffer != NULL ) {
  796. FREE_POOL( DefaultServer.Buffer );
  797. }
  798. if ( ( IrpContext->Specific.Create.fExCredentialCreate ) &&
  799. ( IrpContext->Specific.Create.pExCredentials ) &&
  800. ( !NT_SUCCESS( Iosb.Status ) ) ) {
  801. ExCreateDereferenceCredentials(
  802. IrpContext,
  803. IrpContext->Specific.Create.pExCredentials
  804. );
  805. }
  806. DebugTrace(-1, Dbg, "NwCommonCreate -> %08lx\n", Iosb.Status);
  807. if ( DereferenceCodeSection ) {
  808. NwDereferenceUnlockableCodeSection ();
  809. }
  810. }
  811. //
  812. // Map a timeout error to server not found, so that MPR will
  813. // try to connect on the next network provider instead of giving up,
  814. // which is wrong wrong wrong.
  815. //
  816. if ( Iosb.Status == STATUS_REMOTE_NOT_LISTENING ) {
  817. Iosb.Status = STATUS_BAD_NETWORK_PATH;
  818. }
  819. //
  820. // Map an unbound transport error to server not found, so that MPR
  821. // will try to connect on the next provider.
  822. //
  823. if ( Iosb.Status == STATUS_NETWORK_UNREACHABLE ) {
  824. Iosb.Status = STATUS_BAD_NETWORK_PATH;
  825. }
  826. return Iosb.Status;
  827. }
  828. NTSTATUS
  829. ReadAttachEas(
  830. IN PIRP Irp,
  831. OUT PUNICODE_STRING UserName,
  832. OUT PUNICODE_STRING Password,
  833. OUT PULONG ShareType,
  834. OUT PDWORD CredentialExtension
  835. )
  836. /*++
  837. Routine Description:
  838. This routine processes the EAs provided when the caller attempts
  839. to attach to a remote server.
  840. Note: This routine does not create additional storage for the names.
  841. It is the callers responsibility to save them if required.
  842. Arguments:
  843. Irp - Supplies all the information
  844. UserName - Returns the value of the User name EA
  845. Password - Returns the value of the password EA
  846. ShareType - Returns the value of the share type EA
  847. CredentialExtension - Returns whether or not this create
  848. should use the provided credentials for an credential
  849. extended connection. This is primarily for OleDs
  850. accessing the ds in multiple security contexts.
  851. Return Value:
  852. NTSTATUS - Status of operation
  853. --*/
  854. {
  855. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  856. PFILE_FULL_EA_INFORMATION EaBuffer = Irp->AssociatedIrp.SystemBuffer;
  857. PAGED_CODE();
  858. RtlInitUnicodeString( UserName, NULL );
  859. RtlInitUnicodeString( Password, NULL );
  860. *ShareType = RESOURCETYPE_ANY;
  861. if ( CredentialExtension ) {
  862. *CredentialExtension = FALSE;
  863. }
  864. DebugTrace(+1, Dbg, "ReadAttachEas....\n", 0);
  865. if ( EaBuffer != NULL) {
  866. while (TRUE) {
  867. ULONG EaNameLength = EaBuffer->EaNameLength;
  868. if (strcmp(EaBuffer->EaName, EA_NAME_USERNAME) == 0) {
  869. UserName->Length = EaBuffer->EaValueLength;
  870. UserName->MaximumLength = EaBuffer->EaValueLength;
  871. UserName->Buffer = (PWSTR)(EaBuffer->EaName+EaNameLength+1);
  872. } else if (strcmp(EaBuffer->EaName, EA_NAME_PASSWORD) == 0) {
  873. Password->Length = EaBuffer->EaValueLength;
  874. Password->MaximumLength = EaBuffer->EaValueLength;
  875. Password->Buffer = (PWSTR)(EaBuffer->EaName+EaNameLength+1);
  876. } else if ((strcmp(EaBuffer->EaName, EA_NAME_TYPE) == 0) &&
  877. (EaBuffer->EaValueLength >= sizeof(ULONG))) {
  878. *ShareType = *(ULONG UNALIGNED *)(EaBuffer->EaName+EaNameLength+1);
  879. } else if (strcmp(EaBuffer->EaName, EA_NAME_CREDENTIAL_EX) == 0) {
  880. if ( CredentialExtension ) {
  881. *CredentialExtension = TRUE;
  882. DebugTrace(0, Dbg, "ReadAttachEas signals a credential extension.\n", 0 );
  883. }
  884. } else {
  885. DebugTrace(0, Dbg, "ReadAttachEas Unknown EA -> %s\n", EaBuffer->EaName);
  886. }
  887. if (EaBuffer->NextEntryOffset == 0) {
  888. break;
  889. } else {
  890. EaBuffer = (PFILE_FULL_EA_INFORMATION) ((PCHAR) EaBuffer+EaBuffer->NextEntryOffset);
  891. }
  892. }
  893. }
  894. DebugTrace(-1, Dbg, "ReadAttachEas -> %08lx\n", STATUS_SUCCESS);
  895. return STATUS_SUCCESS;
  896. }
  897. IO_STATUS_BLOCK
  898. OpenRedirector(
  899. IN PIRP_CONTEXT IrpContext,
  900. ULONG DesiredAccess,
  901. ULONG ShareAccess,
  902. PFILE_OBJECT FileObject
  903. )
  904. /*++
  905. Routine Description:
  906. This routines opens a handle to the redirector device.
  907. Arguments:
  908. IrpContext - Supplies all the information
  909. DesiredAccess - The requested access to the redirector.
  910. ShareAccess - The requested share access to the redirector.
  911. FileObject - A pointer to the caller file object.
  912. Return Value:
  913. IO_STATUS_BLOCK - Status of operation
  914. --*/
  915. {
  916. IO_STATUS_BLOCK iosb;
  917. PAGED_CODE();
  918. //
  919. // Note that the object manager will only allow an administrator
  920. // to open the redir itself. This is good.
  921. //
  922. DebugTrace(+1, Dbg, "NwOpenRedirector\n", 0);
  923. NwAcquireExclusiveRcb( &NwRcb, TRUE );
  924. try {
  925. //
  926. // Set the new share access
  927. //
  928. if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess,
  929. ShareAccess,
  930. FileObject,
  931. &NwRcb.ShareAccess,
  932. TRUE ))) {
  933. DebugTrace(0, Dbg, "bad share access\n", 0);
  934. try_return( NOTHING );
  935. }
  936. NwSetFileObject( FileObject, NULL, &NwRcb );
  937. ++NwRcb.OpenCount;
  938. //
  939. // Set the return status.
  940. //
  941. iosb.Status = STATUS_SUCCESS;
  942. iosb.Information = FILE_OPENED;
  943. try_exit: NOTHING;
  944. } finally {
  945. NwReleaseRcb( &NwRcb );
  946. DebugTrace(-1, Dbg, "NwOpenRedirector -> Iosb.Status = %08lx\n", iosb.Status);
  947. }
  948. //
  949. // Return to the caller.
  950. //
  951. return iosb;
  952. }
  953. IO_STATUS_BLOCK
  954. CreateRemoteFile(
  955. IN PIRP_CONTEXT IrpContext,
  956. IN PUNICODE_STRING DriveName
  957. )
  958. /*++
  959. Routine Description:
  960. This routines opens a remote file or directory.
  961. Arguments:
  962. IrpContext - Supplies all the information
  963. DriveName - The drive name. One of three forms X:, LPTx, or NULL.
  964. Return Value:
  965. IO_STATUS_BLOCK - Status of operation
  966. --*/
  967. {
  968. IO_STATUS_BLOCK Iosb;
  969. PIRP Irp;
  970. PIO_STACK_LOCATION IrpSp;
  971. ULONG DesiredAccess;
  972. ULONG ShareAccess;
  973. PFILE_OBJECT FileObject;
  974. UNICODE_STRING FileName;
  975. PFILE_OBJECT RelatedFileObject;
  976. ULONG Options;
  977. ULONG FileAttributes;
  978. BOOLEAN CreateDirectory;
  979. BOOLEAN OpenDirectory;
  980. BOOLEAN DirectoryFile;
  981. BOOLEAN NonDirectoryFile;
  982. BOOLEAN DeleteOnClose;
  983. BOOLEAN OpenTargetDirectory;
  984. ULONG AllocationSize;
  985. // Unhandled open features.
  986. // PFILE_FULL_EA_INFORMATION EaBuffer;
  987. // ULONG EaLength;
  988. // BOOLEAN SequentialOnly;
  989. // BOOLEAN NoIntermediateBuffering;
  990. // BOOLEAN IsPagingFile;
  991. // BOOLEAN NoEaKnowledge;
  992. ULONG CreateDisposition;
  993. PFCB Fcb = NULL;
  994. PICB Icb = NULL;
  995. PDCB Dcb;
  996. PVCB Vcb = NULL;
  997. PSCB Scb;
  998. BOOLEAN IsAFile;
  999. BOOLEAN MayBeADirectory = FALSE;
  1000. BOOLEAN OwnOpenLock = FALSE;
  1001. BOOLEAN SetShareAccess = FALSE;
  1002. BYTE SearchFlags;
  1003. BYTE ShareFlags;
  1004. BOOLEAN CreateTreeConnection = FALSE;
  1005. PUNICODE_STRING VolumeName;
  1006. NTSTATUS Status;
  1007. UNICODE_STRING NdsConnectName;
  1008. WCHAR ConnectBuffer[MAX_NDS_NAME_CHARS];
  1009. BOOLEAN MadeUidNdsName = FALSE;
  1010. PAGED_CODE();
  1011. Irp = IrpContext->pOriginalIrp;
  1012. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1013. DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
  1014. ShareAccess = IrpSp->Parameters.Create.ShareAccess;
  1015. FileObject = IrpSp->FileObject;
  1016. OpenTargetDirectory = BooleanFlagOn( IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY );
  1017. //
  1018. // It is ok to attempt a reconnect if this request fails with a
  1019. // connection error.
  1020. //
  1021. SetFlag( IrpContext->Flags, IRP_FLAG_RECONNECTABLE );
  1022. try {
  1023. //
  1024. // Reference our input parameters to make things easier
  1025. //
  1026. RelatedFileObject = FileObject->RelatedFileObject;
  1027. //
  1028. // We actually want the parsed file name.
  1029. // FileName = FileObject->FileName;
  1030. //
  1031. FileName = IrpContext->Specific.Create.FullPathName;
  1032. Options = IrpSp->Parameters.Create.Options;
  1033. FileAttributes = IrpSp->Parameters.Create.FileAttributes;
  1034. AllocationSize = Irp->Overlay.AllocationSize.LowPart;
  1035. //
  1036. // Short circuit an attempt to open a wildcard name.
  1037. //
  1038. if ( FsRtlDoesNameContainWildCards( &FileName ) ) {
  1039. try_return( Iosb.Status = STATUS_OBJECT_NAME_INVALID );
  1040. }
  1041. // Decipher Option flags and values
  1042. //
  1043. DirectoryFile = BooleanFlagOn( Options, FILE_DIRECTORY_FILE );
  1044. NonDirectoryFile = BooleanFlagOn( Options, FILE_NON_DIRECTORY_FILE );
  1045. DeleteOnClose = BooleanFlagOn( Options, FILE_DELETE_ON_CLOSE );
  1046. //
  1047. // Things we currently ignore, because netware servers don't support it.
  1048. //
  1049. // SequentialOnly = BooleanFlagOn( Options, FILE_SEQUENTIAL_ONLY );
  1050. // NoIntermediateBuffering = BooleanFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
  1051. // NoEaKnowledge = BooleanFlagOn( Options, FILE_NO_EA_KNOWLEDGE );
  1052. // EaBuffer = Irp->AssociatedIrp.SystemBuffer;
  1053. // EaLength = IrpSp->Parameters.Create.EaLength;
  1054. // IsPagingFile = BooleanFlagOn( IrpSp->Flags, SL_OPEN_PAGING_FILE );
  1055. if ( BooleanFlagOn( Options, FILE_CREATE_TREE_CONNECTION ) ) {
  1056. CreateDisposition = FILE_OPEN;
  1057. } else {
  1058. CreateDisposition = (Options >> 24) & 0x000000ff;
  1059. }
  1060. CreateDirectory = (BOOLEAN)(DirectoryFile &&
  1061. ((CreateDisposition == FILE_CREATE) ||
  1062. (CreateDisposition == FILE_OPEN_IF)));
  1063. OpenDirectory = (BOOLEAN)(DirectoryFile &&
  1064. ((CreateDisposition == FILE_OPEN) ||
  1065. (CreateDisposition == FILE_OPEN_IF)));
  1066. Dcb = NULL;
  1067. if ( RelatedFileObject != NULL ) {
  1068. PNONPAGED_DCB NonPagedDcb;
  1069. NonPagedDcb = RelatedFileObject->FsContext;
  1070. if ( NonPagedDcb ) {
  1071. Dcb = NonPagedDcb->Fcb;
  1072. }
  1073. //
  1074. // If there is a related file object then this is a relative open
  1075. // and it better be a DCB.
  1076. //
  1077. if ( !Dcb || (NodeType( Dcb ) != NW_NTC_DCB) ) {
  1078. DebugTrace(0, Dbg, "Bad file name\n", 0);
  1079. Iosb.Status = STATUS_OBJECT_NAME_INVALID;
  1080. try_return( Iosb );
  1081. }
  1082. //
  1083. // Obtain SCB pointers.
  1084. //
  1085. IrpContext->pScb = Dcb->Scb;
  1086. IrpContext->pNpScb = Dcb->Scb->pNpScb;
  1087. }
  1088. //
  1089. // We are about ready to send a packet. Append this IRP context
  1090. // the SCB workqueue, and wait until it gets to the front.
  1091. //
  1092. NwAppendToQueueAndWait( IrpContext );
  1093. ASSERT( IrpContext->pNpScb->Requests.Flink == &IrpContext->NextRequest );
  1094. //
  1095. // Acquire the Global FCB resource to ensure that one thread
  1096. // can't access the half created FCB of another thread.
  1097. //
  1098. NwAcquireOpenLock( );
  1099. OwnOpenLock = TRUE;
  1100. //
  1101. // Find the volume for this file.
  1102. //
  1103. CreateTreeConnection = BooleanFlagOn( Options, FILE_CREATE_TREE_CONNECTION );
  1104. if ( CreateTreeConnection ) {
  1105. VolumeName = &IrpContext->Specific.Create.FullPathName;
  1106. } else {
  1107. VolumeName = &IrpContext->Specific.Create.VolumeName;
  1108. }
  1109. if ( Dcb == NULL ) {
  1110. RetryFindVcb:
  1111. Vcb = NwFindVcb(
  1112. IrpContext,
  1113. VolumeName,
  1114. IrpContext->Specific.Create.ShareType,
  1115. IrpContext->Specific.Create.DriveLetter,
  1116. CreateTreeConnection,
  1117. ( BOOLEAN )( CreateTreeConnection && DeleteOnClose ) );
  1118. if ( Vcb == NULL ) {
  1119. //
  1120. // If this create failed because we need nds data, get
  1121. // the data from the ds and resubmit the request.
  1122. //
  1123. if ( IrpContext->Specific.Create.NdsCreate &&
  1124. IrpContext->Specific.Create.NeedNdsData ) {
  1125. //
  1126. // Release the open resource so we can move around.
  1127. //
  1128. NwReleaseOpenLock( );
  1129. OwnOpenLock = FALSE;
  1130. //
  1131. // Take the volume name and build the server/share
  1132. // connect name.
  1133. //
  1134. NdsConnectName.Buffer = ConnectBuffer;
  1135. NdsConnectName.MaximumLength = sizeof( ConnectBuffer );
  1136. NdsConnectName.Length = 0;
  1137. //
  1138. // Get the ds information. We may jump servers here.
  1139. //
  1140. Status = NdsMapObjectToServerShare( IrpContext,
  1141. &Scb,
  1142. &NdsConnectName,
  1143. CreateTreeConnection,
  1144. &(IrpContext->Specific.Create.dwNdsOid) );
  1145. if( !NT_SUCCESS( Status ) ) {
  1146. ExRaiseStatus( Status );
  1147. }
  1148. //
  1149. // Make sure we are on the scb queue after all the
  1150. // possible server jumping.
  1151. //
  1152. NwAppendToQueueAndWait( IrpContext );
  1153. NwAcquireOpenLock( );
  1154. OwnOpenLock = TRUE;
  1155. //
  1156. // Prepend the Uid to the server/share name.
  1157. //
  1158. MergeStrings( &IrpContext->Specific.Create.UidConnectName,
  1159. &Scb->UnicodeUid,
  1160. &NdsConnectName,
  1161. PagedPool );
  1162. MadeUidNdsName = TRUE;
  1163. //
  1164. // We have the data, so re-do the connect.
  1165. //
  1166. IrpContext->Specific.Create.NeedNdsData = FALSE;
  1167. goto RetryFindVcb;
  1168. } else {
  1169. //
  1170. // If this was an open to delete a tree connect, and we failed
  1171. // to find the VCB, simply return the error.
  1172. //
  1173. Iosb.Status = STATUS_BAD_NETWORK_PATH;
  1174. try_return ( Iosb );
  1175. }
  1176. }
  1177. } else {
  1178. Vcb = Dcb->Vcb;
  1179. NwReferenceVcb( Vcb );
  1180. }
  1181. ASSERT( Vcb->Scb == IrpContext->pScb );
  1182. //
  1183. // If this is the target name for a rename then we want to find the
  1184. // DCB for the parent directory.
  1185. //
  1186. if (OpenTargetDirectory) {
  1187. Iosb = OpenRenameTarget(IrpContext, Vcb, Dcb, &Icb );
  1188. if (Icb != NULL) {
  1189. Fcb = Icb->SuperType.Fcb;
  1190. }
  1191. try_return ( Iosb );
  1192. }
  1193. //
  1194. // Find the FCB for this file. If the FCB exists, we get a
  1195. // referenced pointer. Otherwise a new FCB is created.
  1196. //
  1197. Fcb = NwFindFcb( IrpContext->pScb, Vcb, &FileName, Dcb );
  1198. // in rare cases, NwFindFcb might return NULL instead of throwing an exception
  1199. // Raid # 432500
  1200. if (Fcb == NULL) {
  1201. DebugTrace(0, Dbg, "NwFindFcb returned NULL in CreateRemoteFile\n", 0);
  1202. Iosb.Status = STATUS_INVALID_PARAMETER;
  1203. try_return( Iosb );
  1204. }
  1205. //
  1206. // Check the share access for this file. The share access
  1207. // is updated if access is granted.
  1208. //
  1209. if (!IsTerminalServer() ||
  1210. !FlagOn( Vcb->Flags, VCB_FLAG_PRINT_QUEUE )) {
  1211. if ( Fcb->IcbCount > 0 ) {
  1212. NwAcquireSharedFcb( Fcb->NonPagedFcb, TRUE );
  1213. Iosb.Status = IoCheckShareAccess(
  1214. DesiredAccess,
  1215. ShareAccess,
  1216. FileObject,
  1217. &Fcb->ShareAccess,
  1218. TRUE );
  1219. NwReleaseFcb( Fcb->NonPagedFcb );
  1220. if ( !NT_SUCCESS( Iosb.Status ) ) {
  1221. try_return( Iosb );
  1222. }
  1223. } else {
  1224. NwAcquireExclusiveFcb( Fcb->NonPagedFcb, TRUE );
  1225. IoSetShareAccess(
  1226. DesiredAccess,
  1227. ShareAccess,
  1228. FileObject,
  1229. &Fcb->ShareAccess );
  1230. NwReleaseFcb( Fcb->NonPagedFcb );
  1231. }
  1232. SetShareAccess = TRUE;
  1233. }
  1234. //
  1235. // Now create the ICB.
  1236. //
  1237. Icb = NwCreateIcb( NW_NTC_ICB, Fcb );
  1238. Icb->FileObject = FileObject;
  1239. NwSetFileObject( FileObject, Fcb->NonPagedFcb, Icb );
  1240. #ifndef QFE_BUILD
  1241. //
  1242. // Supply a resource for the modified page write to grab when
  1243. // writing mem mapped files. We do this because it is imposed
  1244. // on us by the system, we do not require the resource for any
  1245. // real serialization.
  1246. //
  1247. // This flag should not be zeroed (nealch: May 6, 2002)
  1248. //Fcb->NonPagedFcb->Header.Flags = 0;
  1249. Fcb->NonPagedFcb->Header.Resource = NULL;
  1250. #endif
  1251. #ifdef NWFASTIO
  1252. //
  1253. // Initialize private cache map so that the i/o system will call
  1254. // our fast path.
  1255. //
  1256. FileObject->PrivateCacheMap = (PVOID)1;
  1257. #endif
  1258. IrpContext->Icb = Icb;
  1259. //
  1260. // Allocate an 8 bit PID for this ICB. Use different thread so
  1261. // each Wow program gets its own id. This is because if the same id
  1262. // has locks using two handles and closes just one of them the locks
  1263. // on that handle are not discarded.
  1264. //
  1265. Iosb.Status = NwMapPid(IrpContext->pNpScb, (ULONG_PTR)PsGetCurrentThread(), &Icb->Pid );
  1266. if ( !NT_SUCCESS( Iosb.Status ) ) {
  1267. try_return( Iosb.Status );
  1268. }
  1269. //
  1270. // Try to figure out what it is we're expected to open.
  1271. //
  1272. Iosb.Status = STATUS_SUCCESS;
  1273. if ( FlagOn( Vcb->Flags, VCB_FLAG_PRINT_QUEUE ) ) {
  1274. //
  1275. // Opening a print queue job.
  1276. //
  1277. Iosb = CreatePrintJob( IrpContext, Vcb, Icb, DriveName );
  1278. } else if ( DirectoryFile ||
  1279. ( Fcb->State == FCB_STATE_OPENED &&
  1280. Fcb->NodeTypeCode == NW_NTC_DCB ) ) {
  1281. //
  1282. // Opening a directory.
  1283. //
  1284. MayBeADirectory = TRUE;
  1285. switch ( CreateDisposition ) {
  1286. case FILE_OPEN:
  1287. Iosb = ChangeDirectory( IrpContext, Vcb, Icb );
  1288. break;
  1289. case FILE_CREATE:
  1290. Iosb = CreateDir( IrpContext, Vcb, Icb );
  1291. break;
  1292. case FILE_OPEN_IF:
  1293. Iosb.Status = FileOrDirectoryExists( IrpContext,
  1294. Vcb,
  1295. Icb,
  1296. &Icb->SuperType.Fcb->RelativeFileName,
  1297. &IsAFile );
  1298. //
  1299. // If the opener specified a directory, fail this request
  1300. // if the object is a file.
  1301. //
  1302. if ( NT_SUCCESS( Iosb.Status ) && IsAFile ) {
  1303. Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
  1304. } else if ( !NT_SUCCESS( Iosb.Status )) {
  1305. Iosb = CreateDir( IrpContext, Vcb, Icb );
  1306. }
  1307. break;
  1308. case FILE_SUPERSEDE:
  1309. case FILE_OVERWRITE:
  1310. case FILE_OVERWRITE_IF:
  1311. Iosb.Status = STATUS_INVALID_PARAMETER;
  1312. break;
  1313. default:
  1314. KeBugCheck( RDR_FILE_SYSTEM );
  1315. }
  1316. } else {
  1317. SearchFlags = NtAttributesToNwAttributes( FileAttributes );
  1318. ShareFlags = NtToNwShareFlags( DesiredAccess, ShareAccess );
  1319. IsAFile = NonDirectoryFile ||
  1320. (Fcb->State == FCB_STATE_OPENED &&
  1321. Fcb->NodeTypeCode == NW_NTC_FCB );
  1322. //
  1323. // Assume we are opening a file. If that fails, and it makes
  1324. // sense try to open a directory.
  1325. //
  1326. switch ( CreateDisposition ) {
  1327. case FILE_OPEN:
  1328. //
  1329. // If the disposition is FILE_OPEN try to avoid an unneeded
  1330. // open, for some desired access types.
  1331. //
  1332. switch ( DesiredAccess & ~SYNCHRONIZE ) {
  1333. case FILE_WRITE_ATTRIBUTES:
  1334. case FILE_READ_ATTRIBUTES:
  1335. case DELETE:
  1336. Iosb.Status = FileOrDirectoryExists(
  1337. IrpContext,
  1338. Vcb,
  1339. Icb,
  1340. &Icb->SuperType.Fcb->RelativeFileName,
  1341. &IsAFile );
  1342. if ( !IsAFile) {
  1343. MayBeADirectory = TRUE;
  1344. }
  1345. //
  1346. // Fail open of read only file for delete access,
  1347. // since the netware server won't fail the delete.
  1348. //
  1349. if ( NT_SUCCESS( Iosb.Status ) &&
  1350. CreateDisposition == DELETE &&
  1351. FlagOn( Icb->NpFcb->Attributes, NW_ATTRIBUTE_READ_ONLY ) ) {
  1352. Iosb.Status = STATUS_ACCESS_DENIED;
  1353. }
  1354. if ( ( Iosb.Status == STATUS_OBJECT_NAME_NOT_FOUND ) &&
  1355. ( (DesiredAccess & ~SYNCHRONIZE) == DELETE ) ) {
  1356. //
  1357. // we may not have scan rights. fake the return as OK.
  1358. // NW allows the delete without scan rights.
  1359. //
  1360. Iosb.Status = STATUS_SUCCESS;
  1361. }
  1362. break;
  1363. default:
  1364. Iosb = OpenFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags );
  1365. if ( ( Iosb.Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  1366. Iosb.Status == STATUS_FILE_IS_A_DIRECTORY )
  1367. && !IsAFile) {
  1368. //
  1369. // Opener didn't specify file or directory, and open
  1370. // file failed. So try open directory.
  1371. //
  1372. Iosb = ChangeDirectory( IrpContext, Vcb, Icb );
  1373. MayBeADirectory = TRUE;
  1374. } else if ( (Iosb.Status == STATUS_SHARING_VIOLATION) &&
  1375. ((ShareFlags == (NW_OPEN_FOR_READ | NW_DENY_WRITE)) ||
  1376. (ShareFlags == (NW_OPEN_FOR_READ)))) {
  1377. //
  1378. // if the file was already open exclusive (eg. GENERIC_EXECUTE)
  1379. // then a debugger opening it again for read will fail with
  1380. // sharing violation. In this case, we will try open exclusive
  1381. // again to see if that passes.
  1382. //
  1383. ShareFlags |= NW_OPEN_EXCLUSIVE ;
  1384. ShareFlags &= ~(NW_DENY_WRITE | NW_DENY_READ);
  1385. Iosb = OpenFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags );
  1386. }
  1387. break;
  1388. }
  1389. break;
  1390. case FILE_CREATE:
  1391. Iosb = CreateNewFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags );
  1392. break;
  1393. case FILE_OPEN_IF:
  1394. Iosb.Status = FileOrDirectoryExists( IrpContext,
  1395. Vcb,
  1396. Icb,
  1397. &Icb->SuperType.Fcb->RelativeFileName,
  1398. &IsAFile );
  1399. if ( NT_SUCCESS( Iosb.Status ) ) {
  1400. Iosb = OpenFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags );
  1401. } else {
  1402. Iosb = CreateNewFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags );
  1403. }
  1404. if ( !NT_SUCCESS( Iosb.Status ) && !IsAFile) {
  1405. //
  1406. // Opener didn't specify file or directory, and open
  1407. // file and create new file both failed. So try open
  1408. // or create directory.
  1409. //
  1410. MayBeADirectory = TRUE;
  1411. Iosb.Status = FileOrDirectoryExists(
  1412. IrpContext,
  1413. Vcb,
  1414. Icb,
  1415. &Icb->SuperType.Fcb->RelativeFileName,
  1416. &IsAFile);
  1417. if ( NT_SUCCESS( Iosb.Status ) ) {
  1418. Iosb.Information = FILE_OPENED;
  1419. } else {
  1420. Iosb = CreateDir( IrpContext, Vcb, Icb );
  1421. }
  1422. }
  1423. break;
  1424. //
  1425. // None of the below make sense for directories so if the
  1426. // file operation fails, just return the failure status
  1427. // to the user.
  1428. //
  1429. case FILE_SUPERSEDE:
  1430. case FILE_OVERWRITE_IF:
  1431. //
  1432. // Actually, if Overwrite is chosen, we are supposed to
  1433. // get the attributes for a file and OR them with the
  1434. // new attributes.
  1435. //
  1436. Iosb = CreateOrOverwriteFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags, FALSE );
  1437. break;
  1438. case FILE_OVERWRITE:
  1439. Iosb.Status = FileOrDirectoryExists(
  1440. IrpContext,
  1441. Vcb,
  1442. Icb,
  1443. &Icb->SuperType.Fcb->RelativeFileName,
  1444. &IsAFile );
  1445. if ( NT_SUCCESS( Iosb.Status ) ) {
  1446. Iosb = CreateOrOverwriteFile( IrpContext, Vcb, Icb, SearchFlags, ShareFlags, FALSE );
  1447. }
  1448. break;
  1449. default:
  1450. KeBugCheck( RDR_FILE_SYSTEM );
  1451. }
  1452. }
  1453. try_exit: NOTHING;
  1454. } finally {
  1455. if ( Vcb != NULL ) {
  1456. NwDereferenceVcb( Vcb, IrpContext, FALSE );
  1457. }
  1458. if ( MadeUidNdsName ) {
  1459. FREE_POOL( IrpContext->Specific.Create.UidConnectName.Buffer );
  1460. }
  1461. if ( AbnormalTermination() || !NT_SUCCESS( Iosb.Status ) ) {
  1462. //
  1463. // Remove the share access if necessary
  1464. //
  1465. if ( SetShareAccess ) {
  1466. NwAcquireExclusiveFcb( Fcb->NonPagedFcb, TRUE );
  1467. IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
  1468. NwReleaseFcb( Fcb->NonPagedFcb );
  1469. }
  1470. //
  1471. // Failed to create
  1472. //
  1473. if ( Icb != NULL ) {
  1474. if ( Icb->Pid != 0 ) {
  1475. NwUnmapPid(IrpContext->pNpScb, Icb->Pid, NULL );
  1476. }
  1477. //
  1478. // dfergus 19 Apr 2001 #330484
  1479. //
  1480. NwDeleteIcb( NULL, Icb );
  1481. // added to fix 330484
  1482. IrpContext->Icb = NULL;
  1483. //
  1484. // if the operation failed, make sure we NULL out the
  1485. // FsContext field (nealch)
  1486. //
  1487. NwSetFileObject( FileObject, NULL, NULL );
  1488. }
  1489. //
  1490. // If this was a tree connect, derefence the extra
  1491. // reference on the VCB.
  1492. //
  1493. if ( CreateTreeConnection && !DeleteOnClose ) {
  1494. if ( Vcb != NULL ) {
  1495. NwDereferenceVcb( Vcb, IrpContext, FALSE );
  1496. }
  1497. }
  1498. NwDequeueIrpContext( IrpContext, FALSE );
  1499. } else {
  1500. Icb->State = ICB_STATE_OPENED;
  1501. if ( Fcb->State == FCB_STATE_OPEN_PENDING ) {
  1502. Fcb->State = FCB_STATE_OPENED;
  1503. }
  1504. if ( DeleteOnClose && !CreateTreeConnection ) {
  1505. SetFlag( Fcb->Flags, FCB_FLAGS_DELETE_ON_CLOSE );
  1506. }
  1507. FileObject->SectionObjectPointer = &Fcb->NonPagedFcb->SegmentObject;
  1508. if ( MayBeADirectory ) {
  1509. //
  1510. // We successfully opened the file as a directory.
  1511. // If the DCB is newly created, it will be marked
  1512. // type FCB, update it.
  1513. //
  1514. Fcb->NodeTypeCode = NW_NTC_DCB;
  1515. }
  1516. NwDequeueIrpContext( IrpContext, FALSE );
  1517. }
  1518. if ( OwnOpenLock ) {
  1519. NwReleaseOpenLock( );
  1520. }
  1521. }
  1522. return( Iosb );
  1523. }
  1524. IO_STATUS_BLOCK
  1525. ChangeDirectory(
  1526. PIRP_CONTEXT IrpContext,
  1527. PVCB Vcb,
  1528. PICB Icb
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. This routines sets the directory for a remote drive.
  1533. Arguments:
  1534. IrpContext - Supplies all the information
  1535. Vcb - A pointer to the VCB for the remote drive.
  1536. Icb - A pointer to the file we are opening.
  1537. Return Value:
  1538. IO_STATUS_BLOCK - Status of operation
  1539. --*/
  1540. {
  1541. IO_STATUS_BLOCK Iosb;
  1542. PFCB Fcb;
  1543. BYTE Attributes;
  1544. BOOLEAN FirstTime = TRUE;
  1545. PAGED_CODE();
  1546. //
  1547. // No need to send a packet if we are opening the root of the volume.
  1548. //
  1549. if ( Icb->SuperType.Fcb->RelativeFileName.Length == 0 ) {
  1550. Iosb.Status = STATUS_SUCCESS;
  1551. Iosb.Information = FILE_OPENED;
  1552. return( Iosb );
  1553. }
  1554. Retry:
  1555. if ( !BooleanFlagOn( Icb->SuperType.Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  1556. Iosb.Status = ExchangeWithWait (
  1557. IrpContext,
  1558. SynchronousResponseCallback,
  1559. "FwbbJ",
  1560. NCP_SEARCH_FILE,
  1561. -1,
  1562. Vcb->Specific.Disk.Handle,
  1563. SEARCH_ALL_DIRECTORIES,
  1564. &Icb->SuperType.Fcb->RelativeFileName );
  1565. if ( NT_SUCCESS( Iosb.Status ) ) {
  1566. Iosb.Status = ParseResponse(
  1567. IrpContext,
  1568. IrpContext->rsp,
  1569. IrpContext->ResponseLength,
  1570. "N==_b",
  1571. 14,
  1572. &Attributes );
  1573. }
  1574. } else {
  1575. Iosb.Status = ExchangeWithWait (
  1576. IrpContext,
  1577. SynchronousResponseCallback,
  1578. "LbbWDbDbC",
  1579. NCP_LFN_GET_INFO,
  1580. Vcb->Specific.Disk.LongNameSpace,
  1581. Vcb->Specific.Disk.LongNameSpace,
  1582. SEARCH_ALL_DIRECTORIES,
  1583. LFN_FLAG_INFO_ATTRIBUTES |
  1584. LFN_FLAG_INFO_MODIFY_TIME,
  1585. Vcb->Specific.Disk.VolumeNumber,
  1586. Vcb->Specific.Disk.Handle,
  1587. 0,
  1588. &Icb->SuperType.Fcb->RelativeFileName );
  1589. if ( NT_SUCCESS( Iosb.Status ) ) {
  1590. Iosb.Status = ParseResponse(
  1591. IrpContext,
  1592. IrpContext->rsp,
  1593. IrpContext->ResponseLength,
  1594. "N_b",
  1595. 4,
  1596. &Attributes );
  1597. }
  1598. //
  1599. // Unfortunately, this succeeds even if the file in question
  1600. // is not a directory.
  1601. //
  1602. if ( NT_SUCCESS( Iosb.Status ) &&
  1603. ( !FlagOn( Attributes, NW_ATTRIBUTE_DIRECTORY ) ) ) {
  1604. Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
  1605. }
  1606. }
  1607. if ((Iosb.Status == STATUS_INVALID_HANDLE) &&
  1608. (FirstTime)) {
  1609. //
  1610. // Check to see if Volume handle is invalid. Caused when volume
  1611. // is unmounted and then remounted.
  1612. //
  1613. FirstTime = FALSE;
  1614. NwReopenVcbHandle( IrpContext, Vcb );
  1615. goto Retry;
  1616. }
  1617. Fcb = Icb->SuperType.Fcb;
  1618. Fcb->NonPagedFcb->Attributes = (UCHAR)Attributes;
  1619. SetFlag( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID );
  1620. //
  1621. // Set information field assuming success. It will be ignored
  1622. // if the NCP failed.
  1623. //
  1624. Iosb.Information = FILE_OPENED;
  1625. if ( Iosb.Status == STATUS_UNSUCCESSFUL ) {
  1626. Iosb.Status = STATUS_OBJECT_PATH_NOT_FOUND;
  1627. }
  1628. return( Iosb );
  1629. }
  1630. IO_STATUS_BLOCK
  1631. CreateDir(
  1632. PIRP_CONTEXT IrpContext,
  1633. PVCB Vcb,
  1634. PICB Icb
  1635. )
  1636. /*++
  1637. Routine Description:
  1638. This routines create a new directory.
  1639. Arguments:
  1640. IrpContext - Supplies all the information
  1641. Vcb - A pointer to the VCB for the remote drive.
  1642. Return Value:
  1643. IO_STATUS_BLOCK - Status of operation
  1644. --*/
  1645. {
  1646. IO_STATUS_BLOCK Iosb;
  1647. PAGED_CODE();
  1648. if ( Icb->SuperType.Fcb->RelativeFileName.Length == 0 ) {
  1649. Iosb.Status = STATUS_ACCESS_DENIED;
  1650. return( Iosb );
  1651. }
  1652. if ( !BooleanFlagOn( Icb->SuperType.Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  1653. if (!IsFatNameValid(&Icb->SuperType.Fcb->RelativeFileName)) {
  1654. Iosb.Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
  1655. return( Iosb );
  1656. }
  1657. Iosb.Status = ExchangeWithWait (
  1658. IrpContext,
  1659. SynchronousResponseCallback,
  1660. "SbbJ",
  1661. NCP_DIR_FUNCTION, NCP_CREATE_DIRECTORY,
  1662. Vcb->Specific.Disk.Handle,
  1663. 0xFF,
  1664. &Icb->SuperType.Fcb->RelativeFileName );
  1665. } else {
  1666. Iosb.Status = ExchangeWithWait(
  1667. IrpContext,
  1668. SynchronousResponseCallback,
  1669. "LbbWDDWbDbC",
  1670. NCP_LFN_OPEN_CREATE,
  1671. Vcb->Specific.Disk.LongNameSpace,
  1672. LFN_FLAG_OM_CREATE,
  1673. 0, // Search Flags,
  1674. 0, // Return Info Mask
  1675. NW_ATTRIBUTE_DIRECTORY,
  1676. 0x00ff, // Desired access
  1677. Vcb->Specific.Disk.VolumeNumber,
  1678. Vcb->Specific.Disk.Handle,
  1679. 0, // Short directory flag
  1680. &Icb->SuperType.Fcb->RelativeFileName );
  1681. }
  1682. if ( NT_SUCCESS( Iosb.Status ) ) {
  1683. Iosb.Status = ParseResponse(
  1684. IrpContext,
  1685. IrpContext->rsp,
  1686. IrpContext->ResponseLength,
  1687. "N" );
  1688. }
  1689. //
  1690. // Set information field assuming success. It will be ignored
  1691. // if the NCP failed.
  1692. //
  1693. Iosb.Information = FILE_CREATED;
  1694. if ( Iosb.Status == STATUS_UNSUCCESSFUL ) {
  1695. Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
  1696. }
  1697. return( Iosb );
  1698. }
  1699. NTSTATUS
  1700. FileOrDirectoryExists(
  1701. IN PIRP_CONTEXT IrpContext,
  1702. IN PVCB Vcb,
  1703. IN PICB Icb OPTIONAL,
  1704. PUNICODE_STRING Name,
  1705. OUT PBOOLEAN IsAFile
  1706. )
  1707. /*++
  1708. Routine Description:
  1709. This routines looks to see if a file or directory exists.
  1710. Arguments:
  1711. IrpContext - Supplies allx the information
  1712. Vcb - A pointer to the VCB for the remote drive.
  1713. Icb - A pointer to the ICB for the file we are looking for.
  1714. Name - Fully qualified name.
  1715. IsAFile - Returns TRUE is the found file is a file, FALSE if it is
  1716. a directory. Return nothing if the function returns FALSE.
  1717. Return Value:
  1718. IO_STATUS_BLOCK - Status of operation
  1719. --*/
  1720. {
  1721. ULONG Attributes;
  1722. ULONG FileSize;
  1723. USHORT LastModifiedDate;
  1724. USHORT LastModifiedTime;
  1725. USHORT CreationDate;
  1726. USHORT CreationTime = DEFAULT_TIME;
  1727. USHORT LastAccessDate;
  1728. NTSTATUS Status;
  1729. PFCB Fcb;
  1730. BOOLEAN FirstTime = TRUE;
  1731. PAGED_CODE();
  1732. //
  1733. // No need to send a packet if we are searching for the root of the volume.
  1734. //
  1735. if ( Name->Length == 0 ) {
  1736. *IsAFile = FALSE;
  1737. return( STATUS_SUCCESS );
  1738. }
  1739. //
  1740. // Decide how to handle this request. If we have an ICB, use the FCB
  1741. // to determine the file name type, otherwise we have to make the
  1742. // decision here.
  1743. //
  1744. if ( Icb != NULL &&
  1745. !BooleanFlagOn( Icb->SuperType.Fcb->Flags, FCB_FLAGS_LONG_NAME ) ||
  1746. Vcb->Specific.Disk.LongNameSpace == LFN_NO_OS2_NAME_SPACE ||
  1747. IsFatNameValid( Name ) ) {
  1748. Retry:
  1749. //
  1750. // First try a file
  1751. //
  1752. IrpContext->ResponseLength = 0;
  1753. Status = ExchangeWithWait (
  1754. IrpContext,
  1755. SynchronousResponseCallback,
  1756. "FwbbJ",
  1757. NCP_SEARCH_FILE,
  1758. -1,
  1759. Vcb->Specific.Disk.Handle,
  1760. SEARCH_ALL_FILES,
  1761. Name );
  1762. if ( NT_SUCCESS( Status ) ) {
  1763. Status = ParseResponse(
  1764. IrpContext,
  1765. IrpContext->rsp,
  1766. IrpContext->ResponseLength,
  1767. "N==_b-dwwww",
  1768. 14,
  1769. &Attributes,
  1770. &FileSize,
  1771. &CreationDate,
  1772. &LastAccessDate,
  1773. &LastModifiedDate,
  1774. &LastModifiedTime );
  1775. }
  1776. if ((Status == STATUS_INVALID_HANDLE) &&
  1777. (FirstTime)) {
  1778. //
  1779. // Check to see if Volume handle is invalid. Caused when volume
  1780. // is unmounted and then remounted.
  1781. //
  1782. FirstTime = FALSE;
  1783. NwReopenVcbHandle( IrpContext, Vcb );
  1784. goto Retry;
  1785. }
  1786. if ( Status == STATUS_UNSUCCESSFUL ) {
  1787. //
  1788. // Not a file, Is it a directory?
  1789. //
  1790. Status = ExchangeWithWait (
  1791. IrpContext,
  1792. SynchronousResponseCallback,
  1793. "FwbbJ",
  1794. NCP_SEARCH_FILE,
  1795. -1,
  1796. Vcb->Specific.Disk.Handle,
  1797. SEARCH_ALL_DIRECTORIES,
  1798. Name );
  1799. if ( NT_SUCCESS( Status ) ) {
  1800. Status = ParseResponse(
  1801. IrpContext,
  1802. IrpContext->rsp,
  1803. IrpContext->ResponseLength,
  1804. "N==_b",
  1805. 14,
  1806. &Attributes );
  1807. }
  1808. //
  1809. // If the exchange or ParseResponse fails then exit with not found
  1810. //
  1811. if ( !NT_SUCCESS( Status ) ) {
  1812. return( STATUS_OBJECT_NAME_NOT_FOUND );
  1813. }
  1814. *IsAFile = FALSE;
  1815. ASSERT( (Attributes & NW_ATTRIBUTE_DIRECTORY) != 0 );
  1816. } else {
  1817. if ( Status == STATUS_UNEXPECTED_NETWORK_ERROR &&
  1818. IrpContext->ResponseLength >= sizeof( NCP_RESPONSE ) ) {
  1819. //
  1820. // Work-around for netware bug. If netware returns short
  1821. // packet, just return success. We exit prematurely
  1822. // because we have no attributes to record.
  1823. //
  1824. Icb = NULL;
  1825. *IsAFile = TRUE;
  1826. return ( STATUS_SUCCESS );
  1827. }
  1828. if ( !NT_SUCCESS( Status ) ) {
  1829. return( Status );
  1830. }
  1831. *IsAFile = TRUE;
  1832. ASSERT( ( Attributes & NW_ATTRIBUTE_DIRECTORY ) == 0 );
  1833. }
  1834. } else {
  1835. Status = ExchangeWithWait (
  1836. IrpContext,
  1837. SynchronousResponseCallback,
  1838. "LbbWDbDbC",
  1839. NCP_LFN_GET_INFO,
  1840. Vcb->Specific.Disk.LongNameSpace,
  1841. Vcb->Specific.Disk.LongNameSpace,
  1842. SEARCH_ALL_DIRECTORIES,
  1843. LFN_FLAG_INFO_ATTRIBUTES |
  1844. LFN_FLAG_INFO_FILE_SIZE |
  1845. LFN_FLAG_INFO_MODIFY_TIME |
  1846. LFN_FLAG_INFO_CREATION_TIME,
  1847. Vcb->Specific.Disk.VolumeNumber,
  1848. Vcb->Specific.Disk.Handle,
  1849. 0,
  1850. Name );
  1851. if ( NT_SUCCESS( Status ) ) {
  1852. Status = ParseResponse(
  1853. IrpContext,
  1854. IrpContext->rsp,
  1855. IrpContext->ResponseLength,
  1856. "N_e=e_xx_xx_x",
  1857. 4,
  1858. &Attributes,
  1859. &FileSize,
  1860. 6,
  1861. &CreationTime,
  1862. &CreationDate,
  1863. 4,
  1864. &LastModifiedTime,
  1865. &LastModifiedDate,
  1866. 4,
  1867. &LastAccessDate );
  1868. }
  1869. //
  1870. // If the exchange or ParseResponse fails then exit with not found
  1871. //
  1872. if ( !NT_SUCCESS( Status ) ) {
  1873. return( STATUS_OBJECT_NAME_NOT_FOUND );
  1874. }
  1875. if ( Attributes & NW_ATTRIBUTE_DIRECTORY) {
  1876. *IsAFile = FALSE;
  1877. } else {
  1878. *IsAFile = TRUE;
  1879. }
  1880. }
  1881. //
  1882. // If the caller supplied an ICB, update the FCB attributes.
  1883. // We'll use this info if the caller does a query attributes
  1884. // on the ICB.
  1885. //
  1886. if ( Icb != NULL && *IsAFile ) {
  1887. Fcb = Icb->SuperType.Fcb;
  1888. ASSERT( Fcb->NodeTypeCode == NW_NTC_FCB );
  1889. Fcb->NonPagedFcb->Attributes = (UCHAR)Attributes;
  1890. Fcb->NonPagedFcb->Header.FileSize.QuadPart = FileSize;
  1891. Fcb->LastModifiedDate = LastModifiedDate;
  1892. Fcb->LastModifiedTime = LastModifiedTime;
  1893. Fcb->CreationTime = CreationTime;
  1894. Fcb->CreationDate = CreationDate;
  1895. Fcb->LastAccessDate = LastAccessDate;
  1896. DebugTrace( 0, Dbg, "Attributes -> %08lx\n", Fcb->NonPagedFcb->Attributes );
  1897. DebugTrace( 0, Dbg, "FileSize.Low-> %08lx\n", Fcb->NonPagedFcb->Header.FileSize.LowPart );
  1898. DebugTrace( 0, Dbg, "ModifiedDate-> %08lx\n", Fcb->LastModifiedDate );
  1899. DebugTrace( 0, Dbg, "ModifiedTime-> %08lx\n", Fcb->LastModifiedTime );
  1900. DebugTrace( 0, Dbg, "CreationTime-> %08lx\n", Fcb->CreationTime );
  1901. DebugTrace( 0, Dbg, "CreationDate-> %08lx\n", Fcb->CreationDate );
  1902. DebugTrace( 0, Dbg, "LastAccDate -> %08lx\n", Fcb->LastAccessDate );
  1903. SetFlag( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID );
  1904. }
  1905. return( STATUS_SUCCESS );
  1906. }
  1907. IO_STATUS_BLOCK
  1908. OpenFile(
  1909. IN PIRP_CONTEXT IrpContext,
  1910. IN PVCB Vcb,
  1911. IN PICB Icb,
  1912. IN BYTE Attributes,
  1913. IN BYTE OpenFlags
  1914. )
  1915. /*++
  1916. Routine Description:
  1917. This routines sets opens a file on a netware server. It fails if
  1918. the file does not exist.
  1919. Arguments:
  1920. IrpContext - Supplies all the information
  1921. Vcb - A pointer to the VCB for the remote drive.
  1922. Icb - A pointer to the ICB we are opening.
  1923. Attributes - Open attributes.
  1924. OpenFlags - Open mode and sharing mode flags.
  1925. Return Value:
  1926. IO_STATUS_BLOCK - Status of operation
  1927. --*/
  1928. {
  1929. IO_STATUS_BLOCK Iosb;
  1930. PFCB Fcb;
  1931. PAGED_CODE();
  1932. //
  1933. // No need to send a packet if we are trying to open the root of
  1934. // the volume as a file.
  1935. //
  1936. if ( Icb->SuperType.Fcb->RelativeFileName.Length == 0 ) {
  1937. Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
  1938. return( Iosb );
  1939. }
  1940. Fcb = Icb->SuperType.Fcb;
  1941. ASSERT( NodeType( Fcb ) == NW_NTC_FCB );
  1942. //
  1943. // Send the open request and wait for the response.
  1944. //
  1945. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  1946. Iosb.Status = ExchangeWithWait (
  1947. IrpContext,
  1948. SynchronousResponseCallback,
  1949. "FbbbJ",
  1950. NCP_OPEN_FILE,
  1951. Vcb->Specific.Disk.Handle,
  1952. SEARCH_ALL_FILES,
  1953. OpenFlags,
  1954. &Icb->SuperType.Fcb->RelativeFileName );
  1955. if ( ( ReadExecOnlyFiles ) &&
  1956. ( !NT_SUCCESS( Iosb.Status ) ) ) {
  1957. //
  1958. // Retry the open with the appropriate flags for
  1959. // execute only files.
  1960. //
  1961. Iosb.Status = ExchangeWithWait (
  1962. IrpContext,
  1963. SynchronousResponseCallback,
  1964. "FbbbJ",
  1965. NCP_OPEN_FILE,
  1966. Vcb->Specific.Disk.Handle,
  1967. SEARCH_EXEC_ONLY_FILES,
  1968. OpenFlags,
  1969. &Icb->SuperType.Fcb->RelativeFileName );
  1970. }
  1971. if ( NT_SUCCESS( Iosb.Status ) ) {
  1972. Iosb.Status = ParseResponse(
  1973. IrpContext,
  1974. IrpContext->rsp,
  1975. IrpContext->ResponseLength,
  1976. "Nr=_b-dwwww",
  1977. Icb->Handle,
  1978. sizeof( Icb->Handle ),
  1979. 14,
  1980. &Fcb->NonPagedFcb->Attributes,
  1981. &Fcb->NonPagedFcb->Header.FileSize,
  1982. &Fcb->CreationDate,
  1983. &Fcb->LastAccessDate,
  1984. &Fcb->LastModifiedDate,
  1985. &Fcb->LastModifiedTime );
  1986. Fcb->CreationTime = DEFAULT_TIME;
  1987. }
  1988. } else {
  1989. Iosb.Status = ExchangeWithWait (
  1990. IrpContext,
  1991. SynchronousResponseCallback,
  1992. "LbbWDDWbDbC",
  1993. NCP_LFN_OPEN_CREATE,
  1994. Vcb->Specific.Disk.LongNameSpace,
  1995. LFN_FLAG_OM_OPEN,
  1996. NW_ATTRIBUTE_HIDDEN | NW_ATTRIBUTE_SYSTEM, // Search Flags,
  1997. LFN_FLAG_INFO_ATTRIBUTES |
  1998. LFN_FLAG_INFO_FILE_SIZE |
  1999. LFN_FLAG_INFO_MODIFY_TIME |
  2000. LFN_FLAG_INFO_CREATION_TIME,
  2001. 0, // Create attributes
  2002. OpenFlags, // Desired access
  2003. Vcb->Specific.Disk.VolumeNumber,
  2004. Vcb->Specific.Disk.Handle,
  2005. 0, // Short directory flag
  2006. &Icb->SuperType.Fcb->RelativeFileName );
  2007. if ( ( ReadExecOnlyFiles ) &&
  2008. ( !NT_SUCCESS( Iosb.Status ) ) ) {
  2009. Iosb.Status = ExchangeWithWait (
  2010. IrpContext,
  2011. SynchronousResponseCallback,
  2012. "LbbWDDWbDbC",
  2013. NCP_LFN_OPEN_CREATE,
  2014. Vcb->Specific.Disk.LongNameSpace,
  2015. LFN_FLAG_OM_OPEN,
  2016. NW_ATTRIBUTE_EXEC_ONLY,
  2017. LFN_FLAG_INFO_ATTRIBUTES |
  2018. LFN_FLAG_INFO_FILE_SIZE |
  2019. LFN_FLAG_INFO_MODIFY_TIME |
  2020. LFN_FLAG_INFO_CREATION_TIME,
  2021. 0, // Create attributes
  2022. OpenFlags, // Desired access
  2023. Vcb->Specific.Disk.VolumeNumber,
  2024. Vcb->Specific.Disk.Handle,
  2025. 0, // Short directory flag
  2026. &Icb->SuperType.Fcb->RelativeFileName );
  2027. }
  2028. if ( NT_SUCCESS( Iosb.Status ) ) {
  2029. Iosb.Status = ParseResponse(
  2030. IrpContext,
  2031. IrpContext->rsp,
  2032. IrpContext->ResponseLength,
  2033. "Ne_e=e_xx_xx_x",
  2034. &Icb->Handle[2],
  2035. 6,
  2036. &Fcb->NonPagedFcb->Attributes,
  2037. &Fcb->NonPagedFcb->Header.FileSize,
  2038. 6,
  2039. &Fcb->CreationTime,
  2040. &Fcb->CreationDate,
  2041. 4,
  2042. &Fcb->LastModifiedTime,
  2043. &Fcb->LastModifiedDate,
  2044. 4,
  2045. &Fcb->LastAccessDate );
  2046. }
  2047. }
  2048. if ( NT_SUCCESS( Iosb.Status ) ) {
  2049. //
  2050. // NT does not allow you to open a read only file for write access.
  2051. // Netware does. To fake NT semantics, check to see if we should
  2052. // fail the open that the netware server just succeeded.
  2053. //
  2054. if ( ( Fcb->NonPagedFcb->Attributes & NW_ATTRIBUTE_READ_ONLY ) &&
  2055. ( OpenFlags & NW_OPEN_FOR_WRITE ) ) {
  2056. CloseFile( IrpContext, Icb );
  2057. Iosb.Status = STATUS_ACCESS_DENIED;
  2058. }
  2059. SetFlag( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID );
  2060. Icb->HasRemoteHandle = TRUE;
  2061. DebugTrace( 0, Dbg, "Attributes -> %08lx\n", Fcb->NonPagedFcb->Attributes );
  2062. DebugTrace( 0, Dbg, "FileSize.Low-> %08lx\n", Fcb->NonPagedFcb->Header.FileSize.LowPart );
  2063. DebugTrace( 0, Dbg, "ModifiedDate-> %08lx\n", Fcb->LastModifiedDate );
  2064. DebugTrace( 0, Dbg, "ModifiedTime-> %08lx\n", Fcb->LastModifiedTime );
  2065. DebugTrace( 0, Dbg, "CreationDate-> %08lx\n", Fcb->CreationDate );
  2066. DebugTrace( 0, Dbg, "CreationTime-> %08lx\n", Fcb->CreationTime );
  2067. DebugTrace( 0, Dbg, "LastAccDate -> %08lx\n", Fcb->LastAccessDate );
  2068. }
  2069. //
  2070. // Set information field assuming success. It will be ignored
  2071. // if the NCP failed.
  2072. //
  2073. Iosb.Information = FILE_OPENED;
  2074. if ( Iosb.Status == STATUS_UNSUCCESSFUL ) {
  2075. Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND;
  2076. }
  2077. return( Iosb );
  2078. }
  2079. IO_STATUS_BLOCK
  2080. CreateNewFile(
  2081. IN PIRP_CONTEXT IrpContext,
  2082. IN PVCB Vcb,
  2083. IN PICB Icb,
  2084. IN BYTE CreateAttributes,
  2085. IN BYTE OpenFlags
  2086. )
  2087. /*++
  2088. Routine Description:
  2089. This routines creates a new file on a netware server. It fails
  2090. if the file exists.
  2091. Arguments:
  2092. IrpContext - Supplies all the information
  2093. Vcb - A pointer to the VCB for the remote drive.
  2094. Icb - A pointer to the ICB we are opening.
  2095. CreateAttributes - Create attributes.
  2096. OpenFlags - Open mode and sharing mode flags.
  2097. Return Value:
  2098. IO_STATUS_BLOCK - Status of operation
  2099. --*/
  2100. {
  2101. IO_STATUS_BLOCK Iosb;
  2102. PFCB Fcb;
  2103. UCHAR DelayedAttributes;
  2104. BOOLEAN CloseAndReopen;
  2105. PAGED_CODE();
  2106. //
  2107. // If the user opens the file for shared access, then we will need to
  2108. // create the file close, then reopen it (since we have no NCP to say
  2109. // create with shared access). If the file is being created read-only,
  2110. // and the creator requests write access then we pull the additional
  2111. // trick of creating the file without the read-only, and set it later,
  2112. // so that the second open can succeed.
  2113. //
  2114. CloseAndReopen = FALSE;
  2115. DelayedAttributes = 0;
  2116. if ( OpenFlags != NW_OPEN_EXCLUSIVE ) {
  2117. CloseAndReopen = TRUE;
  2118. if ( ( CreateAttributes & NW_ATTRIBUTE_READ_ONLY ) &&
  2119. ( OpenFlags & NW_OPEN_FOR_WRITE ) ) {
  2120. DelayedAttributes = CreateAttributes;
  2121. CreateAttributes = 0;
  2122. }
  2123. }
  2124. //
  2125. // Send the create request and wait for the response.
  2126. //
  2127. Fcb = Icb->SuperType.Fcb;
  2128. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  2129. if (!IsFatNameValid(&Icb->SuperType.Fcb->RelativeFileName)) {
  2130. Iosb.Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
  2131. return( Iosb );
  2132. }
  2133. Iosb.Status = ExchangeWithWait (
  2134. IrpContext,
  2135. SynchronousResponseCallback,
  2136. "FbbJ", // NCP Create New File
  2137. NCP_CREATE_NEW_FILE,
  2138. Vcb->Specific.Disk.Handle,
  2139. CreateAttributes,
  2140. &Icb->SuperType.Fcb->RelativeFileName );
  2141. if ( NT_SUCCESS( Iosb.Status ) ) {
  2142. Iosb.Status = ParseResponse(
  2143. IrpContext,
  2144. IrpContext->rsp,
  2145. IrpContext->ResponseLength,
  2146. "Nr=_b-dwwww",
  2147. Icb->Handle, sizeof( Icb->Handle ),
  2148. 14,
  2149. &Fcb->NonPagedFcb->Attributes,
  2150. &Fcb->NonPagedFcb->Header.FileSize,
  2151. &Fcb->CreationDate,
  2152. &Fcb->LastAccessDate,
  2153. &Fcb->LastModifiedDate,
  2154. &Fcb->LastModifiedTime );
  2155. Fcb->CreationTime = DEFAULT_TIME;
  2156. }
  2157. } else {
  2158. Iosb.Status = ExchangeWithWait (
  2159. IrpContext,
  2160. SynchronousResponseCallback,
  2161. "LbbWDDWbDbC",
  2162. NCP_LFN_OPEN_CREATE,
  2163. Vcb->Specific.Disk.LongNameSpace,
  2164. LFN_FLAG_OM_CREATE,
  2165. 0, // Search Flags
  2166. LFN_FLAG_INFO_ATTRIBUTES |
  2167. LFN_FLAG_INFO_FILE_SIZE |
  2168. LFN_FLAG_INFO_MODIFY_TIME |
  2169. LFN_FLAG_INFO_CREATION_TIME,
  2170. CreateAttributes,
  2171. 0, // Desired access
  2172. Vcb->Specific.Disk.VolumeNumber,
  2173. Vcb->Specific.Disk.Handle,
  2174. 0, // Short directory flag
  2175. &Icb->SuperType.Fcb->RelativeFileName );
  2176. if ( NT_SUCCESS( Iosb.Status ) ) {
  2177. Iosb.Status = ParseResponse(
  2178. IrpContext,
  2179. IrpContext->rsp,
  2180. IrpContext->ResponseLength,
  2181. "Ne_e=e_xx_xx_x",
  2182. &Icb->Handle[2],
  2183. 6,
  2184. &Fcb->NonPagedFcb->Attributes,
  2185. &Fcb->NonPagedFcb->Header.FileSize,
  2186. 6,
  2187. &Fcb->CreationTime,
  2188. &Fcb->CreationDate,
  2189. 4,
  2190. &Fcb->LastModifiedTime,
  2191. &Fcb->LastModifiedDate,
  2192. 4,
  2193. &Fcb->LastAccessDate );
  2194. }
  2195. }
  2196. if ( NT_SUCCESS( Iosb.Status ) ) {
  2197. SetFlag( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID );
  2198. Icb->HasRemoteHandle = TRUE;
  2199. DebugTrace( 0, Dbg, "Attributes -> %08lx\n", Fcb->NonPagedFcb->Attributes );
  2200. DebugTrace( 0, Dbg, "FileSize.Low-> %08lx\n", Fcb->NonPagedFcb->Header.FileSize.LowPart );
  2201. DebugTrace( 0, Dbg, "ModifiedDate-> %08lx\n", Fcb->LastModifiedDate );
  2202. DebugTrace( 0, Dbg, "ModifiedTime-> %08lx\n", Fcb->LastModifiedTime );
  2203. DebugTrace( 0, Dbg, "CreationDate-> %08lx\n", Fcb->CreationDate );
  2204. DebugTrace( 0, Dbg, "CreationTime-> %08lx\n", Fcb->CreationTime );
  2205. DebugTrace( 0, Dbg, "LastAcceDate-> %08lx\n", Fcb->LastAccessDate );
  2206. }
  2207. if ( Iosb.Status == STATUS_UNSUCCESSFUL ) {
  2208. Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
  2209. }
  2210. if ( !NT_SUCCESS( Iosb.Status ) ) {
  2211. return( Iosb );
  2212. }
  2213. //
  2214. // We've created the file, and the users wants shared access to the
  2215. // file. Close the file and reopen in sharing mode.
  2216. //
  2217. if ( CloseAndReopen ) {
  2218. CloseFile( IrpContext, Icb );
  2219. Iosb = OpenFile( IrpContext, Vcb, Icb, CreateAttributes, OpenFlags );
  2220. }
  2221. //
  2222. // If we need to set attributes, do it now. Ignore errors, if any.
  2223. //
  2224. if ( DelayedAttributes != 0 ) {
  2225. ExchangeWithWait(
  2226. IrpContext,
  2227. SynchronousResponseCallback,
  2228. "FbbbU",
  2229. NCP_SET_FILE_ATTRIBUTES,
  2230. DelayedAttributes,
  2231. Fcb->Vcb->Specific.Disk.Handle,
  2232. SEARCH_ALL_FILES,
  2233. &Fcb->RelativeFileName );
  2234. }
  2235. //
  2236. // Set information field assuming success. It will be ignored
  2237. // if the NCP failed.
  2238. //
  2239. Iosb.Information = FILE_CREATED;
  2240. return( Iosb );
  2241. }
  2242. IO_STATUS_BLOCK
  2243. CreateOrOverwriteFile(
  2244. IN PIRP_CONTEXT IrpContext,
  2245. IN PVCB Vcb,
  2246. IN PICB Icb,
  2247. IN BYTE CreateAttributes,
  2248. IN BYTE OpenFlags,
  2249. IN BOOLEAN CreateOperation
  2250. )
  2251. /*++
  2252. Routine Description:
  2253. This routines creates a file on a netware server. If the file
  2254. exists it is overwritten.
  2255. Arguments:
  2256. IrpContext - Supplies all the information
  2257. Vcb - A pointer to the VCB for the remote drive.
  2258. Icb - A pointer to the ICB we are opening.
  2259. Attributes - Open attributes.
  2260. OpenFlags - Open mode and sharing mode flags.
  2261. Return Value:
  2262. IO_STATUS_BLOCK - Status of operation
  2263. --*/
  2264. {
  2265. IO_STATUS_BLOCK Iosb;
  2266. PFCB Fcb;
  2267. UCHAR DelayedAttributes;
  2268. BOOLEAN CloseAndReopen;
  2269. PAGED_CODE();
  2270. Fcb = Icb->SuperType.Fcb;
  2271. //
  2272. // Send the request and wait for the response.
  2273. //
  2274. if ( !BooleanFlagOn( Fcb->Flags, FCB_FLAGS_LONG_NAME ) ) {
  2275. if (!IsFatNameValid(&Icb->SuperType.Fcb->RelativeFileName)) {
  2276. Iosb.Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
  2277. return( Iosb );
  2278. }
  2279. //
  2280. // If the user opens the file for shared access, then we will need to
  2281. // create the file close, then reopen it (since we have no NCP to say
  2282. // create with shared access). If the file is being created read-only,
  2283. // and the creator requests write access then we pull the additional
  2284. // trick of creating the file without the read-only, and set it later,
  2285. // so that the second open can succeed.
  2286. //
  2287. if ( ( CreateAttributes & NW_ATTRIBUTE_READ_ONLY ) &&
  2288. ( OpenFlags & NW_OPEN_FOR_WRITE ) ) {
  2289. DelayedAttributes = CreateAttributes;
  2290. CreateAttributes = 0;
  2291. } else {
  2292. DelayedAttributes = 0;
  2293. }
  2294. //
  2295. // Dos namespace create always returns the file exclusive.
  2296. //
  2297. if (!FlagOn(OpenFlags, NW_OPEN_EXCLUSIVE)) {
  2298. CloseAndReopen = TRUE;
  2299. } else {
  2300. CloseAndReopen = FALSE;
  2301. }
  2302. Iosb.Status = ExchangeWithWait (
  2303. IrpContext,
  2304. SynchronousResponseCallback,
  2305. "FbbJ",
  2306. NCP_CREATE_FILE,
  2307. Vcb->Specific.Disk.Handle,
  2308. CreateAttributes,
  2309. &Icb->SuperType.Fcb->RelativeFileName );
  2310. if ( NT_SUCCESS( Iosb.Status ) ) {
  2311. Iosb.Status = ParseResponse(
  2312. IrpContext,
  2313. IrpContext->rsp,
  2314. IrpContext->ResponseLength,
  2315. "Nr=_b-dwwww",
  2316. Icb->Handle,
  2317. sizeof( Icb->Handle ),
  2318. 14,
  2319. &Fcb->NonPagedFcb->Attributes,
  2320. &Fcb->NonPagedFcb->Header.FileSize,
  2321. &Fcb->CreationDate,
  2322. &Fcb->LastAccessDate,
  2323. &Fcb->LastModifiedDate,
  2324. &Fcb->LastModifiedTime );
  2325. Fcb->CreationTime = DEFAULT_TIME;
  2326. }
  2327. //
  2328. // We've created the file, and the users wants shared access to the
  2329. // file. Close the file and reopen in sharing mode.
  2330. //
  2331. if (( NT_SUCCESS( Iosb.Status ) ) &&
  2332. ( CloseAndReopen )) {
  2333. CloseFile( IrpContext, Icb );
  2334. Iosb = OpenFile( IrpContext, Vcb, Icb, CreateAttributes, OpenFlags );
  2335. }
  2336. if ( DelayedAttributes != 0 ) {
  2337. ExchangeWithWait(
  2338. IrpContext,
  2339. SynchronousResponseCallback,
  2340. "FbbbU",
  2341. NCP_SET_FILE_ATTRIBUTES,
  2342. DelayedAttributes,
  2343. Fcb->Vcb->Specific.Disk.Handle,
  2344. SEARCH_ALL_FILES,
  2345. &Fcb->RelativeFileName );
  2346. }
  2347. } else {
  2348. Iosb.Status = ExchangeWithWait (
  2349. IrpContext,
  2350. SynchronousResponseCallback,
  2351. "LbbWDDWbDbC",
  2352. NCP_LFN_OPEN_CREATE,
  2353. Vcb->Specific.Disk.LongNameSpace,
  2354. LFN_FLAG_OM_OVERWRITE,
  2355. 0, // Search Flags
  2356. LFN_FLAG_INFO_ATTRIBUTES |
  2357. LFN_FLAG_INFO_FILE_SIZE |
  2358. LFN_FLAG_INFO_MODIFY_TIME |
  2359. LFN_FLAG_INFO_CREATION_TIME,
  2360. CreateAttributes,
  2361. OpenFlags, // DesiredAccess
  2362. Vcb->Specific.Disk.VolumeNumber,
  2363. Vcb->Specific.Disk.Handle,
  2364. 0, // Short directory flag
  2365. &Icb->SuperType.Fcb->RelativeFileName );
  2366. if ( NT_SUCCESS( Iosb.Status ) ) {
  2367. Iosb.Status = ParseResponse(
  2368. IrpContext,
  2369. IrpContext->rsp,
  2370. IrpContext->ResponseLength,
  2371. "Ne_e=e_xx_xx_x",
  2372. &Icb->Handle[2],
  2373. 6,
  2374. &Fcb->NonPagedFcb->Attributes,
  2375. &Fcb->NonPagedFcb->Header.FileSize,
  2376. 6,
  2377. &Fcb->CreationTime,
  2378. &Fcb->CreationDate,
  2379. 4,
  2380. &Fcb->LastModifiedTime,
  2381. &Fcb->LastModifiedDate,
  2382. 4,
  2383. &Fcb->LastAccessDate );
  2384. }
  2385. }
  2386. if ( NT_SUCCESS( Iosb.Status ) ) {
  2387. SetFlag( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID );
  2388. Icb->HasRemoteHandle = TRUE;
  2389. DebugTrace( 0, Dbg, "Attributes -> %08lx\n", Fcb->NonPagedFcb->Attributes );
  2390. DebugTrace( 0, Dbg, "FileSize.Low-> %08lx\n", Fcb->NonPagedFcb->Header.FileSize.LowPart );
  2391. DebugTrace( 0, Dbg, "ModifiedDate-> %08lx\n", Fcb->LastModifiedDate );
  2392. DebugTrace( 0, Dbg, "ModifiedTime-> %08lx\n", Fcb->LastModifiedTime );
  2393. DebugTrace( 0, Dbg, "CreationDate-> %08lx\n", Fcb->CreationDate );
  2394. DebugTrace( 0, Dbg, "CreationTime-> %08lx\n", Fcb->CreationTime );
  2395. DebugTrace( 0, Dbg, "LastAccDate -> %08lx\n", Fcb->LastAccessDate );
  2396. } else {
  2397. return( Iosb );
  2398. }
  2399. //
  2400. // Set information field assuming success. It will be ignored
  2401. // if the NCP failed.
  2402. //
  2403. if ( CreateOperation) {
  2404. Iosb.Information = FILE_CREATED;
  2405. } else {
  2406. Iosb.Information = FILE_OVERWRITTEN;
  2407. }
  2408. return( Iosb );
  2409. }
  2410. IO_STATUS_BLOCK
  2411. OpenRenameTarget(
  2412. IN PIRP_CONTEXT IrpContext,
  2413. IN PVCB Vcb,
  2414. IN PDCB Dcb,
  2415. IN PICB* Icb
  2416. )
  2417. /*++
  2418. Routine Description:
  2419. This routine opens a directory. If the filename provided specifies
  2420. a directory then the file/directory to be renamed will be put in this
  2421. directory.
  2422. If the target foo\bar does not exist or is a file then the source of
  2423. the rename must be a file and will end up in the directory foo with
  2424. the name bar
  2425. Arguments:
  2426. IrpContext - Supplies all the information
  2427. Vcb - A pointer to the VCB for the remote drive.
  2428. Dcb - A pointer to the DCB for relative opens. If NULL the FileName
  2429. is an full path name. If non NUL the FileName is relative to
  2430. this directory.
  2431. Icb - A pointer to where the address of the Icb is to be stored.
  2432. Return Value:
  2433. NT_STATUS - Status of operation
  2434. --*/
  2435. {
  2436. PIRP Irp;
  2437. PIO_STACK_LOCATION IrpSp;
  2438. IO_STATUS_BLOCK Iosb;
  2439. PFCB Fcb;
  2440. BOOLEAN FullNameIsAFile;
  2441. BOOLEAN FullNameExists;
  2442. BOOLEAN PathIsAFile;
  2443. #if 0
  2444. UNICODE_STRING Drive;
  2445. WCHAR DriveLetter;
  2446. UNICODE_STRING Server;
  2447. UNICODE_STRING Volume;
  2448. UNICODE_STRING FileName;
  2449. #endif
  2450. UNICODE_STRING Path;
  2451. UNICODE_STRING FullName;
  2452. UNICODE_STRING CompleteName;
  2453. UNICODE_STRING VcbName;
  2454. PWCH pTrailingSlash;
  2455. USHORT i;
  2456. USHORT DcbNameLength;
  2457. PAGED_CODE();
  2458. DebugTrace(+1, Dbg, "OpenRenameTarget\n", 0);
  2459. //
  2460. // Get the current IRP stack location
  2461. //
  2462. Irp = IrpContext->pOriginalIrp;
  2463. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  2464. //
  2465. // Build a complete filename of the form \g:\server\volume\dir1\file
  2466. //
  2467. if ( Dcb != NULL ) {
  2468. //
  2469. // Strip to UID portion of the DCB name.
  2470. //
  2471. for ( i = 0 ; i < Dcb->FullFileName.Length / sizeof(WCHAR) ; i++ ) {
  2472. if ( Dcb->FullFileName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR ) {
  2473. break;
  2474. }
  2475. }
  2476. ASSERT( Dcb->FullFileName.Buffer[i] == OBJ_NAME_PATH_SEPARATOR );
  2477. //
  2478. // Now build the full name by appending the file name to the DCB name.
  2479. //
  2480. DcbNameLength = Dcb->FullFileName.Length - ( i * sizeof(WCHAR) );
  2481. CompleteName.Length = DcbNameLength + IrpSp->FileObject->FileName.Length + sizeof( WCHAR);
  2482. CompleteName.MaximumLength = CompleteName.Length;
  2483. CompleteName.Buffer = ALLOCATE_POOL_EX( PagedPool, CompleteName.Length );
  2484. RtlCopyMemory(
  2485. CompleteName.Buffer,
  2486. Dcb->FullFileName.Buffer + i,
  2487. DcbNameLength );
  2488. CompleteName.Buffer[ DcbNameLength / sizeof(WCHAR) ] = L'\\';
  2489. RtlCopyMemory(
  2490. CompleteName.Buffer + DcbNameLength / sizeof(WCHAR ) + 1,
  2491. IrpSp->FileObject->FileName.Buffer,
  2492. IrpSp->FileObject->FileName.Length );
  2493. Dcb = NULL;
  2494. } else {
  2495. CompleteName = IrpSp->FileObject->FileName;
  2496. }
  2497. //
  2498. // Calculate the VCB name, without the UID prefix.
  2499. //
  2500. VcbName.Buffer = wcschr( Vcb->Name.Buffer, L'\\' );
  2501. VcbName.Length = (USHORT) (Vcb->Name.Length -
  2502. ( (PCHAR)VcbName.Buffer - (PCHAR)Vcb->Name.Buffer ));
  2503. //
  2504. // Calculate the target relative name. This is simply the complete
  2505. // name minus the VcbName and the leading backslash.
  2506. //
  2507. FullName.Buffer = CompleteName.Buffer + ( VcbName.Length / sizeof(WCHAR) ) + 1;
  2508. FullName.Length = (USHORT) (CompleteName.Length -
  2509. ( (PCHAR)FullName.Buffer - (PCHAR)CompleteName.Buffer ));
  2510. //
  2511. // Calculate the target directory relative name. This the the target
  2512. // full name, minus the last component of the name.
  2513. //
  2514. pTrailingSlash = FullName.Buffer + FullName.Length / sizeof(WCHAR) - 1;
  2515. for ( i = 0; i < FullName.Length ; i += sizeof(WCHAR) ) {
  2516. if ( *pTrailingSlash == L'\\' ) {
  2517. break;
  2518. }
  2519. --pTrailingSlash;
  2520. }
  2521. Path.Buffer = FullName.Buffer;
  2522. if ( i == FullName.Length ) {
  2523. //
  2524. // If no trailing slash was found, the the target path is the
  2525. // root directory.
  2526. //
  2527. Path.Length = 0;
  2528. } else {
  2529. Path.Length = (USHORT) ((PCHAR)pTrailingSlash - (PCHAR)FullName.Buffer);
  2530. }
  2531. #if 0
  2532. Iosb.Status = CrackPath(
  2533. &CompleteName,
  2534. &Drive,
  2535. &DriveLetter,
  2536. &Server,
  2537. &Volume,
  2538. &Path,
  2539. &FileName,
  2540. &FullName );
  2541. #endif
  2542. Iosb.Status = FileOrDirectoryExists( IrpContext,
  2543. Vcb,
  2544. NULL,
  2545. &Path,
  2546. &PathIsAFile );
  2547. if ( !NT_SUCCESS( Iosb.Status) ) {
  2548. // The directory containing the file does not exist
  2549. return(Iosb);
  2550. }
  2551. Iosb.Status = FileOrDirectoryExists( IrpContext,
  2552. Vcb,
  2553. NULL,
  2554. &FullName,
  2555. &FullNameIsAFile );
  2556. if ( !NT_SUCCESS( Iosb.Status ) ) {
  2557. FullNameExists = FALSE;
  2558. Iosb.Information = FILE_DOES_NOT_EXIST;
  2559. } else {
  2560. FullNameExists = TRUE;
  2561. Iosb.Information = 0;
  2562. }
  2563. DebugTrace( 0, Dbg, "FullNameExists = %08lx\n", FullNameExists);
  2564. DebugTrace( 0, Dbg, "FullNameIsAFile = %08lx\n", FullNameIsAFile);
  2565. try {
  2566. UNICODE_STRING TargetPath;
  2567. //
  2568. // Find the FCB for this file. If the FCB exists, we get a
  2569. // referenced pointer. Otherwise a new FCB is created.
  2570. // The file is the complete path minus the target filename.
  2571. //
  2572. TargetPath = CompleteName;
  2573. Fcb = NwFindFcb( IrpContext->pScb, Vcb, &TargetPath, Dcb );
  2574. // in rare cases, NwFindFcb might return NULL instead of throwing an exception
  2575. // Raid # 432500
  2576. if (Fcb == NULL) {
  2577. DebugTrace(0, Dbg, "NwFindFcb returned NULL in OpenRenameTarget\n", 0);
  2578. Iosb.Status = STATUS_INVALID_PARAMETER;
  2579. try_return( Iosb );
  2580. }
  2581. //
  2582. // Now create the ICB.
  2583. //
  2584. *Icb = NwCreateIcb( NW_NTC_ICB, Fcb );
  2585. (*Icb)->FileObject = IrpSp->FileObject;
  2586. NwSetFileObject( IrpSp->FileObject, Fcb->NonPagedFcb, *Icb );
  2587. (*Icb)->Exists = FullNameExists;
  2588. (*Icb)->IsAFile = FullNameIsAFile;
  2589. try_return(Iosb.Status = STATUS_SUCCESS);
  2590. try_exit: NOTHING;
  2591. } finally {
  2592. if ( AbnormalTermination() || !NT_SUCCESS( Iosb.Status ) ) {
  2593. //
  2594. // Failed to create
  2595. //
  2596. if ( *Icb != NULL ) {
  2597. NwDeleteIcb( NULL, *Icb );
  2598. *Icb = NULL;
  2599. }
  2600. }
  2601. }
  2602. DebugTrace(-1, Dbg, "OpenRenameTarget\n", Iosb.Status);
  2603. return( Iosb );
  2604. }
  2605. IO_STATUS_BLOCK
  2606. CreatePrintJob(
  2607. PIRP_CONTEXT IrpContext,
  2608. PVCB Vcb,
  2609. PICB Icb,
  2610. PUNICODE_STRING DriveName
  2611. )
  2612. /*++
  2613. Routine Description:
  2614. This routines create a new directory.
  2615. Arguments:
  2616. IrpContext - Supplies all the information
  2617. Vcb - A pointer to the VCB for the remote print queue.
  2618. Icb - A pointer to the newly created ICB.
  2619. DriveName - LPTx
  2620. Return Value:
  2621. IO_STATUS_BLOCK - Status of operation
  2622. --*/
  2623. {
  2624. IO_STATUS_BLOCK Iosb;
  2625. PFCB Fcb;
  2626. ANSI_STRING ODriveName;
  2627. static CHAR LptName[] = "LPT" ;
  2628. ULONG PrintOptions;
  2629. PLOGON Logon;
  2630. PUNICODE_STRING BannerName;
  2631. PAGED_CODE();
  2632. BannerName = &IrpContext->pScb->UserName;
  2633. NwAcquireExclusiveRcb( &NwRcb, TRUE );
  2634. Logon = FindUser( &IrpContext->pScb->UserUid, TRUE );
  2635. if ( Logon == NULL ) {
  2636. PrintOptions = NwPrintOptions;
  2637. } else {
  2638. PrintOptions = Logon->NwPrintOptions;
  2639. /*
  2640. * If user name is GUEST, use the validated user name
  2641. */
  2642. if ((BannerName->Length == 0 ) ||
  2643. (RtlCompareUnicodeString( BannerName, &Guest.UserName, TRUE ) == 0 )) {
  2644. BannerName = &Logon->UserName;
  2645. }
  2646. }
  2647. NwReleaseRcb( &NwRcb );
  2648. //
  2649. // Make sure the print queue name is correct.
  2650. //
  2651. if ( Icb->SuperType.Fcb->RelativeFileName.Length != 0 ) {
  2652. Iosb.Status = STATUS_OBJECT_PATH_SYNTAX_BAD;
  2653. return( Iosb );
  2654. }
  2655. //
  2656. // Send a create queue job packet, and wait the response.
  2657. //
  2658. if ((DriveName->Length == 0 ) ||
  2659. (!NT_SUCCESS(RtlUnicodeStringToOemString( &ODriveName, DriveName, TRUE )))) {
  2660. //
  2661. // if we dont have a name, use the string "LPT". we do this because
  2662. // some printers insist on a name.
  2663. //
  2664. RtlInitString(&ODriveName, LptName);
  2665. }
  2666. Iosb.Status = ExchangeWithWait (
  2667. IrpContext,
  2668. SynchronousResponseCallback,
  2669. "Sd_ddw_b_r_bbwwww_x-x_", // Format string
  2670. NCP_ADMIN_FUNCTION, NCP_CREATE_QUEUE_JOB,
  2671. Vcb->Specific.Print.QueueId,// Queue ID
  2672. 6, // Skip bytes
  2673. 0xffffffff, // Target Server ID number
  2674. 0xffffffff, 0xffff, // Target Execution time
  2675. 11, // Skip bytes
  2676. 0x00, // Job Control Flags
  2677. 26, // Skip bytes
  2678. ODriveName.Buffer, ODriveName.Length, // Description
  2679. 50 - ODriveName.Length , // Description pad
  2680. 0, // Version number
  2681. 8, // Tab Size
  2682. 1, // Number of copies
  2683. PrintOptions, // Control Flags
  2684. 0x3C, // Maximum lines
  2685. 0x84, // Maximum characters
  2686. 22, // Skip bytes
  2687. BannerName, 13, // Banner Name
  2688. &Vcb->ShareName, 12, // Header Name
  2689. 1+14+80 // null last string & skip rest of client area
  2690. );
  2691. //
  2692. // free the string if it was allocated
  2693. //
  2694. if (ODriveName.Buffer != LptName)
  2695. RtlFreeAnsiString(&ODriveName);
  2696. if ( NT_SUCCESS( Iosb.Status ) ) {
  2697. Iosb.Status = ParseResponse(
  2698. IrpContext,
  2699. IrpContext->rsp,
  2700. IrpContext->ResponseLength,
  2701. "N_w_r",
  2702. 22,
  2703. &Icb->JobId,
  2704. 18,
  2705. Icb->Handle, sizeof(Icb->Handle) );
  2706. }
  2707. if ( NT_SUCCESS( Iosb.Status ) ) {
  2708. Fcb = Icb->SuperType.Fcb;
  2709. Fcb->NonPagedFcb->Attributes = 0;
  2710. Fcb->CreationDate = 0;
  2711. Fcb->LastAccessDate = 0;
  2712. Fcb->LastModifiedDate = 0;
  2713. Fcb->LastModifiedTime = 0;
  2714. Icb->HasRemoteHandle = TRUE;
  2715. Icb->IsPrintJob = TRUE;
  2716. Icb->ActuallyPrinted = FALSE;
  2717. SetFlag( Fcb->Flags, FCB_FLAGS_ATTRIBUTES_ARE_VALID );
  2718. }
  2719. //
  2720. // Set information field assuming success. It will be ignored
  2721. // if the NCP failed.
  2722. //
  2723. Iosb.Information = FILE_CREATED;
  2724. if ( Iosb.Status == STATUS_UNSUCCESSFUL ) {
  2725. Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
  2726. }
  2727. return( Iosb );
  2728. }
  2729. VOID
  2730. CloseFile(
  2731. PIRP_CONTEXT pIrpContext,
  2732. PICB pIcb
  2733. )
  2734. /*++
  2735. Routine Description:
  2736. This routines closes an opened file.
  2737. Arguments:
  2738. pIrpContext - Supplies all the information
  2739. pIcb - A pointer to the newly created ICB.
  2740. Return Value:
  2741. None.
  2742. --*/
  2743. {
  2744. PAGED_CODE();
  2745. ExchangeWithWait(
  2746. pIrpContext,
  2747. SynchronousResponseCallback,
  2748. "F-r",
  2749. NCP_CLOSE,
  2750. pIcb->Handle, 6 );
  2751. }