2 * Win32 virtual memory functions
4 * Copyright 1997 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
28 #include <sys/types.h>
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
36 #define WIN32_NO_STATUS
42 #include "wine/exception.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(virtual);
47 WINE_DECLARE_DEBUG_CHANNEL(seh);
49 static unsigned int page_size;
51 /* filter for page-fault exceptions */
52 static WINE_EXCEPTION_FILTER(page_fault)
54 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
55 return EXCEPTION_EXECUTE_HANDLER;
56 return EXCEPTION_CONTINUE_SEARCH;
60 /***********************************************************************
61 * VirtualAlloc (KERNEL32.@)
62 * Reserves or commits a region of pages in virtual address space
65 * Base address of allocated region of pages
68 LPVOID WINAPI VirtualAlloc(
69 LPVOID addr, /* [in] Address of region to reserve or commit */
70 SIZE_T size, /* [in] Size of region */
71 DWORD type, /* [in] Type of allocation */
72 DWORD protect)/* [in] Type of access protection */
74 return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
78 /***********************************************************************
79 * VirtualAllocEx (KERNEL32.@)
81 * Seems to be just as VirtualAlloc, but with process handle.
84 * Base address of allocated region of pages
87 LPVOID WINAPI VirtualAllocEx(
88 HANDLE hProcess, /* [in] Handle of process to do mem operation */
89 LPVOID addr, /* [in] Address of region to reserve or commit */
90 SIZE_T size, /* [in] Size of region */
91 DWORD type, /* [in] Type of allocation */
92 DWORD protect ) /* [in] Type of access protection */
97 if ((status = NtAllocateVirtualMemory( hProcess, &ret, 0, &size, type, protect )))
99 SetLastError( RtlNtStatusToDosError(status) );
106 /***********************************************************************
107 * VirtualFree (KERNEL32.@)
108 * Release or decommits a region of pages in virtual address space.
114 BOOL WINAPI VirtualFree(
115 LPVOID addr, /* [in] Address of region of committed pages */
116 SIZE_T size, /* [in] Size of region */
117 DWORD type /* [in] Type of operation */
119 return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
123 /***********************************************************************
124 * VirtualFreeEx (KERNEL32.@)
125 * Release or decommits a region of pages in virtual address space.
131 BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type )
133 NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
134 if (status) SetLastError( RtlNtStatusToDosError(status) );
139 /***********************************************************************
140 * VirtualLock (KERNEL32.@)
141 * Locks the specified region of virtual address space
144 * Always returns TRUE
150 BOOL WINAPI VirtualLock( LPVOID addr, /* [in] Address of first byte of range to lock */
151 SIZE_T size ) /* [in] Number of bytes in range to lock */
153 NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
154 if (status) SetLastError( RtlNtStatusToDosError(status) );
159 /***********************************************************************
160 * VirtualUnlock (KERNEL32.@)
161 * Unlocks a range of pages in the virtual address space
164 * Always returns TRUE
170 BOOL WINAPI VirtualUnlock( LPVOID addr, /* [in] Address of first byte of range */
171 SIZE_T size ) /* [in] Number of bytes in range */
173 NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
174 if (status) SetLastError( RtlNtStatusToDosError(status) );
179 /***********************************************************************
180 * VirtualProtect (KERNEL32.@)
181 * Changes the access protection on a region of committed pages
187 BOOL WINAPI VirtualProtect(
188 LPVOID addr, /* [in] Address of region of committed pages */
189 SIZE_T size, /* [in] Size of region */
190 DWORD new_prot, /* [in] Desired access protection */
191 LPDWORD old_prot /* [out] Address of variable to get old protection */
193 return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
197 /***********************************************************************
198 * VirtualProtectEx (KERNEL32.@)
199 * Changes the access protection on a region of committed pages in the
200 * virtual address space of a specified process
206 BOOL WINAPI VirtualProtectEx(
207 HANDLE process, /* [in] Handle of process */
208 LPVOID addr, /* [in] Address of region of committed pages */
209 SIZE_T size, /* [in] Size of region */
210 DWORD new_prot, /* [in] Desired access protection */
211 LPDWORD old_prot /* [out] Address of variable to get old protection */ )
213 NTSTATUS status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
214 if (status) SetLastError( RtlNtStatusToDosError(status) );
219 /***********************************************************************
220 * VirtualQuery (KERNEL32.@)
221 * Provides info about a range of pages in virtual address space
224 * Number of bytes returned in information buffer
225 * or 0 if addr is >= 0xc0000000 (kernel space).
227 SIZE_T WINAPI VirtualQuery(
228 LPCVOID addr, /* [in] Address of region */
229 PMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
230 SIZE_T len /* [in] Size of buffer */
232 return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
236 /***********************************************************************
237 * VirtualQueryEx (KERNEL32.@)
238 * Provides info about a range of pages in virtual address space of a
242 * Number of bytes returned in information buffer
244 SIZE_T WINAPI VirtualQueryEx(
245 HANDLE process, /* [in] Handle of process */
246 LPCVOID addr, /* [in] Address of region */
247 PMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
248 SIZE_T len /* [in] Size of buffer */ )
253 if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
255 SetLastError( RtlNtStatusToDosError(status) );
262 /***********************************************************************
263 * CreateFileMappingA (KERNEL32.@)
264 * Creates a named or unnamed file-mapping object for the specified file
268 * 0: Mapping object does not exist
271 HANDLE WINAPI CreateFileMappingA(
272 HANDLE hFile, /* [in] Handle of file to map */
273 SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
274 DWORD protect, /* [in] Protection for mapping object */
275 DWORD size_high, /* [in] High-order 32 bits of object size */
276 DWORD size_low, /* [in] Low-order 32 bits of object size */
277 LPCSTR name /* [in] Name of file-mapping object */ )
279 WCHAR buffer[MAX_PATH];
281 if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
283 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
285 SetLastError( ERROR_FILENAME_EXCED_RANGE );
288 return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
292 /***********************************************************************
293 * CreateFileMappingW (KERNEL32.@)
294 * See CreateFileMappingA.
296 HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
297 DWORD protect, DWORD size_high,
298 DWORD size_low, LPCWSTR name )
300 static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;
303 OBJECT_ATTRIBUTES attr;
304 UNICODE_STRING nameW;
306 DWORD access, sec_type;
309 attr.Length = sizeof(attr);
310 attr.RootDirectory = 0;
311 attr.ObjectName = NULL;
312 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
313 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
314 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
315 attr.SecurityQualityOfService = NULL;
319 RtlInitUnicodeString( &nameW, name );
320 attr.ObjectName = &nameW;
323 sec_type = protect & sec_flags;
324 protect &= ~sec_flags;
325 if (!sec_type) sec_type = SEC_COMMIT;
330 protect = PAGE_READONLY; /* Win9x compatibility */
334 access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
337 access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE;
340 SetLastError( ERROR_INVALID_PARAMETER );
344 if (hFile == INVALID_HANDLE_VALUE)
347 if (!size_low && !size_high)
349 SetLastError( ERROR_INVALID_PARAMETER );
354 size.u.LowPart = size_low;
355 size.u.HighPart = size_high;
357 status = NtCreateSection( &ret, access, &attr, &size, protect, sec_type, hFile );
358 if (status == STATUS_OBJECT_NAME_EXISTS)
359 SetLastError( ERROR_ALREADY_EXISTS );
361 SetLastError( RtlNtStatusToDosError(status) );
366 /***********************************************************************
367 * OpenFileMappingA (KERNEL32.@)
368 * Opens a named file-mapping object.
374 HANDLE WINAPI OpenFileMappingA(
375 DWORD access, /* [in] Access mode */
376 BOOL inherit, /* [in] Inherit flag */
377 LPCSTR name ) /* [in] Name of file-mapping object */
379 WCHAR buffer[MAX_PATH];
381 if (!name) return OpenFileMappingW( access, inherit, NULL );
383 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
385 SetLastError( ERROR_FILENAME_EXCED_RANGE );
388 return OpenFileMappingW( access, inherit, buffer );
392 /***********************************************************************
393 * OpenFileMappingW (KERNEL32.@)
394 * See OpenFileMappingA.
396 HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
398 OBJECT_ATTRIBUTES attr;
399 UNICODE_STRING nameW;
405 SetLastError( ERROR_INVALID_PARAMETER );
408 attr.Length = sizeof(attr);
409 attr.RootDirectory = 0;
410 attr.ObjectName = &nameW;
411 attr.Attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
412 attr.SecurityDescriptor = NULL;
413 attr.SecurityQualityOfService = NULL;
414 RtlInitUnicodeString( &nameW, name );
416 if (access == FILE_MAP_COPY) access = FILE_MAP_READ;
418 if ((status = NtOpenSection( &ret, access, &attr )))
420 SetLastError( RtlNtStatusToDosError(status) );
427 /***********************************************************************
428 * MapViewOfFile (KERNEL32.@)
429 * Maps a view of a file into the address space
432 * Starting address of mapped view
435 LPVOID WINAPI MapViewOfFile(
436 HANDLE mapping, /* [in] File-mapping object to map */
437 DWORD access, /* [in] Access mode */
438 DWORD offset_high, /* [in] High-order 32 bits of file offset */
439 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
440 SIZE_T count /* [in] Number of bytes to map */
442 return MapViewOfFileEx( mapping, access, offset_high,
443 offset_low, count, NULL );
447 /***********************************************************************
448 * MapViewOfFileEx (KERNEL32.@)
449 * Maps a view of a file into the address space
452 * Starting address of mapped view
455 LPVOID WINAPI MapViewOfFileEx(
456 HANDLE handle, /* [in] File-mapping object to map */
457 DWORD access, /* [in] Access mode */
458 DWORD offset_high, /* [in] High-order 32 bits of file offset */
459 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
460 SIZE_T count, /* [in] Number of bytes to map */
461 LPVOID addr /* [in] Suggested starting address for mapped view */
464 LARGE_INTEGER offset;
467 offset.u.LowPart = offset_low;
468 offset.u.HighPart = offset_high;
470 if (access & FILE_MAP_WRITE) protect = PAGE_READWRITE;
471 else if (access & FILE_MAP_READ) protect = PAGE_READONLY;
472 else if (access & FILE_MAP_COPY) protect = PAGE_WRITECOPY;
473 else protect = PAGE_NOACCESS;
475 if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
476 &count, ViewShare, 0, protect )))
478 SetLastError( RtlNtStatusToDosError(status) );
485 /***********************************************************************
486 * UnmapViewOfFile (KERNEL32.@)
487 * Unmaps a mapped view of a file.
490 * Should addr be an LPCVOID?
496 BOOL WINAPI UnmapViewOfFile( LPVOID addr ) /* [in] Address where mapped view begins */
498 NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), addr );
499 if (status) SetLastError( RtlNtStatusToDosError(status) );
504 /***********************************************************************
505 * FlushViewOfFile (KERNEL32.@)
506 * Writes to the disk a byte range within a mapped view of a file
512 BOOL WINAPI FlushViewOfFile( LPCVOID base, /* [in] Start address of byte range to flush */
513 SIZE_T size ) /* [in] Number of bytes in range */
515 NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
518 if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
519 else SetLastError( RtlNtStatusToDosError(status) );
525 /***********************************************************************
526 * IsBadReadPtr (KERNEL32.@)
528 * Check for read access on a memory block.
531 * FALSE: Process has read access to entire block
534 BOOL WINAPI IsBadReadPtr(
535 LPCVOID ptr, /* [in] Address of memory block */
536 UINT size ) /* [in] Size of block */
538 if (!size) return FALSE; /* handle 0 size case w/o reference */
539 if (!ptr) return TRUE;
541 if (!page_size) page_size = getpagesize();
544 volatile const char *p = ptr;
548 while (count > page_size)
555 dummy = p[count - 1];
559 TRACE_(seh)("%p caused page fault during read\n", ptr);
567 /***********************************************************************
568 * IsBadWritePtr (KERNEL32.@)
570 * Check for write access on a memory block.
573 * FALSE: Process has write access to entire block
576 BOOL WINAPI IsBadWritePtr(
577 LPVOID ptr, /* [in] Address of memory block */
578 UINT size ) /* [in] Size of block in bytes */
580 if (!size) return FALSE; /* handle 0 size case w/o reference */
581 if (!ptr) return TRUE;
583 if (!page_size) page_size = getpagesize();
586 volatile char *p = ptr;
589 while (count > page_size)
600 TRACE_(seh)("%p caused page fault during write\n", ptr);
608 /***********************************************************************
609 * IsBadHugeReadPtr (KERNEL32.@)
611 * Check for read access on a memory block.
614 * FALSE: Process has read access to entire block
617 BOOL WINAPI IsBadHugeReadPtr(
618 LPCVOID ptr, /* [in] Address of memory block */
619 UINT size /* [in] Size of block */
621 return IsBadReadPtr( ptr, size );
625 /***********************************************************************
626 * IsBadHugeWritePtr (KERNEL32.@)
628 * Check for write access on a memory block.
631 * FALSE: Process has write access to entire block
634 BOOL WINAPI IsBadHugeWritePtr(
635 LPVOID ptr, /* [in] Address of memory block */
636 UINT size /* [in] Size of block */
638 return IsBadWritePtr( ptr, size );
642 /***********************************************************************
643 * IsBadCodePtr (KERNEL32.@)
645 * Check for read access on a memory address.
648 * FALSE: Process has read access to specified memory
651 BOOL WINAPI IsBadCodePtr( FARPROC ptr ) /* [in] Address of function */
653 return IsBadReadPtr( ptr, 1 );
657 /***********************************************************************
658 * IsBadStringPtrA (KERNEL32.@)
660 * Check for read access on a range of memory pointed to by a string pointer.
663 * FALSE: Read access to all bytes in string
666 BOOL WINAPI IsBadStringPtrA(
667 LPCSTR str, /* [in] Address of string */
668 UINT max ) /* [in] Maximum size of string */
670 if (!str) return TRUE;
674 volatile const char *p = str;
675 while (p != str + max) if (!*p++) break;
679 TRACE_(seh)("%p caused page fault during read\n", str);
687 /***********************************************************************
688 * IsBadStringPtrW (KERNEL32.@)
689 * See IsBadStringPtrA.
691 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT max )
693 if (!str) return TRUE;
697 volatile const WCHAR *p = str;
698 while (p != str + max) if (!*p++) break;
702 TRACE_(seh)("%p caused page fault during read\n", str);