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

📄 moniker.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *	Monikers
 *
 *	Copyright 1998	Marcus Meissner
 *      Copyright 1999  Noomen Hamza
 *      Copyright 2005  Robert Shearman (for CodeWeavers)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * TODO:
 * - IRunningObjectTable should work interprocess, but currently doesn't.
 *   Native (on Win2k at least) uses an undocumented RPC interface, IROT, to
 *   communicate with RPCSS which contains the table of marshalled data.
 */

#include <assert.h>
#include <stdarg.h>
#include <string.h>

#define COBJMACROS

#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wtypes.h"
#include "ole2.h"

#include "wine/list.h"
#include "wine/debug.h"

#include "compobj_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(ole);

/* define the structure of the running object table elements */
struct rot_entry
{
    struct list        entry;
    MInterfacePointer* object; /* marshaled running object*/
    MInterfacePointer* moniker; /* marshaled moniker that identifies this object */
    MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */
    DWORD              cookie; /* cookie identifying this object */
    FILETIME           last_modified;
};

/* define the RunningObjectTableImpl structure */
typedef struct RunningObjectTableImpl
{
    const IRunningObjectTableVtbl *lpVtbl;
    LONG ref;

    struct list rot; /* list of ROT entries */
    CRITICAL_SECTION lock;
} RunningObjectTableImpl;

static RunningObjectTableImpl* runningObjectTableInstance = NULL;



static inline HRESULT WINAPI
IrotRegister(DWORD *cookie)
{
    static LONG last_cookie = 1;
    *cookie = InterlockedIncrement(&last_cookie);
    return S_OK;
}

/* define the EnumMonikerImpl structure */
typedef struct EnumMonikerImpl
{
    const IEnumMonikerVtbl *lpVtbl;
    LONG ref;

    MInterfacePointer **monikers;
    ULONG moniker_count;
    ULONG pos;
} EnumMonikerImpl;


/* IEnumMoniker Local functions*/
static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
    ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker);

static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream)
{
    HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
    void *pv = GlobalLock(hglobal);
    memcpy(pv, mip->abData, mip->ulCntData);
    GlobalUnlock(hglobal);
    return CreateStreamOnHGlobal(hglobal, TRUE, stream);
}

static inline void rot_entry_delete(struct rot_entry *rot_entry)
{
    /* FIXME: revoke entry from rpcss's copy of the ROT */
    if (rot_entry->object)
    {
        IStream *stream;
        HRESULT hr;
        hr = create_stream_on_mip_ro(rot_entry->object, &stream);
        if (hr == S_OK)
        {
            CoReleaseMarshalData(stream);
            IUnknown_Release(stream);
        }
    }
    if (rot_entry->moniker)
    {
        IStream *stream;
        HRESULT hr;
        hr = create_stream_on_mip_ro(rot_entry->moniker, &stream);
        if (hr == S_OK)
        {
            CoReleaseMarshalData(stream);
            IUnknown_Release(stream);
        }
    }
    HeapFree(GetProcessHeap(), 0, rot_entry->object);
    HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
    HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
    HeapFree(GetProcessHeap(), 0, rot_entry);
}

/* moniker_data must be freed with HeapFree when no longer in use */
static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data)
{
    HRESULT hr;
    IROTData *pROTData = NULL;
    ULONG size = 0;
    hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData);
    if (hr != S_OK)
    {
        ERR("Failed to query moniker for IROTData interface, hr = 0x%08lx\n", hr);
        return hr;
    }
    IROTData_GetComparisonData(pROTData, NULL, 0, &size);
    *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
    (*moniker_data)->ulCntData = size;
    hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
    if (hr != S_OK)
    {
        ERR("Failed to copy comparison data into buffer, hr = 0x%08lx\n", hr);
        HeapFree(GetProcessHeap(), 0, *moniker_data);
        return hr;
    }
    return S_OK;
}

/***********************************************************************
 *        RunningObjectTable_QueryInterface
 */
static HRESULT WINAPI
RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
                                      REFIID riid,void** ppvObject)
{
    RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;

    TRACE("(%p,%p,%p)\n",This,riid,ppvObject);

    /* validate arguments */

    if (ppvObject==0)
        return E_INVALIDARG;

    *ppvObject = 0;

    if (IsEqualIID(&IID_IUnknown, riid) ||
        IsEqualIID(&IID_IRunningObjectTable, riid))
        *ppvObject = (IRunningObjectTable*)This;

    if ((*ppvObject)==0)
        return E_NOINTERFACE;

    IRunningObjectTable_AddRef(iface);

    return S_OK;
}

/***********************************************************************
 *        RunningObjectTable_AddRef
 */
static ULONG WINAPI
RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
{
    RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;

    TRACE("(%p)\n",This);

    return InterlockedIncrement(&This->ref);
}

/***********************************************************************
 *        RunningObjectTable_Initialize
 */
static HRESULT WINAPI
RunningObjectTableImpl_Destroy(void)
{
    struct list *cursor, *cursor2;

    TRACE("()\n");

    if (runningObjectTableInstance==NULL)
        return E_INVALIDARG;

    /* free the ROT table memory */
    LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot)
    {
        struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
        list_remove(&rot_entry->entry);
        rot_entry_delete(rot_entry);
    }

    /* free the ROT structure memory */
    HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
    runningObjectTableInstance = NULL;

    return S_OK;
}

/***********************************************************************
 *        RunningObjectTable_Release
 */
static ULONG WINAPI
RunningObjectTableImpl_Release(IRunningObjectTable* iface)
{
    RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
    ULONG ref;

    TRACE("(%p)\n",This);

    ref = InterlockedDecrement(&This->ref);

    /* uninitialize ROT structure if there's no more references to it */
    if (ref == 0)
    {
        struct list *cursor, *cursor2;
        LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot)
        {
            struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
            list_remove(&rot_entry->entry);
            rot_entry_delete(rot_entry);
        }
        /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
         *  when RunningObjectTableImpl_UnInitialize function is called
         */
    }

    return ref;
}

/***********************************************************************
 *        RunningObjectTable_Register
 *
 * PARAMS
 * grfFlags       [in] Registration options 
 * punkObject     [in] the object being registered
 * pmkObjectName  [in] the moniker of the object being registered
 * pdwRegister    [in] the value identifying the registration
 */
static HRESULT WINAPI
RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
               IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
{
    RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
    struct rot_entry *rot_entry;
    HRESULT hr = S_OK;
    IStream *pStream = NULL;
    DWORD mshlflags;

    TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);

    /*
     * there's only two types of register : strong and or weak registration
     * (only one must be passed on parameter)
     */
    if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
         (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ||  (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
         (grfFlags) )
    {
        ERR("Invalid combination of ROTFLAGS: %lx\n", grfFlags);
        return E_INVALIDARG;
    }

    if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
        return E_INVALIDARG;

    rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
    if (!rot_entry)
        return E_OUTOFMEMORY;

    CoFileTimeNow(&rot_entry->last_modified);

    /* marshal object */
    hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
    if (hr != S_OK)
    {
        rot_entry_delete(rot_entry);
        return hr;
    }
    mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;
    hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);
    /* FIXME: a cleaner way would be to create an IStream class that writes
     * directly to an MInterfacePointer */
    if (hr == S_OK)
    {
        HGLOBAL hglobal;
        hr = GetHGlobalFromStream(pStream, &hglobal);
        if (hr == S_OK)
        {
            SIZE_T size = GlobalSize(hglobal);
            const void *pv = GlobalLock(hglobal);
            rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
            rot_entry->object->ulCntData = size;
            memcpy(&rot_entry->object->abData, pv, size);
            GlobalUnlock(hglobal);
        }
    }
    IStream_Release(pStream);
    if (hr != S_OK)
    {
        rot_entry_delete(rot_entry);
        return hr;
    }

    hr = get_moniker_comparison_data(pmkObjectName, &rot_entry->moniker_data);
    if (hr != S_OK)
    {
        rot_entry_delete(rot_entry);
        return hr;
    }

    hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
    if (hr != S_OK)
    {
        rot_entry_delete(rot_entry);
        return hr;
    }
    /* marshal moniker */
    hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
    /* FIXME: a cleaner way would be to create an IStream class that writes
     * directly to an MInterfacePointer */
    if (hr == S_OK)
    {
        HGLOBAL hglobal;
        hr = GetHGlobalFromStream(pStream, &hglobal);
        if (hr == S_OK)
        {
            SIZE_T size = GlobalSize(hglobal);
            const void *pv = GlobalLock(hglobal);
            rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
            rot_entry->moniker->ulCntData = size;
            memcpy(&rot_entry->moniker->abData, pv, size);
            GlobalUnlock(hglobal);
        }
    }
    IStream_Release(pStream);
    if (hr != S_OK)
    {
        rot_entry_delete(rot_entry);
        return hr;
    }

    /* FIXME: not the right signature of IrotRegister function */
    hr = IrotRegister(&rot_entry->cookie);
    if (hr != S_OK)
    {
        rot_entry_delete(rot_entry);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -