|
|
#include "stock.h"
#pragma hdrstop
#include <varutil.h>
#include <shdocvw.h>
#define VariantInit(p) memset(p, 0, sizeof(*(p)))
// ---------------------------------------------------
//
// InitVariantFrom... functions
//
STDAPI InitVariantFromInt(VARIANT *pvar, int lVal) { pvar->vt = VT_I4; pvar->lVal = lVal; return S_OK; }
STDAPI InitVariantFromUINT(VARIANT *pvar, UINT ulVal) { pvar->vt = VT_UI4; pvar->ulVal = ulVal; return S_OK; }
STDAPI_(UINT) VariantToUINT(VARIANT varIn) { VARIANT varResult = {0}; return SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_UI4)) ? varResult.ulVal : 0; }
STDAPI_(int) VariantToInt(VARIANT varIn) { VARIANT varResult = {0}; return SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_I4)) ? varResult.lVal : 0; }
STDAPI_(BOOL) VariantToBOOL(VARIANT varIn) { VARIANT varResult = {0}; if (SUCCEEDED(VariantChangeType(&varResult, &varIn, 0, VT_BOOL))) return (varResult.boolVal == VARIANT_FALSE) ? FALSE : TRUE; return FALSE; }
STDAPI_(BOOL) VariantToBuffer(const VARIANT* pvar, void *pv, UINT cb) { if (pvar && pvar->vt == (VT_ARRAY | VT_UI1)) { CopyMemory(pv, pvar->parray->pvData, cb); return TRUE; } return FALSE; }
STDAPI_(BOOL) VariantToGUID(const VARIANT *pvar, GUID *pguid) { return VariantToBuffer(pvar, pguid, sizeof(*pguid)); }
STDAPI_(LPCWSTR) VariantToStrCast(const VARIANT *pvar) { LPCWSTR psz = NULL;
ASSERT(!IsBadReadPtr(pvar, sizeof(pvar)));
if (pvar->vt == (VT_BYREF | VT_VARIANT) && pvar->pvarVal) pvar = pvar->pvarVal;
if (pvar->vt == VT_BSTR) psz = pvar->bstrVal; else if (pvar->vt == (VT_BSTR | VT_BYREF)) psz = *pvar->pbstrVal; return psz; }
STDAPI InitVariantFromBuffer(VARIANT *pvar, const void *pv, UINT cb) { HRESULT hr; VariantInit(pvar); SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, cb); // create a one-dimensional safe array
if (psa) { CopyMemory(psa->pvData, pv, cb);
pvar->vt = VT_ARRAY | VT_UI1; pvar->parray = psa; hr = S_OK; } else hr = E_OUTOFMEMORY; return hr; }
STDAPI_(UINT) _MyILGetSize(LPCITEMIDLIST pidl) { UINT cbTotal = 0; if (pidl) { cbTotal += sizeof(pidl->mkid.cb); // Null terminator
while (pidl->mkid.cb) { cbTotal += pidl->mkid.cb; pidl = _ILNext(pidl); } } return cbTotal; }
STDAPI InitVariantFromIDList(VARIANT* pvar, LPCITEMIDLIST pidl) { return InitVariantFromBuffer(pvar, pidl, _MyILGetSize(pidl)); }
STDAPI InitVariantFromGUID(VARIANT *pvar, REFGUID guid) { return InitVariantFromBuffer(pvar, &guid, sizeof(guid)); }
STDAPI InitBSTRVariantFromGUID(VARIANT *pvar, REFGUID guid) { WCHAR wszGuid[GUIDSTR_MAX]; HRESULT hr; if (SUCCEEDED(SHStringFromGUIDW(guid, wszGuid, ARRAYSIZE(wszGuid)))) { hr = InitVariantFromStr(pvar, wszGuid); } else { hr = E_FAIL; VariantInit(pvar); } return hr; }
// note, this frees the STRRET contents
STDAPI InitVariantFromStrRet(STRRET *pstrret, LPCITEMIDLIST pidl, VARIANT *pv) { WCHAR szTemp[INFOTIPSIZE]; HRESULT hres = StrRetToBufW(pstrret, pidl, szTemp, ARRAYSIZE(szTemp)); if (SUCCEEDED(hres)) { pv->bstrVal = SysAllocString(szTemp); if (pv->bstrVal) pv->vt = VT_BSTR; hres = pv->bstrVal ? S_OK : E_OUTOFMEMORY; } return hres; }
// returns:
// S_OK success
// S_FALSE successfully created an empty string from a NULL [in] parameter
// E_OUTOFMEMORY
STDAPI InitVariantFromStr(VARIANT *pvar, LPCWSTR psz) { VariantInit(pvar);
// There is no NULL bstr value, so convert NULL to "".
pvar->bstrVal = SysAllocString(psz ? psz : L""); if (pvar->bstrVal) pvar->vt = VT_BSTR;
return pvar->bstrVal ? (psz ? S_OK : S_FALSE) : E_OUTOFMEMORY; }
// time is in GMT. this function converts to local time
STDAPI InitVariantFromFileTime(const FILETIME *pft, VARIANT *pv) { SYSTEMTIME st; FILETIME ftLocal;
FileTimeToLocalFileTime(pft, &ftLocal);
//
// Watch out for the special filesystem "uninitialized" values.
//
if (FILETIMEtoInt64(*pft) == FT_NTFS_UNKNOWNGMT || FILETIMEtoInt64(ftLocal) == FT_FAT_UNKNOWNLOCAL) return E_FAIL;
FileTimeToSystemTime(pft, &st); pv->vt = VT_DATE; return SystemTimeToVariantTime(&st, &pv->date) ? S_OK : E_FAIL; // delay load...
}
// Note: will allocate it for you if you pass NULL pszBuf
STDAPI_(LPTSTR) VariantToStr(const VARIANT *pvar, LPWSTR pszBuf, int cchBuf) { TCHAR szBuf[INFOTIPSIZE];
if (pszBuf) { DEBUGWhackPathBuffer(pszBuf, cchBuf); } else { pszBuf = szBuf; cchBuf = ARRAYSIZE(szBuf); } *pszBuf = 0;
BOOL fDone = FALSE; if (pvar->vt == VT_DATE) // we want our date formatting
{ USHORT wDosDate, wDosTime; if (VariantTimeToDosDateTime(pvar->date, &wDosDate, &wDosTime)) { DosTimeToDateTimeString(wDosDate, wDosTime, pszBuf, cchBuf, 0); fDone = TRUE; } }
if (!fDone) { VARIANT varDst = {0};
if (VT_BSTR != pvar->vt) { if (S_OK == VariantChangeType(&varDst, (VARIANT*)pvar, 0, VT_BSTR)) { ASSERT(VT_BSTR == varDst.vt);
pvar = &varDst; } else pszBuf = NULL; // error
} if (VT_BSTR == pvar->vt) { StrCpyNW(pszBuf, pvar->bstrVal, cchBuf); }
if (pvar == &varDst) VariantClear(&varDst); }
if (pszBuf == szBuf) return StrDup(szBuf); else return pszBuf; }
// ---------------------------------------------------
// [in,out] pvar: [in] initialized with property bag data
// [out] data in format vtDesired or VT_EMPTY if no conversion
// [in] vtDesired: [in] type to convert to, or VT_EMPTY to accept all types of data
//
STDAPI VariantChangeTypeForRead(VARIANT *pvar, VARTYPE vtDesired) { HRESULT hr = S_OK;
if ((pvar->vt != vtDesired) && (vtDesired != VT_EMPTY)) { VARIANT varTmp; VARIANT varSrc;
// cache a copy of [in]pvar in varSrc - we will free this later
CopyMemory(&varSrc, pvar, sizeof(varTmp)); VARIANT* pvarToCopy = &varSrc;
// oleaut's VariantChangeType doesn't support
// hex number string -> number conversion, which we want,
// so convert those to another format they understand.
//
// if we're in one of these cases, varTmp will be initialized
// and pvarToCopy will point to it instead
//
if (VT_BSTR == varSrc.vt) { switch (vtDesired) { case VT_I1: case VT_I2: case VT_I4: case VT_INT: { if (StrToIntExW(varSrc.bstrVal, STIF_SUPPORT_HEX, &varTmp.intVal)) { varTmp.vt = VT_INT; pvarToCopy = &varTmp; } break; }
case VT_UI1: case VT_UI2: case VT_UI4: case VT_UINT: { if (StrToIntExW(varSrc.bstrVal, STIF_SUPPORT_HEX, (int*)&varTmp.uintVal)) { varTmp.vt = VT_UINT; pvarToCopy = &varTmp; } break; } } }
// clear our [out] buffer, in case VariantChangeType fails
VariantInit(pvar);
hr = VariantChangeType(pvar, pvarToCopy, 0, vtDesired);
// clear the cached [in] value
VariantClear(&varSrc); // if initialized, varTmp is VT_UINT or VT_UINT, neither of which need VariantClear
}
return hr; }
// ---------------------------------------------------
//
// Other conversion functions
//
STDAPI_(BSTR) SysAllocStringA(LPCSTR psz) { if (psz) { WCHAR wsz[INFOTIPSIZE]; // assumes INFOTIPSIZE number of chars max
SHAnsiToUnicode(psz, wsz, ARRAYSIZE(wsz)); return SysAllocString(wsz); } return NULL; }
STDAPI StringToStrRetW(LPCWSTR pszName, STRRET *pStrRet) { pStrRet->uType = STRRET_WSTR; return SHStrDupW(pszName, &pStrRet->pOleStr); }
STDAPI_(void) DosTimeToDateTimeString(WORD wDate, WORD wTime, LPTSTR pszText, UINT cchText, int fmt) { FILETIME ft; DWORD dwFlags = FDTF_DEFAULT;
// Netware directories do not have dates...
if (wDate == 0) { *pszText = 0; return; }
DosDateTimeToFileTime(wDate, wTime, &ft); switch (fmt) { case LVCFMT_LEFT_TO_RIGHT : dwFlags |= FDTF_LTRDATE; break; case LVCFMT_RIGHT_TO_LEFT : dwFlags |= FDTF_RTLDATE; break; } SHFormatDateTime(&ft, &dwFlags, pszText, cchText); }
STDAPI GetDateProperty(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, FILETIME *pft) { VARIANT var = {0}; HRESULT hr = psf->GetDetailsEx(pidl, pscid, &var); if (SUCCEEDED(hr)) { hr = E_FAIL; if (VT_DATE == var.vt) { SYSTEMTIME st; if (VariantTimeToSystemTime(var.date, &st) && SystemTimeToFileTime(&st, pft)) { hr = S_OK; } }
VariantClear(&var); // Done with it.
} return hr; }
STDAPI GetLongProperty(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, ULONGLONG *pullVal) { *pullVal = 0;
VARIANT var = {0}; HRESULT hr = psf->GetDetailsEx(pidl, pscid, &var); if (SUCCEEDED(hr)) { if (VT_UI8 == var.vt) { *pullVal = var.ullVal; hr = S_OK; } else { VARIANT varLong = {0}; hr = VariantChangeType(&varLong, &var, 0, VT_UI8); if (SUCCEEDED(hr)) { *pullVal = varLong.ullVal; VariantClear(&varLong); } } VariantClear(&var); // Done with it.
} return hr; }
STDAPI GetStringProperty(IShellFolder2 *psf, LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, LPTSTR pszVal, int cchMax) { *pszVal = 0;
VARIANT var = {0}; HRESULT hr = psf->GetDetailsEx(pidl, pscid, &var); if (SUCCEEDED(hr)) { hr = VariantToStr(&var, pszVal, cchMax) ? S_OK : E_FAIL; VariantClear(&var); // Done with it.
} return hr; }
STDAPI QueryInterfaceVariant(VARIANT v, REFIID riid, void **ppv) { *ppv = NULL; HRESULT hr = E_NOINTERFACE;
if ((VT_UNKNOWN == v.vt) && v.punkVal) { hr = v.punkVal->QueryInterface(riid, ppv); } return hr; }
|