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.

441 lines
8.1 KiB

  1. //
  2. // util.cpp, implementation for various utility classes
  3. //
  4. #include "global.h"
  5. #include "util.h"
  6. extern LPCWSTR g_pwszSsrRootPath;
  7. extern const DWORD g_dwSsrRootPathLen;
  8. /*
  9. Routine Description:
  10. Name:
  11. CSafeArray::CSafeArray
  12. Functionality:
  13. Constructor. Will prepare our private data for a safearray variant.
  14. In case the in parameter is not a safearray, then we will behave as
  15. it is a one element array.
  16. Virtual:
  17. no.
  18. Arguments:
  19. none.
  20. Return Value:
  21. none.
  22. Notes:
  23. */
  24. CSafeArray::CSafeArray (
  25. IN VARIANT * pVal
  26. ) : m_pSA(NULL),
  27. m_pVal(NULL),
  28. m_ulSize(0),
  29. m_bValidArray(true)
  30. {
  31. if (pVal->vt & VT_ARRAY)
  32. {
  33. m_pSA = pVal->parray;
  34. if ( pVal->vt & VT_BYREF )
  35. {
  36. m_pSA = *(pVal->pparray);
  37. }
  38. LONG lb = 0;
  39. LONG ub = 0;
  40. ::SafeArrayGetLBound(m_pSA, 1, &lb);
  41. ::SafeArrayGetUBound(m_pSA, 1, &ub);
  42. m_ulSize = ub - lb + 1;
  43. //
  44. // we won't support it as an array, instead, we treat it as
  45. // a normal VARIANT
  46. //
  47. if (m_pSA->cDims > 2)
  48. {
  49. m_ulSize = 1;
  50. m_pVal = pVal;
  51. m_bValidArray = false;
  52. m_pSA = NULL;
  53. }
  54. }
  55. else
  56. {
  57. m_ulSize = 1;
  58. m_pVal = pVal;
  59. m_bValidArray = false;
  60. }
  61. }
  62. /*
  63. Routine Description:
  64. Name:
  65. CSafeArray::GetElement
  66. Functionality:
  67. Get the ulIndex-th element as the given (guid) interface object.
  68. Virtual:
  69. no.
  70. Arguments:
  71. none.
  72. Return Value:
  73. Success:
  74. S_OK
  75. Failure:
  76. various error codes.
  77. Notes:
  78. */
  79. HRESULT
  80. CSafeArray::GetElement (
  81. IN REFIID guid,
  82. IN ULONG ulIndex,
  83. OUT IUnknown ** ppUnk
  84. )
  85. {
  86. //
  87. // The following default return value is not really good for invalid
  88. // array var given to this object.
  89. //
  90. if (ppUnk == NULL || ulIndex >= m_ulSize)
  91. {
  92. return E_INVALIDARG;
  93. }
  94. else if (!m_bValidArray)
  95. {
  96. //
  97. // if the given variant is not an array, then
  98. // we will use the value to handle the request
  99. //
  100. if (ulIndex == 0 && m_pVal != NULL)
  101. {
  102. if (m_pVal->vt == VT_UNKNOWN)
  103. {
  104. return m_pVal->punkVal->QueryInterface(guid, (LPVOID*)ppUnk);
  105. }
  106. else if (m_pVal->vt == VT_DISPATCH)
  107. {
  108. return m_pVal->pdispVal->QueryInterface(guid, (LPVOID*)ppUnk);
  109. }
  110. else
  111. {
  112. return E_SSR_VARIANT_NOT_CONTAIN_OBJECT;
  113. }
  114. }
  115. else if (ulIndex >= 1)
  116. {
  117. return E_SSR_ARRAY_INDEX_OUT_OF_RANGE;
  118. }
  119. else
  120. {
  121. return E_SSR_NO_VALID_ELEMENT;
  122. }
  123. }
  124. HRESULT hr = E_INVALIDARG;
  125. *ppUnk = NULL;
  126. VARIANT v;
  127. ::VariantInit(&v);
  128. long index[1] = {ulIndex};
  129. hr = ::SafeArrayGetElement(m_pSA, index, &v);
  130. if (SUCCEEDED(hr) && v.vt == VT_UNKNOWN)
  131. {
  132. hr = v.punkVal->QueryInterface(guid, (LPVOID*)ppUnk);
  133. if (S_OK != hr)
  134. {
  135. hr = E_NOINTERFACE;
  136. }
  137. }
  138. else if (SUCCEEDED(hr) && v.vt == VT_DISPATCH)
  139. {
  140. hr = v.pdispVal->QueryInterface(guid, (LPVOID*)ppUnk);
  141. if (S_OK != hr)
  142. {
  143. hr = E_NOINTERFACE;
  144. }
  145. }
  146. else
  147. {
  148. hr = E_NOINTERFACE;
  149. }
  150. ::VariantClear(&v);
  151. return hr;
  152. }
  153. /*
  154. Routine Description:
  155. Name:
  156. CSafeArray::GetElement
  157. Functionality:
  158. Get the ulIndex-th element as the given type (non-interface).
  159. Virtual:
  160. no.
  161. Arguments:
  162. none.
  163. Return Value:
  164. Success:
  165. S_OK
  166. Failure:
  167. various error codes.
  168. Notes:
  169. */
  170. HRESULT
  171. CSafeArray::GetElement (
  172. IN ULONG ulIndex,
  173. IN VARTYPE vt,
  174. OUT VARIANT * pVal
  175. )
  176. {
  177. HRESULT hr = GetElement(ulIndex, pVal);
  178. //
  179. // if the types do not match, then we need to coerce it
  180. //
  181. if (SUCCEEDED(hr) && pVal->vt != vt)
  182. {
  183. VARIANT v;
  184. hr = ::VariantCopy(&v, pVal);
  185. ::VariantClear(pVal);
  186. if (SUCCEEDED(hr))
  187. {
  188. hr = ::VariantChangeType(pVal, &v, VARIANT_NOVALUEPROP, vt);
  189. }
  190. ::VariantClear(&v);
  191. }
  192. return hr;
  193. }
  194. /*
  195. Routine Description:
  196. Name:
  197. CSafeArray::GetElement
  198. Functionality:
  199. Get the ulIndex-th element as a variant.
  200. Virtual:
  201. no.
  202. Arguments:
  203. none.
  204. Return Value:
  205. Success:
  206. S_OK
  207. Failure:
  208. various error codes.
  209. Notes:
  210. */
  211. HRESULT
  212. CSafeArray::GetElement (
  213. IN ULONG ulIndex,
  214. OUT VARIANT * pVal
  215. )
  216. {
  217. if (pVal == NULL || ulIndex >= m_ulSize)
  218. {
  219. return E_INVALIDARG;
  220. }
  221. ::VariantInit(pVal);
  222. if (!m_bValidArray)
  223. {
  224. if (ulIndex == 0 && m_pVal != NULL)
  225. {
  226. return ::VariantCopy(pVal, m_pVal);
  227. }
  228. else if (ulIndex >= 1)
  229. {
  230. return E_SSR_ARRAY_INDEX_OUT_OF_RANGE;
  231. }
  232. else
  233. {
  234. return E_SSR_NO_VALID_ELEMENT;
  235. }
  236. }
  237. HRESULT hr = E_INVALIDARG;
  238. LONG index[2] = {ulIndex, 0};
  239. if (m_pSA->cDims > 1)
  240. {
  241. //
  242. // we must be dealing with 2-dimensional arrays because we don't
  243. // support more than that
  244. //
  245. LONG ilb = m_pSA->rgsabound[1].lLbound;
  246. LONG iSize = m_pSA->rgsabound[1].cElements;
  247. VARIANT * pvarValues = new VARIANT[iSize];
  248. if (pvarValues != NULL)
  249. {
  250. //
  251. // null all the contents
  252. //
  253. ::memset(pvarValues, 0, sizeof(VARIANT) * iSize);
  254. for (LONG i = ilb; i < ilb + iSize; i++)
  255. {
  256. //
  257. // Gett every element in the second dimension, so the index[1]
  258. //
  259. index[1] = i;
  260. hr = ::SafeArrayGetElement(m_pSA, index, &(pvarValues[i - ilb]));
  261. if (FAILED(hr))
  262. {
  263. break;
  264. }
  265. }
  266. if (SUCCEEDED(hr))
  267. {
  268. SAFEARRAYBOUND rgsabound[1];
  269. rgsabound[0].lLbound = 0;
  270. rgsabound[0].cElements = iSize;
  271. SAFEARRAY * psa = ::SafeArrayCreate(VT_VARIANT , 1, rgsabound);
  272. if (psa == NULL)
  273. {
  274. hr = E_OUTOFMEMORY;
  275. }
  276. else
  277. {
  278. //
  279. // put every element in the second dimension into the new safearray
  280. // BTW, this is a single dimension new safearray, so the index[0]
  281. //
  282. for (i = 0; i < iSize; i++)
  283. {
  284. index[0] = i;
  285. hr = ::SafeArrayPutElement(psa, index, &(pvarValues[i]));
  286. if (FAILED(hr))
  287. {
  288. break;
  289. }
  290. }
  291. if (SUCCEEDED(hr))
  292. {
  293. pVal->vt = VT_ARRAY | VT_VARIANT;
  294. pVal->parray = psa;
  295. }
  296. else
  297. {
  298. ::SafeArrayDestroy(psa);
  299. }
  300. }
  301. }
  302. //
  303. // now clean it up
  304. //
  305. for (i = 0; i < iSize; i++)
  306. {
  307. ::VariantClear(&(pvarValues[i]));
  308. }
  309. delete [] pvarValues;
  310. }
  311. }
  312. else
  313. {
  314. hr = ::SafeArrayGetElement(m_pSA, index, pVal);
  315. }
  316. return hr;
  317. }