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.

702 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. DesiredAccess = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
  144. AllocationAttributes = flProtect & (SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE);
  145. flProtect ^= AllocationAttributes;
  146. if (AllocationAttributes == 0) {
  147. AllocationAttributes = SEC_COMMIT;
  148. }
  149. if ( flProtect == PAGE_READWRITE ) {
  150. DesiredAccess |= (SECTION_MAP_READ | SECTION_MAP_WRITE);
  151. }
  152. else
  153. if ( flProtect != PAGE_READONLY && flProtect != PAGE_WRITECOPY ) {
  154. SetLastError(ERROR_INVALID_PARAMETER);
  155. return NULL;
  156. }
  157. if ( ARGUMENT_PRESENT(lpName) ) {
  158. RtlInitUnicodeString(&ObjectName,lpName);
  159. pObja = BaseFormatObjectAttributes(&Obja,lpFileMappingAttributes,&ObjectName);
  160. }
  161. else {
  162. pObja = BaseFormatObjectAttributes(&Obja,lpFileMappingAttributes,NULL);
  163. }
  164. if ( dwMaximumSizeLow || dwMaximumSizeHigh ) {
  165. SectionSize = &SectionSizeData;
  166. SectionSize->LowPart = dwMaximumSizeLow;
  167. SectionSize->HighPart = dwMaximumSizeHigh;
  168. }
  169. else {
  170. SectionSize = NULL;
  171. }
  172. if (hFile == INVALID_HANDLE_VALUE) {
  173. hFile = NULL;
  174. if ( !SectionSize ) {
  175. SetLastError(ERROR_INVALID_PARAMETER);
  176. return NULL;
  177. }
  178. }
  179. Status = NtCreateSection(
  180. &Section,
  181. DesiredAccess,
  182. pObja,
  183. SectionSize,
  184. flProtect,
  185. AllocationAttributes,
  186. hFile
  187. );
  188. if ( !NT_SUCCESS(Status) ) {
  189. BaseSetLastNTError(Status);
  190. return Section = NULL;
  191. }
  192. else {
  193. if ( Status == STATUS_OBJECT_NAME_EXISTS ) {
  194. SetLastError(ERROR_ALREADY_EXISTS);
  195. }
  196. else {
  197. SetLastError(0);
  198. }
  199. }
  200. return Section;
  201. }
  202. HANDLE
  203. APIENTRY
  204. OpenFileMappingA(
  205. DWORD dwDesiredAccess,
  206. BOOL bInheritHandle,
  207. LPCSTR lpName
  208. )
  209. /*++
  210. Routine Description:
  211. ANSI thunk to OpenFileMappingW
  212. --*/
  213. {
  214. PUNICODE_STRING Unicode;
  215. ANSI_STRING AnsiString;
  216. NTSTATUS Status;
  217. if ( ARGUMENT_PRESENT(lpName) ) {
  218. Unicode = &NtCurrentTeb()->StaticUnicodeString;
  219. RtlInitAnsiString(&AnsiString,lpName);
  220. Status = RtlAnsiStringToUnicodeString(Unicode,&AnsiString,FALSE);
  221. if ( !NT_SUCCESS(Status) ) {
  222. if ( Status == STATUS_BUFFER_OVERFLOW ) {
  223. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  224. }
  225. else {
  226. BaseSetLastNTError(Status);
  227. }
  228. return NULL;
  229. }
  230. }
  231. else {
  232. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  233. return NULL;
  234. }
  235. return OpenFileMappingW(
  236. dwDesiredAccess,
  237. bInheritHandle,
  238. (LPCWSTR)Unicode->Buffer
  239. );
  240. }
  241. HANDLE
  242. APIENTRY
  243. OpenFileMappingW(
  244. DWORD dwDesiredAccess,
  245. BOOL bInheritHandle,
  246. LPCWSTR lpName
  247. )
  248. {
  249. OBJECT_ATTRIBUTES Obja;
  250. UNICODE_STRING ObjectName;
  251. NTSTATUS Status;
  252. HANDLE Object;
  253. if ( !lpName ) {
  254. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  255. return NULL;
  256. }
  257. RtlInitUnicodeString(&ObjectName,lpName);
  258. InitializeObjectAttributes(
  259. &Obja,
  260. &ObjectName,
  261. (bInheritHandle ? OBJ_INHERIT : 0),
  262. BaseGetNamedObjectDirectory(),
  263. NULL
  264. );
  265. if ( dwDesiredAccess == FILE_MAP_COPY ) {
  266. dwDesiredAccess = FILE_MAP_READ;
  267. }
  268. Status = NtOpenSection(
  269. &Object,
  270. dwDesiredAccess,
  271. &Obja
  272. );
  273. if ( !NT_SUCCESS(Status) ) {
  274. BaseSetLastNTError(Status);
  275. return NULL;
  276. }
  277. return Object;
  278. }
  279. LPVOID
  280. APIENTRY
  281. MapViewOfFile(
  282. HANDLE hFileMappingObject,
  283. DWORD dwDesiredAccess,
  284. DWORD dwFileOffsetHigh,
  285. DWORD dwFileOffsetLow,
  286. SIZE_T dwNumberOfBytesToMap
  287. )
  288. /*++
  289. Routine Description:
  290. A view of a file may be mapped into the address space of the calling
  291. process using MapViewOfFile.
  292. Mapping a file object makes the specified portion of the file
  293. visible in the address space of the calling process. The return
  294. address is a pointer to memory that when addressed causes data
  295. within the file to be accessed.
  296. Mapping a view of a file has some simple coherency rules:
  297. - Multiple views on a file are coherent if they are derived from
  298. the same file mapping object. If a process opens a file,
  299. creates a mapping object, duplicates the object to another
  300. process... If both processes map a view of the file, they will
  301. both see a coherent view of the file's data... they will
  302. effectively be viewing shared memory backed by the file.
  303. - If multiple mapping objects exist for the same file, then views
  304. derived from the different mapping objects are not garunteed to
  305. be coherent.
  306. - A mapped view on a file is not garunteed to be coherent with a
  307. file being accessed via ReadFile or WriteFile.
  308. Arguments:
  309. hFileMappingObject - Supplies an open handle to a file mapping object
  310. that is to be mapped into the callers address space.
  311. dwDesiredAccess - Specifies the access that is requested to the file
  312. mapping object. This determines the page protection of the pages
  313. mapped by the file.
  314. dwDesiredAccess Values:
  315. FILE_MAP_WRITE - Read/write access is desired. The mapping
  316. object must have been created with PAGE_READWRITE
  317. protection. The hFileMappingObject must have been created
  318. with FILE_MAP_WRITE access. A read/write view of the file will
  319. be mapped.
  320. FILE_MAP_READ - Read access is desired. The mapping object must
  321. have been created with PAGE_READWRITE or PAGE_READ
  322. protection. The hFileMappingObject must have been created
  323. with FILE_MAP_READ access. A read only view of the file
  324. will be mapped.
  325. dwFileOffsetHigh - Supplies the high order 32-bits of the file
  326. offset where mapping is to begin.
  327. dwFileOffsetLow - Supplies the low order 32-bits of the file offset
  328. where mapping is to begin. The combination of the high and low
  329. offsets must specify a 64Kb aligned offset within the file. It
  330. is an error if this is not the case.
  331. dwNumberOfBytesToMap - Supplies the number of bytes of the file to map.
  332. A value of zero specifies that the entire file is to be mapped.
  333. Return Value:
  334. NON-NULL - Returns the address of where the file is mapped.
  335. NULL - The operation failed. Extended error status is available
  336. using GetLastError.
  337. --*/
  338. {
  339. return MapViewOfFileEx(
  340. hFileMappingObject,
  341. dwDesiredAccess,
  342. dwFileOffsetHigh,
  343. dwFileOffsetLow,
  344. dwNumberOfBytesToMap,
  345. NULL
  346. );
  347. }
  348. LPVOID
  349. APIENTRY
  350. MapViewOfFileEx(
  351. HANDLE hFileMappingObject,
  352. DWORD dwDesiredAccess,
  353. DWORD dwFileOffsetHigh,
  354. DWORD dwFileOffsetLow,
  355. SIZE_T dwNumberOfBytesToMap,
  356. LPVOID lpBaseAddress
  357. )
  358. /*++
  359. Routine Description:
  360. A view of a file may be mapped into the address space of the calling
  361. process using MapViewOfFileEx.
  362. Mapping a file object makes the specified portion of the file
  363. visible in the address space of the calling process. The return
  364. address is a pointer to memory that when addressed causes data
  365. within the file to be accessed. This API allows the caller to
  366. supply the system with a suggested mapping address. The system
  367. will round this address down to the nearest 64k boundry and attempt
  368. to map the file at thet address. If there is not enough address space
  369. at that address, this call will fail.
  370. Mapping a view of a file has some simple coherency rules:
  371. - Multiple views on a file are coherent if they are derived from
  372. the same file mapping object. If a process opens a file,
  373. creates a mapping object, duplicates the object to another
  374. process... If both processes map a view of the file, they will
  375. both see a coherent view of the file's data... they will
  376. effectively be viewing shared memory backed by the file.
  377. - If multiple mapping objects exist for the same file, then views
  378. derived from the different mapping objects are not garunteed to
  379. be coherent.
  380. - A mapped view on a file is not garunteed to be coherent with a
  381. file being accessed via ReadFile or WriteFile.
  382. Arguments:
  383. hFileMappingObject - Supplies an open handle to a file mapping object
  384. that is to be mapped into the callers address space.
  385. dwDesiredAccess - Specifies the access that is requested to the file
  386. mapping object. This determines the page protection of the pages
  387. mapped by the file.
  388. dwDesiredAccess Values:
  389. FILE_MAP_WRITE - Read/write access is desired. The mapping
  390. object must have been created with PAGE_READWRITE
  391. protection. The hFileMappingObject must have been created
  392. with FILE_MAP_WRITE access. A read/write view of the file will
  393. be mapped.
  394. FILE_MAP_READ - Read access is desired. The mapping object must
  395. have been created with PAGE_READWRITE or PAGE_READ
  396. protection. The hFileMappingObject must have been created
  397. with FILE_MAP_READ access. A read only view of the file
  398. will be mapped.
  399. dwFileOffsetHigh - Supplies the high order 32-bits of the file
  400. offset where mapping is to begin.
  401. dwFileOffsetLow - Supplies the low order 32-bits of the file offset
  402. where mapping is to begin. The combination of the high and low
  403. offsets must specify a 64Kb aligned offset within the file. It
  404. is an error if this is not the case.
  405. dwNumberOfBytesToMap - Supplies the number of bytes of the file to map.
  406. A value of zero specifies that the entire file is to be mapped.
  407. lpBaseAddress - Supplies the base address of where in the processes
  408. address space the mapping is to begin at. The address is
  409. rounded down to the nearest 64k boundry by the system. A value
  410. of NULL for this parameter operates exactly the same as
  411. MapViewOfFile... The system picks the mapping base address
  412. without any hint from the caller.
  413. Return Value:
  414. NON-NULL - Returns the address of where the file is mapped.
  415. NULL - The operation failed. Extended error status is available
  416. using GetLastError.
  417. --*/
  418. {
  419. NTSTATUS Status;
  420. LARGE_INTEGER SectionOffset;
  421. SIZE_T ViewSize;
  422. PVOID ViewBase;
  423. ULONG Protect;
  424. SectionOffset.LowPart = dwFileOffsetLow;
  425. SectionOffset.HighPart = dwFileOffsetHigh;
  426. ViewSize = dwNumberOfBytesToMap;
  427. ViewBase = lpBaseAddress;
  428. if ( dwDesiredAccess == FILE_MAP_COPY ) {
  429. Protect = PAGE_WRITECOPY;
  430. }
  431. else
  432. if ( dwDesiredAccess & FILE_MAP_WRITE ) {
  433. Protect = PAGE_READWRITE;
  434. }
  435. else if ( dwDesiredAccess & FILE_MAP_READ ) {
  436. Protect = PAGE_READONLY;
  437. }
  438. else {
  439. Protect = PAGE_NOACCESS;
  440. }
  441. Status = NtMapViewOfSection(
  442. hFileMappingObject,
  443. NtCurrentProcess(),
  444. &ViewBase,
  445. 0L,
  446. 0L,
  447. &SectionOffset,
  448. &ViewSize,
  449. ViewShare,
  450. 0L,
  451. Protect
  452. );
  453. if ( !NT_SUCCESS(Status) ) {
  454. BaseSetLastNTError(Status);
  455. return NULL;
  456. }
  457. return ViewBase;
  458. }
  459. BOOL
  460. APIENTRY
  461. FlushViewOfFile(
  462. LPCVOID lpBaseAddress,
  463. SIZE_T dwNumberOfBytesToFlush
  464. )
  465. /*++
  466. Routine Description:
  467. A byte range within a mapped view of a file can be flushed to disk
  468. using FlushViewOfFile.
  469. A byte range within a mapped view of a file can be flushed to disk
  470. using FlushViewOfFile.
  471. Flushing a range of a mapped view causes any dirty pages within that
  472. range to be written to disk. This operation automatically happens
  473. whenever a view is unmapped (either explicitly or as a result of
  474. process termination).
  475. Arguments:
  476. lpBaseAddress - Supplies the base address of a set of bytes that are
  477. to be flushed to the on disk representation of the mapped file.
  478. dwNumberOfBytesToFlush - Supplies the number of bytes to flush.
  479. Return Value:
  480. TRUE - The operation was successful. All dirty pages within the
  481. specified range are stored in the on-disk representation of the
  482. mapped file.
  483. FALSE - The operation failed. Extended error status is available
  484. using GetLastError.
  485. --*/
  486. {
  487. NTSTATUS Status;
  488. PVOID BaseAddress;
  489. SIZE_T RegionSize;
  490. IO_STATUS_BLOCK IoStatus;
  491. BaseAddress = (PVOID)lpBaseAddress;
  492. RegionSize = dwNumberOfBytesToFlush;
  493. Status = NtFlushVirtualMemory(
  494. NtCurrentProcess(),
  495. &BaseAddress,
  496. &RegionSize,
  497. &IoStatus
  498. );
  499. if ( !NT_SUCCESS(Status) ) {
  500. if ( Status == STATUS_NOT_MAPPED_DATA ) {
  501. return TRUE;
  502. }
  503. BaseSetLastNTError(Status);
  504. return FALSE;
  505. }
  506. return TRUE;
  507. }
  508. BOOL
  509. APIENTRY
  510. UnmapViewOfFile(
  511. LPCVOID lpBaseAddress
  512. )
  513. /*++
  514. Routine Description:
  515. A previously mapped view of a file may be unmapped from the callers
  516. address space using UnmapViewOfFile.
  517. Arguments:
  518. lpBaseAddress - Supplies the base address of a previously mapped
  519. view of a file that is to be unmapped. This value must be
  520. identical to the value returned by a previous call to
  521. MapViewOfFile.
  522. Return Value:
  523. TRUE - The operation was successful. All dirty pages within the
  524. specified range are stored in the on-disk representation of the
  525. mapped file.
  526. FALSE - The operation failed. Extended error status is available
  527. using GetLastError.
  528. --*/
  529. {
  530. NTSTATUS Status;
  531. Status = NtUnmapViewOfSection(NtCurrentProcess(),(PVOID)lpBaseAddress);
  532. if ( !NT_SUCCESS(Status) ) {
  533. if (Status == STATUS_INVALID_PAGE_PROTECTION) {
  534. //
  535. // Unlock any pages that were locked with MmSecureVirtualMemory.
  536. // This is useful for SANs.
  537. //
  538. if (RtlFlushSecureMemoryCache((PVOID)lpBaseAddress, 0)) {
  539. Status = NtUnmapViewOfSection(NtCurrentProcess(),
  540. (PVOID)lpBaseAddress
  541. );
  542. if (NT_SUCCESS( Status )) {
  543. return( TRUE );
  544. }
  545. }
  546. }
  547. BaseSetLastNTError(Status);
  548. return FALSE;
  549. }
  550. return TRUE;
  551. }