virtual.c 24.5 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * Win32 virtual memory functions
 *
 * Copyright 1997 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
19 20
 */

21
#include "config.h"
22
#include "wine/port.h"
23

Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <fcntl.h>
25
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
26 27 28
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
29 30
#ifdef HAVE_UNISTD_H
# include <unistd.h>
31
#endif
32

33
#include "ntstatus.h"
34
#define WIN32_NO_STATUS
35
#define NONAMELESSUNION
36
#include "windef.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
37
#include "winbase.h"
38
#include "winnls.h"
39
#include "winternl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
40
#include "winerror.h"
41
#include "psapi.h"
42
#include "wine/exception.h"
43
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
44

45 46
#include "kernel_private.h"

47
WINE_DECLARE_DEBUG_CHANNEL(seh);
48
WINE_DECLARE_DEBUG_CHANNEL(file);
Alexandre Julliard's avatar
Alexandre Julliard committed
49

Alexandre Julliard's avatar
Alexandre Julliard committed
50 51

/***********************************************************************
52
 *             VirtualAlloc   (KERNEL32.@)
53 54 55 56 57 58 59 60
 *
 * Reserves or commits a region of pages in virtual address space.
 *
 * PARAMS
 *  addr    [I] Address of region to reserve or commit.
 *  size    [I] Size of region.
 *  type    [I] Type of allocation.
 *  protect [I] Type of access protection.
Alexandre Julliard's avatar
Alexandre Julliard committed
61 62
 *
 * RETURNS
63 64
 *	Success: Base address of allocated region of pages.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
65
 */
66
LPVOID WINAPI DECLSPEC_HOTPATCH VirtualAlloc( void *addr, SIZE_T size, DWORD type, DWORD protect )
67
{
68
    return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
Alexandre Julliard's avatar
Alexandre Julliard committed
69 70 71 72
}


/***********************************************************************
73
 *             VirtualAllocEx   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
74
 *
75
 * Seems to be just as VirtualAlloc, but with process handle.
76
 *
77 78 79 80 81 82 83 84
 * PARAMS
 *  hProcess [I] Handle to process to do mem operation.
 *  addr     [I] Address of region to reserve or commit.
 *  size     [I] Size of region.
 *  type     [I] Type of allocation.
 *  protect  [I] Type of access protection.
 *
 *
85
 * RETURNS
86 87
 *	Success: Base address of allocated region of pages.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
88
 */
89 90
LPVOID WINAPI VirtualAllocEx( HANDLE hProcess, LPVOID addr, SIZE_T size,
    DWORD type, DWORD protect )
Alexandre Julliard's avatar
Alexandre Julliard committed
91
{
92
    LPVOID ret = addr;
93
    NTSTATUS status;
Alexandre Julliard's avatar
Alexandre Julliard committed
94

95
    if ((status = NtAllocateVirtualMemory( hProcess, &ret, 0, &size, type, protect )))
Alexandre Julliard's avatar
Alexandre Julliard committed
96
    {
97 98
        SetLastError( RtlNtStatusToDosError(status) );
        ret = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
99
    }
100
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
101 102 103 104
}


/***********************************************************************
105
 *             VirtualFree   (KERNEL32.@)
106 107 108 109 110 111 112
 *
 * Releases or decommits a region of pages in virtual address space.
 *
 * PARAMS
 *  addr [I] Address of region of committed pages.
 *  size [I] Size of region.
 *  type [I] Type of operation.
Alexandre Julliard's avatar
Alexandre Julliard committed
113 114
 *
 * RETURNS
115 116
 *	Success: TRUE.
 *	Failure: FALSE.
Alexandre Julliard's avatar
Alexandre Julliard committed
117
 */
118 119
BOOL WINAPI VirtualFree( LPVOID addr, SIZE_T size, DWORD type )
{
120
    return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
Alexandre Julliard's avatar
Alexandre Julliard committed
121 122 123 124
}


/***********************************************************************
125
 *             VirtualFreeEx   (KERNEL32.@)
126 127 128 129 130 131 132 133
 *
 * Releases or decommits a region of pages in virtual address space.
 *
 * PARAMS
 *  process [I] Handle to process.
 *  addr    [I] Address of region to free.
 *  size    [I] Size of region.
 *  type    [I] Type of operation.
Alexandre Julliard's avatar
Alexandre Julliard committed
134 135
 *
 * RETURNS
136 137
 *	Success: TRUE.
 *	Failure: FALSE.
Alexandre Julliard's avatar
Alexandre Julliard committed
138
 */
139
BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type )
140 141 142 143
{
    NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
144 145 146 147
}


/***********************************************************************
148
 *             VirtualLock   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
149
 *
150 151 152 153 154
 * Locks the specified region of virtual address space.
 *
 * PARAMS
 *  addr [I] Address of first byte of range to lock.
 *  size [I] Number of bytes in range to lock.
Alexandre Julliard's avatar
Alexandre Julliard committed
155 156
 *
 * RETURNS
157 158 159 160 161 162
 *	Success: TRUE.
 *	Failure: FALSE.
 *
 * NOTES
 *	Always returns TRUE.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
163
 */
164
BOOL WINAPI VirtualLock( LPVOID addr, SIZE_T size )
165
{
166 167 168
    NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
169 170 171
}


172
/***********************************************************************
173
 *             VirtualUnlock   (KERNEL32.@)
174
 *
175 176 177 178 179
 * Unlocks a range of pages in the virtual address space.
 *
 * PARAMS
 *  addr [I] Address of first byte of range.
 *  size [I] Number of bytes in range.
180
 *
181
 * RETURNS
182 183 184 185 186 187
 *	Success: TRUE.
 *	Failure: FALSE.
 *
 * NOTES
 *	Always returns TRUE.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
188
 */
189
BOOL WINAPI VirtualUnlock( LPVOID addr, SIZE_T size )
Alexandre Julliard's avatar
Alexandre Julliard committed
190
{
191 192 193
    NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
194 195 196
}


197
/***********************************************************************
198
 *             VirtualProtect   (KERNEL32.@)
199 200 201 202 203 204 205 206
 *
 * Changes the access protection on a region of committed pages.
 *
 * PARAMS
 *  addr     [I] Address of region of committed pages.
 *  size     [I] Size of region.
 *  new_prot [I] Desired access protection.
 *  old_prot [O] Address of variable to get old protection.
Alexandre Julliard's avatar
Alexandre Julliard committed
207 208
 *
 * RETURNS
209 210
 *	Success: TRUE.
 *	Failure: FALSE.
211
 */
212 213
BOOL WINAPI VirtualProtect( LPVOID addr, SIZE_T size, DWORD new_prot, LPDWORD old_prot)
{
214
    return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
Alexandre Julliard's avatar
Alexandre Julliard committed
215 216 217 218
}


/***********************************************************************
219
 *             VirtualProtectEx   (KERNEL32.@)
220
 *
221
 * Changes the access protection on a region of committed pages in the
222 223 224 225 226 227 228 229
 * virtual address space of a specified process.
 *
 * PARAMS
 *  process  [I] Handle of process.
 *  addr     [I] Address of region of committed pages.
 *  size     [I] Size of region.
 *  new_prot [I] Desired access protection.
 *  old_prot [O] Address of variable to get old protection.
Alexandre Julliard's avatar
Alexandre Julliard committed
230 231
 *
 * RETURNS
232 233
 *	Success: TRUE.
 *	Failure: FALSE.
Alexandre Julliard's avatar
Alexandre Julliard committed
234
 */
235 236
BOOL WINAPI VirtualProtectEx( HANDLE process, LPVOID addr, SIZE_T size,
    DWORD new_prot, LPDWORD old_prot )
237
{
238 239 240
    NTSTATUS status;
    DWORD prot;

241
    /* Win9x allows passing NULL as old_prot while this fails on NT */
242 243 244
    if (!old_prot && (GetVersion() & 0x80000000)) old_prot = &prot;

    status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
245 246
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
247 248 249 250
}


/***********************************************************************
251
 *             VirtualQuery   (KERNEL32.@)
252 253 254 255 256 257 258
 *
 * Provides info about a range of pages in virtual address space.
 *
 * PARAMS
 *  addr [I] Address of region.
 *  info [O] Address of info buffer.
 *  len  [I] Size of buffer.
Alexandre Julliard's avatar
Alexandre Julliard committed
259 260
 *
 * RETURNS
261 262
 *	Number of bytes returned in information buffer or 0 if
 *	addr >= 0xc0000000 (kernel space).
Alexandre Julliard's avatar
Alexandre Julliard committed
263
 */
264 265 266
SIZE_T WINAPI VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info,
    SIZE_T len )
{
267
    return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
Alexandre Julliard's avatar
Alexandre Julliard committed
268 269 270 271
}


/***********************************************************************
272
 *             VirtualQueryEx   (KERNEL32.@)
273
 *
274
 * Provides info about a range of pages in virtual address space of a
275 276 277 278 279 280 281
 * specified process.
 *
 * PARAMS
 *  process [I] Handle to process.
 *  addr    [I] Address of region.
 *  info    [O] Address of info buffer.
 *  len     [I] Size of buffer.
282 283
 *
 * RETURNS
284
 *	Number of bytes returned in information buffer.
Alexandre Julliard's avatar
Alexandre Julliard committed
285
 */
286 287
SIZE_T WINAPI VirtualQueryEx( HANDLE process, LPCVOID addr,
    PMEMORY_BASIC_INFORMATION info, SIZE_T len )
Alexandre Julliard's avatar
Alexandre Julliard committed
288
{
289
    SIZE_T ret;
290 291 292
    NTSTATUS status;

    if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
Alexandre Julliard's avatar
Alexandre Julliard committed
293
    {
294 295
        SetLastError( RtlNtStatusToDosError(status) );
        ret = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
296
    }
297
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
298 299 300 301
}


/***********************************************************************
302
 *             CreateFileMappingA   (KERNEL32.@)
303 304 305 306 307 308 309 310 311 312
 *
 * Creates a named or unnamed file-mapping object for the specified file.
 *
 * PARAMS
 *  hFile     [I] Handle to the file to map.
 *  sa        [I] Optional security attributes.
 *  protect   [I] Protection for mapping object.
 *  size_high [I] High-order 32 bits of object size.
 *  size_low  [I] Low-order 32 bits of object size.
 *  name      [I] Name of file-mapping object.
Alexandre Julliard's avatar
Alexandre Julliard committed
313 314
 *
 * RETURNS
315 316
 *	Success: Handle.
 *	Failure: NULL. Mapping object does not exist.
Alexandre Julliard's avatar
Alexandre Julliard committed
317
 */
318 319
HANDLE WINAPI CreateFileMappingA( HANDLE hFile, SECURITY_ATTRIBUTES *sa,
    DWORD protect, DWORD size_high, DWORD size_low, LPCSTR name )
Alexandre Julliard's avatar
Alexandre Julliard committed
320
{
321
    WCHAR buffer[MAX_PATH];
Alexandre Julliard's avatar
Alexandre Julliard committed
322

323
    if (!name) return CreateFileMappingW( hFile, sa, protect, size_high, size_low, NULL );
Alexandre Julliard's avatar
Alexandre Julliard committed
324

325
    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
326 327 328 329
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
330
    return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
331 332 333 334
}


/***********************************************************************
335
 *             CreateFileMappingW   (KERNEL32.@)
336
 *
337
 * See CreateFileMappingA.
Alexandre Julliard's avatar
Alexandre Julliard committed
338
 */
339 340
HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
                                  DWORD protect, DWORD size_high,
341
                                  DWORD size_low, LPCWSTR name )
Alexandre Julliard's avatar
Alexandre Julliard committed
342
{
343 344
    static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;

345
    HANDLE ret;
346 347 348 349 350 351 352
    NTSTATUS status;
    DWORD access, sec_type;
    LARGE_INTEGER size;

    sec_type = protect & sec_flags;
    protect &= ~sec_flags;
    if (!sec_type) sec_type = SEC_COMMIT;
353

354 355 356
    /* Win9x compatibility */
    if (!protect && (GetVersion() & 0x80000000)) protect = PAGE_READONLY;

357
    switch(protect)
358
    {
359 360
    case PAGE_READONLY:
    case PAGE_WRITECOPY:
361
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
362 363
        break;
    case PAGE_READWRITE:
364
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE;
365
        break;
366 367
    case PAGE_EXECUTE_READ:
    case PAGE_EXECUTE_WRITECOPY:
368
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE;
369 370
        break;
    case PAGE_EXECUTE_READWRITE:
371
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE;
372
        break;
373 374
    default:
        SetLastError( ERROR_INVALID_PARAMETER );
375 376 377
        return 0;
    }

378
    if (hFile == INVALID_HANDLE_VALUE)
379
    {
380 381
        hFile = 0;
        if (!size_low && !size_high)
382 383 384 385 386 387
        {
            SetLastError( ERROR_INVALID_PARAMETER );
            return 0;
        }
    }

388 389
    size.u.LowPart  = size_low;
    size.u.HighPart = size_high;
390

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
    if (sa || name)
    {
        OBJECT_ATTRIBUTES attr;
        UNICODE_STRING nameW;

        attr.Length                   = sizeof(attr);
        attr.RootDirectory            = 0;
        attr.ObjectName               = NULL;
        attr.Attributes               = OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
        attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
        attr.SecurityQualityOfService = NULL;
        if (name)
        {
            RtlInitUnicodeString( &nameW, name );
            attr.ObjectName = &nameW;
            attr.RootDirectory = get_BaseNamedObjects_handle();
        }
        status = NtCreateSection( &ret, access, &attr, &size, protect, sec_type, hFile );
    }
    else status = NtCreateSection( &ret, access, NULL, &size, protect, sec_type, hFile );

412 413 414 415
    if (status == STATUS_OBJECT_NAME_EXISTS)
        SetLastError( ERROR_ALREADY_EXISTS );
    else
        SetLastError( RtlNtStatusToDosError(status) );
416
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
417 418 419 420
}


/***********************************************************************
421
 *             OpenFileMappingA   (KERNEL32.@)
422
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
423
 * Opens a named file-mapping object.
Alexandre Julliard's avatar
Alexandre Julliard committed
424
 *
425 426 427 428 429
 * PARAMS
 *  access  [I] Access mode.
 *  inherit [I] Inherit flag.
 *  name    [I] Name of file-mapping object.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
430
 * RETURNS
431 432
 *	Success: Handle.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
433
 */
434
HANDLE WINAPI OpenFileMappingA( DWORD access, BOOL inherit, LPCSTR name )
435
{
436 437 438 439 440
    WCHAR buffer[MAX_PATH];

    if (!name) return OpenFileMappingW( access, inherit, NULL );

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
441 442 443 444
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
445
    return OpenFileMappingW( access, inherit, buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
446 447 448 449
}


/***********************************************************************
450
 *             OpenFileMappingW   (KERNEL32.@)
451
 *
452
 * See OpenFileMappingA.
Alexandre Julliard's avatar
Alexandre Julliard committed
453
 */
454
HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
Alexandre Julliard's avatar
Alexandre Julliard committed
455
{
456 457
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING nameW;
458
    HANDLE ret;
459 460 461
    NTSTATUS status;

    if (!name)
462
    {
463
        SetLastError( ERROR_INVALID_PARAMETER );
464 465
        return 0;
    }
466
    attr.Length = sizeof(attr);
467
    attr.RootDirectory = get_BaseNamedObjects_handle();
468
    attr.ObjectName = &nameW;
469
    attr.Attributes = inherit ? OBJ_INHERIT : 0;
470 471 472 473
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;
    RtlInitUnicodeString( &nameW, name );

474
    if (access == FILE_MAP_COPY) access = SECTION_MAP_READ;
475 476 477 478 479 480

    if (GetVersion() & 0x80000000)
    {
        /* win9x doesn't do access checks, so try with full access first */
        if (!NtOpenSection( &ret, access | SECTION_MAP_READ | SECTION_MAP_WRITE, &attr )) return ret;
    }
481 482

    if ((status = NtOpenSection( &ret, access, &attr )))
483
    {
484 485
        SetLastError( RtlNtStatusToDosError(status) );
        ret = 0;
486 487
    }
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
488 489 490 491
}


/***********************************************************************
492
 *             MapViewOfFile   (KERNEL32.@)
493 494 495 496 497 498 499 500 501
 *
 * Maps a view of a file into the address space.
 *
 * PARAMS
 *  mapping     [I] File-mapping object to map.
 *  access      [I] Access mode.
 *  offset_high [I] High-order 32 bits of file offset.
 *  offset_low  [I] Low-order 32 bits of file offset.
 *  count       [I] Number of bytes to map.
Alexandre Julliard's avatar
Alexandre Julliard committed
502 503
 *
 * RETURNS
504 505
 *	Success: Starting address of mapped view.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
506
 */
507
LPVOID WINAPI DECLSPEC_HOTPATCH MapViewOfFile( HANDLE mapping, DWORD access,
508 509
    DWORD offset_high, DWORD offset_low, SIZE_T count )
{
Alexandre Julliard's avatar
Alexandre Julliard committed
510 511 512 513 514 515
    return MapViewOfFileEx( mapping, access, offset_high,
                            offset_low, count, NULL );
}


/***********************************************************************
516
 *             MapViewOfFileEx   (KERNEL32.@)
517 518 519 520 521 522 523 524 525 526
 *
 * Maps a view of a file into the address space.
 *
 * PARAMS
 *  handle      [I] File-mapping object to map.
 *  access      [I] Access mode.
 *  offset_high [I] High-order 32 bits of file offset.
 *  offset_low  [I] Low-order 32 bits of file offset.
 *  count       [I] Number of bytes to map.
 *  addr        [I] Suggested starting address for mapped view.
Alexandre Julliard's avatar
Alexandre Julliard committed
527 528
 *
 * RETURNS
529 530
 *	Success: Starting address of mapped view.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
531
 */
532 533 534
LPVOID WINAPI MapViewOfFileEx( HANDLE handle, DWORD access,
    DWORD offset_high, DWORD offset_low, SIZE_T count, LPVOID addr )
{
535 536 537
    NTSTATUS status;
    LARGE_INTEGER offset;
    ULONG protect;
538
    BOOL exec;
539

540 541
    offset.u.LowPart  = offset_low;
    offset.u.HighPart = offset_high;
542

543 544
    exec = access & FILE_MAP_EXECUTE;
    access &= ~FILE_MAP_EXECUTE;
Alexandre Julliard's avatar
Alexandre Julliard committed
545

546 547 548 549 550 551 552
    if (access == FILE_MAP_COPY)
        protect = exec ? PAGE_EXECUTE_WRITECOPY : PAGE_WRITECOPY;
    else if (access & FILE_MAP_WRITE)
        protect = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
    else if (access & FILE_MAP_READ)
        protect = exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
    else protect = PAGE_NOACCESS;
553

554
    if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
555
                                      &count, ViewShare, 0, protect )) < 0)
556
    {
557 558
        SetLastError( RtlNtStatusToDosError(status) );
        addr = NULL;
559
    }
560 561
    return addr;
}
562

563

564 565
/***********************************************************************
 *             UnmapViewOfFile   (KERNEL32.@)
566
 *
567 568
 * Unmaps a mapped view of a file.
 *
569 570
 * PARAMS
 *  addr [I] Address where mapped view begins.
571 572
 *
 * RETURNS
573 574 575
 *	Success: TRUE.
 *	Failure: FALSE.
 *
576
 */
577
BOOL WINAPI UnmapViewOfFile( LPCVOID addr )
578
{
579 580 581 582 583 584 585 586 587 588 589 590 591
    NTSTATUS status;

    if (GetVersion() & 0x80000000)
    {
        MEMORY_BASIC_INFORMATION info;
        if (!VirtualQuery( addr, &info, sizeof(info) ) || info.AllocationBase != addr)
        {
            SetLastError( ERROR_INVALID_ADDRESS );
            return FALSE;
        }
    }

    status = NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr );
592 593 594
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
}
595

Alexandre Julliard's avatar
Alexandre Julliard committed
596

597 598
/***********************************************************************
 *             FlushViewOfFile   (KERNEL32.@)
599 600 601 602 603 604
 *
 * Writes to the disk a byte range within a mapped view of a file.
 *
 * PARAMS
 *  base [I] Start address of byte range to flush.
 *  size [I] Number of bytes in range.
605 606
 *
 * RETURNS
607 608
 *	Success: TRUE.
 *	Failure: FALSE.
609
 */
610
BOOL WINAPI FlushViewOfFile( LPCVOID base, SIZE_T size )
611 612 613
{
    NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
    if (status)
Alexandre Julliard's avatar
Alexandre Julliard committed
614
    {
615 616
        if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
        else SetLastError( RtlNtStatusToDosError(status) );
Alexandre Julliard's avatar
Alexandre Julliard committed
617
    }
618 619
    return !status;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
620

621

622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
/***********************************************************************
 *             GetWriteWatch   (KERNEL32.@)
 */
UINT WINAPI GetWriteWatch( DWORD flags, LPVOID base, SIZE_T size, LPVOID *addresses,
                           ULONG_PTR *count, ULONG *granularity )
{
    NTSTATUS status;

    status = NtGetWriteWatch( GetCurrentProcess(), flags, base, size, addresses, count, granularity );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return status ? ~0u : 0;
}


/***********************************************************************
 *             ResetWriteWatch   (KERNEL32.@)
 */
UINT WINAPI ResetWriteWatch( LPVOID base, SIZE_T size )
{
    NTSTATUS status;

    status = NtResetWriteWatch( GetCurrentProcess(), base, size );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return status ? ~0u : 0;
}


649 650 651
/***********************************************************************
 *             IsBadReadPtr   (KERNEL32.@)
 *
652 653
 * Check for read access on a memory block.
 *
654 655 656
 * ptr  [I] Address of memory block.
 * size [I] Size of block.
 *
657
 * RETURNS
658 659
 *  Success: TRUE.
 *	Failure: FALSE. Process has read access to entire block.
660
 */
661
BOOL WINAPI IsBadReadPtr( LPCVOID ptr, UINT_PTR size )
662 663
{
    if (!size) return FALSE;  /* handle 0 size case w/o reference */
664
    if (!ptr) return TRUE;
665
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
666
    {
667
        volatile const char *p = ptr;
668
        char dummy __attribute__((unused));
669
        UINT_PTR count = size;
670

671
        while (count > system_info.PageSize)
Alexandre Julliard's avatar
Alexandre Julliard committed
672
        {
673
            dummy = *p;
674 675
            p += system_info.PageSize;
            count -= system_info.PageSize;
Alexandre Julliard's avatar
Alexandre Julliard committed
676
        }
677 678
        dummy = p[0];
        dummy = p[count - 1];
Alexandre Julliard's avatar
Alexandre Julliard committed
679
    }
680
    __EXCEPT_PAGE_FAULT
681 682 683 684
    {
        TRACE_(seh)("%p caused page fault during read\n", ptr);
        return TRUE;
    }
685 686 687
    __ENDTRY
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
688

689

690 691 692
/***********************************************************************
 *             IsBadWritePtr   (KERNEL32.@)
 *
693 694
 * Check for write access on a memory block.
 *
695 696 697 698
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block in bytes.
 *
699
 * RETURNS
700 701
 *  Success: TRUE.
 *	Failure: FALSE. Process has write access to entire block.
702
 */
703
BOOL WINAPI IsBadWritePtr( LPVOID ptr, UINT_PTR size )
704 705
{
    if (!size) return FALSE;  /* handle 0 size case w/o reference */
706
    if (!ptr) return TRUE;
707 708 709
    __TRY
    {
        volatile char *p = ptr;
710
        UINT_PTR count = size;
711

712
        while (count > system_info.PageSize)
713 714
        {
            *p |= 0;
715 716
            p += system_info.PageSize;
            count -= system_info.PageSize;
717 718 719 720
        }
        p[0] |= 0;
        p[count - 1] |= 0;
    }
721
    __EXCEPT_PAGE_FAULT
722 723 724 725
    {
        TRACE_(seh)("%p caused page fault during write\n", ptr);
        return TRUE;
    }
726 727 728
    __ENDTRY
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
729 730


731 732
/***********************************************************************
 *             IsBadHugeReadPtr   (KERNEL32.@)
733 734 735
 *
 * Check for read access on a memory block.
 *
736 737 738 739
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block.
 *
740
 * RETURNS
741 742
 *  Success: TRUE.
 *	Failure: FALSE. Process has read access to entire block.
743
 */
744
BOOL WINAPI IsBadHugeReadPtr( LPCVOID ptr, UINT_PTR size )
745
{
746 747
    return IsBadReadPtr( ptr, size );
}
Alexandre Julliard's avatar
Alexandre Julliard committed
748 749


750 751
/***********************************************************************
 *             IsBadHugeWritePtr   (KERNEL32.@)
752 753 754
 *
 * Check for write access on a memory block.
 *
755 756 757 758
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block.
 *
759
 * RETURNS
760 761
 *  Success: TRUE.
 *	Failure: FALSE. Process has write access to entire block.
762
 */
763
BOOL WINAPI IsBadHugeWritePtr( LPVOID ptr, UINT_PTR size )
764
{
765
    return IsBadWritePtr( ptr, size );
Alexandre Julliard's avatar
Alexandre Julliard committed
766 767 768
}


Alexandre Julliard's avatar
Alexandre Julliard committed
769
/***********************************************************************
770
 *             IsBadCodePtr   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
771
 *
772 773
 * Check for read access on a memory address.
 *
774 775 776
 * PARAMS
 *  ptr [I] Address of function.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
777
 * RETURNS
778 779
 *	Success: TRUE.
 *	Failure: FALSE. Process has read access to specified memory.
Alexandre Julliard's avatar
Alexandre Julliard committed
780
 */
781
BOOL WINAPI IsBadCodePtr( FARPROC ptr )
782 783 784
{
    return IsBadReadPtr( ptr, 1 );
}
Alexandre Julliard's avatar
Alexandre Julliard committed
785 786


787 788 789
/***********************************************************************
 *             IsBadStringPtrA   (KERNEL32.@)
 *
790 791
 * Check for read access on a range of memory pointed to by a string pointer.
 *
792 793 794 795
 * PARAMS
 *  str [I] Address of string.
 *  max [I] Maximum size of string.
 *
796
 * RETURNS
797 798
 *	Success: TRUE.
 *	Failure: FALSE. Read access to all bytes in string.
799
 */
800
BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT_PTR max )
801
{
802 803
    if (!str) return TRUE;
    
804
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
805
    {
806 807
        volatile const char *p = str;
        while (p != str + max) if (!*p++) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
808
    }
809
    __EXCEPT_PAGE_FAULT
810 811 812 813
    {
        TRACE_(seh)("%p caused page fault during read\n", str);
        return TRUE;
    }
814
    __ENDTRY
Alexandre Julliard's avatar
Alexandre Julliard committed
815 816
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
817

Alexandre Julliard's avatar
Alexandre Julliard committed
818

Alexandre Julliard's avatar
Alexandre Julliard committed
819
/***********************************************************************
820
 *             IsBadStringPtrW   (KERNEL32.@)
821
 *
822
 * See IsBadStringPtrA.
Alexandre Julliard's avatar
Alexandre Julliard committed
823
 */
824
BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT_PTR max )
825
{
826 827
    if (!str) return TRUE;
    
828
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
829
    {
830 831
        volatile const WCHAR *p = str;
        while (p != str + max) if (!*p++) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
832
    }
833
    __EXCEPT_PAGE_FAULT
834 835 836 837
    {
        TRACE_(seh)("%p caused page fault during read\n", str);
        return TRUE;
    }
838 839
    __ENDTRY
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
840
}
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866

/***********************************************************************
 *           K32GetMappedFileNameA (KERNEL32.@)
 */
DWORD WINAPI K32GetMappedFileNameA(HANDLE process, LPVOID lpv, LPSTR file_name, DWORD size)
{
    FIXME_(file)("(%p, %p, %p, %d): stub\n", process, lpv, file_name, size);

    if (file_name && size)
        file_name[0] = '\0';

    return 0;
}

/***********************************************************************
 *           K32GetMappedFileNameW (KERNEL32.@)
 */
DWORD WINAPI K32GetMappedFileNameW(HANDLE process, LPVOID lpv, LPWSTR file_name, DWORD size)
{
    FIXME_(file)("(%p, %p, %p, %d): stub\n", process, lpv, file_name, size);

    if (file_name && size)
        file_name[0] = '\0';

    return 0;
}
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884

/***********************************************************************
 *           K32EnumPageFilesA (KERNEL32.@)
 */
BOOL WINAPI K32EnumPageFilesA( PENUM_PAGE_FILE_CALLBACKA callback, LPVOID context )
{
    FIXME_(file)("(%p, %p) stub\n", callback, context );
    return FALSE;
}

/***********************************************************************
 *           K32EnumPageFilesW (KERNEL32.@)
 */
BOOL WINAPI K32EnumPageFilesW( PENUM_PAGE_FILE_CALLBACKW callback, LPVOID context )
{
    FIXME_(file)("(%p, %p) stub\n", callback, context );
    return FALSE;
}
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913

/***********************************************************************
 *           K32GetWsChanges (KERNEL32.@)
 */
BOOL WINAPI K32GetWsChanges(HANDLE process, PPSAPI_WS_WATCH_INFORMATION watchinfo, DWORD size)
{
    NTSTATUS status;

    TRACE_(seh)("(%p, %p, %d)\n", process, watchinfo, size);

    status = NtQueryInformationProcess( process, ProcessWorkingSetWatch, watchinfo, size, NULL );

    if (status)
    {
        SetLastError( RtlNtStatusToDosError( status ) );
        return FALSE;
    }
    return TRUE;
}

/***********************************************************************
 *           K32InitializeProcessForWsWatch (KERNEL32.@)
 */
BOOL WINAPI K32InitializeProcessForWsWatch(HANDLE process)
{
    FIXME_(seh)("(process=%p): stub\n", process);

    return TRUE;
}