virtual.c 22 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 34
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
35
#include "ntstatus.h"
36
#define WIN32_NO_STATUS
37
#include "windef.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
38
#include "winbase.h"
39
#include "winnls.h"
40
#include "winternl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
41
#include "winerror.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);
Alexandre Julliard's avatar
Alexandre Julliard committed
48

49
static unsigned int page_size;
50

Alexandre Julliard's avatar
Alexandre Julliard committed
51 52

/***********************************************************************
53
 *             VirtualAlloc   (KERNEL32.@)
54 55 56 57 58 59 60 61
 *
 * 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
62 63
 *
 * RETURNS
64 65
 *	Success: Base address of allocated region of pages.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
66
 */
67
LPVOID WINAPI VirtualAlloc( LPVOID addr, SIZE_T size, DWORD type, DWORD protect )
68
{
69
    return VirtualAllocEx( GetCurrentProcess(), addr, size, type, protect );
Alexandre Julliard's avatar
Alexandre Julliard committed
70 71 72 73
}


/***********************************************************************
74
 *             VirtualAllocEx   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
75
 *
76
 * Seems to be just as VirtualAlloc, but with process handle.
77
 *
78 79 80 81 82 83 84 85
 * 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.
 *
 *
86
 * RETURNS
87 88
 *	Success: Base address of allocated region of pages.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
89
 */
90 91
LPVOID WINAPI VirtualAllocEx( HANDLE hProcess, LPVOID addr, SIZE_T size,
    DWORD type, DWORD protect )
Alexandre Julliard's avatar
Alexandre Julliard committed
92
{
93
    LPVOID ret = addr;
94
    NTSTATUS status;
Alexandre Julliard's avatar
Alexandre Julliard committed
95

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


/***********************************************************************
106
 *             VirtualFree   (KERNEL32.@)
107 108 109 110 111 112 113
 *
 * 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
114 115
 *
 * RETURNS
116 117
 *	Success: TRUE.
 *	Failure: FALSE.
Alexandre Julliard's avatar
Alexandre Julliard committed
118
 */
119 120
BOOL WINAPI VirtualFree( LPVOID addr, SIZE_T size, DWORD type )
{
121
    return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
Alexandre Julliard's avatar
Alexandre Julliard committed
122 123 124 125
}


/***********************************************************************
126
 *             VirtualFreeEx   (KERNEL32.@)
127 128 129 130 131 132 133 134
 *
 * 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
135 136
 *
 * RETURNS
137 138
 *	Success: TRUE.
 *	Failure: FALSE.
Alexandre Julliard's avatar
Alexandre Julliard committed
139
 */
140
BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type )
141 142 143 144
{
    NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
145 146 147 148
}


/***********************************************************************
149
 *             VirtualLock   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
150
 *
151 152 153 154 155
 * 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
156 157
 *
 * RETURNS
158 159 160 161 162 163
 *	Success: TRUE.
 *	Failure: FALSE.
 *
 * NOTES
 *	Always returns TRUE.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
164
 */
165
BOOL WINAPI VirtualLock( LPVOID addr, SIZE_T size )
166
{
167 168 169
    NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
170 171 172
}


173
/***********************************************************************
174
 *             VirtualUnlock   (KERNEL32.@)
175
 *
176 177 178 179 180
 * 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.
181
 *
182
 * RETURNS
183 184 185 186 187 188
 *	Success: TRUE.
 *	Failure: FALSE.
 *
 * NOTES
 *	Always returns TRUE.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
189
 */
190
BOOL WINAPI VirtualUnlock( LPVOID addr, SIZE_T size )
Alexandre Julliard's avatar
Alexandre Julliard committed
191
{
192 193 194
    NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
195 196 197
}


198
/***********************************************************************
199
 *             VirtualProtect   (KERNEL32.@)
200 201 202 203 204 205 206 207
 *
 * 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
208 209
 *
 * RETURNS
210 211
 *	Success: TRUE.
 *	Failure: FALSE.
212
 */
213 214
BOOL WINAPI VirtualProtect( LPVOID addr, SIZE_T size, DWORD new_prot, LPDWORD old_prot)
{
215
    return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
Alexandre Julliard's avatar
Alexandre Julliard committed
216 217 218 219
}


/***********************************************************************
220
 *             VirtualProtectEx   (KERNEL32.@)
221
 *
222
 * Changes the access protection on a region of committed pages in the
223 224 225 226 227 228 229 230
 * 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
231 232
 *
 * RETURNS
233 234
 *	Success: TRUE.
 *	Failure: FALSE.
Alexandre Julliard's avatar
Alexandre Julliard committed
235
 */
236 237
BOOL WINAPI VirtualProtectEx( HANDLE process, LPVOID addr, SIZE_T size,
    DWORD new_prot, LPDWORD old_prot )
238
{
239 240 241
    NTSTATUS status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
242 243 244 245
}


/***********************************************************************
246
 *             VirtualQuery   (KERNEL32.@)
247 248 249 250 251 252 253
 *
 * 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
254 255
 *
 * RETURNS
256 257
 *	Number of bytes returned in information buffer or 0 if
 *	addr >= 0xc0000000 (kernel space).
Alexandre Julliard's avatar
Alexandre Julliard committed
258
 */
259 260 261
SIZE_T WINAPI VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info,
    SIZE_T len )
{
262
    return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
Alexandre Julliard's avatar
Alexandre Julliard committed
263 264 265 266
}


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

    if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
Alexandre Julliard's avatar
Alexandre Julliard committed
288
    {
289 290
        SetLastError( RtlNtStatusToDosError(status) );
        ret = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
291
    }
292
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
293 294 295 296
}


/***********************************************************************
297
 *             CreateFileMappingA   (KERNEL32.@)
298 299 300 301 302 303 304 305 306 307
 *
 * 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
308 309
 *
 * RETURNS
310 311
 *	Success: Handle.
 *	Failure: NULL. Mapping object does not exist.
Alexandre Julliard's avatar
Alexandre Julliard committed
312
 */
313 314
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
315
{
316
    WCHAR buffer[MAX_PATH];
Alexandre Julliard's avatar
Alexandre Julliard committed
317

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

320
    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
321 322 323 324
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
325
    return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
326 327 328 329
}


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

340
    HANDLE ret;
341 342 343 344 345 346 347
    NTSTATUS status;
    DWORD access, sec_type;
    LARGE_INTEGER size;

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

349
    switch(protect)
350
    {
351
    case 0:
352 353
        protect = PAGE_READONLY;  /* Win9x compatibility */
        /* fall through */
354 355
    case PAGE_READONLY:
    case PAGE_WRITECOPY:
356
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE;
357 358
        break;
    case PAGE_READWRITE:
359
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE;
360
        break;
361
    case PAGE_EXECUTE:
362
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT;
363 364 365
        break;
    case PAGE_EXECUTE_READ:
    case PAGE_EXECUTE_WRITECOPY:
366
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT;
367 368
        break;
    case PAGE_EXECUTE_READWRITE:
369
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT;
370
        break;
371 372
    default:
        SetLastError( ERROR_INVALID_PARAMETER );
373 374 375
        return 0;
    }

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

386 387
    size.u.LowPart  = size_low;
    size.u.HighPart = size_high;
388

389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    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 );

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


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

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

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


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

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

472 473
    if (access == FILE_MAP_COPY) access = SECTION_MAP_READ;
    access |= SECTION_QUERY;
474 475 476 477 478 479

    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;
    }
480 481

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


/***********************************************************************
491
 *             MapViewOfFile   (KERNEL32.@)
492 493 494 495 496 497 498 499 500
 *
 * 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
501 502
 *
 * RETURNS
503 504
 *	Success: Starting address of mapped view.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
505
 */
506 507 508
LPVOID WINAPI MapViewOfFile( HANDLE mapping, DWORD access,
    DWORD offset_high, DWORD offset_low, SIZE_T count )
{
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510 511 512 513 514
    return MapViewOfFileEx( mapping, access, offset_high,
                            offset_low, count, NULL );
}


/***********************************************************************
515
 *             MapViewOfFileEx   (KERNEL32.@)
516 517 518 519 520 521 522 523 524 525
 *
 * 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
526 527
 *
 * RETURNS
528 529
 *	Success: Starting address of mapped view.
 *	Failure: NULL.
Alexandre Julliard's avatar
Alexandre Julliard committed
530
 */
531 532 533
LPVOID WINAPI MapViewOfFileEx( HANDLE handle, DWORD access,
    DWORD offset_high, DWORD offset_low, SIZE_T count, LPVOID addr )
{
534 535 536 537
    NTSTATUS status;
    LARGE_INTEGER offset;
    ULONG protect;

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

    if (access & FILE_MAP_WRITE) protect = PAGE_READWRITE;
    else if (access & FILE_MAP_COPY) protect = PAGE_WRITECOPY;
543
    else protect = PAGE_READONLY;
Alexandre Julliard's avatar
Alexandre Julliard committed
544

545 546
    if (access & FILE_MAP_EXECUTE) protect <<= 4;

547
    if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
548
                                      &count, ViewShare, 0, protect )) < 0)
549
    {
550 551
        SetLastError( RtlNtStatusToDosError(status) );
        addr = NULL;
552
    }
553 554
    return addr;
}
555

556

557 558
/***********************************************************************
 *             UnmapViewOfFile   (KERNEL32.@)
559
 *
560 561
 * Unmaps a mapped view of a file.
 *
562 563
 * PARAMS
 *  addr [I] Address where mapped view begins.
564 565
 *
 * RETURNS
566 567 568
 *	Success: TRUE.
 *	Failure: FALSE.
 *
569
 */
570
BOOL WINAPI UnmapViewOfFile( LPCVOID addr )
571
{
572
    NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), (void *)addr );
573 574 575
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
}
576

Alexandre Julliard's avatar
Alexandre Julliard committed
577

578 579
/***********************************************************************
 *             FlushViewOfFile   (KERNEL32.@)
580 581 582 583 584 585
 *
 * 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.
586 587
 *
 * RETURNS
588 589
 *	Success: TRUE.
 *	Failure: FALSE.
590
 */
591
BOOL WINAPI FlushViewOfFile( LPCVOID base, SIZE_T size )
592 593 594
{
    NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
    if (status)
Alexandre Julliard's avatar
Alexandre Julliard committed
595
    {
596 597
        if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
        else SetLastError( RtlNtStatusToDosError(status) );
Alexandre Julliard's avatar
Alexandre Julliard committed
598
    }
599 600
    return !status;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
601

602

603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629
/***********************************************************************
 *             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;
}


630 631 632
/***********************************************************************
 *             IsBadReadPtr   (KERNEL32.@)
 *
633 634
 * Check for read access on a memory block.
 *
635 636 637
 * ptr  [I] Address of memory block.
 * size [I] Size of block.
 *
638
 * RETURNS
639 640
 *  Success: TRUE.
 *	Failure: FALSE. Process has read access to entire block.
641
 */
642
BOOL WINAPI IsBadReadPtr( LPCVOID ptr, UINT size )
643 644
{
    if (!size) return FALSE;  /* handle 0 size case w/o reference */
645 646
    if (!ptr) return TRUE;
    
647 648
    if (!page_size) page_size = getpagesize();
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
649
    {
650 651 652 653 654
        volatile const char *p = ptr;
        char dummy;
        UINT count = size;

        while (count > page_size)
Alexandre Julliard's avatar
Alexandre Julliard committed
655
        {
656 657 658
            dummy = *p;
            p += page_size;
            count -= page_size;
Alexandre Julliard's avatar
Alexandre Julliard committed
659
        }
660 661
        dummy = p[0];
        dummy = p[count - 1];
Alexandre Julliard's avatar
Alexandre Julliard committed
662
    }
663
    __EXCEPT_PAGE_FAULT
664 665 666 667
    {
        TRACE_(seh)("%p caused page fault during read\n", ptr);
        return TRUE;
    }
668 669 670
    __ENDTRY
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
671

672

673 674 675
/***********************************************************************
 *             IsBadWritePtr   (KERNEL32.@)
 *
676 677
 * Check for write access on a memory block.
 *
678 679 680 681
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block in bytes.
 *
682
 * RETURNS
683 684
 *  Success: TRUE.
 *	Failure: FALSE. Process has write access to entire block.
685
 */
686
BOOL WINAPI IsBadWritePtr( LPVOID ptr, UINT size )
687 688
{
    if (!size) return FALSE;  /* handle 0 size case w/o reference */
689 690
    if (!ptr) return TRUE;
    
691 692 693 694 695
    if (!page_size) page_size = getpagesize();
    __TRY
    {
        volatile char *p = ptr;
        UINT count = size;
696

697 698 699 700 701 702 703 704 705
        while (count > page_size)
        {
            *p |= 0;
            p += page_size;
            count -= page_size;
        }
        p[0] |= 0;
        p[count - 1] |= 0;
    }
706
    __EXCEPT_PAGE_FAULT
707 708 709 710
    {
        TRACE_(seh)("%p caused page fault during write\n", ptr);
        return TRUE;
    }
711 712 713
    __ENDTRY
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
714 715


716 717
/***********************************************************************
 *             IsBadHugeReadPtr   (KERNEL32.@)
718 719 720
 *
 * Check for read access on a memory block.
 *
721 722 723 724
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block.
 *
725
 * RETURNS
726 727
 *  Success: TRUE.
 *	Failure: FALSE. Process has read access to entire block.
728
 */
729 730
BOOL WINAPI IsBadHugeReadPtr( LPCVOID ptr, UINT size )
{
731 732
    return IsBadReadPtr( ptr, size );
}
Alexandre Julliard's avatar
Alexandre Julliard committed
733 734


735 736
/***********************************************************************
 *             IsBadHugeWritePtr   (KERNEL32.@)
737 738 739
 *
 * Check for write access on a memory block.
 *
740 741 742 743
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block.
 *
744
 * RETURNS
745 746
 *  Success: TRUE.
 *	Failure: FALSE. Process has write access to entire block.
747
 */
748 749
BOOL WINAPI IsBadHugeWritePtr( LPVOID ptr, UINT size )
{
750
    return IsBadWritePtr( ptr, size );
Alexandre Julliard's avatar
Alexandre Julliard committed
751 752 753
}


Alexandre Julliard's avatar
Alexandre Julliard committed
754
/***********************************************************************
755
 *             IsBadCodePtr   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
756
 *
757 758
 * Check for read access on a memory address.
 *
759 760 761
 * PARAMS
 *  ptr [I] Address of function.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
762
 * RETURNS
763 764
 *	Success: TRUE.
 *	Failure: FALSE. Process has read access to specified memory.
Alexandre Julliard's avatar
Alexandre Julliard committed
765
 */
766
BOOL WINAPI IsBadCodePtr( FARPROC ptr )
767 768 769
{
    return IsBadReadPtr( ptr, 1 );
}
Alexandre Julliard's avatar
Alexandre Julliard committed
770 771


772 773 774
/***********************************************************************
 *             IsBadStringPtrA   (KERNEL32.@)
 *
775 776
 * Check for read access on a range of memory pointed to by a string pointer.
 *
777 778 779 780
 * PARAMS
 *  str [I] Address of string.
 *  max [I] Maximum size of string.
 *
781
 * RETURNS
782 783
 *	Success: TRUE.
 *	Failure: FALSE. Read access to all bytes in string.
784
 */
785
BOOL WINAPI IsBadStringPtrA( LPCSTR str, UINT max )
786
{
787 788
    if (!str) return TRUE;
    
789
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
790
    {
791 792
        volatile const char *p = str;
        while (p != str + max) if (!*p++) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
793
    }
794
    __EXCEPT_PAGE_FAULT
795 796 797 798
    {
        TRACE_(seh)("%p caused page fault during read\n", str);
        return TRUE;
    }
799
    __ENDTRY
Alexandre Julliard's avatar
Alexandre Julliard committed
800 801
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
802

Alexandre Julliard's avatar
Alexandre Julliard committed
803

Alexandre Julliard's avatar
Alexandre Julliard committed
804
/***********************************************************************
805
 *             IsBadStringPtrW   (KERNEL32.@)
806
 *
807
 * See IsBadStringPtrA.
Alexandre Julliard's avatar
Alexandre Julliard committed
808
 */
809 810
BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT max )
{
811 812
    if (!str) return TRUE;
    
813
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
814
    {
815 816
        volatile const WCHAR *p = str;
        while (p != str + max) if (!*p++) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
817
    }
818
    __EXCEPT_PAGE_FAULT
819 820 821 822
    {
        TRACE_(seh)("%p caused page fault during read\n", str);
        return TRUE;
    }
823 824
    __ENDTRY
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
825
}