main.c 14.5 KB
Newer Older
1 2 3 4 5
/*
 *    MSHTML Class Factory
 *
 * Copyright 2002 Lionel Ulmer
 * Copyright 2003 Mike McCormack
6
 * Copyright 2005 Jacek Caban
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23
 */

#include <stdarg.h>
24
#include <stdio.h>
25

26 27
#define COBJMACROS

28 29
#include "windef.h"
#include "winbase.h"
30
#include "winuser.h"
31
#include "winreg.h"
32
#include "ole2.h"
33
#include "advpub.h"
34
#include "shlwapi.h"
35
#include "optary.h"
36
#include "shlguid.h"
37

38
#include "wine/unicode.h"
39 40
#include "wine/debug.h"

41
#define INIT_GUID
42 43 44
#include "mshtml_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
45

46
HINSTANCE hInst;
47
DWORD mshtml_tls = TLS_OUT_OF_INDEXES;
48

49 50
static HINSTANCE shdoclc = NULL;

51 52
static void thread_detach(void)
{
53 54
    thread_data_t *thread_data;

55 56 57 58 59 60 61
    thread_data = get_thread_data(FALSE);
    if(!thread_data)
        return;

    if(thread_data->thread_hwnd)
        DestroyWindow(thread_data->thread_hwnd);

62
    heap_free(thread_data);
63 64 65 66 67
}

static void process_detach(void)
{
    close_gecko();
68
    release_typelib();
69

70 71
    if(shdoclc)
        FreeLibrary(shdoclc);
72
    if(mshtml_tls != TLS_OUT_OF_INDEXES)
73
        TlsFree(mshtml_tls);
74
}
75

76 77 78 79 80 81 82 83 84 85 86
HINSTANCE get_shdoclc(void)
{
    static const WCHAR wszShdoclc[] =
        {'s','h','d','o','c','l','c','.','d','l','l',0};

    if(shdoclc)
        return shdoclc;

    return shdoclc = LoadLibraryExW(wszShdoclc, NULL, LOAD_LIBRARY_AS_DATAFILE);
}

87 88 89
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
    switch(fdwReason) {
90 91 92 93
    case DLL_PROCESS_ATTACH:
        hInst = hInstDLL;
        break;
    case DLL_PROCESS_DETACH:
94
        process_detach();
95 96 97 98
        break;
    case DLL_THREAD_DETACH:
        thread_detach();
        break;
99
    }
100
    return TRUE;
101 102
}

103 104 105 106 107 108
/***********************************************************
 *    ClassFactory implementation
 */
typedef HRESULT (*CreateInstanceFunc)(IUnknown*,REFIID,void**);
typedef struct {
    const IClassFactoryVtbl *lpVtbl;
109
    LONG ref;
110 111 112 113
    CreateInstanceFunc fnCreateInstance;
} ClassFactory;

static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFGUID riid, void **ppvObject)
114
{
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    if(IsEqualGUID(&IID_IClassFactory, riid) || IsEqualGUID(&IID_IUnknown, riid)) {
        IClassFactory_AddRef(iface);
        *ppvObject = iface;
        return S_OK;
    }

    WARN("not supported iid %s\n", debugstr_guid(riid));
    *ppvObject = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
{
    ClassFactory *This = (ClassFactory*)iface;
    ULONG ref = InterlockedIncrement(&This->ref);
130
    TRACE("(%p) ref = %u\n", This, ref);
131 132
    return ref;
}
133

134 135 136 137
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
{
    ClassFactory *This = (ClassFactory*)iface;
    ULONG ref = InterlockedDecrement(&This->ref);
138

139
    TRACE("(%p) ref = %u\n", This, ref);
140

141
    if(!ref) {
142
        heap_free(This);
143
    }
144

145 146
    return ref;
}
147

148 149 150 151 152 153 154 155 156
static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
        REFIID riid, void **ppvObject)
{
    ClassFactory *This = (ClassFactory*)iface;
    return This->fnCreateInstance(pUnkOuter, riid, ppvObject);
}

static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
{
157 158
    TRACE("(%p)->(%x)\n", iface, dolock);

159
    /* We never unload the DLL. See DllCanUnloadNow(). */
160 161 162
    return S_OK;
}

163 164 165 166 167 168 169 170 171
static const IClassFactoryVtbl HTMLClassFactoryVtbl = {
    ClassFactory_QueryInterface,
    ClassFactory_AddRef,
    ClassFactory_Release,
    ClassFactory_CreateInstance,
    ClassFactory_LockServer
};

static HRESULT ClassFactory_Create(REFIID riid, void **ppv, CreateInstanceFunc fnCreateInstance)
172
{
173
    ClassFactory *ret = heap_alloc(sizeof(ClassFactory));
174
    HRESULT hres;
175

176 177 178
    ret->lpVtbl = &HTMLClassFactoryVtbl;
    ret->ref = 0;
    ret->fnCreateInstance = fnCreateInstance;
179

180
    hres = IClassFactory_QueryInterface((IClassFactory*)ret, riid, ppv);
181
    if(FAILED(hres)) {
182
        heap_free(ret);
183 184 185 186 187
        *ppv = NULL;
    }
    return hres;
}

188 189 190
/******************************************************************
 *		DllGetClassObject (MSHTML.@)
 */
191
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
192 193
{
    if(IsEqualGUID(&CLSID_HTMLDocument, rclsid)) {
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
        TRACE("(CLSID_HTMLDocument %s %p)\n", debugstr_guid(riid), ppv);
        return ClassFactory_Create(riid, ppv, HTMLDocument_Create);
    }else if(IsEqualGUID(&CLSID_AboutProtocol, rclsid)) {
        TRACE("(CLSID_AboutProtocol %s %p)\n", debugstr_guid(riid), ppv);
        return ProtocolFactory_Create(rclsid, riid, ppv);
    }else if(IsEqualGUID(&CLSID_JSProtocol, rclsid)) {
        TRACE("(CLSID_JSProtocol %s %p)\n", debugstr_guid(riid), ppv);
        return ProtocolFactory_Create(rclsid, riid, ppv);
    }else if(IsEqualGUID(&CLSID_MailtoProtocol, rclsid)) {
        TRACE("(CLSID_MailtoProtocol %s %p)\n", debugstr_guid(riid), ppv);
        return ProtocolFactory_Create(rclsid, riid, ppv);
    }else if(IsEqualGUID(&CLSID_ResProtocol, rclsid)) {
        TRACE("(CLSID_ResProtocol %s %p)\n", debugstr_guid(riid), ppv);
        return ProtocolFactory_Create(rclsid, riid, ppv);
    }else if(IsEqualGUID(&CLSID_SysimageProtocol, rclsid)) {
        TRACE("(CLSID_SysimageProtocol %s %p)\n", debugstr_guid(riid), ppv);
        return ProtocolFactory_Create(rclsid, riid, ppv);
211 212 213
    }else if(IsEqualGUID(&CLSID_HTMLLoadOptions, rclsid)) {
        TRACE("(CLSID_HTMLLoadOptions %s %p)\n", debugstr_guid(riid), ppv);
        return ClassFactory_Create(riid, ppv, HTMLLoadOptions_Create);
214 215 216 217 218 219
    }

    FIXME("Unknown class %s\n", debugstr_guid(rclsid));
    return CLASS_E_CLASSNOTAVAILABLE;
}

220 221 222
/******************************************************************
 *              DllCanUnloadNow (MSHTML.@)
 */
223
HRESULT WINAPI DllCanUnloadNow(void)
224
{
225 226 227
    TRACE("()\n");
    /* The cost of keeping this DLL in memory is small. */
    return S_FALSE;
228 229
}

230 231 232 233 234
/***********************************************************************
 *          RunHTMLApplication (MSHTML.@)
 *
 * Appears to have the same prototype as WinMain.
 */
Jacek Caban's avatar
Jacek Caban committed
235 236
HRESULT WINAPI RunHTMLApplication( HINSTANCE hinst, HINSTANCE hPrevInst,
                               LPSTR szCmdLine, INT nCmdShow )
237 238 239 240
{
    FIXME("%p %p %s %d\n", hinst, hPrevInst, debugstr_a(szCmdLine), nCmdShow );
    return 0;
}
241

242 243 244 245 246 247 248 249 250
/***********************************************************************
 *          RNIGetCompatibleVersion (MSHTML.@)
 */
DWORD WINAPI RNIGetCompatibleVersion(void)
{
    TRACE("()\n");
    return 0x20000;
}

251 252 253
/***********************************************************************
 *          DllInstall (MSHTML.@)
 */
254
HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
255 256 257 258 259
{
    FIXME("stub %d %s: returning S_OK\n", bInstall, debugstr_w(cmdline));
    return S_OK;
}

260 261 262 263 264 265 266 267 268 269
/***********************************************************************
 *          ShowHTMLDialog (MSHTML.@)
 */
HRESULT WINAPI ShowHTMLDialog(HWND hwndParent, IMoniker *pMk, VARIANT *pvarArgIn,
        WCHAR *pchOptions, VARIANT *pvarArgOut)
{
    FIXME("(%p %p %p %s %p)\n", hwndParent, pMk, pvarArgIn, debugstr_w(pchOptions), pvarArgOut);
    return E_NOTIMPL;
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
DEFINE_GUID(CLSID_CBackgroundPropertyPage, 0x3050F232, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CCDAnchorPropertyPage, 0x3050F1FC, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CCDGenericPropertyPage, 0x3050F17F, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CDwnBindInfo, 0x3050F3C2, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CHiFiUses, 0x5AAF51B3, 0xB1F0, 0x11D1, 0xB6,0xAB, 0x00,0xA0,0xC9,0x08,0x33,0xE9);
DEFINE_GUID(CLSID_CHtmlComponentConstructor, 0x3050F4F8, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CInlineStylePropertyPage, 0x3050F296, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CPeerHandler, 0x5AAF51B2, 0xB1F0, 0x11D1, 0xB6,0xAB, 0x00,0xA0,0xC9,0x08,0x33,0xE9);
DEFINE_GUID(CLSID_CRecalcEngine, 0x3050F499, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CSvrOMUses, 0x3050F4F0, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_CrSource, 0x65014010, 0x9F62, 0x11D1, 0xA6,0x51, 0x00,0x60,0x08,0x11,0xD5,0xCE);
DEFINE_GUID(CLSID_ExternalFrameworkSite, 0x3050F163, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_HTADocument, 0x3050F5C8, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_HTMLPluginDocument, 0x25336921, 0x03F9, 0x11CF, 0x8F,0xD0, 0x00,0xAA,0x00,0x68,0x6F,0x13);
DEFINE_GUID(CLSID_HTMLPopup, 0x3050F667, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_HTMLPopupDoc, 0x3050F67D, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_HTMLServerDoc, 0x3050F4E7, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_IImageDecodeFilter, 0x607FD4E8, 0x0A03, 0x11D1, 0xAB,0x1D, 0x00,0xC0,0x4F,0xC9,0xB3,0x04);
DEFINE_GUID(CLSID_IImgCtx, 0x3050F3D6, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_IntDitherer, 0x05F6FE1A, 0xECEF, 0x11D0, 0xAA,0xE7, 0x00,0xC0,0x4F,0xC9,0xB3,0x04);
DEFINE_GUID(CLSID_MHTMLDocument, 0x3050F3D9, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
DEFINE_GUID(CLSID_Scriptlet, 0xAE24FDAE, 0x03C6, 0x11D1, 0x8B,0x76, 0x00,0x80,0xC7,0x44,0xF3,0x89);
DEFINE_GUID(CLSID_TridentAPI, 0x429AF92C, 0xA51F, 0x11D2, 0x86,0x1E, 0x00,0xC0,0x4F,0xA3,0x5C,0x89);

294 295 296 297 298 299 300 301
#define INF_SET_ID(id)            \
    do                            \
    {                             \
        static CHAR name[] = #id; \
                                  \
        pse[i].pszName = name;    \
        clsids[i++] = &id;        \
    } while (0)
302 303

#define INF_SET_CLSID(clsid) INF_SET_ID(CLSID_ ## clsid)
304 305 306 307 308

static HRESULT register_server(BOOL do_register)
{
    HRESULT hres;
    HMODULE hAdvpack;
309
    HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
310 311
    STRTABLEA strtable;
    STRENTRYA pse[35];
312
    static CLSID const *clsids[35];
313
    unsigned int i = 0;
314

315 316 317
    static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};

    TRACE("(%x)\n", do_register);
318

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
    INF_SET_CLSID(AboutProtocol);
    INF_SET_CLSID(CAnchorBrowsePropertyPage);
    INF_SET_CLSID(CBackgroundPropertyPage);
    INF_SET_CLSID(CCDAnchorPropertyPage);
    INF_SET_CLSID(CCDGenericPropertyPage);
    INF_SET_CLSID(CDocBrowsePropertyPage);
    INF_SET_CLSID(CDwnBindInfo);
    INF_SET_CLSID(CHiFiUses);
    INF_SET_CLSID(CHtmlComponentConstructor);
    INF_SET_CLSID(CImageBrowsePropertyPage);
    INF_SET_CLSID(CInlineStylePropertyPage);
    INF_SET_CLSID(CPeerHandler);
    INF_SET_CLSID(CRecalcEngine);
    INF_SET_CLSID(CSvrOMUses);
    INF_SET_CLSID(CrSource);
    INF_SET_CLSID(ExternalFrameworkSite);
    INF_SET_CLSID(HTADocument);
    INF_SET_CLSID(HTMLDocument);
    INF_SET_CLSID(HTMLLoadOptions);
    INF_SET_CLSID(HTMLPluginDocument);
    INF_SET_CLSID(HTMLPopup);
    INF_SET_CLSID(HTMLPopupDoc);
    INF_SET_CLSID(HTMLServerDoc);
    INF_SET_CLSID(HTMLWindowProxy);
    INF_SET_CLSID(IImageDecodeFilter);
    INF_SET_CLSID(IImgCtx);
    INF_SET_CLSID(IntDitherer);
    INF_SET_CLSID(JSProtocol);
    INF_SET_CLSID(MHTMLDocument);
    INF_SET_CLSID(MailtoProtocol);
    INF_SET_CLSID(ResProtocol);
    INF_SET_CLSID(Scriptlet);
    INF_SET_CLSID(SysimageProtocol);
    INF_SET_CLSID(TridentAPI);
353
    INF_SET_ID(LIBID_MSHTML);
354 355

    for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++) {
356
        pse[i].pszValue = heap_alloc(39);
357
        sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
358 359 360 361 362 363 364 365 366
                clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
                clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
                clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
    }

    strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
    strtable.pse = pse;

    hAdvpack = LoadLibraryW(wszAdvpack);
367
    pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
368 369 370 371

    hres = pRegInstall(hInst, do_register ? "RegisterDll" : "UnregisterDll", &strtable);

    for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
372
        heap_free(pse[i].pszValue);
373

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
    if(FAILED(hres)) {
        ERR("RegInstall failed: %08x\n", hres);
        return hres;
    }

    if(do_register) {
        ITypeLib *typelib;

        static const WCHAR wszMSHTML[] = {'m','s','h','t','m','l','.','t','l','b',0};

        hres = LoadTypeLibEx(wszMSHTML, REGKIND_REGISTER, &typelib);
        if(SUCCEEDED(hres))
            ITypeLib_Release(typelib);
    }else {
        hres = UnRegisterTypeLib(&LIBID_MSHTML, 4, 0, LOCALE_SYSTEM_DEFAULT, SYS_WIN32);
    }

    if(FAILED(hres))
        ERR("typelib registration failed: %08x\n", hres);

394 395 396
    if(do_register && SUCCEEDED(hres))
        load_gecko(TRUE);

397 398 399 400
    return hres;
}

#undef INF_SET_CLSID
401
#undef INF_SET_ID
402

403 404 405
/***********************************************************************
 *          DllRegisterServer (MSHTML.@)
 */
406
HRESULT WINAPI DllRegisterServer(void)
407
{
408 409 410 411 412 413
    return register_server(TRUE);
}

/***********************************************************************
 *          DllUnregisterServer (MSHTML.@)
 */
414
HRESULT WINAPI DllUnregisterServer(void)
415 416
{
    return register_server(FALSE);
417
}
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

const char *debugstr_variant(const VARIANT *v)
{
    switch(V_VT(v)) {
    case VT_EMPTY:
        return wine_dbg_sprintf("{VT_EMPTY}");
    case VT_NULL:
        return wine_dbg_sprintf("{VT_NULL}");
    case VT_I4:
        return wine_dbg_sprintf("{VT_I4: %d}", V_I4(v));
    case VT_R8:
        return wine_dbg_sprintf("{VT_R8: %lf}", V_R8(v));
    case VT_BSTR:
        return wine_dbg_sprintf("{VT_BSTR: %s}", debugstr_w(V_BSTR(v)));
    case VT_DISPATCH:
        return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v));
    case VT_BOOL:
        return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v));
    default:
        return wine_dbg_sprintf("{vt %d}", V_VT(v));
    }
}