|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N C B A S E . C P P
//
// Contents: Basic common code.
//
// Notes: Pollute this under penalty of death.
//
// Author: shaunco 20 Sep 1997
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "ncbase.h"
#include "ncdebug.h"
#include "ncperms.h"
#include "ncstring.h"
//+---------------------------------------------------------------------------
//
// Function: AddRefObj
//
// Purpose: AddRef's the object pointed to by punk by calling
// punk->AddRef();
//
// Arguments:
// punk [in] Object to be AddRef'd. Can be NULL.
//
// Returns: Result of AddRef call.
//
// Author: danielwe 25 Feb 1997
//
// Notes: Using this function to AddRef an object will reduce
// our code size.
//
NOTHROW ULONG AddRefObj ( IUnknown* punk) { return (punk) ? punk->AddRef () : 0; }
//+---------------------------------------------------------------------------
//
// Function: ReleaseObj
//
// Purpose: Releases the object pointed to by punk by calling
// punk->Release();
//
// Arguments:
// punk [in] Object to be released. Can be NULL.
//
// Returns: Result of Release call.
//
// Author: danielwe 25 Feb 1997
//
// Notes: Using this function to release a (possibly NULL) object will
// reduce our code size.
//
NOTHROW ULONG ReleaseObj ( IUnknown* punk) { return (punk) ? punk->Release () : 0; }
//+--------------------------------------------------------------------------
//
// Function: DwWin32ErrorFromHr
//
// Purpose: Converts the HRESULT to a Win32 error or SetupApi error.
//
// Arguments:
// hr [in] The HRESULT to convert
//
// Returns: Converted DWORD value.
//
// Author: billbe 22 Apr 1997
//
// Notes:
//
NOTHROW DWORD DwWin32ErrorFromHr ( HRESULT hr) { DWORD dw = ERROR_SUCCESS;
// All success codes convert to ERROR_SUCCESS so we only need to handle
// failures.
if (FAILED(hr)) { DWORD dwFacility = HRESULT_FACILITY(hr);
if (FACILITY_SETUPAPI == dwFacility) { // reconstruct the SetupApi error using the correct masks
dw = HRESULT_CODE(hr) | APPLICATION_ERROR_MASK | ERROR_SEVERITY_ERROR;
// Check to make sure dw maps to a known SetupApi error
AssertSz(FDwordWithinRange(ERROR_EXPECTED_SECTION_NAME, dw, ERROR_GENERAL_SYNTAX) || FDwordWithinRange(ERROR_WRONG_INF_STYLE, dw, ERROR_NO_BACKUP) || FDwordWithinRange(ERROR_NO_ASSOCIATED_CLASS, dw, ERROR_SET_SYSTEM_RESTORE_POINT), "The mapped SetupApi error is not known " "(or is new)!!!"); } else if (FACILITY_WIN32 == dwFacility) { dw = HRESULT_CODE(hr); } else if (FACILITY_ITF == dwFacility) { dw = ERROR_GEN_FAILURE; } else { // cannot convert it
AssertSz(FALSE, "Facility was not SETUP or WIN32!"); dw = hr; } }
return dw; }
//+---------------------------------------------------------------------------
//
// Function: HrCoTaskMemAlloc
//
// Purpose: Call CoTaskMemAlloc but return an HRESULT.
//
// Arguments:
// cb [in] Count of bytes to allocate.
// ppv [out] Returned pointer to bytes.
//
// Returns: S_OK or E_OUTOFMEMORY.
//
// Author: shaunco 31 May 1997
//
// Notes:
//
HRESULT HrCoTaskMemAlloc ( ULONG cb, VOID** ppv) { HRESULT hr = S_OK; *ppv = CoTaskMemAlloc (cb); if (!*ppv) { hr = E_OUTOFMEMORY; } TraceError ("HrCoTaskMemAlloc", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrCoTaskMemAllocAndDupSzLen
//
// Purpose: Allocate memory using CoTaskMemAlloc and copy a string
// into it. This is used by the implementation of COM interfaces
// that return strings.
//
// Arguments:
// pszSrc [in] Pointer to source string.
// cchSrc [in] Number of characters to copy from source string.
// ppszDst [out] Address of pointer to destination string.
//
// Returns: S_OK or E_OUTOFMEMORY
//
// Author: shaunco 14 Jan 1999
//
// Notes: NULL input pointers are allocated as empty strings
// deliberately.
// The returned string is guaranteed to be NULL terminated.
//
HRESULT HrCoTaskMemAllocAndDupSzLen ( IN PCWSTR pszSrc, IN ULONG cchSrc, OUT PWSTR* ppszDst) { Assert (ppszDst);
HRESULT hr; DWORD cb = cchSrc * sizeof(WCHAR);
hr = E_OUTOFMEMORY; *ppszDst = (PWSTR)CoTaskMemAlloc (cb + sizeof(WCHAR)); if (*ppszDst) { hr = S_OK; wcsncpy (*ppszDst, pszSrc, cchSrc); (*ppszDst)[cchSrc] = 0; }
TraceError ("HrCoTaskMemAllocAndDupSz", hr); return hr; }
HRESULT HrCoTaskMemAllocAndDupSz ( IN PCWSTR pszSrc, OUT PWSTR* ppszDst) { return HrCoTaskMemAllocAndDupSzLen ( pszSrc, CchOfSzSafe(pszSrc), ppszDst); }
//+---------------------------------------------------------------------------
//
// Function: HrFromLastWin32Error
//
// Purpose: Converts the GetLastError() Win32 call into a proper HRESULT.
//
// Arguments:
// (none)
//
// Returns: Converted HRESULT value.
//
// Author: danielwe 24 Mar 1997
//
// Notes: This is not inline as it actually generates quite a bit of
// code.
// If GetLastError returns an error that looks like a SetupApi
// error, this function will convert the error to an HRESULT
// with FACILITY_SETUP instead of FACILITY_WIN32
//
NOTHROW HRESULT HrFromLastWin32Error () { DWORD dwError = GetLastError(); HRESULT hr;
// This test is testing SetupApi errors only (this is
// temporary because the new HRESULT_FROM_SETUPAPI macro will
// do the entire conversion)
if (dwError & (APPLICATION_ERROR_MASK | ERROR_SEVERITY_ERROR)) { hr = HRESULT_FROM_SETUPAPI(dwError); } else { hr = HRESULT_FROM_WIN32(dwError); } return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrGetProcAddress
//
// Purpose: Loads a libray and returns the address of a procedure within
// the library
//
// Arguments:
// hModule [in] The handle to the library module instance
// pszaFunction [in] Function to retrieve
// ppfn [out] Address of szFunction
//
// Returns: S_OK if successful, Win32 converted error if failure.
//
// Author: billbe 10 June 1997
//
// Notes:
//
HRESULT HrGetProcAddress ( HMODULE hModule, PCSTR pszaFunction, FARPROC* ppfn) { Assert(hModule); Assert(pszaFunction); Assert(ppfn);
HRESULT hr = S_OK; *ppfn = GetProcAddress(hModule, pszaFunction); if (!*ppfn) { hr = HrFromLastWin32Error(); TraceTag(ttidError, "HrGetProcAddress failed: szFunction: %s", pszaFunction); }
TraceError("HrGetProcAddress", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrLoadLibAndGetProcs
//
// Purpose: Load a dynamic link library and the addresses of one or
// more procedures within that library.
//
// Arguments:
// pszLibPath [in] Path to the DLL to load.
// cFunctions [in] Number of procedures to load.
// apszaFunctionNames [in] Array of function names. (Must be 'cFunctions'
// of them.)
// phmod [out] Returned handle to the loaded module.
// apfn [out] Array of returned pointers to the procedures
// loaded. (Must be 'cFunctions' of them.)
//
// Returns: S_OK if all procedures were loaded, S_FALSE if only
// some of them were, or a Win32 error code. If only
// one procedure is to be loaded and it is not, S_FALSE will
// not be returned, rather, the reason for why the single
// procedure could not be loaded will be returned. This allows
// HrLoadLibAndGetProc to be implemented using this function.
//
// Author: shaunco 19 Jan 1998
//
// Notes: phmod should be freed by the caller using FreeLibrary if
// the return value is S_OK.
//
HRESULT HrLoadLibAndGetProcs ( PCWSTR pszLibPath, UINT cFunctions, const PCSTR* apszaFunctionNames, HMODULE* phmod, FARPROC* apfn) { Assert (pszLibPath); Assert (cFunctions); Assert (apszaFunctionNames); Assert (phmod); Assert (apfn);
HRESULT hr = S_OK;
// Load the module and initialize the output parameters.
//
HMODULE hmod = LoadLibrary (pszLibPath); *phmod = hmod; ZeroMemory (apfn, cFunctions * sizeof(FARPROC));
if (hmod) { // Get the proc address of each function.
//
for (UINT i = 0; i < cFunctions; i++) { apfn[i] = GetProcAddress (hmod, apszaFunctionNames[i]);
if (!apfn[i]) { // Couldn't load all functions. We'll be returning S_FALSE
// (if their are more than one function.)
//
hr = S_FALSE;
TraceTag (ttidError, "HrLoadLibAndGetProcs: GetProcAddress " "for '%s' failed.", apszaFunctionNames[i]); } }
// If we're only loading one function, and it failed,
// return the failure.
//
if ((1 == cFunctions) && !apfn[0]) { hr = HrFromLastWin32Error (); FreeLibrary (hmod); } } else { hr = HrFromLastWin32Error (); TraceTag (ttidError, "HrLoadLibAndGetProcs: LoadLibrary (%S) failed.", pszLibPath); }
TraceError ("HrLoadLibAndGetProcs", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrGetProcAddressesVa
//
// Purpose: Get proc-address of each function-name passed
//
// Arguments:
// hModule [in] handle of DLL
// arglist [in] list of var-args. the expected format is
// "func-name", FARPROC*, ..., NULL
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 29-December-97
//
// Notes:
//
HRESULT HrGetProcAddressesVa ( HMODULE hModule, va_list arglist) { PCSTR szFunctionName; FARPROC* ppfn; HRESULT hr = S_OK; typedef FARPROC* PFARPROC;
while (NULL != (szFunctionName = va_arg(arglist, CHAR*))) { ppfn = va_arg(arglist, PFARPROC); *ppfn = GetProcAddress(hModule, szFunctionName);
if (!*ppfn) { hr = HrFromLastWin32Error(); TraceTag(ttidError, "HrGetProcAddressesVa failed: szFunction: %s", szFunctionName); break; } }
TraceError("HrGetProcAddressesVa", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrGetProcAddressesV
//
// Purpose: Get proc-address of each function-name passed
//
// Arguments:
// hModule [in] handle of DLL
// ... [in] list of var-args. the expected format is
// "func-name", FARPROC*, ..., NULL
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 29-December-97
//
// Notes:
//
HRESULT HrGetProcAddressesV ( HMODULE hModule, ...) { HRESULT hr=S_OK; va_list arglist;
va_start(arglist, hModule);
hr = HrGetProcAddressesVa(hModule, arglist);
va_end(arglist);
TraceError("HrGetProcAddressesV", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrLoadLibAndGetProcsV
//
// Purpose: Get proc-address of each function-name passed
//
// Arguments:
// pszLibPath [in] DLL to load
// phModule [out] pointer to handle of DLL loaded
// ... [in] list of var-args. the expected format is
// "func-name", FARPROC*, ..., NULL
//
// Returns: S_OK on success, otherwise an error code
//
// Author: kumarp 29-December-97
//
// Notes:
//
HRESULT HrLoadLibAndGetProcsV ( PCWSTR pszLibPath, HMODULE* phModule, ...) { Assert(pszLibPath); Assert(phModule);
HRESULT hr = S_OK;
// Attempt to load the library
*phModule = LoadLibrary(pszLibPath);
if (*phModule) { va_list arglist;
va_start(arglist, phModule);
hr = HrGetProcAddressesVa(*phModule, arglist);
va_end(arglist);
if (FAILED(hr)) { // Free the library
FreeLibrary(*phModule); } } else { hr = HrFromLastWin32Error(); TraceTag(ttidError, "HrLoadLibAndGetProcsV failed: szLibPath: %S", pszLibPath); }
// if we failed then we should set *phModule to NULL since we might
// have successfully loaded it and failed getting the proc
if (FAILED(hr)) { *phModule = NULL; }
TraceError("HrLoadLibAndGetProcsV", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrCreateEventWithWorldAccess
//
// Purpose: Creates a event with permissions to allow access to
// everyone.
//
// Arguments:
// pszName [in] Name for the event.
// fManualReset [in] See Win32 docs.
// fInitialState [in] See Win32 docs.
// pfAlreadyExists [out] TRUE if the event already existed.
// FALSE otherwise.
// phEvent [out] The created event.
//
// Returns: S_OK on success. An error code otherwise.
//
// Author: BillBe 16 Nov 1998
//
// Notes:
//
HRESULT HrCreateEventWithWorldAccess(PCWSTR pszName, BOOL fManualReset, BOOL fInitialState, BOOL* pfAlreadyExists, HANDLE* phEvent) { Assert(pszName); Assert(phEvent);
if (pfAlreadyExists) { *pfAlreadyExists = FALSE; }
*phEvent = NULL;
// Create the correct descriptor.
PSECURITY_DESCRIPTOR pSd; HRESULT hr = HrAllocateSecurityDescriptorAllowAccessToWorld(&pSd); if (SUCCEEDED(hr)) { SECURITY_ATTRIBUTES sa = {0}; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = FALSE;
// Create Event
//
*phEvent = CreateEvent(&sa, fManualReset, fInitialState, pszName);
hr = HrFromLastWin32Error(); if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) { if (pfAlreadyExists) { *pfAlreadyExists = TRUE; } hr = S_OK; }
MemFree(pSd); }
TraceError("HrCreateEventWithWorldAccess", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrCreateMutexWithWorldAccess
//
// Purpose: Creates a mutex with permissions to allow access to
// everyone.
//
// Arguments:
// pszName [in] Name for the mutex.
// fInitialOwner [in] See Win32 docs.
// pfAlreadyExists [out] TRUE if the mutex already existed,
// FALSE otherwise.
// phMutex [out] The created mutex.
//
// Returns: S_OK on success. An error code otherwise.
//
// Author: BillBe 16 Nov 1998
//
// Notes:
//
HRESULT HrCreateMutexWithWorldAccess ( PCWSTR pszName, BOOL fInitialOwner, BOOL* pfAlreadyExists, HANDLE* phMutex) { Assert(pszName); Assert(phMutex);
if (pfAlreadyExists) { *pfAlreadyExists = FALSE; }
*phMutex = NULL;
// Create the correct descriptor.
PSECURITY_DESCRIPTOR pSd; HRESULT hr = HrAllocateSecurityDescriptorAllowAccessToWorld(&pSd); if (S_OK == hr) { SECURITY_ATTRIBUTES sa = {0}; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = FALSE;
// Create Mutex
//
*phMutex = CreateMutex(&sa, fInitialOwner, pszName);
hr = HrFromLastWin32Error(); if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr) { if (pfAlreadyExists) { *pfAlreadyExists = TRUE; } hr = S_OK; }
MemFree(pSd); }
TraceError("HrCreateMutexWithWorldAccess", hr); return hr; }
//+---------------------------------------------------------------------------
// The standard parameterization of CoSetProxyBlanket. Call this instead
// of CoSetProxyBlanket so you get the same security and authentication
// settings as everyone else. This version saves code space at the call-site
// because it pushes only one parameter instead of eight.
// This does not return an error because it does not invalidate the use of
// pUnk after it's called.
//
VOID NcSetProxyBlanket ( IN IUnknown* pUnk) { HRESULT hr;
hr = CoSetProxyBlanket ( pUnk, RPC_C_AUTHN_WINNT, // use NT default security
RPC_C_AUTHZ_NONE, // use NT default authentication
NULL, // must be null if default
RPC_C_AUTHN_LEVEL_CALL, // call
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, // use process token
EOAC_NONE);
if(SUCCEEDED(hr)) { IUnknown * pUnkSet = NULL; hr = pUnk->QueryInterface(&pUnkSet); if(SUCCEEDED(hr)) { hr = CoSetProxyBlanket ( pUnkSet, RPC_C_AUTHN_WINNT, // use NT default security
RPC_C_AUTHZ_NONE, // use NT default authentication
NULL, // must be null if default
RPC_C_AUTHN_LEVEL_CALL, // call
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, // use process token
EOAC_NONE); ReleaseObj(pUnkSet); } }
TraceHr(ttidError, FAL, hr, (E_NOINTERFACE == hr), "NcSetProxyBlanket"); }
//+---------------------------------------------------------------------------
//
// Function: HrCreateInstanceBase
//
// Purpose: Creates a COM object and sets default proxy settings.
//
// Arguments:
// rclsid [in] See documentation for CoCreateInstance.
// dwClsContext [in] ""
// riid [in] ""
// ppv [out] ""
//
// Returns: S_OK on success. An error code otherwise.
//
// Author: mbend 1 Mar 2000
//
// Notes: Call type safe version HrCreateInstance
//
HRESULT HrCreateInstanceBase ( REFCLSID rclsid, DWORD dwClsContext, REFIID riid, LPVOID * ppv) { HRESULT hr = S_OK;
hr = ::CoCreateInstance(rclsid, NULL, dwClsContext, riid, ppv);
if(SUCCEEDED(hr) && (dwClsContext & CLSCTX_LOCAL_SERVER)) { NcSetProxyBlanket(reinterpret_cast<IUnknown*>(*ppv)); }
TraceError("HrCreateInstanceBase", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrQIAndSetProxyBlanketBase
//
// Purpose: Performs QueryInterface and sets default proxy settings.
//
// Arguments:
// pUnk [in] Interface pointer to perform QueryInterface on.
// riid [in] See documentation of QueryInterface
// ppv [out] ""
//
// Returns: S_OK on success. An error code otherwise.
//
// Author: mbend 1 Mar 2000
//
// Notes: Call type safe version HrQIAndSetProxyBlanket
//
HRESULT HrQIAndSetProxyBlanketBase(IUnknown * pUnk, REFIID riid, void ** ppv) { HRESULT hr = pUnk->QueryInterface(riid, ppv); if(SUCCEEDED(hr)) { NcSetProxyBlanket(reinterpret_cast<IUnknown*>(*ppv)); }
TraceError("HrQIAndSetProxyBlanketBase", hr); return hr; }
|