From 7572fe233acf2a5b5e1267f57f61d8a1d852b88b Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Fri, 7 Nov 2008 11:00:30 +0000 Subject: [PATCH] - Sync ole32 to Wine-20081105 (matching rpcrt4 sync). Tested with two versions of FoxIt for bug #2361, it doesn't happen. Also tested with MS Office 2003 installation (which goes up to "Writing system registry values"). - Remove epm server building from rpcrt4, it belongs to rpcss. svn path=/trunk/; revision=37240 --- reactos/dll/win32/ole32/clipboard.c | 2 +- reactos/dll/win32/ole32/comcat.c | 1353 +++++++++++++++++++++ reactos/dll/win32/ole32/compobj.c | 33 +- reactos/dll/win32/ole32/compobj_private.h | 2 +- reactos/dll/win32/ole32/dcom.idl | 2 +- reactos/dll/win32/ole32/defaulthandler.c | 286 ++++- reactos/dll/win32/ole32/filemoniker.c | 16 +- reactos/dll/win32/ole32/moniker.c | 468 +++++-- reactos/dll/win32/ole32/moniker.h | 1 + reactos/dll/win32/ole32/ole2.c | 2 +- reactos/dll/win32/ole32/ole2nls.c | 2 +- reactos/dll/win32/ole32/ole2stubs.c | 9 + reactos/dll/win32/ole32/ole32.rbuild | 2 + reactos/dll/win32/ole32/ole32.spec | 2 +- reactos/dll/win32/ole32/oleproxy.c | 5 +- reactos/dll/win32/ole32/regsvr.c | 15 + reactos/dll/win32/ole32/rpc.c | 2 +- reactos/dll/win32/ole32/storage32.c | 12 +- reactos/dll/win32/ole32/usrmarshal.c | 96 +- reactos/dll/win32/rpcrt4/rpcrt4.rbuild | 3 - 20 files changed, 2084 insertions(+), 229 deletions(-) create mode 100644 reactos/dll/win32/ole32/comcat.c diff --git a/reactos/dll/win32/ole32/clipboard.c b/reactos/dll/win32/ole32/clipboard.c index 909b21547d2..0e9d55c4eca 100644 --- a/reactos/dll/win32/ole32/clipboard.c +++ b/reactos/dll/win32/ole32/clipboard.c @@ -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 index 00000000000..9120df09126 --- /dev/null +++ b/reactos/dll/win32/ole32/comcat.c @@ -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 +#include + +#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; +} diff --git a/reactos/dll/win32/ole32/compobj.c b/reactos/dll/win32/ole32/compobj.c index 69f42fcc997..37907eccca1 100644 --- a/reactos/dll/win32/ole32/compobj.c +++ b/reactos/dll/win32/ole32/compobj.c @@ -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" @@ -66,14 +63,12 @@ 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 diff --git a/reactos/dll/win32/ole32/compobj_private.h b/reactos/dll/win32/ole32/compobj_private.h index fbfe37c2b9c..81d591ea3fb 100644 --- a/reactos/dll/win32/ole32/compobj_private.h +++ b/reactos/dll/win32/ole32/compobj_private.h @@ -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 diff --git a/reactos/dll/win32/ole32/dcom.idl b/reactos/dll/win32/ole32/dcom.idl index d4abf43e721..a1c0dcd5689 100644 --- a/reactos/dll/win32/ole32/dcom.idl +++ b/reactos/dll/win32/ole32/dcom.idl @@ -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 diff --git a/reactos/dll/win32/ole32/defaulthandler.c b/reactos/dll/win32/ole32/defaulthandler.c index afacc510dd7..6844ee86b3a 100644 --- a/reactos/dll/win32/ole32/defaulthandler.c +++ b/reactos/dll/win32/ole32/defaulthandler.c @@ -64,6 +64,13 @@ 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; - return IPersistStorage_GetClassID(This->dataCache_PersistStg, clsid); + 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 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; - return IPersistStorage_IsDirty(This->dataCache_PersistStg); + 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); + + 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; - return IPersistStorage_InitNew(This->dataCache_PersistStg, pStg); + TRACE("(%p)->(%p)\n", iface, pStg); + init_ole_stream(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; - return IPersistStorage_Load(This->dataCache_PersistStg, pStg); + TRACE("(%p)->(%p)\n", iface, pStg); + + hr = load_ole_stream(This, 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; - return IPersistStorage_SaveCompleted(This->dataCache_PersistStg, pStgNew); + 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 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; - return IPersistStorage_HandsOffStorage(This->dataCache_PersistStg); + TRACE("(%p)\n", iface); + + hr = IPersistStorage_HandsOffStorage(This->dataCache_PersistStg); + + if(SUCCEEDED(hr) && object_is_running(This)) + hr = IPersistStorage_HandsOffStorage(This->pPSDelegate); + + 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; diff --git a/reactos/dll/win32/ole32/filemoniker.c b/reactos/dll/win32/ole32/filemoniker.c index 74c867a2a8e..3dae13970aa 100644 --- a/reactos/dll/win32/ole32/filemoniker.c +++ b/reactos/dll/win32/ole32/filemoniker.c @@ -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); diff --git a/reactos/dll/win32/ole32/moniker.c b/reactos/dll/win32/ole32/moniker.c index a4d2a5efc59..4e5646279b2 100644 --- a/reactos/dll/win32/ole32/moniker.c +++ b/reactos/dll/win32/ole32/moniker.c @@ -19,14 +19,11 @@ * 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 +#include "config.h" +#include "wine/port.h" + #include #include @@ -42,25 +39,33 @@ #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 HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream) +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 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,7 +170,33 @@ 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->cookie) + { + InterfaceData *object = NULL; + InterfaceData *moniker = NULL; + __TRY + { + 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->object) { IStream *stream; @@ -124,25 +208,13 @@ static inline void rot_entry_delete(struct rot_entry *rot_entry) IUnknown_Release(stream); } } - if (rot_entry->moniker) - { - IStream *stream; - HRESULT hr; - hr = create_stream_on_mip_ro(rot_entry->moniker, &stream); - if (hr == S_OK) - { - CoReleaseMarshalData(stream); - IUnknown_Release(stream); - } - } HeapFree(GetProcessHeap(), 0, rot_entry->object); - HeapFree(GetProcessHeap(), 0, rot_entry->moniker); HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data); HeapFree(GetProcessHeap(), 0, rot_entry); } /* moniker_data must be freed with HeapFree when no longer in use */ -static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data) +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; + InterfaceList *interface_list = NULL; + HRESULT hr; - EnterCriticalSection(&This->lock); + TRACE("(%p, %p)\n", This, ppenumMoniker); - LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry ) - moniker_count++; + *ppenumMoniker = NULL; - monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers)); - - 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;imoniker_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); +} diff --git a/reactos/dll/win32/ole32/moniker.h b/reactos/dll/win32/ole32/moniker.h index 32335c133a5..207b0e07491 100644 --- a/reactos/dll/win32/ole32/moniker.h +++ b/reactos/dll/win32/ole32/moniker.h @@ -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); diff --git a/reactos/dll/win32/ole32/ole2.c b/reactos/dll/win32/ole32/ole2.c index 5cee7a1e9fe..bdbf6da7861 100644 --- a/reactos/dll/win32/ole32/ole2.c +++ b/reactos/dll/win32/ole32/ole2.c @@ -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 ); diff --git a/reactos/dll/win32/ole32/ole2nls.c b/reactos/dll/win32/ole32/ole2nls.c index f42ddf9b92c..b21601b5390 100644 --- a/reactos/dll/win32/ole32/ole2nls.c +++ b/reactos/dll/win32/ole32/ole2nls.c @@ -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 diff --git a/reactos/dll/win32/ole32/ole2stubs.c b/reactos/dll/win32/ole32/ole2stubs.c index e3396516564..7c457047e57 100644 --- a/reactos/dll/win32/ole32/ole2stubs.c +++ b/reactos/dll/win32/ole32/ole2stubs.c @@ -119,3 +119,12 @@ HRESULT WINAPI OleRegEnumFormatEtc ( return E_NOTIMPL; } + +/*********************************************************************** + * CoGetCallerTID [OLE32.@] + */ +HRESULT WINAPI CoGetCallerTID(LPDWORD lpdwTID) +{ + FIXME("stub!\n"); + return E_NOTIMPL; +} diff --git a/reactos/dll/win32/ole32/ole32.rbuild b/reactos/dll/win32/ole32/ole32.rbuild index 275b9d0bdb0..9a430b09c19 100644 --- a/reactos/dll/win32/ole32/ole32.rbuild +++ b/reactos/dll/win32/ole32/ole32.rbuild @@ -14,6 +14,7 @@ advapi32 user32 gdi32 + ole32_irot_client ole32_proxy rpcrt4 kernel32 @@ -24,6 +25,7 @@ bindctx.c classmoniker.c clipboard.c + comcat.c compobj.c compositemoniker.c datacache.c diff --git a/reactos/dll/win32/ole32/ole32.spec b/reactos/dll/win32/ole32/ole32.spec index 7561156884c..e5e90b3e15c 100644 --- a/reactos/dll/win32/ole32/ole32.spec +++ b/reactos/dll/win32/ole32/ole32.spec @@ -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 diff --git a/reactos/dll/win32/ole32/oleproxy.c b/reactos/dll/win32/ole32/oleproxy.c index 64f4441a51a..99a86f009e3 100644 --- a/reactos/dll/win32/ole32/oleproxy.c +++ b/reactos/dll/win32/ole32/oleproxy.c @@ -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); diff --git a/reactos/dll/win32/ole32/regsvr.c b/reactos/dll/win32/ole32/regsvr.c index e4109317b12..07ddde01661 100644 --- a/reactos/dll/win32/ole32/regsvr.c +++ b/reactos/dll/win32/ole32/regsvr.c @@ -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 */ }; diff --git a/reactos/dll/win32/ole32/rpc.c b/reactos/dll/win32/ole32/rpc.c index b805dba656b..74d7968f3b4 100644 --- a/reactos/dll/win32/ole32/rpc.c +++ b/reactos/dll/win32/ole32/rpc.c @@ -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 * diff --git a/reactos/dll/win32/ole32/storage32.c b/reactos/dll/win32/ole32/storage32.c index 705585bd3d7..3c88a36f766 100644 --- a/reactos/dll/win32/ole32/storage32.c +++ b/reactos/dll/win32/ole32/storage32.c @@ -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++) { diff --git a/reactos/dll/win32/ole32/usrmarshal.c b/reactos/dll/win32/ole32/usrmarshal.c index b8487c30031..e504485cb08 100644 --- a/reactos/dll/win32/ole32/usrmarshal.c +++ b/reactos/dll/win32/ole32/usrmarshal.c @@ -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( diff --git a/reactos/dll/win32/rpcrt4/rpcrt4.rbuild b/reactos/dll/win32/rpcrt4/rpcrt4.rbuild index cd161c0e8a2..cb802ac9824 100644 --- a/reactos/dll/win32/rpcrt4/rpcrt4.rbuild +++ b/reactos/dll/win32/rpcrt4/rpcrt4.rbuild @@ -41,9 +41,6 @@ . rpcrt4.spec - - epm.idl - epm.idl