/*++ Copyright (c) 1989 Microsoft Corporation Module Name: DownLvlO.c Abstract: This module implements downlevel opens. --*/ #include "precomp.h" #pragma hdrstop //// //// The Bug check file id for this module //// // //#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE) // // The debug trace level // #define Dbg (DEBUG_TRACE_CREATE) VOID MRxSmbPopulateFileInfoInOE( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, USHORT FileAttributes, ULONG LastWriteTimeInSeconds, ULONG FileSize ); PVOID MRxSmbPopulateFcbInitPacketForCore(void); NTSTATUS MRxSmbFinishPseudoOpenFromGFAResponse ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange ); NTSTATUS MRxSmbFinishCoreCreateDirectory ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, USHORT Attributes ); NTSTATUS MRxSmbGetFileAttributes( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE ) /*++ Routine Description: This routine does a GetFileAttributes and remembers the reponse. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbSynchronousGetFileAttributes entering.......OE=%08lx\n",OrdinaryExchange)); if (FsRtlDoesNameContainWildCards(&capFcb->AlreadyPrefixedName)) { Status = STATUS_OBJECT_NAME_INVALID; goto FINALLY; } StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_QUERY_INFORMATION, SMB_REQUEST_SIZE(QUERY_INFORMATION), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0B4!", // 0 UCHAR WordCount; // Count of parameter words = 0 SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: &capFcb->AlreadyPrefixedName // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_GFA ); // //save the result into the srvopen for use later..as appropriate if (NT_SUCCESS(Status)) { PMRX_SMB_SRV_OPEN smbSrvOpen = OrdinaryExchange->Create.smbSrvOpen; if (smbSrvOpen!=NULL) { ASSERT ( FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,Create.smbSrvOpen) == FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,Info.smbSrvOpen)); ASSERT ( FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,Create.FileInfo) == FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,Info.FileInfo)); smbSrvOpen->FileInfo = OrdinaryExchange->Create.FileInfo; smbSrvOpen->RxContextSerialNumber = (RxContext->SerialNumber); KeQueryTickCount(&smbSrvOpen->TimeStampInTicks); } } FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbSynchronousGetFileAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbCoreDeleteForSupercedeOrClose( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE, BOOLEAN DeleteDirectory ) /*++ Routine Description: This routine does a GetFileAttributes and remembers the reponse. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCoreDeleteForSupercede entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); // if (!DeleteDirectory) { ULONG SearchAttributes = SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN; // a la rdr1 COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_DELETE, SMB_REQUEST_SIZE(DELETE), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0wB4!", // 0 UCHAR WordCount; // Count of parameter words = 1 SearchAttributes, // w _USHORT( SearchAttributes ); SMB_WCT_CHECK(1) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: OrdinaryExchange->pPathArgument1 // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); } else { COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_DELETE_DIRECTORY, SMB_REQUEST_SIZE(DELETE_DIRECTORY), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0B4!", // 0 UCHAR WordCount; // Count of parameter words = 0 SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: OrdinaryExchange->pPathArgument1 // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); } Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCoreDeleteForSupercede exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbCoreCheckPath( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE ) /*++ Routine Description: This routine does a GetFileAttributes and remembers the reponse. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCoreCheckPath entering.......OE=%08lx\n", OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse, SMB_COM_CHECK_DIRECTORY, SMB_REQUEST_SIZE(CHECK_DIRECTORY), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0), RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0B4!", // UCHAR WordCount; // Count of parameter words = 0 SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: OrdinaryExchange->pPathArgument1 // 4 UCHAR BufferFormat; // 0x04 -- ASCII // UCHAR FileName[]; // File name ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_CORECHECKDIRECTORY ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCoreCheckPath exiting.......OE=%08lx, st=%08lx\n", OrdinaryExchange,Status) ); return(Status); } NTSTATUS MRxSmbCoreOpen( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE, ULONG OpenShareMode, ULONG Attribute ) /*++ Routine Description: This routine does a core open. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCoreOpen entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_OPEN, SMB_REQUEST_SIZE(OPEN), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0wwB4!", // 0 UCHAR WordCount; // Count of parameter words = 2 OpenShareMode, // w _USHORT( DesiredAccess ); // Mode - read/write/share Attribute, // w _USHORT( SearchAttributes ); SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: &capFcb->AlreadyPrefixedName // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_COREOPEN ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCoreOpen exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbSetFileAttributes( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE, ULONG SmbAttributes, ULONG LastWriteTime ) /*++ Routine Description: This routine does a core create directory..... Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbSetFileAttributes entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); if (FlagOn(Exchange->SmbCeContext.pServerEntry->Server.DialectFlags,DF_WFW|DF_W95)){ LastWriteTime = 0; } COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse, SMB_COM_SET_INFORMATION, SMB_REQUEST_SIZE(SET_INFORMATION), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0wdwwwwwB4!", // 0 UCHAR WordCount; // Count of parameter words = 8 SmbAttributes, // w _USHORT( FileAttributes ); LastWriteTime, // d _ULONG( LastWriteTimeInSeconds ); 0,0,0,0,0, // 5*w _USHORT( Reserved )[5]; // Reserved (must be 0) SMB_WCT_CHECK(8) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: &capFcb->AlreadyPrefixedName // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_SFA ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbSFAAfterCreateDirectory exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbCoreCreateDirectory( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE ) /*++ Routine Description: This routine does a core create directory..... Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCoreCreateDirectory entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse, SMB_COM_CREATE_DIRECTORY, SMB_REQUEST_SIZE(CREATE_DIRECTORY), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0B4!", // 0 UCHAR WordCount; // Count of parameter words = 0 SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: &capFcb->AlreadyPrefixedName // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_CORECREATEDIRECTORY ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCoreCreateDirectory exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbCoreCreate( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE, ULONG Attribute, BOOLEAN CreateNew ) /*++ Routine Description: This routine does a core create.....if the flag is set we use create new. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCoreCreate entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse, (UCHAR)(CreateNew?SMB_COM_CREATE_NEW:SMB_COM_CREATE), SMB_REQUEST_SIZE(CREATE), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0wdB4!", // 0 UCHAR WordCount; // Count of parameter words = 3 Attribute, // w _USHORT( FileAttributes ); // New file attributes 0, // d _ULONG( CreationTimeInSeconds ); // Creation time SMB_WCT_CHECK(3) // B _USHORT( ByteCount ); // Count of data bytes; min = 2 // UCHAR Buffer[1]; // Buffer containing: &capFcb->AlreadyPrefixedName // 4 //UCHAR BufferFormat; // 0x04 -- ASCII // //UCHAR FileName[]; // File name ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_CORECREATE ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCoreCreate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbCloseAfterCoreCreate( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE ) /*++ Routine Description: This routine does a close..... Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCloseAfterCoreCreate entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse, SMB_COM_CLOSE, SMB_REQUEST_SIZE(CLOSE), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ); MRxSmbStuffSMB (StufferState, "0wdB!", // 0 UCHAR WordCount; // Count of parameter words = 3 // w _USHORT( Fid ); // File handle OrdinaryExchange->Create.FidReturnedFromCreate, 0, // d _ULONG( LastWriteTimeInSeconds ); // Time of last write, low and high SMB_WCT_CHECK(3) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0 // UCHAR Buffer[1]; // empty ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_CLOSEAFTERCORECREATE ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCloseAfterCoreCreate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbCoreTruncate( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE, ULONG Fid, ULONG FileTruncationPoint ) /*++ Routine Description: This routine does a truncate to implement FILE_OVERWRITE and FILE_OVERWRITE_IF..... it is also used in the "extend-for-cached-write" path. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureFobx; PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; RxDbgTrace(+1, Dbg, ("MRxSmbCoreTruncate entering.......OE=%08lx\n",OrdinaryExchange)); StufferState = &OrdinaryExchange->AssociatedStufferState; ASSERT( StufferState ); COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse, SMB_COM_WRITE, SMB_REQUEST_SIZE(WRITE), NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED, 0,0,0,0 STUFFERTRACE(Dbg,'FC')) ) MRxSmbStuffSMB (StufferState, "0wwdwByw!", // 0 UCHAR WordCount; // Count of parameter words = 5 Fid, // w _USHORT( Fid ); // File handle 0, // w _USHORT( Count ); // Number of bytes to be written FileTruncationPoint, // d _ULONG( Offset ); // Offset in file to begin write 0, // w _USHORT( Remaining ); // Bytes remaining to satisfy request SMB_WCT_CHECK(5) // B _USHORT( ByteCount ); // Count of data bytes // //UCHAR Buffer[1]; // Buffer containing: 0x01, // y UCHAR BufferFormat; // 0x01 -- Data block 0 // w _USHORT( DataLength ); // Length of data // ULONG Buffer[1]; // Data ); Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, SMBPSE_OETYPE_CORETRUNCATE ); FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbCoreTruncate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbDownlevelCreate( SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE ) /*++ Routine Description: This routine implements downlevel creates. Arguments: OrdinaryExchange - an exchange to be used for conducting this open. Return Value: NTSTATUS - The return status for the operation Notes: For core, in particular, this is pretty painful because a different smb must be used for different dispositions. In addition, we cannot really open a directory. By in large, we will follow a strategy similar to rdr1. If the openmode maps into something that a downlevel server won't understand then we don't really open the file.....we just do a GFA to ensure that it's there and hope that we can do path-based ops for the duration. --*/ { NTSTATUS Status = STATUS_NOT_IMPLEMENTED; RxCaptureFcb; RxCaptureFobx; PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters; ULONG CreateOptions = cp->CreateOptions; ULONG FileAttributes = cp->FileAttributes; ACCESS_MASK DesiredAccess = cp->DesiredAccess; USHORT ShareAccess = (USHORT)(cp->ShareAccess); ULONG Disposition = cp->Disposition; PUNICODE_STRING PathName = &capFcb->AlreadyPrefixedName; USHORT mappedDisposition = MRxSmbMapDisposition(Disposition); USHORT mappedSharingMode = MRxSmbMapShareAccess(ShareAccess); USHORT mappedAttributes = MRxSmbMapFileAttributes(FileAttributes); USHORT mappedOpenMode = MRxSmbMapDesiredAccess(DesiredAccess); LARGE_INTEGER AllocationSize = cp->AllocationSize; LARGE_INTEGER CurrentTime; ULONG SecondsSince1970; PMRXIFS_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext); PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange; PSMBSTUFFER_BUFFER_STATE StufferState; BOOLEAN MustBeAFile = (MustBeFile(CreateOptions)!=0); BOOLEAN MustBeADirectory = (MustBeDirectory(CreateOptions)!=0) || BooleanFlagOn(RxContext->Create.Flags,RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH); BOOLEAN ItsADirectory = FALSE; BOOLEAN ItsTheShareRoot = FALSE; RxDbgTrace(+1, Dbg, ("MRxSmbDownlevelCreate entering.......OE=%08lx\n",OrdinaryExchange)); RxDbgTrace( 0, Dbg, ("mapAtt,Shr,Disp,OM %04lx,%04lx,%04lx,%04lx\n", mappedAttributes,mappedSharingMode,mappedDisposition,mappedOpenMode)); SmbPseOEAssertConsistentLinkageFromOE("Downlevel Create:"); StufferState = &OrdinaryExchange->AssociatedStufferState; OrdinaryExchange->NeedToReinitializeStufferState = FALSE; if (OrdinaryExchange->Create.CreateWithEasSidsOrLongName) { Status = STATUS_NOT_SUPPORTED; goto FINALLY; } if (AllocationSize.HighPart != 0) { Status = STATUS_INVALID_PARAMETER; goto FINALLY; } ASSERT( NodeType(RxContext->Create.pSrvOpen) == RDBSS_NTC_SRVOPEN ); OrdinaryExchange->Create.smbSrvOpen = MRxIfsGetSrvOpenExtension(RxContext->Create.pSrvOpen); // // we know that the root a share exists and that it's a directory....the catch is that GetFileAttributes // will return a NO_SUCH_FILE error for the root if it's really a root on the server. record this and use it // to our advantage later. if ((PathName->Length == sizeof(WCHAR)) && (PathName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) { if (MustBeAFile) { Status = STATUS_FILE_IS_A_DIRECTORY; goto FINALLY; } MustBeADirectory = TRUE; // we know it's a directory! ItsTheShareRoot = TRUE; } if ( (mappedOpenMode == ((USHORT)-1)) || (Disposition == FILE_SUPERSEDE) || (!MustBeAFile) ) { // // go find out what's there....... Status = MRxSmbGetFileAttributes( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS ); RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate gfastatus=%08lx\n",Status)); if (NT_SUCCESS(Status)) { ULONG Attributes = SmbGetUshort(&OrdinaryExchange->Create.FileInfo.Basic.FileAttributes); ItsADirectory = BooleanFlagOn(Attributes,SMB_FILE_ATTRIBUTE_DIRECTORY); RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate attributes=%08lx\n",Attributes)); if ((Disposition==FILE_CREATE)) { Status = STATUS_OBJECT_NAME_COLLISION; goto FINALLY; } if (MustBeADirectory && !ItsADirectory && (Disposition!=FILE_SUPERSEDE)) { Status = STATUS_OBJECT_TYPE_MISMATCH; goto FINALLY; } if (MustBeAFile && ItsADirectory && (Disposition!=FILE_SUPERSEDE)) { Status = STATUS_OBJECT_TYPE_MISMATCH; goto FINALLY; } //if (!MustBeAFile && ItsADirectory && (Disposition==FILE_OPEN)){ if (Disposition==FILE_OPEN){ //we're done except to finish AND to set the flags in the srvopen MRxSmbFinishPseudoOpenFromGFAResponse ( OrdinaryExchange ); goto FINALLY; } } else if (Status != STATUS_NO_SUCH_FILE) { goto FINALLY; } else if ((Disposition==FILE_CREATE) || (Disposition==FILE_OPEN_IF) || (Disposition==FILE_OVERWRITE_IF) || (Disposition==FILE_SUPERSEDE)) { NOTHING; } else if (ItsTheShareRoot) { PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen; PMRX_SMB_SRV_OPEN smbSrvOpen = MRxIfsGetSrvOpenExtension(SrvOpen); //here we have run into a true root....so we can't get attributes. fill in a fake //response and finish. also, flip the bit that says we can't gfa this guy. RtlZeroMemory(&OrdinaryExchange->Create.FileInfo,sizeof(OrdinaryExchange->Create.FileInfo)); MRxSmbFinishPseudoOpenFromGFAResponse ( OrdinaryExchange ); MRxSmbPopulateFileInfoInOE( OrdinaryExchange, SMB_FILE_ATTRIBUTE_DIRECTORY, 0, 0 ); smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_CANT_GETATTRIBS; Status = STATUS_SUCCESS; goto FINALLY; } else { goto FINALLY; } } SmbCeResetExchange(&OrdinaryExchange->Exchange); //must reset! if (NT_SUCCESS(Status) &&(Disposition == FILE_SUPERSEDE)) { OrdinaryExchange->pPathArgument1 = PathName; // //we have to get rid of the existing entity...using a delete or a rmdir as appropriate Status = MRxSmbCoreDeleteForSupercedeOrClose(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, OrdinaryExchange->Create.FileInfo.Standard.Directory ); if (!NT_SUCCESS(Status)) { RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate could notsupersede st=%08lx\n",Status)); goto FINALLY; } SmbCeResetExchange(&OrdinaryExchange->Exchange); //must reset! } if (MustBeADirectory || (ItsADirectory &&(Disposition == FILE_SUPERSEDE)) ) { ASSERT (Disposition!=FILE_OPEN); Status = MRxSmbCoreCreateDirectory(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS); if (!NT_SUCCESS(Status)) { RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate couldn't mkdir st=%08lx\n",Status)); goto FINALLY; } if ( (mappedAttributes & ( SMB_FILE_ATTRIBUTE_READONLY | SMB_FILE_ATTRIBUTE_HIDDEN | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_ARCHIVE )!= 0) ) { // //we have to set the attributes Status = MRxSmbSetFileAttributes( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, mappedAttributes,0); //lastwritetime=0 if (!NT_SUCCESS(Status)) { RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate couldn't sfa st=%08lx\n",Status)); } } MRxSmbFinishCoreCreateDirectory ( OrdinaryExchange, mappedAttributes ); goto FINALLY; } //no pseudoOpens yet if ( TRUE ) { ULONG workingDisposition = Disposition; ULONG iterationcount; BOOLEAN MayNeedATruncate = FALSE; // // we use the disposition as a state and case out.....some are hard and some are easy // for example, if it's CREATE then we use the CREATE_NEW to create the file but // the resulting open is no good so we close it and open it again using the // open. for OPEN_IF we assume that the file will be there // and drop into create if it's not. for (iterationcount=0;;iterationcount++) { switch (workingDisposition) { case FILE_OVERWRITE: case FILE_OVERWRITE_IF: MayNeedATruncate = TRUE; //lack of break intentional case FILE_OPEN_IF: case FILE_OPEN: Status = MRxSmbCoreOpen(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, mappedOpenMode|mappedSharingMode, mappedAttributes); if (!((workingDisposition == FILE_OPEN_IF) || (workingDisposition == FILE_OVERWRITE_IF)) || (Status != STATUS_NO_SUCH_FILE) || (iterationcount>6) )break; SmbCeResetExchange(&OrdinaryExchange->Exchange); //must reset! case FILE_SUPERSEDE: case FILE_CREATE: Status = MRxSmbCoreCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, mappedAttributes,TRUE); //(workingDisposition==FILE_CREATE)); if (!NT_SUCCESS(Status)) { RxDbgTrace(-1, Dbg, ("MRxSmbDownlevelCreate exiting.......createnew failed st=%08lx\n",Status)); break; } //now, we have a network handle. BUT, it's a compatibility-mode open. since we don't want that we // need to close and reopen with the parameters specified. there is a window here! what can i do?? Status = MRxSmbCloseAfterCoreCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS); if (!NT_SUCCESS(Status)) { RxDbgTrace(-1, Dbg, ("MRxSmbDownlevelCreate exiting.......closeaftercreatenew failed st=%08lx\n",Status)); break; } workingDisposition = FILE_OPEN_IF; continue; // this wraps back to the switch with a new disposition //break; default : ASSERT(!"Bad Disposition"); Status = STATUS_INVALID_PARAMETER; } break; //exit the loop } if (!NT_SUCCESS(Status))goto FINALLY; //we may need a truncate....this is different from rdr1. if (MayNeedATruncate && !OrdinaryExchange->Create.FileWasCreated && (OrdinaryExchange->Create.FileSizeReturnedFromOpen!=0) ) { Status = MRxSmbCoreTruncate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, OrdinaryExchange->Create.FidReturnedFromOpen, 0 ); } goto FINALLY; } FINALLY: RxDbgTrace(-1, Dbg, ("MRxSmbDownlevelCreate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status)); return(Status); } NTSTATUS MRxSmbFinishGFA ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, PRESP_QUERY_INFORMATION Response ) /*++ Routine Description: This routine copies the response to the GetFileAttributes SMB. But, it must be called synchronously. Arguments: OrdinaryExchange - the exchange instance Response - the response Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; PFILE_BASIC_INFORMATION BasicInformation = &OrdinaryExchange->Create.FileInfo.Basic; PFILE_STANDARD_INFORMATION StandardInformation = &OrdinaryExchange->Create.FileInfo.Standard; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxSmbFinishGFA\n", 0 )); SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishGFA:"); ASSERT( (Response->WordCount==10)); ASSERT( (SmbGetUshort(&Response->ByteCount)==0)); //what we do here is to put the data into the ordinary exchange...it's locked down do //we wcould do this at DPC level MRxSmbPopulateFileInfoInOE( OrdinaryExchange, SmbGetUshort(&Response->FileAttributes), SmbGetUlong(&Response->LastWriteTimeInSeconds), SmbGetUlong(&Response->FileSize) ); RxDbgTrace(-1, Dbg, ("MRxSmbFinishGFA returning %08lx\n", Status )); return Status; } NTSTATUS MRxSmbCreateFileSuccessTail ( PRX_CONTEXT RxContext, PBOOLEAN MustRegainExclusiveResource, RX_FILE_TYPE StorageType, SMB_FILE_ID Fid, ULONG ServerVersion, UCHAR OplockLevel, ULONG CreateAction, PSMBPSE_FILEINFO_BUNDLE FileInfo ); NTSTATUS MRxSmbFinishCoreCreate ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, PRESP_CREATE Response ) /*++ Routine Description: This routine copies the fid from a core create response. it does not finish the fcb......if a compatibility mode open is acceptable then it could. Arguments: OrdinaryExchange - the exchange instance Response - the response Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreCreate\n", 0 )); SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreCreate:"); ASSERT( (Response->WordCount==1)); ASSERT( (SmbGetUshort(&Response->ByteCount)==0)); OrdinaryExchange->Create.FidReturnedFromCreate = SmbGetUshort(&Response->Fid); OrdinaryExchange->Create.FileWasCreated = TRUE; //notice that we didn't finish here! we should IFF a compatibilty-mode open is okay RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreCreate returning %08lx\n", Status )); return Status; } #define JUST_USE_THE_STUFF_IN_THE_OE (0xfbad) VOID MRxSmbPopulateFileInfoInOE( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, USHORT FileAttributes, ULONG LastWriteTimeInSeconds, ULONG FileSize ) { PFILE_BASIC_INFORMATION BasicInformation = &OrdinaryExchange->Create.FileInfo.Basic; PFILE_STANDARD_INFORMATION StandardInformation = &OrdinaryExchange->Create.FileInfo.Standard; BasicInformation->FileAttributes = MRxSmbMapSmbAttributes(FileAttributes); StandardInformation->NumberOfLinks = 1; BasicInformation->CreationTime.QuadPart = 0; BasicInformation->LastAccessTime.QuadPart = 0; MRxSmbSecondsSince1970ToTime(LastWriteTimeInSeconds, MRxSmbExchangeToServer(OrdinaryExchange), &BasicInformation->LastWriteTime); BasicInformation->ChangeTime.QuadPart = 0; StandardInformation->AllocationSize.QuadPart = FileSize; //rdr1 actually rounds up based of svr disk attribs StandardInformation->EndOfFile.QuadPart = FileSize; StandardInformation->Directory = BooleanFlagOn(BasicInformation->FileAttributes,FILE_ATTRIBUTE_DIRECTORY); } NTSTATUS MRxSmbFinishCoreOpen ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, PRESP_OPEN Response ) /*++ Routine Description: This routine finishes a core open. Arguments: OrdinaryExchange - the exchange instance Response - the response Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; PRX_CONTEXT RxContext = OrdinaryExchange->RxContext; RX_FILE_TYPE StorageType; SMB_FILE_ID Fid; ULONG CreateAction; FCB_INIT_PACKET InitPacket; ULONG FileSize; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreOpen\n", 0 )); SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreOpen:"); ASSERT( (Response->WordCount==7)); ASSERT( (SmbGetUshort(&Response->ByteCount)==0)); StorageType = FileTypeFile; Fid = SmbGetUshort(&Response->Fid); OrdinaryExchange->Create.FidReturnedFromOpen = Fid; FileSize = OrdinaryExchange->Create.FileSizeReturnedFromOpen = SmbGetUlong(&Response->DataSize); CreateAction = (OrdinaryExchange->Create.FileWasCreated)?FILE_CREATED : (OrdinaryExchange->Create.FileWasTruncated)?FILE_OVERWRITTEN :FILE_OPENED; MRxSmbPopulateFileInfoInOE( OrdinaryExchange, SmbGetUshort(&Response->FileAttributes), SmbGetUlong(&Response->LastWriteTimeInSeconds), FileSize ); MRxSmbCreateFileSuccessTail ( RxContext, &OrdinaryExchange->Create.MustRegainExclusiveResource, StorageType, Fid, OrdinaryExchange->ServerVersion, SMB_OPLOCK_LEVEL_NONE, CreateAction, &OrdinaryExchange->Create.FileInfo ); OrdinaryExchange->Create.FinalCondition = Condition_Good; IF_DEBUG{ RxCaptureFcb; RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreOpen returning %08lx, fcbstate =%08lx\n", Status, wrapperFcb->FcbState )); } return Status; } NTSTATUS MRxSmbFinishCoreCreateDirectory ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange, USHORT Attributes ) /*++ Routine Description: This routine finishes a core create directory. but, it is not called from the receive routine...... Arguments: OrdinaryExchange - the exchange instance Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; PRX_CONTEXT RxContext = OrdinaryExchange->RxContext; RxCaptureFobx; PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen; PMRX_SMB_SRV_OPEN smbSrvOpen = MRxIfsGetSrvOpenExtension(SrvOpen); RX_FILE_TYPE StorageType; SMB_FILE_ID Fid; ULONG CreateAction; FCB_INIT_PACKET InitPacket; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreCreateDirectory\n", 0 )); SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreCreateDirectory:"); StorageType = FileTypeDirectory; Fid = 0xbadd; CreateAction = FILE_CREATED; MRxSmbPopulateFileInfoInOE( OrdinaryExchange, Attributes, 0, 0 ); MRxSmbCreateFileSuccessTail ( RxContext, &OrdinaryExchange->Create.MustRegainExclusiveResource, StorageType, Fid, OrdinaryExchange->ServerVersion, SMB_OPLOCK_LEVEL_NONE, CreateAction, &OrdinaryExchange->Create.FileInfo ); smbSrvOpen->Flags |= (SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN | SMB_SRVOPEN_FLAG_CANT_REALLY_OPEN); OrdinaryExchange->Create.FinalCondition = Condition_Good; IF_DEBUG{ RxCaptureFcb; RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreCreateDirectory returning %08lx, fcbstate =%08lx\n", Status, wrapperFcb->FcbState )); } return Status; } NTSTATUS MRxSmbFinishPseudoOpenFromGFAResponse ( PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange ) /*++ Routine Description: This routine finishes a directory pseudoopen. Arguments: OrdinaryExchange - the exchange instance Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; PRX_CONTEXT RxContext = OrdinaryExchange->RxContext; RxCaptureFobx; PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen; PMRX_SMB_SRV_OPEN smbSrvOpen = MRxIfsGetSrvOpenExtension(SrvOpen); RX_FILE_TYPE StorageType; SMB_FILE_ID Fid; ULONG CreateAction; FCB_INIT_PACKET InitPacket; ULONG FileSize; PAGED_CODE(); RxDbgTrace(+1, Dbg, ("MRxSmbFinishPseudoOpenFromGFAResponse\n")); SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishPseudoOpenFromGFAResponse:"); StorageType = OrdinaryExchange->Create.FileInfo.Standard.Directory ? FileTypeDirectory : FileTypeFile; Fid = 0xbadd; CreateAction = FILE_OPENED; MRxSmbCreateFileSuccessTail ( RxContext, &OrdinaryExchange->Create.MustRegainExclusiveResource, StorageType, Fid, OrdinaryExchange->ServerVersion, SMB_OPLOCK_LEVEL_NONE, CreateAction, &OrdinaryExchange->Create.FileInfo ); smbSrvOpen->Flags |= (SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN | SMB_SRVOPEN_FLAG_CANT_REALLY_OPEN); OrdinaryExchange->Create.FinalCondition = Condition_Good; IF_DEBUG{ RxCaptureFcb; RxDbgTrace(-1, Dbg, ("MRxSmbFinishPseudoOpenFromGFAResponse returning %08lx, fcbstate =%08lx\n", Status, wrapperFcb->FcbState )); } return Status; } LARGE_INTEGER MRxSmbConvertSmbTimeToTime ( IN PSMBCE_SERVER Server OPTIONAL, IN SMB_TIME Time, IN SMB_DATE Date ) /*++ Routine Description: This routine converts an SMB time to an NT time structure. Arguments: IN SMB_TIME Time - Supplies the time of day to convert IN SMB_DATE Date - Supplies the day of the year to convert IN supplies the server for tz bias. Return Value: LARGE_INTEGER - Time structure describing input time. --*/ { TIME_FIELDS TimeFields; LARGE_INTEGER OutputTime; // // This routine cannot be paged because it is called from both the // MRxSmbFileDiscardableSection and the MRxSmbVCDiscardableSection. // if (SmbIsTimeZero(&Date) && SmbIsTimeZero(&Time)) { OutputTime.LowPart = OutputTime.HighPart = 0; } else { TimeFields.Year = Date.Struct.Year + (USHORT )1980; TimeFields.Month = Date.Struct.Month; TimeFields.Day = Date.Struct.Day; TimeFields.Hour = Time.Struct.Hours; TimeFields.Minute = Time.Struct.Minutes; TimeFields.Second = Time.Struct.TwoSeconds*(USHORT )2; TimeFields.Milliseconds = 0; // // Make sure that the times specified in the SMB are reasonable // before converting them. // if (TimeFields.Year < 1601) { TimeFields.Year = 1601; } if (TimeFields.Month > 12) { TimeFields.Month = 12; } if (TimeFields.Hour >= 24) { TimeFields.Hour = 23; } if (TimeFields.Minute >= 60) { TimeFields.Minute = 59; } if (TimeFields.Second >= 60) { TimeFields.Second = 59; } if (!RtlTimeFieldsToTime(&TimeFields, &OutputTime)) { OutputTime.HighPart = 0; OutputTime.LowPart = 0; return OutputTime; } if (ARGUMENT_PRESENT(Server)) { OutputTime.QuadPart = OutputTime.QuadPart + Server->TimeZoneBias.QuadPart; } ExLocalTimeToSystemTime(&OutputTime, &OutputTime); } return OutputTime; } BOOLEAN MRxSmbConvertTimeToSmbTime ( IN PLARGE_INTEGER InputTime, IN PSMB_EXCHANGE Exchange OPTIONAL, OUT PSMB_TIME Time, OUT PSMB_DATE Date ) /*++ Routine Description: This routine converts an NT time structure to an SMB time. Arguments: IN LARGE_INTEGER InputTime - Supplies the time to convert. OUT PSMB_TIME Time - Returns the converted time of day. OUT PSMB_DATE Date - Returns the converted day of the year. Return Value: BOOLEAN - TRUE if input time could be converted. --*/ { TIME_FIELDS TimeFields; PAGED_CODE(); if (InputTime->LowPart == 0 && InputTime->HighPart == 0) { Time->Ushort = Date->Ushort = 0; } else { LARGE_INTEGER LocalTime; ExSystemTimeToLocalTime(InputTime, &LocalTime); if (ARGUMENT_PRESENT(Exchange)) { PSMBCE_SERVER Server = &Exchange->SmbCeContext.pServerEntry->Server; LocalTime.QuadPart -= Server->TimeZoneBias.QuadPart; } RtlTimeToTimeFields(&LocalTime, &TimeFields); if (TimeFields.Year < 1980) { return FALSE; } Date->Struct.Year = (USHORT )(TimeFields.Year - 1980); Date->Struct.Month = TimeFields.Month; Date->Struct.Day = TimeFields.Day; Time->Struct.Hours = TimeFields.Hour; Time->Struct.Minutes = TimeFields.Minute; // // When converting from a higher granularity time to a lesser // granularity time (seconds to 2 seconds), always round up // the time, don't round down. // Time->Struct.TwoSeconds = (TimeFields.Second + (USHORT)1) / (USHORT )2; } return TRUE; } BOOLEAN MRxSmbTimeToSecondsSince1970 ( IN PLARGE_INTEGER CurrentTime, //IN PSMB_EXCHANGE Exchange OPTIONAL, IN PSMBCE_SERVER Server OPTIONAL, OUT PULONG SecondsSince1970 ) /*++ Routine Description: This routine returns the CurrentTime in UTC and returns the equivalent current time in the servers timezone. Arguments: IN PLARGE_INTEGER CurrentTime - Supplies the current system time in UTC. IN PSMB_EXCHANGE Exchange - Supplies the difference in timezones between the server and the workstation. If not supplied then the assumption is that they are in the same timezone. OUT PULONG SecondsSince1970 - Returns the # of seconds since 1970 in the servers timezone or MAXULONG if conversion fails. Return Value: BOOLEAN - TRUE if the time could be converted. --*/ { LARGE_INTEGER ServerTime; LARGE_INTEGER TempTime; BOOLEAN ReturnValue; PAGED_CODE(); if (ARGUMENT_PRESENT(Server)) { TempTime.QuadPart = (*CurrentTime).QuadPart - Server->TimeZoneBias.QuadPart; ExSystemTimeToLocalTime(&TempTime, &ServerTime); } else { ExSystemTimeToLocalTime(CurrentTime, &ServerTime); } ReturnValue = RtlTimeToSecondsSince1970(&ServerTime, SecondsSince1970); if ( ReturnValue == FALSE ) { // // We can't represent the time legally, peg it at // the max legal time. // *SecondsSince1970 = MAXULONG; } return ReturnValue; } VOID MRxSmbSecondsSince1970ToTime ( IN ULONG SecondsSince1970, //IN PSMB_EXCHANGE Exchange OPTIONAL, IN PSMBCE_SERVER Server, OUT PLARGE_INTEGER CurrentTime ) /*++ Routine Description: This routine returns the Local system time derived from a time in seconds in the servers timezone. Arguments: IN ULONG SecondsSince1970 - Supplies the # of seconds since 1970 in servers timezone. IN PSMB_EXCHANGE Exchange - Supplies the difference in timezones between the server and the workstation. If not supplied then the assumption is that they are in the same timezone. OUT PLARGE_INTEGER CurrentTime - Returns the current system time in UTC. Return Value: None. --*/ { LARGE_INTEGER LocalTime; RtlSecondsSince1970ToTime (SecondsSince1970, &LocalTime); ExLocalTimeToSystemTime(&LocalTime, CurrentTime); if (ARGUMENT_PRESENT(Server)) { (*CurrentTime).QuadPart = (*CurrentTime).QuadPart + Server->TimeZoneBias.QuadPart; } return; } ULONG MRxSmbMapSmbAttributes ( IN USHORT SmbAttribs ) /*++ Routine Description: This routine maps an SMB (DOS/OS2) file attribute into an NT file attribute. Arguments: IN USHORT SmbAttribs - Supplies the SMB attribute to map. Return Value: ULONG - NT Attribute mapping SMB attribute --*/ { ULONG Attributes = 0; if (SmbAttribs==0) { Attributes = FILE_ATTRIBUTE_NORMAL; } else { ASSERT (SMB_FILE_ATTRIBUTE_READONLY == FILE_ATTRIBUTE_READONLY); ASSERT (SMB_FILE_ATTRIBUTE_HIDDEN == FILE_ATTRIBUTE_HIDDEN); ASSERT (SMB_FILE_ATTRIBUTE_SYSTEM == FILE_ATTRIBUTE_SYSTEM); ASSERT (SMB_FILE_ATTRIBUTE_ARCHIVE == FILE_ATTRIBUTE_ARCHIVE); ASSERT (SMB_FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY); Attributes = SmbAttribs & FILE_ATTRIBUTE_VALID_FLAGS; } return Attributes; } USHORT MRxSmbMapDisposition ( IN ULONG Disposition ) /*++ Routine Description: This routine takes an NT disposition, and maps it into an OS/2 CreateAction to be put into an SMB. Arguments: IN ULONG Disposition - Supplies the NT disposition to map. Return Value: USHORT - OS/2 Access mapping that maps NT access --*/ { PAGED_CODE(); switch (Disposition) { case FILE_OVERWRITE_IF: case FILE_SUPERSEDE: return SMB_OFUN_OPEN_TRUNCATE | SMB_OFUN_CREATE_CREATE; break; case FILE_CREATE: return SMB_OFUN_OPEN_FAIL | SMB_OFUN_CREATE_CREATE; break; case FILE_OVERWRITE: return SMB_OFUN_OPEN_TRUNCATE | SMB_OFUN_CREATE_FAIL; break; case FILE_OPEN: return SMB_OFUN_OPEN_OPEN | SMB_OFUN_CREATE_FAIL; break; case FILE_OPEN_IF: return SMB_OFUN_OPEN_OPEN | SMB_OFUN_CREATE_CREATE; break; default: return 0; break; } } ULONG MRxSmbUnmapDisposition ( IN USHORT SmbDisposition ) /*++ Routine Description: This routine takes an OS/2 disposition and maps it into an NT disposition. Arguments: IN USHORT SmbDisposition - Supplies the OS/2 disposition to map. Return Value: ULONG - NT disposition mapping OS/2 disposition --*/ { // // Mask off oplocked bit. // switch (SmbDisposition & 0x7fff) { case SMB_OACT_OPENED: return FILE_OPENED; break; case SMB_OACT_CREATED: return FILE_CREATED; break; case SMB_OACT_TRUNCATED: return FILE_OVERWRITTEN; break; } ASSERT(!"not a reasonable smbdiposition"); return 0; } USHORT MRxSmbMapDesiredAccess ( IN ULONG DesiredAccess ) /*++ Routine Description: This routine takes an NT DesiredAccess value and converts it to an OS/2 access mode. Arguments: IN ULONG DesiredAccess - Supplies the NT desired access to map. Return Value: USHORT - The mapped OS/2 access mode that compares to the NT code specified. If there is no mapping for the NT code, we return -1 as the access mode. --*/ { PAGED_CODE(); // // If the user asked for both read and write access, return read/write. // if ((DesiredAccess & FILE_READ_DATA)&&(DesiredAccess & FILE_WRITE_DATA)) { return SMB_DA_ACCESS_READ_WRITE; } // // If the user requested WRITE_DATA, return write. // if (DesiredAccess & FILE_WRITE_DATA) { return SMB_DA_ACCESS_WRITE; } // // If the user requested READ_DATA, return read. // if (DesiredAccess & FILE_READ_DATA) { return SMB_DA_ACCESS_READ; } // // If the user requested ONLY execute access, then request execute // access. Execute access is the "weakest" of the possible desired // accesses, so it takes least precedence. // if (DesiredAccess & FILE_EXECUTE) { return SMB_DA_ACCESS_EXECUTE; } // // If we couldn't figure out what we were doing, return -1 // // Among the attributes that we do not map are: // // FILE_READ_ATTRIBUTES // FILE_WRITE_ATTRIBUTES // FILE_READ_EAS // FILE_WRITE_EAS // return (USHORT)-1; } USHORT MRxSmbMapShareAccess ( IN USHORT ShareAccess ) /*++ Routine Description: This routine takes an NT ShareAccess value and converts it to an OS/2 sharing mode. Arguments: IN USHORT ShareAccess - Supplies the OS/2 share access to map. Return Value: USHORT - The mapped OS/2 sharing mode that compares to the NT code specified --*/ { USHORT ShareMode = SMB_DA_SHARE_EXCLUSIVE; PAGED_CODE(); if ((ShareAccess & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == (FILE_SHARE_READ | FILE_SHARE_WRITE)) { ShareMode = SMB_DA_SHARE_DENY_NONE; } else if (ShareAccess & FILE_SHARE_READ) { ShareMode = SMB_DA_SHARE_DENY_WRITE; } else if (ShareAccess & FILE_SHARE_WRITE) { ShareMode = SMB_DA_SHARE_DENY_READ; } return ShareMode; } USHORT MRxSmbMapFileAttributes ( IN ULONG FileAttributes ) /*++ Routine Description: This routine takes an NT file attribute mapping and converts it into an OS/2 file attribute definition. Arguments: IN ULONG FileAttributes - Supplies the file attributes to map. Return Value: USHORT --*/ { USHORT ResultingAttributes = 0; PAGED_CODE(); if (FileAttributes==FILE_ATTRIBUTE_NORMAL) { return ResultingAttributes; } if (FileAttributes & FILE_ATTRIBUTE_READONLY) { ResultingAttributes |= SMB_FILE_ATTRIBUTE_READONLY; } if (FileAttributes & FILE_ATTRIBUTE_HIDDEN) { ResultingAttributes |= SMB_FILE_ATTRIBUTE_HIDDEN; } if (FileAttributes & FILE_ATTRIBUTE_SYSTEM) { ResultingAttributes |= SMB_FILE_ATTRIBUTE_SYSTEM; } if (FileAttributes & FILE_ATTRIBUTE_ARCHIVE) { ResultingAttributes |= SMB_FILE_ATTRIBUTE_ARCHIVE; } return ResultingAttributes; }