⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stg_prop.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -