Source code of Windows XP (NT5)
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.

455 lines
13 KiB

  1. #include <pch.h>
  2. #pragma hdrstop
  3. #include "ncutil.h"
  4. #include "oleauto.h"
  5. #include "limits.h"
  6. #include "stdio.h"
  7. HRESULT HrGetProperty(IDispatch * lpObject, OLECHAR *lpszProperty, VARIANT * lpResult)
  8. {
  9. HRESULT hr;
  10. DISPID pDisp;
  11. DISPPARAMS dp;
  12. // Setup empty DISPPARAMS structure
  13. dp.rgvarg = NULL;
  14. dp.rgdispidNamedArgs = NULL;
  15. dp.cArgs = 0;
  16. dp.cNamedArgs = 0;
  17. // Clear out the result value
  18. VariantClear(lpResult);
  19. // See if such a property exists
  20. hr = lpObject->GetIDsOfNames(IID_NULL, &lpszProperty, 1, LOCALE_SYSTEM_DEFAULT, &pDisp);
  21. if (SUCCEEDED(hr))
  22. {
  23. // Get the property from the object
  24. hr = lpObject->Invoke(pDisp, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  25. DISPATCH_PROPERTYGET, &dp, lpResult, NULL, NULL);
  26. }
  27. return hr;
  28. }
  29. HRESULT HrJScriptArrayToSafeArray(IDispatch *JScriptArray, VARIANT * pVtResult)
  30. {
  31. HRESULT hr = E_UNEXPECTED;
  32. VARIANT vtPropertyValue, vtTemp, *pvtData;
  33. SAFEARRAY *pSArray = NULL;
  34. SAFEARRAYBOUND pSArrayBounds[1];
  35. long lIndex = -1;
  36. long cElements = -1;
  37. char szTemp[MAX_PATH];
  38. bool bFixedSizeArray = false;
  39. OLECHAR *pszPropertyIndex = NULL;
  40. if ((JScriptArray == NULL) || (pVtResult == NULL))
  41. return E_POINTER;
  42. // Initialise the variants
  43. VariantInit(&vtPropertyValue);
  44. VariantInit(&vtTemp);
  45. // Clear the return value
  46. VariantClear(pVtResult);
  47. // Fudge a 'try' block by using a once-only 'do' loop. Can't use
  48. // try-throw-catch in ATL MinDependency builds without linking in the CRT
  49. do
  50. {
  51. // Get the length of the array, if available
  52. hr = HrGetProperty(JScriptArray, L"length", &vtPropertyValue);
  53. if (SUCCEEDED(hr))
  54. {
  55. // Change to a 'long'
  56. hr = VariantChangeType(&vtTemp, &vtPropertyValue, 0, VT_I4);
  57. if (SUCCEEDED(hr))
  58. {
  59. cElements = vtTemp.lVal;
  60. // Create the array with the correct size
  61. pSArrayBounds[0].lLbound = 0;
  62. pSArrayBounds[0].cElements = cElements;
  63. pSArray = SafeArrayCreate(VT_VARIANT, 1, pSArrayBounds);
  64. // Couldn't create the array
  65. if (pSArray == NULL)
  66. {
  67. hr = E_OUTOFMEMORY;
  68. break;
  69. }
  70. // We know the size of the array, so it can be locked now
  71. // for faster access
  72. bFixedSizeArray = true;
  73. hr = SafeArrayAccessData(pSArray, (void **) &pvtData);
  74. // Couldn't lock data - something wrong
  75. if (FAILED(hr))
  76. {
  77. break;
  78. }
  79. }
  80. }
  81. // Couldn't get the length (should never happen?), so create an empty array
  82. if (FAILED(hr))
  83. {
  84. // Default to maximum possible size
  85. cElements = LONG_MAX;
  86. // Create the array with zero size
  87. pSArrayBounds[0].lLbound = 0;
  88. pSArrayBounds[0].cElements = 0;
  89. pSArray = SafeArrayCreate(VT_VARIANT, 1, pSArrayBounds);
  90. // Couldn't create the array
  91. if (pSArray == NULL)
  92. {
  93. hr = E_OUTOFMEMORY;
  94. break;
  95. }
  96. // Need to dynamically size the array
  97. bFixedSizeArray = false;
  98. }
  99. // Allocate memory for the wide version of the property value
  100. pszPropertyIndex = (OLECHAR *) CoTaskMemAlloc(sizeof(OLECHAR) * MAX_PATH);
  101. // Start at 0
  102. for (lIndex = 0; lIndex < cElements; lIndex++)
  103. {
  104. // Get name of the next indexed element, and convert to Unicode
  105. sprintf(szTemp, "%ld", lIndex);
  106. MultiByteToWideChar(CP_ACP, NULL, szTemp, -1, pszPropertyIndex, MAX_PATH);
  107. // See if such a property exists, and get it
  108. hr = HrGetProperty(JScriptArray, pszPropertyIndex, &vtPropertyValue);
  109. if (SUCCEEDED(hr))
  110. {
  111. // Redim the array if needed (expensive!). There are 'better' ways to
  112. // do this, eg increase the size of the array in "chunks" and then
  113. // cut back extra elements at the end, etc.
  114. if (bFixedSizeArray == false)
  115. {
  116. // Increase the size of the array, and lock the data
  117. pSArrayBounds->cElements++;
  118. hr = SafeArrayRedim(pSArray, pSArrayBounds);
  119. hr = SafeArrayAccessData(pSArray, (void **) &pvtData);
  120. }
  121. else
  122. hr = S_OK;
  123. if (SUCCEEDED(hr))
  124. {
  125. hr = VariantCopy(&(pvtData[lIndex]),
  126. &vtPropertyValue);
  127. // Unlock data again, if necessary
  128. if (bFixedSizeArray == false)
  129. {
  130. SafeArrayUnaccessData(pSArray);
  131. }
  132. }
  133. VariantClear(&vtPropertyValue);
  134. }
  135. // If we couldn't determine the length, and the property get
  136. // failed, then quit the loop. Don't quit if we know the length
  137. // because the array could be sparse
  138. if ((FAILED(hr)) && (bFixedSizeArray == false))
  139. break;
  140. }
  141. // Unlock data for fixed-size array
  142. if (bFixedSizeArray)
  143. {
  144. SafeArrayUnaccessData(pSArray);
  145. }
  146. // only do the loop once
  147. } while (false);
  148. // Clean up
  149. VariantClear(&vtPropertyValue);
  150. VariantClear(&vtTemp);
  151. if (pszPropertyIndex != NULL)
  152. CoTaskMemFree(pszPropertyIndex);
  153. // Success - the loop terminated because we got an array index
  154. // that didn't exist, or we got all the elements
  155. if ((hr == DISP_E_UNKNOWNNAME) || (lIndex == cElements))
  156. {
  157. pVtResult->vt = VT_VARIANT | VT_ARRAY;
  158. pVtResult->parray = pSArray;
  159. return S_OK;
  160. }
  161. // Loop terminated for another reason - fail
  162. else
  163. {
  164. SafeArrayDestroy(pSArray);
  165. return hr;
  166. }
  167. }
  168. /*
  169. * Function: HrConvertStringToLong()
  170. *
  171. * Author: Shyam Pather (SPATHER)
  172. *
  173. * Purpose: Converts a string representation of a number into a long.
  174. * Handles decimal and hexadecimal numbers.
  175. *
  176. * Arguments:
  177. * pwsz [in] The string representation of the number
  178. * plValue [out] Returns the long representation of the number, if
  179. * the function succeeds.
  180. *
  181. * Return Value:
  182. * S_OK if successful, other HRESULT otherwise.
  183. *
  184. * Notes:
  185. * Format of the input string:
  186. * - sign may be indicated by a '+' or '-' at the beginning of the
  187. * string (if no sign is specified, the number is assumed to be
  188. * positive)
  189. * - leading zeroes are ignored
  190. * - if the string contains "0x" or "0X" after the optional sign
  191. * character, it is assumed to represent a hexadecimal number,
  192. * otherwise it is assumed to represent a decimal number (and
  193. * any hex digits found are considered invalid)
  194. * - letters in hexadecimal numbers may be specified in upper or
  195. * lower case
  196. *
  197. * Known limitations:
  198. * - will allow a string containing more than one consecutive
  199. * leading sign character ('+' or '-') to be parsed - only the
  200. * last sign character will be considered. e.g. will convert
  201. * "---+--+1" to 1 and "+++-+--1" to -1.
  202. * - allows zeroes to be mixed in with leading sign characters -
  203. * these are ignored e.g. will convert "++0--1" to -1.
  204. */
  205. HRESULT
  206. HrConvertStringToLong(
  207. IN LPWSTR pwsz,
  208. OUT LONG * plValue)
  209. {
  210. HRESULT hr = S_OK;
  211. int iSign = 1;
  212. int iBase = 10;
  213. *plValue = 0;
  214. if (pwsz)
  215. {
  216. size_t ucch = 0;
  217. BOOL bDoneLeader = FALSE;
  218. // Take care of any leader characters.
  219. while (!bDoneLeader)
  220. {
  221. switch (pwsz[0])
  222. {
  223. case L'+':
  224. iSign = 1;
  225. break;
  226. case L'-':
  227. iSign = -1;
  228. break;
  229. case L'0':
  230. // Ignore leading zero.
  231. break;
  232. case L'x':
  233. iBase = 16;
  234. break;
  235. case L'X':
  236. iBase = 16;
  237. break;
  238. default:
  239. bDoneLeader = TRUE;
  240. };
  241. if (!bDoneLeader)
  242. pwsz++;
  243. };
  244. // Count remaining characters - these are the digits.
  245. ucch = wcslen(pwsz);
  246. if (ucch)
  247. {
  248. // Go through the string and determine the value of each digit.
  249. LPBYTE rgbDigitVals = NULL;
  250. rgbDigitVals = new BYTE [ucch];
  251. if (rgbDigitVals)
  252. {
  253. for (unsigned int i = 0; i < ucch; i++)
  254. {
  255. if ((pwsz[i] >= L'0') && (pwsz[i] <= L'9'))
  256. {
  257. rgbDigitVals[i] = pwsz[i] - L'0';
  258. }
  259. else if ((16 == iBase) && (pwsz[i] >= L'A') && (pwsz[i] <= L'F'))
  260. {
  261. rgbDigitVals[i] = 10 + pwsz[i] - L'A';
  262. }
  263. else if ((16 == iBase) && (pwsz[i] >= L'a') && (pwsz[i] <= L'f'))
  264. {
  265. rgbDigitVals[i] = 10 + pwsz[i] - L'a';
  266. }
  267. else
  268. {
  269. // Invalid digit encountered.
  270. hr = E_INVALIDARG;
  271. break;
  272. }
  273. }
  274. // If no invalid digits encountered, calculate the final number.
  275. if (SUCCEEDED(hr))
  276. {
  277. LONG lVal = 0;
  278. LONG lPlaceValue = 1;
  279. UINT j = ucch - 1;
  280. // Have to start from the back of the array (least significant position).
  281. for ( ; j != (UINT(-1)); --j)
  282. {
  283. // Calculate the value of this digit and add it to the result.
  284. lVal += rgbDigitVals[j] * lPlaceValue;
  285. // Calculate the value of the next digit position (i.e. in decimal, the first
  286. // position has value 1, the second, value 10, the third, value 100 etc).
  287. lPlaceValue *= iBase;
  288. }
  289. lVal *= iSign; // Properly adjust for sign.
  290. *plValue = lVal;
  291. }
  292. MemFree(rgbDigitVals);
  293. rgbDigitVals = NULL;
  294. }
  295. else
  296. {
  297. hr = E_OUTOFMEMORY;
  298. }
  299. }
  300. }
  301. return hr;
  302. }
  303. HRESULT
  304. HrBytesToVariantArray(
  305. IN LPBYTE pbData,
  306. IN ULONG cbData,
  307. OUT VARIANT *pVariant
  308. )
  309. {
  310. HRESULT hr = E_FAIL;
  311. SAFEARRAY * pArrayVal = NULL;
  312. SAFEARRAYBOUND arrayBound;
  313. CHAR HUGEP * pArray = NULL;
  314. // Set bound for array
  315. arrayBound.lLbound = 0;
  316. arrayBound.cElements = cbData;
  317. // Create the safe array for the octet string. unsigned char elements;single dimension;aBound size.
  318. pArrayVal = SafeArrayCreate(VT_UI1, 1, &arrayBound);
  319. if (pArrayVal)
  320. {
  321. hr = SafeArrayAccessData(pArrayVal, (void HUGEP * FAR *) &pArray);
  322. if (SUCCEEDED(hr))
  323. {
  324. // Copy the bytes to the safe array.
  325. CopyMemory(pArray, pbData, arrayBound.cElements);
  326. SafeArrayUnaccessData(pArrayVal);
  327. // Set type to array of unsigned char
  328. V_VT(pVariant) = VT_ARRAY | VT_UI1;
  329. // Assign the safe array to the array member.
  330. V_ARRAY(pVariant) = pArrayVal;
  331. hr = S_OK;
  332. }
  333. else
  334. {
  335. // Clean up if array can't be accessed.
  336. if (pArrayVal)
  337. {
  338. SafeArrayDestroy(pArrayVal);
  339. }
  340. }
  341. }
  342. else
  343. {
  344. hr = E_OUTOFMEMORY;
  345. }
  346. TraceError("HrBytesToVariantArray", hr);
  347. return hr;
  348. }
  349. //+---------------------------------------------------------------------------
  350. //
  351. // Function: HrGetGITPointer
  352. //
  353. // Purpose: Returns a pointer to the system-supplied implementation
  354. // of IGlobalInterfaceTable for the current apartment.
  355. //
  356. // Arguments:
  357. // [out] ppgit On return, contains an IGlobalInterfaceTable
  358. // reference which must be freed when no longer needed.
  359. //
  360. //
  361. // Returns:
  362. //
  363. HRESULT
  364. HrGetGITPointer(IGlobalInterfaceTable ** ppgit)
  365. {
  366. Assert(ppgit);
  367. HRESULT hr;
  368. IGlobalInterfaceTable * pgit;
  369. pgit = NULL;
  370. hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
  371. NULL,
  372. CLSCTX_INPROC_SERVER,
  373. IID_IGlobalInterfaceTable,
  374. (LPVOID*)&pgit);
  375. if (FAILED(hr))
  376. {
  377. TraceError("HrGetGITPointer: CoCreateInstance", hr);
  378. pgit = NULL;
  379. }
  380. *ppgit = pgit;
  381. Assert(FImplies(SUCCEEDED(hr), pgit));
  382. Assert(FImplies(FAILED(hr), !pgit));
  383. TraceError("HrGetGITPointer", hr);
  384. return hr;
  385. }