- Sync ole32 to Wine-20081105 (matching rpcrt4 sync). Tested with two versions of...
authorAleksey Bragin <aleksey@reactos.org>
Fri, 7 Nov 2008 11:00:30 +0000 (11:00 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Fri, 7 Nov 2008 11:00:30 +0000 (11:00 +0000)
- Remove epm server building from rpcrt4, it belongs to rpcss.

svn path=/trunk/; revision=37240

20 files changed:
reactos/dll/win32/ole32/clipboard.c
reactos/dll/win32/ole32/comcat.c [new file with mode: 0644]
reactos/dll/win32/ole32/compobj.c
reactos/dll/win32/ole32/compobj_private.h
reactos/dll/win32/ole32/dcom.idl
reactos/dll/win32/ole32/defaulthandler.c
reactos/dll/win32/ole32/filemoniker.c
reactos/dll/win32/ole32/moniker.c
reactos/dll/win32/ole32/moniker.h
reactos/dll/win32/ole32/ole2.c
reactos/dll/win32/ole32/ole2nls.c
reactos/dll/win32/ole32/ole2stubs.c
reactos/dll/win32/ole32/ole32.rbuild
reactos/dll/win32/ole32/ole32.spec
reactos/dll/win32/ole32/oleproxy.c
reactos/dll/win32/ole32/regsvr.c
reactos/dll/win32/ole32/rpc.c
reactos/dll/win32/ole32/storage32.c
reactos/dll/win32/ole32/usrmarshal.c
reactos/dll/win32/rpcrt4/rpcrt4.rbuild

index 909b215..0e9d55c 100644 (file)
@@ -956,7 +956,7 @@ static HRESULT OLEClipbrd_RenderFormat(IDataObject *pIDataObject, LPFORMATETC pF
 
       /* Get the metafile picture out of it */
 
-      if (!FAILED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
+      if (SUCCEEDED(hr = IDataObject_GetData(theOleClipboard->pIDataObjectSrc, &fmt2, &std2)))
       {
         mfp = (METAFILEPICT *)GlobalLock(std2.u.hGlobal);
       }
diff --git a/reactos/dll/win32/ole32/comcat.c b/reactos/dll/win32/ole32/comcat.c
new file mode 100644 (file)
index 0000000..9120df0
--- /dev/null
@@ -0,0 +1,1353 @@
+/*
+ * Comcat implementation
+ *
+ * Copyright (C) 2002 John K. Hohm
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <string.h>
+#include <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#include "ole2.h"
+#include "comcat.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+typedef struct
+{
+    const ICatRegisterVtbl *lpVtbl;
+    const ICatInformationVtbl *infVtbl;
+} ComCatMgrImpl;
+
+struct class_categories {
+    LPCWSTR impl_strings;
+    LPCWSTR req_strings;
+};
+
+static LPENUMCATEGORYINFO COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid);
+static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(struct class_categories *class_categories);
+static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct(REFCLSID rclsid, LPCWSTR impl_req);
+
+/**********************************************************************
+ * File-scope string constants
+ */
+static const WCHAR comcat_keyname[] = {
+    'C','o','m','p','o','n','e','n','t',' ','C','a','t','e','g','o','r','i','e','s',0 };
+static const WCHAR impl_keyname[] = {
+    'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0 };
+static const WCHAR req_keyname[] = {
+    'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0 };
+static const WCHAR clsid_keyname[] = { 'C','L','S','I','D',0 };
+
+
+static inline ComCatMgrImpl *impl_from_ICatInformation( ICatInformation *iface )
+{
+    return (ComCatMgrImpl *)((char*)iface - FIELD_OFFSET(ComCatMgrImpl, infVtbl));
+}
+
+
+/**********************************************************************
+ * COMCAT_RegisterClassCategories
+ */
+static HRESULT COMCAT_RegisterClassCategories(
+    REFCLSID rclsid,
+    LPCWSTR type,
+    ULONG cCategories,
+    const CATID *rgcatid)
+{
+    WCHAR keyname[39];
+    HRESULT res;
+    HKEY clsid_key, class_key, type_key;
+
+    if (cCategories && rgcatid == NULL) return E_POINTER;
+
+    /* Format the class key name. */
+    res = StringFromGUID2(rclsid, keyname, 39);
+    if (FAILED(res)) return res;
+
+    /* Create (or open) the CLSID key. */
+    res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
+                         KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
+    if (res != ERROR_SUCCESS) return E_FAIL;
+
+    /* Create (or open) the class key. */
+    res = RegCreateKeyExW(clsid_key, keyname, 0, NULL, 0,
+                         KEY_READ | KEY_WRITE, NULL, &class_key, NULL);
+    if (res == ERROR_SUCCESS) {
+       /* Create (or open) the category type key. */
+       res = RegCreateKeyExW(class_key, type, 0, NULL, 0,
+                             KEY_READ | KEY_WRITE, NULL, &type_key, NULL);
+       if (res == ERROR_SUCCESS) {
+           for (; cCategories; --cCategories, ++rgcatid) {
+               HKEY key;
+
+               /* Format the category key name. */
+               res = StringFromGUID2(rgcatid, keyname, 39);
+               if (FAILED(res)) continue;
+
+               /* Do the register. */
+               res = RegCreateKeyExW(type_key, keyname, 0, NULL, 0,
+                                     KEY_READ | KEY_WRITE, NULL, &key, NULL);
+               if (res == ERROR_SUCCESS) RegCloseKey(key);
+           }
+           res = S_OK;
+       } else res = E_FAIL;
+       RegCloseKey(class_key);
+    } else res = E_FAIL;
+    RegCloseKey(clsid_key);
+
+    return res;
+}
+
+/**********************************************************************
+ * COMCAT_UnRegisterClassCategories
+ */
+static HRESULT COMCAT_UnRegisterClassCategories(
+    REFCLSID rclsid,
+    LPCWSTR type,
+    ULONG cCategories,
+    const CATID *rgcatid)
+{
+    WCHAR keyname[68] = { 'C', 'L', 'S', 'I', 'D', '\\' };
+    HRESULT res;
+    HKEY type_key;
+
+    if (cCategories && rgcatid == NULL) return E_POINTER;
+
+    /* Format the class category type key name. */
+    res = StringFromGUID2(rclsid, keyname + 6, 39);
+    if (FAILED(res)) return res;
+    keyname[44] = '\\';
+    lstrcpyW(keyname + 45, type);
+
+    /* Open the class category type key. */
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0,
+                       KEY_READ | KEY_WRITE, &type_key);
+    if (res != ERROR_SUCCESS) return E_FAIL;
+
+    for (; cCategories; --cCategories, ++rgcatid) {
+       /* Format the category key name. */
+       res = StringFromGUID2(rgcatid, keyname, 39);
+       if (FAILED(res)) continue;
+
+       /* Do the unregister. */
+       RegDeleteKeyW(type_key, keyname);
+    }
+    RegCloseKey(type_key);
+
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_GetCategoryDesc
+ */
+static HRESULT COMCAT_GetCategoryDesc(HKEY key, LCID lcid, PWCHAR pszDesc,
+                                     ULONG buf_wchars)
+{
+    static const WCHAR fmt[] = { '%', 'l', 'X', 0 };
+    WCHAR valname[5];
+    HRESULT res;
+    DWORD type, size = (buf_wchars - 1) * sizeof(WCHAR);
+
+    if (pszDesc == NULL) return E_INVALIDARG;
+
+    /* FIXME: lcid comparisons are more complex than this! */
+    wsprintfW(valname, fmt, lcid);
+    res = RegQueryValueExW(key, valname, 0, &type, (LPBYTE)pszDesc, &size);
+    if (res != ERROR_SUCCESS || type != REG_SZ) {
+       FIXME("Simplified lcid comparison\n");
+       return CAT_E_NODESCRIPTION;
+    }
+    pszDesc[size / sizeof(WCHAR)] = (WCHAR)0;
+
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_PrepareClassCategories
+ */
+static struct class_categories *COMCAT_PrepareClassCategories(
+    ULONG impl_count, const CATID *impl_catids, ULONG req_count, const CATID *req_catids)
+{
+    struct class_categories *categories;
+    WCHAR *strings;
+
+    categories = HeapAlloc(
+       GetProcessHeap(), HEAP_ZERO_MEMORY,
+       sizeof(struct class_categories) +
+       ((impl_count + req_count) * 39 + 2) * sizeof(WCHAR));
+    if (categories == NULL) return categories;
+
+    strings = (WCHAR *)(categories + 1);
+    categories->impl_strings = strings;
+    while (impl_count--) {
+       StringFromGUID2(impl_catids++, strings, 39);
+       strings += 39;
+    }
+    *strings++ = 0;
+
+    categories->req_strings = strings;
+    while (req_count--) {
+       StringFromGUID2(req_catids++, strings, 39);
+       strings += 39;
+    }
+    *strings++ = 0;
+
+    return categories;
+}
+
+/**********************************************************************
+ * COMCAT_IsClassOfCategories
+ */
+static HRESULT COMCAT_IsClassOfCategories(
+    HKEY key,
+    struct class_categories const* categories)
+{
+    static const WCHAR impl_keyname[] = { 'I', 'm', 'p', 'l', 'e', 'm', 'e', 'n',
+                                          't', 'e', 'd', ' ', 'C', 'a', 't', 'e',
+                                          'g', 'o', 'r', 'i', 'e', 's', 0 };
+    static const WCHAR req_keyname[]  = { 'R', 'e', 'q', 'u', 'i', 'r', 'e', 'd',
+                                          ' ', 'C', 'a', 't', 'e', 'g', 'o', 'r',
+                                          'i', 'e', 's', 0 };
+    HKEY subkey;
+    HRESULT res;
+    DWORD index;
+    LPCWSTR string;
+
+    /* Check that every given category is implemented by class. */
+    res = RegOpenKeyExW(key, impl_keyname, 0, KEY_READ, &subkey);
+    if (res != ERROR_SUCCESS) return S_FALSE;
+    for (string = categories->impl_strings; *string; string += 39) {
+       HKEY catkey;
+       res = RegOpenKeyExW(subkey, string, 0, 0, &catkey);
+       if (res != ERROR_SUCCESS) {
+           RegCloseKey(subkey);
+           return S_FALSE;
+       }
+       RegCloseKey(catkey);
+    }
+    RegCloseKey(subkey);
+
+    /* Check that all categories required by class are given. */
+    res = RegOpenKeyExW(key, req_keyname, 0, KEY_READ, &subkey);
+    if (res == ERROR_SUCCESS) {
+       for (index = 0; ; ++index) {
+           WCHAR keyname[39];
+           DWORD size = 39;
+
+           res = RegEnumKeyExW(subkey, index, keyname, &size,
+                               NULL, NULL, NULL, NULL);
+           if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+           if (size != 38) continue; /* bogus catid in registry */
+           for (string = categories->req_strings; *string; string += 39)
+               if (!strcmpiW(string, keyname)) break;
+           if (!*string) {
+               RegCloseKey(subkey);
+               return S_FALSE;
+           }
+       }
+       RegCloseKey(subkey);
+    }
+
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_QueryInterface
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_QueryInterface(
+    LPCATREGISTER iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    ComCatMgrImpl *This = (ComCatMgrImpl *)iface;
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (ppvObj == NULL) return E_POINTER;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ICatRegister)) {
+       *ppvObj = iface;
+       IUnknown_AddRef(iface);
+       return S_OK;
+    }
+
+    if (IsEqualGUID(riid, &IID_ICatInformation)) {
+       *ppvObj = &This->infVtbl;
+       IUnknown_AddRef(iface);
+       return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_AddRef
+ */
+static ULONG WINAPI COMCAT_ICatRegister_AddRef(LPCATREGISTER iface)
+{
+    return 2; /* non-heap based object */
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_Release
+ */
+static ULONG WINAPI COMCAT_ICatRegister_Release(LPCATREGISTER iface)
+{
+    return 1; /* non-heap based object */
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_RegisterCategories
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_RegisterCategories(
+    LPCATREGISTER iface,
+    ULONG cCategories,
+    CATEGORYINFO *rgci)
+{
+    HKEY comcat_key;
+    HRESULT res;
+
+    TRACE("\n");
+
+    if (cCategories && rgci == NULL)
+       return E_POINTER;
+
+    /* Create (or open) the component categories key. */
+    res = RegCreateKeyExW(HKEY_CLASSES_ROOT, comcat_keyname, 0, NULL, 0,
+                         KEY_READ | KEY_WRITE, NULL, &comcat_key, NULL);
+    if (res != ERROR_SUCCESS) return E_FAIL;
+
+    for (; cCategories; --cCategories, ++rgci) {
+       static const WCHAR fmt[] = { '%', 'l', 'X', 0 };
+       WCHAR keyname[39];
+       WCHAR valname[9];
+       HKEY cat_key;
+
+       /* Create (or open) the key for this category. */
+       if (!StringFromGUID2(&rgci->catid, keyname, 39)) continue;
+       res = RegCreateKeyExW(comcat_key, keyname, 0, NULL, 0,
+                             KEY_READ | KEY_WRITE, NULL, &cat_key, NULL);
+       if (res != ERROR_SUCCESS) continue;
+
+       /* Set the value for this locale's description. */
+       wsprintfW(valname, fmt, rgci->lcid);
+       RegSetValueExW(cat_key, valname, 0, REG_SZ,
+                      (CONST BYTE*)(rgci->szDescription),
+                      (lstrlenW(rgci->szDescription) + 1) * sizeof(WCHAR));
+
+       RegCloseKey(cat_key);
+    }
+
+    RegCloseKey(comcat_key);
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_UnRegisterCategories
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_UnRegisterCategories(
+    LPCATREGISTER iface,
+    ULONG cCategories,
+    CATID *rgcatid)
+{
+    HKEY comcat_key;
+    HRESULT res;
+
+    TRACE("\n");
+
+    if (cCategories && rgcatid == NULL)
+       return E_POINTER;
+
+    /* Open the component categories key. */
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, comcat_keyname, 0,
+                       KEY_READ | KEY_WRITE, &comcat_key);
+    if (res != ERROR_SUCCESS) return E_FAIL;
+
+    for (; cCategories; --cCategories, ++rgcatid) {
+       WCHAR keyname[39];
+
+       /* Delete the key for this category. */
+       if (!StringFromGUID2(rgcatid, keyname, 39)) continue;
+       RegDeleteKeyW(comcat_key, keyname);
+    }
+
+    RegCloseKey(comcat_key);
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_RegisterClassImplCategories
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_RegisterClassImplCategories(
+    LPCATREGISTER iface,
+    REFCLSID rclsid,
+    ULONG cCategories,
+    CATID *rgcatid)
+{
+    TRACE("\n");
+
+    return COMCAT_RegisterClassCategories(
+       rclsid, impl_keyname, cCategories, rgcatid);
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_UnRegisterClassImplCategories
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_UnRegisterClassImplCategories(
+    LPCATREGISTER iface,
+    REFCLSID rclsid,
+    ULONG cCategories,
+    CATID *rgcatid)
+{
+    TRACE("\n");
+
+    return COMCAT_UnRegisterClassCategories(
+       rclsid, impl_keyname, cCategories, rgcatid);
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_RegisterClassReqCategories
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_RegisterClassReqCategories(
+    LPCATREGISTER iface,
+    REFCLSID rclsid,
+    ULONG cCategories,
+    CATID *rgcatid)
+{
+    TRACE("\n");
+
+    return COMCAT_RegisterClassCategories(
+       rclsid, req_keyname, cCategories, rgcatid);
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_UnRegisterClassReqCategories
+ */
+static HRESULT WINAPI COMCAT_ICatRegister_UnRegisterClassReqCategories(
+    LPCATREGISTER iface,
+    REFCLSID rclsid,
+    ULONG cCategories,
+    CATID *rgcatid)
+{
+    TRACE("\n");
+
+    return COMCAT_UnRegisterClassCategories(
+       rclsid, req_keyname, cCategories, rgcatid);
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_QueryInterface
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_QueryInterface(
+    LPCATINFORMATION iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    ComCatMgrImpl *This = impl_from_ICatInformation( iface );
+    return IUnknown_QueryInterface((LPUNKNOWN)This, riid, ppvObj);
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_AddRef
+ */
+static ULONG WINAPI COMCAT_ICatInformation_AddRef(LPCATINFORMATION iface)
+{
+    ComCatMgrImpl *This = impl_from_ICatInformation( iface );
+    return IUnknown_AddRef((LPUNKNOWN)This);
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_Release
+ */
+static ULONG WINAPI COMCAT_ICatInformation_Release(LPCATINFORMATION iface)
+{
+    ComCatMgrImpl *This = impl_from_ICatInformation( iface );
+    return IUnknown_Release((LPUNKNOWN)This);
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_EnumCategories
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_EnumCategories(
+    LPCATINFORMATION iface,
+    LCID lcid,
+    LPENUMCATEGORYINFO *ppenumCatInfo)
+{
+    TRACE("\n");
+
+    if (ppenumCatInfo == NULL) return E_POINTER;
+
+    *ppenumCatInfo = COMCAT_IEnumCATEGORYINFO_Construct(lcid);
+    if (*ppenumCatInfo == NULL) return E_OUTOFMEMORY;
+    IEnumCATEGORYINFO_AddRef(*ppenumCatInfo);
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_GetCategoryDesc
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_GetCategoryDesc(
+    LPCATINFORMATION iface,
+    REFCATID rcatid,
+    LCID lcid,
+    PWCHAR *ppszDesc)
+{
+    WCHAR keyname[60] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n',
+                         't', ' ', 'C', 'a', 't', 'e', 'g', 'o',
+                         'r', 'i', 'e', 's', '\\', 0 };
+    HKEY key;
+    HRESULT res;
+
+    TRACE("\n\tCATID:\t%s\n\tLCID:\t%X\n",debugstr_guid(rcatid), lcid);
+
+    if (rcatid == NULL || ppszDesc == NULL) return E_INVALIDARG;
+
+    /* Open the key for this category. */
+    if (!StringFromGUID2(rcatid, keyname + 21, 39)) return E_FAIL;
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key);
+    if (res != ERROR_SUCCESS) return CAT_E_CATIDNOEXIST;
+
+    /* Allocate a sensible amount of memory for the description. */
+    *ppszDesc = (PWCHAR) CoTaskMemAlloc(128 * sizeof(WCHAR));
+    if (*ppszDesc == NULL) {
+       RegCloseKey(key);
+       return E_OUTOFMEMORY;
+    }
+
+    /* Get the description, and make sure it's null terminated. */
+    res = COMCAT_GetCategoryDesc(key, lcid, *ppszDesc, 128);
+    RegCloseKey(key);
+    if (FAILED(res)) {
+       CoTaskMemFree(*ppszDesc);
+       return res;
+    }
+
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_EnumClassesOfCategories
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_EnumClassesOfCategories(
+    LPCATINFORMATION iface,
+    ULONG cImplemented,
+    CATID *rgcatidImpl,
+    ULONG cRequired,
+    CATID *rgcatidReq,
+    LPENUMCLSID *ppenumCLSID)
+{
+    struct class_categories *categories;
+
+    TRACE("\n");
+
+       if (cImplemented == (ULONG)-1)
+               cImplemented = 0;
+       if (cRequired == (ULONG)-1)
+               cRequired = 0;
+
+    if (ppenumCLSID == NULL ||
+       (cImplemented && rgcatidImpl == NULL) ||
+       (cRequired && rgcatidReq == NULL)) return E_POINTER;
+
+    categories = COMCAT_PrepareClassCategories(cImplemented, rgcatidImpl,
+                                              cRequired, rgcatidReq);
+    if (categories == NULL) return E_OUTOFMEMORY;
+    *ppenumCLSID = COMCAT_CLSID_IEnumGUID_Construct(categories);
+    if (*ppenumCLSID == NULL) {
+       HeapFree(GetProcessHeap(), 0, categories);
+       return E_OUTOFMEMORY;
+    }
+    IEnumGUID_AddRef(*ppenumCLSID);
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_IsClassOfCategories
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_IsClassOfCategories(
+    LPCATINFORMATION iface,
+    REFCLSID rclsid,
+    ULONG cImplemented,
+    CATID *rgcatidImpl,
+    ULONG cRequired,
+    CATID *rgcatidReq)
+{
+    WCHAR keyname[45] = { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
+    HRESULT res;
+    struct class_categories *categories;
+    HKEY key;
+
+    if (WINE_TRACE_ON(ole)) {
+       ULONG count;
+       TRACE("\n\tCLSID:\t%s\n\tImplemented %u\n",debugstr_guid(rclsid),cImplemented);
+       for (count = 0; count < cImplemented; ++count)
+           TRACE("\t\t%s\n",debugstr_guid(&rgcatidImpl[count]));
+       TRACE("\tRequired %u\n",cRequired);
+       for (count = 0; count < cRequired; ++count)
+           TRACE("\t\t%s\n",debugstr_guid(&rgcatidReq[count]));
+    }
+
+    if ((cImplemented && rgcatidImpl == NULL) ||
+       (cRequired && rgcatidReq == NULL)) return E_POINTER;
+
+    res = StringFromGUID2(rclsid, keyname + 6, 39);
+    if (FAILED(res)) return res;
+
+    categories = COMCAT_PrepareClassCategories(cImplemented, rgcatidImpl,
+                                              cRequired, rgcatidReq);
+    if (categories == NULL) return E_OUTOFMEMORY;
+
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key);
+    if (res == ERROR_SUCCESS) {
+       res = COMCAT_IsClassOfCategories(key, categories);
+       RegCloseKey(key);
+    } else res = S_FALSE;
+
+    HeapFree(GetProcessHeap(), 0, categories);
+
+    return res;
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_EnumImplCategoriesOfClass
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_EnumImplCategoriesOfClass(
+    LPCATINFORMATION iface,
+    REFCLSID rclsid,
+    LPENUMCATID *ppenumCATID)
+{
+    static const WCHAR postfix[24] = { '\\', 'I', 'm', 'p', 'l', 'e', 'm', 'e',
+                         'n', 't', 'e', 'd', ' ', 'C', 'a', 't',
+                         'e', 'g', 'o', 'r', 'i', 'e', 's', 0 };
+
+    TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid));
+
+    if (rclsid == NULL || ppenumCATID == NULL)
+       return E_POINTER;
+
+    *ppenumCATID = COMCAT_CATID_IEnumGUID_Construct(rclsid, postfix);
+    if (*ppenumCATID == NULL) return E_OUTOFMEMORY;
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatInformation_EnumReqCategoriesOfClass
+ */
+static HRESULT WINAPI COMCAT_ICatInformation_EnumReqCategoriesOfClass(
+    LPCATINFORMATION iface,
+    REFCLSID rclsid,
+    LPENUMCATID *ppenumCATID)
+{
+    static const WCHAR postfix[21] = { '\\', 'R', 'e', 'q', 'u', 'i', 'r', 'e',
+                         'd', ' ', 'C', 'a', 't', 'e', 'g', 'o',
+                         'r', 'i', 'e', 's', 0 };
+
+    TRACE("\n\tCLSID:\t%s\n",debugstr_guid(rclsid));
+
+    if (rclsid == NULL || ppenumCATID == NULL)
+       return E_POINTER;
+
+    *ppenumCATID = COMCAT_CATID_IEnumGUID_Construct(rclsid, postfix);
+    if (*ppenumCATID == NULL) return E_OUTOFMEMORY;
+    return S_OK;
+}
+
+/**********************************************************************
+ * COMCAT_ICatRegister_Vtbl
+ */
+static const ICatRegisterVtbl COMCAT_ICatRegister_Vtbl =
+{
+    COMCAT_ICatRegister_QueryInterface,
+    COMCAT_ICatRegister_AddRef,
+    COMCAT_ICatRegister_Release,
+    COMCAT_ICatRegister_RegisterCategories,
+    COMCAT_ICatRegister_UnRegisterCategories,
+    COMCAT_ICatRegister_RegisterClassImplCategories,
+    COMCAT_ICatRegister_UnRegisterClassImplCategories,
+    COMCAT_ICatRegister_RegisterClassReqCategories,
+    COMCAT_ICatRegister_UnRegisterClassReqCategories
+};
+
+
+/**********************************************************************
+ * COMCAT_ICatInformation_Vtbl
+ */
+static const ICatInformationVtbl COMCAT_ICatInformation_Vtbl =
+{
+    COMCAT_ICatInformation_QueryInterface,
+    COMCAT_ICatInformation_AddRef,
+    COMCAT_ICatInformation_Release,
+    COMCAT_ICatInformation_EnumCategories,
+    COMCAT_ICatInformation_GetCategoryDesc,
+    COMCAT_ICatInformation_EnumClassesOfCategories,
+    COMCAT_ICatInformation_IsClassOfCategories,
+    COMCAT_ICatInformation_EnumImplCategoriesOfClass,
+    COMCAT_ICatInformation_EnumReqCategoriesOfClass
+};
+
+/**********************************************************************
+ * static ComCatMgr instance
+ */
+static ComCatMgrImpl COMCAT_ComCatMgr =
+{
+    &COMCAT_ICatRegister_Vtbl,
+    &COMCAT_ICatInformation_Vtbl
+};
+
+/**********************************************************************
+ * COMCAT_IClassFactory_QueryInterface (also IUnknown)
+ */
+static HRESULT WINAPI COMCAT_IClassFactory_QueryInterface(
+    LPCLASSFACTORY iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (ppvObj == NULL) return E_POINTER;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+       IsEqualGUID(riid, &IID_IClassFactory))
+    {
+       *ppvObj = (LPVOID)iface;
+        IUnknown_AddRef(iface);
+       return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+/**********************************************************************
+ * COMCAT_IClassFactory_AddRef (also IUnknown)
+ */
+static ULONG WINAPI COMCAT_IClassFactory_AddRef(LPCLASSFACTORY iface)
+{
+    return 2; /* non-heap based object */
+}
+
+/**********************************************************************
+ * COMCAT_IClassFactory_Release (also IUnknown)
+ */
+static ULONG WINAPI COMCAT_IClassFactory_Release(LPCLASSFACTORY iface)
+{
+    return 1; /* non-heap based object */
+}
+
+/**********************************************************************
+ * COMCAT_IClassFactory_CreateInstance
+ */
+static HRESULT WINAPI COMCAT_IClassFactory_CreateInstance(
+    LPCLASSFACTORY iface,
+    LPUNKNOWN pUnkOuter,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    HRESULT res;
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (ppvObj == NULL) return E_POINTER;
+
+    /* Don't support aggregation (Windows doesn't) */
+    if (pUnkOuter != NULL) return CLASS_E_NOAGGREGATION;
+
+    res = IUnknown_QueryInterface((LPUNKNOWN)&COMCAT_ComCatMgr, riid, ppvObj);
+    if (SUCCEEDED(res)) {
+       return res;
+    }
+
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+/**********************************************************************
+ * COMCAT_IClassFactory_LockServer
+ */
+static HRESULT WINAPI COMCAT_IClassFactory_LockServer(
+    LPCLASSFACTORY iface,
+    BOOL fLock)
+{
+    FIXME("(%d), stub!\n",fLock);
+    return S_OK;
+}
+
+/**********************************************************************
+ * static ClassFactory instance
+ */
+static const IClassFactoryVtbl ComCatCFVtbl =
+{
+    COMCAT_IClassFactory_QueryInterface,
+    COMCAT_IClassFactory_AddRef,
+    COMCAT_IClassFactory_Release,
+    COMCAT_IClassFactory_CreateInstance,
+    COMCAT_IClassFactory_LockServer
+};
+
+static const IClassFactoryVtbl *ComCatCF = &ComCatCFVtbl;
+
+HRESULT ComCatCF_Create(REFIID riid, LPVOID *ppv)
+{
+    return IClassFactory_QueryInterface((IClassFactory *)&ComCatCF, riid, ppv);
+}
+
+/**********************************************************************
+ * IEnumCATEGORYINFO implementation
+ *
+ * This implementation is not thread-safe.  The manager itself is, but
+ * I can't imagine a valid use of an enumerator in several threads.
+ */
+typedef struct
+{
+    const IEnumCATEGORYINFOVtbl *lpVtbl;
+    LONG  ref;
+    LCID  lcid;
+    HKEY  key;
+    DWORD next_index;
+} IEnumCATEGORYINFOImpl;
+
+static ULONG WINAPI COMCAT_IEnumCATEGORYINFO_AddRef(LPENUMCATEGORYINFO iface)
+{
+    IEnumCATEGORYINFOImpl *This = (IEnumCATEGORYINFOImpl *)iface;
+
+    TRACE("\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_QueryInterface(
+    LPENUMCATEGORYINFO iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (ppvObj == NULL) return E_POINTER;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+       IsEqualGUID(riid, &IID_IEnumCATEGORYINFO))
+    {
+       *ppvObj = (LPVOID)iface;
+       COMCAT_IEnumCATEGORYINFO_AddRef(iface);
+       return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI COMCAT_IEnumCATEGORYINFO_Release(LPENUMCATEGORYINFO iface)
+{
+    IEnumCATEGORYINFOImpl *This = (IEnumCATEGORYINFOImpl *)iface;
+    ULONG ref;
+
+    TRACE("\n");
+
+    ref = InterlockedDecrement(&This->ref);
+    if (ref == 0) {
+       if (This->key) RegCloseKey(This->key);
+       HeapFree(GetProcessHeap(), 0, This);
+       return 0;
+    }
+    return ref;
+}
+
+static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Next(
+    LPENUMCATEGORYINFO iface,
+    ULONG celt,
+    CATEGORYINFO *rgelt,
+    ULONG *pceltFetched)
+{
+    IEnumCATEGORYINFOImpl *This = (IEnumCATEGORYINFOImpl *)iface;
+    ULONG fetched = 0;
+
+    TRACE("\n");
+
+    if (rgelt == NULL) return E_POINTER;
+
+    if (This->key) while (fetched < celt) {
+       LSTATUS res;
+       HRESULT hr;
+       WCHAR catid[39];
+       DWORD cName = 39;
+       HKEY subkey;
+
+       res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
+                           NULL, NULL, NULL, NULL);
+       if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+       ++(This->next_index);
+
+       hr = CLSIDFromString(catid, &rgelt->catid);
+       if (FAILED(hr)) continue;
+
+       res = RegOpenKeyExW(This->key, catid, 0, KEY_READ, &subkey);
+       if (res != ERROR_SUCCESS) continue;
+
+       hr = COMCAT_GetCategoryDesc(subkey, This->lcid,
+                                   rgelt->szDescription, 128);
+       RegCloseKey(subkey);
+       if (FAILED(hr)) continue;
+
+       rgelt->lcid = This->lcid;
+       ++fetched;
+       ++rgelt;
+    }
+
+    if (pceltFetched) *pceltFetched = fetched;
+    return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Skip(
+    LPENUMCATEGORYINFO iface,
+    ULONG celt)
+{
+    IEnumCATEGORYINFOImpl *This = (IEnumCATEGORYINFOImpl *)iface;
+
+    TRACE("\n");
+
+    This->next_index += celt;
+    /* This should return S_FALSE when there aren't celt elems to skip. */
+    return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Reset(LPENUMCATEGORYINFO iface)
+{
+    IEnumCATEGORYINFOImpl *This = (IEnumCATEGORYINFOImpl *)iface;
+
+    TRACE("\n");
+
+    This->next_index = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_IEnumCATEGORYINFO_Clone(
+    LPENUMCATEGORYINFO iface,
+    IEnumCATEGORYINFO **ppenum)
+{
+    IEnumCATEGORYINFOImpl *This = (IEnumCATEGORYINFOImpl *)iface;
+    static const WCHAR keyname[] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n',
+                                     't', ' ', 'C', 'a', 't', 'e', 'g', 'o',
+                                     'r', 'i', 'e', 's', 0 };
+    IEnumCATEGORYINFOImpl *new_this;
+
+    TRACE("\n");
+
+    if (ppenum == NULL) return E_POINTER;
+
+    new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumCATEGORYINFOImpl));
+    if (new_this == NULL) return E_OUTOFMEMORY;
+
+    new_this->lpVtbl = This->lpVtbl;
+    new_this->ref = 1;
+    new_this->lcid = This->lcid;
+    /* FIXME: could we more efficiently use DuplicateHandle? */
+    RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key);
+    new_this->next_index = This->next_index;
+
+    *ppenum = (LPENUMCATEGORYINFO)new_this;
+    return S_OK;
+}
+
+static const IEnumCATEGORYINFOVtbl COMCAT_IEnumCATEGORYINFO_Vtbl =
+{
+    COMCAT_IEnumCATEGORYINFO_QueryInterface,
+    COMCAT_IEnumCATEGORYINFO_AddRef,
+    COMCAT_IEnumCATEGORYINFO_Release,
+    COMCAT_IEnumCATEGORYINFO_Next,
+    COMCAT_IEnumCATEGORYINFO_Skip,
+    COMCAT_IEnumCATEGORYINFO_Reset,
+    COMCAT_IEnumCATEGORYINFO_Clone
+};
+
+static LPENUMCATEGORYINFO COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid)
+{
+    IEnumCATEGORYINFOImpl *This;
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumCATEGORYINFOImpl));
+    if (This) {
+        static const WCHAR keyname[] = { 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n',
+                                         't', ' ', 'C', 'a', 't', 'e', 'g', 'o',
+                                         'r', 'i', 'e', 's', 0 };
+
+       This->lpVtbl = &COMCAT_IEnumCATEGORYINFO_Vtbl;
+       This->lcid = lcid;
+       RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key);
+    }
+    return (LPENUMCATEGORYINFO)This;
+}
+
+/**********************************************************************
+ * ClassesOfCategories IEnumCLSID (IEnumGUID) implementation
+ *
+ * This implementation is not thread-safe.  The manager itself is, but
+ * I can't imagine a valid use of an enumerator in several threads.
+ */
+typedef struct
+{
+    const IEnumGUIDVtbl *lpVtbl;
+    LONG  ref;
+    struct class_categories *categories;
+    HKEY  key;
+    DWORD next_index;
+} CLSID_IEnumGUIDImpl;
+
+static ULONG WINAPI COMCAT_CLSID_IEnumGUID_AddRef(LPENUMGUID iface)
+{
+    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
+    TRACE("\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_QueryInterface(
+    LPENUMGUID iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (ppvObj == NULL) return E_POINTER;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+       IsEqualGUID(riid, &IID_IEnumGUID))
+    {
+       *ppvObj = (LPVOID)iface;
+       COMCAT_CLSID_IEnumGUID_AddRef(iface);
+       return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI COMCAT_CLSID_IEnumGUID_Release(LPENUMGUID iface)
+{
+    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
+    ULONG ref;
+
+    TRACE("\n");
+
+    ref = InterlockedDecrement(&This->ref);
+    if (ref == 0) {
+       if (This->key) RegCloseKey(This->key);
+       HeapFree(GetProcessHeap(), 0, (LPVOID)This->categories);
+       HeapFree(GetProcessHeap(), 0, This);
+       return 0;
+    }
+    return ref;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Next(
+    LPENUMGUID iface,
+    ULONG celt,
+    GUID *rgelt,
+    ULONG *pceltFetched)
+{
+    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
+    ULONG fetched = 0;
+
+    TRACE("\n");
+
+    if (rgelt == NULL) return E_POINTER;
+
+    if (This->key) while (fetched < celt) {
+       LSTATUS res;
+       HRESULT hr;
+       WCHAR clsid[39];
+       DWORD cName = 39;
+       HKEY subkey;
+
+       res = RegEnumKeyExW(This->key, This->next_index, clsid, &cName,
+                           NULL, NULL, NULL, NULL);
+       if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+       ++(This->next_index);
+
+       hr = CLSIDFromString(clsid, rgelt);
+       if (FAILED(hr)) continue;
+
+       res = RegOpenKeyExW(This->key, clsid, 0, KEY_READ, &subkey);
+       if (res != ERROR_SUCCESS) continue;
+
+       hr = COMCAT_IsClassOfCategories(subkey, This->categories);
+       RegCloseKey(subkey);
+       if (hr != S_OK) continue;
+
+       ++fetched;
+       ++rgelt;
+    }
+
+    if (pceltFetched) *pceltFetched = fetched;
+    return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Skip(
+    LPENUMGUID iface,
+    ULONG celt)
+{
+    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
+
+    TRACE("\n");
+
+    This->next_index += celt;
+    FIXME("Never returns S_FALSE\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Reset(LPENUMGUID iface)
+{
+    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
+
+    TRACE("\n");
+
+    This->next_index = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Clone(
+    LPENUMGUID iface,
+    IEnumGUID **ppenum)
+{
+    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
+    static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 };
+    CLSID_IEnumGUIDImpl *new_this;
+    DWORD size;
+
+    TRACE("\n");
+
+    if (ppenum == NULL) return E_POINTER;
+
+    new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
+    if (new_this == NULL) return E_OUTOFMEMORY;
+
+    new_this->lpVtbl = This->lpVtbl;
+    new_this->ref = 1;
+    size = HeapSize(GetProcessHeap(), 0, (LPVOID)This->categories);
+    new_this->categories =
+       HeapAlloc(GetProcessHeap(), 0, size);
+    if (new_this->categories == NULL) {
+       HeapFree(GetProcessHeap(), 0, new_this);
+       return E_OUTOFMEMORY;
+    }
+    memcpy((LPVOID)new_this->categories, This->categories, size);
+    /* FIXME: could we more efficiently use DuplicateHandle? */
+    RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key);
+    new_this->next_index = This->next_index;
+
+    *ppenum = (LPENUMGUID)new_this;
+    return S_OK;
+}
+
+static const IEnumGUIDVtbl COMCAT_CLSID_IEnumGUID_Vtbl =
+{
+    COMCAT_CLSID_IEnumGUID_QueryInterface,
+    COMCAT_CLSID_IEnumGUID_AddRef,
+    COMCAT_CLSID_IEnumGUID_Release,
+    COMCAT_CLSID_IEnumGUID_Next,
+    COMCAT_CLSID_IEnumGUID_Skip,
+    COMCAT_CLSID_IEnumGUID_Reset,
+    COMCAT_CLSID_IEnumGUID_Clone
+};
+
+static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(struct class_categories *categories)
+{
+    CLSID_IEnumGUIDImpl *This;
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
+    if (This) {
+       static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 };
+
+       This->lpVtbl = &COMCAT_CLSID_IEnumGUID_Vtbl;
+       This->categories = categories;
+       RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key);
+    }
+    return (LPENUMGUID)This;
+}
+
+/**********************************************************************
+ * CategoriesOfClass IEnumCATID (IEnumGUID) implementation
+ *
+ * This implementation is not thread-safe.  The manager itself is, but
+ * I can't imagine a valid use of an enumerator in several threads.
+ */
+typedef struct
+{
+    const IEnumGUIDVtbl *lpVtbl;
+    LONG  ref;
+    WCHAR keyname[68];
+    HKEY  key;
+    DWORD next_index;
+} CATID_IEnumGUIDImpl;
+
+static ULONG WINAPI COMCAT_CATID_IEnumGUID_AddRef(LPENUMGUID iface)
+{
+    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
+    TRACE("\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_QueryInterface(
+    LPENUMGUID iface,
+    REFIID riid,
+    LPVOID *ppvObj)
+{
+    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
+
+    if (ppvObj == NULL) return E_POINTER;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+       IsEqualGUID(riid, &IID_IEnumGUID))
+    {
+       *ppvObj = (LPVOID)iface;
+       COMCAT_CATID_IEnumGUID_AddRef(iface);
+       return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI COMCAT_CATID_IEnumGUID_Release(LPENUMGUID iface)
+{
+    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
+    ULONG ref;
+
+    TRACE("\n");
+
+    ref = InterlockedDecrement(&This->ref);
+    if (ref == 0) {
+       if (This->key) RegCloseKey(This->key);
+       HeapFree(GetProcessHeap(), 0, This);
+       return 0;
+    }
+    return ref;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Next(
+    LPENUMGUID iface,
+    ULONG celt,
+    GUID *rgelt,
+    ULONG *pceltFetched)
+{
+    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
+    ULONG fetched = 0;
+
+    TRACE("\n");
+
+    if (rgelt == NULL) return E_POINTER;
+
+    if (This->key) while (fetched < celt) {
+       LSTATUS res;
+       HRESULT hr;
+       WCHAR catid[39];
+       DWORD cName = 39;
+
+       res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
+                           NULL, NULL, NULL, NULL);
+       if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
+       ++(This->next_index);
+
+       hr = CLSIDFromString(catid, rgelt);
+       if (FAILED(hr)) continue;
+
+       ++fetched;
+       ++rgelt;
+    }
+
+    if (pceltFetched) *pceltFetched = fetched;
+    return fetched == celt ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Skip(
+    LPENUMGUID iface,
+    ULONG celt)
+{
+    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
+
+    TRACE("\n");
+
+    This->next_index += celt;
+    FIXME("Never returns S_FALSE\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Reset(LPENUMGUID iface)
+{
+    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
+
+    TRACE("\n");
+
+    This->next_index = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Clone(
+    LPENUMGUID iface,
+    IEnumGUID **ppenum)
+{
+    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
+    CATID_IEnumGUIDImpl *new_this;
+
+    TRACE("\n");
+
+    if (ppenum == NULL) return E_POINTER;
+
+    new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl));
+    if (new_this == NULL) return E_OUTOFMEMORY;
+
+    new_this->lpVtbl = This->lpVtbl;
+    new_this->ref = 1;
+    lstrcpyW(new_this->keyname, This->keyname);
+    /* FIXME: could we more efficiently use DuplicateHandle? */
+    RegOpenKeyExW(HKEY_CLASSES_ROOT, new_this->keyname, 0, KEY_READ, &new_this->key);
+    new_this->next_index = This->next_index;
+
+    *ppenum = (LPENUMGUID)new_this;
+    return S_OK;
+}
+
+static const IEnumGUIDVtbl COMCAT_CATID_IEnumGUID_Vtbl =
+{
+    COMCAT_CATID_IEnumGUID_QueryInterface,
+    COMCAT_CATID_IEnumGUID_AddRef,
+    COMCAT_CATID_IEnumGUID_Release,
+    COMCAT_CATID_IEnumGUID_Next,
+    COMCAT_CATID_IEnumGUID_Skip,
+    COMCAT_CATID_IEnumGUID_Reset,
+    COMCAT_CATID_IEnumGUID_Clone
+};
+
+static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct(
+    REFCLSID rclsid, LPCWSTR postfix)
+{
+    CATID_IEnumGUIDImpl *This;
+
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl));
+    if (This) {
+       WCHAR prefix[6] = { 'C', 'L', 'S', 'I', 'D', '\\' };
+
+       This->lpVtbl = &COMCAT_CATID_IEnumGUID_Vtbl;
+       memcpy(This->keyname, prefix, sizeof(prefix));
+       StringFromGUID2(rclsid, This->keyname + 6, 39);
+       lstrcpyW(This->keyname + 44, postfix);
+       RegOpenKeyExW(HKEY_CLASSES_ROOT, This->keyname, 0, KEY_READ, &This->key);
+    }
+    return (LPENUMGUID)This;
+}
index 69f42fc..37907ec 100644 (file)
@@ -34,9 +34,6 @@
  *   - Implement the OXID resolver so we don't need magic endpoint names for
  *     clients and servers to meet up
  *
- *   - Make all ole interface marshaling use NDR to be wire compatible with
- *     native DCOM
- *
  */
 
 #include "config.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
-HINSTANCE OLE32_hInstance = 0; /* FIXME: make static ... */
+HINSTANCE OLE32_hInstance = 0;
 
 #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
 
 /****************************************************************************
  * This section defines variables internal to the COM module.
- *
- * TODO: Most of these things will have to be made thread-safe.
  */
 
 static HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid,
@@ -116,7 +111,7 @@ static LONG s_COMServerProcessReferences = 0;
  * objects.
  *
  * TODO: Make this data structure aware of inter-process communication. This
- *       means that parts of this will be exported to the Wine Server.
+ *       means that parts of this will be exported to rpcss.
  */
 typedef struct tagRegisteredClass
 {
@@ -209,8 +204,8 @@ static void COMPOBJ_InitProcess( void )
      * following class is created. The *caller* of CoMarshalInterface (i.e., the
      * application) is responsible for pumping the message loop in that thread.
      * The WM_USER messages which point to the RPCs are then dispatched to
-     * COM_AptWndProc by the user's code from the apartment in which the interface
-     * was unmarshalled.
+     * apartment_wndproc by the user's code from the apartment in which the
+     * interface was unmarshalled.
      */
     memset(&wclass, 0, sizeof(wclass));
     wclass.lpfnWndProc = apartment_wndproc;
@@ -560,6 +555,8 @@ struct host_thread_params
     HWND apartment_hwnd;
 };
 
+/* thread for hosting an object to allow an object to appear to be created in
+ * an apartment with an incompatible threading model */
 static DWORD CALLBACK apartment_hostobject_thread(LPVOID p)
 {
     struct host_thread_params *params = p;
@@ -609,7 +606,12 @@ static DWORD CALLBACK apartment_hostobject_thread(LPVOID p)
     return S_OK;
 }
 
-static HRESULT apartment_hostobject_in_hostapt(struct apartment *apt, BOOL multi_threaded, BOOL main_apartment, HKEY hkeydll, REFCLSID rclsid, REFIID riid, void **ppv)
+/* finds or creates a host apartment, creates the object inside it and returns
+ * a proxy to it so that the object can be used in the apartment of the
+ * caller of this function */
+static HRESULT apartment_hostobject_in_hostapt(
+    struct apartment *apt, BOOL multi_threaded, BOOL main_apartment,
+    HKEY hkeydll, REFCLSID rclsid, REFIID riid, void **ppv)
 {
     struct host_object_params params;
     HWND apartment_hwnd = NULL;
@@ -715,6 +717,8 @@ static HRESULT apartment_hostobject_in_hostapt(struct apartment *apt, BOOL multi
     return hr;
 }
 
+/* create a window for the apartment or return the current one if one has
+ * already been created */
 HRESULT apartment_createwindowifneeded(struct apartment *apt)
 {
     if (apt->multi_threaded)
@@ -738,6 +742,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt)
     return S_OK;
 }
 
+/* retrieves the window for the main- or apartment-threaded apartment */
 HWND apartment_getwindow(const struct apartment *apt)
 {
     assert(!apt->multi_threaded);
@@ -750,6 +755,8 @@ void apartment_joinmta(void)
     COM_CurrentInfo()->apt = MTA;
 }
 
+/* gets the specified class object by loading the appropriate DLL, if
+ * necessary and calls the DllGetClassObject function for the DLL */
 static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
                                         BOOL apartment_threaded,
                                         REFCLSID rclsid, REFIID riid, void **ppv)
@@ -822,6 +829,8 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
     return hr;
 }
 
+/* frees unused libraries loaded by apartment_getclassobject by calling the
+ * DLL's DllCanUnloadNow entry point */
 static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
 {
     struct apartment_loaded_dll *entry, *next;
@@ -834,6 +843,10 @@ static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
 
             if (real_delay == INFINITE)
             {
+                /* DLLs that return multi-threaded objects aren't unloaded
+                 * straight away to cope for programs that have races between
+                 * last object destruction and threads in the DLLs that haven't
+                 * finished, despite DllCanUnloadNow returning S_OK */
                 if (entry->multi_threaded)
                     real_delay = 10 * 60 * 1000; /* 10 minutes */
                 else
index fbfe37c..81d591e 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 1999 Francis Beaudet
  * Copyright 1999 Sylvain St-Germain
  * Copyright 2002 Marcus Meissner
- * Copyright 2003 Ove Kåven, TransGaming Technologies
+ * Copyright 2003 Ove Kåven, TransGaming Technologies
  * Copyright 2004 Mike Hearn, Rob Shearman, CodeWeavers Inc
  *
  * This library is free software; you can redistribute it and/or
index d4abf43..a1c0dcd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003 Ove Kåven, TransGaming Technologies
+ * Copyright 2003 Ove Kåven, TransGaming Technologies
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
index afacc51..6844ee8 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
+enum storage_state
+{
+    storage_state_uninitialised,
+    storage_state_initialised,
+    storage_state_loaded
+};
+
 /****************************************************************************
  * DefaultHandler
  *
@@ -119,16 +126,14 @@ struct DefaultHandler
 
   /* connection cookie for the advise on the delegate OLE object */
   DWORD dwAdvConn;
+
+  /* storage passed to Load or InitNew */
+  IStorage *storage;
+  enum storage_state storage_state;
 };
 
 typedef struct DefaultHandler DefaultHandler;
 
-/*
- * Here, I define utility functions to help with the casting of the
- * "This" parameter.
- * There is a version to accommodate all of the VTables implemented
- * by this object.
- */
 static inline DefaultHandler *impl_from_IOleObject( IOleObject *iface )
 {
     return (DefaultHandler *)((char*)iface - FIELD_OFFSET(DefaultHandler, lpVtbl));
@@ -186,7 +191,6 @@ static HRESULT WINAPI DefaultHandler_NDIUnknown_QueryInterface(
 {
   DefaultHandler *This = impl_from_NDIUnknown(iface);
 
-  /* Perform a sanity check on the parameters. */
   if (!ppvObject)
     return E_INVALIDARG;
 
@@ -258,7 +262,6 @@ static ULONG WINAPI DefaultHandler_NDIUnknown_Release(
   DefaultHandler *This = impl_from_NDIUnknown(iface);
   ULONG ref;
 
-  /* Decrease the reference count on this object. */
   ref = InterlockedDecrement(&This->ref);
 
   if (!ref) DefaultHandler_Destroy(This);
@@ -361,7 +364,6 @@ static HRESULT WINAPI DefaultHandler_GetClientSite(
 {
   DefaultHandler *This = impl_from_IOleObject(iface);
 
-  /* Sanity check. */
   if (!ppClientSite)
     return E_POINTER;
 
@@ -402,7 +404,6 @@ static HRESULT WINAPI DefaultHandler_SetHostNames(
   HeapFree( GetProcessHeap(), 0, This->containerObj );
   This->containerObj = NULL;
 
-  /* Copy the string supplied. */
   if (szContainerApp)
   {
       if ((This->containerApp = HeapAlloc( GetProcessHeap(), 0,
@@ -419,8 +420,8 @@ static HRESULT WINAPI DefaultHandler_SetHostNames(
   return S_OK;
 }
 
-/* undos the work done by DefaultHandler_Run */
-static void WINAPI DefaultHandler_Stop(DefaultHandler *This)
+/* undoes the work done by DefaultHandler_Run */
+static void DefaultHandler_Stop(DefaultHandler *This)
 {
   if (!object_is_running(This))
     return;
@@ -631,8 +632,15 @@ static HRESULT WINAPI DefaultHandler_EnumVerbs(
 static HRESULT WINAPI DefaultHandler_Update(
            IOleObject*        iface)
 {
-  FIXME(": Stub\n");
-  return E_NOTIMPL;
+    DefaultHandler *This = impl_from_IOleObject(iface);
+    TRACE("(%p)\n", iface);
+
+    if (!object_is_running(This))
+    {
+        FIXME("Should run object\n");
+        return E_NOTIMPL;
+    }
+    return IOleObject_Update(This->pOleDelegate);
 }
 
 /************************************************************************
@@ -645,9 +653,13 @@ static HRESULT WINAPI DefaultHandler_Update(
 static HRESULT WINAPI DefaultHandler_IsUpToDate(
            IOleObject*        iface)
 {
-  TRACE("(%p)\n", iface);
+    DefaultHandler *This = impl_from_IOleObject(iface);
+    TRACE("(%p)\n", iface);
 
-  return OLE_E_NOTRUNNING;
+    if (object_is_running(This))
+        return IOleObject_IsUpToDate(This->pOleDelegate);
+
+    return OLE_E_NOTRUNNING;
 }
 
 /************************************************************************
@@ -668,7 +680,6 @@ static HRESULT WINAPI DefaultHandler_GetUserClassID(
   if (object_is_running(This))
     return IOleObject_GetUserClassID(This->pOleDelegate, pClsid);
 
-  /* Sanity check. */
   if (!pClsid)
     return E_POINTER;
 
@@ -693,6 +704,8 @@ static HRESULT WINAPI DefaultHandler_GetUserType(
   DefaultHandler *This = impl_from_IOleObject(iface);
 
   TRACE("(%p, %d, %p)\n", iface, dwFormOfType, pszUserType);
+  if (object_is_running(This))
+    return IOleObject_GetUserType(This->pOleDelegate, dwFormOfType, pszUserType);
 
   return OleRegGetUserType(&This->clsid, dwFormOfType, pszUserType);
 }
@@ -764,9 +777,6 @@ static HRESULT WINAPI DefaultHandler_GetExtent(
                                targetDevice,
                                psizel);
 
-  /*
-   * Cleanup
-   */
   IViewObject2_Release(cacheView);
 
   return hres;
@@ -845,7 +855,6 @@ static HRESULT WINAPI DefaultHandler_EnumAdvise(
 
   TRACE("(%p, %p)\n", iface, ppenumAdvise);
 
-  /* Sanity check */
   if (!ppenumAdvise)
     return E_POINTER;
 
@@ -1202,7 +1211,6 @@ static HRESULT WINAPI DefaultHandler_EnumDAdvise(
 
   TRACE("(%p, %p)\n", iface, ppenumAdvise);
 
-  /* Sanity check */
   if (!ppenumAdvise)
     return E_POINTER;
 
@@ -1305,7 +1313,12 @@ static HRESULT WINAPI DefaultHandler_Run(
     IOleObject_QueryInterface(This->pOleDelegate, &IID_IPersistStorage,
                               (void **)&This->pPSDelegate);
     if (This->pPSDelegate)
-      hr = IPersistStorage_InitNew(This->pPSDelegate, NULL);
+    {
+      if(This->storage_state == storage_state_initialised)
+        hr = IPersistStorage_InitNew(This->pPSDelegate, This->storage);
+      else if(This->storage_state == storage_state_loaded)
+        hr = IPersistStorage_Load(This->pPSDelegate, This->storage);
+    }
   }
 
   if (SUCCEEDED(hr) && This->containerApp)
@@ -1507,9 +1520,17 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_GetClassID(
             IPersistStorage*     iface,
             CLSID*               clsid)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, clsid);
+
+    if(object_is_running(This))
+        hr = IPersistStorage_GetClassID(This->pPSDelegate, clsid);
+    else
+        hr = IPersistStorage_GetClassID(This->dataCache_PersistStg, clsid);
 
-  return IPersistStorage_GetClassID(This->dataCache_PersistStg, clsid);
+    return hr;
 }
 
 /************************************************************************
@@ -1519,9 +1540,106 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_GetClassID(
 static HRESULT WINAPI DefaultHandler_IPersistStorage_IsDirty(
             IPersistStorage*     iface)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", iface);
+
+    hr = IPersistStorage_IsDirty(This->dataCache_PersistStg);
+    if(hr != S_FALSE) return hr;
+
+    if(object_is_running(This))
+        hr = IPersistStorage_IsDirty(This->pPSDelegate);
+
+    return hr;
+}
+
+/***********************************************************************
+ *   init_ole_stream
+ *
+ * Creates the '\1Ole' stream.
+ * The format of this stream is as follows:
+ *
+ * DWORD Version == 0x02000001
+ * DWORD Flags - low bit set indicates the object is a link otherwise it's embedded.
+ * DWORD LinkupdateOption - [MS-OLEDS describes this as an implementation specific hint
+ *                           supplied by the app that creates the data structure.  May be
+ *                           ignored on processing].
+ *
+ * DWORD Reserved == 0
+ * DWORD MonikerStreamSize - size of the rest of the data (ie CLSID + moniker stream data).
+ * CLSID clsid - class id of object capable of processing the moniker
+ * BYTE  data[] - moniker data for a link
+ */
+
+static const WCHAR OleStream[] = {1,'O','l','e',0};
+typedef struct
+{
+    DWORD version;
+    DWORD flags;
+    DWORD link_update_opt;
+    DWORD res;
+    DWORD moniker_size;
+} ole_stream_header_t;
+static const DWORD ole_stream_version = 0x02000001;
+
+static void init_ole_stream(IStorage *storage)
+{
+    HRESULT hr;
+    IStream *stream;
+
+    hr = IStorage_CreateStream(storage, OleStream, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream);
+    if(SUCCEEDED(hr))
+    {
+        DWORD written;
+        ole_stream_header_t header;
+
+        header.version         = ole_stream_version;
+        header.flags           = 0;
+        header.link_update_opt = 0;
+        header.res             = 0;
+        header.moniker_size    = 0;
+
+        IStream_Write(stream, &header, sizeof(header), &written);
+        IStream_Release(stream);
+    }
+    return;
+}
+
+static HRESULT load_ole_stream(DefaultHandler *This, IStorage *storage)
+{
+    IStream *stream;
+    HRESULT hr;
+
+    hr = IStorage_OpenStream(storage, OleStream, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream);
 
-  return IPersistStorage_IsDirty(This->dataCache_PersistStg);
+    if(SUCCEEDED(hr))
+    {
+        DWORD read;
+        ole_stream_header_t header;
+
+        hr = IStream_Read(stream, &header, sizeof(header), &read);
+        if(hr == S_OK && read == sizeof(header) && header.version == ole_stream_version)
+        {
+            if(header.flags & 1)
+            {
+                /* FIXME: Read the moniker and deal with the link */
+                FIXME("Linked objects are not supported yet\n");
+            }
+        }
+        else
+        {
+            WARN("Incorrect OleStream header\n");
+            hr = DV_E_CLIPFORMAT;
+        }
+        IStream_Release(stream);
+    }
+    else
+    {
+        init_ole_stream(storage);
+        hr = S_OK;
+    }
+    return hr;
 }
 
 /************************************************************************
@@ -1532,9 +1650,25 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_InitNew(
            IPersistStorage*     iface,
            IStorage*            pStg)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, pStg);
+    init_ole_stream(pStg);
 
-  return IPersistStorage_InitNew(This->dataCache_PersistStg, pStg);
+    hr = IPersistStorage_InitNew(This->dataCache_PersistStg, pStg);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_InitNew(This->pPSDelegate, pStg);
+
+    if(SUCCEEDED(hr))
+    {
+        IStorage_AddRef(pStg);
+        This->storage = pStg;
+        This->storage_state = storage_state_initialised;
+    }
+
+    return hr;
 }
 
 
@@ -1546,9 +1680,26 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_Load(
            IPersistStorage*     iface,
            IStorage*            pStg)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, pStg);
+
+    hr = load_ole_stream(This, pStg);
 
-  return IPersistStorage_Load(This->dataCache_PersistStg, pStg);
+    if(SUCCEEDED(hr))
+        hr = IPersistStorage_Load(This->dataCache_PersistStg, pStg);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_Load(This->pPSDelegate, pStg);
+
+    if(SUCCEEDED(hr))
+    {
+        IStorage_AddRef(pStg);
+        This->storage = pStg;
+        This->storage_state = storage_state_loaded;
+    }
+    return hr;
 }
 
 
@@ -1559,11 +1710,18 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_Load(
 static HRESULT WINAPI DefaultHandler_IPersistStorage_Save(
            IPersistStorage*     iface,
            IStorage*            pStgSave,
-           BOOL                 fSaveAsLoad)
+           BOOL                 fSameAsLoad)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
 
-  return IPersistStorage_Save(This->dataCache_PersistStg, pStgSave, fSaveAsLoad);
+    TRACE("(%p)->(%p, %d)\n", iface, pStgSave, fSameAsLoad);
+
+    hr = IPersistStorage_Save(This->dataCache_PersistStg, pStgSave, fSameAsLoad);
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_Save(This->pPSDelegate, pStgSave, fSameAsLoad);
+
+    return hr;
 }
 
 
@@ -1575,9 +1733,25 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_SaveCompleted(
            IPersistStorage*     iface,
            IStorage*            pStgNew)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", iface, pStgNew);
+
+    hr = IPersistStorage_SaveCompleted(This->dataCache_PersistStg, pStgNew);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_SaveCompleted(This->pPSDelegate, pStgNew);
+
+    if(pStgNew)
+    {
+        IStorage_AddRef(pStgNew);
+        if(This->storage) IStorage_Release(This->storage);
+        This->storage = pStgNew;
+        This->storage_state = storage_state_loaded;
+    }
 
-  return IPersistStorage_SaveCompleted(This->dataCache_PersistStg, pStgNew);
+    return hr;
 }
 
 
@@ -1588,9 +1762,21 @@ static HRESULT WINAPI DefaultHandler_IPersistStorage_SaveCompleted(
 static HRESULT WINAPI DefaultHandler_IPersistStorage_HandsOffStorage(
             IPersistStorage*     iface)
 {
-  DefaultHandler *This = impl_from_IPersistStorage(iface);
+    DefaultHandler *This = impl_from_IPersistStorage(iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", iface);
+
+    hr = IPersistStorage_HandsOffStorage(This->dataCache_PersistStg);
+
+    if(SUCCEEDED(hr) && object_is_running(This))
+        hr = IPersistStorage_HandsOffStorage(This->pPSDelegate);
 
-  return IPersistStorage_HandsOffStorage(This->dataCache_PersistStg);
+    if(This->storage) IStorage_Release(This->storage);
+    This->storage = NULL;
+    This->storage_state = storage_state_uninitialised;
+
+    return hr;
 }
 
 
@@ -1696,9 +1882,6 @@ static DefaultHandler* DefaultHandler_Construct(
   DefaultHandler* This = NULL;
   HRESULT hr;
 
-  /*
-   * Allocate space for the object.
-   */
   This = HeapAlloc(GetProcessHeap(), 0, sizeof(DefaultHandler));
 
   if (!This)
@@ -1741,9 +1924,7 @@ static DefaultHandler* DefaultHandler_Construct(
     hr = IUnknown_QueryInterface(This->dataCache, &IID_IPersistStorage, (void**)&This->dataCache_PersistStg);
   if(FAILED(hr))
     ERR("Unexpected error creating data cache\n");
-  /*
-   * Initialize the other data members of the class.
-   */
+
   This->clsid = *clsid;
   This->clientSite = NULL;
   This->oleAdviseHolder = NULL;
@@ -1755,6 +1936,8 @@ static DefaultHandler* DefaultHandler_Construct(
   This->pDataDelegate = NULL;
 
   This->dwAdvConn = 0;
+  This->storage = NULL;
+  This->storage_state = storage_state_uninitialised;
 
   return This;
 }
@@ -1765,13 +1948,11 @@ static void DefaultHandler_Destroy(
   /* release delegates */
   DefaultHandler_Stop(This);
 
-  /* Free the strings idenfitying the object */
   HeapFree( GetProcessHeap(), 0, This->containerApp );
   This->containerApp = NULL;
   HeapFree( GetProcessHeap(), 0, This->containerObj );
   This->containerObj = NULL;
 
-  /* Release our reference to the data cache. */
   if (This->dataCache)
   {
     IPersistStorage_Release(This->dataCache_PersistStg);
@@ -1780,28 +1961,30 @@ static void DefaultHandler_Destroy(
     This->dataCache = NULL;
   }
 
-  /* Same thing for the client site. */
   if (This->clientSite)
   {
     IOleClientSite_Release(This->clientSite);
     This->clientSite = NULL;
   }
 
-  /* And the advise holder. */
   if (This->oleAdviseHolder)
   {
     IOleAdviseHolder_Release(This->oleAdviseHolder);
     This->oleAdviseHolder = NULL;
   }
 
-  /* And the data advise holder. */
   if (This->dataAdviseHolder)
   {
     IDataAdviseHolder_Release(This->dataAdviseHolder);
     This->dataAdviseHolder = NULL;
   }
 
-  /* Free the actual default handler structure. */
+  if (This->storage)
+  {
+    IStorage_Release(This->storage);
+    This->storage = NULL;
+  }
+
   HeapFree(GetProcessHeap(), 0, This);
 }
 
@@ -1819,9 +2002,6 @@ HRESULT WINAPI OleCreateDefaultHandler(
 
   TRACE("(%s, %p, %s, %p)\n", debugstr_guid(clsid), pUnkOuter, debugstr_guid(riid), ppvObj);
 
-  /*
-   * Sanity check
-   */
   if (!ppvObj)
     return E_POINTER;
 
index 74c867a..3dae139 100644 (file)
@@ -358,12 +358,12 @@ FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
 
     /* write a 0 WORD */
     res=IStream_Write(pStm,&ZERO,sizeof(WORD),NULL);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* write length of filePath string ( 0 included )*/
     bytesA = WideCharToMultiByte( CP_ACP, 0, filePathW, -1, NULL, 0, NULL, NULL );
     res=IStream_Write(pStm,&bytesA,sizeof(DWORD),NULL);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* write A string (with '\0') */
     filePathA=HeapAlloc(GetProcessHeap(),0,bytesA);
@@ -372,17 +372,17 @@ FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
     WideCharToMultiByte( CP_ACP, 0, filePathW, -1, filePathA, bytesA, NULL, &bUsedDefault);
     res=IStream_Write(pStm,filePathA,bytesA,NULL);
     HeapFree(GetProcessHeap(),0,filePathA);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* write a DWORD 0xDEADFFFF */
     res=IStream_Write(pStm,&DEADFFFF,sizeof(DWORD),NULL);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* write 5 zero DWORDs */
     for(i=0;i<5;i++)
     {
         res=IStream_Write(pStm,&ZERO,sizeof(DWORD),NULL);
-        if (!SUCCEEDED(res)) return res;
+        if (FAILED(res)) return res;
     }
 
     /* Write the wide version if:
@@ -414,16 +414,16 @@ FileMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
     /* write bytes needed for the filepathW (without 0) + 6 */
     bytesW = len*sizeof(WCHAR) + 6;
     res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* try again, without the extra 6 */
     bytesW -= 6;
     res=IStream_Write(pStm,&bytesW,sizeof(DWORD),NULL);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* write a WORD 3 */
     res=IStream_Write(pStm,&THREE,sizeof(WORD),NULL);
-    if (!SUCCEEDED(res)) return res;
+    if (FAILED(res)) return res;
 
     /* write W string (no 0) */
     res=IStream_Write(pStm,filePathW,bytesW,NULL);
index a4d2a5e..4e56462 100644 (file)
  * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "config.h"
+#include "wine/port.h"
+
 #include <stdarg.h>
 #include <string.h>
 
 #include "wine/list.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
+#include "wine/exception.h"
 
 #include "compobj_private.h"
 #include "moniker.h"
+#include "irot.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
 
 /* see MSDN docs for IROTData::GetComparisonData, which states what this
- * constant is (http://msdn2.microsoft.com/en-us/library/ms693773.aspx) */
+ * constant is
+ */
 #define MAX_COMPARISON_DATA 2048
 
+static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
+{
+    return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
+}
+
 /* 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 */
+    InterfaceData* object; /* marshaled running object*/
+    MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */
     DWORD              cookie; /* cookie identifying this object */
     FILETIME           last_modified;
+    IrotContextHandle  ctxt_handle;
 };
 
 /* define the RunningObjectTableImpl structure */
@@ -74,16 +79,7 @@ typedef struct RunningObjectTableImpl
 } RunningObjectTableImpl;
 
 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
-
-
-
-static inline HRESULT WINAPI
-IrotRegister(DWORD *cookie)
-{
-    static LONG last_cookie = 1;
-    *cookie = InterlockedIncrement(&last_cookie);
-    return S_OK;
-}
+static IrotHandle irot_handle;
 
 /* define the EnumMonikerImpl structure */
 typedef struct EnumMonikerImpl
@@ -91,17 +87,79 @@ typedef struct EnumMonikerImpl
     const IEnumMonikerVtbl *lpVtbl;
     LONG ref;
 
-    MInterfacePointer **monikers;
-    ULONG moniker_count;
+    InterfaceList *moniker_list;
     ULONG pos;
 } EnumMonikerImpl;
 
 
 /* IEnumMoniker Local functions*/
-static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
-    ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker);
+static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
+    ULONG pos, IEnumMoniker **ppenumMoniker);
+
+static IrotHandle get_irot_handle(void)
+{
+    if (!irot_handle)
+    {
+        RPC_STATUS status;
+        RPC_WSTR binding;
+        IrotHandle new_handle;
+        unsigned short ncacn_np[] = IROT_PROTSEQ;
+        unsigned short endpoint[] = IROT_ENDPOINT;
+        status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding);
+        if (status == RPC_S_OK)
+        {
+            status = RpcBindingFromStringBindingW(binding, &new_handle);
+            RpcStringFreeW(&binding);
+        }
+        if (status != RPC_S_OK)
+            return NULL;
+        if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL))
+            /* another thread beat us to it */
+            RpcBindingFree(&new_handle);
+    }
+    return irot_handle;
+}
 
-static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream)
+static BOOL start_rpcss(void)
+{
+    PROCESS_INFORMATION pi;
+    STARTUPINFOW si;
+    static WCHAR cmd[6];
+    static const WCHAR rpcss[] = {'r','p','c','s','s',0};
+    BOOL rslt;
+
+    TRACE("\n");
+
+    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+    ZeroMemory(&si, sizeof(STARTUPINFOA));
+    si.cb = sizeof(STARTUPINFOA);
+
+    memcpy(cmd, rpcss, sizeof(rpcss));
+
+    rslt = CreateProcessW(
+                          NULL,           /* executable */
+                          cmd,            /* command line */
+                          NULL,           /* process security attributes */
+                          NULL,           /* primary thread security attributes */
+                          FALSE,          /* inherit handles */
+                          0,              /* creation flags */
+                          NULL,           /* use parent's environment */
+                          NULL,           /* use parent's current directory */
+                          &si,            /* STARTUPINFO pointer */
+                          &pi             /* PROCESS_INFORMATION */
+                          );
+
+    if (rslt)
+    {
+        CloseHandle(pi.hProcess);
+        CloseHandle(pi.hThread);
+        Sleep(100);
+    }
+
+    return rslt;
+}
+
+static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
 {
     HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
     void *pv = GlobalLock(hglobal);
@@ -112,23 +170,38 @@ static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **s
 
 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)
+    if (rot_entry->cookie)
     {
-        IStream *stream;
-        HRESULT hr;
-        hr = create_stream_on_mip_ro(rot_entry->object, &stream);
-        if (hr == S_OK)
+        InterfaceData *object = NULL;
+        InterfaceData *moniker = NULL;
+        __TRY
         {
-            CoReleaseMarshalData(stream);
-            IUnknown_Release(stream);
+            IrotRevoke(get_irot_handle(), rot_entry->cookie,
+                       &rot_entry->ctxt_handle, &object, &moniker);
+        }
+        __EXCEPT(rpc_filter)
+        {
+        }
+        __ENDTRY
+        MIDL_user_free(object);
+        if (moniker)
+        {
+            IStream *stream;
+            HRESULT hr;
+            hr = create_stream_on_mip_ro(moniker, &stream);
+            if (hr == S_OK)
+            {
+                CoReleaseMarshalData(stream);
+                IUnknown_Release(stream);
+            }
         }
+        MIDL_user_free(moniker);
     }
-    if (rot_entry->moniker)
+    if (rot_entry->object)
     {
         IStream *stream;
         HRESULT hr;
-        hr = create_stream_on_mip_ro(rot_entry->moniker, &stream);
+        hr = create_stream_on_mip_ro(rot_entry->object, &stream);
         if (hr == S_OK)
         {
             CoReleaseMarshalData(stream);
@@ -136,13 +209,12 @@ static inline void rot_entry_delete(struct rot_entry *rot_entry)
         }
     }
     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)
+static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data)
 {
     HRESULT hr;
     IROTData *pROTData = NULL;
@@ -150,8 +222,14 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer
     if (SUCCEEDED(hr))
     {
         ULONG size = MAX_COMPARISON_DATA;
-        *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
+        *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size]));
+        if (!*moniker_data)
+        {
+            IROTData_Release(pROTData);
+            return E_OUTOFMEMORY;
+        }
         hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
+        IROTData_Release(pROTData);
         if (hr != S_OK)
         {
             ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr);
@@ -185,7 +263,7 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer
 
         len = strlenW(pszDisplayName);
         *moniker_data = HeapAlloc(GetProcessHeap(), 0,
-            FIELD_OFFSET(MInterfacePointer, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
+            FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
         if (!*moniker_data)
         {
             CoTaskMemFree(pszDisplayName);
@@ -195,6 +273,7 @@ static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer
 
         memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid));
         memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR));
+        CoTaskMemFree(pszDisplayName);
     }
     return S_OK;
 }
@@ -267,6 +346,7 @@ static HRESULT WINAPI
 RunningObjectTableImpl_Destroy(void)
 {
     struct list *cursor, *cursor2;
+    IrotHandle old_handle;
 
     TRACE("()\n");
 
@@ -288,6 +368,11 @@ RunningObjectTableImpl_Destroy(void)
     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
     runningObjectTableInstance = NULL;
 
+    old_handle = irot_handle;
+    irot_handle = NULL;
+    if (old_handle)
+        RpcBindingFree(&old_handle);
+
     return S_OK;
 }
 
@@ -341,6 +426,7 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
     IStream *pStream = NULL;
     DWORD mshlflags;
     IBindCtx *pbc;
+    InterfaceData *moniker = NULL;
 
     TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
 
@@ -378,7 +464,7 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
             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);
+            memcpy(rot_entry->object->abData, pv, size);
             GlobalUnlock(hglobal);
         }
     }
@@ -442,9 +528,9 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
         {
             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);
+            moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size]));
+            moniker->ulCntData = size;
+            memcpy(moniker->abData, pv, size);
             GlobalUnlock(hglobal);
         }
     }
@@ -452,13 +538,35 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
     IMoniker_Release(pmkObjectName);
     if (hr != S_OK)
     {
+        HeapFree(GetProcessHeap(), 0, moniker);
         rot_entry_delete(rot_entry);
         return hr;
     }
 
-    /* FIXME: not the right signature of IrotRegister function */
-    hr = IrotRegister(&rot_entry->cookie);
-    if (hr != S_OK)
+
+    while (TRUE)
+    {
+        __TRY
+        {
+            hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data,
+                              rot_entry->object, moniker,
+                              &rot_entry->last_modified, grfFlags,
+                              &rot_entry->cookie, &rot_entry->ctxt_handle);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            hr = HRESULT_FROM_WIN32(GetExceptionCode());
+        }
+        __ENDTRY
+        if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+        {
+            if (start_rpcss())
+                continue;
+        }
+        break;
+    }
+    HeapFree(GetProcessHeap(), 0, moniker);
+    if (FAILED(hr))
     {
         rot_entry_delete(rot_entry);
         return hr;
@@ -468,7 +576,6 @@ RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
     *pdwRegister = rot_entry->cookie;
 
     EnterCriticalSection(&This->lock);
-    /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */
     list_add_tail(&This->rot, &rot_entry->entry);
     LeaveCriticalSection(&This->lock);
 
@@ -516,9 +623,9 @@ static HRESULT WINAPI
 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
 {
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer *moniker_data;
+    MonikerComparisonData *moniker_data;
     HRESULT hr;
-    struct rot_entry *rot_entry;
+    const struct rot_entry *rot_entry;
 
     TRACE("(%p,%p)\n",This,pmkObjectName);
 
@@ -532,10 +639,10 @@ RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjec
 
     hr = S_FALSE;
     EnterCriticalSection(&This->lock);
-    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
+    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
     {
         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
-            !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
+            !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
         {
             hr = S_OK;
             break;
@@ -543,7 +650,27 @@ RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjec
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: call IrotIsRunning */
+    if (hr == S_FALSE)
+    {
+        while (TRUE)
+        {
+            __TRY
+            {
+                hr = IrotIsRunning(get_irot_handle(), moniker_data);
+            }
+            __EXCEPT(rpc_filter)
+            {
+                hr = HRESULT_FROM_WIN32(GetExceptionCode());
+            }
+            __ENDTRY
+            if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+            {
+                if (start_rpcss())
+                    continue;
+            }
+            break;
+        }
+    }
 
     HeapFree(GetProcessHeap(), 0, moniker_data);
 
@@ -562,7 +689,9 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
                      IMoniker *pmkObjectName, IUnknown **ppunkObject)
 {
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer *moniker_data;
+    MonikerComparisonData *moniker_data;
+    InterfaceData *object = NULL;
+    IrotCookie cookie;
     HRESULT hr;
     struct rot_entry *rot_entry;
 
@@ -585,7 +714,7 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
     {
         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
-            !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
+            !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
         {
             IStream *pStream;
             hr = create_stream_on_mip_ro(rot_entry->object, &pStream);
@@ -603,9 +732,39 @@ RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: call IrotGetObject */
-    WARN("Moniker unavailable - app may require interprocess running object table\n");
-    hr = MK_E_UNAVAILABLE;
+    TRACE("moniker unavailable locally, calling SCM\n");
+
+    while (TRUE)
+    {
+        __TRY
+        {
+            hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            hr = HRESULT_FROM_WIN32(GetExceptionCode());
+        }
+        __ENDTRY
+        if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+        {
+            if (start_rpcss())
+                continue;
+        }
+        break;
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        IStream *pStream;
+        hr = create_stream_on_mip_ro(object, &pStream);
+        if (hr == S_OK)
+        {
+            hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
+            IStream_Release(pStream);
+        }
+    }
+    else
+        WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr);
 
     HeapFree(GetProcessHeap(), 0, moniker_data);
 
@@ -625,6 +784,7 @@ RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
 {
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
     struct rot_entry *rot_entry;
+    HRESULT hr = E_INVALIDARG;
 
     TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime);
 
@@ -635,14 +795,34 @@ RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
         {
             rot_entry->last_modified = *pfiletime;
             LeaveCriticalSection(&This->lock);
-            return S_OK;
+
+            while (TRUE)
+            {
+                __TRY
+                {
+                    hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime);
+                }
+                __EXCEPT(rpc_filter)
+                {
+                    hr = HRESULT_FROM_WIN32(GetExceptionCode());
+                }
+                __ENDTRY
+                if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+                {
+                    if (start_rpcss())
+                        continue;
+                }
+                break;
+            }
+
+            goto done;
         }
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: call IrotNoteChangeTime */
-
-    return E_INVALIDARG;
+done:
+    TRACE("-- 0x08%x\n", hr);
+    return hr;
 }
 
 /***********************************************************************
@@ -658,8 +838,8 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
 {
     HRESULT hr = MK_E_UNAVAILABLE;
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer *moniker_data;
-    struct rot_entry *rot_entry;
+    MonikerComparisonData *moniker_data;
+    const struct rot_entry *rot_entry;
 
     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
 
@@ -677,10 +857,10 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
     hr = MK_E_UNAVAILABLE;
 
     EnterCriticalSection(&This->lock);
-    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
+    LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
     {
         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
-            !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
+            !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
         {
             *pfiletime = rot_entry->last_modified;
             hr = S_OK;
@@ -689,9 +869,31 @@ RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
     }
     LeaveCriticalSection(&This->lock);
 
-    /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */
+    if (hr != S_OK)
+    {
+        while (TRUE)
+        {
+            __TRY
+            {
+                hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime);
+            }
+            __EXCEPT(rpc_filter)
+            {
+                hr = HRESULT_FROM_WIN32(GetExceptionCode());
+            }
+            __ENDTRY
+            if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+            {
+                if (start_rpcss())
+                    continue;
+            }
+            break;
+        }
+    }
 
     HeapFree(GetProcessHeap(), 0, moniker_data);
+
+    TRACE("-- 0x%08x\n", hr);
     return hr;
 }
 
@@ -705,33 +907,36 @@ static HRESULT WINAPI
 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
                                    IEnumMoniker **ppenumMoniker)
 {
-    HRESULT hr;
     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
-    MInterfacePointer **monikers;
-    ULONG moniker_count = 0;
-    const struct rot_entry *rot_entry;
-    ULONG i = 0;
-
-    EnterCriticalSection(&This->lock);
+    InterfaceList *interface_list = NULL;
+    HRESULT hr;
 
-    LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
-        moniker_count++;
+    TRACE("(%p, %p)\n", This, ppenumMoniker);
 
-    monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers));
+    *ppenumMoniker = NULL;
 
-    LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
+    while (TRUE)
     {
-        SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]);
-        monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);
-        memcpy(monikers[i], rot_entry->moniker, size);
-        i++;
+        __TRY
+        {
+            hr = IrotEnumRunning(get_irot_handle(), &interface_list);
+        }
+        __EXCEPT(rpc_filter)
+        {
+            hr = HRESULT_FROM_WIN32(GetExceptionCode());
+        }
+        __ENDTRY
+        if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
+        {
+            if (start_rpcss())
+                continue;
+        }
+        break;
     }
 
-    LeaveCriticalSection(&This->lock);
-    
-    /* FIXME: call IrotEnumRunning and append data */
-
-    hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker);
+    if (SUCCEEDED(hr))
+        hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list,
+                                                  0, ppenumMoniker);
 
     return hr;
 }
@@ -767,9 +972,9 @@ HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
     /* initialize the virtual table function */
     runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
 
-    /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
-    /* the ROT referred many times not in the same time (all the objects in the ROT will  */
-    /* be removed every time the ROT is removed ) */
+    /* the initial reference is set to "1" so that it isn't destroyed after its
+     * first use until the process is destroyed, as the running object table is
+     * a process-wide cache of a global table */
     runningObjectTableInstance->ref = 1;
 
     list_init(&runningObjectTableInstance->rot);
@@ -873,6 +1078,21 @@ static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
         IParseDisplayName *pdn;
         hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
                                    &IID_IParseDisplayName, (void **)&pdn);
+        /* fallback to using IClassFactory to get IParseDisplayName -
+         * adsldp.dll depends on this */
+        if (FAILED(hr))
+        {
+            IClassFactory *pcf;
+            hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
+                                       &IID_IClassFactory, (void **)&pcf);
+            if (SUCCEEDED(hr))
+            {
+                hr = IClassFactory_CreateInstance(pcf, NULL,
+                                                  &IID_IParseDisplayName,
+                                                  (void **)&pdn);
+                IClassFactory_Release(pcf);
+            }
+        }
         IMoniker_Release(class_moniker);
         if (SUCCEEDED(hr))
         {
@@ -991,9 +1211,9 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
 
         return res;
     }
-    /* if the file is not a storage object then attemps to match various bits in the file against a
-       pattern in the registry. this case is not frequently used ! so I present only the psodocode for
-       this case
+    /* If the file is not a storage object then attempt to match various bits in the file against a
+       pattern in the registry. This case is not frequently used, so I present only the pseudocode for
+       this case.
 
      for(i=0;i<nFileTypes;i++)
 
@@ -1020,7 +1240,7 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
     nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
     absFile=pathDec[nbElm-1];
 
-    /* failed if the path represente a directory and not an absolute file name*/
+    /* failed if the path represents a directory and not an absolute file name*/
     if (!lstrcmpW(absFile, bkslashW))
         return MK_E_INVALIDEXTENSION;
 
@@ -1115,9 +1335,9 @@ static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
 
         TRACE("(%p) Deleting\n",This);
 
-        for (i = 0; i < This->moniker_count; i++)
-            HeapFree(GetProcessHeap(), 0, This->monikers[i]);
-        HeapFree(GetProcessHeap(), 0, This->monikers);
+        for (i = 0; i < This->moniker_list->size; i++)
+            HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]);
+        HeapFree(GetProcessHeap(), 0, This->moniker_list);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -1132,13 +1352,13 @@ static HRESULT   WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IM
     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
     HRESULT hr = S_OK;
 
-    TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_count);
+    TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size);
 
     /* retrieve the requested number of moniker from the current position */
-    for(i = 0; (This->pos < This->moniker_count) && (i < celt); i++)
+    for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
     {
         IStream *stream;
-        hr = create_stream_on_mip_ro(This->monikers[This->pos++], &stream);
+        hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
         if (hr != S_OK) break;
         hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
         IStream_Release(stream);
@@ -1167,7 +1387,7 @@ static HRESULT   WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
 
     TRACE("(%p)\n",This);
 
-    if  (This->pos + celt >= This->moniker_count)
+    if  (This->pos + celt >= This->moniker_list->size)
         return S_FALSE;
 
     This->pos += celt;
@@ -1195,21 +1415,35 @@ static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
 {
     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
-    MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count);
+    InterfaceList *moniker_list;
     ULONG i;
 
     TRACE("(%p)\n",This);
 
-    for (i = 0; i < This->moniker_count; i++)
+    *ppenum = NULL;
+
+    moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
+    if (!moniker_list)
+        return E_OUTOFMEMORY;
+
+    moniker_list->size = This->moniker_list->size;
+    for (i = 0; i < This->moniker_list->size; i++)
     {
-        SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]);
-        monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);
-        memcpy(monikers[i], This->monikers[i], size);
+        SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
+        moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size);
+        if (!moniker_list->interfaces[i])
+        {
+            ULONG end = i;
+            for (i = 0; i < end; i++)
+                HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]);
+            HeapFree(GetProcessHeap(), 0, moniker_list);
+            return E_OUTOFMEMORY;
+        }
+        memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
     }
 
     /* copy the enum structure */ 
-    return EnumMonikerImpl_CreateEnumROTMoniker(monikers, This->moniker_count,
-        This->pos, ppenum);
+    return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
 }
 
 /* Virtual function table for the IEnumMoniker class. */
@@ -1229,8 +1463,7 @@ static const IEnumMonikerVtbl VT_EnumMonikerImpl =
  *        Used by EnumRunning to create the structure and EnumClone
  *       to copy the structure
  */
-static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
-                                                 ULONG moniker_count,
+static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
                                                  ULONG current_pos,
                                                  IEnumMoniker **ppenumMoniker)
 {
@@ -1250,8 +1483,7 @@ static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **m
     /* the initial reference is set to "1" */
     This->ref = 1;                     /* set the ref count to one         */
     This->pos = current_pos;           /* Set the list start posn */
-    This->moniker_count = moniker_count; /* Need the same size table as ROT */
-    This->monikers = monikers;
+    This->moniker_list = moniker_list;
 
     *ppenumMoniker =  (IEnumMoniker*)This;
 
@@ -1427,3 +1659,13 @@ HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
     *outer = (IUnknown *)&This->lpVtbl;
     return S_OK;
 }
+
+void * __RPC_USER MIDL_user_allocate(size_t size)
+{
+    return HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+void __RPC_USER MIDL_user_free(void *p)
+{
+    HeapFree(GetProcessHeap(), 0, p);
+}
index 32335c1..207b0e0 100644 (file)
@@ -36,6 +36,7 @@ HRESULT AntiMonikerCF_Create(REFIID riid, LPVOID *ppv);
 HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv);
 HRESULT ClassMonikerCF_Create(REFIID riid, LPVOID *ppv);
 HRESULT PointerMonikerCF_Create(REFIID riid, LPVOID *ppv);
+HRESULT ComCatCF_Create(REFIID riid, LPVOID *ppv);
 
 /* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */
 int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable);
index 5cee7a1..bdbf6da 100644 (file)
@@ -1299,7 +1299,7 @@ static OleMenuHookItem * OLEMenu_IsHookInstalled( DWORD tid )
  */
 static BOOL OLEMenu_FindMainMenuIndex( HMENU hMainMenu, HMENU hPopupMenu, UINT *pnPos )
 {
-  UINT i, nItems;
+  INT i, nItems;
 
   nItems = GetMenuItemCount( hMainMenu );
 
index f42ddf9..b21601b 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     Copyright 1995  Martin von Loewis
  *      Copyright 1998  David Lee Lambert
- *      Copyright 2000  Julio César Gázquez
+ *      Copyright 2000  Julio César Gázquez
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
index e339651..7c45704 100644 (file)
@@ -119,3 +119,12 @@ HRESULT     WINAPI OleRegEnumFormatEtc (
 
     return E_NOTIMPL;
 }
+
+/***********************************************************************
+ *              CoGetCallerTID        [OLE32.@]
+ */
+HRESULT WINAPI CoGetCallerTID(LPDWORD lpdwTID)
+{
+  FIXME("stub!\n");
+  return E_NOTIMPL;
+}
index 275b9d0..9a430b0 100644 (file)
@@ -14,6 +14,7 @@
        <library>advapi32</library>
        <library>user32</library>
        <library>gdi32</library>
+       <library>ole32_irot_client</library>
        <library>ole32_proxy</library>
        <library>rpcrt4</library>
        <library>kernel32</library>
@@ -24,6 +25,7 @@
        <file>bindctx.c</file>
        <file>classmoniker.c</file>
        <file>clipboard.c</file>
+       <file>comcat.c</file>
        <file>compobj.c</file>
        <file>compositemoniker.c</file>
        <file>datacache.c</file>
index 7561156..e5e90b3 100644 (file)
@@ -22,7 +22,7 @@
 @ stdcall CoFreeUnusedLibraries()
 @ stdcall CoFreeUnusedLibrariesEx(long long)
 @ stdcall CoGetCallContext(ptr ptr)
-@ stub CoGetCallerTID
+@ stdcall CoGetCallerTID(ptr)
 @ stdcall CoGetClassObject(ptr long ptr ptr ptr)
 @ stdcall CoGetContextToken(ptr)
 @ stub CoGetCurrentLogicalThreadId
index 64f4441..99a86f0 100644 (file)
@@ -2,7 +2,7 @@
  *     OLE32 proxy/stub handler
  *
  *  Copyright 2002  Marcus Meissner
- *  Copyright 2001  Ove Kåven, TransGaming Technologies
+ *  Copyright 2001  Ove Kåven, TransGaming Technologies
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -40,6 +40,7 @@
 
 #include "compobj_private.h"
 #include "moniker.h"
+#include "comcat.h"
 
 #include "wine/debug.h"
 
@@ -88,6 +89,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
         return ClassMonikerCF_Create(iid, ppv);
     if (IsEqualCLSID(rclsid, &CLSID_PointerMoniker))
         return PointerMonikerCF_Create(iid, ppv);
+    if (IsEqualGUID(rclsid, &CLSID_StdComponentCategoriesMgr))
+        return ComCatCF_Create(iid, ppv);
 
     return NdrDllGetClassObject(rclsid, iid, ppv, OLE32_ProxyFileList,
                                 &CLSID_PSFactoryBuffer, &PSFactoryBuffer);
index e410931..07ddde0 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "ole2.h"
 #include "olectl.h"
+#include "comcat.h"
 #include "initguid.h"
 #include "compobj_private.h"
 #include "moniker.h"
@@ -406,6 +407,9 @@ static GUID const CLSID_StdOleLink = {
 static GUID const CLSID_PackagerMoniker = {
     0x00000308, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
 
+static GUID const CLSID_PSFactoryBuffer_actxprxy = {
+    0xB8DA6310, 0xE19B, 0x11D0, {0x93,0x3C,0x00,0xA0,0xC9,0x0D,0xCA,0xA9} };
+
 extern GUID const CLSID_Picture_Metafile;
 extern GUID const CLSID_Picture_Dib;
 
@@ -492,6 +496,12 @@ static struct regsvr_coclass const coclass_list[] = {
        "ole32.dll",
        "Apartment"
     },
+    {  &CLSID_StdComponentCategoriesMgr,
+       "Component Categories Manager",
+       NULL,
+       "ole32.dll",
+       "Both"
+    },
     { NULL }                   /* list terminator */
 };
 
@@ -502,6 +512,7 @@ static struct regsvr_coclass const coclass_list[] = {
 #define INTERFACE_ENTRY(interface, base, clsid32, clsid16) { &IID_##interface, #interface, base, sizeof(interface##Vtbl)/sizeof(void*), clsid16, clsid32 }
 #define BAS_INTERFACE_ENTRY(interface, base) INTERFACE_ENTRY(interface, &IID_##base, &CLSID_PSFactoryBuffer, NULL)
 #define STD_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer, NULL)
+#define ACTX_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer_actxprxy, NULL)
 #define LCL_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, NULL, NULL)
 
 static const struct regsvr_interface interface_list[] = {
@@ -561,6 +572,10 @@ static const struct regsvr_interface interface_list[] = {
     LCL_INTERFACE_ENTRY(IClientSecurity),
     LCL_INTERFACE_ENTRY(IServerSecurity),
     STD_INTERFACE_ENTRY(ISequentialStream),
+    ACTX_INTERFACE_ENTRY(IEnumGUID),
+    ACTX_INTERFACE_ENTRY(IEnumCATEGORYINFO),
+    ACTX_INTERFACE_ENTRY(ICatRegister),
+    ACTX_INTERFACE_ENTRY(ICatInformation),
     { NULL }                   /* list terminator */
 };
 
index b805dba..74d7968 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     RPC Manager
  *
- * Copyright 2001  Ove Kåven, TransGaming Technologies
+ * Copyright 2001  Ove Kåven, TransGaming Technologies
  * Copyright 2002  Marcus Meissner
  * Copyright 2005  Mike Hearn, Rob Shearman for CodeWeavers
  *
index 705585b..3c88a36 100644 (file)
@@ -1906,7 +1906,7 @@ static HRESULT WINAPI StorageImpl_Stat( IStorage* iface,
   StorageImpl* const This = (StorageImpl*)iface;
   HRESULT result = StorageBaseImpl_Stat( iface, pstatstg, grfStatFlag );
 
-  if ( !FAILED(result) && ((grfStatFlag & STATFLAG_NONAME) == 0) && This->pwcsName )
+  if ( SUCCEEDED(result) && ((grfStatFlag & STATFLAG_NONAME) == 0) && This->pwcsName )
   {
       CoTaskMemFree(pstatstg->pwcsName);
       pstatstg->pwcsName = CoTaskMemAlloc((lstrlenW(This->pwcsName)+1)*sizeof(WCHAR));
@@ -5895,7 +5895,7 @@ HRESULT WINAPI StgOpenStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD stgf
         return STG_E_INVALIDPARAMETER;
     }
 
-    return StgOpenStorage(pwcsName, NULL, grfMode, (SNB)NULL, 0, (IStorage **)ppObjectOpen); 
+    return StgOpenStorage(pwcsName, NULL, grfMode, NULL, 0, (IStorage **)ppObjectOpen);
 }
 
 
@@ -6335,13 +6335,13 @@ HRESULT  WINAPI OleLoadFromStream(IStream *pStm,REFIID iidInterface,void** ppvOb
     TRACE("(%p,%s,%p)\n",pStm,debugstr_guid(iidInterface),ppvObj);
 
     res=ReadClassStm(pStm,&clsid);
-    if (!SUCCEEDED(res))
+    if (FAILED(res))
        return res;
     res=CoCreateInstance(&clsid,NULL,CLSCTX_INPROC_SERVER,iidInterface,ppvObj);
-    if (!SUCCEEDED(res))
+    if (FAILED(res))
        return res;
     res=IUnknown_QueryInterface((IUnknown*)*ppvObj,&IID_IPersistStream,(LPVOID*)&xstm);
-    if (!SUCCEEDED(res)) {
+    if (FAILED(res)) {
        IUnknown_Release((IUnknown*)*ppvObj);
        return res;
     }
@@ -6583,7 +6583,7 @@ static HRESULT OLECONVERT_LoadOLE10(LPOLESTREAM pOleStream, OLECONVERT_OLESTREAM
        int max_try = 6;
 
        pData->pData = NULL;
-       pData->pstrOleObjFileName = (CHAR *) NULL;
+       pData->pstrOleObjFileName = NULL;
 
        for( nTryCnt=0;nTryCnt < max_try; nTryCnt++)
        {
index b8487c3..e504485 100644 (file)
@@ -2010,8 +2010,10 @@ HRESULT CALLBACK IEnumUnknown_Next_Proxy(
     IUnknown **rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumUnknown_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumUnknown_Next_Stub(
@@ -2020,8 +2022,12 @@ HRESULT __RPC_STUB IEnumUnknown_Next_Stub(
     IUnknown **rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    *pceltFetched = 0;
+    hr = IEnumUnknown_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 HRESULT CALLBACK IBindCtx_SetBindOptions_Proxy(
@@ -2062,8 +2068,10 @@ HRESULT CALLBACK IEnumMoniker_Next_Proxy(
     IMoniker **rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumMoniker_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumMoniker_Next_Stub(
@@ -2072,8 +2080,12 @@ HRESULT __RPC_STUB IEnumMoniker_Next_Stub(
     IMoniker **rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    *pceltFetched = 0;
+    hr = IEnumMoniker_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 BOOL CALLBACK IRunnableObject_IsRunning_Proxy(
@@ -2142,8 +2154,10 @@ HRESULT CALLBACK IEnumString_Next_Proxy(
     LPOLESTR *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumString_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumString_Next_Stub(
@@ -2152,8 +2166,12 @@ HRESULT __RPC_STUB IEnumString_Next_Stub(
     LPOLESTR *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    *pceltFetched = 0;
+    hr = IEnumString_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 HRESULT CALLBACK ISequentialStream_Read_Proxy(
@@ -2244,8 +2262,10 @@ HRESULT CALLBACK IEnumSTATSTG_Next_Proxy(
     STATSTG *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumSTATSTG_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumSTATSTG_Next_Stub(
@@ -2254,8 +2274,12 @@ HRESULT __RPC_STUB IEnumSTATSTG_Next_Stub(
     STATSTG *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    *pceltFetched = 0;
+    hr = IEnumSTATSTG_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 HRESULT CALLBACK IStorage_OpenStream_Proxy(
@@ -2398,8 +2422,9 @@ HRESULT CALLBACK IEnumFORMATETC_Next_Proxy(
     FORMATETC *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumFORMATETC_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumFORMATETC_Next_Stub(
@@ -2408,8 +2433,11 @@ HRESULT __RPC_STUB IEnumFORMATETC_Next_Stub(
     FORMATETC *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    *pceltFetched = 0;
+    hr = IEnumFORMATETC_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 HRESULT CALLBACK IEnumSTATDATA_Next_Proxy(
@@ -2418,8 +2446,10 @@ HRESULT CALLBACK IEnumSTATDATA_Next_Proxy(
     STATDATA *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumSTATDATA_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumSTATDATA_Next_Stub(
@@ -2428,8 +2458,12 @@ HRESULT __RPC_STUB IEnumSTATDATA_Next_Stub(
     STATDATA *rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    *pceltFetched = 0;
+    hr = IEnumSTATDATA_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 void CALLBACK IAdviseSink_OnDataChange_Proxy(
@@ -2642,8 +2676,10 @@ HRESULT CALLBACK IEnumOLEVERB_Next_Proxy(
     LPOLEVERB rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    ULONG fetched;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    if (!pceltFetched) pceltFetched = &fetched;
+    return IEnumOLEVERB_RemoteNext_Proxy(This, celt, rgelt, pceltFetched);
 }
 
 HRESULT __RPC_STUB IEnumOLEVERB_Next_Stub(
@@ -2652,8 +2688,12 @@ HRESULT __RPC_STUB IEnumOLEVERB_Next_Stub(
     LPOLEVERB rgelt,
     ULONG *pceltFetched)
 {
-    FIXME(":stub\n");
-    return E_NOTIMPL;
+    HRESULT hr;
+    TRACE("(%p)->(%d, %p, %p)\n", This, celt, rgelt, pceltFetched);
+    *pceltFetched = 0;
+    hr = IEnumOLEVERB_Next(This, celt, rgelt, pceltFetched);
+    if (hr == S_OK) *pceltFetched = celt;
+    return hr;
 }
 
 HRESULT CALLBACK IViewObject_Draw_Proxy(
index cd161c0..cb802ac 100644 (file)
@@ -41,9 +41,6 @@
        <include base="rpcrt4" root="intermediate">.</include>
        <file>rpcrt4.spec</file>
 </module>
-<module name="rpcrt4_epm_server" type="rpcserver">
-       <file>epm.idl</file>
-</module>
 <module name="rpcrt4_epm_client" type="rpcclient">
        <file>epm.idl</file>
 </module>