virtual.c 24.2 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 "psapi.h"
43
#include "wine/exception.h"
44
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
45

46 47
#include "kernel_private.h"

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

51
static unsigned int page_size;
52

Alexandre Julliard's avatar
Alexandre Julliard committed
53 54

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


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

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


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


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


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


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


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


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


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


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

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


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

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

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


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

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

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

351 352 353
    /* Win9x compatibility */
    if (!protect && (GetVersion() & 0x80000000)) protect = PAGE_READONLY;

354
    switch(protect)
355
    {
356 357
    case PAGE_READONLY:
    case PAGE_WRITECOPY:
358
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE;
359 360
        break;
    case PAGE_READWRITE:
361
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE;
362
        break;
363 364
    case PAGE_EXECUTE_READ:
    case PAGE_EXECUTE_WRITECOPY:
365
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_EXECUTE_EXPLICIT;
366 367
        break;
    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 371
    default:
        SetLastError( ERROR_INVALID_PARAMETER );
372 373 374
        return 0;
    }

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

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

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

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


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

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

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


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

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

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

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

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


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


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

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

541 542
    exec = access & FILE_MAP_EXECUTE;
    access &= ~FILE_MAP_EXECUTE;
Alexandre Julliard's avatar
Alexandre Julliard committed
543

544 545 546 547 548 549 550
    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;
551

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

561

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

Alexandre Julliard's avatar
Alexandre Julliard committed
582

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

607

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
/***********************************************************************
 *             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;
}


635 636 637
/***********************************************************************
 *             IsBadReadPtr   (KERNEL32.@)
 *
638 639
 * Check for read access on a memory block.
 *
640 641 642
 * ptr  [I] Address of memory block.
 * size [I] Size of block.
 *
643
 * RETURNS
644 645
 *  Success: TRUE.
 *	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 651
    if (!ptr) return TRUE;
    
652 653
    if (!page_size) page_size = getpagesize();
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
654
    {
655
        volatile const char *p = ptr;
656
        char dummy __attribute__((unused));
657 658 659
        UINT count = size;

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

677

678 679 680
/***********************************************************************
 *             IsBadWritePtr   (KERNEL32.@)
 *
681 682
 * Check for write access on a memory block.
 *
683 684 685 686
 * PARAMS
 *  ptr  [I] Address of memory block.
 *  size [I] Size of block in bytes.
 *
687
 * RETURNS
688 689
 *  Success: TRUE.
 *	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 695
    if (!ptr) return TRUE;
    
696 697 698 699 700
    if (!page_size) page_size = getpagesize();
    __TRY
    {
        volatile char *p = ptr;
        UINT count = size;
701

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


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


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


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


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

Alexandre Julliard's avatar
Alexandre Julliard committed
808

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

/***********************************************************************
 *           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;
}
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874

/***********************************************************************
 *           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;
}
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903

/***********************************************************************
 *           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;
}