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.

471 lines
12 KiB

  1. #include "stock.h"
  2. #pragma hdrstop
  3. #include <varutil.h>
  4. #include <shdocvw.h>
  5. #include <strsafe.h>
  6. // ---------------------------------------------------
  7. //
  8. // InitVariantFrom... functions
  9. //
  10. STDAPI InitVariantFromInt(VARIANT *pvar, int lVal)
  11. {
  12. pvar->vt = VT_I4;
  13. pvar->lVal = lVal;
  14. return S_OK;
  15. }
  16. STDAPI InitVariantFromUINT(VARIANT *pvar, UINT ulVal)
  17. {
  18. pvar->vt = VT_UI4;
  19. pvar->ulVal = ulVal;
  20. return S_OK;
  21. }
  22. STDAPI InitVariantFromULONGLONG(VARIANT *pvar, ULONGLONG ullVal)
  23. {
  24. pvar->vt = VT_UI8;
  25. pvar->ullVal = ullVal;
  26. return S_OK;
  27. }
  28. STDAPI_(UINT) VariantToUINT(VARIANT varIn)
  29. {
  30. VARIANT varResult = {0};
  31. return SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_UI4)) ? varResult.ulVal : 0;
  32. }
  33. STDAPI_(int) VariantToInt(VARIANT varIn)
  34. {
  35. VARIANT varResult = {0};
  36. return SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_I4)) ? varResult.lVal : 0;
  37. }
  38. STDAPI_(BOOL) VariantToBOOL(VARIANT varIn)
  39. {
  40. VARIANT varResult = {0};
  41. if (SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_BOOL)))
  42. return (varResult.boolVal == VARIANT_FALSE) ? FALSE : TRUE;
  43. return FALSE;
  44. }
  45. STDAPI_(ULONGLONG) VariantToULONGLONG(VARIANT varIn)
  46. {
  47. VARIANT varResult = {0};
  48. return SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_UI8)) ? varResult.ullVal : 0;
  49. }
  50. STDAPI_(BOOL) VariantToBuffer(const VARIANT* pvar, void *pv, UINT cb)
  51. {
  52. if (pvar && pvar->vt == (VT_ARRAY | VT_UI1))
  53. {
  54. LONG lLBound;
  55. LONG lUBound;
  56. void *pvb;
  57. if ( SafeArrayGetDim(pvar->parray) == 1
  58. && SUCCEEDED(SafeArrayGetLBound(pvar->parray, 1, &lLBound))
  59. && SUCCEEDED(SafeArrayGetUBound(pvar->parray, 1, &lUBound))
  60. && (UINT)(lUBound - lLBound) + 1 >= cb
  61. && SUCCEEDED(SafeArrayAccessData(pvar->parray, &pvb)))
  62. {
  63. CopyMemory(pv, pvb, cb);
  64. SafeArrayUnaccessData(pvar->parray);
  65. return TRUE;
  66. }
  67. }
  68. return FALSE;
  69. }
  70. STDAPI_(BOOL) VariantToGUID(const VARIANT *pvar, GUID *pguid)
  71. {
  72. return VariantToBuffer(pvar, pguid, sizeof(*pguid));
  73. }
  74. STDAPI_(LPCWSTR) VariantToStrCast(const VARIANT *pvar)
  75. {
  76. LPCWSTR psz = NULL;
  77. ASSERT(!IsBadReadPtr(pvar, sizeof(pvar)));
  78. if (pvar->vt == (VT_BYREF | VT_VARIANT) && pvar->pvarVal)
  79. pvar = pvar->pvarVal;
  80. if (pvar->vt == VT_BSTR)
  81. psz = pvar->bstrVal;
  82. else if (pvar->vt == (VT_BSTR | VT_BYREF))
  83. psz = *pvar->pbstrVal;
  84. return psz;
  85. }
  86. STDAPI InitVariantFromBuffer(VARIANT *pvar, const void *pv, UINT cb)
  87. {
  88. HRESULT hr;
  89. VariantInit(pvar);
  90. SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, cb); // create a one-dimensional safe array
  91. if (psa)
  92. {
  93. CopyMemory(psa->pvData, pv, cb);
  94. pvar->vt = VT_ARRAY | VT_UI1;
  95. pvar->parray = psa;
  96. hr = S_OK;
  97. }
  98. else
  99. hr = E_OUTOFMEMORY;
  100. return hr;
  101. }
  102. STDAPI_(UINT) _MyILGetSize(LPCITEMIDLIST pidl)
  103. {
  104. UINT cbTotal = 0;
  105. if (pidl)
  106. {
  107. cbTotal += sizeof(pidl->mkid.cb); // Null terminator
  108. while (pidl->mkid.cb)
  109. {
  110. cbTotal += pidl->mkid.cb;
  111. pidl = _ILNext(pidl);
  112. }
  113. }
  114. return cbTotal;
  115. }
  116. STDAPI InitVariantFromIDList(VARIANT* pvar, LPCITEMIDLIST pidl)
  117. {
  118. return InitVariantFromBuffer(pvar, pidl, _MyILGetSize(pidl));
  119. }
  120. STDAPI InitVariantFromGUID(VARIANT *pvar, REFGUID guid)
  121. {
  122. return InitVariantFromBuffer(pvar, &guid, sizeof(guid));
  123. }
  124. STDAPI InitBSTRVariantFromGUID(VARIANT *pvar, REFGUID guid)
  125. {
  126. WCHAR wszGuid[GUIDSTR_MAX];
  127. HRESULT hr;
  128. if (SUCCEEDED(SHStringFromGUIDW(guid, wszGuid, ARRAYSIZE(wszGuid))))
  129. {
  130. hr = InitVariantFromStr(pvar, wszGuid);
  131. }
  132. else
  133. {
  134. hr = E_FAIL;
  135. VariantInit(pvar);
  136. }
  137. return hr;
  138. }
  139. // note, this frees the STRRET contents
  140. STDAPI InitVariantFromStrRet(STRRET *pstrret, LPCITEMIDLIST pidl, VARIANT *pv)
  141. {
  142. WCHAR szTemp[INFOTIPSIZE];
  143. HRESULT hres = StrRetToBufW(pstrret, pidl, szTemp, ARRAYSIZE(szTemp));
  144. if (SUCCEEDED(hres))
  145. {
  146. pv->bstrVal = SysAllocString(szTemp);
  147. if (pv->bstrVal)
  148. pv->vt = VT_BSTR;
  149. hres = pv->bstrVal ? S_OK : E_OUTOFMEMORY;
  150. }
  151. return hres;
  152. }
  153. // returns:
  154. // S_OK success
  155. // S_FALSE successfully created an empty string from a NULL [in] parameter
  156. // E_OUTOFMEMORY
  157. STDAPI InitVariantFromStr(VARIANT *pvar, LPCWSTR psz)
  158. {
  159. VariantInit(pvar);
  160. // There is no NULL bstr value, so convert NULL to "".
  161. pvar->bstrVal = SysAllocString(psz ? psz : L"");
  162. if (pvar->bstrVal)
  163. pvar->vt = VT_BSTR;
  164. return pvar->bstrVal ? (psz ? S_OK : S_FALSE) : E_OUTOFMEMORY;
  165. }
  166. // time is in GMT. this function converts to local time
  167. STDAPI InitVariantFromFileTime(const FILETIME *pft, VARIANT *pv)
  168. {
  169. SYSTEMTIME st;
  170. FILETIME ftLocal;
  171. FileTimeToLocalFileTime(pft, &ftLocal);
  172. //
  173. // Watch out for the special filesystem "uninitialized" values.
  174. //
  175. if (FILETIMEtoInt64(*pft) == FT_NTFS_UNKNOWNGMT ||
  176. FILETIMEtoInt64(ftLocal) == FT_FAT_UNKNOWNLOCAL)
  177. return E_FAIL;
  178. FileTimeToSystemTime(pft, &st);
  179. pv->vt = VT_DATE;
  180. return SystemTimeToVariantTime(&st, &pv->date) ? S_OK : E_FAIL; // delay load...
  181. }
  182. // Note: will allocate it for you if you pass NULL pszBuf
  183. STDAPI_(LPTSTR) VariantToStr(const VARIANT *pvar, LPWSTR pszBuf, int cchBuf)
  184. {
  185. TCHAR szBuf[INFOTIPSIZE];
  186. if (pszBuf)
  187. {
  188. DEBUGWhackPathBuffer(pszBuf, cchBuf);
  189. }
  190. else
  191. {
  192. pszBuf = szBuf;
  193. cchBuf = ARRAYSIZE(szBuf);
  194. }
  195. *pszBuf = 0;
  196. BOOL fDone = FALSE;
  197. if (pvar->vt == VT_DATE) // we want our date formatting
  198. {
  199. USHORT wDosDate, wDosTime;
  200. if (VariantTimeToDosDateTime(pvar->date, &wDosDate, &wDosTime))
  201. {
  202. DosTimeToDateTimeString(wDosDate, wDosTime, pszBuf, cchBuf, 0);
  203. fDone = TRUE;
  204. }
  205. }
  206. if (!fDone)
  207. {
  208. VARIANT varDst = {0};
  209. if (VT_BSTR != pvar->vt)
  210. {
  211. if (S_OK == VariantChangeType(&varDst, (VARIANT*)pvar, 0, VT_BSTR))
  212. {
  213. ASSERT(VT_BSTR == varDst.vt);
  214. pvar = &varDst;
  215. }
  216. else
  217. pszBuf = NULL; // error
  218. }
  219. if (VT_BSTR == pvar->vt && pvar->bstrVal)
  220. {
  221. StringCchCopy(pszBuf, cchBuf, pvar->bstrVal);
  222. }
  223. else
  224. {
  225. pszBuf = NULL; // something bad happened
  226. }
  227. if (pvar == &varDst)
  228. VariantClear(&varDst);
  229. }
  230. if (pszBuf == szBuf)
  231. return StrDup(szBuf);
  232. else
  233. return pszBuf;
  234. }
  235. // ---------------------------------------------------
  236. // [in,out] pvar: [in] initialized with property bag data
  237. // [out] data in format vtDesired or VT_EMPTY if no conversion
  238. // [in] vtDesired: [in] type to convert to, or VT_EMPTY to accept all types of data
  239. //
  240. STDAPI VariantChangeTypeForRead(VARIANT *pvar, VARTYPE vtDesired)
  241. {
  242. HRESULT hr = S_OK;
  243. if ((pvar->vt != vtDesired) && (vtDesired != VT_EMPTY))
  244. {
  245. VARIANT varTmp;
  246. VARIANT varSrc;
  247. // cache a copy of [in]pvar in varSrc - we will free this later
  248. CopyMemory(&varSrc, pvar, sizeof(varSrc));
  249. VARIANT* pvarToCopy = &varSrc;
  250. // oleaut's VariantChangeType doesn't support
  251. // hex number string -> number conversion, which we want,
  252. // so convert those to another format they understand.
  253. //
  254. // if we're in one of these cases, varTmp will be initialized
  255. // and pvarToCopy will point to it instead
  256. //
  257. if (VT_BSTR == varSrc.vt)
  258. {
  259. switch (vtDesired)
  260. {
  261. case VT_I1:
  262. case VT_I2:
  263. case VT_I4:
  264. case VT_INT:
  265. {
  266. if (StrToIntExW(varSrc.bstrVal, STIF_SUPPORT_HEX, &varTmp.intVal))
  267. {
  268. varTmp.vt = VT_INT;
  269. pvarToCopy = &varTmp;
  270. }
  271. break;
  272. }
  273. case VT_UI1:
  274. case VT_UI2:
  275. case VT_UI4:
  276. case VT_UINT:
  277. {
  278. if (StrToIntExW(varSrc.bstrVal, STIF_SUPPORT_HEX, (int*)&varTmp.uintVal))
  279. {
  280. varTmp.vt = VT_UINT;
  281. pvarToCopy = &varTmp;
  282. }
  283. break;
  284. }
  285. }
  286. }
  287. // clear our [out] buffer, in case VariantChangeType fails
  288. VariantInit(pvar);
  289. hr = VariantChangeType(pvar, pvarToCopy, 0, vtDesired);
  290. // clear the cached [in] value
  291. VariantClear(&varSrc);
  292. // if initialized, varTmp is VT_UINT or VT_UINT, neither of which need VariantClear
  293. }
  294. return hr;
  295. }
  296. // ---------------------------------------------------
  297. //
  298. // Other conversion functions
  299. //
  300. STDAPI_(BSTR) SysAllocStringA(LPCSTR psz)
  301. {
  302. if (psz)
  303. {
  304. WCHAR wsz[INFOTIPSIZE]; // assumes INFOTIPSIZE number of chars max
  305. SHAnsiToUnicode(psz, wsz, ARRAYSIZE(wsz));
  306. return SysAllocString(wsz);
  307. }
  308. return NULL;
  309. }
  310. STDAPI StringToStrRetW(LPCWSTR pszName, STRRET *pStrRet)
  311. {
  312. pStrRet->uType = STRRET_WSTR;
  313. return SHStrDupW(pszName, &pStrRet->pOleStr);
  314. }
  315. STDAPI_(void) DosTimeToDateTimeString(WORD wDate, WORD wTime, LPTSTR pszText, UINT cchText, int fmt)
  316. {
  317. FILETIME ft;
  318. DWORD dwFlags = FDTF_DEFAULT;
  319. // Netware directories do not have dates...
  320. if (wDate == 0)
  321. {
  322. *pszText = 0;
  323. return;
  324. }
  325. DosDateTimeToFileTime(wDate, wTime, &ft);
  326. switch (fmt) {
  327. case LVCFMT_LEFT_TO_RIGHT :
  328. dwFlags |= FDTF_LTRDATE;
  329. break;
  330. case LVCFMT_RIGHT_TO_LEFT :
  331. dwFlags |= FDTF_RTLDATE;
  332. break;
  333. }
  334. SHFormatDateTime(&ft, &dwFlags, pszText, cchText);
  335. }
  336. STDAPI GetDateProperty(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, FILETIME *pft)
  337. {
  338. VARIANT var = {0};
  339. HRESULT hr = psf->GetDetailsEx(pidl, pscid, &var);
  340. if (SUCCEEDED(hr))
  341. {
  342. hr = E_FAIL;
  343. if (VT_DATE == var.vt)
  344. {
  345. SYSTEMTIME st;
  346. if (VariantTimeToSystemTime(var.date, &st) && SystemTimeToFileTime(&st, pft))
  347. {
  348. hr = S_OK;
  349. }
  350. }
  351. VariantClear(&var); // Done with it.
  352. }
  353. return hr;
  354. }
  355. STDAPI GetLongProperty(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, ULONGLONG *pullVal)
  356. {
  357. *pullVal = 0;
  358. VARIANT var = {0};
  359. HRESULT hr = psf->GetDetailsEx(pidl, pscid, &var);
  360. if (SUCCEEDED(hr))
  361. {
  362. if (VT_UI8 == var.vt)
  363. {
  364. *pullVal = var.ullVal;
  365. hr = S_OK;
  366. }
  367. else
  368. {
  369. VARIANT varLong = {0};
  370. hr = VariantChangeType(&varLong, &var, 0, VT_UI8);
  371. if (SUCCEEDED(hr))
  372. {
  373. *pullVal = varLong.ullVal;
  374. VariantClear(&varLong);
  375. }
  376. }
  377. VariantClear(&var); // Done with it.
  378. }
  379. return hr;
  380. }
  381. STDAPI GetStringProperty(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, LPTSTR pszVal, int cchMax)
  382. {
  383. *pszVal = 0;
  384. VARIANT var = {0};
  385. HRESULT hr = psf->GetDetailsEx(pidl, pscid, &var);
  386. if (SUCCEEDED(hr))
  387. {
  388. hr = VariantToStr(&var, pszVal, cchMax) ? S_OK : E_FAIL;
  389. VariantClear(&var); // Done with it.
  390. }
  391. return hr;
  392. }
  393. STDAPI QueryInterfaceVariant(VARIANT v, REFIID riid, void **ppv)
  394. {
  395. *ppv = NULL;
  396. HRESULT hr = E_NOINTERFACE;
  397. if ((VT_UNKNOWN == v.vt) && v.punkVal)
  398. {
  399. hr = v.punkVal->QueryInterface(riid, ppv);
  400. }
  401. return hr;
  402. }