/***************************************************************************** * * Valid.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Validate services. On a validation error that would not have * been caught in retail, we throw an exception. * * Contents: * * fFullValidPhwnd * fFullValidPpdw * fFullValidPpfn * fFullValidReadPx * fFullValidWritePx * *****************************************************************************/ /* #include "wia.h" #include #include #include #include #include #include "stipriv.h" #include "debug.h" */ #include "sticomm.h" /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresValidInstanceVer | * * Check the and version number received from * an application. * * @parm HINSTANCE | hinst | * * Purported module instance handle. * * @parm DWORD | dwVersion | * * Version the application is asking for. * *****************************************************************************/ HRESULT EXTERNAL hresValidInstanceVer_(HINSTANCE hinst, DWORD dwVersion, LPCSTR s_szProc) { HRESULT hres = S_OK; TCHAR tszScratch[MAX_PATH]; DWORD dwRealVersion = (dwVersion & ~STI_VERSION_FLAG_MASK); if (GetModuleFileName(hinst, tszScratch, cA(tszScratch) - 1)) { if (( dwRealVersion <= STI_VERSION) &&(dwRealVersion >= STI_VERSION_MIN_ALLOWED)){ hres = S_OK; } else { hres = STIERR_OLD_VERSION; } } else { hres = E_INVALIDARG; } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidHwnd | * * Validate a window handle completely. * * @parm HWND | hwnd | * * Window handle to validate. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ STDMETHODIMP hresFullValidHwnd_(HWND hwnd, LPCSTR s_szProc, int iarg) { HRESULT hres; if (IsWindow(hwnd)) { hres = S_OK; } else { // RPF("ERROR %s: arg %d: not a window handle", s_szProc, iarg); hres = E_HANDLE; } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresValidHandle | * * Validate a generic handle completely. * * @parm HANDLE | handle | * * Handle to validate. * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ STDMETHODIMP hresValidHandle(HANDLE handle) { HANDLE hTemp; HRESULT hres; hres = S_OK; hTemp = INVALID_HANDLE_VALUE; // Validate the handle by calling DuplicateHandle. This function // shouldn't change the state of the handle at all (except some // internal ref count or something). So if it succeeds, then we // know we have a valid handle, otherwise, we will call it invalid. if(!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &hTemp, DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS)) { hres = E_HANDLE; } // Now close our duplicate handle CloseHandle(hTemp); return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidPvCb_ | * * Validate that a buffer is readable or writeable. * * @parm PV | pv | * * Buffer address. * * @parm UINT | cb | * * Size of buffer in bytes. * * @parm PFNBAD | pfnBad | * * Function that determines whether the buffer is bad. * Should be or . * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * High word indicates how many bytes should not be * scrambled. * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ typedef BOOL (WINAPI *PFNBAD)(PCV pv, UINT_PTR cb); #ifndef MAXDEBUG #define hresFullValidPvCb_(pv, cb, pfnBad, z, i) \ _hresFullValidPvCb_(pv, cb, pfnBad) \ #endif STDMETHODIMP hresFullValidPvCb_(PCV pv, UINT cb, PFNBAD pfnBad, LPCSTR s_szProc, int iarg) { HRESULT hres; if (!pfnBad(pv, cb)) { hres = S_OK; } else { RPF("ERROR %s: arg %d: invalid pointer", "", LOWORD(iarg)); hres = E_POINTER; } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidWritePvCb_ | * * Validate that a buffer is writeable. Also scrambles it * if special goo doesn't need to be done. * * @parm PV | pv | * * Buffer address. * * @parm UINT | cb | * * Size of buffer in bytes. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ STDMETHODIMP hresFullValidWritePvCb_(PV pv, UINT cb, LPCSTR s_szProc, int iarg) { HRESULT hres; hres = hresFullValidPvCb_(pv, cb, (PFNBAD)IsBadWritePtr, s_szProc, iarg); #ifdef MAXDEBUG if (SUCCEEDED(hres) && HIWORD(iarg) == 0) { ScrambleBuf(pv, cb); } #endif return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidReadPvCb_ | * * Validate that a buffer is readable. * * @parm PV | pv | * * Buffer address. * * @parm UINT | cb | * * Size of buffer in bytes. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ STDMETHODIMP hresFullValidReadPvCb_(PCV pv, UINT cb, LPCSTR s_szProc, int iarg) { return hresFullValidPvCb_(pv, cb, (PFNBAD)IsBadReadPtr, s_szProc, iarg); } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidPxCb_ | * * Validate that a sized structure is readable or writeable. * * @parm PCV | pv | * * Structure address. The first field of the structure must * be a

. If the structure is being validated for * writing, then all fields beyond the

are scrambled * in MAXDEBUG. * * @parm UINT | cb | * * Expected size of the structure. * * @parm STRUCTPROC | pfnStruct | * * Function which validates that a structure is readable or writable. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the buffer is not readable or writeable. * * if the buffer size is incorrect. * *****************************************************************************/ typedef STDMETHOD(STRUCTPROC)(PCV pv, UINT cb RD(comma LPCSTR s_szProc comma int iarg)); #ifndef MAXDEBUG #define hresFullValidPxCb_(pv, cb, pfnStruct, z, i) \ _hresFullValidPxCb_(pv, cb, pfnStruct) \ #endif STDMETHODIMP hresFullValidPxCb_(PCV pv, UINT cb, STRUCTPROC pfnStruct, LPCSTR s_szProc, int iarg) { HRESULT hres; hres = pfnStruct(pv, cb RD(comma s_szProc comma iarg)); if (SUCCEEDED(hres)) { if (*(LPDWORD)pv == cb) { if (HIWORD(iarg)) { ScrambleBuf(pvAddPvCb(pv, HIWORD(iarg)), cb - HIWORD(iarg)); } } else { //RPF("ERROR %s: arg %d: invalid dwSize", s_szProc, LOWORD(iarg)); hres = E_INVALIDARG; } } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidWritePxCb_ | * * Validate that a sized structure is writeable. * * @parm PV | pv | * * Structure address. The first field of the structure must * be a

. * * @parm UINT | cb | * * Expected size of the structure. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the buffer is not writeable. * * if the buffer size is incorrect. * *****************************************************************************/ STDMETHODIMP hresFullValidWritePxCb_(PV pv, UINT cb, LPCSTR s_szProc, int iarg) { /* * We need to distinguish hresFullValidWritePvCb_ and * _hresFullValidWritePvCb_ manually, because the preprocessor * gets confused. * * We also need to put a cbX(DWORD) into the high word of the iarg * so that the size field won't get demolished. */ #ifdef MAXDEBUG return hresFullValidPxCb_(pv, cb, (STRUCTPROC)hresFullValidWritePvCb_, s_szProc, MAKELONG(iarg, cbX(DWORD))); #else return hresFullValidPxCb_(pv, cb, (STRUCTPROC)_hresFullValidWritePvCb_, s_szProc, iarg); #endif } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidReadPxCb_ | * * Validate that a sized structure is readable. * * @parm PV | pv | * * Structure address. The first field of the structure must * be a

. * * @parm UINT | cb | * * Expected size of the structure. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the buffer is not readable. * * if the buffer size is incorrect. * *****************************************************************************/ STDMETHODIMP hresFullValidReadPxCb_(PCV pv, UINT cb, LPCSTR s_szProc, int iarg) { /* * We need to distinguish hresFullValidReadPvCb_ and * _hresFullValidReadPvCb_ manually, because the preprocessor * gets confused. */ #ifdef MAXDEBUG return hresFullValidPxCb_(pv, cb, hresFullValidReadPvCb_, s_szProc, iarg); #else return hresFullValidPxCb_(pv, cb, _hresFullValidReadPvCb_, s_szProc, iarg); #endif } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidFl_ | * * Validate that no invalid flags are passed. * * @parm DWORD | fl | * * Flags passed by the caller. * * @parm DWORD | flV | * * Flags which are valid. * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ STDMETHODIMP hresFullValidFl_(DWORD fl, DWORD flV, LPCSTR s_szProc, int iarg) { HRESULT hres; if ((fl & ~flV) == 0) { hres = S_OK; } else { //RPF("ERROR %s: arg %d: invalid flags", s_szProc, iarg); hres = E_INVALIDARG; } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidPfn_ | * * Validate that the parameter is a valid code pointer. * * Actually, on Win32 is broken, but * tough. * * @parm FARPROC | pfn | * * Procedure to "validate". * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the parameter is invalid. * *****************************************************************************/ STDMETHODIMP hresFullValidPfn_(FARPROC pfn, LPCSTR s_szProc, int iarg) { HRESULT hres; if (!IsBadCodePtr(pfn)) { hres = S_OK; } else { //RPF("ERROR %s: arg %d: invalid callback address", s_szProc, iarg); hres = E_INVALIDARG; } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidPitf_ | * * Validate that the parameter is an interface pointer. * * We don't look at it very hard. * * @parm PUNK | punk | * * to "validate". * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the pointer itself is bogus. * * if something inside the pointer is bogus. * *****************************************************************************/ STDMETHODIMP hresFullValidPitf_(PUNK punk, LPCSTR s_szProc, int iarg) { HRESULT hres; if (!IsBadReadPtr(punk, cbX(DWORD))) { IUnknownVtbl *pvtbl = punk->lpVtbl; if (!IsBadReadPtr(pvtbl, 3 * cbX(DWORD))) { if (!IsBadCodePtr((FARPROC)pvtbl->QueryInterface) && !IsBadCodePtr((FARPROC)pvtbl->AddRef) && !IsBadCodePtr((FARPROC)pvtbl->Release)) { hres = S_OK; } else { //RPF("ERROR %s: arg %d: invalid pointer", s_szProc, iarg); hres = E_INVALIDARG; } } else { //RPF("ERROR %s: arg %d: invalid pointer", s_szProc, iarg); hres = E_INVALIDARG; } } else { //RPF("ERROR %s: arg %d: invalid pointer", s_szProc, iarg); hres = E_POINTER; } return hres; } /***************************************************************************** * * @doc INTERNAL * * @func HRESULT | hresFullValidPdwOut_ | * * Validate that the parameter is a valid place to stick an * output result. We also smas it to zero. * * @parm PV | pdw | * * Pointer to "validate". * * @parm LPCSTR | s_szProc | * * Name of calling procedure. * * @parm int | iarg | * * Parameter index. (First parameter is 1.) * * @returns * * if the parameter is valid. * * if the pointer itself is bogus. * *****************************************************************************/ STDMETHODIMP hresFullValidPdwOut_(PV pdw, LPCSTR s_szProc, int iarg) { HRESULT hres; if (!IsBadWritePtr(pdw, 4)) { *(LPDWORD)pdw = 0; hres = S_OK; } else { //RPF("ERROR %s: arg %d: invalid pointer", s_szProc, iarg); hres = E_POINTER; } return hres; }