📄 stg_prop.c
字号:
else
hr = STG_E_INSUFFICIENTMEMORY;
}
if (SUCCEEDED(hr))
{
len = WideCharToMultiByte(dstCP, 0, wideStr, -1, NULL, 0,
NULL, NULL);
*dst = CoTaskMemAlloc(len);
if (!*dst)
hr = STG_E_INSUFFICIENTMEMORY;
else
{
BOOL defCharUsed = FALSE;
if (WideCharToMultiByte(dstCP, 0, wideStr, -1, *dst, len,
NULL, &defCharUsed) == 0 || defCharUsed)
{
CoTaskMemFree(*dst);
*dst = NULL;
hr = HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION);
}
}
}
HeapFree(GetProcessHeap(), 0, wideStr_tmp);
}
}
TRACE("returning 0x%08x (%s)\n", hr,
dstCP == CP_UNICODE ? debugstr_w((LPCWSTR)*dst) : debugstr_a(*dst));
return hr;
}
static HRESULT PropertyStorage_PropVariantCopy(PROPVARIANT *prop,
const PROPVARIANT *propvar, LCID targetCP, LCID srcCP)
{
HRESULT hr = S_OK;
assert(prop);
assert(propvar);
if (propvar->vt == VT_LPSTR)
{
hr = PropertyStorage_StringCopy(propvar->u.pszVal, srcCP,
&prop->u.pszVal, targetCP);
if (SUCCEEDED(hr))
prop->vt = VT_LPSTR;
}
else
PropVariantCopy(prop, propvar);
return hr;
}
/* Stores the property with id propid and value propvar into this property
* storage. lcid is ignored if propvar's type is not VT_LPSTR. If propvar's
* type is VT_LPSTR, converts the string using lcid as the source code page
* and This->codePage as the target code page before storing.
* As a side effect, may change This->format to 1 if the type of propvar is
* a version 1-only property.
*/
static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
PROPID propid, const PROPVARIANT *propvar, LCID lcid)
{
HRESULT hr = S_OK;
PROPVARIANT *prop = PropertyStorage_FindProperty(This, propid);
assert(propvar);
if (propvar->vt & VT_BYREF || propvar->vt & VT_ARRAY)
This->format = 1;
switch (propvar->vt)
{
case VT_DECIMAL:
case VT_I1:
case VT_INT:
case VT_UINT:
case VT_VECTOR|VT_I1:
This->format = 1;
}
TRACE("Setting 0x%08x to type %d\n", propid, propvar->vt);
if (prop)
{
PropVariantClear(prop);
hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage,
lcid);
}
else
{
prop = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(PROPVARIANT));
if (prop)
{
hr = PropertyStorage_PropVariantCopy(prop, propvar, This->codePage,
lcid);
if (SUCCEEDED(hr))
{
dictionary_insert(This->propid_to_prop, (void *)propid, prop);
if (propid > This->highestProp)
This->highestProp = propid;
}
else
HeapFree(GetProcessHeap(), 0, prop);
}
else
hr = STG_E_INSUFFICIENTMEMORY;
}
return hr;
}
/* Adds the name srcName to the name dictionaries, mapped to property ID id.
* srcName is encoded in code page cp, and is converted to This->codePage.
* If cp is CP_UNICODE, srcName is actually a unicode string.
* As a side effect, may change This->format to 1 if srcName is too long for
* a version 0 property storage.
* Doesn't validate id.
*/
static HRESULT PropertyStorage_StoreNameWithId(PropertyStorage_impl *This,
LPCSTR srcName, LCID cp, PROPID id)
{
LPSTR name;
HRESULT hr;
assert(srcName);
hr = PropertyStorage_StringCopy((LPCSTR)srcName, cp, &name, This->codePage);
if (SUCCEEDED(hr))
{
if (This->codePage == CP_UNICODE)
{
if (lstrlenW((LPWSTR)name) >= MAX_VERSION_0_PROP_NAME_LENGTH)
This->format = 1;
}
else
{
if (strlen(name) >= MAX_VERSION_0_PROP_NAME_LENGTH)
This->format = 1;
}
TRACE("Adding prop name %s, propid %d\n",
This->codePage == CP_UNICODE ? debugstr_w((LPCWSTR)name) :
debugstr_a(name), id);
dictionary_insert(This->name_to_propid, name, (void *)id);
dictionary_insert(This->propid_to_name, (void *)id, name);
}
return hr;
}
/************************************************************************
* IPropertyStorage_fnWriteMultiple (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnWriteMultiple(
IPropertyStorage* iface,
ULONG cpspec,
const PROPSPEC rgpspec[],
const PROPVARIANT rgpropvar[],
PROPID propidNameFirst)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
HRESULT hr = S_OK;
ULONG i;
TRACE("(%p, %d, %p, %p)\n", iface, cpspec, rgpspec, rgpropvar);
if (cpspec && (!rgpspec || !rgpropvar))
return E_INVALIDARG;
if (!(This->grfMode & STGM_READWRITE))
return STG_E_ACCESSDENIED;
EnterCriticalSection(&This->cs);
This->dirty = TRUE;
This->originatorOS = (DWORD)MAKELONG(LOWORD(GetVersion()),
PROPSETHDR_OSVER_KIND_WIN32) ;
for (i = 0; i < cpspec; i++)
{
if (rgpspec[i].ulKind == PRSPEC_LPWSTR)
{
PROPVARIANT *prop = PropertyStorage_FindPropertyByName(This,
rgpspec[i].u.lpwstr);
if (prop)
PropVariantCopy(prop, &rgpropvar[i]);
else
{
/* Note that I don't do the special cases here that I do below,
* because naming the special PIDs isn't supported.
*/
if (propidNameFirst < PID_FIRST_USABLE ||
propidNameFirst >= PID_MIN_READONLY)
hr = STG_E_INVALIDPARAMETER;
else
{
PROPID nextId = max(propidNameFirst, This->highestProp + 1);
hr = PropertyStorage_StoreNameWithId(This,
(LPCSTR)rgpspec[i].u.lpwstr, CP_UNICODE, nextId);
if (SUCCEEDED(hr))
hr = PropertyStorage_StorePropWithId(This, nextId,
&rgpropvar[i], GetACP());
}
}
}
else
{
switch (rgpspec[i].u.propid)
{
case PID_DICTIONARY:
/* Can't set the dictionary */
hr = STG_E_INVALIDPARAMETER;
break;
case PID_CODEPAGE:
/* Can only set the code page if nothing else has been set */
if (dictionary_num_entries(This->propid_to_prop) == 0 &&
rgpropvar[i].vt == VT_I2)
{
This->codePage = rgpropvar[i].u.iVal;
if (This->codePage == CP_UNICODE)
This->grfFlags &= ~PROPSETFLAG_ANSI;
else
This->grfFlags |= PROPSETFLAG_ANSI;
}
else
hr = STG_E_INVALIDPARAMETER;
break;
case PID_LOCALE:
/* Can only set the locale if nothing else has been set */
if (dictionary_num_entries(This->propid_to_prop) == 0 &&
rgpropvar[i].vt == VT_I4)
This->locale = rgpropvar[i].u.lVal;
else
hr = STG_E_INVALIDPARAMETER;
break;
case PID_ILLEGAL:
/* silently ignore like MSDN says */
break;
default:
if (rgpspec[i].u.propid >= PID_MIN_READONLY)
hr = STG_E_INVALIDPARAMETER;
else
hr = PropertyStorage_StorePropWithId(This,
rgpspec[i].u.propid, &rgpropvar[i], GetACP());
}
}
}
if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
IPropertyStorage_Commit(iface, STGC_DEFAULT);
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnDeleteMultiple (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnDeleteMultiple(
IPropertyStorage* iface,
ULONG cpspec,
const PROPSPEC rgpspec[])
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
ULONG i;
HRESULT hr;
TRACE("(%p, %d, %p)\n", iface, cpspec, rgpspec);
if (cpspec && !rgpspec)
return E_INVALIDARG;
if (!(This->grfMode & STGM_READWRITE))
return STG_E_ACCESSDENIED;
hr = S_OK;
EnterCriticalSection(&This->cs);
This->dirty = TRUE;
for (i = 0; i < cpspec; i++)
{
if (rgpspec[i].ulKind == PRSPEC_LPWSTR)
{
PROPID propid;
if (dictionary_find(This->name_to_propid,
(void *)rgpspec[i].u.lpwstr, (void **)&propid))
dictionary_remove(This->propid_to_prop, (void *)propid);
}
else
{
if (rgpspec[i].u.propid >= PID_FIRST_USABLE &&
rgpspec[i].u.propid < PID_MIN_READONLY)
dictionary_remove(This->propid_to_prop,
(void *)rgpspec[i].u.propid);
else
hr = STG_E_INVALIDPARAMETER;
}
}
if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
IPropertyStorage_Commit(iface, STGC_DEFAULT);
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnReadPropertyNames (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnReadPropertyNames(
IPropertyStorage* iface,
ULONG cpropid,
const PROPID rgpropid[],
LPOLESTR rglpwstrName[])
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
ULONG i;
HRESULT hr = S_FALSE;
TRACE("(%p, %d, %p, %p)\n", iface, cpropid, rgpropid, rglpwstrName);
if (cpropid && (!rgpropid || !rglpwstrName))
return E_INVALIDARG;
EnterCriticalSection(&This->cs);
for (i = 0; i < cpropid && SUCCEEDED(hr); i++)
{
LPWSTR name = PropertyStorage_FindPropertyNameById(This, rgpropid[i]);
if (name)
{
size_t len = lstrlenW(name);
hr = S_OK;
rglpwstrName[i] = CoTaskMemAlloc((len + 1) * sizeof(WCHAR));
if (rglpwstrName)
memcpy(rglpwstrName, name, (len + 1) * sizeof(WCHAR));
else
hr = STG_E_INSUFFICIENTMEMORY;
}
else
rglpwstrName[i] = NULL;
}
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnWritePropertyNames (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnWritePropertyNames(
IPropertyStorage* iface,
ULONG cpropid,
const PROPID rgpropid[],
const LPOLESTR rglpwstrName[])
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
ULONG i;
HRESULT hr;
TRACE("(%p, %d, %p, %p)\n", iface, cpropid, rgpropid, rglpwstrName);
if (cpropid && (!rgpropid || !rglpwstrName))
return E_INVALIDARG;
if (!(This->grfMode & STGM_READWRITE))
return STG_E_ACCESSDENIED;
hr = S_OK;
EnterCriticalSection(&This->cs);
This->dirty = TRUE;
for (i = 0; SUCCEEDED(hr) && i < cpropid; i++)
{
if (rgpropid[i] != PID_ILLEGAL)
hr = PropertyStorage_StoreNameWithId(This, (LPCSTR)rglpwstrName[i],
CP_UNICODE, rgpropid[i]);
}
if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
IPropertyStorage_Commit(iface, STGC_DEFAULT);
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnDeletePropertyNames (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnDeletePropertyNames(
IPropertyStorage* iface,
ULONG cpropid,
const PROPID rgpropid[])
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
ULONG i;
HRESULT hr;
TRACE("(%p, %d, %p)\n", iface, cpropid, rgpropid);
if (cpropid && !rgpropid)
return E_INVALIDARG;
if (!(This->grfMode & STGM_READWRITE))
return STG_E_ACCESSDENIED;
hr = S_OK;
EnterCriticalSection(&This->cs);
This->dirty = TRUE;
for (i = 0; i < cpropid; i++)
{
LPWSTR name = NULL;
if (dictionary_find(This->propid_to_name, (void *)rgpropid[i],
(void **)&name))
{
dictionary_remove(This->propid_to_name, (void *)rgpropid[i]);
dictionary_remove(This->name_to_propid, name);
}
}
if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
IPropertyStorage_Commit(iface, STGC_DEFAULT);
LeaveCriticalSection(&This->cs);
return hr;
}
/************************************************************************
* IPropertyStorage_fnCommit (IPropertyStorage)
*/
static HRESULT WINAPI IPropertyStorage_fnCommit(
IPropertyStorage* iface,
DWORD grfCommitFlags)
{
PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -