kernel32: Only change the Unix current after exec_process to make sure it's inherited...
[wine] / dlls / kernel32 / virtual.c
1 /*
2  * Win32 virtual memory functions
3  *
4  * Copyright 1997 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
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
32
33 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
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/debug.h"
45
46 #include "kernel_private.h"
47
48 WINE_DECLARE_DEBUG_CHANNEL(seh);
49 WINE_DECLARE_DEBUG_CHANNEL(file);
50
51 static unsigned int page_size;
52
53
54 /***********************************************************************
55  *             VirtualAlloc   (KERNEL32.@)
56  *
57  * Reserves or commits a region of pages in virtual address space.
58  *
59  * PARAMS
60  *  addr    [I] Address of region to reserve or commit.
61  *  size    [I] Size of region.
62  *  type    [I] Type of allocation.
63  *  protect [I] Type of access protection.
64  *
65  * RETURNS
66  *      Success: Base address of allocated region of pages.
67  *      Failure: NULL.
68  */
69 LPVOID WINAPI VirtualAlloc( LPVOID addr, SIZE_T size, DWORD type, DWORD protect )
70 {
71     return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
72 }
73
74
75 /***********************************************************************
76  *             VirtualAllocEx   (KERNEL32.@)
77  *
78  * Seems to be just as VirtualAlloc, but with process handle.
79  *
80  * PARAMS
81  *  hProcess [I] Handle to process to do mem operation.
82  *  addr     [I] Address of region to reserve or commit.
83  *  size     [I] Size of region.
84  *  type     [I] Type of allocation.
85  *  protect  [I] Type of access protection.
86  *
87  *
88  * RETURNS
89  *      Success: Base address of allocated region of pages.
90  *      Failure: NULL.
91  */
92 LPVOID WINAPI VirtualAllocEx( HANDLE hProcess, LPVOID addr, SIZE_T size,
93     DWORD type, DWORD protect )
94 {
95     LPVOID ret = addr;
96     NTSTATUS status;
97
98     if ((status = NtAllocateVirtualMemory( hProcess, &ret, 0, &size, type, protect )))
99     {
100         SetLastError( RtlNtStatusToDosError(status) );
101         ret = NULL;
102     }
103     return ret;
104 }
105
106
107 /***********************************************************************
108  *             VirtualFree   (KERNEL32.@)
109  *
110  * Releases or decommits a region of pages in virtual address space.
111  *
112  * PARAMS
113  *  addr [I] Address of region of committed pages.
114  *  size [I] Size of region.
115  *  type [I] Type of operation.
116  *
117  * RETURNS
118  *      Success: TRUE.
119  *      Failure: FALSE.
120  */
121 BOOL WINAPI VirtualFree( LPVOID addr, SIZE_T size, DWORD type )
122 {
123     return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
124 }
125
126
127 /***********************************************************************
128  *             VirtualFreeEx   (KERNEL32.@)
129  *
130  * Releases or decommits a region of pages in virtual address space.
131  *
132  * PARAMS
133  *  process [I] Handle to process.
134  *  addr    [I] Address of region to free.
135  *  size    [I] Size of region.
136  *  type    [I] Type of operation.
137  *
138  * RETURNS
139  *      Success: TRUE.
140  *      Failure: FALSE.
141  */
142 BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type )
143 {
144     NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
145     if (status) SetLastError( RtlNtStatusToDosError(status) );
146     return !status;
147 }
148
149
150 /***********************************************************************
151  *             VirtualLock   (KERNEL32.@)
152  *
153  * Locks the specified region of virtual address space.
154  *
155  * PARAMS
156  *  addr [I] Address of first byte of range to lock.
157  *  size [I] Number of bytes in range to lock.
158  *
159  * RETURNS
160  *      Success: TRUE.
161  *      Failure: FALSE.
162  *
163  * NOTES
164  *      Always returns TRUE.
165  *
166  */
167 BOOL WINAPI VirtualLock( LPVOID addr, SIZE_T size )
168 {
169     NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
170     if (status) SetLastError( RtlNtStatusToDosError(status) );
171     return !status;
172 }
173
174
175 /***********************************************************************
176  *             VirtualUnlock   (KERNEL32.@)
177  *
178  * Unlocks a range of pages in the virtual address space.
179  *
180  * PARAMS
181  *  addr [I] Address of first byte of range.
182  *  size [I] Number of bytes in range.
183  *
184  * RETURNS
185  *      Success: TRUE.
186  *      Failure: FALSE.
187  *
188  * NOTES
189  *      Always returns TRUE.
190  *
191  */
192 BOOL WINAPI VirtualUnlock( LPVOID addr, SIZE_T size )
193 {
194     NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
195     if (status) SetLastError( RtlNtStatusToDosError(status) );
196     return !status;
197 }
198
199
200 /***********************************************************************
201  *             VirtualProtect   (KERNEL32.@)
202  *
203  * Changes the access protection on a region of committed pages.
204  *
205  * PARAMS
206  *  addr     [I] Address of region of committed pages.
207  *  size     [I] Size of region.
208  *  new_prot [I] Desired access protection.
209  *  old_prot [O] Address of variable to get old protection.
210  *
211  * RETURNS
212  *      Success: TRUE.
213  *      Failure: FALSE.
214  */
215 BOOL WINAPI VirtualProtect( LPVOID addr, SIZE_T size, DWORD new_prot, LPDWORD old_prot)
216 {
217     return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
218 }
219
220
221 /***********************************************************************
222  *             VirtualProtectEx   (KERNEL32.@)
223  *
224  * Changes the access protection on a region of committed pages in the
225  * virtual address space of a specified process.
226  *
227  * PARAMS
228  *  process  [I] Handle of process.
229  *  addr     [I] Address of region of committed pages.
230  *  size     [I] Size of region.
231  *  new_prot [I] Desired access protection.
232  *  old_prot [O] Address of variable to get old protection.
233  *
234  * RETURNS
235  *      Success: TRUE.
236  *      Failure: FALSE.
237  */
238 BOOL WINAPI VirtualProtectEx( HANDLE process, LPVOID addr, SIZE_T size,
239     DWORD new_prot, LPDWORD old_prot )
240 {
241     NTSTATUS status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
242     if (status) SetLastError( RtlNtStatusToDosError(status) );
243     return !status;
244 }
245
246
247 /***********************************************************************
248  *             VirtualQuery   (KERNEL32.@)
249  *
250  * Provides info about a range of pages in virtual address space.
251  *
252  * PARAMS
253  *  addr [I] Address of region.
254  *  info [O] Address of info buffer.
255  *  len  [I] Size of buffer.
256  *
257  * RETURNS
258  *      Number of bytes returned in information buffer or 0 if
259  *      addr >= 0xc0000000 (kernel space).
260  */
261 SIZE_T WINAPI VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info,
262     SIZE_T len )
263 {
264     return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
265 }
266
267
268 /***********************************************************************
269  *             VirtualQueryEx   (KERNEL32.@)
270  *
271  * Provides info about a range of pages in virtual address space of a
272  * specified process.
273  *
274  * PARAMS
275  *  process [I] Handle to process.
276  *  addr    [I] Address of region.
277  *  info    [O] Address of info buffer.
278  *  len     [I] Size of buffer.
279  *
280  * RETURNS
281  *      Number of bytes returned in information buffer.
282  */
283 SIZE_T WINAPI VirtualQueryEx( HANDLE process, LPCVOID addr,
284     PMEMORY_BASIC_INFORMATION info, SIZE_T len )
285 {
286     SIZE_T ret;
287     NTSTATUS status;
288
289     if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
290     {
291         SetLastError( RtlNtStatusToDosError(status) );
292         ret = 0;
293     }
294     return ret;
295 }
296
297
298 /***********************************************************************
299  *             CreateFileMappingA   (KERNEL32.@)
300  *
301  * Creates a named or unnamed file-mapping object for the specified file.
302  *
303  * PARAMS
304  *  hFile     [I] Handle to the file to map.
305  *  sa        [I] Optional security attributes.
306  *  protect   [I] Protection for mapping object.
307  *  size_high [I] High-order 32 bits of object size.
308  *  size_low  [I] Low-order 32 bits of object size.
309  *  name      [I] Name of file-mapping object.
310  *
311  * RETURNS
312  *      Success: Handle.
313  *      Failure: NULL. Mapping object does not exist.
314  */
315 HANDLE WINAPI CreateFileMappingA( HANDLE hFile, SECURITY_ATTRIBUTES *sa,
316     DWORD protect, DWORD size_high, DWORD size_low, LPCSTR name )
317 {
318     WCHAR buffer[MAX_PATH];
319
320     if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
321
322     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
323     {
324         SetLastError( ERROR_FILENAME_EXCED_RANGE );
325         return 0;
326     }
327     return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
328 }
329
330
331 /***********************************************************************
332  *             CreateFileMappingW   (KERNEL32.@)
333  *
334  * See CreateFileMappingA.
335  */
336 HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
337                                   DWORD protect, DWORD size_high,
338                                   DWORD size_low, LPCWSTR name )
339 {
340     static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;
341
342     HANDLE ret;
343     NTSTATUS status;
344     DWORD access, sec_type;
345     LARGE_INTEGER size;
346
347     sec_type = protect & sec_flags;
348     protect &= ~sec_flags;
349     if (!sec_type) sec_type = SEC_COMMIT;
350
351     /* Win9x compatibility */
352     if (!protect && (GetVersion() & 0x80000000)) protect = PAGE_READONLY;
353
354     switch(protect)
355     {
356     case PAGE_READONLY:
357     case PAGE_WRITECOPY:
358         access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE;
359         break;
360     case PAGE_READWRITE:
361         access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE;
362         break;
363     case PAGE_EXECUTE_READ:
364     case PAGE_EXECUTE_WRITECOPY:
365         access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT;
366         break;
367     case PAGE_EXECUTE_READWRITE:
368         access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT;
369         break;
370     default:
371         SetLastError( ERROR_INVALID_PARAMETER );
372         return 0;
373     }
374
375     if (hFile == INVALID_HANDLE_VALUE)
376     {
377         hFile = 0;
378         if (!size_low && !size_high)
379         {
380             SetLastError( ERROR_INVALID_PARAMETER );
381             return 0;
382         }
383     }
384
385     size.u.LowPart  = size_low;
386     size.u.HighPart = size_high;
387
388     if (sa || name)
389     {
390         OBJECT_ATTRIBUTES attr;
391         UNICODE_STRING nameW;
392
393         attr.Length                   = sizeof(attr);
394         attr.RootDirectory            = 0;
395         attr.ObjectName               = NULL;
396         attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
397         attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
398         attr.SecurityQualityOfService = NULL;
399         if (name)
400         {
401             RtlInitUnicodeString( &nameW, name );
402             attr.ObjectName = &nameW;
403             attr.RootDirectory = get_BaseNamedObjects_handle();
404         }
405         status = NtCreateSection( &ret, access, &attr, &size, protect, sec_type, hFile );
406     }
407     else status = NtCreateSection( &ret, access, NULL, &size, protect, sec_type, hFile );
408
409     if (status == STATUS_OBJECT_NAME_EXISTS)
410         SetLastError( ERROR_ALREADY_EXISTS );
411     else
412         SetLastError( RtlNtStatusToDosError(status) );
413     return ret;
414 }
415
416
417 /***********************************************************************
418  *             OpenFileMappingA   (KERNEL32.@)
419  *
420  * Opens a named file-mapping object.
421  *
422  * PARAMS
423  *  access  [I] Access mode.
424  *  inherit [I] Inherit flag.
425  *  name    [I] Name of file-mapping object.
426  *
427  * RETURNS
428  *      Success: Handle.
429  *      Failure: NULL.
430  */
431 HANDLE WINAPI OpenFileMappingA( DWORD access, BOOL inherit, LPCSTR name )
432 {
433     WCHAR buffer[MAX_PATH];
434
435     if (!name) return OpenFileMappingW( access, inherit, NULL );
436
437     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
438     {
439         SetLastError( ERROR_FILENAME_EXCED_RANGE );
440         return 0;
441     }
442     return OpenFileMappingW( access, inherit, buffer );
443 }
444
445
446 /***********************************************************************
447  *             OpenFileMappingW   (KERNEL32.@)
448  *
449  * See OpenFileMappingA.
450  */
451 HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
452 {
453     OBJECT_ATTRIBUTES attr;
454     UNICODE_STRING nameW;
455     HANDLE ret;
456     NTSTATUS status;
457
458     if (!name)
459     {
460         SetLastError( ERROR_INVALID_PARAMETER );
461         return 0;
462     }
463     attr.Length = sizeof(attr);
464     attr.RootDirectory = get_BaseNamedObjects_handle();
465     attr.ObjectName = &nameW;
466     attr.Attributes = inherit ? OBJ_INHERIT : 0;
467     attr.SecurityDescriptor = NULL;
468     attr.SecurityQualityOfService = NULL;
469     RtlInitUnicodeString( &nameW, name );
470
471     if (access == FILE_MAP_COPY) access = SECTION_MAP_READ;
472     access |= SECTION_QUERY;
473
474     if (GetVersion() & 0x80000000)
475     {
476         /* win9x doesn't do access checks, so try with full access first */
477         if (!NtOpenSection( &ret, access | SECTION_MAP_READ | SECTION_MAP_WRITE, &attr )) return ret;
478     }
479
480     if ((status = NtOpenSection( &ret, access, &attr )))
481     {
482         SetLastError( RtlNtStatusToDosError(status) );
483         ret = 0;
484     }
485     return ret;
486 }
487
488
489 /***********************************************************************
490  *             MapViewOfFile   (KERNEL32.@)
491  *
492  * Maps a view of a file into the address space.
493  *
494  * PARAMS
495  *  mapping     [I] File-mapping object to map.
496  *  access      [I] Access mode.
497  *  offset_high [I] High-order 32 bits of file offset.
498  *  offset_low  [I] Low-order 32 bits of file offset.
499  *  count       [I] Number of bytes to map.
500  *
501  * RETURNS
502  *      Success: Starting address of mapped view.
503  *      Failure: NULL.
504  */
505 LPVOID WINAPI MapViewOfFile( HANDLE mapping, DWORD access,
506     DWORD offset_high, DWORD offset_low, SIZE_T count )
507 {
508     return MapViewOfFileEx( mapping, access, offset_high,
509                             offset_low, count, NULL );
510 }
511
512
513 /***********************************************************************
514  *             MapViewOfFileEx   (KERNEL32.@)
515  *
516  * Maps a view of a file into the address space.
517  *
518  * PARAMS
519  *  handle      [I] File-mapping object to map.
520  *  access      [I] Access mode.
521  *  offset_high [I] High-order 32 bits of file offset.
522  *  offset_low  [I] Low-order 32 bits of file offset.
523  *  count       [I] Number of bytes to map.
524  *  addr        [I] Suggested starting address for mapped view.
525  *
526  * RETURNS
527  *      Success: Starting address of mapped view.
528  *      Failure: NULL.
529  */
530 LPVOID WINAPI MapViewOfFileEx( HANDLE handle, DWORD access,
531     DWORD offset_high, DWORD offset_low, SIZE_T count, LPVOID addr )
532 {
533     NTSTATUS status;
534     LARGE_INTEGER offset;
535     ULONG protect;
536     BOOL exec;
537
538     offset.u.LowPart  = offset_low;
539     offset.u.HighPart = offset_high;
540
541     exec = access & FILE_MAP_EXECUTE;
542     access &= ~FILE_MAP_EXECUTE;
543
544     if (access == FILE_MAP_COPY)
545         protect = exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY;
546     else if (access & FILE_MAP_WRITE)
547         protect = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
548     else if (access & FILE_MAP_READ)
549         protect = exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
550     else protect = PAGE_NOACCESS;
551
552     if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
553                                       &count, ViewShare, 0, protect )) < 0)
554     {
555         SetLastError( RtlNtStatusToDosError(status) );
556         addr = NULL;
557     }
558     return addr;
559 }
560
561
562 /***********************************************************************
563  *             UnmapViewOfFile   (KERNEL32.@)
564  *
565  * Unmaps a mapped view of a file.
566  *
567  * PARAMS
568  *  addr [I] Address where mapped view begins.
569  *
570  * RETURNS
571  *      Success: TRUE.
572  *      Failure: FALSE.
573  *
574  */
575 BOOL WINAPI UnmapViewOfFile( LPCVOID addr )
576 {
577     NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr );
578     if (status) SetLastError( RtlNtStatusToDosError(status) );
579     return !status;
580 }
581
582
583 /***********************************************************************
584  *             FlushViewOfFile   (KERNEL32.@)
585  *
586  * Writes to the disk a byte range within a mapped view of a file.
587  *
588  * PARAMS
589  *  base [I] Start address of byte range to flush.
590  *  size [I] Number of bytes in range.
591  *
592  * RETURNS
593  *      Success: TRUE.
594  *      Failure: FALSE.
595  */
596 BOOL WINAPI FlushViewOfFile( LPCVOID base, SIZE_T size )
597 {
598     NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
599     if (status)
600     {
601         if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
602         else SetLastError( RtlNtStatusToDosError(status) );
603     }
604     return !status;
605 }
606
607
608 /***********************************************************************
609  *             GetWriteWatch   (KERNEL32.@)
610  */
611 UINT WINAPI GetWriteWatch( DWORD flags, LPVOID base, SIZE_T size, LPVOID *addresses,
612                            ULONG_PTR *count, ULONG *granularity )
613 {
614     NTSTATUS status;
615
616     status = NtGetWriteWatch( GetCurrentProcess(), flags, base, size, addresses, count, granularity );
617     if (status) SetLastError( RtlNtStatusToDosError(status) );
618     return status ? ~0u : 0;
619 }
620
621
622 /***********************************************************************
623  *             ResetWriteWatch   (KERNEL32.@)
624  */
625 UINT WINAPI ResetWriteWatch( LPVOID base, SIZE_T size )
626 {
627     NTSTATUS status;
628
629     status = NtResetWriteWatch( GetCurrentProcess(), base, size );
630     if (status) SetLastError( RtlNtStatusToDosError(status) );
631     return status ? ~0u : 0;
632 }
633
634
635 /***********************************************************************
636  *             IsBadReadPtr   (KERNEL32.@)
637  *
638  * Check for read access on a memory block.
639  *
640  * ptr  [I] Address of memory block.
641  * size [I] Size of block.
642  *
643  * RETURNS
644  *  Success: TRUE.
645  *      Failure: FALSE. Process has read access to entire block.
646  */
647 BOOL WINAPI IsBadReadPtr( LPCVOID ptr, UINT size )
648 {
649     if (!size) return FALSE;  /* handle 0 size case w/o reference */
650     if (!ptr) return TRUE;
651     
652     if (!page_size) page_size = getpagesize();
653     __TRY
654     {
655         volatile const char *p = ptr;
656         char dummy __attribute__((unused));
657         UINT count = size;
658
659         while (count > page_size)
660         {
661             dummy = *p;
662             p += page_size;
663             count -= page_size;
664         }
665         dummy = p[0];
666         dummy = p[count - 1];
667     }
668     __EXCEPT_PAGE_FAULT
669     {
670         TRACE_(seh)("%p caused page fault during read\n", ptr);
671         return TRUE;
672     }
673     __ENDTRY
674     return FALSE;
675 }
676
677
678 /***********************************************************************
679  *             IsBadWritePtr   (KERNEL32.@)
680  *
681  * Check for write access on a memory block.
682  *
683  * PARAMS
684  *  ptr  [I] Address of memory block.
685  *  size [I] Size of block in bytes.
686  *
687  * RETURNS
688  *  Success: TRUE.
689  *      Failure: FALSE. Process has write access to entire block.
690  */
691 BOOL WINAPI IsBadWritePtr( LPVOID ptr, UINT size )
692 {
693     if (!size) return FALSE;  /* handle 0 size case w/o reference */
694     if (!ptr) return TRUE;
695     
696     if (!page_size) page_size = getpagesize();
697     __TRY
698     {
699         volatile char *p = ptr;
700         UINT count = size;
701
702         while (count > page_size)
703         {
704             *p |= 0;
705             p += page_size;
706             count -= page_size;
707         }
708         p[0] |= 0;
709         p[count - 1] |= 0;
710     }
711     __EXCEPT_PAGE_FAULT
712     {
713         TRACE_(seh)("%p caused page fault during write\n", ptr);
714         return TRUE;
715     }
716     __ENDTRY
717     return FALSE;
718 }
719
720
721 /***********************************************************************
722  *             IsBadHugeReadPtr   (KERNEL32.@)
723  *
724  * Check for read access on a memory block.
725  *
726  * PARAMS
727  *  ptr  [I] Address of memory block.
728  *  size [I] Size of block.
729  *
730  * RETURNS
731  *  Success: TRUE.
732  *      Failure: FALSE. Process has read access to entire block.
733  */
734 BOOL WINAPI IsBadHugeReadPtr( LPCVOID ptr, UINT size )
735 {
736     return IsBadReadPtr( ptr, size );
737 }
738
739
740 /***********************************************************************
741  *             IsBadHugeWritePtr   (KERNEL32.@)
742  *
743  * Check for write access on a memory block.
744  *
745  * PARAMS
746  *  ptr  [I] Address of memory block.
747  *  size [I] Size of block.
748  *
749  * RETURNS
750  *  Success: TRUE.
751  *      Failure: FALSE. Process has write access to entire block.
752  */
753 BOOL WINAPI IsBadHugeWritePtr( LPVOID ptr, UINT size )
754 {
755     return IsBadWritePtr( ptr, size );
756 }
757
758
759 /***********************************************************************
760  *             IsBadCodePtr   (KERNEL32.@)
761  *
762  * Check for read access on a memory address.
763  *
764  * PARAMS
765  *  ptr [I] Address of function.
766  *
767  * RETURNS
768  *      Success: TRUE.
769  *      Failure: FALSE. Process has read access to specified memory.
770  */
771 BOOL WINAPI IsBadCodePtr( FARPROC ptr )
772 {
773     return IsBadReadPtr( ptr, 1 );
774 }
775
776
777 /***********************************************************************
778  *             IsBadStringPtrA   (KERNEL32.@)
779  *
780  * Check for read access on a range of memory pointed to by a string pointer.
781  *
782  * PARAMS
783  *  str [I] Address of string.
784  *  max [I] Maximum size of string.
785  *
786  * RETURNS
787  *      Success: TRUE.
788  *      Failure: FALSE. Read access to all bytes in string.
789  */
790 BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT max )
791 {
792     if (!str) return TRUE;
793     
794     __TRY
795     {
796         volatile const char *p = str;
797         while (p != str + max) if (!*p++) break;
798     }
799     __EXCEPT_PAGE_FAULT
800     {
801         TRACE_(seh)("%p caused page fault during read\n", str);
802         return TRUE;
803     }
804     __ENDTRY
805     return FALSE;
806 }
807
808
809 /***********************************************************************
810  *             IsBadStringPtrW   (KERNEL32.@)
811  *
812  * See IsBadStringPtrA.
813  */
814 BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT max )
815 {
816     if (!str) return TRUE;
817     
818     __TRY
819     {
820         volatile const WCHAR *p = str;
821         while (p != str + max) if (!*p++) break;
822     }
823     __EXCEPT_PAGE_FAULT
824     {
825         TRACE_(seh)("%p caused page fault during read\n", str);
826         return TRUE;
827     }
828     __ENDTRY
829     return FALSE;
830 }
831
832 /***********************************************************************
833  *           K32GetMappedFileNameA (KERNEL32.@)
834  */
835 DWORD WINAPI K32GetMappedFileNameA(HANDLE process, LPVOID lpv, LPSTR file_name, DWORD size)
836 {
837     FIXME_(file)("(%p, %p, %p, %d): stub\n", process, lpv, file_name, size);
838
839     if (file_name && size)
840         file_name[0] = '\0';
841
842     return 0;
843 }
844
845 /***********************************************************************
846  *           K32GetMappedFileNameW (KERNEL32.@)
847  */
848 DWORD WINAPI K32GetMappedFileNameW(HANDLE process, LPVOID lpv, LPWSTR file_name, DWORD size)
849 {
850     FIXME_(file)("(%p, %p, %p, %d): stub\n", process, lpv, file_name, size);
851
852     if (file_name && size)
853         file_name[0] = '\0';
854
855     return 0;
856 }
857
858 /***********************************************************************
859  *           K32EnumPageFilesA (KERNEL32.@)
860  */
861 BOOL WINAPI K32EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback, LPVOID context )
862 {
863     FIXME_(file)("(%p, %p) stub\n", callback, context );
864     return FALSE;
865 }
866
867 /***********************************************************************
868  *           K32EnumPageFilesW (KERNEL32.@)
869  */
870 BOOL WINAPI K32EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback, LPVOID context )
871 {
872     FIXME_(file)("(%p, %p) stub\n", callback, context );
873     return FALSE;
874 }
875
876 /***********************************************************************
877  *           K32GetWsChanges (KERNEL32.@)
878  */
879 BOOL WINAPI K32GetWsChanges(HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size)
880 {
881     NTSTATUS status;
882
883     TRACE_(seh)("(%p, %p, %d)\n", process, watchinfo, size);
884
885     status = NtQueryInformationProcess( process, ProcessWorkingSetWatch, watchinfo, size, NULL );
886
887     if (status)
888     {
889         SetLastError( RtlNtStatusToDosError( status ) );
890         return FALSE;
891     }
892     return TRUE;
893 }
894
895 /***********************************************************************
896  *           K32InitializeProcessForWsWatch (KERNEL32.@)
897  */
898 BOOL WINAPI K32InitializeProcessForWsWatch(HANDLE process)
899 {
900     FIXME_(seh)("(process=%p): stub\n", process);
901
902     return TRUE;
903 }