[PATCH] compobj.dll16: Implement CoGetClassObject().
Zebediah Figura
z.figura12 at gmail.com
Sat Feb 4 19:47:32 CST 2017
Fixes bug https://bugs.winehq.org/show_bug.cgi?id=41209
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/compobj.dll16/compobj.c | 242 +++++++++++++++++++++++++++++++---
dlls/compobj.dll16/compobj.dll16.spec | 2 +-
2 files changed, 222 insertions(+), 22 deletions(-)
diff --git a/dlls/compobj.dll16/compobj.c b/dlls/compobj.dll16/compobj.c
index b934a06..1b100c3 100644
--- a/dlls/compobj.dll16/compobj.c
+++ b/dlls/compobj.dll16/compobj.c
@@ -30,6 +30,8 @@
#include <string.h>
#include <assert.h>
+#define COBJMACROS
+
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
@@ -42,6 +44,7 @@
#include "wtypes.h"
#include "wine/unicode.h"
#include "wine/winbase16.h"
+#include "wine/list.h"
#include "wine/debug.h"
@@ -98,6 +101,115 @@ static inline IMalloc16Impl *impl_from_IMalloc16(IMalloc16 *iface)
return CONTAINING_RECORD(iface, IMalloc16Impl, IMalloc16_iface);
}
+typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
+typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
+
+typedef struct tagOpenDll
+{
+ LONG refs;
+ LPSTR library_name;
+ HMODULE16 library;
+ DllGetClassObjectFunc DllGetClassObject;
+ DllCanUnloadNowFunc DllCanUnloadNow;
+ struct list entry;
+} OpenDll;
+
+static struct list openDllList = LIST_INIT(openDllList);
+
+/*****************************************************************************
+ * This section contains OpenDllList implementation
+ */
+
+static OpenDll *COMPOBJ16_DllList_Get(LPCSTR library_name)
+{
+ OpenDll *ptr;
+ LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry)
+ {
+ if (!strcasecmp(library_name, ptr->library_name) &&
+ ++(ptr->refs) != 1) /* entry is being destroy if == 1 */
+ return ptr;
+ }
+
+ return NULL;
+}
+
+static HRESULT COMPOBJ16_DllList_Add(LPCSTR library_name, OpenDll **ret)
+{
+ OpenDll *entry;
+ int len;
+ HRESULT hr = S_OK;
+ HMODULE16 hLibrary;
+ DllCanUnloadNowFunc DllCanUnloadNow;
+ DllGetClassObjectFunc DllGetClassObject;
+
+ *ret = COMPOBJ16_DllList_Get(library_name);
+ if (*ret)
+ {
+ TRACE("found %s already loaded\n", debugstr_a(library_name));
+ return S_OK;
+ }
+
+ hLibrary = LoadLibrary16(library_name);
+ if (!hLibrary)
+ {
+ ERR("couldn't load in-process dll %s\n", debugstr_a(library_name));
+ /* failure: DLL could not be loaded */
+ return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
+ }
+
+ DllCanUnloadNow = (void *)GetProcAddress16(hLibrary, "DllCanUnloadNow");
+ /* Note: failing to find DllCanUnloadNow is not a failure */
+ DllGetClassObject = (void *)GetProcAddress16(hLibrary, "DllGetClassObject");
+ if (!DllGetClassObject)
+ {
+ /* failure: the dll did not export DllGetClassObject */
+ ERR("couldn't find function DllGetClassObject in %s\n", debugstr_a(library_name));
+ FreeLibrary16(hLibrary);
+ return CO_E_DLLNOTFOUND;
+ }
+
+ len = strlen(library_name);
+ entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
+ if (entry)
+ entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(char));
+ if (entry && entry->library_name)
+ {
+ memcpy(entry->library_name, library_name, (len + 1)*sizeof(char));
+ entry->library = hLibrary;
+ entry->refs = 1;
+ entry->DllCanUnloadNow = DllCanUnloadNow;
+ entry->DllGetClassObject = DllGetClassObject;
+ list_add_tail(&openDllList, &entry->entry);
+ *ret = entry;
+
+ TRACE("added new loaded dll %s\n", debugstr_a(library_name));
+ }
+ else
+ {
+ HeapFree(GetProcessHeap(), 0, entry);
+ hr = E_OUTOFMEMORY;
+ FreeLibrary16(hLibrary);
+ }
+
+ return hr;
+}
+
+/* pass FALSE for free_entry to release a reference without destroying the
+ * entry if it reaches zero or TRUE otherwise */
+static void COMPOBJ16_DllList_ReleaseRef(OpenDll *entry)
+{
+ if (--(entry->refs) == 0)
+ {
+ list_remove(&entry->entry);
+
+ TRACE("freeing %x\n", entry->library);
+ FreeLibrary16(entry->library);
+
+ HeapFree(GetProcessHeap(), 0, entry->library_name);
+ HeapFree(GetProcessHeap(), 0, entry);
+ }
+}
+
/******************************************************************************
* IMalloc16_QueryInterface [COMPOBJ.500]
*/
@@ -279,13 +391,34 @@ HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext,
return S_OK;
}
+/***********************************************************************
+ * CoFreeAllLibraries [COMPOBJ.12]
+ */
+void WINAPI CoFreeAllLibraries16(void)
+{
+ OpenDll *entry, *next;
+
+ TRACE("()\n");
+ LIST_FOR_EACH_ENTRY_SAFE(entry, next, &openDllList, OpenDll, entry)
+ {
+ list_remove(&entry->entry);
+
+ TRACE("freeing %x\n", entry->library);
+ FreeLibrary16(entry->library);
+
+ HeapFree(GetProcessHeap(), 0, entry->library_name);
+ HeapFree(GetProcessHeap(), 0, entry);
+ }
+}
+
/******************************************************************************
- * CoInitialize [COMPOBJ.2]
+ * CoInitialize [COMPOBJ.2]
* Set the win16 IMalloc used for memory management
*/
HRESULT WINAPI CoInitialize16(
- LPVOID lpReserved /* [in] pointer to win16 malloc interface */
-) {
+ LPVOID lpReserved) /* [in] pointer to win16 malloc interface */
+{
+ TRACE("()\n");
currentMalloc16 = (LPMALLOC16)lpReserved;
return S_OK;
}
@@ -298,8 +431,8 @@ HRESULT WINAPI CoInitialize16(
*/
void WINAPI CoUninitialize16(void)
{
- TRACE("()\n");
- CoFreeAllLibraries();
+ TRACE("()\n");
+ CoFreeAllLibraries16();
}
/***********************************************************************
@@ -307,7 +440,18 @@ void WINAPI CoUninitialize16(void)
*/
void WINAPI CoFreeUnusedLibraries16(void)
{
- CoFreeUnusedLibraries();
+ OpenDll *entry, *next;
+
+ TRACE("()\n");
+ LIST_FOR_EACH_ENTRY_SAFE(entry, next, &openDllList, OpenDll, entry)
+ {
+ if (entry->DllCanUnloadNow &&
+ WOWCallback16Ex((DWORD)entry->DllCanUnloadNow, WCB16_PASCAL, 0, NULL, NULL))
+ {
+ list_remove(&entry->entry);
+ COMPOBJ16_DllList_ReleaseRef(entry);
+ }
+ }
}
/***********************************************************************
@@ -715,14 +859,65 @@ HRESULT WINAPI CoFileTimeNow16( FILETIME *lpFileTime )
*/
HRESULT WINAPI CoGetClassObject16(
REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
- REFIID iid, LPVOID *ppv)
+ REFIID riid, LPVOID *ppv)
{
- FIXME(", stub!\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid));
+ HRESULT hres = E_UNEXPECTED;
+
+ TRACE("CLSID: %s,IID: %s\n", debugstr_guid(rclsid), debugstr_guid(riid));
+
+ *ppv = NULL;
if (pServerInfo) {
- FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName));
- FIXME("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo);
+ FIXME("pServerInfo->name=%s pAuthInfo=%p\n",
+ debugstr_w(pServerInfo->pwszName), pServerInfo->pAuthInfo);
}
+
+ if (CLSCTX_INPROC_SERVER & dwClsContext)
+ {
+ char idstr[CHARS_IN_GUID];
+ char buf_key[CHARS_IN_GUID+19], dllpath[MAX_PATH+1];
+ LONG dllpath_len = sizeof(dllpath);
+ OpenDll *dll;
+ SEGPTR seg_rclsid = MapLS(rclsid);
+ SEGPTR seg_riid = MapLS(riid);
+ SEGPTR seg_ppv = MapLS(ppv);
+ WORD args[6];
+ DWORD dwRet;
+
+ hres = StringFromGUID216(rclsid, idstr, CHARS_IN_GUID);
+ sprintf(buf_key, "CLSID\\%s\\InprocServer", idstr);
+ if (RegQueryValueA(HKEY_CLASSES_ROOT, buf_key, dllpath, &dllpath_len))
+ {
+ ERR("class %s not registered\n", debugstr_guid(rclsid));
+ return REGDB_E_CLASSNOTREG;
+ }
+
+ hres = COMPOBJ16_DllList_Add(dllpath, &dll);
+ if (FAILED(hres))
+ return hres;
+
+ TRACE("calling DllGetClassObject %p\n", dll->DllGetClassObject);
+ args[5] = SELECTOROF(seg_rclsid);
+ args[4] = OFFSETOF(seg_rclsid);
+ args[3] = SELECTOROF(seg_riid);
+ args[2] = OFFSETOF(seg_riid);
+ args[1] = SELECTOROF(seg_ppv);
+ args[0] = OFFSETOF(seg_ppv);
+ WOWCallback16Ex((DWORD)dll->DllGetClassObject, WCB16_PASCAL, sizeof(args), args, &dwRet);
+ if (dwRet != S_OK)
+ {
+ ERR("DllGetClassObject returned error 0x%08x\n", dwRet);
+ return dwRet;
+ }
+
+ UnMapLS(seg_rclsid);
+ UnMapLS(seg_riid);
+ UnMapLS(seg_ppv);
+
+ return S_OK;
+ }
+
+ FIXME("semi-stub\n");
return E_NOTIMPL;
}
@@ -738,17 +933,22 @@ HRESULT WINAPI CoCreateGuid16(GUID *pguid)
* CoCreateInstance [COMPOBJ.13]
*/
HRESULT WINAPI CoCreateInstance16(
- REFCLSID rclsid,
- LPUNKNOWN pUnkOuter,
- DWORD dwClsContext,
- REFIID iid,
- LPVOID *ppv)
-{
- FIXME("(%s, %p, %x, %s, %p), stub!\n",
- debugstr_guid(rclsid), pUnkOuter, dwClsContext, debugstr_guid(iid),
- ppv
- );
- return E_NOTIMPL;
+ REFCLSID rclsid,
+ LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext,
+ REFIID riid,
+ LPVOID *ppv)
+{
+ IClassFactory *cf;
+ HRESULT hres;
+
+ hres = CoGetClassObject16(rclsid, dwClsContext, NULL, &IID_IClassFactory, (void **)&cf);
+ if (FAILED(hres))
+ return hres;
+
+ hres = IClassFactory_CreateInstance(cf, pUnkOuter, riid, ppv);
+ IClassFactory_Release(cf);
+ return hres;
}
/***********************************************************************
diff --git a/dlls/compobj.dll16/compobj.dll16.spec b/dlls/compobj.dll16/compobj.dll16.spec
index 85dfc42..2c23f2d 100644
--- a/dlls/compobj.dll16/compobj.dll16.spec
+++ b/dlls/compobj.dll16/compobj.dll16.spec
@@ -9,7 +9,7 @@
9 stub COUNMARSHALINTERFACE
10 stub COLOADLIBRARY
11 stub COFREELIBRARY
-12 stub COFREEALLLIBRARIES
+12 pascal CoFreeAllLibraries() CoFreeAllLibraries16
13 pascal CoCreateInstance(ptr ptr long ptr ptr) CoCreateInstance16
14 stub STRINGFROMIID
15 pascal CoDisconnectObject(ptr long) CoDisconnectObject16
--
2.7.4
More information about the wine-patches
mailing list