Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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