Implementation of InprocServer32 CoGetClassObject.
diff --git a/include/ole.h b/include/ole.h
index c21f067..dfaab17 100644
--- a/include/ole.h
+++ b/include/ole.h
@@ -27,6 +27,17 @@
#define OLESTR32(x) L##x /* probably wrong */
#define OLESTR WINELIB_NAME(OLESTR)
+typedef enum tagCLSCTX
+{
+ CLSCTX_INPROC_SERVER = 0x1,
+ CLSCTX_INPROC_HANDLER = 0x2,
+ CLSCTX_LOCAL_SERVER = 0x4,
+ CLSCTX_REMOTE_SERVER = 0x10,
+} CLSCTX;
+
+#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER)
+#define CLSCTX_ALL (CLSCTX_INPROC_HANDLER|CLSCTX_SERVER)
+
typedef unsigned short VARTYPE;
typedef LONG DISPID;
diff --git a/include/winerror.h b/include/winerror.h
index 309617c..429ba2c 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -169,4 +169,9 @@
/* Obtained from lcc-win32 include files */
#define GDI_ERROR 0xffffffff
+
+/* registry errors */
+#define REGDB_E_READREGDB 0x80040150
+#define REGDB_E_CLASSNOTREG 0x80040154
+
#endif /* __WINE_WINERROR_H */
diff --git a/ole/compobj.c b/ole/compobj.c
index 051290a..03f89d3 100644
--- a/ole/compobj.c
+++ b/ole/compobj.c
@@ -507,20 +507,93 @@
LPVOID pvReserved, REFIID iid, LPVOID *ppv)
{
char xclsid[50],xiid[50];
- LPCLASSFACTORY lpclf;
HRESULT hres = E_UNEXPECTED;
+ char dllName[MAX_PATH+1];
+ LONG dllNameLen = MAX_PATH+1;
+ HINSTANCE32 hLibrary;
+ typedef HRESULT (*DllGetClassObjectFunc)(REFCLSID clsid,
+ REFIID iid, LPVOID *ppv);
+ DllGetClassObjectFunc DllGetClassObject;
+
+ HKEY CLSIDkey;
+ char buf[MAX_PATH + 1];
+ int i;
+ int found;
WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
WINE_StringFromCLSID((LPCLSID)iid,xiid);
TRACE(ole,"\n\tCLSID:\t%s,\n\tIID:\t%s\n",xclsid,xiid);
- *ppv = NULL;
- lpclf = IClassFactory_Constructor();
- if (lpclf)
- {
- hres = lpclf->lpvtbl->fnQueryInterface(lpclf,iid, ppv);
- lpclf->lpvtbl->fnRelease(lpclf);
+ /* out of process and remote servers not supported yet */
+ if ((CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER) & dwClsContext) {
+ FIXME(ole, "CLSCTX_LOCAL_SERVER and CLSCTX_REMOTE_SERVER not supported!\n");
+ return E_ACCESSDENIED;
}
+
+ if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) {
+
+ /* lookup CLSID in registry key HKCR/CLSID */
+ hres = RegOpenKeyEx32A(HKEY_CLASSES_ROOT, "CLSID", 0,
+ KEY_ENUMERATE_SUB_KEYS, &CLSIDkey);
+
+ if (hres != ERROR_SUCCESS) {
+ return REGDB_E_READREGDB;
+ }
+
+ /* search all the subkeys for a match to xclsid */
+ found=FALSE;
+ for (i=0; i<100000; i++) {
+
+ char clsidKeyPath[MAX_PATH + 1];
+ HKEY key;
+ LONG res;
+
+ res = RegEnumKey32A(CLSIDkey, i, buf, MAX_PATH);
+ if (res == ERROR_NO_MORE_ITEMS)
+ break;
+ if (res != ERROR_SUCCESS)
+ continue;
+
+ sprintf(clsidKeyPath, "CLSID\\%s", buf);
+
+ if (lstrcmpi32A(buf, xclsid) != 0)
+ continue;
+
+ res = RegOpenKeyEx32A(HKEY_CLASSES_ROOT, clsidKeyPath, 0,
+ KEY_QUERY_VALUE, &key);
+ if (res != ERROR_SUCCESS) {
+ return REGDB_E_READREGDB;
+ }
+ hres = RegQueryValue32A(key, "InprocServer32", dllName, &dllNameLen);
+ if (res != ERROR_SUCCESS) {
+ return REGDB_E_READREGDB;
+ }
+ TRACE(ole,"found InprocServer32 dll %s\n", dllName);
+ found = TRUE;
+ break;
+ }
+
+ if (!found) {
+ return REGDB_E_CLASSNOTREG;
+ }
+
+ /* open dll, call DllGetClassFactory */
+ hLibrary = LoadLibrary32A(dllName);
+
+ if (hLibrary == 0) {
+ TRACE(ole,"couldn't load InprocServer32 dll %s\n", dllName);
+
+ return E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
+ }
+
+ DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress32(hLibrary, "DllGetClassObject");
+ if (DllGetClassObject == NULL) {
+ TRACE(ole,"couldn't find function DllGetClassObject in %s\n", dllName);
+ return E_ACCESSDENIED;
+ }
+ return DllGetClassObject(rclsid, iid, ppv);
+ }
+
return hres;
}
@@ -563,7 +636,8 @@
HRESULT hres;
LPCLASSFACTORY lpclf = 0;
- CoGetClassObject(rclsid, dwClsContext, NULL, &IID_IClassFactory, (LPVOID)&lpclf);
+ hres = CoGetClassObject(rclsid, dwClsContext, NULL, &IID_IClassFactory, (LPVOID)&lpclf);
+ if (!SUCCEEDED(hres)) return hres;
hres = lpclf->lpvtbl->fnCreateInstance(lpclf, pUnkOuter, iid, ppv);
lpclf->lpvtbl->fnRelease(lpclf);
return hres;