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.

444 lines
11 KiB

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