Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

302 lines
11 KiB

//
// validate.h
//
// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved.
//
// Parameter validation macros
//
// Summary:
//
// V_INAME(interfacename) - Set the interface name for error display
// V_STRUCTPTR_READ(ptr,type) - A dwSize struct which we will read
// V_STRUCTPTR_WRITE(ptr,type) - A dwSize struct which we will read/write
// V_PTR_READ(ptr,type) - A typed ptr w/o a dwSize which we will read
// V_PTR_WRITE(ptr,type) - A typed ptr w/o a dwSize which we will read/write
// V_PTR_WRITE_OPT(ptr,type) - An optional typed ptr w/o a dwSize which we will read/write
// V_BUFPTR_READ(ptr,size) - A variable-size buffer that we will read
// V_BUFPTR_READ_OPT(ptr,size) - An optional variable-size buffer that we will read
// V_BUFPTR_WRITE(ptr,size) - A variable-size buffer that we will read/write
// V_BUFPTR_WRITE_OPT(ptr,size) - An optional variable-size buffer that we will read/write
// V_PTRPTR_WRITE(ptrptr) - A pointer to a pointer to write to
// V_PTRPTR_WRITE_OPT(ptrptr) - A pointer to a pointer to write to that is optional
// V_PUNKOUTER(punk) - A pointer to a controlling unknown, aggregation supported
// V_PUNKOUTER_NOADD(punk) - A pointer to a controlling unknown, aggregation not supported
// V_INTERFACE(ptr) - A pointer to a COM interface
// V_INTERFACE_OPT(ptr) - An optional pointer to a COM interface
// V_REFGUID(ref) - A reference to a GUID (type REFGUID)
// V_HWND(hwnd) - A window handle
// V_HWNDOPT(hwnd) - An optional window handle
//
// For handling different versions of structures:
//
// V_STRUCTPTR_READ_VER(ptr,ver) - Begin a struct version block for read access
// At the end, 'ver' will contain the
// discovered version of the struct
// V_STRUCTPTR_READ_VER_CASE(base,ver) - Test struct against version ver of
// type 'base'.
// V_STRUCTPTR_READ_VER_END(base,ptr) - End a struct version block
//
// V_STRUCTPTR_WRITE_VER(ptr,ver) - Struct version block for write access
// V_STRUCTPTR_WRITE_VER_CASE(base,ver)
// V_STRUCTPTR_WRITE_VER_END(base,ptr)
//
// The struct version block expects type names of a base type followed by a
// numeric version, such as
//
// typedef struct { } FOO7;
// typedef struct { } FOO8;
//
// In the header FOO and LPFOO are conditionally typedef'd based on a version
// #define. The DLL will be compiled with the latest version number and hence
// the largest version of the struct.
//
// Since Windows headers are compiled by default with 8-byte alignment, adding
// one DWORD may not cause the size of the structure to change. If this happens
// you will get a 'case label already used' error on one of the VER_CASE macros.
// If this happens, you can get around it by adding a dwReserved field to the
// end of the struct to force the padding.
//
// 'optional' means the pointer is allowed to be NULL by the interface specification.
//
// Sample usage:
//
// int IDirectMusic::SetFooBarInterface(
// LPDMUS_REQUESTED_CAPS pCaps, // Caps w/ dwSize (read-only)
// LPVOID pBuffer, // Buffer we will fill in
// DWORD cbSize, // Size of the buffer
// PDIRECTMUSICBAR pBar) // Callback interface for bar on this buffer
// {
// V_INTERFACE(IDirectMusic::SetFooBarInterface);
// V_BUFPTR_WRITE(pBuffer, cbSize);
// V_INTERFACE(pBar);
// DWORD dwCapsVer; // Must be a DWORD!!!
//
// V_STRUCTPTR_READ_VER(pCaps, dwCapsVer);
// V_STRUCTPTR_READ_VER_CASE(DMUS_REQUESTED_CAPS, 7);
// V_STRUCTPTR_READ_VER_CASE(DMUS_REQUESTED_CAPS, 8);
// V_STRUCTPTR_READ_VER_END_(DMUS_REQUESTED_CAPS, pCaps);
//
// // At this point, if we are still in the function we have a valid pCaps
// // pointer and dwCapsVer is either 7 or 8, indicating the version of
// // the struct passed in.
//
// ...
// }
//
#ifndef _VALIDATE_H_
#define _VALIDATE_H_
#ifdef DBG
#include <stddef.h>
#include "debug.h"
// To turn on DebugBreak on parameter error, use the following or -DRIP_BREAK in the build:
//
//#define RIP_BREAK 1
#ifdef RIP_BREAK
#define _RIP_BREAK DebugBreak();
#else
#define _RIP_BREAK
#endif
#define V_INAME(x) \
static const char __szValidateInterfaceName[] = #x;
#define RIP_E_POINTER(ptr) \
{ Trace(-1, "%s: Invalid pointer " #ptr "\n", __szValidateInterfaceName); \
_RIP_BREAK \
return E_POINTER; }
#define RIP_E_INVALIDARG(ptr) \
{ Trace(-1, "%s: Invalid argument " #ptr "\n", __szValidateInterfaceName); \
_RIP_BREAK \
return E_INVALIDARG; }
#define RIP_E_HANDLE(h) \
{ Trace(-1, "%s: Invalid handle " #h "\n", __szValidateInterfaceName); \
_RIP_BREAK \
return E_HANDLE; }
#define RIP_W_INVALIDSIZE(ptr) \
{ Trace(-1, "%s: " #ptr "->dwSize matches no known structure size. Defaulting to oldest structure.\n", \
__szValidateInterfaceName); \
_RIP_BREAK \
}
#define RIP_E_INVALIDSIZE(ptr) \
{ Trace(-1, "%s: " #ptr "->dwSize is too small\n", __szValidateInterfaceName); \
_RIP_BREAK \
return E_INVALIDARG; }
#define RIP_E_BLOCKVSDWSIZE(ptr) \
{ Trace(-1, "%s: " #ptr " does not point to as much memory as " #ptr "->dwSize indicates\n", \
__szValidateInterfaceName); \
_RIP_BREAK \
return E_INVALIDARG; }
// NOTE: The DebugBreak() not in #ifdef is intentional - this is something that
// must be fixed in our code, not an app-generated error.
//
#define V_ASSERT(exp) \
{ if (!(exp)) { \
Trace(-1, "%s@%s: %s\n", __FILE__, __LINE__, #exp); \
DebugBreak(); }}
#else
#define V_INAME(x)
#define RIP_E_POINTER(ptr) { return E_POINTER; }
#define RIP_E_INVALIDARG(ptr) { return E_INVALIDARG; }
#define RIP_E_HANDLE(h) { return E_HANDLE; }
#define RIP_E_BLOCKVSDWSIZE(ptr) { return E_INVALIDARG; }
#define RIP_W_INVALIDSIZE(ptr)
#define RIP_E_INVALIDSIZE(ptr) { return E_INVALIDARG; }
#define V_ASSERT(exp)
#endif // DBG
// A passed struct we will only read from or may write to. Must be a struct
// with a dwSize.
//
// int foo(CFoo *pFoo)
// ...
// V_STRUCTPTR_READ(pFoo, CFoo);
// V_STRUCTPTR_WRITE(pFoo, CFoo);
//
// Use _PTR_ variants for structs w/o a dwSize
//
#define V_STRUCTPTR_READ(ptr,type) \
{ V_ASSERT(offsetof(type, dwSize) == 0); \
if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
if (ptr->dwSize < sizeof(type)) RIP_E_INVALIDSIZE(ptr); \
if (IsBadReadPtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); }
#define V_STRUCTPTR_WRITE(ptr,type) \
{ V_ASSERT(offsetof(type, dwSize) == 0); \
if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
if (ptr->dwSize < sizeof(type)) RIP_E_INVALIDSIZE(ptr); \
if (IsBadWritePtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); }
#define V_PTR_READ(ptr,type) \
{ if (IsBadReadPtr(ptr, sizeof(type))) RIP_E_POINTER(ptr); }
#define V_PTR_WRITE(ptr,type) \
{ if (IsBadWritePtr(ptr, sizeof(type))) RIP_E_POINTER(ptr); }
#define V_PTR_WRITE_OPT(ptr,type) \
{ if (ptr) if (IsBadWritePtr(ptr, sizeof(type))) RIP_E_POINTER(ptr); }
// A buffer pointer with separate length (not defined by the pointer type) we will only
// read from or may write to.
//
// int foo(LPVOID *pBuffer, DWORD cbBuffer)
// ...
// V_BUFPTR_READ(pBuffer, cbBuffer);
// V_BUFPTR_WRITE(pBuffer, cbBuffer);
//
#define V_BUFPTR_READ(ptr,len) \
{ if (IsBadReadPtr(ptr, len)) RIP_E_POINTER(ptr); }
#define V_BUFPTR_READ_OPT(ptr,len) \
{ if (ptr) V_BUFPTR_READ(ptr,len); }
#define V_BUFPTR_WRITE(ptr,len) \
{ if (IsBadWritePtr(ptr, len)) RIP_E_POINTER(ptr); }
#define V_BUFPTR_WRITE_OPT(ptr,len) \
{ if (ptr) V_BUFPTR_WRITE(ptr,len); }
// A pointer to a pointer (such as a pointer to an interface pointer) to return
//
// int foo(IReturnMe **ppRet)
// ...
// V_PTRPTR_WRITE(ppRet);
// V_PTRPTR_WRITE_OPT(ppRet);
//
#define V_PTRPTR_WRITE(ptr) \
{ if (IsBadWritePtr(ptr, sizeof(void*))) RIP_E_POINTER(ptr); }
#define V_PTRPTR_WRITE_OPT(ptr) \
{ if (ptr) if (IsBadWritePtr(ptr, sizeof(void*))) RIP_E_POINTER(ptr); }
// A pointer to a controlling unknown
//
#define V_PUNKOUTER(punk) \
{ if (punk && IsBadCodePtr(punk)) RIP_E_POINTER(ptr); }
// A pointer to a controlling unknown for which we don't support aggregation
//
#define V_PUNKOUTER_NOAGG(punk) \
{ if (punk && IsBadReadPtr(punk, sizeof(IUnknown))) RIP_E_POINTER(ptr); \
if (punk) return CLASS_E_NOAGGREGATION; }
// Validate an incoming interface pointer.
//
struct _V_GENERIC_INTERFACE
{
FARPROC *(__vptr[1]);
};
#define V_INTERFACE(ptr) \
{ if (IsBadReadPtr(ptr, sizeof(_V_GENERIC_INTERFACE))) RIP_E_POINTER(ptr); \
if (IsBadReadPtr(*reinterpret_cast<_V_GENERIC_INTERFACE*>(ptr)->__vptr, sizeof(FARPROC))) \
RIP_E_POINTER(ptr); \
if (IsBadCodePtr(*(reinterpret_cast<_V_GENERIC_INTERFACE*>(ptr)->__vptr)[0])) RIP_E_POINTER(ptr); }
#define V_INTERFACE_OPT(ptr) \
{ if (ptr) V_INTERFACE(ptr); }
// Validation for a reference to a GUID, which we only ever read.
//
#define V_REFGUID(ref) \
{ if (IsBadReadPtr((void*)&ref, sizeof(GUID))) RIP_E_POINTER((void*)&ref); }
// Validation for a window handle
//
#define V_HWND(h) \
{ if (!IsWindow(h)) RIP_E_HANDLE(h); }
#define V_HWND_OPT(h) \
{ if (h) if (!IsWindow(h)) RIP_E_HANDLE(h); }
// Validation for multiple sized structs based on version
//
#define V_STRUCTPTR_READ_VER(ptr,ver) \
{ ver = 7; DWORD *pdw = &ver; \
if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
if (IsBadReadPtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); \
switch ((ptr)->dwSize) {
#define V_STRUCTPTR_READ_VER_CASE(basetype,ver) \
case sizeof(basetype##ver) : \
V_ASSERT(offsetof(basetype##ver, dwSize) == 0); \
*pdw = ver; break;
#define V_STRUCTPTR_READ_VER_END(basetype,ptr) \
default : if ((ptr)->dwSize > sizeof(basetype##7)) \
{ RIP_W_INVALIDSIZE(ptr); } else \
RIP_E_INVALIDSIZE(ptr); }}
#define V_STRUCTPTR_WRITE_VER(ptr,ver) \
{ ver = 7; DWORD *pdw = &ver; \
if (IsBadReadPtr(ptr, sizeof(DWORD))) RIP_E_BLOCKVSDWSIZE(ptr); \
if (IsBadWritePtr(ptr, (ptr)->dwSize)) RIP_E_BLOCKVSDWSIZE(ptr); \
switch ((ptr)->dwSize) {
#define V_STRUCTPTR_WRITE_VER_CASE(basetype,ver) \
case sizeof(basetype##ver) : \
V_ASSERT(offsetof(basetype##ver, dwSize) == 0); \
*pdw = ver; break;
#define V_STRUCTPTR_WRITE_VER_END(basetype,ptr) \
default : if ((ptr)->dwSize > sizeof(basetype##7)) \
{ RIP_W_INVALIDSIZE(ptr); } else \
RIP_E_INVALIDSIZE(ptr); }}
#endif // _VALIDATE_H_