|
- #pragma once
- #include <windows.h>
-
- /*
- A safer replacement for the obsolete IsBadReadPtr() and IsBadWritePtr() WinAPI functions
- on top of VirtualQuery() which respects Windows guard pages. It does not use SEH
- and is designed to be compatible with the above-mentioned functions.
- The calls to the IsBadReadPtr() and IsBadWritePtr() can be replaced with the calls to
- the IsBadMemPtr() as follows:
- - IsBadReadPtr(...) => IsBadMemPtr(FALSE, ...)
- - IsBadWritePtr(...) => IsBadMemPtr(TRUE, ...)
- */
- BOOL IsBadMemPtr(/*BOOL write, */void* ptr, size_t size)
- {
- MEMORY_BASIC_INFORMATION mbi;
- BOOL ok;
- DWORD mask;
- BYTE* p = (BYTE*)ptr;
- BYTE* maxp = p + size;
- BYTE* regend = NULL;
-
- if (size == 0)
- {
- return FALSE;
- }
-
- if (p == NULL)
- {
- return TRUE;
- }
-
- /*if (write == FALSE)
- {
- mask = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
- }
- else
- {*/
- mask = PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
- /*}*/
-
- do
- {
- if (p == ptr || p == regend)
- {
- if (VirtualQuery((LPCVOID)p, &mbi, sizeof(mbi)) == 0)
- {
- return TRUE;
- }
- else
- {
- regend = ((BYTE*)mbi.BaseAddress + mbi.RegionSize);
- }
- }
-
- ok = (mbi.Protect & mask) != 0;
-
- if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS))
- {
- ok = FALSE;
- }
-
- if (!ok)
- {
- return TRUE;
- }
-
- if (maxp <= regend) /* the whole address range is inside the current memory region */
- {
- return FALSE;
- }
- else if (maxp > regend) /* this region is a part of (or overlaps with) the address range we are checking */
- {
- p = regend; /* lets move to the next memory region */
- }
- } while (p < maxp);
-
- return FALSE;
- }
|