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.

2576 lines
84 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. DownLvlO.c
  5. Abstract:
  6. This module implements downlevel opens.
  7. Author:
  8. Joe Linn [JoeLi] 7-March-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. ////
  14. //// The Bug check file id for this module
  15. ////
  16. //
  17. //#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE)
  18. //
  19. // The debug trace level
  20. //
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, MRxSmbGetFileAttributes)
  23. #pragma alloc_text(PAGE, MRxSmbCoreDeleteForSupercedeOrClose)
  24. #pragma alloc_text(PAGE, MRxSmbCoreCheckPath)
  25. #pragma alloc_text(PAGE, MRxSmbCoreOpen)
  26. #pragma alloc_text(PAGE, MRxSmbSetFileAttributes)
  27. #pragma alloc_text(PAGE, MRxSmbCoreCreateDirectory)
  28. #pragma alloc_text(PAGE, MRxSmbCoreCreate)
  29. #pragma alloc_text(PAGE, MRxSmbCloseAfterCoreCreate)
  30. #pragma alloc_text(PAGE, MRxSmbCoreTruncate)
  31. #pragma alloc_text(PAGE, MRxSmbDownlevelCreate)
  32. #pragma alloc_text(PAGE, MRxSmbFinishGFA)
  33. #pragma alloc_text(PAGE, MRxSmbFinishCoreCreate)
  34. #pragma alloc_text(PAGE, MRxSmbPopulateFileInfoInOE)
  35. #pragma alloc_text(PAGE, MRxSmbFinishCoreOpen)
  36. #pragma alloc_text(PAGE, MRxSmbPseudoOpenTailFromCoreCreateDirectory)
  37. #pragma alloc_text(PAGE, MRxSmbPseudoOpenTailFromFakeGFAResponse)
  38. #pragma alloc_text(PAGE, MRxSmbPseudoOpenTailFromGFAResponse)
  39. #pragma alloc_text(PAGE, MRxSmbConvertSmbTimeToTime)
  40. #pragma alloc_text(PAGE, MRxSmbConvertTimeToSmbTime)
  41. #pragma alloc_text(PAGE, MRxSmbTimeToSecondsSince1970)
  42. #pragma alloc_text(PAGE, MRxSmbSecondsSince1970ToTime)
  43. #pragma alloc_text(PAGE, MRxSmbMapSmbAttributes)
  44. #pragma alloc_text(PAGE, MRxSmbMapDisposition)
  45. #pragma alloc_text(PAGE, MRxSmbUnmapDisposition)
  46. #pragma alloc_text(PAGE, MRxSmbMapDesiredAccess)
  47. #pragma alloc_text(PAGE, MRxSmbMapShareAccess)
  48. #pragma alloc_text(PAGE, MRxSmbMapFileAttributes)
  49. #endif
  50. #define Dbg (DEBUG_TRACE_CREATE)
  51. #pragma warning(error:4101) // Unreferenced local variable
  52. VOID
  53. MRxSmbPopulateFileInfoInOE(
  54. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  55. USHORT FileAttributes,
  56. ULONG LastWriteTimeInSeconds,
  57. ULONG FileSize
  58. );
  59. PVOID
  60. MRxSmbPopulateFcbInitPacketForCore(void);
  61. NTSTATUS
  62. MRxSmbPseudoOpenTailFromGFAResponse (
  63. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  64. );
  65. NTSTATUS
  66. MRxSmbPseudoOpenTailFromFakeGFAResponse (
  67. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  68. RX_FILE_TYPE StorageType
  69. );
  70. NTSTATUS
  71. MRxSmbPseudoOpenTailFromCoreCreateDirectory (
  72. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  73. USHORT Attributes
  74. );
  75. //CODE.IMPROVEMENT all of these routines that do a single core operation are to
  76. // be rolled up into a single routine......
  77. // for this reason, we shouldn't worry about the commonality...the more the better!
  78. NTSTATUS
  79. MRxSmbGetFileAttributes(
  80. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  81. )
  82. /*++
  83. Routine Description:
  84. This routine does a GetFileAttributes and remembers the reponse. This routine also
  85. does the cache for the file information.
  86. Arguments:
  87. OrdinaryExchange - an exchange to be used for conducting this open.
  88. Return Value:
  89. RXSTATUS - The return status for the operation
  90. Notes:
  91. --*/
  92. {
  93. NTSTATUS Status;
  94. RxCaptureFcb;
  95. RxCaptureFobx;
  96. PMRX_SRV_OPEN SrvOpen = NULL;
  97. PMRX_SMB_SRV_OPEN smbSrvOpen = NULL;
  98. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  99. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  100. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(Exchange);
  101. PSMBSTUFFER_BUFFER_STATE StufferState;
  102. PAGED_CODE();
  103. RxDbgTrace(+1, Dbg, ("MRxSmbSynchronousGetFileAttributes entering.......OE=%08lx\n",OrdinaryExchange));
  104. if (FsRtlDoesNameContainWildCards(RemainingName)) {
  105. Status = RX_MAP_STATUS(OBJECT_NAME_INVALID);
  106. goto FINALLY;
  107. }
  108. if (MRxSmbIsFileNotFoundCached(RxContext)) {
  109. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  110. goto FINALLY;
  111. }
  112. // Try to find the cached file infomation
  113. if (MRxSmbIsFileInfoCacheFound(RxContext,
  114. &OrdinaryExchange->Create.FileInfo,
  115. &Status,
  116. NULL)){
  117. goto FINALLY;
  118. }
  119. // If the file has already been opened a QUERY_INFORMATION2 can be issued while
  120. // QUERY_INFORMATION can only be issued against pseudo opened and not yet
  121. // opened files.
  122. if (capFobx != NULL) {
  123. SrvOpen = capFobx->pSrvOpen;
  124. if (SrvOpen != NULL)
  125. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  126. }
  127. StufferState = &OrdinaryExchange->AssociatedStufferState;
  128. if (pServerEntry->Server.Dialect > PCNET1_DIALECT &&
  129. (smbSrvOpen != NULL) &&
  130. (!FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN) &&
  131. !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN) &&
  132. (NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE))) {
  133. COVERED_CALL(
  134. MRxSmbStartSMBCommand(
  135. StufferState,
  136. SetInitialSMB_ForReuse,
  137. SMB_COM_QUERY_INFORMATION2,
  138. SMB_REQUEST_SIZE(QUERY_INFORMATION2),
  139. NO_EXTRA_DATA,
  140. SMB_BEST_ALIGNMENT(1,0),
  141. RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  142. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  143. );
  144. MRxSmbDumpStufferState (1100,"SMB w/ GFA before stuffing",StufferState);
  145. MRxSmbStuffSMB (
  146. StufferState,
  147. "0wB!",
  148. // 0 UCHAR WordCount;
  149. smbSrvOpen->Fid, // w _USHORT(Fid);
  150. SMB_WCT_CHECK(1) 0 // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  151. // UCHAR Buffer[1]; // Buffer containing:
  152. );
  153. MRxSmbDumpStufferState (700,"SMB w/ GFA after stuffing",StufferState);
  154. } else {
  155. COVERED_CALL(
  156. MRxSmbStartSMBCommand(
  157. StufferState,
  158. SetInitialSMB_ForReuse,
  159. SMB_COM_QUERY_INFORMATION,
  160. SMB_REQUEST_SIZE(QUERY_INFORMATION),
  161. NO_EXTRA_DATA,
  162. SMB_BEST_ALIGNMENT(1,0),
  163. RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  164. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  165. );
  166. MRxSmbDumpStufferState (1100,"SMB w/ GFA before stuffing",StufferState);
  167. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  168. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  169. MRxSmbStuffSMB (
  170. StufferState,
  171. "0B4!",
  172. // 0 UCHAR WordCount; // Count of parameter words = 0
  173. SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  174. // UCHAR Buffer[1]; // Buffer containing:
  175. RemainingName
  176. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  177. // //UCHAR FileName[]; // File name
  178. );
  179. MRxSmbDumpStufferState (700,"SMB w/ GFA after stuffing",StufferState);
  180. }
  181. Status = SmbPseOrdinaryExchange(
  182. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  183. SMBPSE_OETYPE_GFA
  184. );
  185. if (NT_SUCCESS(Status)) {
  186. MRxSmbCreateFileInfoCache(RxContext,
  187. &OrdinaryExchange->Create.FileInfo,
  188. pServerEntry,
  189. Status);
  190. } else {
  191. if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  192. Status == STATUS_OBJECT_PATH_NOT_FOUND) {
  193. // create the name based file not found cache
  194. MRxSmbCacheFileNotFound(RxContext);
  195. } else {
  196. // invalid the name based file not found cache if other error happens
  197. MRxSmbInvalidateFileNotFoundCache(RxContext);
  198. }
  199. }
  200. FINALLY:
  201. if (NT_SUCCESS(Status)) {
  202. OrdinaryExchange->Create.StorageTypeFromGFA =
  203. OrdinaryExchange->Create.FileInfo.Standard.Directory ?
  204. FileTypeDirectory : FileTypeFile;
  205. }
  206. RxDbgTrace(-1, Dbg, ("MRxSmbSynchronousGetFileAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  207. return(Status);
  208. }
  209. NTSTATUS
  210. MRxSmbCoreDeleteForSupercedeOrClose(
  211. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  212. BOOLEAN DeleteDirectory
  213. )
  214. /*++
  215. Routine Description:
  216. This routine does a GetFileAttributes and remembers the reponse.
  217. Arguments:
  218. OrdinaryExchange - an exchange to be used for conducting this open.
  219. Return Value:
  220. RXSTATUS - The return status for the operation
  221. Notes:
  222. --*/
  223. {
  224. NTSTATUS Status;
  225. RxCaptureFcb;
  226. RxCaptureFobx;
  227. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  228. PSMBSTUFFER_BUFFER_STATE StufferState;
  229. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  230. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  231. PAGED_CODE();
  232. RxDbgTrace(+1, Dbg, ("MRxSmbCoreDeleteForSupercede entering.......OE=%08lx\n",OrdinaryExchange));
  233. StufferState = &OrdinaryExchange->AssociatedStufferState;
  234. ASSERT( StufferState );
  235. ASSERT( OrdinaryExchange->pPathArgument1 != NULL );
  236. //
  237. if (!DeleteDirectory) {
  238. ULONG SearchAttributes = SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN; // a la rdr1
  239. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_DELETE,
  240. SMB_REQUEST_SIZE(DELETE),
  241. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  242. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  243. );
  244. MRxSmbDumpStufferState (1100,"SMB w/ del before stuffing",StufferState);
  245. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since it's in UNICODE
  246. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  247. // on the other hand, if it's NT<-->NT we don't do it here anyway
  248. MRxSmbStuffSMB (StufferState,
  249. "0wB4!",
  250. // 0 UCHAR WordCount; // Count of parameter words = 1
  251. SearchAttributes, // w _USHORT( SearchAttributes );
  252. SMB_WCT_CHECK(1) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  253. // UCHAR Buffer[1]; // Buffer containing:
  254. OrdinaryExchange->pPathArgument1
  255. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  256. // //UCHAR FileName[]; // File name
  257. );
  258. } else {
  259. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_DELETE_DIRECTORY,
  260. SMB_REQUEST_SIZE(DELETE_DIRECTORY),
  261. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  262. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  263. );
  264. MRxSmbDumpStufferState (1100,"SMB w/ rmdir before stuffing",StufferState);
  265. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  266. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  267. MRxSmbStuffSMB (StufferState,
  268. "0B4!",
  269. // 0 UCHAR WordCount; // Count of parameter words = 0
  270. SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  271. // UCHAR Buffer[1]; // Buffer containing:
  272. OrdinaryExchange->pPathArgument1
  273. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  274. // //UCHAR FileName[]; // File name
  275. );
  276. }
  277. MRxSmbDumpStufferState (700,"SMB w/ del/rmdir after stuffing",StufferState);
  278. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  279. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE
  280. );
  281. if (Status == STATUS_SUCCESS) {
  282. // invalid the name based file info cache
  283. MRxSmbInvalidateFileInfoCache(RxContext);
  284. MRxSmbInvalidateInternalFileInfoCache(RxContext);
  285. MRxSmbCacheFileNotFound(RxContext);
  286. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_FILE_DELETED);
  287. } else {
  288. RxLog(("Delete File: %x %wZ\n",Status,OrdinaryExchange->pPathArgument1));
  289. SmbLog(LOG,
  290. MRxSmbCoreDeleteForSupercedeOrClose,
  291. LOGULONG(Status)
  292. LOGUSTR(*OrdinaryExchange->pPathArgument1));
  293. }
  294. FINALLY:
  295. RxDbgTrace(-1, Dbg, ("MRxSmbCoreDeleteForSupercede exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  296. return(Status);
  297. }
  298. NTSTATUS
  299. MRxSmbCoreCheckPath(
  300. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  301. )
  302. /*++
  303. Routine Description:
  304. This routine does a GetFileAttributes and remembers the reponse.
  305. Arguments:
  306. OrdinaryExchange - an exchange to be used for conducting this open.
  307. Return Value:
  308. RXSTATUS - The return status for the operation
  309. Notes:
  310. --*/
  311. {
  312. NTSTATUS Status;
  313. FILE_BASIC_INFORMATION FileInfoBasic;
  314. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  315. PSMBSTUFFER_BUFFER_STATE StufferState;
  316. PAGED_CODE();
  317. RxDbgTrace(+1, Dbg, ("MRxSmbCoreCheckPath entering.......OE=%08lx\n",
  318. OrdinaryExchange));
  319. // Try to find the cached file infomation
  320. if (MRxSmbIsBasicFileInfoCacheFound(RxContext,
  321. &FileInfoBasic,
  322. &Status,
  323. OrdinaryExchange->pPathArgument1)){
  324. if (Status == STATUS_SUCCESS) {
  325. if (!(FileInfoBasic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  326. Status = STATUS_NOT_A_DIRECTORY;
  327. }
  328. goto FINALLY;
  329. }
  330. }
  331. StufferState = &OrdinaryExchange->AssociatedStufferState;
  332. ASSERT( StufferState );
  333. COVERED_CALL(MRxSmbStartSMBCommand
  334. (StufferState,SetInitialSMB_ForReuse,
  335. SMB_COM_CHECK_DIRECTORY,
  336. SMB_REQUEST_SIZE(CHECK_DIRECTORY),
  337. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),
  338. RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  339. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  340. );
  341. MRxSmbDumpStufferState (1100,"SMB w/ chkdir before stuffing",StufferState);
  342. //CODE.IMPROVEMENT many of these single argument guys can be rooled up
  343. MRxSmbStuffSMB (StufferState,
  344. "0B4!",
  345. // UCHAR WordCount; // Count of parameter words = 0
  346. SMB_WCT_CHECK(0)
  347. // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  348. // UCHAR Buffer[1]; // Buffer containing:
  349. OrdinaryExchange->pPathArgument1
  350. // 4 UCHAR BufferFormat; // 0x04 -- ASCII
  351. // UCHAR FileName[]; // File name
  352. );
  353. MRxSmbDumpStufferState (700,"SMB w/ chkdir after stuffing",StufferState);
  354. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  355. SMBPSE_OETYPE_CORECHECKDIRECTORY
  356. );
  357. FINALLY:
  358. RxDbgTrace(-1, Dbg,
  359. ("MRxSmbCoreCheckPath exiting.......OE=%08lx, st=%08lx\n",
  360. OrdinaryExchange,Status)
  361. );
  362. return(Status);
  363. }
  364. NTSTATUS
  365. MRxSmbCoreOpen(
  366. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  367. ULONG OpenShareMode,
  368. ULONG Attribute
  369. )
  370. /*++
  371. Routine Description:
  372. This routine does a core open.
  373. Arguments:
  374. OrdinaryExchange - an exchange to be used for conducting this open.
  375. Return Value:
  376. RXSTATUS - The return status for the operation
  377. Notes:
  378. --*/
  379. {
  380. NTSTATUS Status = STATUS_SUCCESS;
  381. RxCaptureFcb; //RxCaptureFobx;
  382. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  383. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  384. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  385. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(Exchange);
  386. PSMBSTUFFER_BUFFER_STATE StufferState;
  387. PAGED_CODE();
  388. RxDbgTrace(+1, Dbg, ("MRxSmbCoreOpen entering.......OE=%08lx\n",OrdinaryExchange));
  389. StufferState = &OrdinaryExchange->AssociatedStufferState;
  390. ASSERT( StufferState );
  391. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  392. ASSERT( RxContext->MajorFunction == IRP_MJ_CREATE );
  393. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_OPEN,
  394. SMB_REQUEST_SIZE(OPEN),
  395. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  396. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  397. );
  398. MRxSmbDumpStufferState (1100,"SMB w/ coreopen before stuffing",StufferState);
  399. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  400. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  401. MRxSmbStuffSMB (StufferState,
  402. "0wwB4!",
  403. // 0 UCHAR WordCount; // Count of parameter words = 2
  404. OpenShareMode, // w _USHORT( DesiredAccess ); // Mode - read/write/share
  405. Attribute, // w _USHORT( SearchAttributes );
  406. SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  407. // UCHAR Buffer[1]; // Buffer containing:
  408. RemainingName
  409. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  410. // //UCHAR FileName[]; // File name
  411. );
  412. MRxSmbDumpStufferState (700,"SMB w/ coreopen after stuffing",StufferState);
  413. //ASSERT(!"Now it's stuffed");
  414. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  415. SMBPSE_OETYPE_COREOPEN
  416. );
  417. FINALLY:
  418. RxDbgTrace(-1, Dbg, ("MRxSmbCoreOpen exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  419. return(Status);
  420. }
  421. NTSTATUS
  422. MRxSmbSetFileAttributes(
  423. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  424. ULONG SmbAttributes
  425. )
  426. /*++
  427. Routine Description:
  428. This routine does a core create directory.....
  429. Arguments:
  430. OrdinaryExchange - an exchange to be used for conducting this open.
  431. Return Value:
  432. RXSTATUS - The return status for the operation
  433. Notes:
  434. --*/
  435. {
  436. NTSTATUS Status = STATUS_SUCCESS;
  437. RxCaptureFcb;
  438. RxCaptureFobx;
  439. PMRX_SRV_OPEN SrvOpen = NULL;
  440. PMRX_SMB_SRV_OPEN smbSrvOpen = NULL;
  441. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
  442. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  443. ULONG LastWriteTime = 0;
  444. ULONG FileAttributes = 0;
  445. PLARGE_INTEGER pCreationTime = NULL;
  446. PLARGE_INTEGER pLastWriteTime = NULL;
  447. PLARGE_INTEGER pLastAccessTime = NULL;
  448. SMB_TIME SmbCreationTime;
  449. SMB_DATE SmbCreationDate;
  450. SMB_TIME SmbLastWriteTime;
  451. SMB_DATE SmbLastWriteDate;
  452. SMB_TIME SmbLastAccessTime;
  453. SMB_DATE SmbLastAccessDate;
  454. PSMBSTUFFER_BUFFER_STATE StufferState;
  455. BOOLEAN TimeSpecified = FALSE;
  456. PAGED_CODE();
  457. RxDbgTrace(+1, Dbg, ("MRxSmbSetFileAttributes entering.......OE=%08lx\n",OrdinaryExchange));
  458. StufferState = &OrdinaryExchange->AssociatedStufferState;
  459. ASSERT( StufferState );
  460. if (capFobx != NULL) {
  461. SrvOpen = capFobx->pSrvOpen;
  462. if (SrvOpen != NULL)
  463. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  464. }
  465. SmbCreationTime.Ushort = 0;
  466. SmbCreationDate.Ushort = 0;
  467. SmbLastWriteTime.Ushort = 0;
  468. SmbLastWriteDate.Ushort = 0;
  469. SmbLastAccessTime.Ushort = 0;
  470. SmbLastAccessDate.Ushort = 0;
  471. if (RxContext->MajorFunction == IRP_MJ_SET_INFORMATION) {
  472. BOOLEAN GoodTime;
  473. FileAttributes = ((PFILE_BASIC_INFORMATION)OrdinaryExchange->Info.Buffer)->FileAttributes;
  474. pCreationTime = &((PFILE_BASIC_INFORMATION)OrdinaryExchange->Info.Buffer)->CreationTime;
  475. pLastWriteTime = &((PFILE_BASIC_INFORMATION)OrdinaryExchange->Info.Buffer)->LastWriteTime;
  476. pLastAccessTime = &((PFILE_BASIC_INFORMATION)OrdinaryExchange->Info.Buffer)->LastAccessTime;
  477. if (pLastWriteTime->QuadPart != 0) {
  478. GoodTime = MRxSmbTimeToSecondsSince1970(
  479. pLastWriteTime,
  480. SmbCeGetExchangeServer(OrdinaryExchange),
  481. &LastWriteTime);
  482. if (!GoodTime) {
  483. Status = STATUS_INVALID_PARAMETER;
  484. goto FINALLY;
  485. }
  486. GoodTime = MRxSmbConvertTimeToSmbTime(pLastWriteTime,
  487. (PSMB_EXCHANGE)OrdinaryExchange,
  488. &SmbLastWriteTime,
  489. &SmbLastWriteDate);
  490. if (!GoodTime) {
  491. Status = STATUS_INVALID_PARAMETER;
  492. goto FINALLY;
  493. }
  494. TimeSpecified = TRUE;
  495. }
  496. if (pLastAccessTime->QuadPart != 0) {
  497. GoodTime = MRxSmbConvertTimeToSmbTime(pLastAccessTime,
  498. (PSMB_EXCHANGE)OrdinaryExchange,
  499. &SmbLastAccessTime,
  500. &SmbLastAccessDate);
  501. if (!GoodTime) {
  502. Status = STATUS_INVALID_PARAMETER;
  503. goto FINALLY;
  504. }
  505. TimeSpecified = TRUE;
  506. }
  507. if (pCreationTime->QuadPart != 0) {
  508. GoodTime = MRxSmbConvertTimeToSmbTime(pCreationTime,
  509. (PSMB_EXCHANGE)OrdinaryExchange,
  510. &SmbCreationTime,
  511. &SmbCreationDate);
  512. if (!GoodTime) {
  513. Status = STATUS_INVALID_PARAMETER;
  514. goto FINALLY;
  515. }
  516. TimeSpecified = TRUE;
  517. }
  518. if (!TimeSpecified && (FileAttributes == 0))
  519. {
  520. // caller didn't specify anything worth doing. Return success
  521. // 442486
  522. Status = STATUS_SUCCESS;
  523. goto FINALLY;
  524. }
  525. }
  526. if (smbSrvOpen == NULL ||
  527. FileAttributes != 0 ||
  528. RxContext->MajorFunction != IRP_MJ_SET_INFORMATION ||
  529. FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN) ||
  530. FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN) ||
  531. (pLastWriteTime->QuadPart == 0 && pLastAccessTime->QuadPart == 0 && pCreationTime->QuadPart == 0)) {
  532. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,
  533. SMB_COM_SET_INFORMATION,
  534. SMB_REQUEST_SIZE(SET_INFORMATION),
  535. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  536. 0,0,0,0 STUFFERTRACE(Dbg,'FC')));
  537. MRxSmbDumpStufferState (1100,"SMB w/ sfa before stuffing",StufferState);
  538. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  539. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  540. MRxSmbStuffSMB (StufferState,
  541. "0wdwwwwwB4!",
  542. // 0 UCHAR WordCount; // Count of parameter words = 8
  543. SmbAttributes, // w _USHORT( FileAttributes );
  544. LastWriteTime, // d _ULONG( LastWriteTimeInSeconds );
  545. 0,0,0,0,0, // 5*w _USHORT( Reserved )[5]; // Reserved (must be 0)
  546. SMB_WCT_CHECK(8) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  547. // UCHAR Buffer[1]; // Buffer containing:
  548. RemainingName
  549. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  550. // //UCHAR FileName[]; // File name
  551. );
  552. MRxSmbDumpStufferState (700,"SMB w/ sfa after stuffing",StufferState);
  553. //ASSERT(!"Now it's stuffed");
  554. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  555. SMBPSE_OETYPE_SFA);
  556. } else {
  557. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,
  558. SMB_COM_SET_INFORMATION2,
  559. SMB_REQUEST_SIZE(SET_INFORMATION2),
  560. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  561. 0,0,0,0 STUFFERTRACE(Dbg,'FC')));
  562. MRxSmbDumpStufferState (1100,"SMB w/ sfa 2 before stuffing",StufferState);
  563. MRxSmbStuffSMB (StufferState,
  564. "0wwwwwwwB!",
  565. // 0 UCHAR WordCount; // Count of parameter words = 8
  566. smbSrvOpen->Fid, // w _USHORT( Fid ); // File handle
  567. SmbCreationDate.Ushort, // w SMB_TIME CreationDate;
  568. SmbCreationTime.Ushort, // w SMB_TIME CreationTime;
  569. SmbLastAccessDate.Ushort, // w SMB_TIME LastAccessDate;
  570. SmbLastAccessTime.Ushort, // w SMB_TIME LastAccessTime;
  571. SmbLastWriteDate.Ushort, // w SMB_TIME LastWriteDate;
  572. SmbLastWriteTime.Ushort, // w SMB_TIME LastWriteTime;
  573. SMB_WCT_CHECK(7) 0 // _USHORT( ByteCount ); // Count of data bytes; min = 0
  574. // UCHAR Buffer[1]; // Reserved buffer
  575. );
  576. MRxSmbDumpStufferState (700,"SMB w/ sfa 2 after stuffing",StufferState);
  577. //ASSERT(!"Now it's stuffed");
  578. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  579. SMBPSE_OETYPE_SFA2);
  580. }
  581. if (Status == STATUS_SUCCESS) {
  582. if (RxContext->MajorFunction != IRP_MJ_SET_INFORMATION) {
  583. FileAttributes = MRxSmbMapSmbAttributes((USHORT)SmbAttributes);
  584. }
  585. MRxSmbUpdateBasicFileInfoCache(RxContext,
  586. FileAttributes,
  587. pLastWriteTime);
  588. MRxSmbUpdateStandardFileInfoCache(RxContext,
  589. NULL,
  590. (BOOLEAN)(FileAttributes & FILE_ATTRIBUTE_DIRECTORY));
  591. MRxSmbInvalidateFileNotFoundCache(RxContext);
  592. } else {
  593. if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  594. Status == STATUS_OBJECT_PATH_NOT_FOUND) {
  595. // create the name based file not found cache
  596. MRxSmbCacheFileNotFound(RxContext);
  597. } else {
  598. // invalid the name based file not found cache if other error happens
  599. MRxSmbInvalidateFileNotFoundCache(RxContext);
  600. }
  601. // invalid the name based file info cache
  602. MRxSmbInvalidateFileInfoCache(RxContext);
  603. }
  604. FINALLY:
  605. RxDbgTrace(-1, Dbg, ("MRxSmbSFAAfterCreateDirectory exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  606. return(Status);
  607. }
  608. NTSTATUS
  609. MRxSmbCoreCreateDirectory(
  610. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  611. )
  612. /*++
  613. Routine Description:
  614. This routine does a core create directory.....
  615. Arguments:
  616. OrdinaryExchange - an exchange to be used for conducting this open.
  617. Return Value:
  618. RXSTATUS - The return status for the operation
  619. Notes:
  620. --*/
  621. {
  622. NTSTATUS Status;
  623. RxCaptureFcb; //RxCaptureFobx;
  624. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  625. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  626. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  627. PSMBSTUFFER_BUFFER_STATE StufferState;
  628. PAGED_CODE();
  629. RxDbgTrace(+1, Dbg, ("MRxSmbCoreCreateDirectory entering.......OE=%08lx\n",OrdinaryExchange));
  630. StufferState = &OrdinaryExchange->AssociatedStufferState;
  631. ASSERT( StufferState );
  632. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  633. ASSERT( RxContext->MajorFunction == IRP_MJ_CREATE );
  634. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse,
  635. SMB_COM_CREATE_DIRECTORY,
  636. SMB_REQUEST_SIZE(CREATE_DIRECTORY),
  637. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  638. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  639. );
  640. MRxSmbDumpStufferState (1100,"SMB w/ corecreatedir before stuffing",StufferState);
  641. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  642. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  643. MRxSmbStuffSMB (StufferState,
  644. "0B4!",
  645. // 0 UCHAR WordCount; // Count of parameter words = 0
  646. SMB_WCT_CHECK(0) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  647. // UCHAR Buffer[1]; // Buffer containing:
  648. RemainingName
  649. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  650. // //UCHAR FileName[]; // File name
  651. );
  652. MRxSmbDumpStufferState (700,"SMB w/ corecreatedir after stuffing",StufferState);
  653. //ASSERT(!"Now it's stuffed");
  654. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  655. SMBPSE_OETYPE_CORECREATEDIRECTORY
  656. );
  657. FINALLY:
  658. RxDbgTrace(-1, Dbg, ("MRxSmbCoreCreateDirectory exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  659. return(Status);
  660. }
  661. NTSTATUS
  662. MRxSmbCoreCreate(
  663. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  664. ULONG Attribute,
  665. BOOLEAN CreateNew
  666. )
  667. /*++
  668. Routine Description:
  669. This routine does a core create.....if the flag is set we use create new.
  670. Arguments:
  671. OrdinaryExchange - an exchange to be used for conducting this open.
  672. Return Value:
  673. RXSTATUS - The return status for the operation
  674. Notes:
  675. --*/
  676. {
  677. NTSTATUS Status;
  678. RxCaptureFcb; //RxCaptureFobx;
  679. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  680. PUNICODE_STRING RemainingName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  681. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  682. PSMBSTUFFER_BUFFER_STATE StufferState;
  683. PAGED_CODE();
  684. RxDbgTrace(+1, Dbg, ("MRxSmbCoreCreate entering.......OE=%08lx\n",OrdinaryExchange));
  685. StufferState = &OrdinaryExchange->AssociatedStufferState;
  686. ASSERT( StufferState );
  687. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  688. ASSERT( RxContext->MajorFunction == IRP_MJ_CREATE );
  689. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse,
  690. (UCHAR)(CreateNew?SMB_COM_CREATE_NEW:SMB_COM_CREATE),
  691. SMB_REQUEST_SIZE(CREATE),
  692. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  693. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  694. );
  695. MRxSmbDumpStufferState (1100,"SMB w/ coreopen before stuffing",StufferState);
  696. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  697. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  698. MRxSmbStuffSMB (StufferState,
  699. "0wdB4!",
  700. // 0 UCHAR WordCount; // Count of parameter words = 3
  701. Attribute, // w _USHORT( FileAttributes ); // New file attributes
  702. 0, // d _ULONG( CreationTimeInSeconds ); // Creation time
  703. SMB_WCT_CHECK(3) // B _USHORT( ByteCount ); // Count of data bytes; min = 2
  704. // UCHAR Buffer[1]; // Buffer containing:
  705. RemainingName
  706. // 4 //UCHAR BufferFormat; // 0x04 -- ASCII
  707. // //UCHAR FileName[]; // File name
  708. );
  709. MRxSmbDumpStufferState (700,"SMB w/ corecreate after stuffing",StufferState);
  710. //ASSERT(!"Now it's stuffed");
  711. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  712. SMBPSE_OETYPE_CORECREATE
  713. );
  714. FINALLY:
  715. RxDbgTrace(-1, Dbg, ("MRxSmbCoreCreate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  716. return(Status);
  717. }
  718. NTSTATUS
  719. MRxSmbCloseAfterCoreCreate(
  720. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  721. )
  722. /*++
  723. Routine Description:
  724. This routine does a close.....
  725. Arguments:
  726. OrdinaryExchange - an exchange to be used for conducting this open.
  727. Return Value:
  728. RXSTATUS - The return status for the operation
  729. Notes:
  730. --*/
  731. {
  732. NTSTATUS Status;
  733. RxCaptureFcb; RxCaptureFobx;
  734. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  735. PSMBSTUFFER_BUFFER_STATE StufferState;
  736. PAGED_CODE();
  737. RxDbgTrace(+1, Dbg, ("MRxSmbCloseAfterCoreCreate entering.......OE=%08lx\n",OrdinaryExchange));
  738. StufferState = &OrdinaryExchange->AssociatedStufferState;
  739. ASSERT( StufferState );
  740. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse,
  741. SMB_COM_CLOSE,
  742. SMB_REQUEST_SIZE(CLOSE),
  743. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  744. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  745. );
  746. MRxSmbDumpStufferState (1100,"SMB w/ closeaftercorecreate before stuffing",StufferState);
  747. MRxSmbStuffSMB (StufferState,
  748. "0wdB!",
  749. // 0 UCHAR WordCount; // Count of parameter words = 3
  750. // w _USHORT( Fid ); // File handle
  751. OrdinaryExchange->Create.FidReturnedFromCreate,
  752. 0, // d _ULONG( LastWriteTimeInSeconds ); // Time of last write, low and high
  753. SMB_WCT_CHECK(3) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  754. // UCHAR Buffer[1]; // empty
  755. );
  756. MRxSmbDumpStufferState (700,"SMB w/ closeaftercorecreate after stuffing",StufferState);
  757. //ASSERT(!"Now it's stuffed");
  758. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  759. SMBPSE_OETYPE_CLOSEAFTERCORECREATE
  760. );
  761. FINALLY:
  762. RxDbgTrace(-1, Dbg, ("MRxSmbCloseAfterCoreCreate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  763. return(Status);
  764. }
  765. NTSTATUS
  766. MRxSmbCoreTruncate(
  767. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  768. ULONG Fid,
  769. ULONG FileTruncationPoint
  770. )
  771. /*++
  772. Routine Description:
  773. This routine does a truncate to implement FILE_OVERWRITE and FILE_OVERWRITE_IF.....
  774. it is also used in the "extend-for-cached-write" path.
  775. Arguments:
  776. OrdinaryExchange - an exchange to be used for conducting this open.
  777. Return Value:
  778. RXSTATUS - The return status for the operation
  779. Notes:
  780. --*/
  781. {
  782. NTSTATUS Status;
  783. RxCaptureFcb; RxCaptureFobx;
  784. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  785. PSMBSTUFFER_BUFFER_STATE StufferState;
  786. PAGED_CODE();
  787. RxDbgTrace(+1, Dbg, ("MRxSmbCoreTruncate entering.......OE=%08lx\n",OrdinaryExchange));
  788. StufferState = &OrdinaryExchange->AssociatedStufferState;
  789. ASSERT( StufferState );
  790. COVERED_CALL(MRxSmbStartSMBCommand (StufferState, SetInitialSMB_ForReuse,
  791. SMB_COM_WRITE,
  792. SMB_REQUEST_SIZE(WRITE),
  793. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  794. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  795. )
  796. MRxSmbDumpStufferState (1100,"SMB w/ coretruncate before stuffing",StufferState);
  797. MRxSmbStuffSMB (StufferState,
  798. "0wwdwByw!",
  799. // 0 UCHAR WordCount; // Count of parameter words = 5
  800. Fid, // w _USHORT( Fid ); // File handle
  801. 0, // w _USHORT( Count ); // Number of bytes to be written
  802. FileTruncationPoint, // d _ULONG( Offset ); // Offset in file to begin write
  803. 0, // w _USHORT( Remaining ); // Bytes remaining to satisfy request
  804. SMB_WCT_CHECK(5) // B _USHORT( ByteCount ); // Count of data bytes
  805. // //UCHAR Buffer[1]; // Buffer containing:
  806. 0x01, // y UCHAR BufferFormat; // 0x01 -- Data block
  807. 0 // w _USHORT( DataLength ); // Length of data
  808. // ULONG Buffer[1]; // Data
  809. );
  810. MRxSmbDumpStufferState (700,"SMB w/ coretruncate after stuffing",StufferState);
  811. //ASSERT(!"Now it's stuffed");
  812. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  813. SMBPSE_OETYPE_CORETRUNCATE
  814. );
  815. if (Status == STATUS_SUCCESS) {
  816. LARGE_INTEGER FileSize;
  817. FileSize.HighPart = 0;
  818. FileSize.LowPart = FileTruncationPoint;
  819. MRxSmbUpdateFileInfoCacheFileSize(RxContext, &FileSize);
  820. } else {
  821. if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  822. Status == STATUS_OBJECT_PATH_NOT_FOUND) {
  823. // create the name based file not found cache
  824. MRxSmbCacheFileNotFound(RxContext);
  825. } else {
  826. // invalid the name based file not found cache if other error happens
  827. MRxSmbInvalidateFileNotFoundCache(RxContext);
  828. }
  829. // invalid the name based file info cache
  830. MRxSmbInvalidateFileInfoCache(RxContext);
  831. }
  832. FINALLY:
  833. RxDbgTrace(-1, Dbg, ("MRxSmbCoreTruncate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  834. return(Status);
  835. }
  836. NTSTATUS
  837. MRxSmbDownlevelCreate(
  838. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  839. )
  840. /*++
  841. Routine Description:
  842. This routine implements downlevel creates.
  843. Arguments:
  844. OrdinaryExchange - an exchange to be used for conducting this open.
  845. Return Value:
  846. RXSTATUS - The return status for the operation
  847. Notes:
  848. For core, in particular, this is pretty painful because a different smb must be used
  849. for different dispositions. In addition, we cannot really open a directory.
  850. By in large, we will follow a strategy similar to rdr1. If the openmode maps into something that
  851. a downlevel server won't understand then we don't really open the file.....we just do a GFA to ensure
  852. that it's there and hope that we can do path-based ops for the duration.
  853. --*/
  854. {
  855. NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
  856. RxCaptureFcb; //RxCaptureFobx;
  857. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  858. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  859. PUNICODE_STRING PathName = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  860. PNT_CREATE_PARAMETERS cp = &RxContext->Create.NtCreateParameters;
  861. ULONG CreateOptions = cp->CreateOptions;
  862. ULONG FileAttributes = cp->FileAttributes;
  863. ACCESS_MASK DesiredAccess = cp->DesiredAccess;
  864. USHORT ShareAccess = (USHORT)(cp->ShareAccess);
  865. ULONG Disposition = cp->Disposition;
  866. USHORT mappedDisposition = MRxSmbMapDisposition(Disposition);
  867. USHORT mappedSharingMode = MRxSmbMapShareAccess(ShareAccess);
  868. USHORT mappedAttributes = MRxSmbMapFileAttributes(FileAttributes);
  869. USHORT mappedOpenMode = MRxSmbMapDesiredAccess(DesiredAccess);
  870. LARGE_INTEGER AllocationSize = cp->AllocationSize;
  871. PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  872. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  873. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(Exchange);
  874. PSMBSTUFFER_BUFFER_STATE StufferState;
  875. BOOLEAN MustBeAFile = (MustBeFile(CreateOptions)!=0);
  876. BOOLEAN MustBeADirectory = (MustBeDirectory(CreateOptions)!=0)
  877. || BooleanFlagOn(RxContext->Create.Flags,RX_CONTEXT_CREATE_FLAG_STRIPPED_TRAILING_BACKSLASH);
  878. BOOLEAN ItsADirectory = FALSE;
  879. BOOLEAN ItsTheShareRoot = FALSE;
  880. PAGED_CODE();
  881. // Down level protocols don't have the execute mode.
  882. if (mappedOpenMode == (USHORT)SMB_DA_ACCESS_EXECUTE)
  883. mappedOpenMode = (USHORT)SMB_DA_ACCESS_READ;
  884. RxDbgTrace(+1, Dbg, ("MRxSmbDownlevelCreate entering.......OE=%08lx\n",OrdinaryExchange));
  885. RxDbgTrace( 0, Dbg, ("mapAtt,Shr,Disp,OM %04lx,%04lx,%04lx,%04lx\n",
  886. mappedAttributes,mappedSharingMode,mappedDisposition,mappedOpenMode));
  887. SmbPseOEAssertConsistentLinkageFromOE("Downlevel Create:");
  888. StufferState = &OrdinaryExchange->AssociatedStufferState;
  889. if (OrdinaryExchange->Create.CreateWithEasSidsOrLongName) {
  890. Status = RX_MAP_STATUS(NOT_SUPPORTED);
  891. goto FINALLY;
  892. }
  893. if (AllocationSize.HighPart != 0) {
  894. //CODE.IMPROVEMENT why is the above a not-supported while this is a invalid-param??? joejoe
  895. Status = RX_MAP_STATUS(INVALID_PARAMETER);
  896. goto FINALLY;
  897. }
  898. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  899. OrdinaryExchange->Create.smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  900. OrdinaryExchange->pPathArgument1 = PathName;
  901. //
  902. // we know that the root a share exists and that it's a directory....the catch is that GetFileAttributes
  903. // will return a NO_SUCH_FILE error for the root if it's really a root on the server. record this and use it
  904. // to our advantage later.
  905. if ((PathName->Length == 0)
  906. || ((PathName->Length == sizeof(WCHAR)) && (PathName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) ) {
  907. //if must be a file, it's an error.........
  908. if (MustBeAFile) {
  909. Status = RX_MAP_STATUS(FILE_IS_A_DIRECTORY);
  910. goto FINALLY;
  911. }
  912. //
  913. //if it's the right kind of open, i can just finish up now. these opens are common for GetFSInfo
  914. if ((Disposition == FILE_OPEN) || (Disposition == FILE_OPEN_IF)) {
  915. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse ( OrdinaryExchange, FileTypeDirectory );
  916. goto FINALLY;
  917. }
  918. MustBeADirectory = TRUE; // we know it's a directory!
  919. ItsTheShareRoot = TRUE;
  920. }
  921. //// if all the user wants is attributes and it's a FILE_OPEN, don't do the open now....
  922. //// rather, we'll send pathbased ops later (or do a deferred open if necessary)...
  923. if (Disposition == FILE_OPEN &&
  924. (MustBeADirectory ||
  925. !(cp->DesiredAccess & ~(SYNCHRONIZE | DELETE | FILE_READ_ATTRIBUTES)))) {
  926. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse(OrdinaryExchange, MustBeADirectory?FileTypeDirectory:FileTypeFile);
  927. if (Status == STATUS_SUCCESS) {
  928. Status = MRxSmbQueryFileInformationFromPseudoOpen(
  929. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  930. FileBasicInformation);
  931. if (Status == STATUS_SUCCESS) {
  932. if (MustBeADirectory &&
  933. !OrdinaryExchange->Create.FileInfo.Standard.Directory) {
  934. Status = STATUS_NOT_A_DIRECTORY;
  935. }
  936. if (MustBeAFile &&
  937. OrdinaryExchange->Create.FileInfo.Standard.Directory) {
  938. Status = STATUS_FILE_IS_A_DIRECTORY;
  939. }
  940. }
  941. if (Status != STATUS_SUCCESS) {
  942. RxFreePool(smbSrvOpen->DeferredOpenContext);
  943. smbSrvOpen->DeferredOpenContext = NULL;
  944. }
  945. }
  946. goto FINALLY;
  947. }
  948. if ( (mappedOpenMode == ((USHORT)-1)) ||
  949. (Disposition == FILE_SUPERSEDE) ||
  950. (!MustBeAFile)
  951. ) {
  952. //
  953. // go find out what's there.......
  954. Status = MRxSmbGetFileAttributes(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  955. if (Status == STATUS_SUCCESS &&
  956. MustBeADirectory &&
  957. !OrdinaryExchange->Create.FileInfo.Standard.Directory) {
  958. Status = STATUS_NOT_A_DIRECTORY;
  959. goto FINALLY;
  960. }
  961. RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate GFAorCPstatus=%08lx\n",Status));
  962. if (NT_SUCCESS(Status)) {
  963. ULONG Attributes = SmbGetUshort(&OrdinaryExchange->Create.FileInfo.Basic.FileAttributes);
  964. ItsADirectory = BooleanFlagOn(Attributes,SMB_FILE_ATTRIBUTE_DIRECTORY);
  965. RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate attributes=%08lx\n",Attributes));
  966. if ((Disposition==FILE_CREATE)) {
  967. Status = STATUS_OBJECT_NAME_COLLISION;
  968. goto FINALLY;
  969. }
  970. if (MustBeADirectory && !ItsADirectory && (Disposition!=FILE_SUPERSEDE)) {
  971. if (Disposition == FILE_OPEN) {
  972. // This fix is required for the DFS driver which seems to handle
  973. // STATUS_OBJECT_TYPE_MISMATCH in a special way.
  974. // DFS should be fixed.
  975. Status = STATUS_OBJECT_NAME_COLLISION;
  976. } else {
  977. Status = STATUS_OBJECT_TYPE_MISMATCH;
  978. }
  979. goto FINALLY;
  980. }
  981. if (MustBeAFile && ItsADirectory && (Disposition!=FILE_SUPERSEDE)) {
  982. if (Disposition == FILE_OPEN) {
  983. // This fix is required for the DFS driver which seems to handle
  984. // STATUS_OBJECT_TYPE_MISMATCH in a special way.
  985. // DFS should be fixed.
  986. Status = STATUS_FILE_IS_A_DIRECTORY;
  987. } else {
  988. Status = STATUS_OBJECT_TYPE_MISMATCH;
  989. }
  990. goto FINALLY;
  991. }
  992. //if (!MustBeAFile && ItsADirectory && (Disposition==FILE_OPEN)){
  993. if (Disposition==FILE_OPEN || Disposition==FILE_OPEN_IF){
  994. //we're done except to finish AND to set the flags in the srvopen
  995. MRxSmbPseudoOpenTailFromGFAResponse ( OrdinaryExchange );
  996. goto FINALLY;
  997. }
  998. } else if ( (Status!=STATUS_NO_SUCH_FILE)
  999. && (Status!=STATUS_OBJECT_PATH_NOT_FOUND) ) {
  1000. goto FINALLY;
  1001. } else if ((Disposition==FILE_CREATE)
  1002. || (Disposition==FILE_OPEN_IF)
  1003. || (Disposition==FILE_OVERWRITE_IF)
  1004. || (Disposition==FILE_SUPERSEDE)) {
  1005. //CODE.IMPROVEMENT doing this with four compares is ineficient; we should have a
  1006. // table or something
  1007. NOTHING;
  1008. } else if (ItsTheShareRoot) {
  1009. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1010. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1011. //here we have run into a true root....so we can't get attributes. fill in a fake
  1012. //response and finish. also, flip the bit that says we can't gfa this guy.
  1013. Status = MRxSmbPseudoOpenTailFromFakeGFAResponse ( OrdinaryExchange, FileTypeDirectory );
  1014. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_CANT_GETATTRIBS;
  1015. goto FINALLY;
  1016. } else {
  1017. goto FINALLY;
  1018. }
  1019. }
  1020. SmbCeResetExchange(&OrdinaryExchange->Exchange); //must reset!
  1021. if (NT_SUCCESS(Status) &&(Disposition == FILE_SUPERSEDE)) {
  1022. //
  1023. //we have to get rid of the existing entity...using a delete or a rmdir as appropriate
  1024. Status = MRxSmbCoreDeleteForSupercedeOrClose(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1025. OrdinaryExchange->Create.FileInfo.Standard.Directory
  1026. );
  1027. if (!NT_SUCCESS(Status)) {
  1028. RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate could notsupersede st=%08lx\n",Status));
  1029. goto FINALLY;
  1030. }
  1031. SmbCeResetExchange(&OrdinaryExchange->Exchange); //must reset!
  1032. //CODE.IMPROVEMENT there should be some way
  1033. //that is more automatic than this
  1034. }
  1035. if (MustBeADirectory || (ItsADirectory &&(Disposition == FILE_SUPERSEDE)) ) {
  1036. ASSERT (Disposition!=FILE_OPEN);
  1037. Status = MRxSmbCoreCreateDirectory(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1038. if (!NT_SUCCESS(Status)) {
  1039. RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate couldn't mkdir st=%08lx\n",Status));
  1040. goto FINALLY;
  1041. }
  1042. if ((mappedAttributes &
  1043. (SMB_FILE_ATTRIBUTE_READONLY |
  1044. SMB_FILE_ATTRIBUTE_HIDDEN |
  1045. SMB_FILE_ATTRIBUTE_SYSTEM |
  1046. SMB_FILE_ATTRIBUTE_ARCHIVE)) != 0) {
  1047. //
  1048. //we have to set the attributes
  1049. Status = MRxSmbSetFileAttributes(
  1050. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1051. mappedAttributes);
  1052. if (!NT_SUCCESS(Status)) {
  1053. RxDbgTrace(0, Dbg, ("MRxSmbDownlevelCreate couldn't sfa st=%08lx\n",Status));
  1054. }
  1055. }
  1056. MRxSmbPseudoOpenTailFromCoreCreateDirectory( OrdinaryExchange, mappedAttributes );
  1057. goto FINALLY;
  1058. }
  1059. //if ( (mappedOpenMode != -1) && !MustBeADirectory) {
  1060. //no pseudoOpens yet
  1061. if ( TRUE ) {
  1062. ULONG workingDisposition = Disposition;
  1063. ULONG iterationcount;
  1064. BOOLEAN MayNeedATruncate = FALSE;
  1065. //
  1066. // we use the disposition as a state and case out.....some are hard and some are easy
  1067. // for example, if it's CREATE then we use the CREATE_NEW to create the file but
  1068. // the resulting open is no good so we close it and open it again using the
  1069. // open. for OPEN_IF we assume that the file will be there
  1070. // and drop into create if it's not.
  1071. for (iterationcount=0;;iterationcount++) {
  1072. switch (workingDisposition) {
  1073. case FILE_OVERWRITE:
  1074. case FILE_OVERWRITE_IF:
  1075. MayNeedATruncate = TRUE;
  1076. //lack of break intentional
  1077. case FILE_OPEN_IF:
  1078. case FILE_OPEN:
  1079. Status = MRxSmbCoreOpen(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1080. mappedOpenMode|mappedSharingMode,
  1081. mappedAttributes);
  1082. //if (Status==RxStatus(NO_SUCH_FILE)) {
  1083. // DbgPrint("%08lx %08lx %08lx\n",Status,workingDisposition,iterationcount);
  1084. // DbgBreakPoint();
  1085. //}
  1086. if (!((workingDisposition == FILE_OPEN_IF) || (workingDisposition == FILE_OVERWRITE_IF))
  1087. || (Status!=RX_MAP_STATUS(NO_SUCH_FILE))
  1088. || (iterationcount>6)
  1089. )break;
  1090. SmbCeResetExchange(&OrdinaryExchange->Exchange); //must reset!
  1091. case FILE_SUPERSEDE:
  1092. case FILE_CREATE:
  1093. Status = MRxSmbCoreCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1094. mappedAttributes,TRUE); //(workingDisposition==FILE_CREATE));
  1095. if (!NT_SUCCESS(Status)) {
  1096. RxDbgTrace(-1, Dbg, ("MRxSmbDownlevelCreate exiting.......createnew failed st=%08lx\n",Status));
  1097. break;
  1098. }
  1099. //now, we have a network handle. BUT, it's a compatibility-mode open. since we don't want that we
  1100. // need to close and reopen with the parameters specified. there is a window here! what can i do??
  1101. Status = MRxSmbCloseAfterCoreCreate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1102. if (!NT_SUCCESS(Status)) {
  1103. RxDbgTrace(-1, Dbg, ("MRxSmbDownlevelCreate exiting.......closeaftercreatenew failed st=%08lx\n",Status));
  1104. break;
  1105. }
  1106. workingDisposition = FILE_OPEN_IF;
  1107. continue; // this wraps back to the switch with a new disposition
  1108. //break;
  1109. //case FILE_SUPERSEDE:
  1110. // Status = RxStatus(NOT_SUPPORTED);
  1111. // break;
  1112. default :
  1113. ASSERT(!"Bad Disposition");
  1114. Status = RX_MAP_STATUS(INVALID_PARAMETER);
  1115. }
  1116. break; //exit the loop
  1117. }
  1118. if (!NT_SUCCESS(Status))goto FINALLY;
  1119. //we may need a truncate....this is different from rdr1.
  1120. if (MayNeedATruncate
  1121. && !OrdinaryExchange->Create.FileWasCreated
  1122. && (OrdinaryExchange->Create.FileSizeReturnedFromOpen!=0) ) {
  1123. Status = MRxSmbCoreTruncate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1124. OrdinaryExchange->Create.FidReturnedFromOpen,
  1125. 0
  1126. );
  1127. }
  1128. goto FINALLY;
  1129. }
  1130. FINALLY:
  1131. RxDbgTrace(-1, Dbg, ("MRxSmbDownlevelCreate exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  1132. return(Status);
  1133. }
  1134. NTSTATUS
  1135. MRxSmbFinishGFA (
  1136. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1137. PBYTE Response
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This routine copies the response to the GetFileAttributes SMB. But, it must be called synchronously.
  1142. Arguments:
  1143. OrdinaryExchange - the exchange instance
  1144. Response - the response
  1145. Return Value:
  1146. RXSTATUS - The return status for the operation
  1147. Notes:
  1148. what we do here is to put the data into the ordinary exchange...it's locked down do
  1149. we could do this at DPC level
  1150. --*/
  1151. {
  1152. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1153. PFILE_BASIC_INFORMATION BasicInformation = &OrdinaryExchange->Create.FileInfo.Basic;
  1154. PFILE_STANDARD_INFORMATION StandardInformation = &OrdinaryExchange->Create.FileInfo.Standard;
  1155. PSMB_PARAMS pSmbParams = (PSMB_PARAMS)Response;
  1156. PAGED_CODE();
  1157. RxDbgTrace(+1, Dbg, ("MRxSmbFinishGFA\n", 0 ));
  1158. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishGFA:");
  1159. if (pSmbParams->WordCount == 10) {
  1160. PRESP_QUERY_INFORMATION pQueryInformationResponse;
  1161. pQueryInformationResponse = (PRESP_QUERY_INFORMATION)Response;
  1162. //what we do here is to put the data into the ordinary exchange...it's locked down do
  1163. //we wcould do this at DPC level
  1164. MRxSmbPopulateFileInfoInOE(
  1165. OrdinaryExchange,
  1166. SmbGetUshort(&pQueryInformationResponse->FileAttributes),
  1167. SmbGetUlong(&pQueryInformationResponse->LastWriteTimeInSeconds),
  1168. SmbGetUlong(&pQueryInformationResponse->FileSize)
  1169. );
  1170. } else if (pSmbParams->WordCount == 11) {
  1171. PRESP_QUERY_INFORMATION2 pQueryInformation2Response;
  1172. SMB_TIME LastWriteSmbTime;
  1173. SMB_DATE LastWriteSmbDate;
  1174. LARGE_INTEGER LastWriteTime;
  1175. ULONG LastWriteTimeInSeconds;
  1176. pQueryInformation2Response = (PRESP_QUERY_INFORMATION2)Response;
  1177. RtlCopyMemory(
  1178. &LastWriteSmbTime,
  1179. &pQueryInformation2Response->LastWriteTime,
  1180. sizeof(SMB_TIME));
  1181. RtlCopyMemory(
  1182. &LastWriteSmbDate,
  1183. &pQueryInformation2Response->LastWriteDate,
  1184. sizeof(SMB_DATE));
  1185. LastWriteTime = MRxSmbConvertSmbTimeToTime(NULL,LastWriteSmbTime,LastWriteSmbDate);
  1186. MRxSmbTimeToSecondsSince1970(
  1187. &LastWriteTime,
  1188. NULL,
  1189. &LastWriteTimeInSeconds);
  1190. MRxSmbPopulateFileInfoInOE(
  1191. OrdinaryExchange,
  1192. SmbGetUshort(&pQueryInformation2Response->FileAttributes),
  1193. LastWriteTimeInSeconds,
  1194. SmbGetUlong(&pQueryInformation2Response->FileDataSize)
  1195. );
  1196. }
  1197. RxDbgTrace(-1, Dbg, ("MRxSmbFinishGFA returning %08lx\n", Status ));
  1198. return Status;
  1199. }
  1200. //CODE.IMPROVEMENT shouldn't this be in a .h file.....
  1201. NTSTATUS
  1202. MRxSmbCreateFileSuccessTail (
  1203. PRX_CONTEXT RxContext,
  1204. PBOOLEAN MustRegainExclusiveResource,
  1205. SMBFCB_HOLDING_STATE *SmbFcbHoldingState,
  1206. RX_FILE_TYPE StorageType,
  1207. SMB_FILE_ID Fid,
  1208. ULONG ServerVersion,
  1209. UCHAR OplockLevel,
  1210. ULONG CreateAction,
  1211. PSMBPSE_FILEINFO_BUNDLE FileInfo
  1212. );
  1213. NTSTATUS
  1214. MRxSmbFinishCoreCreate (
  1215. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1216. PRESP_CREATE Response
  1217. )
  1218. /*++
  1219. Routine Description:
  1220. This routine copies the fid from a core create response. it does not finish the fcb......if a compatibility
  1221. mode open is acceptable then it could.
  1222. Arguments:
  1223. OrdinaryExchange - the exchange instance
  1224. Response - the response
  1225. Return Value:
  1226. RXSTATUS - The return status for the operation
  1227. --*/
  1228. {
  1229. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1230. PAGED_CODE();
  1231. RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreCreate\n", 0 ));
  1232. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreCreate:");
  1233. if (Response->WordCount != 1 ||
  1234. SmbGetUshort(&Response->ByteCount) != 0) {
  1235. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1236. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1237. } else {
  1238. OrdinaryExchange->Create.FidReturnedFromCreate = SmbGetUshort(&Response->Fid);
  1239. OrdinaryExchange->Create.FileWasCreated = TRUE;
  1240. //notice that we didn't finish here! we should IFF a compatibilty-mode open is okay
  1241. }
  1242. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreCreate returning %08lx\n", Status ));
  1243. return Status;
  1244. }
  1245. #define JUST_USE_THE_STUFF_IN_THE_OE (0xfbad)
  1246. VOID
  1247. MRxSmbPopulateFileInfoInOE(
  1248. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1249. USHORT FileAttributes,
  1250. ULONG LastWriteTimeInSeconds,
  1251. ULONG FileSize
  1252. )
  1253. {
  1254. PFILE_BASIC_INFORMATION BasicInformation = &OrdinaryExchange->Create.FileInfo.Basic;
  1255. PFILE_STANDARD_INFORMATION StandardInformation = &OrdinaryExchange->Create.FileInfo.Standard;
  1256. BasicInformation->FileAttributes = MRxSmbMapSmbAttributes(FileAttributes);
  1257. StandardInformation->NumberOfLinks = 1;
  1258. BasicInformation->CreationTime.QuadPart = 0;
  1259. BasicInformation->LastAccessTime.QuadPart = 0;
  1260. MRxSmbSecondsSince1970ToTime(LastWriteTimeInSeconds,
  1261. SmbCeGetExchangeServer(OrdinaryExchange),
  1262. &BasicInformation->LastWriteTime);
  1263. BasicInformation->ChangeTime.QuadPart = 0;
  1264. StandardInformation->AllocationSize.QuadPart = FileSize; //rdr1 actually rounds up based of svr disk attribs
  1265. StandardInformation->EndOfFile.QuadPart = FileSize;
  1266. StandardInformation->Directory = BooleanFlagOn(BasicInformation->FileAttributes,FILE_ATTRIBUTE_DIRECTORY);
  1267. }
  1268. NTSTATUS
  1269. MRxSmbFinishCoreOpen (
  1270. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1271. PRESP_OPEN Response
  1272. )
  1273. /*++
  1274. Routine Description:
  1275. This routine finishes a core open.
  1276. Arguments:
  1277. OrdinaryExchange - the exchange instance
  1278. Response - the response
  1279. Return Value:
  1280. RXSTATUS - The return status for the operation
  1281. --*/
  1282. {
  1283. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1284. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1285. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1286. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1287. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1288. RX_FILE_TYPE StorageType;
  1289. SMB_FILE_ID Fid;
  1290. ULONG CreateAction;
  1291. ULONG FileSize;
  1292. PAGED_CODE();
  1293. RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreOpen\n", 0 ));
  1294. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreOpen:");
  1295. if (Response->WordCount != 7 ||
  1296. SmbGetUshort(&Response->ByteCount) != 0) {
  1297. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1298. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1299. goto FINALLY;
  1300. }
  1301. StorageType = FileTypeFile;
  1302. Fid = SmbGetUshort(&Response->Fid);
  1303. OrdinaryExchange->Create.FidReturnedFromOpen = Fid;
  1304. FileSize = OrdinaryExchange->Create.FileSizeReturnedFromOpen = SmbGetUlong(&Response->DataSize);
  1305. CreateAction = (OrdinaryExchange->Create.FileWasCreated)?FILE_CREATED
  1306. : (OrdinaryExchange->Create.FileWasTruncated)?FILE_OVERWRITTEN
  1307. :FILE_OPENED;
  1308. MRxSmbPopulateFileInfoInOE(
  1309. OrdinaryExchange,
  1310. SmbGetUshort(&Response->FileAttributes),
  1311. SmbGetUlong(&Response->LastWriteTimeInSeconds),
  1312. FileSize
  1313. );
  1314. pFileInfo->Basic.FileAttributes = OrdinaryExchange->Create.FileInfo.Basic.FileAttributes;
  1315. pFileInfo->Basic.CreationTime = OrdinaryExchange->Create.FileInfo.Basic.CreationTime;
  1316. pFileInfo->Basic.LastAccessTime = OrdinaryExchange->Create.FileInfo.Basic.LastAccessTime;
  1317. pFileInfo->Basic.LastWriteTime = OrdinaryExchange->Create.FileInfo.Basic.LastWriteTime;
  1318. pFileInfo->Basic.ChangeTime = OrdinaryExchange->Create.FileInfo.Basic.ChangeTime;
  1319. pFileInfo->Standard.NumberOfLinks = OrdinaryExchange->Create.FileInfo.Standard.NumberOfLinks;
  1320. pFileInfo->Standard.AllocationSize = OrdinaryExchange->Create.FileInfo.Standard.AllocationSize;
  1321. pFileInfo->Standard.EndOfFile = OrdinaryExchange->Create.FileInfo.Standard.EndOfFile;
  1322. pFileInfo->Standard.Directory = FALSE;
  1323. //CODE.IMPROVEMENT we could save a bit of stack space by wrapping a struc around the args below....
  1324. MRxSmbCreateFileSuccessTail ( RxContext,
  1325. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  1326. &OrdinaryExchange->SmbFcbHoldingState,
  1327. StorageType,
  1328. Fid,
  1329. OrdinaryExchange->ServerVersion,
  1330. SMB_OPLOCK_LEVEL_NONE,
  1331. CreateAction,
  1332. pFileInfo);
  1333. FINALLY:
  1334. IF_DEBUG{
  1335. RxCaptureFcb;
  1336. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreOpen returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1337. }
  1338. return Status;
  1339. }
  1340. NTSTATUS
  1341. MRxSmbPseudoOpenTailFromCoreCreateDirectory (
  1342. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1343. USHORT Attributes
  1344. )
  1345. /*++
  1346. Routine Description:
  1347. This routine finishes a core create directory. but, it is not called from the receive routine......
  1348. Arguments:
  1349. OrdinaryExchange - the exchange instance
  1350. Return Value:
  1351. RXSTATUS - The return status for the operation
  1352. --*/
  1353. {
  1354. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1355. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1356. RxCaptureFobx;
  1357. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1358. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1359. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1360. RX_FILE_TYPE StorageType;
  1361. SMB_FILE_ID Fid;
  1362. ULONG CreateAction;
  1363. PAGED_CODE();
  1364. RxDbgTrace(+1, Dbg, ("MRxSmbFinishCoreCreateDirectory\n", 0 ));
  1365. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishCoreCreateDirectory:");
  1366. StorageType = FileTypeDirectory;
  1367. Fid = 0xbadd;
  1368. CreateAction = FILE_CREATED;
  1369. MRxSmbPopulateFileInfoInOE(
  1370. OrdinaryExchange,
  1371. Attributes,
  1372. 0,
  1373. 0
  1374. );
  1375. pFileInfo->Basic.FileAttributes = OrdinaryExchange->Create.FileInfo.Basic.FileAttributes;
  1376. pFileInfo->Basic.CreationTime = OrdinaryExchange->Create.FileInfo.Basic.CreationTime;
  1377. pFileInfo->Basic.LastAccessTime = OrdinaryExchange->Create.FileInfo.Basic.LastAccessTime;
  1378. pFileInfo->Basic.LastWriteTime = OrdinaryExchange->Create.FileInfo.Basic.LastWriteTime;
  1379. pFileInfo->Basic.ChangeTime = OrdinaryExchange->Create.FileInfo.Basic.ChangeTime;
  1380. pFileInfo->Standard.NumberOfLinks = OrdinaryExchange->Create.FileInfo.Standard.NumberOfLinks;
  1381. pFileInfo->Standard.AllocationSize = OrdinaryExchange->Create.FileInfo.Standard.AllocationSize;
  1382. pFileInfo->Standard.EndOfFile = OrdinaryExchange->Create.FileInfo.Standard.EndOfFile;
  1383. pFileInfo->Standard.Directory = TRUE;
  1384. //CODE.IMPROVEMENT we could save a bit of stack space by wrapping a struc around the args below....
  1385. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN; //this indicates a pseudoopen to success tail
  1386. MRxSmbCreateFileSuccessTail ( RxContext,
  1387. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  1388. &OrdinaryExchange->SmbFcbHoldingState,
  1389. StorageType,
  1390. Fid,
  1391. OrdinaryExchange->ServerVersion,
  1392. SMB_OPLOCK_LEVEL_NONE,
  1393. CreateAction,
  1394. pFileInfo);
  1395. IF_DEBUG{
  1396. RxCaptureFcb;
  1397. RxDbgTrace(-1, Dbg, ("MRxSmbFinishCoreCreateDirectory returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1398. }
  1399. return Status;
  1400. }
  1401. NTSTATUS
  1402. MRxSmbPseudoOpenTailFromFakeGFAResponse (
  1403. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1404. RX_FILE_TYPE StorageType
  1405. )
  1406. /*++
  1407. Routine Description:
  1408. This routine finishes a pseudoopen from faked up information. Basically, we fill in
  1409. the information that would have been obtained on a GET_FILE_ATTRIBUTES smb and then call
  1410. the PseudoOpenFromGFA routine
  1411. Arguments:
  1412. OrdinaryExchange - the exchange instance
  1413. StorageType - the type of thing that this is supposed to be. If it's supposed to be
  1414. a directory then we set the attributes bit in the GFA info.
  1415. Return Value:
  1416. RXSTATUS - The return status for the operation
  1417. --*/
  1418. {
  1419. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1420. USHORT Attributes = 0;
  1421. PAGED_CODE();
  1422. RtlZeroMemory(
  1423. &OrdinaryExchange->Create.FileInfo,
  1424. sizeof(OrdinaryExchange->Create.FileInfo));
  1425. if (StorageType == FileTypeDirectory) {
  1426. Attributes = SMB_FILE_ATTRIBUTE_DIRECTORY;
  1427. }
  1428. MRxSmbPopulateFileInfoInOE(OrdinaryExchange,Attributes,0,0);
  1429. OrdinaryExchange->Create.StorageTypeFromGFA = StorageType;
  1430. return( MRxSmbPseudoOpenTailFromGFAResponse (OrdinaryExchange) );
  1431. }
  1432. NTSTATUS
  1433. MRxSmbPseudoOpenTailFromGFAResponse (
  1434. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  1435. )
  1436. /*++
  1437. Routine Description:
  1438. This routine finishes a pseudoopen from the information obtained on a
  1439. GET_FILE_ATTRIBUTES smb.
  1440. Arguments:
  1441. OrdinaryExchange - the exchange instance
  1442. Return Value:
  1443. RXSTATUS - The return status for the operation
  1444. --*/
  1445. {
  1446. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  1447. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1448. PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  1449. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1450. PSMBPSE_FILEINFO_BUNDLE pFileInfo = &smbSrvOpen->FileInfo;
  1451. SMB_FILE_ID Fid;
  1452. ULONG CreateAction;
  1453. PAGED_CODE();
  1454. RxDbgTrace(+1, Dbg, ("MRxSmbFinishPseudoOpenFromGFAResponse\n"));
  1455. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishPseudoOpenFromGFAResponse:");
  1456. Fid = 0xbadd;
  1457. CreateAction = FILE_OPENED;
  1458. pFileInfo->Basic.FileAttributes = OrdinaryExchange->Create.FileInfo.Basic.FileAttributes;
  1459. pFileInfo->Basic.CreationTime = OrdinaryExchange->Create.FileInfo.Basic.CreationTime;
  1460. pFileInfo->Basic.LastAccessTime = OrdinaryExchange->Create.FileInfo.Basic.LastAccessTime;
  1461. pFileInfo->Basic.LastWriteTime = OrdinaryExchange->Create.FileInfo.Basic.LastWriteTime;
  1462. pFileInfo->Basic.ChangeTime = OrdinaryExchange->Create.FileInfo.Basic.ChangeTime;
  1463. pFileInfo->Standard.NumberOfLinks = OrdinaryExchange->Create.FileInfo.Standard.NumberOfLinks;
  1464. pFileInfo->Standard.AllocationSize = OrdinaryExchange->Create.FileInfo.Standard.AllocationSize;
  1465. pFileInfo->Standard.EndOfFile = OrdinaryExchange->Create.FileInfo.Standard.EndOfFile;
  1466. pFileInfo->Standard.Directory = (OrdinaryExchange->Create.StorageTypeFromGFA == FileTypeDirectory);
  1467. //CODE.IMPROVEMENT we could save a bit of stack space by wrapping a struc around the args below....
  1468. // it seems to me that everything but the fid coudl be done that way and the success tail routine
  1469. // moved to the wrapper
  1470. smbSrvOpen->Flags |= SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN; //this indicates a pseudoopen to success tail
  1471. MRxSmbCreateFileSuccessTail ( RxContext,
  1472. &OrdinaryExchange->Create.MustRegainExclusiveResource,
  1473. &OrdinaryExchange->SmbFcbHoldingState,
  1474. OrdinaryExchange->Create.StorageTypeFromGFA,
  1475. Fid,
  1476. OrdinaryExchange->ServerVersion,
  1477. SMB_OPLOCK_LEVEL_NONE,
  1478. CreateAction,
  1479. pFileInfo);
  1480. if (smbSrvOpen->DeferredOpenContext == NULL) {
  1481. // if it is a remote boot server file, it already has a deferred open context created
  1482. // on MRxSmbCreateFileSuccessTail
  1483. Status = MRxSmbConstructDeferredOpenContext(RxContext);
  1484. } else {
  1485. // The flag has been cleared when a deferred open context was created for a remote boot server file.
  1486. SetFlag(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN);
  1487. }
  1488. if (Status!=STATUS_SUCCESS) {
  1489. RxDbgTrace(-1, Dbg, ("MRxSmbFinishPseudoOpenFromGFAResponse construct dfo failed %08lx \n",Status));
  1490. }
  1491. IF_DEBUG{
  1492. RxCaptureFcb;
  1493. RxDbgTrace(-1, Dbg, ("MRxSmbFinishPseudoOpenFromGFAResponse returning %08lx, fcbstate =%08lx\n", Status, capFcb->FcbState ));
  1494. }
  1495. return Status;
  1496. }
  1497. LARGE_INTEGER
  1498. MRxSmbConvertSmbTimeToTime (
  1499. //IN PSMB_EXCHANGE Exchange OPTIONAL,
  1500. IN PSMBCE_SERVER Server OPTIONAL,
  1501. IN SMB_TIME Time,
  1502. IN SMB_DATE Date
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This routine converts an SMB time to an NT time structure.
  1507. Arguments:
  1508. IN SMB_TIME Time - Supplies the time of day to convert
  1509. IN SMB_DATE Date - Supplies the day of the year to convert
  1510. IN supplies the server for tz bias.
  1511. Return Value:
  1512. LARGE_INTEGER - Time structure describing input time.
  1513. --*/
  1514. {
  1515. TIME_FIELDS TimeFields;
  1516. LARGE_INTEGER OutputTime;
  1517. PAGED_CODE();
  1518. //
  1519. // This routine cannot be paged because it is called from both the
  1520. // MRxSmbFileDiscardableSection and the MRxSmbVCDiscardableSection.
  1521. //
  1522. if (SmbIsTimeZero(&Date) && SmbIsTimeZero(&Time)) {
  1523. OutputTime.LowPart = OutputTime.HighPart = 0;
  1524. } else {
  1525. TimeFields.Year = Date.Struct.Year + (USHORT )1980;
  1526. TimeFields.Month = Date.Struct.Month;
  1527. TimeFields.Day = Date.Struct.Day;
  1528. TimeFields.Hour = Time.Struct.Hours;
  1529. TimeFields.Minute = Time.Struct.Minutes;
  1530. TimeFields.Second = Time.Struct.TwoSeconds*(USHORT )2;
  1531. TimeFields.Milliseconds = 0;
  1532. //
  1533. // Make sure that the times specified in the SMB are reasonable
  1534. // before converting them.
  1535. //
  1536. if (TimeFields.Year < 1601) {
  1537. TimeFields.Year = 1601;
  1538. }
  1539. if (TimeFields.Month > 12) {
  1540. TimeFields.Month = 12;
  1541. }
  1542. if (TimeFields.Hour >= 24) {
  1543. TimeFields.Hour = 23;
  1544. }
  1545. if (TimeFields.Minute >= 60) {
  1546. TimeFields.Minute = 59;
  1547. }
  1548. if (TimeFields.Second >= 60) {
  1549. TimeFields.Second = 59;
  1550. }
  1551. if (!RtlTimeFieldsToTime(&TimeFields, &OutputTime)) {
  1552. OutputTime.HighPart = 0;
  1553. OutputTime.LowPart = 0;
  1554. return OutputTime;
  1555. }
  1556. #ifndef WIN9X
  1557. if (ARGUMENT_PRESENT(Server)) {
  1558. OutputTime.QuadPart = OutputTime.QuadPart + Server->TimeZoneBias.QuadPart;
  1559. }
  1560. ExLocalTimeToSystemTime(&OutputTime, &OutputTime);
  1561. #else
  1562. OutputTime.HighPart = 0;
  1563. OutputTime.LowPart = 0;
  1564. #endif
  1565. }
  1566. return OutputTime;
  1567. }
  1568. BOOLEAN
  1569. MRxSmbConvertTimeToSmbTime (
  1570. IN PLARGE_INTEGER InputTime,
  1571. IN PSMB_EXCHANGE Exchange OPTIONAL,
  1572. OUT PSMB_TIME Time,
  1573. OUT PSMB_DATE Date
  1574. )
  1575. /*++
  1576. Routine Description:
  1577. This routine converts an NT time structure to an SMB time.
  1578. Arguments:
  1579. IN LARGE_INTEGER InputTime - Supplies the time to convert.
  1580. OUT PSMB_TIME Time - Returns the converted time of day.
  1581. OUT PSMB_DATE Date - Returns the converted day of the year.
  1582. Return Value:
  1583. BOOLEAN - TRUE if input time could be converted.
  1584. --*/
  1585. {
  1586. TIME_FIELDS TimeFields;
  1587. PAGED_CODE();
  1588. if (InputTime->LowPart == 0 && InputTime->HighPart == 0) {
  1589. Time->Ushort = Date->Ushort = 0;
  1590. } else {
  1591. LARGE_INTEGER LocalTime;
  1592. ExSystemTimeToLocalTime(InputTime, &LocalTime);
  1593. if (ARGUMENT_PRESENT(Exchange)) {
  1594. PSMBCE_SERVER Server = SmbCeGetExchangeServer(Exchange);
  1595. LocalTime.QuadPart -= Server->TimeZoneBias.QuadPart;
  1596. }
  1597. RtlTimeToTimeFields(&LocalTime, &TimeFields);
  1598. if (TimeFields.Year < 1980) {
  1599. return FALSE;
  1600. }
  1601. Date->Struct.Year = (USHORT )(TimeFields.Year - 1980);
  1602. Date->Struct.Month = TimeFields.Month;
  1603. Date->Struct.Day = TimeFields.Day;
  1604. Time->Struct.Hours = TimeFields.Hour;
  1605. Time->Struct.Minutes = TimeFields.Minute;
  1606. //
  1607. // When converting from a higher granularity time to a lesser
  1608. // granularity time (seconds to 2 seconds), always round up
  1609. // the time, don't round down.
  1610. //
  1611. Time->Struct.TwoSeconds = (TimeFields.Second + (USHORT)1) / (USHORT )2;
  1612. }
  1613. return TRUE;
  1614. }
  1615. BOOLEAN
  1616. MRxSmbTimeToSecondsSince1970 (
  1617. IN PLARGE_INTEGER CurrentTime,
  1618. IN PSMBCE_SERVER Server OPTIONAL,
  1619. OUT PULONG SecondsSince1970
  1620. )
  1621. /*++
  1622. Routine Description:
  1623. This routine returns the CurrentTime in UTC and returns the
  1624. equivalent current time in the servers timezone.
  1625. Arguments:
  1626. IN PLARGE_INTEGER CurrentTime - Supplies the current system time in UTC.
  1627. IN PSMBCE_SERVER Server - Supplies the difference in timezones between
  1628. the server and the workstation. If not supplied
  1629. then the assumption is that they are in the
  1630. same timezone.
  1631. OUT PULONG SecondsSince1970 - Returns the # of seconds since 1970 in
  1632. the servers timezone or MAXULONG if conversion
  1633. fails.
  1634. Return Value:
  1635. BOOLEAN - TRUE if the time could be converted.
  1636. --*/
  1637. {
  1638. LARGE_INTEGER ServerTime;
  1639. LARGE_INTEGER TempTime;
  1640. BOOLEAN ReturnValue;
  1641. PAGED_CODE();
  1642. if (ARGUMENT_PRESENT(Server) &&
  1643. ((*CurrentTime).QuadPart != 0)) {
  1644. TempTime.QuadPart = (*CurrentTime).QuadPart - Server->TimeZoneBias.QuadPart;
  1645. ExSystemTimeToLocalTime(&TempTime, &ServerTime);
  1646. } else {
  1647. ExSystemTimeToLocalTime(CurrentTime, &ServerTime);
  1648. }
  1649. ReturnValue = RtlTimeToSecondsSince1970(&ServerTime, SecondsSince1970);
  1650. if ( ReturnValue == FALSE ) {
  1651. //
  1652. // We can't represent the time legally, peg it at
  1653. // the max legal time.
  1654. //
  1655. *SecondsSince1970 = MAXULONG;
  1656. }
  1657. return ReturnValue;
  1658. }
  1659. VOID
  1660. MRxSmbSecondsSince1970ToTime (
  1661. IN ULONG SecondsSince1970,
  1662. //IN PSMB_EXCHANGE Exchange OPTIONAL,
  1663. IN PSMBCE_SERVER Server,
  1664. OUT PLARGE_INTEGER CurrentTime
  1665. )
  1666. /*++
  1667. Routine Description:
  1668. This routine returns the Local system time derived from a time
  1669. in seconds in the servers timezone.
  1670. Arguments:
  1671. IN ULONG SecondsSince1970 - Supplies the # of seconds since 1970 in
  1672. servers timezone.
  1673. IN PSMB_EXCHANGE Exchange - Supplies the difference in timezones between
  1674. the server and the workstation. If not supplied
  1675. then the assumption is that they are in the
  1676. same timezone.
  1677. OUT PLARGE_INTEGER CurrentTime - Returns the current system time in UTC.
  1678. Return Value:
  1679. None.
  1680. --*/
  1681. {
  1682. LARGE_INTEGER LocalTime;
  1683. PAGED_CODE();
  1684. RtlSecondsSince1970ToTime (SecondsSince1970, &LocalTime);
  1685. ExLocalTimeToSystemTime(&LocalTime, CurrentTime);
  1686. if (ARGUMENT_PRESENT(Server)) {
  1687. (*CurrentTime).QuadPart = (*CurrentTime).QuadPart + Server->TimeZoneBias.QuadPart;
  1688. }
  1689. return;
  1690. }
  1691. ULONG
  1692. MRxSmbMapSmbAttributes (
  1693. IN USHORT SmbAttribs
  1694. )
  1695. /*++
  1696. Routine Description:
  1697. This routine maps an SMB (DOS/OS2) file attribute into an NT
  1698. file attribute.
  1699. Arguments:
  1700. IN USHORT SmbAttribs - Supplies the SMB attribute to map.
  1701. Return Value:
  1702. ULONG - NT Attribute mapping SMB attribute
  1703. --*/
  1704. {
  1705. ULONG Attributes = 0;
  1706. PAGED_CODE();
  1707. if (SmbAttribs==0) {
  1708. Attributes = FILE_ATTRIBUTE_NORMAL;
  1709. } else {
  1710. ASSERT (SMB_FILE_ATTRIBUTE_READONLY == FILE_ATTRIBUTE_READONLY);
  1711. ASSERT (SMB_FILE_ATTRIBUTE_HIDDEN == FILE_ATTRIBUTE_HIDDEN);
  1712. ASSERT (SMB_FILE_ATTRIBUTE_SYSTEM == FILE_ATTRIBUTE_SYSTEM);
  1713. ASSERT (SMB_FILE_ATTRIBUTE_ARCHIVE == FILE_ATTRIBUTE_ARCHIVE);
  1714. ASSERT (SMB_FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY);
  1715. Attributes = SmbAttribs & FILE_ATTRIBUTE_VALID_FLAGS;
  1716. }
  1717. return Attributes;
  1718. }
  1719. USHORT
  1720. MRxSmbMapDisposition (
  1721. IN ULONG Disposition
  1722. )
  1723. /*++
  1724. Routine Description:
  1725. This routine takes an NT disposition, and maps it into an OS/2
  1726. CreateAction to be put into an SMB.
  1727. Arguments:
  1728. IN ULONG Disposition - Supplies the NT disposition to map.
  1729. Return Value:
  1730. USHORT - OS/2 Access mapping that maps NT access
  1731. --*/
  1732. {
  1733. PAGED_CODE();
  1734. switch (Disposition) {
  1735. case FILE_OVERWRITE_IF:
  1736. case FILE_SUPERSEDE:
  1737. return SMB_OFUN_OPEN_TRUNCATE | SMB_OFUN_CREATE_CREATE;
  1738. break;
  1739. case FILE_CREATE:
  1740. return SMB_OFUN_OPEN_FAIL | SMB_OFUN_CREATE_CREATE;
  1741. break;
  1742. case FILE_OVERWRITE:
  1743. return SMB_OFUN_OPEN_TRUNCATE | SMB_OFUN_CREATE_FAIL;
  1744. break;
  1745. case FILE_OPEN:
  1746. return SMB_OFUN_OPEN_OPEN | SMB_OFUN_CREATE_FAIL;
  1747. break;
  1748. case FILE_OPEN_IF:
  1749. return SMB_OFUN_OPEN_OPEN | SMB_OFUN_CREATE_CREATE;
  1750. break;
  1751. default:
  1752. //InternalError(("Unknown disposition passed to MRxSmbMapDisposition"));
  1753. //MRxSmbInternalError(EVENT_RDR_DISPOSITION);
  1754. return 0;
  1755. break;
  1756. }
  1757. }
  1758. ULONG
  1759. MRxSmbUnmapDisposition (
  1760. IN USHORT SmbDisposition,
  1761. ULONG Disposition
  1762. )
  1763. /*++
  1764. Routine Description:
  1765. This routine takes an OS/2 disposition and maps it into an NT
  1766. disposition.
  1767. Arguments:
  1768. IN USHORT SmbDisposition - Supplies the OS/2 disposition to map.
  1769. Return Value:
  1770. ULONG - NT disposition mapping OS/2 disposition
  1771. --*/
  1772. {
  1773. ULONG MapDisposition;
  1774. PAGED_CODE();
  1775. //
  1776. // Mask off oplocked bit.
  1777. //
  1778. switch (SmbDisposition & 0x7fff) {
  1779. case SMB_OACT_OPENED:
  1780. MapDisposition = FILE_OPENED;
  1781. break;
  1782. case SMB_OACT_CREATED:
  1783. MapDisposition = FILE_CREATED;
  1784. break;
  1785. case SMB_OACT_TRUNCATED:
  1786. MapDisposition = FILE_OVERWRITTEN;
  1787. break;
  1788. default:
  1789. MapDisposition = Disposition;
  1790. }
  1791. return MapDisposition;
  1792. }
  1793. USHORT
  1794. MRxSmbMapDesiredAccess (
  1795. IN ULONG DesiredAccess
  1796. )
  1797. /*++
  1798. Routine Description:
  1799. This routine takes an NT DesiredAccess value and converts it
  1800. to an OS/2 access mode.
  1801. Arguments:
  1802. IN ULONG DesiredAccess - Supplies the NT desired access to map.
  1803. Return Value:
  1804. USHORT - The mapped OS/2 access mode that compares to the NT code
  1805. specified. If there is no mapping for the NT code, we return
  1806. -1 as the access mode.
  1807. --*/
  1808. {
  1809. PAGED_CODE();
  1810. //
  1811. // If the user asked for both read and write access, return read/write.
  1812. //
  1813. if ((DesiredAccess & FILE_READ_DATA)&&(DesiredAccess & FILE_WRITE_DATA)) {
  1814. return SMB_DA_ACCESS_READ_WRITE;
  1815. }
  1816. //
  1817. // If the user requested WRITE_DATA, return write.
  1818. //
  1819. if (DesiredAccess & FILE_WRITE_DATA) {
  1820. return SMB_DA_ACCESS_WRITE;
  1821. }
  1822. //
  1823. // If the user requested READ_DATA, return read.
  1824. //
  1825. if (DesiredAccess & FILE_READ_DATA) {
  1826. return SMB_DA_ACCESS_READ;
  1827. }
  1828. //
  1829. // If the user requested ONLY execute access, then request execute
  1830. // access. Execute access is the "weakest" of the possible desired
  1831. // accesses, so it takes least precedence.
  1832. //
  1833. if (DesiredAccess & FILE_EXECUTE) {
  1834. return SMB_DA_ACCESS_EXECUTE;
  1835. }
  1836. //
  1837. // If we couldn't figure out what we were doing, return -1
  1838. //
  1839. // Among the attributes that we do not map are:
  1840. //
  1841. // FILE_READ_ATTRIBUTES
  1842. // FILE_WRITE_ATTRIBUTES
  1843. // FILE_READ_EAS
  1844. // FILE_WRITE_EAS
  1845. //
  1846. // dprintf(DPRT_ERROR, ("Could not map DesiredAccess of %08lx\n", DesiredAccess));
  1847. return (USHORT)0;
  1848. }
  1849. USHORT
  1850. MRxSmbMapShareAccess (
  1851. IN USHORT ShareAccess
  1852. )
  1853. /*++
  1854. Routine Description:
  1855. This routine takes an NT ShareAccess value and converts it to an
  1856. OS/2 sharing mode.
  1857. Arguments:
  1858. IN USHORT ShareAccess - Supplies the OS/2 share access to map.
  1859. Return Value:
  1860. USHORT - The mapped OS/2 sharing mode that compares to the NT code
  1861. specified
  1862. --*/
  1863. {
  1864. USHORT ShareMode = SMB_DA_SHARE_EXCLUSIVE;
  1865. PAGED_CODE();
  1866. if ((ShareAccess & (FILE_SHARE_READ | FILE_SHARE_WRITE)) ==
  1867. (FILE_SHARE_READ | FILE_SHARE_WRITE)) {
  1868. ShareMode = SMB_DA_SHARE_DENY_NONE;
  1869. } else if (ShareAccess & FILE_SHARE_READ) {
  1870. ShareMode = SMB_DA_SHARE_DENY_WRITE;
  1871. } else if (ShareAccess & FILE_SHARE_WRITE) {
  1872. ShareMode = SMB_DA_SHARE_DENY_READ;
  1873. }
  1874. // else if (ShareAccess & FILE_SHARE_DELETE) {
  1875. // InternalError(("Support for FILE_SHARE_DELETE NYI\n"));
  1876. // }
  1877. return ShareMode;
  1878. }
  1879. USHORT
  1880. MRxSmbMapFileAttributes (
  1881. IN ULONG FileAttributes
  1882. )
  1883. /*++
  1884. Routine Description:
  1885. This routine takes an NT file attribute mapping and converts it into
  1886. an OS/2 file attribute definition.
  1887. Arguments:
  1888. IN ULONG FileAttributes - Supplies the file attributes to map.
  1889. Return Value:
  1890. USHORT
  1891. --*/
  1892. {
  1893. USHORT ResultingAttributes = 0;
  1894. PAGED_CODE();
  1895. if (FileAttributes==FILE_ATTRIBUTE_NORMAL) {
  1896. return ResultingAttributes;
  1897. }
  1898. if (FileAttributes & FILE_ATTRIBUTE_READONLY) {
  1899. ResultingAttributes |= SMB_FILE_ATTRIBUTE_READONLY;
  1900. }
  1901. if (FileAttributes & FILE_ATTRIBUTE_HIDDEN) {
  1902. ResultingAttributes |= SMB_FILE_ATTRIBUTE_HIDDEN;
  1903. }
  1904. if (FileAttributes & FILE_ATTRIBUTE_SYSTEM) {
  1905. ResultingAttributes |= SMB_FILE_ATTRIBUTE_SYSTEM;
  1906. }
  1907. if (FileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
  1908. ResultingAttributes |= SMB_FILE_ATTRIBUTE_ARCHIVE;
  1909. }
  1910. return ResultingAttributes;
  1911. }