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

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