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.

514 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. FileIo.c
  5. Abstract:
  6. This module implements various FileSystem routines used by
  7. the PGM Transport
  8. Author:
  9. Mohammad Shabbir Alam (MAlam) 3-30-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #ifdef FILE_LOGGING
  14. #include "fileio.tmh"
  15. #endif // FILE_LOGGING
  16. NTSTATUS
  17. BuildPgmDataFileName(
  18. IN tSEND_SESSION *pSend
  19. );
  20. //******************* Pageable Routine Declarations ****************
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, BuildPgmDataFileName)
  23. #pragma alloc_text(PAGE, PgmCreateDataFileAndMapSection)
  24. #pragma alloc_text(PAGE, PgmUnmapAndCloseDataFile)
  25. #endif
  26. //******************* Pageable Routine Declarations ****************
  27. //----------------------------------------------------------------------------
  28. NTSTATUS
  29. BuildPgmDataFileName(
  30. IN tSEND_SESSION *pSend
  31. )
  32. /*++
  33. Routine Description:
  34. This routine build the string for the file name used for buffering
  35. data packets.
  36. Arguments:
  37. IN pSend -- the Send object
  38. Return Value:
  39. NONE -- since we don't expect any error
  40. --*/
  41. {
  42. UNICODE_STRING ucPortNumber;
  43. WCHAR wcPortNumber[10];
  44. USHORT usRandomNumber, MaxFileLength;
  45. PAGED_CODE();
  46. if (pPgmRegistryConfig->Flags & PGM_REGISTRY_SENDER_FILE_SPECIFIED)
  47. {
  48. MaxFileLength = pPgmRegistryConfig->ucSenderFileLocation.Length / sizeof(WCHAR);
  49. }
  50. else
  51. {
  52. MaxFileLength = sizeof (WS_DEFAULT_SENDER_FILE_LOCATION) / sizeof (WCHAR);
  53. }
  54. //
  55. // The file name is composed of the following:
  56. // "\\T" + Last2DigitPort# + UptoMAX_USHORT5DigitRandom# + ".PGM" + "\0"
  57. //
  58. MaxFileLength += 2 + 2 + 5 + 4 + 1;
  59. if (!(pSend->pSender->DataFileName.Buffer = PgmAllocMem ((sizeof (WCHAR) * MaxFileLength), PGM_TAG('2'))))
  60. {
  61. PgmTrace (LogError, ("BuildPgmDataFileName: ERROR -- " \
  62. "STATUS_INSUFFICIENT_RESOURCES allocating <%d> bytes\n", MaxFileLength));
  63. return (STATUS_INSUFFICIENT_RESOURCES);
  64. }
  65. pSend->pSender->DataFileName.MaximumLength = sizeof (WCHAR) * MaxFileLength;
  66. pSend->pSender->DataFileName.Length = 0;
  67. //
  68. // First, set the root directory
  69. //
  70. if (pPgmRegistryConfig->Flags & PGM_REGISTRY_SENDER_FILE_SPECIFIED)
  71. {
  72. RtlAppendUnicodeToString (&pSend->pSender->DataFileName, pPgmRegistryConfig->ucSenderFileLocation.Buffer);
  73. }
  74. else
  75. {
  76. RtlAppendUnicodeToString (&pSend->pSender->DataFileName, WS_DEFAULT_SENDER_FILE_LOCATION);
  77. }
  78. RtlAppendUnicodeToString (&pSend->pSender->DataFileName, L"\\T");
  79. //
  80. // Append the last 2 digits of the Port#
  81. //
  82. ucPortNumber.MaximumLength = sizeof (wcPortNumber);
  83. ucPortNumber.Buffer = wcPortNumber;
  84. usRandomNumber = pSend->TSI.hPort % 100;
  85. if (usRandomNumber < 10)
  86. {
  87. RtlAppendUnicodeToString (&pSend->pSender->DataFileName, L"0");
  88. }
  89. RtlIntegerToUnicodeString ((ULONG) usRandomNumber, 10, &ucPortNumber);
  90. RtlAppendUnicodeStringToString (&pSend->pSender->DataFileName, &ucPortNumber);
  91. //
  92. // Now, Append a random 5 digit value
  93. //
  94. GetRandomData ((PUCHAR) &usRandomNumber, sizeof (usRandomNumber));
  95. RtlIntegerToUnicodeString ((ULONG) usRandomNumber, 10, &ucPortNumber);
  96. RtlAppendUnicodeStringToString (&pSend->pSender->DataFileName, &ucPortNumber);
  97. //
  98. // Now, add the file name extension for id
  99. //
  100. RtlAppendUnicodeToString (&pSend->pSender->DataFileName, L".PGM");
  101. return (STATUS_SUCCESS);
  102. }
  103. //----------------------------------------------------------------------------
  104. NTSTATUS
  105. PgmCreateDataFileAndMapSection(
  106. IN tADDRESS_CONTEXT *pAddress,
  107. IN tSEND_SESSION *pSend
  108. )
  109. /*++
  110. Routine Description:
  111. This routine creates the file and creates a section mapping for it.
  112. This file is used for buffering the data packets on behalf of the sender
  113. Arguments:
  114. IN pSend -- the Send object
  115. Return Value:
  116. NTSTATUS - Final status of the create operation
  117. --*/
  118. {
  119. SECURITY_DESCRIPTOR *pSecurityDescriptor;
  120. OBJECT_ATTRIBUTES ObjectAttributes;
  121. IO_STATUS_BLOCK IoStatusBlock;
  122. LARGE_INTEGER lgMaxDataFileSize;
  123. NTSTATUS Status;
  124. ULONGLONG Size, BlockSize, PacketsInWindow;
  125. ULONG DesiredAccess;
  126. ULONG FileAttributes, AllocationAttributes;
  127. ULONG ShareAccess;
  128. ULONG CreateDisposition;
  129. ULONG CreateOptions;
  130. ULONG Protection;
  131. SIZE_T ViewSize;
  132. KAPC_STATE ApcState;
  133. BOOLEAN fAttached;
  134. PAGED_CODE();
  135. //
  136. // Make sure we are currently attached to the Application process
  137. //
  138. PgmAttachToProcessForVMAccess (pSend, &ApcState, &fAttached, REF_PROCESS_ATTACH_CREATE_DATA_FILE);
  139. //
  140. // First build the File name string
  141. //
  142. Status = BuildPgmDataFileName (pSend);
  143. if (!NT_SUCCESS (Status))
  144. {
  145. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  146. "BuildPgmDataFileName returned <%x>\n", Status));
  147. PgmDetachProcess (&ApcState, &fAttached, REF_PROCESS_ATTACH_CREATE_DATA_FILE);
  148. return (Status);
  149. }
  150. //
  151. // Compute the size of the Data file required to hold 2 * Window size
  152. // Also make it a multiple of the MTU and the FECGroupSize (if applicable)
  153. //
  154. PacketsInWindow = pSend->pAssociatedAddress->WindowSizeInBytes / pSend->pAssociatedAddress->OutIfMTU;
  155. if (pSend->FECGroupSize > 1)
  156. {
  157. // PacketsInWindow += PacketsInWindow + (PacketsInWindow >> 2) + pSend->FECGroupSize - 1;
  158. PacketsInWindow += PacketsInWindow + pSend->FECGroupSize - 1;
  159. }
  160. else
  161. {
  162. PacketsInWindow += PacketsInWindow - (PacketsInWindow >> 2);
  163. }
  164. if (PacketsInWindow > SENDER_MAX_WINDOW_SIZE_PACKETS)
  165. {
  166. PacketsInWindow = SENDER_MAX_WINDOW_SIZE_PACKETS;
  167. if (pSend->pAssociatedAddress->WindowSizeInBytes > ((PacketsInWindow >> 1) *
  168. pSend->pAssociatedAddress->OutIfMTU))
  169. {
  170. pSend->pAssociatedAddress->WindowSizeInBytes = (PacketsInWindow >> 1) * pSend->pAssociatedAddress->OutIfMTU;
  171. pSend->pAssociatedAddress->WindowSizeInMSecs = (BITS_PER_BYTE *
  172. pSend->pAssociatedAddress->WindowSizeInBytes) /
  173. pSend->pAssociatedAddress->RateKbitsPerSec;
  174. }
  175. }
  176. BlockSize = pSend->FECGroupSize * pSend->pSender->PacketBufferSize;
  177. Size = PacketsInWindow * pSend->pSender->PacketBufferSize;
  178. Size = (Size / BlockSize) * BlockSize;
  179. pSend->pSender->MaxDataFileSize = Size;
  180. pSend->pSender->MaxPacketsInBuffer = Size / pSend->pSender->PacketBufferSize;
  181. lgMaxDataFileSize.QuadPart = Size;
  182. Status = InitRDataInfo (pAddress, pSend);
  183. if (!NT_SUCCESS (Status))
  184. {
  185. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  186. "InitRDataInfo returned <%x>\n", Status));
  187. PgmFreeMem (pSend->pSender->DataFileName.Buffer);
  188. pSend->pSender->DataFileName.Buffer = NULL;
  189. PgmDetachProcess (&ApcState, &fAttached, REF_PROCESS_ATTACH_CREATE_DATA_FILE);
  190. return (Status);
  191. }
  192. pSecurityDescriptor = NULL;
  193. Status = PgmBuildAdminSecurityDescriptor (&pSecurityDescriptor);
  194. if (!NT_SUCCESS (Status))
  195. {
  196. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  197. "PgmCreateSecurityDescriptor returned <%x>\n", Status));
  198. goto Cleanup;
  199. }
  200. PgmZeroMemory (&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
  201. InitializeObjectAttributes (&ObjectAttributes,
  202. &pSend->pSender->DataFileName,
  203. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  204. NULL,
  205. pSecurityDescriptor);
  206. //
  207. // We need to open the data file. This file contains data
  208. // and will be mapped into memory. Read and Write access
  209. // are requested.
  210. //
  211. DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA | DELETE;
  212. // Using the FILE_ATTRIBUTE_TEMPORARY flag:
  213. // you let the system know that the file is likely to be short lived.
  214. // The temporary file is created as a normal file. The system needs to do
  215. // a minimal amount of lazy writes to the file system to keep the disk
  216. // structures (directories and so forth) consistent. This gives the
  217. // appearance that the file has been written to the disk. However, unless
  218. // the Memory Manager detects an inadequate supply of free pages and
  219. // starts writing modified pages to the disk, the Cache Manager's Lazy
  220. // Writer may never write the data pages of this file to the disk.
  221. // If the system has enough memory, the pages may remain in memory for
  222. // any arbitrary amount of time. Because temporary files are generally
  223. // short lived, there is a good chance the system will never write the pages to the disk.
  224. FileAttributes = FILE_ATTRIBUTE_TEMPORARY;
  225. ShareAccess = 0; // Gives the caller exclusive access to the open file
  226. CreateDisposition = FILE_CREATE | FILE_SUPERSEDE;
  227. // Delete the file when the last handle to it is passed to ZwClose.
  228. CreateOptions = FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE;
  229. PgmZeroMemory (&IoStatusBlock, sizeof(IO_STATUS_BLOCK));
  230. Status = ZwCreateFile (&pSend->pSender->FileHandle,
  231. DesiredAccess,
  232. &ObjectAttributes,
  233. &IoStatusBlock,
  234. &lgMaxDataFileSize, // AllocationSize
  235. FileAttributes,
  236. ShareAccess,
  237. CreateDisposition,
  238. CreateOptions,
  239. NULL, // EaBuffer
  240. 0); // EaLength
  241. if (!NT_SUCCESS (Status))
  242. {
  243. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  244. "ZwCreateFile for <%wZ> returned <%x>\n", &pSend->pSender->DataFileName, Status));
  245. goto Cleanup;
  246. }
  247. //
  248. // Now we have a handle to our open test file. We now create a section
  249. // object with this handle.
  250. //
  251. DesiredAccess = STANDARD_RIGHTS_REQUIRED |
  252. SECTION_QUERY |
  253. SECTION_MAP_READ |
  254. SECTION_MAP_WRITE;
  255. Protection = PAGE_READWRITE;
  256. AllocationAttributes = SEC_COMMIT;
  257. PgmZeroMemory (&ObjectAttributes, sizeof (OBJECT_ATTRIBUTES));
  258. InitializeObjectAttributes (&ObjectAttributes,
  259. NULL,
  260. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  261. NULL,
  262. NULL);
  263. Status = ZwCreateSection (&pSend->pSender->SectionHandle,
  264. DesiredAccess,
  265. &ObjectAttributes, // NULL ?
  266. &lgMaxDataFileSize,
  267. Protection,
  268. AllocationAttributes,
  269. pSend->pSender->FileHandle);
  270. if (!NT_SUCCESS (Status))
  271. {
  272. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  273. "ZwCreateSection for <%wZ> returned <%x>\n", &pSend->pSender->DataFileName, Status));
  274. goto Cleanup;
  275. }
  276. //
  277. // Reference the section object, if a view is mapped to the section
  278. // object, the object is not dereferenced as the virtual address
  279. // descriptor contains a pointer to the section object.
  280. //
  281. Status = ObReferenceObjectByHandle (pSend->pSender->SectionHandle,
  282. 0,
  283. 0,
  284. KernelMode,
  285. &pSend->pSender->pSectionObject,
  286. NULL );
  287. if (!NT_SUCCESS (Status))
  288. {
  289. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  290. "ObReferenceObjectByHandle for SectionHandle=<%p> returned <%x>\n",
  291. pSend->pSender->SectionHandle, Status));
  292. goto Cleanup;
  293. }
  294. //
  295. // Our section object has been created and linked to the file
  296. // object that was previous opened. Now we map a view on
  297. // this section.
  298. //
  299. ViewSize = 0;
  300. Protection = PAGE_READWRITE;
  301. Status = ZwMapViewOfSection (pSend->pSender->SectionHandle,
  302. NtCurrentProcess(),
  303. &pSend->pSender->SendDataBufferMapping,
  304. 0L, // ZeroBits
  305. 0L, // CommitSize (initially committed region)
  306. NULL, // &SectionOffset
  307. &ViewSize,
  308. ViewUnmap, // InheritDisposition: for child processes
  309. 0L, // AllocationType
  310. Protection);
  311. if (!NT_SUCCESS (Status))
  312. {
  313. PgmTrace (LogError, ("PgmCreateDataFileAndMapSection: ERROR -- " \
  314. "ZwMapViewOfSection for <%wZ> returned <%x>\n", &pSend->pSender->DataFileName, Status));
  315. goto Cleanup;
  316. }
  317. PgmTrace (LogStatus, ("PgmCreateDataFileAndMapSection: " \
  318. "Mapped <%wZ> to address<%p>, Filelength=<%I64d>\n",
  319. &pSend->pSender->DataFileName, pSend->pSender->SendDataBufferMapping, Size));
  320. pSend->pSender->BufferSizeAvailable = pSend->pSender->MaxDataFileSize;
  321. pSend->pSender->BufferPacketsAvailable = (ULONG) pSend->pSender->MaxPacketsInBuffer;
  322. pSend->pSender->LeadingWindowOffset = pSend->pSender->TrailingWindowOffset = 0;
  323. //
  324. // Now, reference the process
  325. //
  326. ObReferenceObject (pSend->Process);
  327. PgmDetachProcess (&ApcState, &fAttached, REF_PROCESS_ATTACH_CREATE_DATA_FILE);
  328. PgmFreeMem (pSecurityDescriptor);
  329. return (STATUS_SUCCESS);
  330. Cleanup:
  331. ASSERT (!NT_SUCCESS (Status));
  332. if (pSend->pSender->pSectionObject)
  333. {
  334. ObDereferenceObject (pSend->pSender->pSectionObject);
  335. pSend->pSender->pSectionObject = NULL;
  336. }
  337. if (pSend->pSender->SectionHandle)
  338. {
  339. ZwClose (pSend->pSender->SectionHandle);
  340. pSend->pSender->SectionHandle = NULL;
  341. }
  342. if (pSend->pSender->FileHandle)
  343. {
  344. ZwClose (pSend->pSender->FileHandle);
  345. pSend->pSender->FileHandle = NULL;
  346. }
  347. if (pSecurityDescriptor)
  348. {
  349. PgmFreeMem (pSecurityDescriptor);
  350. }
  351. PgmDetachProcess (&ApcState, &fAttached, REF_PROCESS_ATTACH_CREATE_DATA_FILE);
  352. PgmFreeMem (pSend->pSender->DataFileName.Buffer);
  353. pSend->pSender->DataFileName.Buffer = NULL;
  354. DestroyRDataInfo (pSend);
  355. return (Status);
  356. }
  357. //----------------------------------------------------------------------------
  358. NTSTATUS
  359. PgmUnmapAndCloseDataFile(
  360. IN tSEND_SESSION *pSend
  361. )
  362. /*++
  363. Routine Description:
  364. This routine cleansup the file mapping and closes the file
  365. handles. The file should automatically get deleted on closing
  366. the handle since we used the FILE_DELETE_ON_CLOSE option while
  367. creating the file.
  368. Arguments:
  369. IN pSend -- the Send object
  370. Return Value:
  371. NTSTATUS - Final status of the operation (STATUS_SUCCESS)
  372. --*/
  373. {
  374. NTSTATUS Status;
  375. KAPC_STATE ApcState;
  376. BOOLEAN fAttached;
  377. PAGED_CODE();
  378. DestroyRDataInfo (pSend);
  379. PgmAttachToProcessForVMAccess (pSend, &ApcState, &fAttached, REF_PROCESS_ATTACH_CLOSE_DATA_FILE);
  380. Status = ZwUnmapViewOfSection (NtCurrentProcess(), (PVOID) pSend->pSender->SendDataBufferMapping);
  381. ASSERT (NT_SUCCESS (Status));
  382. ObDereferenceObject (pSend->pSender->pSectionObject);
  383. pSend->pSender->pSectionObject = NULL;
  384. Status = ZwClose (pSend->pSender->SectionHandle);
  385. ASSERT (NT_SUCCESS (Status));
  386. pSend->pSender->SectionHandle = NULL;
  387. Status = ZwClose (pSend->pSender->FileHandle);
  388. ASSERT (NT_SUCCESS (Status));
  389. PgmDetachProcess (&ApcState, &fAttached, REF_PROCESS_ATTACH_CLOSE_DATA_FILE);
  390. ObDereferenceObject (pSend->Process); // Since we had referenced it when the file was created
  391. pSend->pSender->SendDataBufferMapping = NULL;
  392. pSend->pSender->pSectionObject = NULL;
  393. pSend->pSender->SectionHandle = NULL;
  394. pSend->pSender->FileHandle = NULL;
  395. PgmTrace (LogStatus, ("PgmUnmapAndCloseDataFile: " \
  396. "pSend = <%p>\n", pSend));
  397. return (STATUS_SUCCESS);
  398. }