|
|
#include <pch.h>
#pragma hdrstop
#include "ncutil.h"
#include "oleauto.h"
#include "limits.h"
#include "stdio.h"
HRESULT HrGetProperty(IDispatch * lpObject, OLECHAR *lpszProperty, VARIANT * lpResult) { HRESULT hr; DISPID pDisp; DISPPARAMS dp;
// Setup empty DISPPARAMS structure
dp.rgvarg = NULL; dp.rgdispidNamedArgs = NULL; dp.cArgs = 0; dp.cNamedArgs = 0;
// Clear out the result value
VariantClear(lpResult);
// See if such a property exists
hr = lpObject->GetIDsOfNames(IID_NULL, &lpszProperty, 1, LOCALE_SYSTEM_DEFAULT, &pDisp); if (SUCCEEDED(hr)) { // Get the property from the object
hr = lpObject->Invoke(pDisp, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, lpResult, NULL, NULL); }
return hr; }
HRESULT HrJScriptArrayToSafeArray(IDispatch *JScriptArray, VARIANT * pVtResult) { HRESULT hr = E_UNEXPECTED; VARIANT vtPropertyValue, vtTemp, *pvtData; SAFEARRAY *pSArray = NULL; SAFEARRAYBOUND pSArrayBounds[1]; long lIndex = -1; long cElements = -1; char szTemp[MAX_PATH]; bool bFixedSizeArray = false; OLECHAR *pszPropertyIndex = NULL;
if ((JScriptArray == NULL) || (pVtResult == NULL)) return E_POINTER;
// Initialise the variants
VariantInit(&vtPropertyValue); VariantInit(&vtTemp);
// Clear the return value
VariantClear(pVtResult);
// Fudge a 'try' block by using a once-only 'do' loop. Can't use
// try-throw-catch in ATL MinDependency builds without linking in the CRT
do { // Get the length of the array, if available
hr = HrGetProperty(JScriptArray, L"length", &vtPropertyValue); if (SUCCEEDED(hr)) { // Change to a 'long'
hr = VariantChangeType(&vtTemp, &vtPropertyValue, 0, VT_I4); if (SUCCEEDED(hr)) { cElements = vtTemp.lVal;
// Create the array with the correct size
pSArrayBounds[0].lLbound = 0; pSArrayBounds[0].cElements = cElements; pSArray = SafeArrayCreate(VT_VARIANT, 1, pSArrayBounds);
// Couldn't create the array
if (pSArray == NULL) { hr = E_OUTOFMEMORY; break; }
// We know the size of the array, so it can be locked now
// for faster access
bFixedSizeArray = true; hr = SafeArrayAccessData(pSArray, (void **) &pvtData);
// Couldn't lock data - something wrong
if (FAILED(hr)) { break; } } }
// Couldn't get the length (should never happen?), so create an empty array
if (FAILED(hr)) { // Default to maximum possible size
cElements = LONG_MAX;
// Create the array with zero size
pSArrayBounds[0].lLbound = 0; pSArrayBounds[0].cElements = 0; pSArray = SafeArrayCreate(VT_VARIANT, 1, pSArrayBounds);
// Couldn't create the array
if (pSArray == NULL) { hr = E_OUTOFMEMORY; break; }
// Need to dynamically size the array
bFixedSizeArray = false; }
// Allocate memory for the wide version of the property value
pszPropertyIndex = (OLECHAR *) CoTaskMemAlloc(sizeof(OLECHAR) * MAX_PATH);
// Start at 0
for (lIndex = 0; lIndex < cElements; lIndex++) { // Get name of the next indexed element, and convert to Unicode
sprintf(szTemp, "%ld", lIndex); MultiByteToWideChar(CP_ACP, NULL, szTemp, -1, pszPropertyIndex, MAX_PATH);
// See if such a property exists, and get it
hr = HrGetProperty(JScriptArray, pszPropertyIndex, &vtPropertyValue); if (SUCCEEDED(hr)) { // Redim the array if needed (expensive!). There are 'better' ways to
// do this, eg increase the size of the array in "chunks" and then
// cut back extra elements at the end, etc.
if (bFixedSizeArray == false) { // Increase the size of the array, and lock the data
pSArrayBounds->cElements++; hr = SafeArrayRedim(pSArray, pSArrayBounds); hr = SafeArrayAccessData(pSArray, (void **) &pvtData); } else hr = S_OK;
if (SUCCEEDED(hr)) { hr = VariantCopy(&(pvtData[lIndex]), &vtPropertyValue);
// Unlock data again, if necessary
if (bFixedSizeArray == false) { SafeArrayUnaccessData(pSArray); } }
VariantClear(&vtPropertyValue); }
// If we couldn't determine the length, and the property get
// failed, then quit the loop. Don't quit if we know the length
// because the array could be sparse
if ((FAILED(hr)) && (bFixedSizeArray == false)) break; } // Unlock data for fixed-size array
if (bFixedSizeArray) { SafeArrayUnaccessData(pSArray); } // only do the loop once
} while (false);
// Clean up
VariantClear(&vtPropertyValue); VariantClear(&vtTemp); if (pszPropertyIndex != NULL) CoTaskMemFree(pszPropertyIndex);
// Success - the loop terminated because we got an array index
// that didn't exist, or we got all the elements
if ((hr == DISP_E_UNKNOWNNAME) || (lIndex == cElements)) { pVtResult->vt = VT_VARIANT | VT_ARRAY; pVtResult->parray = pSArray;
return S_OK; } // Loop terminated for another reason - fail
else { SafeArrayDestroy(pSArray); return hr; } }
/*
* Function: HrConvertStringToLong() * * Author: Shyam Pather (SPATHER) * * Purpose: Converts a string representation of a number into a long. * Handles decimal and hexadecimal numbers. * * Arguments: * pwsz [in] The string representation of the number * plValue [out] Returns the long representation of the number, if * the function succeeds. * * Return Value: * S_OK if successful, other HRESULT otherwise. * * Notes: * Format of the input string: * - sign may be indicated by a '+' or '-' at the beginning of the * string (if no sign is specified, the number is assumed to be * positive) * - leading zeroes are ignored * - if the string contains "0x" or "0X" after the optional sign * character, it is assumed to represent a hexadecimal number, * otherwise it is assumed to represent a decimal number (and * any hex digits found are considered invalid) * - letters in hexadecimal numbers may be specified in upper or * lower case * * Known limitations: * - will allow a string containing more than one consecutive * leading sign character ('+' or '-') to be parsed - only the * last sign character will be considered. e.g. will convert * "---+--+1" to 1 and "+++-+--1" to -1. * - allows zeroes to be mixed in with leading sign characters - * these are ignored e.g. will convert "++0--1" to -1. */
HRESULT HrConvertStringToLong( IN LPWSTR pwsz, OUT LONG * plValue) { HRESULT hr = S_OK; int iSign = 1; int iBase = 10;
*plValue = 0;
if (pwsz) { size_t ucch = 0; BOOL bDoneLeader = FALSE;
// Take care of any leader characters.
while (!bDoneLeader) { switch (pwsz[0]) { case L'+': iSign = 1; break; case L'-': iSign = -1; break; case L'0': // Ignore leading zero.
break; case L'x': iBase = 16; break; case L'X': iBase = 16; break;
default: bDoneLeader = TRUE; };
if (!bDoneLeader) pwsz++; };
// Count remaining characters - these are the digits.
ucch = wcslen(pwsz);
if (ucch) { // Go through the string and determine the value of each digit.
LPBYTE rgbDigitVals = NULL;
rgbDigitVals = new BYTE [ucch];
if (rgbDigitVals) { for (unsigned int i = 0; i < ucch; i++) { if ((pwsz[i] >= L'0') && (pwsz[i] <= L'9')) { rgbDigitVals[i] = pwsz[i] - L'0'; } else if ((16 == iBase) && (pwsz[i] >= L'A') && (pwsz[i] <= L'F')) { rgbDigitVals[i] = 10 + pwsz[i] - L'A'; } else if ((16 == iBase) && (pwsz[i] >= L'a') && (pwsz[i] <= L'f')) { rgbDigitVals[i] = 10 + pwsz[i] - L'a'; } else { // Invalid digit encountered.
hr = E_INVALIDARG; break; } }
// If no invalid digits encountered, calculate the final number.
if (SUCCEEDED(hr)) { LONG lVal = 0; LONG lPlaceValue = 1; UINT j = ucch - 1;
// Have to start from the back of the array (least significant position).
for ( ; j != (UINT(-1)); --j) { // Calculate the value of this digit and add it to the result.
lVal += rgbDigitVals[j] * lPlaceValue;
// Calculate the value of the next digit position (i.e. in decimal, the first
// position has value 1, the second, value 10, the third, value 100 etc).
lPlaceValue *= iBase; }
lVal *= iSign; // Properly adjust for sign.
*plValue = lVal; }
MemFree(rgbDigitVals); rgbDigitVals = NULL; } else { hr = E_OUTOFMEMORY; } } }
return hr; }
HRESULT HrBytesToVariantArray( IN LPBYTE pbData, IN ULONG cbData, OUT VARIANT *pVariant ) { HRESULT hr = E_FAIL; SAFEARRAY * pArrayVal = NULL; SAFEARRAYBOUND arrayBound; CHAR HUGEP * pArray = NULL;
// Set bound for array
arrayBound.lLbound = 0; arrayBound.cElements = cbData;
// Create the safe array for the octet string. unsigned char elements;single dimension;aBound size.
pArrayVal = SafeArrayCreate(VT_UI1, 1, &arrayBound); if (pArrayVal) { hr = SafeArrayAccessData(pArrayVal, (void HUGEP * FAR *) &pArray); if (SUCCEEDED(hr)) { // Copy the bytes to the safe array.
CopyMemory(pArray, pbData, arrayBound.cElements); SafeArrayUnaccessData(pArrayVal);
// Set type to array of unsigned char
V_VT(pVariant) = VT_ARRAY | VT_UI1;
// Assign the safe array to the array member.
V_ARRAY(pVariant) = pArrayVal; hr = S_OK; } else { // Clean up if array can't be accessed.
if (pArrayVal) { SafeArrayDestroy(pArrayVal); } } } else { hr = E_OUTOFMEMORY; }
TraceError("HrBytesToVariantArray", hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: HrGetGITPointer
//
// Purpose: Returns a pointer to the system-supplied implementation
// of IGlobalInterfaceTable for the current apartment.
//
// Arguments:
// [out] ppgit On return, contains an IGlobalInterfaceTable
// reference which must be freed when no longer needed.
//
//
// Returns:
//
HRESULT HrGetGITPointer(IGlobalInterfaceTable ** ppgit) { Assert(ppgit);
HRESULT hr; IGlobalInterfaceTable * pgit;
pgit = NULL;
hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (LPVOID*)&pgit); if (FAILED(hr)) { TraceError("HrGetGITPointer: CoCreateInstance", hr); pgit = NULL; }
*ppgit = pgit;
Assert(FImplies(SUCCEEDED(hr), pgit)); Assert(FImplies(FAILED(hr), !pgit));
TraceError("HrGetGITPointer", hr); return hr; }
|