📄 stg_prop.c
字号:
HRESULT hr;
TRACE("(%p, 0x%08x)\n", iface, grfCommitFlags);
if (!(This->grfMode & STGM_READWRITE))
return STG_E_ACCESSDENIED;
EnterCriticalSection(&This->cs);
if (This->dirty)
hr = PropertyStorage_WriteToStream(This);
else
hr = S_OK;
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnRevert (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnRevert(
IPropertyStorage* iface)
{
HRESULT hr;
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
TRACE("%p\n", iface);
EnterCriticalSection(&This->cs);
if (This->dirty)
{
PropertyStorage_DestroyDictionaries(This);
hr = PropertyStorage_CreateDictionaries(This);
if (SUCCEEDED(hr))
hr = PropertyStorage_ReadFromStream(This);
}
else
hr = S_OK;
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnEnum (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnEnum(
IPropertyStorage* iface,
IEnumSTATPROPSTG** ppenum)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
return create_EnumSTATPROPSTG(This, ppenum);
}
/************************************************************************
* IPropertyStorage_fnSetTimes (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnSetTimes(
IPropertyStorage* iface,
const FILETIME* pctime,
const FILETIME* patime,
const FILETIME* pmtime)
{
FIXME("\n");
return E_NOTIMPL;
}
/************************************************************************
* IPropertyStorage_fnSetClass (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnSetClass(
IPropertyStorage* iface,
REFCLSID clsid)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
TRACE("%p, %s\n", iface, debugstr_guid(clsid));
if (!clsid)
return E_INVALIDARG;
if (!(This->grfMode & STGM_READWRITE))
return STG_E_ACCESSDENIED;
memcpy(&This->clsid, clsid, sizeof(This->clsid));
This->dirty = TRUE;
if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
IPropertyStorage_Commit(iface, STGC_DEFAULT);
return S_OK;
}
/************************************************************************
* IPropertyStorage_fnStat (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnStat(
IPropertyStorage* iface,
STATPROPSETSTG* statpsstg)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
STATSTG stat;
HRESULT hr;
TRACE("%p, %p\n", iface, statpsstg);
if (!statpsstg)
return E_INVALIDARG;
hr = IStream_Stat(This->stm, &stat, STATFLAG_NONAME);
if (SUCCEEDED(hr))
{
memcpy(&statpsstg->fmtid, &This->fmtid, sizeof(statpsstg->fmtid));
memcpy(&statpsstg->clsid, &This->clsid, sizeof(statpsstg->clsid));
statpsstg->grfFlags = This->grfFlags;
memcpy(&statpsstg->mtime, &stat.mtime, sizeof(statpsstg->mtime));
memcpy(&statpsstg->ctime, &stat.ctime, sizeof(statpsstg->ctime));
memcpy(&statpsstg->atime, &stat.atime, sizeof(statpsstg->atime));
statpsstg->dwOSVersion = This->originatorOS;
}
return hr;
}
static int PropertyStorage_PropNameCompare(const void *a, const void *b,
void *extra)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)extra;
if (This->codePage == CP_UNICODE)
{
TRACE("(%s, %s)\n", debugstr_w(a), debugstr_w(b));
if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
return lstrcmpW((LPCWSTR)a, (LPCWSTR)b);
else
return lstrcmpiW((LPCWSTR)a, (LPCWSTR)b);
}
else
{
TRACE("(%s, %s)\n", debugstr_a(a), debugstr_a(b));
if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
return lstrcmpA((LPCSTR)a, (LPCSTR)b);
else
return lstrcmpiA((LPCSTR)a, (LPCSTR)b);
}
}
static void PropertyStorage_PropNameDestroy(void *k, void *d, void *extra)
{
CoTaskMemFree(k);
}
static int PropertyStorage_PropCompare(const void *a, const void *b,
void *extra)
{
TRACE("(%d, %d)\n", (PROPID)a, (PROPID)b);
return (PROPID)a - (PROPID)b;
}
static void PropertyStorage_PropertyDestroy(void *k, void *d, void *extra)
{
PropVariantClear((PROPVARIANT *)d);
HeapFree(GetProcessHeap(), 0, d);
}
#ifdef WORDS_BIGENDIAN
/* Swaps each character in str to or from little endian; assumes the conversion
* is symmetric, that is, that le16toh is equivalent to htole16.
*/
static void PropertyStorage_ByteSwapString(LPWSTR str, size_t len)
{
DWORD i;
/* Swap characters to host order.
* FIXME: alignment?
*/
for (i = 0; i < len; i++)
str[i] = le16toh(str[i]);
}
#else
#define PropertyStorage_ByteSwapString(s, l)
#endif
/* Reads the dictionary from the memory buffer beginning at ptr. Interprets
* the entries according to the values of This->codePage and This->locale.
* FIXME: there isn't any checking whether the read property extends past the
* end of the buffer.
*/
static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This,
BYTE *ptr)
{
DWORD numEntries, i;
HRESULT hr = S_OK;
assert(This->name_to_propid);
assert(This->propid_to_name);
StorageUtl_ReadDWord(ptr, 0, &numEntries);
TRACE("Reading %d entries:\n", numEntries);
ptr += sizeof(DWORD);
for (i = 0; SUCCEEDED(hr) && i < numEntries; i++)
{
PROPID propid;
DWORD cbEntry;
StorageUtl_ReadDWord(ptr, 0, &propid);
ptr += sizeof(PROPID);
StorageUtl_ReadDWord(ptr, 0, &cbEntry);
ptr += sizeof(DWORD);
TRACE("Reading entry with ID 0x%08x, %d bytes\n", propid, cbEntry);
/* Make sure the source string is NULL-terminated */
if (This->codePage != CP_UNICODE)
ptr[cbEntry - 1] = '\0';
else
*((LPWSTR)ptr + cbEntry / sizeof(WCHAR)) = '\0';
hr = PropertyStorage_StoreNameWithId(This, (char*)ptr, This->codePage, propid);
if (This->codePage == CP_UNICODE)
{
/* Unicode entries are padded to DWORD boundaries */
if (cbEntry % sizeof(DWORD))
ptr += sizeof(DWORD) - (cbEntry % sizeof(DWORD));
}
ptr += sizeof(DWORD) + cbEntry;
}
return hr;
}
/* FIXME: there isn't any checking whether the read property extends past the
* end of the buffer.
*/
static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
PROPVARIANT *prop, const BYTE *data)
{
HRESULT hr = S_OK;
assert(prop);
assert(data);
StorageUtl_ReadDWord(data, 0, (DWORD *)&prop->vt);
data += sizeof(DWORD);
switch (prop->vt)
{
case VT_EMPTY:
case VT_NULL:
break;
case VT_I1:
prop->u.cVal = *(const char *)data;
TRACE("Read char 0x%x ('%c')\n", prop->u.cVal, prop->u.cVal);
break;
case VT_UI1:
prop->u.bVal = *(const UCHAR *)data;
TRACE("Read byte 0x%x\n", prop->u.bVal);
break;
case VT_I2:
StorageUtl_ReadWord(data, 0, (WORD*)&prop->u.iVal);
TRACE("Read short %d\n", prop->u.iVal);
break;
case VT_UI2:
StorageUtl_ReadWord(data, 0, &prop->u.uiVal);
TRACE("Read ushort %d\n", prop->u.uiVal);
break;
case VT_INT:
case VT_I4:
StorageUtl_ReadDWord(data, 0, (DWORD*)&prop->u.lVal);
TRACE("Read long %ld\n", prop->u.lVal);
break;
case VT_UINT:
case VT_UI4:
StorageUtl_ReadDWord(data, 0, &prop->u.ulVal);
TRACE("Read ulong %d\n", prop->u.ulVal);
break;
case VT_LPSTR:
{
DWORD count;
StorageUtl_ReadDWord(data, 0, &count);
if (This->codePage == CP_UNICODE && count / 2)
{
WARN("Unicode string has odd number of bytes\n");
hr = STG_E_INVALIDHEADER;
}
else
{
prop->u.pszVal = CoTaskMemAlloc(count);
if (prop->u.pszVal)
{
memcpy(prop->u.pszVal, data + sizeof(DWORD), count);
/* This is stored in the code page specified in This->codePage.
* Don't convert it, the caller will just store it as-is.
*/
if (This->codePage == CP_UNICODE)
{
/* Make sure it's NULL-terminated */
prop->u.pszVal[count / sizeof(WCHAR) - 1] = '\0';
TRACE("Read string value %s\n",
debugstr_w(prop->u.pwszVal));
}
else
{
/* Make sure it's NULL-terminated */
prop->u.pszVal[count - 1] = '\0';
TRACE("Read string value %s\n", debugstr_a(prop->u.pszVal));
}
}
else
hr = STG_E_INSUFFICIENTMEMORY;
}
break;
}
case VT_LPWSTR:
{
DWORD count;
StorageUtl_ReadDWord(data, 0, &count);
prop->u.pwszVal = CoTaskMemAlloc(count * sizeof(WCHAR));
if (prop->u.pwszVal)
{
memcpy(prop->u.pwszVal, data + sizeof(DWORD),
count * sizeof(WCHAR));
/* make sure string is NULL-terminated */
prop->u.pwszVal[count - 1] = '\0';
PropertyStorage_ByteSwapString(prop->u.pwszVal, count);
TRACE("Read string value %s\n", debugstr_w(prop->u.pwszVal));
}
else
hr = STG_E_INSUFFICIENTMEMORY;
break;
}
case VT_FILETIME:
StorageUtl_ReadULargeInteger(data, 0,
(ULARGE_INTEGER *)&prop->u.filetime);
break;
case VT_CF:
{
DWORD len = 0, tag = 0;
StorageUtl_ReadDWord(data, 0, &len);
StorageUtl_ReadDWord(data, 4, &tag);
if (len > 8)
{
len -= 8;
prop->u.pclipdata = CoTaskMemAlloc(sizeof (CLIPDATA));
prop->u.pclipdata->cbSize = len;
prop->u.pclipdata->ulClipFmt = tag;
prop->u.pclipdata->pClipData = CoTaskMemAlloc(len);
memcpy(prop->u.pclipdata->pClipData, data+8, len);
}
else
hr = STG_E_INVALIDPARAMETER;
}
break;
default:
FIXME("unsupported type %d\n", prop->vt);
hr = STG_E_INVALIDPARAMETER;
}
return hr;
}
static HRESULT PropertyStorage_ReadHeaderFromStream(IStream *stm,
PROPERTYSETHEADER *hdr)
{
BYTE buf[sizeof(PROPERTYSETHEADER)];
ULONG count = 0;
HRESULT hr;
assert(stm);
assert(hdr);
hr = IStream_Read(stm, buf, sizeof(buf), &count);
if (SUCCEEDED(hr))
{
if (count != sizeof(buf))
{
WARN("read only %d\n", count);
hr = STG_E_INVALIDHEADER;
}
else
{
StorageUtl_ReadWord(buf, offsetof(PROPERTYSETHEADER, wByteOrder),
&hdr->wByteOrder);
StorageUtl_ReadWord(buf, offsetof(PROPERTYSETHEADER, wFormat),
&hdr->wFormat);
StorageUtl_ReadDWord(buf, offsetof(PROPERTYSETHEADER, dwOSVer),
&hdr->dwOSVer);
StorageUtl_ReadGUID(buf, offsetof(PROPERTYSETHEADER, clsid),
&hdr->clsid);
StorageUtl_ReadDWord(buf, offsetof(PROPERTYSETHEADER, reserved),
&hdr->reserved);
}
}
TRACE("returning 0x%08x\n", hr);
return hr;
}
static HRESULT PropertyStorage_ReadFmtIdOffsetFromStream(IStream *stm,
FORMATIDOFFSET *fmt)
{
BYTE buf[sizeof(FORMATIDOFFSET)];
ULONG count = 0;
HRESULT hr;
assert(stm);
assert(fmt);
hr = IStream_Read(stm, buf, sizeof(buf), &count);
if (SUCCEEDED(hr))
{
if (count != sizeof(buf))
{
WARN("read only %d\n", count);
hr = STG_E_INVALIDHEADER;
}
else
{
StorageUtl_ReadGUID(buf, offsetof(FORMATIDOFFSET, fmtid),
&fmt->fmtid);
StorageUtl_ReadDWord(buf, offsetof(FORMATIDOFFSET, dwOffset),
&fmt->dwOffset);
}
}
TRACE("returning 0x%08x\n", hr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -