📄 stg_prop.c
字号:
if (FAILED(hr))
goto end;
seek.QuadPart = SECTIONHEADER_OFFSET + *sectionOffset;
hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
if (FAILED(hr))
goto end;
StorageUtl_WriteDWord((LPBYTE)&dwType, 0, var->vt);
hr = IStream_Write(This->stm, &dwType, sizeof(dwType), &count);
if (FAILED(hr))
goto end;
*sectionOffset += sizeof(dwType);
switch (var->vt)
{
case VT_EMPTY:
case VT_NULL:
bytesWritten = 0;
break;
case VT_I1:
case VT_UI1:
hr = IStream_Write(This->stm, &var->u.cVal, sizeof(var->u.cVal),
&count);
bytesWritten = count;
break;
case VT_I2:
case VT_UI2:
{
WORD wTemp;
StorageUtl_WriteWord((LPBYTE)&wTemp, 0, var->u.iVal);
hr = IStream_Write(This->stm, &wTemp, sizeof(wTemp), &count);
bytesWritten = count;
break;
}
case VT_I4:
case VT_UI4:
{
DWORD dwTemp;
StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, var->u.lVal);
hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
bytesWritten = count;
break;
}
case VT_LPSTR:
{
DWORD len, dwTemp;
if (This->codePage == CP_UNICODE)
len = (lstrlenW(var->u.pwszVal) + 1) * sizeof(WCHAR);
else
len = lstrlenA(var->u.pszVal) + 1;
StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, len);
hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
if (FAILED(hr))
goto end;
hr = IStream_Write(This->stm, var->u.pszVal, len, &count);
bytesWritten = count + sizeof(DWORD);
break;
}
case VT_LPWSTR:
{
DWORD len = lstrlenW(var->u.pwszVal) + 1, dwTemp;
StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, len);
hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
if (FAILED(hr))
goto end;
hr = IStream_Write(This->stm, var->u.pwszVal, len * sizeof(WCHAR),
&count);
bytesWritten = count + sizeof(DWORD);
break;
}
case VT_FILETIME:
{
FILETIME temp;
StorageUtl_WriteULargeInteger((BYTE *)&temp, 0,
(const ULARGE_INTEGER *)&var->u.filetime);
hr = IStream_Write(This->stm, &temp, sizeof(FILETIME), &count);
bytesWritten = count;
break;
}
case VT_CF:
{
DWORD cf_hdr[2], len;
len = var->u.pclipdata->cbSize;
StorageUtl_WriteDWord((LPBYTE)&cf_hdr[0], 0, len + 8);
StorageUtl_WriteDWord((LPBYTE)&cf_hdr[1], 0, var->u.pclipdata->ulClipFmt);
hr = IStream_Write(This->stm, &cf_hdr, sizeof(cf_hdr), &count);
if (FAILED(hr))
goto end;
hr = IStream_Write(This->stm, &var->u.pclipdata->pClipData, len, &count);
if (FAILED(hr))
goto end;
bytesWritten = count + sizeof cf_hdr;
break;
}
default:
FIXME("unsupported type: %d\n", var->vt);
return STG_E_INVALIDPARAMETER;
}
if (SUCCEEDED(hr))
{
*sectionOffset += bytesWritten;
if (bytesWritten % sizeof(DWORD))
{
DWORD padding = sizeof(DWORD) - bytesWritten % sizeof(DWORD);
TRACE("adding %d bytes of padding\n", padding);
*sectionOffset += padding;
}
}
end:
return hr;
}
struct PropertyClosure
{
HRESULT hr;
DWORD propNum;
DWORD *sectionOffset;
};
static BOOL PropertyStorage_PropertiesWriter(const void *key, const void *value,
void *extra, void *closure)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)extra;
struct PropertyClosure *c = (struct PropertyClosure *)closure;
assert(key);
assert(value);
assert(extra);
assert(closure);
c->hr = PropertyStorage_WritePropertyToStream(This, c->propNum++,
(DWORD)key, value, c->sectionOffset);
return SUCCEEDED(c->hr);
}
static HRESULT PropertyStorage_WritePropertiesToStream(
PropertyStorage_impl *This, DWORD startingPropNum, DWORD *sectionOffset)
{
struct PropertyClosure closure;
assert(sectionOffset);
closure.hr = S_OK;
closure.propNum = startingPropNum;
closure.sectionOffset = sectionOffset;
dictionary_enumerate(This->propid_to_prop, PropertyStorage_PropertiesWriter,
&closure);
return closure.hr;
}
static HRESULT PropertyStorage_WriteHeadersToStream(PropertyStorage_impl *This)
{
HRESULT hr;
ULONG count = 0;
LARGE_INTEGER seek = { {0} };
PROPERTYSETHEADER hdr;
FORMATIDOFFSET fmtOffset;
hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
if (FAILED(hr))
goto end;
PropertyStorage_MakeHeader(This, &hdr);
hr = IStream_Write(This->stm, &hdr, sizeof(hdr), &count);
if (FAILED(hr))
goto end;
if (count != sizeof(hdr))
{
hr = STG_E_WRITEFAULT;
goto end;
}
PropertyStorage_MakeFmtIdOffset(This, &fmtOffset);
hr = IStream_Write(This->stm, &fmtOffset, sizeof(fmtOffset), &count);
if (FAILED(hr))
goto end;
if (count != sizeof(fmtOffset))
{
hr = STG_E_WRITEFAULT;
goto end;
}
hr = S_OK;
end:
return hr;
}
static HRESULT PropertyStorage_WriteToStream(PropertyStorage_impl *This)
{
PROPERTYSECTIONHEADER sectionHdr;
HRESULT hr;
ULONG count;
LARGE_INTEGER seek;
DWORD numProps, prop, sectionOffset, dwTemp;
PROPVARIANT var;
PropertyStorage_WriteHeadersToStream(This);
/* Count properties. Always at least one property, the code page */
numProps = 1;
if (dictionary_num_entries(This->name_to_propid))
numProps++;
if (This->locale != LOCALE_SYSTEM_DEFAULT)
numProps++;
if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
numProps++;
numProps += dictionary_num_entries(This->propid_to_prop);
/* Write section header with 0 bytes right now, I'll adjust it after
* writing properties.
*/
PropertyStorage_MakeSectionHdr(0, numProps, §ionHdr);
seek.QuadPart = SECTIONHEADER_OFFSET;
hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
if (FAILED(hr))
goto end;
hr = IStream_Write(This->stm, §ionHdr, sizeof(sectionHdr), &count);
if (FAILED(hr))
goto end;
prop = 0;
sectionOffset = sizeof(PROPERTYSECTIONHEADER) +
numProps * sizeof(PROPERTYIDOFFSET);
if (dictionary_num_entries(This->name_to_propid))
{
prop++;
hr = PropertyStorage_WriteDictionaryToStream(This, §ionOffset);
if (FAILED(hr))
goto end;
}
PropVariantInit(&var);
var.vt = VT_I2;
var.u.iVal = This->codePage;
hr = PropertyStorage_WritePropertyToStream(This, prop++, PID_CODEPAGE,
&var, §ionOffset);
if (FAILED(hr))
goto end;
if (This->locale != LOCALE_SYSTEM_DEFAULT)
{
var.vt = VT_I4;
var.u.lVal = This->locale;
hr = PropertyStorage_WritePropertyToStream(This, prop++, PID_LOCALE,
&var, §ionOffset);
if (FAILED(hr))
goto end;
}
if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
{
var.vt = VT_I4;
var.u.lVal = 1;
hr = PropertyStorage_WritePropertyToStream(This, prop++, PID_BEHAVIOR,
&var, §ionOffset);
if (FAILED(hr))
goto end;
}
hr = PropertyStorage_WritePropertiesToStream(This, prop, §ionOffset);
if (FAILED(hr))
goto end;
/* Now write the byte count of the section */
seek.QuadPart = SECTIONHEADER_OFFSET;
hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
if (FAILED(hr))
goto end;
StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, sectionOffset);
hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
end:
return hr;
}
/***********************************************************************
* PropertyStorage_Construct
*/
static void PropertyStorage_DestroyDictionaries(PropertyStorage_impl *This)
{
dictionary_destroy(This->name_to_propid);
This->name_to_propid = NULL;
dictionary_destroy(This->propid_to_name);
This->propid_to_name = NULL;
dictionary_destroy(This->propid_to_prop);
This->propid_to_prop = NULL;
}
static HRESULT PropertyStorage_CreateDictionaries(PropertyStorage_impl *This)
{
HRESULT hr = S_OK;
This->name_to_propid = dictionary_create(
PropertyStorage_PropNameCompare, PropertyStorage_PropNameDestroy,
This);
if (!This->name_to_propid)
{
hr = STG_E_INSUFFICIENTMEMORY;
goto end;
}
This->propid_to_name = dictionary_create(PropertyStorage_PropCompare,
NULL, This);
if (!This->propid_to_name)
{
hr = STG_E_INSUFFICIENTMEMORY;
goto end;
}
This->propid_to_prop = dictionary_create(PropertyStorage_PropCompare,
PropertyStorage_PropertyDestroy, This);
if (!This->propid_to_prop)
{
hr = STG_E_INSUFFICIENTMEMORY;
goto end;
}
end:
if (FAILED(hr))
PropertyStorage_DestroyDictionaries(This);
return hr;
}
static HRESULT PropertyStorage_BaseConstruct(IStream *stm,
REFFMTID rfmtid, DWORD grfMode, PropertyStorage_impl **pps)
{
HRESULT hr = S_OK;
assert(pps);
assert(rfmtid);
*pps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof **pps);
if (!*pps)
return E_OUTOFMEMORY;
(*pps)->vtbl = &IPropertyStorage_Vtbl;
(*pps)->ref = 1;
InitializeCriticalSection(&(*pps)->cs);
(*pps)->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PropertyStorage_impl.cs");
(*pps)->stm = stm;
memcpy(&(*pps)->fmtid, rfmtid, sizeof((*pps)->fmtid));
(*pps)->grfMode = grfMode;
hr = PropertyStorage_CreateDictionaries(*pps);
if (FAILED(hr))
{
IStream_Release(stm);
(*pps)->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&(*pps)->cs);
HeapFree(GetProcessHeap(), 0, *pps);
*pps = NULL;
}
return hr;
}
static HRESULT PropertyStorage_ConstructFromStream(IStream *stm,
REFFMTID rfmtid, DWORD grfMode, IPropertyStorage** pps)
{
PropertyStorage_impl *ps;
HRESULT hr;
assert(pps);
hr = PropertyStorage_BaseConstruct(stm, rfmtid, grfMode, &ps);
if (SUCCEEDED(hr))
{
hr = PropertyStorage_ReadFromStream(ps);
if (SUCCEEDED(hr))
{
*pps = (IPropertyStorage *)ps;
TRACE("PropertyStorage %p constructed\n", ps);
hr = S_OK;
}
else
{
PropertyStorage_DestroyDictionaries(ps);
HeapFree(GetProcessHeap(), 0, ps);
}
}
return hr;
}
static HRESULT PropertyStorage_ConstructEmpty(IStream *stm,
REFFMTID rfmtid, DWORD grfFlags, DWORD grfMode, IPropertyStorage** pps)
{
PropertyStorage_impl *ps;
HRESULT hr;
assert(pps);
hr = PropertyStorage_BaseConstruct(stm, rfmtid, grfMode, &ps);
if (SUCCEEDED(hr))
{
ps->format = 0;
ps->grfFlags = grfFlags;
if (ps->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
ps->format = 1;
/* default to Unicode unless told not to, as specified here:
* http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp
*/
if (ps->grfFlags & PROPSETFLAG_ANSI)
ps->codePage = GetACP();
else
ps->codePage = CP_UNICODE;
ps->locale = LOCALE_SYSTEM_DEFAULT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -