]> git.sesse.net Git - vlc/blobdiff - activex/main.cpp
Better a compile warning than a bug. Thanks to Robert Stepanek.
[vlc] / activex / main.cpp
index 4cc9084d1f6a7e760f2e40963f831ca91ddade88..f40854ad4cf1b2ad95c0a146aca8f048ca12cc9f 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * main.cpp: ActiveX control for VLC
  *****************************************************************************
- * Copyright (C) 2005 VideoLAN
+ * Copyright (C) 2005 the VideoLAN team
  *
  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
  *
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #include "plugin.h"
+#include "utils.h"
+
+#include <stdio.h>
 
 #include <comcat.h>
 #include <windows.h>
 #include <shlwapi.h>
 
+#include <guiddef.h>
+
 using namespace std;
 
 #define COMPANY_STR "VideoLAN"
 #define PROGRAM_STR "VLCPlugin"
-#define VERSION_MAJOR_STR "1"
-#define VERSION_MINOR_STR "0"
 #define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
 
 #define THREADING_MODEL "Apartment"
 #define MISC_STATUS     "131473"
 
 #define PROGID_STR COMPANY_STR"."PROGRAM_STR
-#define VERS_PROGID_STR COMPANY_STR"."PROGRAM_STR"."VERSION_MAJOR_STR
-#define VERSION_STR VERSION_MAJOR_STR"."VERSION_MINOR_STR
 
 #define GUID_STRLEN 39
 
 /*
-** MingW headers do not declare those
+** MingW headers & libs do not declare those
 */
-extern const CATID CATID_SafeForInitializing;
-extern const CATID CATID_SafeForScripting;
+static DEFINE_GUID(_CATID_InternetAware,       0x0DE86A58, 0x2BAA, 0x11CF, 0xA2, 0x29, 0x00,0xAA,0x00,0x3D,0x73,0x52);
+static DEFINE_GUID(_CATID_SafeForInitializing, 0x7DD95802, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
+static DEFINE_GUID(_CATID_SafeForScripting,    0x7DD95801, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
 
 static LONG i_class_ref= 0;
 static HINSTANCE h_instance= 0;
 
+HMODULE DllGetModule()
+{
+    return h_instance;
+};
+
 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
 {
     HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
 
     *ppv = NULL;
 
-    if( CLSID_VLCPlugin == rclsid )
+    if( (CLSID_VLCPlugin == rclsid )
+     || ( CLSID_VLCPlugin2 == rclsid) )
     {
-        VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);
+        VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
         hr = plugin->QueryInterface(riid, ppv);
         plugin->Release();
     }
@@ -72,48 +80,67 @@ STDAPI DllCanUnloadNow(VOID)
     return (0 == i_class_ref) ? S_OK: S_FALSE;
 };
 
-static LPCTSTR TStrFromGUID(REFGUID clsid)
+static inline HKEY keyCreate(HKEY parentKey, LPCSTR keyName)
 {
-    LPOLESTR oleStr;
-
-    if( FAILED(StringFromIID(clsid, &oleStr)) )
-        return NULL;
-
-    //check whether TCHAR and OLECHAR are both either ANSI or UNICODE
-    if( sizeof(TCHAR) == sizeof(OLECHAR) )
-        return (LPCTSTR)oleStr;
-
-    LPTSTR pct_CLSID = NULL;
-#ifndef OLE2ANSI
-    size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);
-    if( len > 0 )
+    HKEY childKey;
+    if( ERROR_SUCCESS == RegCreateKeyExA(parentKey, keyName, 0, NULL,
+                REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
     {
-        pct_CLSID = (char *)CoTaskMemAlloc(len);
-        WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);
+        return childKey;
     }
-#else
-    size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);
-    if( len > 0 )
+    return NULL;
+};
+
+static inline HKEY keySet(HKEY hKey, LPCSTR valueName, const void *s, size_t len)
+{
+    if( NULL != hKey )
     {
-        clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));
-        WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len);
+        RegSetValueExA(hKey, valueName, 0, REG_SZ,
+            (const BYTE*)s, len);
     }
-#endif
-    CoTaskMemFree(oleStr);
-    return pct_CLSID;
+    return hKey;
 };
 
-static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
+static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len)
 {
-    HKEY childKey;
-    if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
-                REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
+    return keySet(hKey, NULL, s, len);
+};
+
+static inline HKEY keySetDef(HKEY hKey, LPCSTR s)
+{
+    return keySetDef(hKey, s, strlen(s)+1);
+};
+
+static inline HKEY keyClose(HKEY hKey)
+{
+    if( NULL != hKey )
     {
-        return childKey;
+        RegCloseKey(hKey);
     }
     return NULL;
 };
 
+static HRESULT UnregisterProgID(REFCLSID rclsid, unsigned int version)
+{
+    LPCSTR psz_CLSID = CStrFromGUID(rclsid);
+
+    if( NULL == psz_CLSID )
+        return E_OUTOFMEMORY;
+
+    char progId[sizeof(PROGID_STR)+16];
+    sprintf(progId, "%s.%u", PROGID_STR, version);
+
+    SHDeleteKeyA(HKEY_CLASSES_ROOT, progId);
+
+    HKEY hClsIDKey;
+    if( ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_WRITE, &hClsIDKey) )
+    {
+        SHDeleteKey(hClsIDKey, psz_CLSID);
+        RegCloseKey(hClsIDKey);
+    }
+    CoTaskMemFree((void *)psz_CLSID);
+};
+
 STDAPI DllUnregisterServer(VOID)
 {
     // unregister type lib from the registry
@@ -126,168 +153,167 @@ STDAPI DllUnregisterServer(VOID)
         CATID implCategories[] = {
             CATID_Control,
             CATID_PersistsToPropertyBag,
-            CATID_SafeForInitializing,
-            CATID_SafeForScripting,
+            _CATID_InternetAware,
+            _CATID_SafeForInitializing,
+            _CATID_SafeForScripting,
         };
 
         pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,
                 sizeof(implCategories)/sizeof(CATID), implCategories);
+        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
+                sizeof(implCategories)/sizeof(CATID), implCategories);
         pcr->Release();
     }
 
-    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
     SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
 
-    LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
-
-    if( NULL == psz_CLSID )
-        return E_OUTOFMEMORY;
-
-    HKEY hClsIDKey;
-    if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
-    {
-        SHDeleteKey(hClsIDKey, psz_CLSID);
-        RegCloseKey(hClsIDKey);
-    }
-    CoTaskMemFree((void *)psz_CLSID);
+    UnregisterProgID(CLSID_VLCPlugin, 2);
+    UnregisterProgID(CLSID_VLCPlugin2, 1);
 
     return S_OK;
 };
 
-STDAPI DllRegisterServer(VOID)
+static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, const char *path, size_t pathLen)
 {
-    DllUnregisterServer();
+    char progId[sizeof(PROGID_STR)+16];
+    sprintf(progId, "%s.%u", PROGID_STR, version);
 
-    char DllPath[MAX_PATH];
-    DWORD DllPathLen= GetModuleFileName(h_instance, DllPath, sizeof(DllPath)) ;
-       if( 0 == DllPathLen )
-        return E_UNEXPECTED;
+    char description[sizeof(DESCRIPTION)+16];
+    sprintf(description, "%s v%u", DESCRIPTION, version);
 
-    LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);
+    HKEY hClassKey;
+    {
+        LPCSTR psz_CLSID = CStrFromGUID(rclsid);
 
-    if( NULL == psz_CLSID )
-        return E_OUTOFMEMORY;
+        if( NULL == psz_CLSID )
+            return E_OUTOFMEMORY;
 
-    HKEY hBaseKey;
+        HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
+        if( NULL != hProgKey )
+        {
+            // default key value
+            keySetDef(hProgKey, description);
 
-    if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
-        return SELFREG_E_CLASS;
+            keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
+                psz_CLSID,
+                GUID_STRLEN));
 
-    HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);
+            //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
+            RegCloseKey(hProgKey);
+        }
+        if( isDefault )
+        {
+            hProgKey = keyCreate(HKEY_CLASSES_ROOT, PROGID_STR);
+            if( NULL != hProgKey )
+            {
+                // default key value
+                keySetDef(hProgKey, description);
+
+                keyClose(keySetDef(keyCreate(hProgKey, "CLSID"),
+                    psz_CLSID,
+                    GUID_STRLEN));
+
+                keyClose(keySetDef(keyCreate(hProgKey, "CurVer"),
+                    progId));
+            }
+        }
+        hClassKey = keyCreate(hParent, psz_CLSID);
+        CoTaskMemFree((void *)psz_CLSID);
+    }
     if( NULL != hClassKey )
     {
-        HKEY hSubKey;
-
         // default key value
-        RegSetValueEx(hClassKey, NULL, 0, REG_SZ,
-                (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
+        keySetDef(hClassKey, description);
 
         // Control key value
-        hSubKey = keyCreate(hClassKey, TEXT("Control"));
-        RegCloseKey(hSubKey);
+        keyClose(keyCreate(hClassKey, "Control"));
+
+        // Insertable key value
+        //keyClose(keyCreate(hClassKey, "Insertable"));
+
+        // ToolboxBitmap32 key value
+        {
+            char iconPath[pathLen+3];
+            memcpy(iconPath, path, pathLen);
+            strcpy(iconPath+pathLen, ",1");
+            keyClose(keySetDef(keyCreate(hClassKey,
+                "ToolboxBitmap32"),
+                iconPath, sizeof(iconPath)));
+        }
 
 #ifdef BUILD_LOCALSERVER
         // LocalServer32 key value
-        hSubKey = keyCreate(hClassKey, TEXT("LocalServer32"));
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                (const BYTE*)DllPath, DllPathLen);
-        RegCloseKey(hSubKey);
+        keyClose(keySetDef(keyCreate(hClassKey,
+            "LocalServer32", path, pathLen+1)));
 #else
         // InprocServer32 key value
-        hSubKey = keyCreate(hClassKey, TEXT("InprocServer32"));
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                (const BYTE*)DllPath, DllPathLen);
-        RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,
-                (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));
-        RegCloseKey(hSubKey);
+        {
+            HKEY hSubKey = keySetDef(keyCreate(hClassKey,
+                "InprocServer32"),
+                path, pathLen+1);
+            keySet(hSubKey,
+                "ThreadingModel",
+                THREADING_MODEL, sizeof(THREADING_MODEL));
+            keyClose(hSubKey);
+        }
 #endif
 
         // MiscStatus key value
-        hSubKey = keyCreate(hClassKey, TEXT("MiscStatus\\1"));
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (const BYTE*)MISC_STATUS, sizeof(MISC_STATUS));
-        RegCloseKey(hSubKey);
+        keyClose(keySetDef(keyCreate(hClassKey,
+            "MiscStatus\\1"),
+            MISC_STATUS, sizeof(MISC_STATUS)));
 
         // Programmable key value
-        hSubKey = keyCreate(hClassKey, TEXT("Programmable"));
-        RegCloseKey(hSubKey);
+        keyClose(keyCreate(hClassKey, "Programmable"));
 
         // ProgID key value
-        hSubKey = keyCreate(hClassKey, TEXT("ProgID"));
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ, 
-                (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
-        RegCloseKey(hSubKey);
+        keyClose(keySetDef(keyCreate(hClassKey,
+            TEXT("ProgID")),
+            progId));
 
         // VersionIndependentProgID key value
-        hSubKey = keyCreate(hClassKey, TEXT("VersionIndependentProgID"));
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ, 
-                (const BYTE*)PROGID_STR, sizeof(PROGID_STR));
-        RegCloseKey(hSubKey);
+        keyClose(keySetDef(keyCreate(hClassKey,
+            "VersionIndependentProgID"),
+            PROGID_STR, sizeof(PROGID_STR)));
 
         // Version key value
-        hSubKey = keyCreate(hClassKey, TEXT("Version"));
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                (const BYTE*)VERSION_STR, sizeof(VERSION_STR));
-        RegCloseKey(hSubKey);
+        keyClose(keySetDef(keyCreate(hClassKey,
+            "Version"),
+            "1.0"));
 
         // TypeLib key value
-        LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);
+        LPCSTR psz_LIBID = CStrFromGUID(LIBID_AXVLC);
         if( NULL != psz_LIBID )
         {
-            hSubKey = keyCreate(hClassKey, TEXT("TypeLib"));
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                    (const BYTE*)psz_LIBID, sizeof(TCHAR)*GUID_STRLEN);
-            RegCloseKey(hSubKey);
+            keyClose(keySetDef(keyCreate(hClassKey,
+                    "TypeLib"),
+                    psz_LIBID, GUID_STRLEN));
+            CoTaskMemFree((void *)psz_LIBID);
         }
         RegCloseKey(hClassKey);
     }
-    RegCloseKey(hBaseKey);
-
-    hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
-    if( NULL != hBaseKey )
-    {
-        // default key value
-        RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
-                (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
+    return S_OK;
+}
 
-        HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
-        if( NULL != hSubKey )
-        {
-            // default key value
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                    (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
+STDAPI DllRegisterServer(VOID)
+{
+    DllUnregisterServer();
 
-            RegCloseKey(hSubKey);
-        }
-        hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));
-        if( NULL != hSubKey )
-        {
-            // default key value
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                    (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));
+    char DllPath[MAX_PATH];
+    DWORD DllPathLen=GetModuleFileNameA(h_instance, DllPath, sizeof(DllPath)) ;
+    if( 0 == DllPathLen )
+        return E_UNEXPECTED;
 
-            RegCloseKey(hSubKey);
-        }
-        RegCloseKey(hBaseKey);
-    }
+    HKEY hBaseKey;
 
-    hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));
-    if( NULL != hBaseKey )
-    {
-        // default key value
-        RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,
-                (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));
+    if( ERROR_SUCCESS != RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
+        return SELFREG_E_CLASS;
 
-        HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));
-        if( NULL != hSubKey )
-        {
-            // default key value
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,
-                    (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);
+    RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
+    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
 
-            RegCloseKey(hSubKey);
-        }
-        RegCloseKey(hBaseKey);
-    }
+    RegCloseKey(hBaseKey);
 
     // indicate which component categories we support
     ICatRegister *pcr;
@@ -296,17 +322,26 @@ STDAPI DllRegisterServer(VOID)
         CATID implCategories[] = {
             CATID_Control,
             CATID_PersistsToPropertyBag,
-            CATID_SafeForInitializing,
-            CATID_SafeForScripting,
+            _CATID_InternetAware,
+            _CATID_SafeForInitializing,
+            _CATID_SafeForScripting,
         };
 
         pcr->RegisterClassImplCategories(CLSID_VLCPlugin,
                 sizeof(implCategories)/sizeof(CATID), implCategories);
+        pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
+                sizeof(implCategories)/sizeof(CATID), implCategories);
         pcr->Release();
     }
 
     // register type lib into the registry
     ITypeLib *typeLib;
+
+#ifdef BUILD_LOCALSERVER
+    // replace .exe by .tlb
+    strcpy(DllPath+DllPathLen-4, ".tlb");
+#endif
+
 #ifndef OLE2ANSI
     size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, -1, NULL, 0);
     if( typeLibPathLen > 0 )
@@ -314,8 +349,10 @@ STDAPI DllRegisterServer(VOID)
         LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));
         MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);
         if( FAILED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )
+#ifndef BUILD_LOCALSERVER
             return SELFREG_E_TYPELIB;
         typeLib->Release();
+#endif
         CoTaskMemFree((void *)typeLibPath);
     }
 #else
@@ -324,8 +361,6 @@ STDAPI DllRegisterServer(VOID)
     typeLib->Release();
 #endif
 
-    CoTaskMemFree((void *)psz_CLSID);
-
     return S_OK;
 };
 
@@ -360,6 +395,7 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
         return 0;
  
     DWORD dwRegisterClassObject;
+    DWORD dwRegisterClassObject2;
 
     if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
         CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
@@ -371,6 +407,10 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
                     ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
         return 0;
 
+    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
+                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
+        return 0;
+
     classProc->Release();
 
     /*
@@ -381,7 +421,7 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
         while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
         {
             if( msg.message == WM_QUIT )
-                break;  // Leave the PeekMessage while() loop
+                break;  // break out PeekMessage loop
 
             /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
                 continue;*/
@@ -391,7 +431,7 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
         }
 
         if(msg.message == WM_QUIT)
-            break;  // Leave the for() loop
+            break;  // break out main loop
 
         WaitMessage();
     }
@@ -399,8 +439,11 @@ STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
     if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
         CoRevokeClassObject(dwRegisterClassObject);
 
+    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
+        CoRevokeClassObject(dwRegisterClassObject2);
+
     // Reached on WM_QUIT message
-    CoUninitialize();
+    OleUninitialize();
     return ((int) msg.wParam);
 };