atl30.c 15.7 KB
Newer Older
1 2 3 4
/*
 * Implementation of Active Template Library (atl.dll)
 *
 * Copyright 2004 Aric Stewart for CodeWeavers
5
 * Copyright 2005 Jacek Caban
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21 22 23
 */

#include <stdio.h>

24 25
#define COBJMACROS

26
#include "objidl.h"
27
#include "rpcproxy.h"
28
#include "atlbase.h"
29
#include "atlwin.h"
30

31
#include "wine/debug.h"
32 33
#include "wine/unicode.h"

34 35
WINE_DEFAULT_DEBUG_CHANNEL(atl);

36
extern HINSTANCE atl_instance;
37

38
#define ATLVer1Size FIELD_OFFSET(_ATL_MODULEW, dwAtlBuildVer)
39

40
HRESULT WINAPI AtlModuleInit(_ATL_MODULEW* pM, _ATL_OBJMAP_ENTRYW* p, HINSTANCE h)
41 42
{
    INT i;
43
    UINT size;
44

45
    TRACE("(%p %p %p)\n", pM, p, h);
46

47
    size = pM->cbSize;
48
    switch (size)
49
    {
50 51 52 53 54 55 56 57
    case ATLVer1Size:
    case sizeof(_ATL_MODULEW):
#ifdef _WIN64
    case sizeof(_ATL_MODULEW) + sizeof(void *):
#endif
        break;
    default:
        WARN("Unknown structure version (size %i)\n",size);
58 59
        return E_INVALIDARG;
    }
60

61 62
    memset(pM,0,pM->cbSize);
    pM->cbSize = size;
63 64 65 66 67 68
    pM->m_hInst = h;
    pM->m_hInstResource = h;
    pM->m_hInstTypeLib = h;
    pM->m_pObjMap = p;
    pM->m_hHeap = GetProcessHeap();

69 70 71 72
    InitializeCriticalSection(&pM->u.m_csTypeInfoHolder);
    InitializeCriticalSection(&pM->m_csWindowCreate);
    InitializeCriticalSection(&pM->m_csObjMap);

73 74
    /* call mains */
    i = 0;
75
    if (pM->m_pObjMap != NULL  && size > ATLVer1Size)
76
    {
77 78 79 80 81 82 83
        while (pM->m_pObjMap[i].pclsid != NULL)
        {
            TRACE("Initializing object %i %p\n",i,p[i].pfnObjectMain);
            if (p[i].pfnObjectMain)
                p[i].pfnObjectMain(TRUE);
            i++;
        }
84 85 86 87 88
    }

    return S_OK;
}

89 90 91 92 93 94 95 96 97 98 99 100 101
static _ATL_OBJMAP_ENTRYW_V1 *get_objmap_entry( _ATL_MODULEW *mod, unsigned int index )
{
    _ATL_OBJMAP_ENTRYW_V1 *ret;

    if (mod->cbSize == ATLVer1Size)
        ret = (_ATL_OBJMAP_ENTRYW_V1 *)mod->m_pObjMap + index;
    else
        ret = (_ATL_OBJMAP_ENTRYW_V1 *)(mod->m_pObjMap + index);

    if (!ret->pclsid) ret = NULL;
    return ret;
}

102
HRESULT WINAPI AtlModuleLoadTypeLib(_ATL_MODULEW *pM, LPCOLESTR lpszIndex,
103 104
                                    BSTR *pbstrPath, ITypeLib **ppTypeLib)
{
105 106 107 108 109
    TRACE("(%p, %s, %p, %p)\n", pM, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);

    if (!pM)
        return E_INVALIDARG;

110
    return AtlLoadTypeLib(pM->m_hInstTypeLib, lpszIndex, pbstrPath, ppTypeLib);
111 112
}

113
HRESULT WINAPI AtlModuleTerm(_ATL_MODULE *pM)
114
{
115
    _ATL_TERMFUNC_ELEM *iter, *tmp;
116 117 118

    TRACE("(%p)\n", pM);

119 120 121 122 123 124 125 126 127 128
    if (pM->cbSize > ATLVer1Size)
    {
        iter = pM->m_pTermFuncs;

        while(iter) {
            iter->pFunc(iter->dw);
            tmp = iter;
            iter = iter->pNext;
            HeapFree(GetProcessHeap(), 0, tmp);
        }
129 130 131 132 133
    }

    return S_OK;
}

134
HRESULT WINAPI AtlModuleRegisterClassObjects(_ATL_MODULEW *pM, DWORD dwClsContext,
135 136
                                             DWORD dwFlags)
{
137
    _ATL_OBJMAP_ENTRYW_V1 *obj;
138 139
    int i=0;

140
    TRACE("(%p %i %i)\n",pM, dwClsContext, dwFlags);
141 142 143 144

    if (pM == NULL)
        return E_INVALIDARG;

145
    while ((obj = get_objmap_entry( pM, i++ )))
146 147 148 149 150 151 152 153 154 155 156
    {
        IUnknown* pUnknown;
        HRESULT rc;

        TRACE("Registering object %i\n",i);
        if (obj->pfnGetClassObject)
        {
            rc = obj->pfnGetClassObject(obj->pfnCreateInstance, &IID_IUnknown,
                                   (LPVOID*)&pUnknown);
            if (SUCCEEDED (rc) )
            {
157 158 159 160 161 162
                rc = CoRegisterClassObject(obj->pclsid, pUnknown, dwClsContext,
                                           dwFlags, &obj->dwRegister);

                if (FAILED (rc) )
                    WARN("Failed to register object %i: 0x%08x\n", i, rc);

163 164 165 166 167 168
                if (pUnknown)
                    IUnknown_Release(pUnknown);
            }
        }
    }

169
   return S_OK;
170 171
}

172
HRESULT WINAPI AtlModuleUnregisterServerEx(_ATL_MODULEW* pM, BOOL bUnRegTypeLib, const CLSID* pCLSID)
173 174 175 176 177
{
    FIXME("(%p, %i, %p) stub\n", pM, bUnRegTypeLib, pCLSID);
    return S_OK;
}

178 179 180 181
/***********************************************************************
 *           AtlModuleRegisterServer         [ATL.@]
 *
 */
182
HRESULT WINAPI AtlModuleRegisterServer(_ATL_MODULEW* pM, BOOL bRegTypeLib, const CLSID* clsid)
183
{
184
    const _ATL_OBJMAP_ENTRYW_V1 *obj;
185 186 187 188 189 190 191 192
    int i;
    HRESULT hRes;

    TRACE("%p %d %s\n", pM, bRegTypeLib, debugstr_guid(clsid));

    if (pM == NULL)
        return E_INVALIDARG;

193
    for (i = 0; (obj = get_objmap_entry( pM, i )) != NULL; i++) /* register CLSIDs */
194
    {
195
        if (!clsid || IsEqualCLSID(obj->pclsid, clsid))
196 197 198 199 200
        {
            TRACE("Registering clsid %s\n", debugstr_guid(obj->pclsid));
            hRes = obj->pfnUpdateRegistry(TRUE); /* register */
            if (FAILED(hRes))
                return hRes;
201 202 203 204 205 206 207 208 209 210 211

            if(pM->cbSize > ATLVer1Size) {
                const struct _ATL_CATMAP_ENTRY *catmap;

                catmap = ((const _ATL_OBJMAP_ENTRYW*)obj)->pfnGetCategoryMap();
                if(catmap) {
                    hRes = AtlRegisterClassCategoriesHelper(obj->pclsid, catmap, TRUE);
                    if(FAILED(hRes))
                        return hRes;
                }
            }
212 213 214 215 216
        }
    }

    if (bRegTypeLib)
    {
217
        hRes = AtlRegisterTypeLib(pM->m_hInstTypeLib, NULL);
218 219 220 221
        if (FAILED(hRes))
            return hRes;
    }

222 223
    return S_OK;
}
224 225 226 227 228 229 230

/***********************************************************************
 *           AtlModuleGetClassObject              [ATL.@]
 */
HRESULT WINAPI AtlModuleGetClassObject(_ATL_MODULEW *pm, REFCLSID rclsid,
                                       REFIID riid, LPVOID *ppv)
{
231
    _ATL_OBJMAP_ENTRYW_V1 *obj;
232
    int i;
233
    HRESULT hres = CLASS_E_CLASSNOTAVAILABLE;
234 235 236 237 238 239

    TRACE("%p %s %s %p\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);

    if (pm == NULL)
        return E_INVALIDARG;

240
    for (i = 0; (obj = get_objmap_entry( pm, i )) != NULL; i++)
241
    {
242
        if (IsEqualCLSID(obj->pclsid, rclsid))
243 244 245
        {
            TRACE("found object %i\n", i);
            if (obj->pfnGetClassObject)
246 247 248 249 250 251 252 253 254
            {
                if (!obj->pCF)
                    hres = obj->pfnGetClassObject(obj->pfnCreateInstance,
                                                  &IID_IUnknown,
                                                  (void **)&obj->pCF);
                if (obj->pCF)
                    hres = IUnknown_QueryInterface(obj->pCF, riid, ppv);
                break;
            }
255 256 257 258 259
        }
    }

    WARN("no class object found for %s\n", debugstr_guid(rclsid));

260
    return hres;
261 262 263 264 265 266 267
}

/***********************************************************************
 *           AtlModuleGetClassObject              [ATL.@]
 */
HRESULT WINAPI AtlModuleRegisterTypeLib(_ATL_MODULEW *pm, LPCOLESTR lpszIndex)
{
268 269 270 271 272
    TRACE("%p %s\n", pm, debugstr_w(lpszIndex));

    if (!pm)
        return E_INVALIDARG;

273
    return AtlRegisterTypeLib(pm->m_hInstTypeLib, lpszIndex);
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
}

/***********************************************************************
 *           AtlModuleRevokeClassObjects          [ATL.@]
 */
HRESULT WINAPI AtlModuleRevokeClassObjects(_ATL_MODULEW *pm)
{
    FIXME("%p\n", pm);
    return E_FAIL;
}

/***********************************************************************
 *           AtlModuleUnregisterServer           [ATL.@]
 */
HRESULT WINAPI AtlModuleUnregisterServer(_ATL_MODULEW *pm, const CLSID *clsid)
{
    FIXME("%p %s\n", pm, debugstr_guid(clsid));
    return E_FAIL;
}
293

294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
/***********************************************************************
 *           AtlModuleRegisterWndClassInfoA           [ATL.@]
 *
 * See AtlModuleRegisterWndClassInfoW.
 */
ATOM WINAPI AtlModuleRegisterWndClassInfoA(_ATL_MODULEA *pm, _ATL_WNDCLASSINFOA *wci, WNDPROC *pProc)
{
    ATOM atom;

    FIXME("%p %p %p semi-stub\n", pm, wci, pProc);

    atom = wci->m_atom;
    if (!atom)
    {
        WNDCLASSEXA wc;

        TRACE("wci->m_wc.lpszClassName = %s\n", wci->m_wc.lpszClassName);

312 313 314
        if (wci->m_lpszOrigName)
            FIXME( "subclassing %s not implemented\n", debugstr_a(wci->m_lpszOrigName));

315 316
        if (!wci->m_wc.lpszClassName)
        {
317
            snprintf(wci->m_szAutoName, sizeof(wci->m_szAutoName), "ATL%08lx", (UINT_PTR)wci);
318 319 320 321 322 323
            TRACE("auto-generated class name %s\n", wci->m_szAutoName);
            wci->m_wc.lpszClassName = wci->m_szAutoName;
        }

        atom = GetClassInfoExA(pm->m_hInst, wci->m_wc.lpszClassName, &wc);
        if (!atom)
324 325 326 327
        {
            wci->m_wc.hInstance = pm->m_hInst;
            wci->m_wc.hCursor   = LoadCursorA( wci->m_bSystemCursor ? NULL : pm->m_hInst,
                                               wci->m_lpszCursorID );
328
            atom = RegisterClassExA(&wci->m_wc);
329
        }
330 331 332
        wci->pWndProc = wci->m_wc.lpfnWndProc;
        wci->m_atom = atom;
    }
333 334

    if (wci->m_lpszOrigName) *pProc = wci->pWndProc;
335 336 337 338 339

    TRACE("returning 0x%04x\n", atom);
    return atom;
}

340 341
/***********************************************************************
 *           AtlModuleRegisterWndClassInfoW           [ATL.@]
342 343 344 345 346 347 348 349 350 351 352 353
 *
 * PARAMS
 *  pm   [IO] Information about the module registering the window.
 *  wci  [IO] Information about the window being registered.
 *  pProc [O] Window procedure of the registered class.
 *
 * RETURNS
 *  Atom representing the registered class.
 *
 * NOTES
 *  Can be called multiple times without error, unlike RegisterClassEx().
 *
354 355
 *  If the class name is NULL, then a class with a name of "ATLxxxxxxxx" is
 *  registered, where the 'x's represent a unique value.
356
 *
357 358 359
 */
ATOM WINAPI AtlModuleRegisterWndClassInfoW(_ATL_MODULEW *pm, _ATL_WNDCLASSINFOW *wci, WNDPROC *pProc)
{
360 361 362 363 364 365 366 367 368 369 370
    ATOM atom;

    FIXME("%p %p %p semi-stub\n", pm, wci, pProc);

    atom = wci->m_atom;
    if (!atom)
    {
        WNDCLASSEXW wc;

        TRACE("wci->m_wc.lpszClassName = %s\n", debugstr_w(wci->m_wc.lpszClassName));

371 372 373
        if (wci->m_lpszOrigName)
            FIXME( "subclassing %s not implemented\n", debugstr_w(wci->m_lpszOrigName));

374 375
        if (!wci->m_wc.lpszClassName)
        {
376
            static const WCHAR szFormat[] = {'A','T','L','%','0','8','l','x',0};
377
            snprintfW(wci->m_szAutoName, ARRAY_SIZE(wci->m_szAutoName), szFormat, (UINT_PTR)wci);
378 379 380 381 382 383
            TRACE("auto-generated class name %s\n", debugstr_w(wci->m_szAutoName));
            wci->m_wc.lpszClassName = wci->m_szAutoName;
        }

        atom = GetClassInfoExW(pm->m_hInst, wci->m_wc.lpszClassName, &wc);
        if (!atom)
384 385 386 387
        {
            wci->m_wc.hInstance = pm->m_hInst;
            wci->m_wc.hCursor   = LoadCursorW( wci->m_bSystemCursor ? NULL : pm->m_hInst,
                                               wci->m_lpszCursorID );
388
            atom = RegisterClassExW(&wci->m_wc);
389
        }
390 391 392
        wci->pWndProc = wci->m_wc.lpfnWndProc;
        wci->m_atom = atom;
    }
393 394

    if (wci->m_lpszOrigName) *pProc = wci->pWndProc;
395 396 397

    TRACE("returning 0x%04x\n", atom);
    return atom;
398
}
399

400 401 402
/***********************************************************************
 *           AtlModuleAddCreateWndData          [ATL.@]
 */
403
void WINAPI AtlModuleAddCreateWndData(_ATL_MODULEW *pM, _AtlCreateWndData *pData, void* pvObject)
404 405 406 407 408
{
    TRACE("(%p, %p, %p)\n", pM, pData, pvObject);

    pData->m_pThis = pvObject;
    pData->m_dwThreadID = GetCurrentThreadId();
409 410

    EnterCriticalSection(&pM->m_csWindowCreate);
411 412
    pData->m_pNext = pM->m_pCreateWndList;
    pM->m_pCreateWndList = pData;
413
    LeaveCriticalSection(&pM->m_csWindowCreate);
414 415 416 417 418
}

/***********************************************************************
 *           AtlModuleExtractCreateWndData      [ATL.@]
 *
419
 *  NOTE: Tests show that this function extracts one of _AtlCreateWndData
420 421
 *        records from the current thread from a list
 *
422
 */
423
void* WINAPI AtlModuleExtractCreateWndData(_ATL_MODULEW *pM)
424 425
{
    _AtlCreateWndData **ppData;
426
    void *ret = NULL;
427 428 429

    TRACE("(%p)\n", pM);

430 431
    EnterCriticalSection(&pM->m_csWindowCreate);

432 433 434 435 436 437
    for(ppData = &pM->m_pCreateWndList; *ppData!=NULL; ppData = &(*ppData)->m_pNext)
    {
        if ((*ppData)->m_dwThreadID == GetCurrentThreadId())
        {
            _AtlCreateWndData *pData = *ppData;
            *ppData = pData->m_pNext;
438 439
            ret = pData->m_pThis;
            break;
440 441
        }
    }
442 443 444

    LeaveCriticalSection(&pM->m_csWindowCreate);
    return ret;
445
}
446

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
/***********************************************************************
 *           AtlModuleUpdateRegistryFromResourceD         [ATL.@]
 *
 */
HRESULT WINAPI AtlModuleUpdateRegistryFromResourceD(_ATL_MODULEW* pM, LPCOLESTR lpszRes,
        BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg)
{
    TRACE("(%p %s %d %p %p)\n", pM, debugstr_w(lpszRes), bRegister, pMapEntries, pReg);

    return AtlUpdateRegistryFromResourceD(pM->m_hInst, lpszRes, bRegister, pMapEntries, pReg);
}

static HRESULT WINAPI RegistrarCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppvObject)
{
    TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);

    if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
        *ppvObject = iface;
        IClassFactory_AddRef( iface );
        return S_OK;
    }

    return E_NOINTERFACE;
}

static ULONG WINAPI RegistrarCF_AddRef(IClassFactory *iface)
{
    return 2;
}

static ULONG WINAPI RegistrarCF_Release(IClassFactory *iface)
{
    return 1;
}

static HRESULT WINAPI RegistrarCF_CreateInstance(IClassFactory *iface, LPUNKNOWN pUnkOuter,
                                                REFIID riid, void **ppv)
{
    IRegistrar *registrar;
    HRESULT hres;

    TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);

    if(pUnkOuter) {
        *ppv = NULL;
        return CLASS_E_NOAGGREGATION;
    }

    hres = AtlCreateRegistrar(&registrar);
    if(FAILED(hres))
        return hres;

    hres = IRegistrar_QueryInterface(registrar, riid, ppv);
    IRegistrar_Release(registrar);
    return hres;
}

static HRESULT WINAPI RegistrarCF_LockServer(IClassFactory *iface, BOOL lock)
{
    TRACE("(%p)->(%x)\n", iface, lock);
    return S_OK;
}

static const IClassFactoryVtbl IRegistrarCFVtbl = {
    RegistrarCF_QueryInterface,
    RegistrarCF_AddRef,
    RegistrarCF_Release,
    RegistrarCF_CreateInstance,
    RegistrarCF_LockServer
};

static IClassFactory RegistrarCF = { &IRegistrarCFVtbl };

/**************************************************************
 * DllGetClassObject (ATL.2)
 */
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, LPVOID *ppvObject)
{
    TRACE("(%s %s %p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppvObject);

    if(IsEqualGUID(&CLSID_Registrar, clsid))
        return IClassFactory_QueryInterface( &RegistrarCF, riid, ppvObject );

    FIXME("Not supported class %s\n", debugstr_guid(clsid));
    return CLASS_E_CLASSNOTAVAILABLE;
}

/***********************************************************************
 *              DllRegisterServer (ATL.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
539
    return __wine_register_resources( atl_instance );
540 541 542 543 544 545 546
}

/***********************************************************************
 *              DllUnRegisterServer (ATL.@)
 */
HRESULT WINAPI DllUnregisterServer(void)
{
547
    return __wine_unregister_resources( atl_instance );
548 549 550 551 552 553 554 555 556
}

/***********************************************************************
 *              DllCanUnloadNow (ATL.@)
 */
HRESULT WINAPI DllCanUnloadNow(void)
{
    return S_FALSE;
}