source: trunk/src/kernel32/hmmmap.cpp@ 22018

Last change on this file since 22018 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

File size: 10.9 KB
Line 
1/* $Id: hmmmap.cpp,v 1.24 2003-04-02 11:03:31 sandervl Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 * Win32 Unified Handle Manager for OS/2
6 * Copyright 1999 Patrick Haller (haller@zebra.fh-weingarten.de)
7 */
8
9#undef DEBUG_LOCAL
10//#define DEBUG_LOCAL
11
12
13/*****************************************************************************
14 * Remark *
15 *****************************************************************************
16
17 */
18
19
20/*****************************************************************************
21 * Includes *
22 *****************************************************************************/
23
24#include <os2win.h>
25#include <stdlib.h>
26#include <string.h>
27#include "unicode.h"
28#include "misc.h"
29
30#include "HandleManager.H"
31#include "HMMMap.h"
32#include "mmap.h"
33#include "heapshared.h"
34
35#define DBG_LOCALLOG DBG_hmmmap
36#include "dbglocal.h"
37
38/*****************************************************************************
39 * Defines *
40 *****************************************************************************/
41
42/*****************************************************************************
43 * Structures *
44 *****************************************************************************/
45
46/*****************************************************************************
47 * Local Prototypes *
48 *****************************************************************************/
49
50//******************************************************************************
51//******************************************************************************
52DWORD HMDeviceMemMapClass::CreateFileMapping(PHMHANDLEDATA pHMHandleData,
53 HANDLE hFile,
54 SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
55 DWORD protect, /* [in] Protection for mapping object */
56 DWORD size_high, /* [in] High-order 32 bits of object size */
57 DWORD size_low, /* [in] Low-order 32 bits of object size */
58 LPCSTR name) /* [in] Name of file-mapping object */
59{
60 Win32MemMap *map;
61
62 if((hFile == -1 && size_low == 0) || size_high ||
63 protect & ~(PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY|SEC_COMMIT|SEC_IMAGE|SEC_RESERVE|SEC_NOCACHE) ||
64 (protect & (PAGE_READONLY|PAGE_READWRITE|PAGE_WRITECOPY)) == 0 ||
65// (hFile == -1 && (protect & SEC_COMMIT)) ||
66 ((protect & SEC_COMMIT) && (protect & SEC_RESERVE)))
67 {
68
69 dprintf(("CreateFileMappingA: invalid parameter (combination)!"));
70 dprintf(("Parameters: %x %x %x %x %s", hFile, protect, size_high, size_low, name));
71 return ERROR_INVALID_PARAMETER;
72 }
73
74 //It's not allowed to map a file of length 0 according to MSDN. This time
75 //the docs are correct. (verified in NT4 SP6)
76 //bird: It's not allowed to create a non-file based mapping with size 0.
77 //TODO: also need to verify access rights of the file handle (write maps need
78 // write access obviously)
79 if(hFile != -1) {
80 DWORD dwFileSizeLow = 0, dwFileSizeHigh = 0;
81
82 dwFileSizeLow = ::GetFileSize(hFile, &dwFileSizeHigh);
83 if(dwFileSizeHigh == 0 && dwFileSizeLow == 0) {
84 /*
85 * Two actions, if we can grow the file we should if not fail.
86 */
87 if (!(protect & PAGE_READWRITE)) /* TODO: check this and verify flags */
88 {
89 dprintf(("CreateFileMappingA: not allowed to map a file with length 0!!"));
90 return ERROR_NOT_ENOUGH_MEMORY; /* XP returns this if the mapping is readonly, odd.. */
91 }
92 /*
93 * Try extend the file.
94 * (Not sure if we need to preserve the filepointer, but it doesn't hurt I think.)
95 */
96 LONG lFilePosHigh = 0;
97 DWORD dwFilePosLow = ::SetFilePointer(hFile, 0, &lFilePosHigh, FILE_CURRENT);
98 LONG lFileSizeHigh = size_high;
99 if ( ::SetFilePointer(hFile, size_low, &lFileSizeHigh, FILE_BEGIN) == INVALID_SET_FILE_POINTER
100 || !::SetEndOfFile(hFile))
101 {
102 ::SetFilePointer(hFile, dwFilePosLow, &lFilePosHigh, FILE_BEGIN);
103 dprintf(("CreateFileMappingA: unable to grow file to 0x%#08x%08x bytes.\n", size_high, size_low));
104 return ERROR_DISK_FULL;
105 }
106 ::SetFilePointer(hFile, dwFilePosLow, &lFilePosHigh, FILE_BEGIN);
107 }
108 }
109
110 map = Win32MemMap::findMap((LPSTR)name);
111 if(map != NULL) {
112 dprintf(("CreateFileMappingA: duplicating map %s!", name));
113
114 DWORD protflags = map->getProtFlags();
115 switch(protect) {
116 case FILE_MAP_WRITE:
117 if(!(protflags & PAGE_WRITECOPY))
118 dprintf(("Different flags for duplicate!"));
119 break;
120 case FILE_MAP_READ:
121 if(!(protflags & (PAGE_READWRITE | PAGE_READONLY)))
122 dprintf(("Different flags for duplicate!"));
123 break;
124 case FILE_MAP_COPY:
125 if(!(protflags & PAGE_WRITECOPY))
126 dprintf(("Different flags for duplicate!"));
127 break;
128 }
129 //TODO:
130 //Is it allowed to open an existing view with different flags?
131 //(i.e. write access to readonly object)
132 // -> for the same file handle, yes
133
134 //if map already exists, we must create a new handle to the existing
135 //map object and return ERROR_ALREADY_EXISTS
136 pHMHandleData->dwUserData = (ULONG)map;
137 pHMHandleData->dwInternalType = HMTYPE_MEMMAP;
138
139 //findMap already incremented the reference count, so we simply don't
140 //release it here
141 return ERROR_ALREADY_EXISTS;
142 }
143
144 //We reuse the original memory map object if another one is created for
145 //the same file handle
146 //TODO: different file handles can exist for the same file (DuplicateHandle)
147 map = Win32MemMap::findMapByFile(hFile);
148 if(map) {
149 Win32MemMapDup *dupmap;
150
151 dprintf(("CreateFileMappingA: duplicating map with file %x!", hFile));
152
153 dupmap = new Win32MemMapDup(map, hFile, size_low, protect, (LPSTR)name);
154
155 if(dupmap == NULL) {
156 dprintf(("CreateFileMappingA: can't create Win32MemMap object!"));
157 return ERROR_OUTOFMEMORY;
158 }
159 map->Release(); //findMapByFile increases the refcount, so decrease it here
160 map = dupmap;
161 }
162 else {
163 map = new Win32MemMap(hFile, size_low, protect, (LPSTR)name);
164
165 if(map == NULL) {
166 dprintf(("CreateFileMappingA: can't create Win32MemMap object!"));
167 return ERROR_OUTOFMEMORY;
168 }
169 }
170 if(map->Init(size_low) == FALSE) {
171 dprintf(("CreateFileMappingA: init failed!"));
172 delete map;
173 return ERROR_GEN_FAILURE;
174 }
175 pHMHandleData->dwUserData = (ULONG)map;
176 pHMHandleData->dwInternalType = HMTYPE_MEMMAP;
177 return NO_ERROR;
178}
179//******************************************************************************
180//******************************************************************************
181DWORD HMDeviceMemMapClass::OpenFileMapping(PHMHANDLEDATA pHMHandleData,
182 DWORD access, /* [in] Access mode */
183 BOOL inherit, /* [in] Inherit flag */
184 LPCSTR name ) /* [in] Name of file-mapping object */
185{
186 Win32MemMap *map;
187 DWORD protflags;
188 DWORD ret;
189
190 if(name == NULL)
191 return ERROR_INVALID_PARAMETER;
192
193 map = Win32MemMap::findMap((LPSTR)name);
194 if(map == NULL) {
195 dprintf(("OpenFileMapping: mapping %s not found", name));
196 return ERROR_FILE_NOT_FOUND;
197 }
198 protflags = map->getProtFlags();
199 switch(access) {
200 case FILE_MAP_WRITE:
201 case FILE_MAP_ALL_ACCESS:
202 if(!(protflags & (PAGE_WRITECOPY|PAGE_READWRITE))) {
203 ret = ERROR_INVALID_PARAMETER;
204 goto fail;
205 }
206 break;
207 case FILE_MAP_READ:
208 if(!(protflags & (PAGE_READWRITE | PAGE_READONLY))) {
209 ret = ERROR_INVALID_PARAMETER;
210 goto fail;
211 }
212 break;
213 case FILE_MAP_COPY:
214 if(!(protflags & PAGE_WRITECOPY)) {
215 ret = ERROR_INVALID_PARAMETER;
216 goto fail;
217 }
218 break;
219 }
220 //findMap already incremented the reference count, so we simply don't
221 //release it here
222 pHMHandleData->dwUserData = (ULONG)map;
223 pHMHandleData->dwInternalType = HMTYPE_MEMMAP;
224 return NO_ERROR;
225
226fail:
227 map->Release();
228 return ret;
229}
230//******************************************************************************
231//******************************************************************************
232LPVOID HMDeviceMemMapClass::MapViewOfFileEx(PHMHANDLEDATA pHMHandleData,
233 DWORD dwDesiredAccess,
234 DWORD dwFileOffsetHigh,
235 DWORD dwFileOffsetLow,
236 DWORD dwNumberOfBytesToMap,
237 LPVOID lpBaseAddress)
238{
239 Win32MemMap *map;
240
241 dprintf(("KERNEL32: HMDeviceMemMapClass::MapViewOfFileEx(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh)\n",
242 pHMHandleData->hHMHandle,
243 dwDesiredAccess,
244 dwFileOffsetHigh,
245 dwFileOffsetLow,
246 dwNumberOfBytesToMap,
247 lpBaseAddress));
248
249 if(lpBaseAddress != NULL)
250 {
251#if 0
252 //No can do. Let us choose the address
253 dprintf(("Can't create view to virtual address %x", lpBaseAddress));
254 SetLastError(ERROR_OUTOFMEMORY);
255 return NULL;
256#else
257 // PH 2000/05/24 IBM VAJ3 uses this function.
258 // I don't think we'll ever succeed in EXACTLY copying the original
259 // behaviour of the function. Maybe ignoring the base address helps?
260 dprintf(("WARNING: suggested virtual address %x IGNORED! (experimental API violation)",
261 lpBaseAddress));
262#endif
263 }
264
265 if(pHMHandleData->dwUserData == NULL || pHMHandleData->dwInternalType != HMTYPE_MEMMAP) {
266 dprintf(("MapViewOfFileEx: invalid handle data!"));
267 SetLastError(ERROR_INVALID_HANDLE);
268 return NULL;
269 }
270 map = (Win32MemMap *)pHMHandleData->dwUserData;
271
272 return map->mapViewOfFile(dwNumberOfBytesToMap, dwFileOffsetLow, dwDesiredAccess);
273}
274//******************************************************************************
275//******************************************************************************
276BOOL HMDeviceMemMapClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
277{
278 Win32MemMap *map;
279
280 dprintf(("HMDeviceMemMapClass::CloseHandle %x", pHMHandleData->dwUserData));
281 if(pHMHandleData->dwUserData == NULL || pHMHandleData->dwInternalType != HMTYPE_MEMMAP) {
282 dprintf(("HMDeviceMemMapClass::CloseHandle: invalid handle data!"));
283 return FALSE;
284 }
285 //Although an application may close the file handle used to create a file
286 //mapping object, the system keeps the corresponding file open until the last
287 //view of the file is unmapped.
288 map = (Win32MemMap *)pHMHandleData->dwUserData;
289 map->Release();
290
291 return TRUE;
292}
293//******************************************************************************
294//******************************************************************************
Note: See TracBrowser for help on using the repository browser.