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 #include "kernel_private.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(virtual);
49 WINE_DECLARE_DEBUG_CHANNEL(seh);
51 static unsigned int page_size;
53 /* filter for page-fault exceptions */
54 static WINE_EXCEPTION_FILTER(page_fault)
56 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
57 return EXCEPTION_EXECUTE_HANDLER;
58 return EXCEPTION_CONTINUE_SEARCH;
62 /***********************************************************************
63 * VirtualAlloc (KERNEL32.@)
64 * Reserves or commits a region of pages in virtual address space
67 * Base address of allocated region of pages
70 LPVOID WINAPI VirtualAlloc(
71 LPVOID addr, /* [in] Address of region to reserve or commit */
72 SIZE_T size, /* [in] Size of region */
73 DWORD type, /* [in] Type of allocation */
74 DWORD protect)/* [in] Type of access protection */
76 return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
80 /***********************************************************************
81 * VirtualAllocEx (KERNEL32.@)
83 * Seems to be just as VirtualAlloc, but with process handle.
86 * Base address of allocated region of pages
89 LPVOID WINAPI VirtualAllocEx(
90 HANDLE hProcess, /* [in] Handle of process to do mem operation */
91 LPVOID addr, /* [in] Address of region to reserve or commit */
92 SIZE_T size, /* [in] Size of region */
93 DWORD type, /* [in] Type of allocation */
94 DWORD protect ) /* [in] Type of access protection */
99 if ((status = NtAllocateVirtualMemory( hProcess, &ret, 0, &size, type, protect )))
101 SetLastError( RtlNtStatusToDosError(status) );
108 /***********************************************************************
109 * VirtualFree (KERNEL32.@)
110 * Release or decommits a region of pages in virtual address space.
116 BOOL WINAPI VirtualFree(
117 LPVOID addr, /* [in] Address of region of committed pages */
118 SIZE_T size, /* [in] Size of region */
119 DWORD type /* [in] Type of operation */
121 return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
125 /***********************************************************************
126 * VirtualFreeEx (KERNEL32.@)
127 * Release or decommits a region of pages in virtual address space.
133 BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type )
135 NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
136 if (status) SetLastError( RtlNtStatusToDosError(status) );
141 /***********************************************************************
142 * VirtualLock (KERNEL32.@)
143 * Locks the specified region of virtual address space
146 * Always returns TRUE
152 BOOL WINAPI VirtualLock( LPVOID addr, /* [in] Address of first byte of range to lock */
153 SIZE_T size ) /* [in] Number of bytes in range to lock */
155 NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
156 if (status) SetLastError( RtlNtStatusToDosError(status) );
161 /***********************************************************************
162 * VirtualUnlock (KERNEL32.@)
163 * Unlocks a range of pages in the virtual address space
166 * Always returns TRUE
172 BOOL WINAPI VirtualUnlock( LPVOID addr, /* [in] Address of first byte of range */
173 SIZE_T size ) /* [in] Number of bytes in range */
175 NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
176 if (status) SetLastError( RtlNtStatusToDosError(status) );
181 /***********************************************************************
182 * VirtualProtect (KERNEL32.@)
183 * Changes the access protection on a region of committed pages
189 BOOL WINAPI VirtualProtect(
190 LPVOID addr, /* [in] Address of region of committed pages */
191 SIZE_T size, /* [in] Size of region */
192 DWORD new_prot, /* [in] Desired access protection */
193 LPDWORD old_prot /* [out] Address of variable to get old protection */
195 return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
199 /***********************************************************************
200 * VirtualProtectEx (KERNEL32.@)
201 * Changes the access protection on a region of committed pages in the
202 * virtual address space of a specified process
208 BOOL WINAPI VirtualProtectEx(
209 HANDLE process, /* [in] Handle of process */
210 LPVOID addr, /* [in] Address of region of committed pages */
211 SIZE_T size, /* [in] Size of region */
212 DWORD new_prot, /* [in] Desired access protection */
213 LPDWORD old_prot /* [out] Address of variable to get old protection */ )
215 NTSTATUS status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
216 if (status) SetLastError( RtlNtStatusToDosError(status) );
221 /***********************************************************************
222 * VirtualQuery (KERNEL32.@)
223 * Provides info about a range of pages in virtual address space
226 * Number of bytes returned in information buffer
227 * or 0 if addr is >= 0xc0000000 (kernel space).
229 SIZE_T WINAPI VirtualQuery(
230 LPCVOID addr, /* [in] Address of region */
231 PMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
232 SIZE_T len /* [in] Size of buffer */
234 return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
238 /***********************************************************************
239 * VirtualQueryEx (KERNEL32.@)
240 * Provides info about a range of pages in virtual address space of a
244 * Number of bytes returned in information buffer
246 SIZE_T WINAPI VirtualQueryEx(
247 HANDLE process, /* [in] Handle of process */
248 LPCVOID addr, /* [in] Address of region */
249 PMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
250 SIZE_T len /* [in] Size of buffer */ )
255 if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
257 SetLastError( RtlNtStatusToDosError(status) );
264 /***********************************************************************
265 * CreateFileMappingA (KERNEL32.@)
266 * Creates a named or unnamed file-mapping object for the specified file
270 * 0: Mapping object does not exist
273 HANDLE WINAPI CreateFileMappingA(
274 HANDLE hFile, /* [in] Handle of file to map */
275 SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
276 DWORD protect, /* [in] Protection for mapping object */
277 DWORD size_high, /* [in] High-order 32 bits of object size */
278 DWORD size_low, /* [in] Low-order 32 bits of object size */
279 LPCSTR name /* [in] Name of file-mapping object */ )
281 WCHAR buffer[MAX_PATH];
283 if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
285 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
287 SetLastError( ERROR_FILENAME_EXCED_RANGE );
290 return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
294 /***********************************************************************
295 * CreateFileMappingW (KERNEL32.@)
296 * See CreateFileMappingA.
298 HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
299 DWORD protect, DWORD size_high,
300 DWORD size_low, LPCWSTR name )
302 static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;
305 OBJECT_ATTRIBUTES attr;
306 UNICODE_STRING nameW;
308 DWORD access, sec_type;
311 attr.Length = sizeof(attr);
312 attr.RootDirectory = 0;
313 attr.ObjectName = NULL;
314 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
315 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
316 attr.SecurityDescriptor = sa ? sa->lpSecurityDescriptor : NULL;
317 attr.SecurityQualityOfService = NULL;
321 RtlInitUnicodeString( &nameW, name );
322 attr.ObjectName = &nameW;
323 attr.RootDirectory = get_BaseNamedObjects_handle();
326 sec_type = protect & sec_flags;
327 protect &= ~sec_flags;
328 if (!sec_type) sec_type = SEC_COMMIT;
333 protect = PAGE_READONLY; /* Win9x compatibility */
337 access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
340 access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE;
343 SetLastError( ERROR_INVALID_PARAMETER );
347 if (hFile == INVALID_HANDLE_VALUE)
350 if (!size_low && !size_high)
352 SetLastError( ERROR_INVALID_PARAMETER );
357 size.u.LowPart = size_low;
358 size.u.HighPart = size_high;
360 status = NtCreateSection( &ret, access, &attr, &size, protect, sec_type, hFile );
361 if (status == STATUS_OBJECT_NAME_EXISTS)
362 SetLastError( ERROR_ALREADY_EXISTS );
364 SetLastError( RtlNtStatusToDosError(status) );
369 /***********************************************************************
370 * OpenFileMappingA (KERNEL32.@)
371 * Opens a named file-mapping object.
377 HANDLE WINAPI OpenFileMappingA(
378 DWORD access, /* [in] Access mode */
379 BOOL inherit, /* [in] Inherit flag */
380 LPCSTR name ) /* [in] Name of file-mapping object */
382 WCHAR buffer[MAX_PATH];
384 if (!name) return OpenFileMappingW( access, inherit, NULL );
386 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
388 SetLastError( ERROR_FILENAME_EXCED_RANGE );
391 return OpenFileMappingW( access, inherit, buffer );
395 /***********************************************************************
396 * OpenFileMappingW (KERNEL32.@)
397 * See OpenFileMappingA.
399 HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
401 OBJECT_ATTRIBUTES attr;
402 UNICODE_STRING nameW;
408 SetLastError( ERROR_INVALID_PARAMETER );
411 attr.Length = sizeof(attr);
412 attr.RootDirectory = get_BaseNamedObjects_handle();
413 attr.ObjectName = &nameW;
414 attr.Attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
415 attr.SecurityDescriptor = NULL;
416 attr.SecurityQualityOfService = NULL;
417 RtlInitUnicodeString( &nameW, name );
419 if (access == FILE_MAP_COPY) access = FILE_MAP_READ;
421 if ((status = NtOpenSection( &ret, access, &attr )))
423 SetLastError( RtlNtStatusToDosError(status) );
430 /***********************************************************************
431 * MapViewOfFile (KERNEL32.@)
432 * Maps a view of a file into the address space
435 * Starting address of mapped view
438 LPVOID WINAPI MapViewOfFile(
439 HANDLE mapping, /* [in] File-mapping object to map */
440 DWORD access, /* [in] Access mode */
441 DWORD offset_high, /* [in] High-order 32 bits of file offset */
442 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
443 SIZE_T count /* [in] Number of bytes to map */
445 return MapViewOfFileEx( mapping, access, offset_high,
446 offset_low, count, NULL );
450 /***********************************************************************
451 * MapViewOfFileEx (KERNEL32.@)
452 * Maps a view of a file into the address space
455 * Starting address of mapped view
458 LPVOID WINAPI MapViewOfFileEx(
459 HANDLE handle, /* [in] File-mapping object to map */
460 DWORD access, /* [in] Access mode */
461 DWORD offset_high, /* [in] High-order 32 bits of file offset */
462 DWORD offset_low, /* [in] Low-order 32 bits of file offset */
463 SIZE_T count, /* [in] Number of bytes to map */
464 LPVOID addr /* [in] Suggested starting address for mapped view */
467 LARGE_INTEGER offset;
470 offset.u.LowPart = offset_low;
471 offset.u.HighPart = offset_high;
473 if (access & FILE_MAP_WRITE) protect = PAGE_READWRITE;
474 else if (access & FILE_MAP_READ) protect = PAGE_READONLY;
475 else if (access & FILE_MAP_COPY) protect = PAGE_WRITECOPY;
476 else protect = PAGE_NOACCESS;
478 if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
479 &count, ViewShare, 0, protect )))
481 SetLastError( RtlNtStatusToDosError(status) );
488 /***********************************************************************
489 * UnmapViewOfFile (KERNEL32.@)
490 * Unmaps a mapped view of a file.
493 * Should addr be an LPCVOID?
499 BOOL WINAPI UnmapViewOfFile( LPVOID addr ) /* [in] Address where mapped view begins */
501 NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), addr );
502 if (status) SetLastError( RtlNtStatusToDosError(status) );
507 /***********************************************************************
508 * FlushViewOfFile (KERNEL32.@)
509 * Writes to the disk a byte range within a mapped view of a file
515 BOOL WINAPI FlushViewOfFile( LPCVOID base, /* [in] Start address of byte range to flush */
516 SIZE_T size ) /* [in] Number of bytes in range */
518 NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
521 if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
522 else SetLastError( RtlNtStatusToDosError(status) );
528 /***********************************************************************
529 * IsBadReadPtr (KERNEL32.@)
531 * Check for read access on a memory block.
534 * FALSE: Process has read access to entire block
537 BOOL WINAPI IsBadReadPtr(
538 LPCVOID ptr, /* [in] Address of memory block */
539 UINT size ) /* [in] Size of block */
541 if (!size) return FALSE; /* handle 0 size case w/o reference */
542 if (!ptr) return TRUE;
544 if (!page_size) page_size = getpagesize();
547 volatile const char *p = ptr;
551 while (count > page_size)
558 dummy = p[count - 1];
562 TRACE_(seh)("%p caused page fault during read\n", ptr);
570 /***********************************************************************
571 * IsBadWritePtr (KERNEL32.@)
573 * Check for write access on a memory block.
576 * FALSE: Process has write access to entire block
579 BOOL WINAPI IsBadWritePtr(
580 LPVOID ptr, /* [in] Address of memory block */
581 UINT size ) /* [in] Size of block in bytes */
583 if (!size) return FALSE; /* handle 0 size case w/o reference */
584 if (!ptr) return TRUE;
586 if (!page_size) page_size = getpagesize();
589 volatile char *p = ptr;
592 while (count > page_size)
603 TRACE_(seh)("%p caused page fault during write\n", ptr);
611 /***********************************************************************
612 * IsBadHugeReadPtr (KERNEL32.@)
614 * Check for read access on a memory block.
617 * FALSE: Process has read access to entire block
620 BOOL WINAPI IsBadHugeReadPtr(
621 LPCVOID ptr, /* [in] Address of memory block */
622 UINT size /* [in] Size of block */
624 return IsBadReadPtr( ptr, size );
628 /***********************************************************************
629 * IsBadHugeWritePtr (KERNEL32.@)
631 * Check for write access on a memory block.
634 * FALSE: Process has write access to entire block
637 BOOL WINAPI IsBadHugeWritePtr(
638 LPVOID ptr, /* [in] Address of memory block */
639 UINT size /* [in] Size of block */
641 return IsBadWritePtr( ptr, size );
645 /***********************************************************************
646 * IsBadCodePtr (KERNEL32.@)
648 * Check for read access on a memory address.
651 * FALSE: Process has read access to specified memory
654 BOOL WINAPI IsBadCodePtr( FARPROC ptr ) /* [in] Address of function */
656 return IsBadReadPtr( ptr, 1 );
660 /***********************************************************************
661 * IsBadStringPtrA (KERNEL32.@)
663 * Check for read access on a range of memory pointed to by a string pointer.
666 * FALSE: Read access to all bytes in string
669 BOOL WINAPI IsBadStringPtrA(
670 LPCSTR str, /* [in] Address of string */
671 UINT max ) /* [in] Maximum size of string */
673 if (!str) return TRUE;
677 volatile const char *p = str;
678 while (p != str + max) if (!*p++) break;
682 TRACE_(seh)("%p caused page fault during read\n", str);
690 /***********************************************************************
691 * IsBadStringPtrW (KERNEL32.@)
692 * See IsBadStringPtrA.
694 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT max )
696 if (!str) return TRUE;
700 volatile const WCHAR *p = str;
701 while (p != str + max) if (!*p++) break;
705 TRACE_(seh)("%p caused page fault during read\n", str);