main.cpp 14.2 KB
Newer Older
1 2 3
/*****************************************************************************
 * main.cpp: ActiveX control for VLC
 *****************************************************************************
4
 * Copyright (C) 2005 the VideoLAN team
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
Antoine Cellerier's avatar
Antoine Cellerier committed
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 22
 *****************************************************************************/

23 24 25 26
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

27
#include "plugin.h"
28 29 30
#include "utils.h"

#include <stdio.h>
31

Rafaël Carré's avatar
Rafaël Carré committed
32
#include <objsafe.h>
33 34 35 36
#include <comcat.h>
#include <windows.h>
#include <shlwapi.h>

37
#include <tchar.h>
38

39 40 41 42 43 44
#ifdef __MINGW32__
# include <_mingw.h>
# if defined(__MINGW32_MAJOR_VERSION) && !defined(__MINGW64_VERSION_MAJOR)
#  undef GUID_EXT
#  define GUID_EXT
#  include <initguid.h>
45 46
DEFINE_GUID(CATID_InternetAware, \
    0x0DE86A58, 0x2BAA, 0x11CF, 0xA2, 0x29, 0x00,0xAA,0x00,0x3D,0x73,0x52);
47 48 49 50
DEFINE_GUID(CATID_SafeForInitializing, \
    0x7DD95802, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
DEFINE_GUID(CATID_SafeForScripting, \
    0x7DD95801, 0x9882, 0x11CF, 0x9F, 0xA9, 0x00,0xAA,0x00,0x6C,0x42,0xC4);
51
#  endif /* __MINGW32_MAJOR_VERSION && !__MINGW64_VERSION_MAJOR */
52 53 54
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT
55
#endif /* __MINGW32__ */
56

57 58
using namespace std;

59
#define DESCRIPTION "VLC ActiveX Plugin and IE Web Plugin"
60

61 62 63
#define THREADING_MODEL "Apartment"
#define MISC_STATUS     "131473"

64
#define PROGID_STR "VideoLAN.VLCPlugin"
65 66 67 68 69 70

#define GUID_STRLEN 39

static LONG i_class_ref= 0;
static HINSTANCE h_instance= 0;

71 72 73 74 75
HMODULE DllGetModule()
{
    return h_instance;
};

76
STDAPI EXPORT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
77 78 79 80 81
{
    HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;

    *ppv = NULL;

82
    if( CLSID_VLCPlugin2 == rclsid )
83
    {
84 85
        VLCPluginClass *plugin =
            new VLCPluginClass(&i_class_ref, h_instance, rclsid);
86 87 88 89 90 91
        hr = plugin->QueryInterface(riid, ppv);
        plugin->Release();
    }
    return hr;
};

92
STDAPI EXPORT DllCanUnloadNow(VOID)
93 94 95 96
{
    return (0 == i_class_ref) ? S_OK: S_FALSE;
};

97
static inline HKEY keyCreate(HKEY parentKey, LPCTSTR keyName)
98
{
99
    HKEY childKey;
100
    if( ERROR_SUCCESS == RegCreateKeyEx(parentKey, keyName, 0, NULL,
101
             REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &childKey, NULL) )
102
    {
103
        return childKey;
104
    }
105 106 107
    return NULL;
};

108 109
static inline HKEY keySet(HKEY hKey, LPCTSTR valueName,
                          const void *s, size_t len, DWORD dwType = REG_SZ)
110 111
{
    if( NULL != hKey )
112
    {
113
        RegSetValueEx(hKey, valueName, 0, dwType, (const BYTE*)s, len);
114
    }
115
    return hKey;
116 117
};

118 119
static inline HKEY keySetDef(HKEY hKey,
                             const void *s, size_t len, DWORD dwType = REG_SZ)
120
{
121
    return keySet(hKey, NULL, s, len, dwType);
122 123
};

124
static inline HKEY keySetDef(HKEY hKey, LPCTSTR s)
125
{
126
    return keySetDef(hKey, s, sizeof(TCHAR)*(_tcslen(s)+1), REG_SZ);
127 128 129 130 131
};

static inline HKEY keyClose(HKEY hKey)
{
    if( NULL != hKey )
132
    {
133
        RegCloseKey(hKey);
134 135 136 137
    }
    return NULL;
};

138
static void UnregisterProgID(REFCLSID rclsid, unsigned int version)
139
{
140
    OLECHAR szCLSID[GUID_STRLEN];
141

142
    StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
143

144
    TCHAR progId[sizeof(PROGID_STR)+16];
145
    _stprintf(progId, TEXT("%s.%u"), PROGID_STR, version);
146

147
    SHDeleteKey(HKEY_CLASSES_ROOT, progId);
148 149

    HKEY hClsIDKey;
150
    if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_WRITE, &hClsIDKey) )
151
    {
152
        SHDeleteKey(hClsIDKey, szCLSID);
153 154
        RegCloseKey(hClsIDKey);
    }
155 156 157 158 159 160

    if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Ext\\Stats"), 0, KEY_WRITE, &hClsIDKey) )
    {
        SHDeleteKey(hClsIDKey, szCLSID);
        RegCloseKey(hClsIDKey);
    }
161 162
};

163
STDAPI EXPORT DllUnregisterServer(VOID)
164 165
{
    // unregister type lib from the registry
166
#if !defined(_WIN64)
167
    UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN32);
168 169 170
#else
    UnRegisterTypeLib(LIBID_AXVLC, 1, 0, LOCALE_NEUTRAL, SYS_WIN64);
#endif
171 172 173

    // remove component categories we supports
    ICatRegister *pcr;
174
    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
175 176 177 178
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
        CATID implCategories[] = {
            CATID_Control,
            CATID_PersistsToPropertyBag,
179 180 181
            CATID_InternetAware,
            CATID_SafeForInitializing,
            CATID_SafeForScripting,
182 183
        };

184 185
        pcr->UnRegisterClassImplCategories(CLSID_VLCPlugin2,
                sizeof(implCategories)/sizeof(CATID), implCategories);
186 187 188
        pcr->Release();
    }

189
    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
190

191 192
    SHDeleteKey(HKEY_CLASSES_ROOT, TEXT("MIME\\Database\\Content Type\\application/x-vlc-plugin"));

193
    UnregisterProgID(CLSID_VLCPlugin2, 1);
194 195 196 197

    return S_OK;
};

198
static HRESULT RegisterClassID(HKEY hParent, REFCLSID rclsid, unsigned int version, BOOL isDefault, LPCTSTR path, size_t pathLen)
199
{
200
    TCHAR progId[sizeof(PROGID_STR)+16];
201
    _stprintf(progId, TEXT("%s.%u"), PROGID_STR, version);
202

203
    TCHAR description[sizeof(DESCRIPTION)+16];
204
    _stprintf(description, TEXT("%s v%u"), DESCRIPTION, version);
205

206 207
    HKEY hClassKey;
    {
208
        OLECHAR szCLSID[GUID_STRLEN];
209

210
        StringFromGUID2(rclsid, szCLSID, GUID_STRLEN);
211

212 213 214 215 216 217
        HKEY hProgKey = keyCreate(HKEY_CLASSES_ROOT, progId);
        if( NULL != hProgKey )
        {
            // default key value
            keySetDef(hProgKey, description);

218
            keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
219
                               szCLSID, sizeof(szCLSID)));
220

221
            //hSubKey = keyClose(keyCreate(hBaseKey, "Insertable"));
222
 
223 224 225 226
            RegCloseKey(hProgKey);
        }
        if( isDefault )
        {
227
            hProgKey = keyCreate(HKEY_CLASSES_ROOT, TEXT(PROGID_STR));
228 229 230 231 232
            if( NULL != hProgKey )
            {
                // default key value
                keySetDef(hProgKey, description);

233
                keyClose(keySetDef(keyCreate(hProgKey, TEXT("CLSID")),
234
                                   szCLSID, sizeof(szCLSID)));
235

236
                keyClose(keySetDef(keyCreate(hProgKey, TEXT("CurVer")),
237
                                   progId));
238
            }
239 240 241 242 243 244 245 246 247 248 249
            
            // register the mime type for the type attribute
            hProgKey = keyCreate(HKEY_CLASSES_ROOT, TEXT("MIME\\Database\\Content Type\\application/x-vlc-plugin"));
            if( NULL != hProgKey )
            {
                // default key value
                keySetDef(hProgKey, description);

                keyClose(keySet(hProgKey, TEXT("CLSID"),
                                szCLSID, sizeof(szCLSID)));
            }
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268

            // entry for addons list
            hProgKey = keyCreate(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Ext\\Stats"));
            if( NULL != hProgKey )
            {
                HKEY hSubKey = keyCreate(hProgKey, szCLSID);
                if( NULL != hSubKey )
                {
                    HKEY hSubKey2 = keyCreate(hSubKey, TEXT("iexplore"));
                    if( NULL != hSubKey2 )
                    {
                        keyClose(keyCreate(hSubKey2, TEXT("AllowedDomains\\*")));

                        DWORD value = 1;
                        keyClose(keySet(hSubKey2, TEXT("Type"),
                                        (const BYTE*)&value, sizeof(value), REG_DWORD));
                    }
                }
            }
269
        }
270
        hClassKey = keyCreate(hParent, szCLSID);
271
    }
272 273 274
    if( NULL != hClassKey )
    {
        // default key value
275
        keySetDef(hClassKey, description);
276 277

        // Control key value
278
        keyClose(keyCreate(hClassKey, TEXT("Control")));
279

280
        // Insertable key value
281
        //keyClose(keyCreate(hClassKey, TEXT("Insertable")));
282

283
        // ToolboxBitmap32 key value
284
        {
285 286
            std::vector<TCHAR> iconPathBuf(pathLen+3, 0);
            TCHAR* iconPath = &iconPathBuf[0];
287 288
            memcpy(iconPath, path, sizeof(TCHAR)*pathLen);
            _tcscpy(iconPath+pathLen, TEXT(",1"));
289
            keyClose(keySetDef(keyCreate(hClassKey,
290
                TEXT("ToolboxBitmap32")),
291
                iconPath, sizeof(TCHAR)*(_tcslen(iconPath)+1)));
292
        }
293

294 295
#ifdef BUILD_LOCALSERVER
        // LocalServer32 key value
296
        keyClose(keySetDef(keyCreate(hClassKey,
297
            TEXT("LocalServer32"), path, sizeof(TCHAR)*(pathLen+1))));
298
#else
299
        // InprocServer32 key value
300 301
        {
            HKEY hSubKey = keySetDef(keyCreate(hClassKey,
302 303
                TEXT("InprocServer32")),
                path, sizeof(TCHAR)*(pathLen+1));
304
            keySet(hSubKey,
305 306
                TEXT("ThreadingModel"),
                TEXT(THREADING_MODEL), sizeof(TEXT(THREADING_MODEL)));
307 308
            keyClose(hSubKey);
        }
309
#endif
310 311

        // MiscStatus key value
312 313
        keyClose(keySetDef(keyCreate(hClassKey,TEXT("MiscStatus\\1")),
                           TEXT(MISC_STATUS), sizeof(TEXT(MISC_STATUS))));
314 315

        // Programmable key value
316
        keyClose(keyCreate(hClassKey, TEXT("Programmable")));
317 318

        // ProgID key value
319
        keyClose(keySetDef(keyCreate(hClassKey,TEXT("ProgID")),progId));
320 321

        // VersionIndependentProgID key value
322
        keyClose(keySetDef(keyCreate(hClassKey,
323
                                     TEXT("VersionIndependentProgID")),
324
                           TEXT(PROGID_STR), sizeof(TEXT(PROGID_STR))));
325 326

        // Version key value
327
        keyClose(keySetDef(keyCreate(hClassKey,TEXT("Version")),TEXT("1.0")));
328 329

        // TypeLib key value
330 331 332 333
        OLECHAR szLIBID[GUID_STRLEN];

        StringFromGUID2(LIBID_AXVLC, szLIBID, GUID_STRLEN);

334 335
        keyClose(keySetDef(keyCreate(hClassKey,TEXT("TypeLib")),
                           szLIBID, sizeof(szLIBID)));
336
 
337 338
        RegCloseKey(hClassKey);
    }
339 340 341
    return S_OK;
}

342
STDAPI EXPORT DllRegisterServer(VOID)
343 344 345
{
    DllUnregisterServer();

346 347
    TCHAR DllPath[MAX_PATH];
    DWORD DllPathLen=GetModuleFileName(h_instance, DllPath, MAX_PATH) ;
348
    if( 0 == DllPathLen )
349
        return E_UNEXPECTED;
350
    DllPath[MAX_PATH-1] = '\0';
351 352 353

    HKEY hBaseKey;

354 355
    if( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"),
                                      0, KEY_CREATE_SUB_KEY, &hBaseKey) )
356
        return SELFREG_E_CLASS;
357

358
    RegisterClassID(hBaseKey, CLSID_VLCPlugin2, 2, TRUE, DllPath, DllPathLen);
359 360 361

    RegCloseKey(hBaseKey);

362 363
    // indicate which component categories we support
    ICatRegister *pcr;
364
    if( SUCCEEDED(CoCreateInstance(CLSID_StdComponentCategoriesMgr,
365 366 367 368
            NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr)) ) {
        CATID implCategories[] = {
            CATID_Control,
            CATID_PersistsToPropertyBag,
369 370 371
            CATID_InternetAware,
            CATID_SafeForInitializing,
            CATID_SafeForScripting,
372 373
        };

374 375
        pcr->RegisterClassImplCategories(CLSID_VLCPlugin2,
                sizeof(implCategories)/sizeof(CATID), implCategories);
376 377 378
        pcr->Release();
    }

379 380
#ifdef BUILD_LOCALSERVER
    // replace .exe by .tlb
381
    _tcscpy(DllPath+DllPathLen-4, TEXT(".tlb"));
382
#endif
383

384 385 386 387 388
    // register type lib into the registry
    ITypeLib *typeLib;

    HRESULT result = LoadTypeLibEx(DllPath, REGKIND_REGISTER, &typeLib);
    if( SUCCEEDED(result) )
389
        typeLib->Release();
390

391
    return result;
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
};

#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;
    }

411 412 413 414 415 416 417 418
    h_instance = hInst;

    if( FAILED(DllRegisterServer()) )
    {
        cerr << "cannot register Local Server" << endl;
        return 1;
    }

419 420
    IUnknown *classProc = NULL;

421 422
    if( FAILED(DllGetClassObject(CLSID_VLCPlugin, IID_IUnknown,
                                 (LPVOID *)&classProc)) )
423 424 425
        return 0;
 
    DWORD dwRegisterClassObject;
426
    DWORD dwRegisterClassObject2;
427 428 429 430 431 432 433 434 435 436 437

    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;

438 439 440 441
    if( FAILED(RegisterActiveObject(classProc, CLSID_VLCPlugin2,
                    ACTIVEOBJECT_WEAK, &dwRegisterActiveObject2)) )
        return 0;

442 443 444 445 446 447 448 449 450 451
    classProc->Release();

    /*
    * Polling messages from event queue
    */
    while( S_FALSE == DllCanUnloadNow() )
    {
        while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
        {
            if( msg.message == WM_QUIT )
452
                break;  // break out PeekMessage loop
453 454 455 456 457 458 459 460 461

            /*if(TranslateAccelerator(ghwndApp, ghAccel, &msg))
                continue;*/

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
462
            break;  // break out main loop
463 464 465 466 467 468 469

        WaitMessage();
    }

    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject, NULL)) )
        CoRevokeClassObject(dwRegisterClassObject);

470 471 472
    if( SUCCEEDED(RevokeActiveObject(dwRegisterActiveObject2, NULL)) )
        CoRevokeClassObject(dwRegisterClassObject2);

473
    // Reached on WM_QUIT message
474
    OleUninitialize();
475 476 477 478 479
    return ((int) msg.wParam);
};

#else

480
STDAPI_(BOOL) EXPORT DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved )
481
{
482
    (void)lpReserved;
483 484 485 486 487 488 489 490 491 492 493 494 495 496
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
            h_instance = (HINSTANCE)hModule;
            break;

        default:
            break;
    }
    return TRUE;
};

#endif