ntdll: Use syscall thunks for virtual memory functions.
[wine.git] / dlls / kernel32 / virtual.c
blob97581a5db109a5a558e82d9734bb295b53f0a9da
1 /*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
33 #define WINE_NO_INLINE_STRING
34 #include "ntstatus.h"
35 #define WIN32_NO_STATUS
36 #define NONAMELESSUNION
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winnls.h"
40 #include "winternl.h"
41 #include "winerror.h"
42 #include "psapi.h"
43 #include "wine/exception.h"
44 #include "wine/unicode.h"
45 #include "wine/debug.h"
47 #include "kernel_private.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(seh);
52 static LONG WINAPI badptr_handler( EXCEPTION_POINTERS *eptr )
54 EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
56 if (rec->ExceptionCode == STATUS_ACCESS_VIOLATION) return EXCEPTION_EXECUTE_HANDLER;
57 if (rec->ExceptionCode == STATUS_STACK_OVERFLOW)
59 /* restore stack guard page */
60 void *addr = (char *)NtCurrentTeb()->DeallocationStack + system_info.PageSize;
61 SIZE_T size = (char *)rec - (char *)addr;
62 ULONG old_prot;
63 NtProtectVirtualMemory( GetCurrentProcess(), &addr, &size, PAGE_GUARD|PAGE_READWRITE, &old_prot );
64 return EXCEPTION_EXECUTE_HANDLER;
66 return EXCEPTION_CONTINUE_SEARCH;
69 /***********************************************************************
70 * IsBadReadPtr (KERNEL32.@)
72 * Check for read access on a memory block.
74 * ptr [I] Address of memory block.
75 * size [I] Size of block.
77 * RETURNS
78 * Success: TRUE.
79 * Failure: FALSE. Process has read access to entire block.
81 BOOL WINAPI IsBadReadPtr( LPCVOID ptr, UINT_PTR size )
83 if (!size) return FALSE; /* handle 0 size case w/o reference */
84 if (!ptr) return TRUE;
85 __TRY
87 volatile const char *p = ptr;
88 char dummy __attribute__((unused));
89 UINT_PTR count = size;
91 while (count > system_info.PageSize)
93 dummy = *p;
94 p += system_info.PageSize;
95 count -= system_info.PageSize;
97 dummy = p[0];
98 dummy = p[count - 1];
100 __EXCEPT( badptr_handler )
102 TRACE("%p caused page fault during read\n", ptr);
103 return TRUE;
105 __ENDTRY
106 return FALSE;
110 /***********************************************************************
111 * IsBadWritePtr (KERNEL32.@)
113 * Check for write access on a memory block.
115 * PARAMS
116 * ptr [I] Address of memory block.
117 * size [I] Size of block in bytes.
119 * RETURNS
120 * Success: TRUE.
121 * Failure: FALSE. Process has write access to entire block.
123 BOOL WINAPI IsBadWritePtr( LPVOID ptr, UINT_PTR size )
125 if (!size) return FALSE; /* handle 0 size case w/o reference */
126 if (!ptr) return TRUE;
127 __TRY
129 volatile char *p = ptr;
130 UINT_PTR count = size;
132 while (count > system_info.PageSize)
134 *p |= 0;
135 p += system_info.PageSize;
136 count -= system_info.PageSize;
138 p[0] |= 0;
139 p[count - 1] |= 0;
141 __EXCEPT( badptr_handler )
143 TRACE("%p caused page fault during write\n", ptr);
144 return TRUE;
146 __ENDTRY
147 return FALSE;
151 /***********************************************************************
152 * IsBadHugeReadPtr (KERNEL32.@)
154 * Check for read access on a memory block.
156 * PARAMS
157 * ptr [I] Address of memory block.
158 * size [I] Size of block.
160 * RETURNS
161 * Success: TRUE.
162 * Failure: FALSE. Process has read access to entire block.
164 BOOL WINAPI IsBadHugeReadPtr( LPCVOID ptr, UINT_PTR size )
166 return IsBadReadPtr( ptr, size );
170 /***********************************************************************
171 * IsBadHugeWritePtr (KERNEL32.@)
173 * Check for write access on a memory block.
175 * PARAMS
176 * ptr [I] Address of memory block.
177 * size [I] Size of block.
179 * RETURNS
180 * Success: TRUE.
181 * Failure: FALSE. Process has write access to entire block.
183 BOOL WINAPI IsBadHugeWritePtr( LPVOID ptr, UINT_PTR size )
185 return IsBadWritePtr( ptr, size );
189 /***********************************************************************
190 * IsBadCodePtr (KERNEL32.@)
192 * Check for read access on a memory address.
194 * PARAMS
195 * ptr [I] Address of function.
197 * RETURNS
198 * Success: TRUE.
199 * Failure: FALSE. Process has read access to specified memory.
201 BOOL WINAPI IsBadCodePtr( FARPROC ptr )
203 return IsBadReadPtr( ptr, 1 );
207 /***********************************************************************
208 * IsBadStringPtrA (KERNEL32.@)
210 * Check for read access on a range of memory pointed to by a string pointer.
212 * PARAMS
213 * str [I] Address of string.
214 * max [I] Maximum size of string.
216 * RETURNS
217 * Success: TRUE.
218 * Failure: FALSE. Read access to all bytes in string.
220 BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
222 if (!str) return TRUE;
224 __TRY
226 volatile const char *p = str;
227 while (p != str + max) if (!*p++) break;
229 __EXCEPT( badptr_handler )
231 TRACE("%p caused page fault during read\n", str);
232 return TRUE;
234 __ENDTRY
235 return FALSE;
239 /***********************************************************************
240 * IsBadStringPtrW (KERNEL32.@)
242 * See IsBadStringPtrA.
244 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT_PTR max )
246 if (!str) return TRUE;
248 __TRY
250 volatile const WCHAR *p = str;
251 while (p != str + max) if (!*p++) break;
253 __EXCEPT( badptr_handler )
255 TRACE("%p caused page fault during read\n", str);
256 return TRUE;
258 __ENDTRY
259 return FALSE;
261 /***********************************************************************
262 * lstrcatA (KERNEL32.@)
263 * lstrcat (KERNEL32.@)
265 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
267 __TRY
269 strcat( dst, src );
271 __EXCEPT( badptr_handler )
273 SetLastError( ERROR_INVALID_PARAMETER );
274 return NULL;
276 __ENDTRY
277 return dst;
281 /***********************************************************************
282 * lstrcatW (KERNEL32.@)
284 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
286 __TRY
288 strcatW( dst, src );
290 __EXCEPT( badptr_handler )
292 SetLastError( ERROR_INVALID_PARAMETER );
293 return NULL;
295 __ENDTRY
296 return dst;
300 /***********************************************************************
301 * lstrcpyA (KERNEL32.@)
302 * lstrcpy (KERNEL32.@)
304 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
306 __TRY
308 /* this is how Windows does it */
309 memmove( dst, src, strlen(src)+1 );
311 __EXCEPT( badptr_handler )
313 SetLastError( ERROR_INVALID_PARAMETER );
314 return NULL;
316 __ENDTRY
317 return dst;
321 /***********************************************************************
322 * lstrcpyW (KERNEL32.@)
324 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
326 __TRY
328 strcpyW( dst, src );
330 __EXCEPT( badptr_handler )
332 SetLastError( ERROR_INVALID_PARAMETER );
333 return NULL;
335 __ENDTRY
336 return dst;