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.

2414 lines
79 KiB

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