Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

732 lines
21 KiB

  1. /*++
  2. Copyright (c) 1990,1991 Microsoft Corporation
  3. Module Name:
  4. filemap.c
  5. Abstract:
  6. This module implements Win32 mapped file APIs
  7. Author:
  8. Mark Lucovsky (markl) 15-Feb-1991
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. HANDLE
  13. APIENTRY
  14. CreateFileMappingA(
  15. HANDLE hFile,
  16. LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  17. DWORD flProtect,
  18. DWORD dwMaximumSizeHigh,
  19. DWORD dwMaximumSizeLow,
  20. LPCSTR lpName
  21. )
  22. /*++
  23. Routine Description:
  24. ANSI thunk to CreateFileMappingW
  25. --*/
  26. {
  27. PUNICODE_STRING Unicode;
  28. ANSI_STRING AnsiString;
  29. NTSTATUS Status;
  30. LPCWSTR NameBuffer;
  31. NameBuffer = NULL;
  32. if ( ARGUMENT_PRESENT(lpName) ) {
  33. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  34. RtlInitAnsiString(&AnsiString,lpName);
  35. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  36. if ( !NT_SUCCESS(Status) ) {
  37. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  38. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  39. }
  40. else {
  41. BaseSetLastNTError(Status);
  42. }
  43. return NULL;
  44. }
  45. NameBuffer = (LPCWSTR)Unicode->Buffer;
  46. }
  47. return CreateFileMappingW(
  48. hFile,
  49. lpFileMappingAttributes,
  50. flProtect,
  51. dwMaximumSizeHigh,
  52. dwMaximumSizeLow,
  53. NameBuffer
  54. );
  55. }
  56. HANDLE
  57. APIENTRY
  58. CreateFileMappingW(
  59. HANDLE hFile,
  60. LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  61. DWORD flProtect,
  62. DWORD dwMaximumSizeHigh,
  63. DWORD dwMaximumSizeLow,
  64. LPCWSTR lpName
  65. )
  66. /*++
  67. Routine Description:
  68. A file mapping object can be created using CreateFileMapping
  69. Creating a file mapping object creates the potential for mapping a
  70. view of the file into an address space. File mapping objects may be
  71. shared either through process creation or handle duplication.
  72. Having a handle to a file mapping object allows for mapping of the
  73. file. It does not mean that the file is actually mapped.
  74. A file mapping object has a maximum size. This is used to size the
  75. file. A file may not grow beyond the size specified in the mapping
  76. object. While not required, it is recommended that when opening a
  77. file that you intend to map, the file should be opened for exclusive
  78. access. Win32 does not require that a mapped file and a file
  79. accessed via the IO primitives (ReadFile/WriteFile) are coherent.
  80. In addition to the STANDARD_RIGHTS_REQUIRED access flags, the
  81. following object type specific access flags are valid for file
  82. mapping objects:
  83. - FILE_MAP_WRITE - Write map access to the file mapping object is
  84. desired. This allows a writable view of the file to be
  85. mapped. Note that if flProtect does not include
  86. PAGE_READWRITE, this access type does not allow writing the
  87. mapped file.
  88. - FILE_MAP_READ - Read map access to the file mapping object is
  89. desired. This allows a readablee view of the file to be
  90. mapped.
  91. - FILE_MAP_ALL_ACCESS - This set of access flags specifies all of
  92. the possible access flags for a file mapping object.
  93. Arguments:
  94. hFile - Supplies an open handle to a file that a mapping object is
  95. to be created for. The file must be opened with an access mode
  96. that is compatible with the specified pretection flags. A value
  97. of INVALID_HANDLE_VALUE specifies that the mapping object is
  98. backed by the system paging file. If this is the case, a size
  99. must be specified.
  100. lpFileMappingAttributes - An optional parameter that may be used to
  101. specify the attributes of the new file mapping object. If the
  102. parameter is not specified, then the file mapping object is
  103. created without a security descriptor, and the resulting handle
  104. is not inherited on process creation:
  105. flProtect - The protection desired for mapping object when the file
  106. is mapped.
  107. flProtect Values
  108. PAGE_READONLY - Read access to the committed region of pages is
  109. allowed. An attempt to write or execute the committed
  110. region results in an access violation. The specified hFile
  111. must have been created with GENERIC_READ access.
  112. PAGE_READWRITE - Read and write access to the committed region
  113. of pages is allowed. The specified hFile must have been
  114. created with GENERIC_READ and GENERIC_WRITE access.
  115. PAGE_WRITECOPY - Read and copy on write access to the committed
  116. region of pages is allowed. The specified hFile must have been
  117. created with GENERIC_READ access.
  118. dwMaximumSizeHigh - Supplies the high order 32-bits of the maximum
  119. size of the file mapping object.
  120. dwMaximumSizeLow - Supplies the low order 32-bits of the maximum
  121. size of the file mapping object. A value of zero along with a
  122. value of zero in dwMaximumSizeHigh indicates that the size of
  123. the file mapping object is equal to the current size of the file
  124. specified by hFile.
  125. lpName - Supplies the name ofthe file mapping object.
  126. Return Value:
  127. NON-NULL - Returns a handle to the new file mapping object. The
  128. handle has full access to the new file mapping object and may be
  129. used in any API that requires a handle to a file mapping object.
  130. FALSE/NULL - The operation failed. Extended error status is available
  131. using GetLastError.
  132. --*/
  133. {
  134. HANDLE Section;
  135. NTSTATUS Status;
  136. LARGE_INTEGER SectionSizeData;
  137. PLARGE_INTEGER SectionSize;
  138. OBJECT_ATTRIBUTES Obja;
  139. POBJECT_ATTRIBUTES pObja;
  140. ACCESS_MASK DesiredAccess;
  141. UNICODE_STRING ObjectName;
  142. ULONG AllocationAttributes;
  143. PWCHAR pstrNewObjName = NULL;
  144. DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
  145. AllocationAttributes = flProtect & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE);
  146. flProtect ^= AllocationAttributes;
  147. if (AllocationAttributes == 0) {
  148. AllocationAttributes = SEC_COMMIT;
  149. }
  150. if ( flProtect == PAGE_READWRITE ) {
  151. DesiredAccess |= (SECTION_MAP_READ | SECTION_MAP_WRITE);
  152. }
  153. else
  154. if ( flProtect != PAGE_READONLY && flProtect != PAGE_WRITECOPY ) {
  155. SetLastError(ERROR_INVALID_PARAMETER);
  156. return NULL;
  157. }
  158. if ( ARGUMENT_PRESENT(lpName) ) {
  159. if (gpTermsrvFormatObjectName &&
  160. (pstrNewObjName = gpTermsrvFormatObjectName(lpName))) {
  161. RtlInitUnicodeString(&ObjectName,pstrNewObjName);
  162. } else {
  163. RtlInitUnicodeString(&ObjectName,lpName);
  164. }
  165. pObja = BaseFormatObjectAttributes(&Obja,lpFileMappingAttributes,&ObjectName);
  166. }
  167. else {
  168. pObja = BaseFormatObjectAttributes(&Obja,lpFileMappingAttributes,NULL);
  169. }
  170. if ( dwMaximumSizeLow || dwMaximumSizeHigh ) {
  171. SectionSize = &SectionSizeData;
  172. SectionSize->LowPart = dwMaximumSizeLow;
  173. SectionSize->HighPart = dwMaximumSizeHigh;
  174. }
  175. else {
  176. SectionSize = NULL;
  177. }
  178. if (hFile == INVALID_HANDLE_VALUE) {
  179. hFile = NULL;
  180. if ( !SectionSize ) {
  181. SetLastError(ERROR_INVALID_PARAMETER);
  182. if (pstrNewObjName) {
  183. RtlFreeHeap(RtlProcessHeap(), 0, pstrNewObjName);
  184. }
  185. return NULL;
  186. }
  187. }
  188. Status = NtCreateSection(
  189. &Section,
  190. DesiredAccess,
  191. pObja,
  192. SectionSize,
  193. flProtect,
  194. AllocationAttributes,
  195. hFile
  196. );
  197. if (pstrNewObjName) {
  198. RtlFreeHeap(RtlProcessHeap(), 0, pstrNewObjName);
  199. }
  200. if ( !NT_SUCCESS(Status) ) {
  201. BaseSetLastNTError(Status);
  202. return Section = NULL;
  203. }
  204. else {
  205. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  206. SetLastError(ERROR_ALREADY_EXISTS);
  207. }
  208. else {
  209. SetLastError(0);
  210. }
  211. }
  212. return Section;
  213. }
  214. HANDLE
  215. APIENTRY
  216. OpenFileMappingA(
  217. DWORD dwDesiredAccess,
  218. BOOL bInheritHandle,
  219. LPCSTR lpName
  220. )
  221. /*++
  222. Routine Description:
  223. ANSI thunk to OpenFileMappingW
  224. --*/
  225. {
  226. PUNICODE_STRING Unicode;
  227. ANSI_STRING AnsiString;
  228. NTSTATUS Status;
  229. if ( ARGUMENT_PRESENT(lpName) ) {
  230. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  231. RtlInitAnsiString(&AnsiString,lpName);
  232. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  233. if ( !NT_SUCCESS(Status) ) {
  234. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  235. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  236. }
  237. else {
  238. BaseSetLastNTError(Status);
  239. }
  240. return NULL;
  241. }
  242. }
  243. else {
  244. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  245. return NULL;
  246. }
  247. return OpenFileMappingW(
  248. dwDesiredAccess,
  249. bInheritHandle,
  250. (LPCWSTR)Unicode->Buffer
  251. );
  252. }
  253. HANDLE
  254. APIENTRY
  255. OpenFileMappingW(
  256. DWORD dwDesiredAccess,
  257. BOOL bInheritHandle,
  258. LPCWSTR lpName
  259. )
  260. {
  261. OBJECT_ATTRIBUTES Obja;
  262. UNICODE_STRING ObjectName;
  263. NTSTATUS Status;
  264. HANDLE Object;
  265. PWCHAR pstrNewObjName = NULL;
  266. if ( !lpName ) {
  267. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  268. return NULL;
  269. }
  270. if (gpTermsrvFormatObjectName &&
  271. (pstrNewObjName = gpTermsrvFormatObjectName(lpName))) {
  272. RtlInitUnicodeString(&ObjectName,pstrNewObjName);
  273. } else {
  274. RtlInitUnicodeString(&ObjectName,lpName);
  275. }
  276. InitializeObjectAttributes(
  277. &Obja,
  278. &ObjectName,
  279. (bInheritHandle ? OBJ_INHERIT : 0),
  280. BaseGetNamedObjectDirectory(),
  281. NULL
  282. );
  283. if ( dwDesiredAccess == FILE_MAP_COPY ) {
  284. dwDesiredAccess = FILE_MAP_READ;
  285. }
  286. Status = NtOpenSection(
  287. &Object,
  288. dwDesiredAccess,
  289. &Obja
  290. );
  291. if (pstrNewObjName) {
  292. RtlFreeHeap(RtlProcessHeap(), 0, pstrNewObjName);
  293. }
  294. if ( !NT_SUCCESS(Status) ) {
  295. BaseSetLastNTError(Status);
  296. return NULL;
  297. }
  298. return Object;
  299. }
  300. LPVOID
  301. APIENTRY
  302. MapViewOfFile(
  303. HANDLE hFileMappingObject,
  304. DWORD dwDesiredAccess,
  305. DWORD dwFileOffsetHigh,
  306. DWORD dwFileOffsetLow,
  307. SIZE_T dwNumberOfBytesToMap
  308. )
  309. /*++
  310. Routine Description:
  311. A view of a file may be mapped into the address space of the calling
  312. process using MapViewOfFile.
  313. Mapping a file object makes the specified portion of the file
  314. visible in the address space of the calling process. The return
  315. address is a pointer to memory that when addressed causes data
  316. within the file to be accessed.
  317. Mapping a view of a file has some simple coherency rules:
  318. - Multiple views on a file are coherent if they are derived from
  319. the same file mapping object. If a process opens a file,
  320. creates a mapping object, duplicates the object to another
  321. process... If both processes map a view of the file, they will
  322. both see a coherent view of the file's data... they will
  323. effectively be viewing shared memory backed by the file.
  324. - If multiple mapping objects exist for the same file, then views
  325. derived from the different mapping objects are not garunteed to
  326. be coherent.
  327. - A mapped view on a file is not garunteed to be coherent with a
  328. file being accessed via ReadFile or WriteFile.
  329. Arguments:
  330. hFileMappingObject - Supplies an open handle to a file mapping object
  331. that is to be mapped into the callers address space.
  332. dwDesiredAccess - Specifies the access that is requested to the file
  333. mapping object. This determines the page protection of the pages
  334. mapped by the file.
  335. dwDesiredAccess Values:
  336. FILE_MAP_WRITE - Read/write access is desired. The mapping
  337. object must have been created with PAGE_READWRITE
  338. protection. The hFileMappingObject must have been created
  339. with FILE_MAP_WRITE access. A read/write view of the file will
  340. be mapped.
  341. FILE_MAP_READ - Read access is desired. The mapping object must
  342. have been created with PAGE_READWRITE or PAGE_READ
  343. protection. The hFileMappingObject must have been created
  344. with FILE_MAP_READ access. A read only view of the file
  345. will be mapped.
  346. dwFileOffsetHigh - Supplies the high order 32-bits of the file
  347. offset where mapping is to begin.
  348. dwFileOffsetLow - Supplies the low order 32-bits of the file offset
  349. where mapping is to begin. The combination of the high and low
  350. offsets must specify a 64Kb aligned offset within the file. It
  351. is an error if this is not the case.
  352. dwNumberOfBytesToMap - Supplies the number of bytes of the file to map.
  353. A value of zero specifies that the entire file is to be mapped.
  354. Return Value:
  355. NON-NULL - Returns the address of where the file is mapped.
  356. NULL - The operation failed. Extended error status is available
  357. using GetLastError.
  358. --*/
  359. {
  360. return MapViewOfFileEx(
  361. hFileMappingObject,
  362. dwDesiredAccess,
  363. dwFileOffsetHigh,
  364. dwFileOffsetLow,
  365. dwNumberOfBytesToMap,
  366. NULL
  367. );
  368. }
  369. LPVOID
  370. APIENTRY
  371. MapViewOfFileEx(
  372. HANDLE hFileMappingObject,
  373. DWORD dwDesiredAccess,
  374. DWORD dwFileOffsetHigh,
  375. DWORD dwFileOffsetLow,
  376. SIZE_T dwNumberOfBytesToMap,
  377. LPVOID lpBaseAddress
  378. )
  379. /*++
  380. Routine Description:
  381. A view of a file may be mapped into the address space of the calling
  382. process using MapViewOfFileEx.
  383. Mapping a file object makes the specified portion of the file
  384. visible in the address space of the calling process. The return
  385. address is a pointer to memory that when addressed causes data
  386. within the file to be accessed. This API allows the caller to
  387. supply the system with a suggested mapping address. The system
  388. will round this address down to the nearest 64k boundry and attempt
  389. to map the file at thet address. If there is not enough address space
  390. at that address, this call will fail.
  391. Mapping a view of a file has some simple coherency rules:
  392. - Multiple views on a file are coherent if they are derived from
  393. the same file mapping object. If a process opens a file,
  394. creates a mapping object, duplicates the object to another
  395. process... If both processes map a view of the file, they will
  396. both see a coherent view of the file's data... they will
  397. effectively be viewing shared memory backed by the file.
  398. - If multiple mapping objects exist for the same file, then views
  399. derived from the different mapping objects are not garunteed to
  400. be coherent.
  401. - A mapped view on a file is not garunteed to be coherent with a
  402. file being accessed via ReadFile or WriteFile.
  403. Arguments:
  404. hFileMappingObject - Supplies an open handle to a file mapping object
  405. that is to be mapped into the callers address space.
  406. dwDesiredAccess - Specifies the access that is requested to the file
  407. mapping object. This determines the page protection of the pages
  408. mapped by the file.
  409. dwDesiredAccess Values:
  410. FILE_MAP_WRITE - Read/write access is desired. The mapping
  411. object must have been created with PAGE_READWRITE
  412. protection. The hFileMappingObject must have been created
  413. with FILE_MAP_WRITE access. A read/write view of the file will
  414. be mapped.
  415. FILE_MAP_READ - Read access is desired. The mapping object must
  416. have been created with PAGE_READWRITE or PAGE_READ
  417. protection. The hFileMappingObject must have been created
  418. with FILE_MAP_READ access. A read only view of the file
  419. will be mapped.
  420. dwFileOffsetHigh - Supplies the high order 32-bits of the file
  421. offset where mapping is to begin.
  422. dwFileOffsetLow - Supplies the low order 32-bits of the file offset
  423. where mapping is to begin. The combination of the high and low
  424. offsets must specify a 64Kb aligned offset within the file. It
  425. is an error if this is not the case.
  426. dwNumberOfBytesToMap - Supplies the number of bytes of the file to map.
  427. A value of zero specifies that the entire file is to be mapped.
  428. lpBaseAddress - Supplies the base address of where in the processes
  429. address space the mapping is to begin at. The address is
  430. rounded down to the nearest 64k boundry by the system. A value
  431. of NULL for this parameter operates exactly the same as
  432. MapViewOfFile... The system picks the mapping base address
  433. without any hint from the caller.
  434. Return Value:
  435. NON-NULL - Returns the address of where the file is mapped.
  436. NULL - The operation failed. Extended error status is available
  437. using GetLastError.
  438. --*/
  439. {
  440. NTSTATUS Status;
  441. LARGE_INTEGER SectionOffset;
  442. SIZE_T ViewSize;
  443. PVOID ViewBase;
  444. ULONG Protect;
  445. SectionOffset.LowPart = dwFileOffsetLow;
  446. SectionOffset.HighPart = dwFileOffsetHigh;
  447. ViewSize = dwNumberOfBytesToMap;
  448. ViewBase = lpBaseAddress;
  449. if ( dwDesiredAccess == FILE_MAP_COPY ) {
  450. Protect = PAGE_WRITECOPY;
  451. }
  452. else
  453. if ( dwDesiredAccess & FILE_MAP_WRITE ) {
  454. Protect = PAGE_READWRITE;
  455. }
  456. else if ( dwDesiredAccess & FILE_MAP_READ ) {
  457. Protect = PAGE_READONLY;
  458. }
  459. else {
  460. Protect = PAGE_NOACCESS;
  461. }
  462. Status = NtMapViewOfSection(
  463. hFileMappingObject,
  464. NtCurrentProcess(),
  465. &ViewBase,
  466. 0L,
  467. 0L,
  468. &SectionOffset,
  469. &ViewSize,
  470. ViewShare,
  471. 0L,
  472. Protect
  473. );
  474. if ( !NT_SUCCESS(Status) ) {
  475. BaseSetLastNTError(Status);
  476. return NULL;
  477. }
  478. return ViewBase;
  479. }
  480. BOOL
  481. APIENTRY
  482. FlushViewOfFile(
  483. LPCVOID lpBaseAddress,
  484. SIZE_T dwNumberOfBytesToFlush
  485. )
  486. /*++
  487. Routine Description:
  488. A byte range within a mapped view of a file can be flushed to disk
  489. using FlushViewOfFile.
  490. A byte range within a mapped view of a file can be flushed to disk
  491. using FlushViewOfFile.
  492. Flushing a range of a mapped view causes any dirty pages within that
  493. range to be written to disk. This operation automatically happens
  494. whenever a view is unmapped (either explicitly or as a result of
  495. process termination).
  496. Arguments:
  497. lpBaseAddress - Supplies the base address of a set of bytes that are
  498. to be flushed to the on disk representation of the mapped file.
  499. dwNumberOfBytesToFlush - Supplies the number of bytes to flush.
  500. Return Value:
  501. TRUE - The operation was successful. All dirty pages within the
  502. specified range are stored in the on-disk representation of the
  503. mapped file.
  504. FALSE - The operation failed. Extended error status is available
  505. using GetLastError.
  506. --*/
  507. {
  508. NTSTATUS Status;
  509. PVOID BaseAddress;
  510. SIZE_T RegionSize;
  511. IO_STATUS_BLOCK IoStatus;
  512. BaseAddress = (PVOID)lpBaseAddress;
  513. RegionSize = dwNumberOfBytesToFlush;
  514. Status = NtFlushVirtualMemory(
  515. NtCurrentProcess(),
  516. &BaseAddress,
  517. &RegionSize,
  518. &IoStatus
  519. );
  520. if ( !NT_SUCCESS(Status) ) {
  521. if ( Status == STATUS_NOT_MAPPED_DATA ) {
  522. return TRUE;
  523. }
  524. BaseSetLastNTError(Status);
  525. return FALSE;
  526. }
  527. return TRUE;
  528. }
  529. BOOL
  530. APIENTRY
  531. UnmapViewOfFile(
  532. LPCVOID lpBaseAddress
  533. )
  534. /*++
  535. Routine Description:
  536. A previously mapped view of a file may be unmapped from the callers
  537. address space using UnmapViewOfFile.
  538. Arguments:
  539. lpBaseAddress - Supplies the base address of a previously mapped
  540. view of a file that is to be unmapped. This value must be
  541. identical to the value returned by a previous call to
  542. MapViewOfFile.
  543. Return Value:
  544. TRUE - The operation was successful. All dirty pages within the
  545. specified range are stored in the on-disk representation of the
  546. mapped file.
  547. FALSE - The operation failed. Extended error status is available
  548. using GetLastError.
  549. --*/
  550. {
  551. NTSTATUS Status;
  552. Status = NtUnmapViewOfSection(NtCurrentProcess(),(PVOID)lpBaseAddress);
  553. if ( !NT_SUCCESS(Status) ) {
  554. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  555. //
  556. // Unlock any pages that were locked with MmSecureVirtualMemory.
  557. // This is useful for SANs.
  558. //
  559. if (RtlFlushSecureMemoryCache((PVOID)lpBaseAddress, 0)) {
  560. Status = NtUnmapViewOfSection(NtCurrentProcess(),
  561. (PVOID)lpBaseAddress
  562. );
  563. if (NT_SUCCESS( Status )) {
  564. return( TRUE );
  565. }
  566. }
  567. }
  568. BaseSetLastNTError(Status);
  569. return FALSE;
  570. }
  571. return TRUE;
  572. }