]> git.sesse.net Git - vlc/blobdiff - activex/main.cpp
Input access locking, part 3 (final).
[vlc] / activex / main.cpp
index a1500da2efcdd76b431a0bb45a4524132e7d2176..e508557bc62eed8488e31bae969c9e05835ab2af 100644 (file)
-/*****************************************************************************\r
- * main.cpp: ActiveX control for VLC\r
- *****************************************************************************\r
- * Copyright (C) 2005 VideoLAN\r
- *\r
- * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
- *****************************************************************************/\r
-\r
-#include "plugin.h"\r
-\r
-#include <comcat.h>\r
-#include <windows.h>\r
-#include <shlwapi.h>\r
-\r
-using namespace std;\r
-\r
-#define THREADING_MODEL "Both"\r
-#define COMPANY_STR "VideoLAN"\r
-#define PROGRAM_STR "VLCPlugin"\r
-#define VERSION_MAJOR_STR "1"\r
-#define VERSION_MINOR_STR "0"\r
-#define DESCRIPTION "VideoLAN VLC ActiveX Plugin"\r
-\r
-#define PROGID_STR COMPANY_STR"."PROGRAM_STR\r
-#define VERS_PROGID_STR COMPANY_STR"."PROGRAM_STR"."VERSION_MAJOR_STR\r
-#define VERSION_STR VERSION_MAJOR_STR"."VERSION_MINOR_STR\r
-\r
-#define GUID_STRLEN 39\r
-\r
-/*\r
-** MingW headers do not declare those\r
-*/\r
-extern const CATID CATID_SafeForInitializing;\r
-extern const CATID CATID_SafeForScripting;\r
-\r
-static LONG i_class_ref= 0;\r
-static HINSTANCE h_instance= 0;\r
-\r
-STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)\r
-{\r
-    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;\r
-\r
-    *ppv = NULL;\r
-\r
-    if( CLSID_VLCPlugin == rclsid )\r
-    {\r
-        VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance);\r
-        hr = plugin->QueryInterface(riid, ppv);\r
-        plugin->Release();\r
-    }\r
-    return hr;\r
-};\r
-\r
-STDAPI DllCanUnloadNow(VOID)\r
-{\r
-    return (0 == i_class_ref) ? S_OK: S_FALSE;\r
-};\r
-\r
-static LPCTSTR TStrFromGUID(REFGUID clsid) {\r
-    LPOLESTR oleStr;\r
-\r
-    if( FAILED(StringFromIID(clsid, &oleStr)) )\r
-        return NULL;\r
-\r
-    //check whether TCHAR and OLECHAR are both either ANSI or UNICODE\r
-    if( sizeof(TCHAR) == sizeof(OLECHAR) )\r
-        return (LPCTSTR)oleStr;\r
-\r
-    LPTSTR pct_CLSID = NULL;\r
-#ifndef OLE2ANSI\r
-    size_t len = WideCharToMultiByte(CP_ACP, 0, oleStr, -1, NULL, 0, NULL, NULL);\r
-    if( len > 0 )\r
-    {\r
-        pct_CLSID = (char *)CoTaskMemAlloc(len);\r
-        WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len, NULL, NULL);\r
-    }\r
-#else\r
-    size_t len = MutiByteToWideChar(CP_ACP, 0, oleStr, -1, NULL, 0);\r
-    if( len > 0 )\r
-    {\r
-        clsidStr = (wchar_t *)CoTaskMemAlloc(len*sizeof(wchar_t));\r
-        WideCharToMultiByte(CP_ACP, 0, oleStr, -1, pct_CLSID, len);\r
-    }\r
-#endif\r
-    CoTaskMemFree(oleStr);\r
-    return pct_CLSID;\r
-};\r
-\r
-static HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)\r
-{\r
-    HKEY childKey;\r
-    if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,\r
-                REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )\r
-    {\r
-        return childKey;\r
-    }\r
-    return NULL;\r
-};\r
-\r
-STDAPI DllUnregisterServer(VOID)\r
-{\r
-    // unregister type lib from the registry\r
-    UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);\r
-\r
-    // remove component categories we supports\r
-    ICatRegister *pcr;\r
-    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, \r
-            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {\r
-        CATID implCategories[] = {\r
-            CATID_Control,\r
-            CATID_PersistsToPropertyBag,\r
-            CATID_SafeForInitializing,\r
-            CATID_SafeForScripting,\r
-        };\r
-\r
-        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin,\r
-                sizeof(implCategories)/sizeof(CATID), implCategories);\r
-        pcr->Release();\r
-    }\r
-\r
-    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));\r
-    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));\r
-\r
-    LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);\r
-\r
-    if( NULL == psz_CLSID )\r
-        return E_OUTOFMEMORY;\r
-\r
-    HKEY hClsIDKey;\r
-    if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )\r
-    {\r
-        SHDeleteKey(hClsIDKey, psz_CLSID);\r
-        RegCloseKey(hClsIDKey);\r
-    }\r
-    CoTaskMemFree((void *)psz_CLSID);\r
-\r
-    return S_OK;\r
-};\r
-\r
-STDAPI DllRegisterServer(VOID)\r
-{\r
-    DllUnregisterServer();\r
-\r
-    char DllPath[MAX_PATH];\r
-    DWORD DllPathLen= GetModuleFileName(h_instance, DllPath, sizeof(DllPath)) ;\r
-       if( 0 == DllPathLen )\r
-        return E_FAIL;\r
-\r
-    LPCTSTR psz_CLSID = TStrFromGUID(CLSID_VLCPlugin);\r
-\r
-    if( NULL == psz_CLSID )\r
-        return E_OUTOFMEMORY;\r
-\r
-    HKEY hBaseKey;\r
-\r
-    if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )\r
-        return E_FAIL;\r
-\r
-    HKEY hClassKey = keyCreate(hBaseKey, psz_CLSID);\r
-    if( NULL != hClassKey )\r
-    {\r
-        HKEY hSubKey;\r
-\r
-        // default key value\r
-        RegSetValueEx(hClassKey, NULL, 0, REG_SZ,\r
-                (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));\r
-\r
-        // Control key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("Control"));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // InprocServer32 key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("InprocServer32"));\r
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
-                (const BYTE*)DllPath, DllPathLen);\r
-        RegSetValueEx(hSubKey, TEXT("ThreadingModel"), 0, REG_SZ,\r
-                (const BYTE*)THREADING_MODEL, sizeof(THREADING_MODEL));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // MiscStatus key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("MiscStatus\\1"));\r
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (const BYTE*)"131473", sizeof("131473"));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // Programmable key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("Programmable"));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // ProgID key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("ProgID"));\r
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ, \r
-                (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // VersionIndependentProgID key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("VersionIndependentProgID"));\r
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ, \r
-                (const BYTE*)PROGID_STR, sizeof(PROGID_STR));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // Version key value\r
-        hSubKey = keyCreate(hClassKey, TEXT("Version"));\r
-        RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
-                (const BYTE*)VERSION_STR, sizeof(VERSION_STR));\r
-        RegCloseKey(hSubKey);\r
-\r
-        // TypeLib key value\r
-        LPCTSTR psz_LIBID = TStrFromGUID(LIBID_AXVLC);\r
-        if( NULL != psz_LIBID )\r
-        {\r
-            hSubKey = keyCreate(hClassKey, TEXT("TypeLib"));\r
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
-                    (const BYTE*)psz_LIBID, sizeof(TCHAR)*GUID_STRLEN);\r
-            RegCloseKey(hSubKey);\r
-        }\r
-        RegCloseKey(hClassKey);\r
-    }\r
-    RegCloseKey(hBaseKey);\r
-\r
-    hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));\r
-    if( NULL != hBaseKey )\r
-    {\r
-        // default key value\r
-        RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,\r
-                (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));\r
-\r
-        HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));\r
-        if( NULL != hSubKey )\r
-        {\r
-            // default key value\r
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
-                    (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);\r
-\r
-            RegCloseKey(hSubKey);\r
-        }\r
-        hSubKey = keyCreate(hBaseKey, TEXT("CurVer"));\r
-        if( NULL != hSubKey )\r
-        {\r
-            // default key value\r
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
-                    (const BYTE*)VERS_PROGID_STR, sizeof(VERS_PROGID_STR));\r
-\r
-            RegCloseKey(hSubKey);\r
-        }\r
-        RegCloseKey(hBaseKey);\r
-    }\r
-\r
-    hBaseKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(VERS_PROGID_STR));\r
-    if( NULL != hBaseKey )\r
-    {\r
-        // default key value\r
-        RegSetValueEx(hBaseKey, NULL, 0, REG_SZ,\r
-                (const BYTE*)DESCRIPTION, sizeof(DESCRIPTION));\r
-\r
-        HKEY hSubKey = keyCreate(hBaseKey, TEXT("CLSID"));\r
-        if( NULL != hSubKey )\r
-        {\r
-            // default key value\r
-            RegSetValueEx(hSubKey, NULL, 0, REG_SZ,\r
-                    (const BYTE*)psz_CLSID, sizeof(TCHAR)*GUID_STRLEN);\r
-\r
-            RegCloseKey(hSubKey);\r
-        }\r
-        RegCloseKey(hBaseKey);\r
-    }\r
-\r
-    // indicate which component categories we support\r
-    ICatRegister *pcr;\r
-    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, \r
-            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {\r
-        CATID implCategories[] = {\r
-            CATID_Control,\r
-            CATID_PersistsToPropertyBag,\r
-            CATID_SafeForInitializing,\r
-            CATID_SafeForScripting,\r
-        };\r
-\r
-        pcr->RegisterClassImplCategories(CLSID_VLCPlugin,\r
-                sizeof(implCategories)/sizeof(CATID), implCategories);\r
-        pcr->Release();\r
-    }\r
-\r
-    // register type lib into the registry\r
-    ITypeLib *typeLib;\r
-#ifndef OLE2ANSI\r
-    size_t typeLibPathLen = MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, NULL, 0);\r
-    if( typeLibPathLen > 0 )\r
-    {\r
-        LPOLESTR typeLibPath = (LPOLESTR)CoTaskMemAlloc(typeLibPathLen*sizeof(wchar_t));\r
-        MultiByteToWideChar(CP_ACP, 0, DllPath, DllPathLen, typeLibPath, typeLibPathLen);\r
-        if( SUCCEEDED(LoadTypeLibEx(typeLibPath, REGKIND_REGISTER, &typeLib)) )\r
-            typeLib->Release();\r
-        CoTaskMemFree((void *)typeLibPath);\r
-    }\r
-#else\r
-    if( SUCCEEDED(LoadTypeLibEx((LPOLESTR)DllPath, REGKIND_REGISTER, &typeLib)) )\r
-        typeLib->Release();\r
-#endif\r
-\r
-    CoTaskMemFree((void *)psz_CLSID);\r
-\r
-    return S_OK;\r
-};\r
-\r
-#ifdef BUILD_LOCALSERVER\r
-\r
-/*\r
-** easier to debug an application than a DLL on cygwin GDB :)\r
-*/\r
-#include <iostream>\r
-\r
-STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)\r
-{\r
-    MSG msg;\r
-\r
-    if( FAILED(OleInitialize(NULL)) )\r
-    {\r
-        cerr << "cannot initialize OLE" << endl;\r
-        return 1;\r
-    }\r
-\r
-    IUnknown *classProc = NULL;\r
-\r
-    if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )\r
-        return 0;\r
\r
-    DWORD dwRegisterClassObject;\r
-\r
-    if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,\r
-        CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )\r
-        return 0;\r
-\r
-    DWORD dwRegisterActiveObject;\r
-\r
-    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,\r
-                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )\r
-        return 0;\r
-\r
-    classProc->Release();\r
-\r
-    /*\r
-    * Polling messages from event queue\r
-    */\r
-    while( S_FALSE == DllCanUnloadNow() )\r
-    {\r
-        while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )\r
-        {\r
-            if( msg.message == WM_QUIT )\r
-                break;  // Leave the PeekMessage while() loop\r
-\r
-            /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))\r
-                continue;*/\r
-\r
-            TranslateMessage(&msg);\r
-            DispatchMessage(&msg);\r
-        }\r
-\r
-        if(msg.message == WM_QUIT)\r
-            break;  // Leave the for() loop\r
-\r
-        WaitMessage();\r
-    }\r
-\r
-    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )\r
-        CoRevokeClassObject(dwRegisterClassObject);\r
-\r
-    // Reached on WM_QUIT message\r
-    CoUninitialize();\r
-    return ((int) msg.wParam);\r
-};\r
-\r
-#else\r
-\r
-STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )\r
-{\r
-    switch( fdwReason )\r
-    {\r
-        case DLL_PROCESS_ATTACH:\r
-            h_instance = (HINSTANCE)hModule;\r
-            break;\r
-\r
-        default:\r
-            break;\r
-    }\r
-    return TRUE;\r
-};\r
-\r
-#endif\r
-\r
+/*****************************************************************************
+ * main.cpp: ActiveX control for VLC
+ *****************************************************************************
+ * Copyright (C) 2005 the VideoLAN team
+ *
+ * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * 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., 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 <tchar.h>
+#include <guiddef.h>
+
+using namespace std;
+
+#define COMPANY_STR "VideoLAN"
+#define PROGRAM_STR "VLCPlugin"
+#define DESCRIPTION "VideoLAN VLC ActiveX Plugin"
+
+#define THREADING_MODEL "Apartment"
+#define MISC_STATUS     "131473"
+
+#define PROGID_STR COMPANY_STR"."PROGRAM_STR
+
+#define GUID_STRLEN 39
+
+/*
+** MingW headers & libs do not declare those
+*/
+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 )
+     || ( CLSID_VLCPlugin2 == rclsid) )
+    {
+        VLCPluginClass *plugin = new VLCPluginClass(&i_class_ref, h_instance, rclsid);
+        hr = plugin->QueryInterface(riid, ppv);
+        plugin->Release();
+    }
+    return hr;
+};
+
+STDAPI DllCanUnloadNow(VOID)
+{
+    return (0 == i_class_ref) ? S_OK: S_FALSE;
+};
+
+static inline HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
+{
+    HKEY childKey;
+    if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
+                REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
+    {
+        return childKey;
+    }
+    return NULL;
+};
+
+static inline HKEY keySet(HKEY hKey, LPCTSTR valueName, const void *s, size_t len, DWORD dwType = REG_SZ)
+{
+    if( NULL != hKey )
+    {
+        RegSetValueEx(hKey, valueName, 0, dwType,
+            (const BYTE*)s, len);
+    }
+    return hKey;
+};
+
+static inline HKEY keySetDef(HKEY hKey, const void *s, size_t len, DWORD dwType = REG_SZ)
+{
+    return keySet(hKey, NULL, s, len, dwType);
+};
+
+static inline HKEY keySetDef(HKEY hKey, LPCTSTR s)
+{
+    return keySetDef(hKey, s, sizeof(TCHAR)*(_tcslen(s)+1), REG_SZ);
+};
+
+static inline HKEY keyClose(HKEY hKey)
+{
+    if( NULL != hKey )
+    {
+        RegCloseKey(hKey);
+    }
+    return NULL;
+};
+
+static void UnregisterProgID(REFCLSID rclsid, unsigned int version)
+{
+    OLECHAR szCLSID[GUID_STRLEN];
+
+    StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
+
+    TCHAR progId[sizeof(PROGID_STR)+16];
+    _stprintf(progId, TEXT("%s.%u"), TEXT(PROGID_STR), version);
+
+    SHDeleteKey(HKEY_CLASSES_ROOT, progId);
+
+    HKEY hClsIDKey;
+    if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
+    {
+        SHDeleteKey(hClsIDKey, szCLSID);
+        RegCloseKey(hClsIDKey);
+    }
+};
+
+STDAPI DllUnregisterServer(VOID)
+{
+    // unregister type lib from the registry
+    UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
+
+    // remove component categories we supports
+    ICatRegister *pcr;
+    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
+            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
+        CATID implCategories[] = {
+            CATID_Control,
+            CATID_PersistsToPropertyBag,
+            _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(PROGID_STR));
+
+    UnregisterProgID(CLSID_VLCPlugin, 2);
+    UnregisterProgID(CLSID_VLCPlugin2, 1);
+
+    return S_OK;
+};
+
+static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, LPCTSTR path, size_t pathLen)
+{
+    TCHAR progId[sizeof(PROGID_STR)+16];
+    _stprintf(progId, TEXT("%s.%u"), TEXT(PROGID_STR), version);
+
+    TCHAR description[sizeof(DESCRIPTION)+16];
+    _stprintf(description, TEXT("%s v%u"), TEXT(DESCRIPTION), version);
+
+    HKEY hClassKey;
+    {
+        OLECHAR szCLSID[GUID_STRLEN];
+
+        StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
+
+        HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
+        if( NULL != hProgKey )
+        {
+            // default key value
+            keySetDef(hProgKey, description);
+
+            keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
+                szCLSID,
+                sizeof(szCLSID)));
+
+            //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
+            RegCloseKey(hProgKey);
+        }
+        if( isDefault )
+        {
+            hProgKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
+            if( NULL != hProgKey )
+            {
+                // default key value
+                keySetDef(hProgKey, description);
+
+                keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
+                    szCLSID,
+                    sizeof(szCLSID)));
+
+                keyClose(keySetDef(keyCreate(hProgKey, TEXT("CurVer")),
+                    progId));
+            }
+        }
+        hClassKey = keyCreate(hParent, szCLSID);
+    }
+    if( NULL != hClassKey )
+    {
+        // default key value
+        keySetDef(hClassKey, description);
+
+        // Control key value
+        keyClose(keyCreate(hClassKey, TEXT("Control")));
+
+        // Insertable key value
+        //keyClose(keyCreate(hClassKey, TEXT("Insertable")));
+
+        // ToolboxBitmap32 key value
+        {
+            TCHAR iconPath[pathLen+3];
+            memcpy(iconPath, path, sizeof(TCHAR)*pathLen);
+            _tcscpy(iconPath+pathLen, TEXT(",1"));
+            keyClose(keySetDef(keyCreate(hClassKey,
+                TEXT("ToolboxBitmap32")),
+                iconPath, sizeof(iconPath)));
+        }
+
+#ifdef BUILD_LOCALSERVER
+        // LocalServer32 key value
+        keyClose(keySetDef(keyCreate(hClassKey,
+            TEXT("LocalServer32"), path, sizeof(TCHAR)*(pathLen+1))));
+#else
+        // InprocServer32 key value
+        {
+            HKEY hSubKey = keySetDef(keyCreate(hClassKey,
+                TEXT("InprocServer32")),
+                path, sizeof(TCHAR)*(pathLen+1));
+            keySet(hSubKey,
+                TEXT("ThreadingModel"),
+                TEXT(THREADING_MODEL), sizeof(TEXT(THREADING_MODEL)));
+            keyClose(hSubKey);
+        }
+#endif
+
+        // MiscStatus key value
+        keyClose(keySetDef(keyCreate(hClassKey,
+            TEXT("MiscStatus\\1")),
+            TEXT(MISC_STATUS), sizeof(TEXT(MISC_STATUS))));
+
+        // Programmable key value
+        keyClose(keyCreate(hClassKey, TEXT("Programmable")));
+
+        // ProgID key value
+        keyClose(keySetDef(keyCreate(hClassKey,
+            TEXT("ProgID")),
+            progId));
+
+        // VersionIndependentProgID key value
+        keyClose(keySetDef(keyCreate(hClassKey,
+            TEXT("VersionIndependentProgID")),
+            TEXT(PROGID_STR), sizeof(TEXT(PROGID_STR))));
+
+        // Version key value
+        keyClose(keySetDef(keyCreate(hClassKey,
+            TEXT("Version")),
+            TEXT("1.0")));
+
+        // TypeLib key value
+        OLECHAR szLIBID[GUID_STRLEN];
+
+        StringFromGUID2(LIBID_AXVLC, szLIBID, GUID_STRLEN);
+
+        keyClose(keySetDef(keyCreate(hClassKey,
+                TEXT("TypeLib")),
+                szLIBID, sizeof(szLIBID)));
+        RegCloseKey(hClassKey);
+    }
+    return S_OK;
+}
+
+STDAPI DllRegisterServer(VOID)
+{
+    DllUnregisterServer();
+
+    TCHAR DllPath[MAX_PATH];
+    DWORD DllPathLen=GetModuleFileName(h_instance, DllPath, MAX_PATH) ;
+    if( 0 == DllPathLen )
+        return E_UNEXPECTED;
+
+    HKEY hBaseKey;
+
+    if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_CREATE_SUB_KEY, &hBaseKey) )
+        return SELFREG_E_CLASS;
+
+    RegisterClassID(hBaseKey, CLSID_VLCPlugin, 1, FALSE, DllPath, DllPathLen);
+    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
+
+    RegCloseKey(hBaseKey);
+
+    // indicate which component categories we support
+    ICatRegister *pcr;
+    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr, 
+            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
+        CATID implCategories[] = {
+            CATID_Control,
+            CATID_PersistsToPropertyBag,
+            _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();
+    }
+
+#ifdef BUILD_LOCALSERVER
+    // replace .exe by .tlb
+    _tcscpy(DllPath+DllPathLen-4, TEXT(".tlb"));
+#endif
+
+    // register type lib into the registry
+    ITypeLib *typeLib;
+
+    HRESULT result = LoadTypeLibEx(DllPath, REGKIND_REGISTER, &typeLib);
+    if( SUCCEEDED(result) )
+        typeLib->Release();
+
+    return result;
+};
+
+#ifdef BUILD_LOCALSERVER
+
+/*
+** easier to debug an application than a DLL on cygwin GDB :)
+*/
+#include <iostream>
+
+STDAPI_(int) WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
+{
+    MSG msg;
+
+    if( FAILED(OleInitialize(NULL)) )
+    {
+        cerr << "cannot initialize OLE" << endl;
+        return 1;
+    }
+
+    h_instance = hInst;
+
+    if( FAILED(DllRegisterServer()) )
+    {
+        cerr << "cannot register Local Server" << endl;
+        return 1;
+    }
+
+    IUnknown *classProc = NULL;
+
+    if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown, (LPVOID *)&classProc)) )
+        return 0;
+    DWORD dwRegisterClassObject;
+    DWORD dwRegisterClassObject2;
+
+    if( FAILED(CoRegisterClassObject(CLSID_VLCPlugin, classProc,
+        CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwRegisterClassObject)) )
+        return 0;
+
+    DWORD dwRegisterActiveObject;
+
+    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin,
+                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject)) )
+        return 0;
+
+    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
+                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
+        return 0;
+
+    classProc->Release();
+
+    /*
+    * Polling messages from event queue
+    */
+    while( S_FALSE == DllCanUnloadNow() )
+    {
+        while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
+        {
+            if( msg.message == WM_QUIT )
+                break;  // break out PeekMessage loop
+
+            /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
+                continue;*/
+
+            TranslateMessage(&msg);
+            DispatchMessage(&msg);
+        }
+
+        if(msg.message == WM_QUIT)
+            break;  // break out main loop
+
+        WaitMessage();
+    }
+
+    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
+        CoRevokeClassObject(dwRegisterClassObject);
+
+    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
+        CoRevokeClassObject(dwRegisterClassObject2);
+
+    // Reached on WM_QUIT message
+    OleUninitialize();
+    return ((int) msg.wParam);
+};
+
+#else
+
+STDAPI_(BOOL) DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
+{
+    switch( fdwReason )
+    {
+        case DLL_PROCESS_ATTACH:
+            h_instance = (HINSTANCE)hModule;
+            break;
+
+        default:
+            break;
+    }
+    return TRUE;
+};
+
+#endif
+