oleaut32/typelib.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



First set of fixes to typelib.c

1) Implement HELPDIR subkeys properly in RegisterTypeLib()

2) Implement UnRegisterTypeLib()

3) Fix various minor bugs I found in the other static functions.

The changes I've made come from reading MSDN, and have been compared with a 
real windows installation using a test program, and regmon etc from 
sysinternals.com. 
Index: dlls/oleaut32/typelib.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v
retrieving revision 1.107
diff -u -b -r1.107 typelib.c
--- dlls/oleaut32/typelib.c	10 Dec 2003 00:38:17 -0000	1.107
+++ dlls/oleaut32/typelib.c	11 Dec 2003 18:33:05 -0000
@@ -339,14 +339,14 @@
         switch(regkind)
         {
             case REGKIND_DEFAULT:
-                /* FIXME: is this correct? */
-                if (!szFile || !szFile[0] ||
-		   (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
-                    break;
+                /* don't register typelibs supplied with full path. Experimentation confirms the following */
+                if ((!szFile) ||
+                    ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
+                    (szFile[0] && (szFile[1] == ':'))) break;
                 /* else fall-through */
+
             case REGKIND_REGISTER:
-                /* FIXME: Help path? */
-                if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
+                if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
                 {
                     IUnknown_Release(*pptLib);
                     *pptLib = 0;
@@ -408,9 +408,11 @@
     OLECHAR guid[80];
     LPSTR guidA;
     CHAR keyName[120];
+    CHAR tmp[MAX_PATH];
     HKEY key, subKey;
     UINT types, tidx;
     TYPEKIND kind;
+    DWORD disposition;
     static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
 
     if (ptlib == NULL || szFullPath == NULL)
@@ -431,10 +433,11 @@
     {
         LPOLESTR doc;
 
+        /* Set the human-readable name of the typelib */
         if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
         {
             if (RegSetValueExW(key, NULL, 0, REG_SZ,
-                (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
+                (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
                 res = E_FAIL;
 
             SysFreeString(doc);
@@ -442,12 +445,29 @@
         else
             res = E_FAIL;
 
-        /* FIXME: This *seems* to be 0 always, not sure though */
-        if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
+        /* Make up the name of the typelib path subkey */
+        sprintf(tmp, "%u\\", (int) attr->lcid);
+        switch(attr->syskind) {
+        case SYS_WIN16:
+            strcat(tmp, "win16");
+            break;
+
+        case SYS_WIN32:
+            strcat(tmp, "win32");
+            break;
+
+        default:
+            TRACE("Typelib is for unsupported syskind %i\n", attr->syskind);
+            res = E_FAIL;
+            break;
+        }
+
+        /* Create the typelib path subkey */
+        if (res == S_OK && RegCreateKeyExA(key, tmp, 0, NULL, 0,
             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
         {
             if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
-                (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
+                (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
                 res = E_FAIL;
 
             RegCloseKey(subKey);
@@ -455,6 +475,7 @@
         else
             res = E_FAIL;
 
+        /* Create the flags subkey */
         if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
             KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
         {
@@ -464,7 +485,47 @@
             if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
                 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
                 res = E_FAIL;
+
+            RegCloseKey(subKey);
+        }
+        else
+            res = E_FAIL;
+
+        /* create the helpdir subkey */
+        if (res == S_OK && RegCreateKeyExA(key, "HELPDIR", 0, NULL, 0,
+            KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
+        {
+            BOOL freeHelpDir = FALSE;
+            OLECHAR* pIndexStr;
+
+            /* if we created a new key, and helpDir was null, set the helpdir
+               to the directory which contains the typelib. However,
+               if we just opened an existing key, we leave the helpdir alone */
+            if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
+                szHelpDir = SysAllocString(szFullPath);
+                pIndexStr = strrchrW(szHelpDir, '\\');
+                if (pIndexStr) {
+                    *pIndexStr = 0;
+                }
+                freeHelpDir = TRUE;
+            }
+
+            /* if we have an szHelpDir, set it! */
+            if (szHelpDir != NULL) {
+                if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
+                    (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
+                    res = E_FAIL;
+                }
+            }
+
+            /* tidy up */
+            if (freeHelpDir) SysFreeString(szHelpDir);
+            RegCloseKey(subKey);
+
+        } else {
+            res = E_FAIL;
         }
+
         RegCloseKey(key);
     }
     else
@@ -476,32 +537,34 @@
 	if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
 	    LPOLESTR name = NULL;
 	    ITypeInfo *tinfo = NULL;
-	    BOOL stop = FALSE;
+
 	    ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
+
 	    switch (kind) {
 	    case TKIND_INTERFACE:
 		TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
 		ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
 		break;
+
 	    case TKIND_DISPATCH:
 		TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
-		/* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
-		break;
-	    case TKIND_COCLASS:
-		TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
-		/* coclasses should probably not be registered? */
+                ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
 		break;
+
 	    default:
 		TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
 		break;
 	    }
+
 	    if (tinfo) {
 		TYPEATTR *tattr = NULL;
 		ITypeInfo_GetTypeAttr(tinfo, &tattr);
+
 		if (tattr) {
 		    TRACE_(typelib)("guid=%s, flags=%04x (",
 				    debugstr_guid(&tattr->guid),
 				    tattr->wTypeFlags);
+
 		    if (TRACE_ON(typelib)) {
 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
 			XX(FAPPOBJECT);
@@ -522,6 +585,7 @@
 #undef XX
 			MESSAGE("\n");
 		    }
+
 		    /*
 		     * FIXME: The 1 is just here until we implement rpcrt4
 		     *        stub/proxy handling. Until then it helps IShield
@@ -529,6 +593,10 @@
 		     */
 		    if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
 		    {
+                        if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
+                            FIXME("Registering non-oleautomation interface!\n");
+                        }
+
 			/* register interface<->typelib coupling */
 			StringFromGUID2(&tattr->guid, guid, 80);
 			guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
@@ -547,6 +615,7 @@
 					       PSOA, strlen(PSOA));
 				RegCloseKey(subKey);
 			    }
+
 			    if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
 				KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
 				RegSetValueExA(subKey, NULL, 0, REG_SZ,
@@ -566,15 +635,18 @@
 					       ver, lstrlenA(ver));
 				RegCloseKey(subKey);
 			    }
+
 			    RegCloseKey(key);
 			}
 		    }
+
 		    ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
 		}
+
 		ITypeInfo_Release(tinfo);
 	    }
+
 	    SysFreeString(name);
-	    if (stop) break;
 	}
     }
 
@@ -600,8 +672,155 @@
 	LCID lcid,	/* [in] locale id */
 	SYSKIND syskind)
 {
+    BSTR tlibPath = NULL;
+    DWORD tmpLength;
+    CHAR keyName[MAX_PATH];
+    CHAR* syskindName;
+    CHAR subKeyName[MAX_PATH];
+    LPSTR guidA;
+    int result = S_OK;
+    DWORD i = 0;
+    OLECHAR guid[80];
+    BOOL deleteOtherStuff;
+    HKEY key = NULL;
+    HKEY subKey = NULL;
+    TYPEATTR* typeAttr = NULL;
+    TYPEKIND kind;
+    ITypeInfo* typeInfo = NULL;
+    ITypeLib* typeLib = NULL;
+    int numTypes;
+
     TRACE("(IID: %s): stub\n",debugstr_guid(libid));
-    return S_OK;	/* FIXME: pretend everything is OK */
+
+    /* Create the path to the key */
+    StringFromGUID2(libid, guid, 80);
+    guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
+    snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
+        guidA, wVerMajor, wVerMinor);
+    HeapFree(GetProcessHeap(), 0, guidA);
+
+    /* Work out the syskind name */
+    switch(syskind) {
+    case SYS_WIN16:
+        syskindName = "win16";
+        break;
+
+    case SYS_WIN32:
+        syskindName = "win32";
+        break;
+
+    default:
+        TRACE("Unsupported syskind %i\n", syskind);
+        result = E_INVALIDARG;
+        goto end;
+    }
+
+    /* get the path to the typelib on disk */
+    if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
+        result = E_INVALIDARG;
+        goto end;
+    }
+
+    /* Try and open the key to the type library. */
+    if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
+        result = E_INVALIDARG;
+        goto end;
+    }
+
+    /* Try and load the type library */
+    if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
+        result = TYPE_E_INVALIDSTATE;
+        goto end;
+    }
+
+    /* remove any types registered with this typelib */
+    numTypes = ITypeLib_GetTypeInfoCount(typeLib);
+    for (i=0; i<numTypes; i++) {
+        /* get the kind of type */
+        if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
+            goto enddeleteloop;
+        }
+
+        /* skip non-interfaces, and get type info for the type */
+        if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
+            goto enddeleteloop;
+        }
+        if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
+            goto enddeleteloop;
+        }
+        if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
+            goto enddeleteloop;
+        }
+
+        /* the path to the type */
+        StringFromGUID2(&typeAttr->guid, guid, 80);
+        guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
+        snprintf(subKeyName, sizeof(subKeyName), "Interface\\%s", guidA);
+        HeapFree(GetProcessHeap(), 0, guidA);
+
+        /* Delete its bits */
+        if (RegOpenKeyExA(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
+            goto enddeleteloop;
+        }
+        RegDeleteKeyA(subKey, "ProxyStubClsid");
+        RegDeleteKeyA(subKey, "ProxyStubClsid32");
+        RegDeleteKeyA(subKey, "TypeLib");
+        RegCloseKey(subKey);
+        subKey = NULL;
+        RegDeleteKeyA(HKEY_CLASSES_ROOT, subKeyName);
+
+enddeleteloop:
+        if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
+        typeAttr = NULL;
+        if (typeInfo) ITypeInfo_Release(typeInfo);
+        typeInfo = NULL;
+    }
+
+    /* Now, delete the type library path subkey */
+    sprintf(subKeyName, "%u\\%s", (int) lcid, syskindName);
+    RegDeleteKeyA(key, subKeyName);
+    sprintf(subKeyName, "%u", (int) lcid);
+    RegDeleteKeyA(key, subKeyName);
+
+    /* check if there is anything besides the FLAGS/HELPDIR keys.
+       If there is, we don't delete them */
+    tmpLength = sizeof(subKeyName);
+    deleteOtherStuff = TRUE;
+    i = 0;
+    while(RegEnumKeyExA(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
+        tmpLength = sizeof(subKeyName);
+
+        /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
+        if (!strcmp(subKeyName, "FLAGS")) continue;
+        if (!strcmp(subKeyName, "HELPDIR")) continue;
+        deleteOtherStuff = FALSE;
+        break;
+    }
+
+    /* only delete the other parts of the key if we're absolutely sure */
+    if (deleteOtherStuff) {
+        RegDeleteKeyA(key, "FLAGS");
+        RegDeleteKeyA(key, "HELPDIR");
+        RegCloseKey(key);
+        key = NULL;
+
+        StringFromGUID2(libid, guid, 80);
+        guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
+        sprintf(keyName, "TypeLib\\%s\\%x.%x", guidA, wVerMajor, wVerMinor);
+        MESSAGE("mooo: %s\n", keyName);
+        RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
+        sprintf(keyName, "TypeLib\\%s", guidA);
+        MESSAGE("mooo: %s\n", keyName);
+        RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
+        HeapFree(GetProcessHeap(), 0, guidA);
+    }
+
+end:
+    if (tlibPath) SysFreeString(tlibPath);
+    if (typeLib) ITypeLib_Release(typeLib);
+    if (subKey) RegCloseKey(subKey);
+    if (key) RegCloseKey(key);
+    return result;
 }
 
 /*======================= ITypeLib implementation =======================*/

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux