virtual.c 19.3 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 18
 *
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 25 26 27
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
28 29
#ifdef HAVE_UNISTD_H
# include <unistd.h>
30
#endif
31

32 33
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
34
#include "winnls.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
35
#include "winbase.h"
36
#include "winternl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
37
#include "winerror.h"
38
#include "wine/exception.h"
39
#include "excpt.h"
40
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
41

42
WINE_DEFAULT_DEBUG_CHANNEL(virtual);
Alexandre Julliard's avatar
Alexandre Julliard committed
43

44
static unsigned int page_size;
45 46 47 48 49 50 51 52 53

/* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault)
{
    if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
        return EXCEPTION_EXECUTE_HANDLER;
    return EXCEPTION_CONTINUE_SEARCH;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
54 55

/***********************************************************************
56 57
 *             VirtualAlloc   (KERNEL32.@)
 * Reserves or commits a region of pages in virtual address space
Alexandre Julliard's avatar
Alexandre Julliard committed
58 59
 *
 * RETURNS
60
 *	Base address of allocated region of pages
Alexandre Julliard's avatar
Alexandre Julliard committed
61
 *	NULL: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
62
 */
63 64
LPVOID WINAPI VirtualAlloc(
              LPVOID addr,  /* [in] Address of region to reserve or commit */
65
              SIZE_T size,  /* [in] Size of region */
66 67
              DWORD type,   /* [in] Type of allocation */
              DWORD protect)/* [in] Type of access protection */
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.
Alexandre Julliard's avatar
Alexandre Julliard committed
77
 */
78 79 80
LPVOID WINAPI VirtualAllocEx(
              HANDLE hProcess, /* [in] Handle of process to do mem operation */
              LPVOID addr,     /* [in] Address of region to reserve or commit */
81
              SIZE_T size,     /* [in] Size of region */
82 83
              DWORD type,      /* [in] Type of allocation */
              DWORD protect )  /* [in] Type of access protection */
Alexandre Julliard's avatar
Alexandre Julliard committed
84
{
85 86
    LPVOID ret;
    NTSTATUS status;
Alexandre Julliard's avatar
Alexandre Julliard committed
87

88
    if ((status = NtAllocateVirtualMemory( hProcess, &ret, addr, &size, type, protect )))
Alexandre Julliard's avatar
Alexandre Julliard committed
89
    {
90 91
        SetLastError( RtlNtStatusToDosError(status) );
        ret = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
92
    }
93
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
94 95 96 97
}


/***********************************************************************
98 99
 *             VirtualFree   (KERNEL32.@)
 * Release or decommits a region of pages in virtual address space.
Alexandre Julliard's avatar
Alexandre Julliard committed
100 101
 *
 * RETURNS
102 103
 *	TRUE: Success
 *	FALSE: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
104
 */
105 106
BOOL WINAPI VirtualFree(
              LPVOID addr, /* [in] Address of region of committed pages */
107
              SIZE_T size, /* [in] Size of region */
108
              DWORD type   /* [in] Type of operation */
Alexandre Julliard's avatar
Alexandre Julliard committed
109
) {
110
    return VirtualFreeEx( GetCurrentProcess(), addr, size, type );
Alexandre Julliard's avatar
Alexandre Julliard committed
111 112 113 114
}


/***********************************************************************
115 116
 *             VirtualFreeEx   (KERNEL32.@)
 * Release or decommits a region of pages in virtual address space.
Alexandre Julliard's avatar
Alexandre Julliard committed
117 118
 *
 * RETURNS
119 120
 *	TRUE: Success
 *	FALSE: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
121
 */
122
BOOL WINAPI VirtualFreeEx( HANDLE process, LPVOID addr, SIZE_T size, DWORD type )
123 124 125 126
{
    NTSTATUS status = NtFreeVirtualMemory( process, &addr, &size, type );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
127 128 129 130
}


/***********************************************************************
131 132
 *             VirtualLock   (KERNEL32.@)
 * Locks the specified region of virtual address space
Alexandre Julliard's avatar
Alexandre Julliard committed
133
 *
134 135
 * NOTE
 *	Always returns TRUE
Alexandre Julliard's avatar
Alexandre Julliard committed
136 137 138 139
 *
 * RETURNS
 *	TRUE: Success
 *	FALSE: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
140
 */
141
BOOL WINAPI VirtualLock( LPVOID addr, /* [in] Address of first byte of range to lock */
142
                         SIZE_T size ) /* [in] Number of bytes in range to lock */
143
{
144 145 146
    NTSTATUS status = NtLockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
147 148 149
}


150
/***********************************************************************
151 152
 *             VirtualUnlock   (KERNEL32.@)
 * Unlocks a range of pages in the virtual address space
153
 *
154 155
 * NOTE
 *	Always returns TRUE
156
 *
157 158 159
 * RETURNS
 *	TRUE: Success
 *	FALSE: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
160
 */
161
BOOL WINAPI VirtualUnlock( LPVOID addr, /* [in] Address of first byte of range */
162
                           SIZE_T size ) /* [in] Number of bytes in range */
Alexandre Julliard's avatar
Alexandre Julliard committed
163
{
164 165 166
    NTSTATUS status = NtUnlockVirtualMemory( GetCurrentProcess(), &addr, &size, 1 );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
167 168 169
}


170
/***********************************************************************
171 172
 *             VirtualProtect   (KERNEL32.@)
 * Changes the access protection on a region of committed pages
Alexandre Julliard's avatar
Alexandre Julliard committed
173 174 175
 *
 * RETURNS
 *	TRUE: Success
176 177 178 179
 *	FALSE: Failure
 */
BOOL WINAPI VirtualProtect(
              LPVOID addr,     /* [in] Address of region of committed pages */
180
              SIZE_T size,     /* [in] Size of region */
181 182
              DWORD new_prot,  /* [in] Desired access protection */
              LPDWORD old_prot /* [out] Address of variable to get old protection */
Alexandre Julliard's avatar
Alexandre Julliard committed
183
) {
184
    return VirtualProtectEx( GetCurrentProcess(), addr, size, new_prot, old_prot );
Alexandre Julliard's avatar
Alexandre Julliard committed
185 186 187 188
}


/***********************************************************************
189 190 191
 *             VirtualProtectEx   (KERNEL32.@)
 * Changes the access protection on a region of committed pages in the
 * virtual address space of a specified process
Alexandre Julliard's avatar
Alexandre Julliard committed
192 193
 *
 * RETURNS
194 195
 *	TRUE: Success
 *	FALSE: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
196
 */
197 198 199
BOOL WINAPI VirtualProtectEx(
              HANDLE process,  /* [in]  Handle of process */
              LPVOID addr,     /* [in]  Address of region of committed pages */
200
              SIZE_T size,     /* [in]  Size of region */
201 202
              DWORD new_prot,  /* [in]  Desired access protection */
              LPDWORD old_prot /* [out] Address of variable to get old protection */ )
203
{
204 205 206
    NTSTATUS status = NtProtectVirtualMemory( process, &addr, &size, new_prot, old_prot );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
Alexandre Julliard's avatar
Alexandre Julliard committed
207 208 209 210
}


/***********************************************************************
211 212
 *             VirtualQuery   (KERNEL32.@)
 * Provides info about a range of pages in virtual address space
Alexandre Julliard's avatar
Alexandre Julliard committed
213 214
 *
 * RETURNS
215 216
 *	Number of bytes returned in information buffer
 *	or 0 if addr is >= 0xc0000000 (kernel space).
Alexandre Julliard's avatar
Alexandre Julliard committed
217
 */
218
SIZE_T WINAPI VirtualQuery(
219
             LPCVOID addr,                    /* [in]  Address of region */
220
             PMEMORY_BASIC_INFORMATION info,  /* [out] Address of info buffer */
221
             SIZE_T len                       /* [in]  Size of buffer */
222 223
) {
    return VirtualQueryEx( GetCurrentProcess(), addr, info, len );
Alexandre Julliard's avatar
Alexandre Julliard committed
224 225 226 227
}


/***********************************************************************
228 229 230 231 232 233
 *             VirtualQueryEx   (KERNEL32.@)
 * Provides info about a range of pages in virtual address space of a
 * specified process
 *
 * RETURNS
 *	Number of bytes returned in information buffer
Alexandre Julliard's avatar
Alexandre Julliard committed
234
 */
235
SIZE_T WINAPI VirtualQueryEx(
236 237
             HANDLE process,                  /* [in] Handle of process */
             LPCVOID addr,                    /* [in] Address of region */
238
             PMEMORY_BASIC_INFORMATION info,  /* [out] Address of info buffer */
239
             SIZE_T len                       /* [in] Size of buffer */ )
Alexandre Julliard's avatar
Alexandre Julliard committed
240
{
241 242 243 244
    DWORD ret;
    NTSTATUS status;

    if ((status = NtQueryVirtualMemory( process, addr, MemoryBasicInformation, info, len, &ret )))
Alexandre Julliard's avatar
Alexandre Julliard committed
245
    {
246 247
        SetLastError( RtlNtStatusToDosError(status) );
        ret = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
248
    }
249
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
250 251 252 253
}


/***********************************************************************
254
 *             CreateFileMappingA   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
255 256 257
 * Creates a named or unnamed file-mapping object for the specified file
 *
 * RETURNS
Alexandre Julliard's avatar
Alexandre Julliard committed
258 259
 *	Handle: Success
 *	0: Mapping object does not exist
Alexandre Julliard's avatar
Alexandre Julliard committed
260
 *	NULL: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
261
 */
262
HANDLE WINAPI CreateFileMappingA(
263
                HANDLE hFile,   /* [in] Handle of file to map */
Alexandre Julliard's avatar
Alexandre Julliard committed
264
                SECURITY_ATTRIBUTES *sa, /* [in] Optional security attributes*/
Alexandre Julliard's avatar
Alexandre Julliard committed
265 266 267
                DWORD protect,   /* [in] Protection for mapping object */
                DWORD size_high, /* [in] High-order 32 bits of object size */
                DWORD size_low,  /* [in] Low-order 32 bits of object size */
Alexandre Julliard's avatar
Alexandre Julliard committed
268 269
                LPCSTR name      /* [in] Name of file-mapping object */ )
{
270
    WCHAR buffer[MAX_PATH];
Alexandre Julliard's avatar
Alexandre Julliard committed
271

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

274
    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
275 276 277 278
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
279
    return CreateFileMappingW( hFile, sa, protect, size_high, size_low, buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
280 281 282 283
}


/***********************************************************************
284
 *             CreateFileMappingW   (KERNEL32.@)
285
 * See CreateFileMappingA
Alexandre Julliard's avatar
Alexandre Julliard committed
286
 */
287 288
HANDLE WINAPI CreateFileMappingW( HANDLE hFile, LPSECURITY_ATTRIBUTES sa,
                                  DWORD protect, DWORD size_high,
289
                                  DWORD size_low, LPCWSTR name )
Alexandre Julliard's avatar
Alexandre Julliard committed
290
{
291 292
    static const int sec_flags = SEC_FILE | SEC_IMAGE | SEC_RESERVE | SEC_COMMIT | SEC_NOCACHE;

293
    HANDLE ret;
294 295 296 297 298 299 300 301 302 303 304 305
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING nameW;
    NTSTATUS status;
    DWORD access, sec_type;
    LARGE_INTEGER size;

    attr.Length                   = sizeof(attr);
    attr.RootDirectory            = 0;
    attr.ObjectName               = NULL;
    attr.Attributes               = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
    attr.SecurityDescriptor       = sa ? sa->lpSecurityDescriptor : NULL;
    attr.SecurityQualityOfService = NULL;
306

307 308 309 310 311
    if (name)
    {
        RtlInitUnicodeString( &nameW, name );
        attr.ObjectName = &nameW;
    }
312

313 314 315
    sec_type = protect & sec_flags;
    protect &= ~sec_flags;
    if (!sec_type) sec_type = SEC_COMMIT;
316

317
    switch(protect)
318
    {
319 320 321 322 323 324 325 326 327 328
    case 0:
    case PAGE_READONLY:
    case PAGE_WRITECOPY:
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ;
        break;
    case PAGE_READWRITE:
        access = STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE;
        break;
    default:
        SetLastError( ERROR_INVALID_PARAMETER );
329 330 331
        return 0;
    }

332
    if (hFile == INVALID_HANDLE_VALUE)
333
    {
334 335
        hFile = 0;
        if (!size_low && !size_high)
336 337 338 339 340 341
        {
            SetLastError( ERROR_INVALID_PARAMETER );
            return 0;
        }
    }

342 343
    size.s.LowPart  = size_low;
    size.s.HighPart = size_high;
344

345 346
    status = NtCreateSection( &ret, access, &attr, &size, protect, sec_type, hFile );
    SetLastError( RtlNtStatusToDosError(status) );
347
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
348 349 350 351
}


/***********************************************************************
352
 *             OpenFileMappingA   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
353
 * Opens a named file-mapping object.
Alexandre Julliard's avatar
Alexandre Julliard committed
354 355
 *
 * RETURNS
Alexandre Julliard's avatar
Alexandre Julliard committed
356
 *	Handle: Success
Alexandre Julliard's avatar
Alexandre Julliard committed
357
 *	NULL: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
358
 */
359
HANDLE WINAPI OpenFileMappingA(
Alexandre Julliard's avatar
Alexandre Julliard committed
360
                DWORD access,   /* [in] Access mode */
361
                BOOL inherit, /* [in] Inherit flag */
362 363
                LPCSTR name )   /* [in] Name of file-mapping object */
{
364 365 366 367 368
    WCHAR buffer[MAX_PATH];

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

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
369 370 371 372
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
373
    return OpenFileMappingW( access, inherit, buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
374 375 376 377
}


/***********************************************************************
378
 *             OpenFileMappingW   (KERNEL32.@)
379
 * See OpenFileMappingA
Alexandre Julliard's avatar
Alexandre Julliard committed
380
 */
381
HANDLE WINAPI OpenFileMappingW( DWORD access, BOOL inherit, LPCWSTR name)
Alexandre Julliard's avatar
Alexandre Julliard committed
382
{
383 384
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING nameW;
385
    HANDLE ret;
386 387 388
    NTSTATUS status;

    if (!name)
389
    {
390
        SetLastError( ERROR_INVALID_PARAMETER );
391 392
        return 0;
    }
393 394 395 396 397 398 399 400 401 402 403
    attr.Length = sizeof(attr);
    attr.RootDirectory = 0;
    attr.ObjectName = &nameW;
    attr.Attributes = inherit ? OBJ_INHERIT : 0;
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;
    RtlInitUnicodeString( &nameW, name );

    if (access == FILE_MAP_COPY) access = FILE_MAP_READ;

    if ((status = NtOpenSection( &ret, access, &attr )))
404
    {
405 406
        SetLastError( RtlNtStatusToDosError(status) );
        ret = 0;
407 408
    }
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
409 410 411 412
}


/***********************************************************************
413
 *             MapViewOfFile   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
414 415 416 417 418
 * Maps a view of a file into the address space
 *
 * RETURNS
 *	Starting address of mapped view
 *	NULL: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
419
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
420
LPVOID WINAPI MapViewOfFile(
421
              HANDLE mapping,  /* [in] File-mapping object to map */
Alexandre Julliard's avatar
Alexandre Julliard committed
422 423 424
              DWORD access,      /* [in] Access mode */
              DWORD offset_high, /* [in] High-order 32 bits of file offset */
              DWORD offset_low,  /* [in] Low-order 32 bits of file offset */
425
              SIZE_T count       /* [in] Number of bytes to map */
Alexandre Julliard's avatar
Alexandre Julliard committed
426
) {
Alexandre Julliard's avatar
Alexandre Julliard committed
427 428 429 430 431 432
    return MapViewOfFileEx( mapping, access, offset_high,
                            offset_low, count, NULL );
}


/***********************************************************************
433
 *             MapViewOfFileEx   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
434 435 436 437 438
 * Maps a view of a file into the address space
 *
 * RETURNS
 *	Starting address of mapped view
 *	NULL: Failure
Alexandre Julliard's avatar
Alexandre Julliard committed
439
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
440
LPVOID WINAPI MapViewOfFileEx(
441
              HANDLE handle,   /* [in] File-mapping object to map */
Alexandre Julliard's avatar
Alexandre Julliard committed
442 443 444
              DWORD access,      /* [in] Access mode */
              DWORD offset_high, /* [in] High-order 32 bits of file offset */
              DWORD offset_low,  /* [in] Low-order 32 bits of file offset */
445
              SIZE_T count,      /* [in] Number of bytes to map */
Alexandre Julliard's avatar
Alexandre Julliard committed
446
              LPVOID addr        /* [in] Suggested starting address for mapped view */
Alexandre Julliard's avatar
Alexandre Julliard committed
447
) {
448 449 450 451 452 453 454 455 456 457 458
    NTSTATUS status;
    LARGE_INTEGER offset;
    ULONG protect;

    offset.s.LowPart  = offset_low;
    offset.s.HighPart = offset_high;

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

460 461
    if ((status = NtMapViewOfSection( handle, GetCurrentProcess(), &addr, 0, 0, &offset,
                                      &count, ViewShare, 0, protect )))
462
    {
463 464
        SetLastError( RtlNtStatusToDosError(status) );
        addr = NULL;
465
    }
466 467
    return addr;
}
468

469

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
/***********************************************************************
 *             UnmapViewOfFile   (KERNEL32.@)
 * Unmaps a mapped view of a file.
 *
 * NOTES
 *	Should addr be an LPCVOID?
 *
 * RETURNS
 *	TRUE: Success
 *	FALSE: Failure
 */
BOOL WINAPI UnmapViewOfFile( LPVOID addr ) /* [in] Address where mapped view begins */
{
    NTSTATUS status = NtUnmapViewOfSection( GetCurrentProcess(), addr );
    if (status) SetLastError( RtlNtStatusToDosError(status) );
    return !status;
}
487

Alexandre Julliard's avatar
Alexandre Julliard committed
488

489 490 491 492 493 494 495 496 497
/***********************************************************************
 *             FlushViewOfFile   (KERNEL32.@)
 * Writes to the disk a byte range within a mapped view of a file
 *
 * RETURNS
 *	TRUE: Success
 *	FALSE: Failure
 */
BOOL WINAPI FlushViewOfFile( LPCVOID base,  /* [in] Start address of byte range to flush */
498
                             SIZE_T size )   /* [in] Number of bytes in range */
499 500 501
{
    NTSTATUS status = NtFlushVirtualMemory( GetCurrentProcess(), &base, &size, 0 );
    if (status)
Alexandre Julliard's avatar
Alexandre Julliard committed
502
    {
503 504
        if (status == STATUS_NOT_MAPPED_DATA) status = STATUS_SUCCESS;
        else SetLastError( RtlNtStatusToDosError(status) );
Alexandre Julliard's avatar
Alexandre Julliard committed
505
    }
506 507
    return !status;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
508

509 510 511 512 513 514 515 516 517 518 519 520 521 522 523

/***********************************************************************
 *             IsBadReadPtr   (KERNEL32.@)
 *
 * RETURNS
 *	FALSE: Process has read access to entire block
 *      TRUE: Otherwise
 */
BOOL WINAPI IsBadReadPtr(
              LPCVOID ptr, /* [in] Address of memory block */
              UINT size )  /* [in] Size of block */
{
    if (!size) return FALSE;  /* handle 0 size case w/o reference */
    if (!page_size) page_size = getpagesize();
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
524
    {
525 526 527 528 529
        volatile const char *p = ptr;
        char dummy;
        UINT count = size;

        while (count > page_size)
Alexandre Julliard's avatar
Alexandre Julliard committed
530
        {
531 532 533
            dummy = *p;
            p += page_size;
            count -= page_size;
Alexandre Julliard's avatar
Alexandre Julliard committed
534
        }
535 536
        dummy = p[0];
        dummy = p[count - 1];
Alexandre Julliard's avatar
Alexandre Julliard committed
537
    }
538 539 540 541
    __EXCEPT(page_fault) { return TRUE; }
    __ENDTRY
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
542

543

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
/***********************************************************************
 *             IsBadWritePtr   (KERNEL32.@)
 *
 * RETURNS
 *	FALSE: Process has write access to entire block
 *      TRUE: Otherwise
 */
BOOL WINAPI IsBadWritePtr(
              LPVOID ptr, /* [in] Address of memory block */
              UINT size ) /* [in] Size of block in bytes */
{
    if (!size) return FALSE;  /* handle 0 size case w/o reference */
    if (!page_size) page_size = getpagesize();
    __TRY
    {
        volatile char *p = ptr;
        UINT count = size;
561

562 563 564 565 566 567 568 569 570 571 572 573 574
        while (count > page_size)
        {
            *p |= 0;
            p += page_size;
            count -= page_size;
        }
        p[0] |= 0;
        p[count - 1] |= 0;
    }
    __EXCEPT(page_fault) { return TRUE; }
    __ENDTRY
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
575 576


577 578 579 580 581 582 583 584 585 586 587 588
/***********************************************************************
 *             IsBadHugeReadPtr   (KERNEL32.@)
 * RETURNS
 *	FALSE: Process has read access to entire block
 *      TRUE: Otherwise
 */
BOOL WINAPI IsBadHugeReadPtr(
              LPCVOID ptr, /* [in] Address of memory block */
              UINT size  /* [in] Size of block */
) {
    return IsBadReadPtr( ptr, size );
}
Alexandre Julliard's avatar
Alexandre Julliard committed
589 590


591 592 593 594 595 596 597 598 599 600 601
/***********************************************************************
 *             IsBadHugeWritePtr   (KERNEL32.@)
 * RETURNS
 *	FALSE: Process has write access to entire block
 *      TRUE: Otherwise
 */
BOOL WINAPI IsBadHugeWritePtr(
              LPVOID ptr, /* [in] Address of memory block */
              UINT size /* [in] Size of block */
) {
    return IsBadWritePtr( ptr, size );
Alexandre Julliard's avatar
Alexandre Julliard committed
602 603 604
}


Alexandre Julliard's avatar
Alexandre Julliard committed
605
/***********************************************************************
606
 *             IsBadCodePtr   (KERNEL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
607 608
 *
 * RETURNS
609 610
 *	FALSE: Process has read access to specified memory
 *	TRUE: Otherwise
Alexandre Julliard's avatar
Alexandre Julliard committed
611
 */
612 613 614 615
BOOL WINAPI IsBadCodePtr( FARPROC ptr ) /* [in] Address of function */
{
    return IsBadReadPtr( ptr, 1 );
}
Alexandre Julliard's avatar
Alexandre Julliard committed
616 617


618 619 620 621 622 623 624 625 626 627 628 629
/***********************************************************************
 *             IsBadStringPtrA   (KERNEL32.@)
 *
 * RETURNS
 *	FALSE: Read access to all bytes in string
 *	TRUE: Else
 */
BOOL WINAPI IsBadStringPtrA(
              LPCSTR str, /* [in] Address of string */
              UINT max )  /* [in] Maximum size of string */
{
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
630
    {
631 632
        volatile const char *p = str;
        while (p != str + max) if (!*p++) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
633
    }
634 635
    __EXCEPT(page_fault) { return TRUE; }
    __ENDTRY
Alexandre Julliard's avatar
Alexandre Julliard committed
636 637
    return FALSE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
638

Alexandre Julliard's avatar
Alexandre Julliard committed
639

Alexandre Julliard's avatar
Alexandre Julliard committed
640
/***********************************************************************
641 642
 *             IsBadStringPtrW   (KERNEL32.@)
 * See IsBadStringPtrA
Alexandre Julliard's avatar
Alexandre Julliard committed
643
 */
644 645 646
BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT max )
{
    __TRY
Alexandre Julliard's avatar
Alexandre Julliard committed
647
    {
648 649
        volatile const WCHAR *p = str;
        while (p != str + max) if (!*p++) break;
Alexandre Julliard's avatar
Alexandre Julliard committed
650
    }
651 652 653
    __EXCEPT(page_fault) { return TRUE; }
    __ENDTRY
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
654
}