2 * Copyright 2012 Stefan Leichter
3 * Copyright 2012 Jacek Caban for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/debug.h"
25 #include "wine/unicode.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(atl100);
29 static inline void *heap_alloc(size_t len)
31 return HeapAlloc(GetProcessHeap(), 0, len);
34 static inline BOOL heap_free(void *mem)
36 return HeapFree(GetProcessHeap(), 0, mem);
39 static ICatRegister *catreg;
41 /***********************************************************************
42 * AtlAdvise [atl100.@]
44 HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID *iid, LPDWORD pdw)
46 FIXME("%p %p %p %p\n", pUnkCP, pUnk, iid, pdw);
50 /***********************************************************************
51 * AtlUnadvise [atl100.@]
53 HRESULT WINAPI AtlUnadvise(IUnknown *pUnkCP, const IID *iid, DWORD dw)
55 FIXME("%p %p %d\n", pUnkCP, iid, dw);
59 /***********************************************************************
60 * AtlFreeMarshalStream [atl100.@]
62 HRESULT WINAPI AtlFreeMarshalStream(IStream *stm)
68 /***********************************************************************
69 * AtlMarshalPtrInProc [atl100.@]
71 HRESULT WINAPI AtlMarshalPtrInProc(IUnknown *pUnk, const IID *iid, IStream **pstm)
73 FIXME("%p %p %p\n", pUnk, iid, pstm);
77 /***********************************************************************
78 * AtlUnmarshalPtr [atl100.@]
80 HRESULT WINAPI AtlUnmarshalPtr(IStream *stm, const IID *iid, IUnknown **ppUnk)
82 FIXME("%p %p %p\n", stm, iid, ppUnk);
86 /***********************************************************************
87 * AtlCreateTargetDC [atl100.@]
89 HDC WINAPI AtlCreateTargetDC( HDC hdc, DVTARGETDEVICE *dv )
91 static const WCHAR displayW[] = {'d','i','s','p','l','a','y',0};
92 const WCHAR *driver = NULL, *device = NULL, *port = NULL;
93 DEVMODEW *devmode = NULL;
95 TRACE( "(%p, %p)\n", hdc, dv );
99 if (dv->tdDriverNameOffset) driver = (WCHAR *)((char *)dv + dv->tdDriverNameOffset);
100 if (dv->tdDeviceNameOffset) device = (WCHAR *)((char *)dv + dv->tdDeviceNameOffset);
101 if (dv->tdPortNameOffset) port = (WCHAR *)((char *)dv + dv->tdPortNameOffset);
102 if (dv->tdExtDevmodeOffset) devmode = (DEVMODEW *)((char *)dv + dv->tdExtDevmodeOffset);
109 return CreateDCW( driver, device, port, devmode );
112 /***********************************************************************
113 * AtlHiMetricToPixel [atl100.@]
115 void WINAPI AtlHiMetricToPixel(const SIZEL* lpHiMetric, SIZEL* lpPix)
117 HDC dc = GetDC(NULL);
118 lpPix->cx = lpHiMetric->cx * GetDeviceCaps( dc, LOGPIXELSX ) / 100;
119 lpPix->cy = lpHiMetric->cy * GetDeviceCaps( dc, LOGPIXELSY ) / 100;
120 ReleaseDC( NULL, dc );
123 /***********************************************************************
124 * AtlPixelToHiMetric [atl100.@]
126 void WINAPI AtlPixelToHiMetric(const SIZEL* lpPix, SIZEL* lpHiMetric)
128 HDC dc = GetDC(NULL);
129 lpHiMetric->cx = 100 * lpPix->cx / GetDeviceCaps( dc, LOGPIXELSX );
130 lpHiMetric->cy = 100 * lpPix->cy / GetDeviceCaps( dc, LOGPIXELSY );
131 ReleaseDC( NULL, dc );
134 /***********************************************************************
135 * AtlComPtrAssign [atl100.@]
137 IUnknown* WINAPI AtlComPtrAssign(IUnknown** pp, IUnknown *p)
139 TRACE("(%p %p)\n", pp, p);
141 if (p) IUnknown_AddRef(p);
142 if (*pp) IUnknown_Release(*pp);
147 /***********************************************************************
148 * AtlComQIPtrAssign [atl100.@]
150 IUnknown* WINAPI AtlComQIPtrAssign(IUnknown** pp, IUnknown *p, REFIID riid)
152 IUnknown *new_p = NULL;
154 TRACE("(%p %p %s)\n", pp, p, debugstr_guid(riid));
156 if (p) IUnknown_QueryInterface(p, riid, (void **)&new_p);
157 if (*pp) IUnknown_Release(*pp);
162 /***********************************************************************
163 * AtlInternalQueryInterface [atl100.@]
165 HRESULT WINAPI AtlInternalQueryInterface(void* this, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
168 HRESULT rc = E_NOINTERFACE;
169 TRACE("(%p, %p, %s, %p)\n",this, pEntries, debugstr_guid(iid), ppvObject);
171 if (IsEqualGUID(iid,&IID_IUnknown))
173 TRACE("Returning IUnknown\n");
174 *ppvObject = ((LPSTR)this+pEntries[0].dw);
175 IUnknown_AddRef((IUnknown*)*ppvObject);
179 while (pEntries[i].pFunc != 0)
181 TRACE("Trying entry %i (%s %i %p)\n",i,debugstr_guid(pEntries[i].piid),
182 pEntries[i].dw, pEntries[i].pFunc);
184 if (!pEntries[i].piid || IsEqualGUID(iid,pEntries[i].piid))
187 if (pEntries[i].pFunc == (_ATL_CREATORARGFUNC*)1)
190 *ppvObject = ((LPSTR)this+pEntries[i].dw);
191 IUnknown_AddRef((IUnknown*)*ppvObject);
197 rc = pEntries[i].pFunc(this, iid, ppvObject, pEntries[i].dw);
198 if(rc==S_OK || pEntries[i].piid)
204 TRACE("Done returning (0x%x)\n",rc);
208 /* FIXME: should be in a header file */
209 typedef struct ATL_PROPMAP_ENTRY
213 const CLSID* pclsidPropPage;
214 const IID* piidDispatch;
220 /***********************************************************************
221 * AtlIPersistStreamInit_Load [atl100.@]
223 HRESULT WINAPI AtlIPersistStreamInit_Load( LPSTREAM pStm, ATL_PROPMAP_ENTRY *pMap,
224 void *pThis, IUnknown *pUnk)
226 FIXME("(%p, %p, %p, %p)\n", pStm, pMap, pThis, pUnk);
231 /***********************************************************************
232 * AtlIPersistStreamInit_Save [atl100.@]
234 HRESULT WINAPI AtlIPersistStreamInit_Save(LPSTREAM pStm, BOOL fClearDirty,
235 ATL_PROPMAP_ENTRY *pMap, void *pThis,
238 FIXME("(%p, %d, %p, %p, %p)\n", pStm, fClearDirty, pMap, pThis, pUnk);
243 /***********************************************************************
244 * AtlModuleAddTermFunc [atl100.@]
246 HRESULT WINAPI AtlModuleAddTermFunc(_ATL_MODULE *pM, _ATL_TERMFUNC *pFunc, DWORD_PTR dw)
248 _ATL_TERMFUNC_ELEM *termfunc_elem;
250 TRACE("(%p %p %ld)\n", pM, pFunc, dw);
252 termfunc_elem = HeapAlloc(GetProcessHeap(), 0, sizeof(_ATL_TERMFUNC_ELEM));
253 termfunc_elem->pFunc = pFunc;
254 termfunc_elem->dw = dw;
255 termfunc_elem->pNext = pM->m_pTermFuncs;
257 pM->m_pTermFuncs = termfunc_elem;
262 /***********************************************************************
263 * AtlCallTermFunc [atl100.@]
265 void WINAPI AtlCallTermFunc(_ATL_MODULE *pM)
267 _ATL_TERMFUNC_ELEM *iter = pM->m_pTermFuncs, *tmp;
272 iter->pFunc(iter->dw);
275 HeapFree(GetProcessHeap(), 0, tmp);
278 pM->m_pTermFuncs = NULL;
281 /***********************************************************************
282 * AtlLoadTypeLib [atl100.56]
284 HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex,
285 BSTR *pbstrPath, ITypeLib **ppTypeLib)
287 size_t path_len, index_len;
288 ITypeLib *typelib = NULL;
292 static const WCHAR tlb_extW[] = {'.','t','l','b',0};
294 TRACE("(%p %s %p %p)\n", inst, debugstr_w(lpszIndex), pbstrPath, ppTypeLib);
296 index_len = lpszIndex ? strlenW(lpszIndex) : 0;
297 path = heap_alloc((MAX_PATH+index_len)*sizeof(WCHAR) + sizeof(tlb_extW));
299 return E_OUTOFMEMORY;
301 path_len = GetModuleFileNameW(inst, path, MAX_PATH);
303 return HRESULT_FROM_WIN32(GetLastError());
306 memcpy(path+path_len, lpszIndex, (index_len+1)*sizeof(WCHAR));
308 hres = LoadTypeLib(path, &typelib);
312 for(ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--);
315 memcpy(ptr, tlb_extW, sizeof(tlb_extW));
316 hres = LoadTypeLib(path, &typelib);
319 if(SUCCEEDED(hres)) {
320 *pbstrPath = SysAllocString(path);
322 ITypeLib_Release(typelib);
323 hres = E_OUTOFMEMORY;
331 *ppTypeLib = typelib;
335 /***********************************************************************
336 * AtlWinModuleInit [atl100.65]
338 HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *winmod)
340 TRACE("(%p\n", winmod);
342 if(winmod->cbSize != sizeof(*winmod))
345 InitializeCriticalSection(&winmod->m_csWindowCreate);
346 winmod->m_pCreateWndList = NULL;
350 /***********************************************************************
351 * AtlWinModuleAddCreateWndData [atl100.43]
353 void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pM, _AtlCreateWndData *pData, void *pvObject)
355 TRACE("(%p, %p, %p)\n", pM, pData, pvObject);
357 pData->m_pThis = pvObject;
358 pData->m_dwThreadID = GetCurrentThreadId();
360 EnterCriticalSection(&pM->m_csWindowCreate);
361 pData->m_pNext = pM->m_pCreateWndList;
362 pM->m_pCreateWndList = pData;
363 LeaveCriticalSection(&pM->m_csWindowCreate);
366 /***********************************************************************
367 * AtlWinModuleExtractCreateWndData [atl100.44]
369 void* WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *winmod)
371 _AtlCreateWndData *iter, *prev = NULL;
374 TRACE("(%p)\n", winmod);
376 thread_id = GetCurrentThreadId();
378 EnterCriticalSection(&winmod->m_csWindowCreate);
380 for(iter = winmod->m_pCreateWndList; iter && iter->m_dwThreadID != thread_id; iter = iter->m_pNext)
384 prev->m_pNext = iter->m_pNext;
386 winmod->m_pCreateWndList = iter->m_pNext;
389 LeaveCriticalSection(&winmod->m_csWindowCreate);
391 return iter ? iter->m_pThis : NULL;
394 /***********************************************************************
395 * AtlComModuleGetClassObject [atl100.15]
397 HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, REFIID riid, void **ppv)
399 _ATL_OBJMAP_ENTRY **iter;
402 TRACE("(%p %s %s %p)\n", pm, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
407 for(iter = pm->m_ppAutoObjMapFirst; iter < pm->m_ppAutoObjMapLast; iter++) {
408 if(IsEqualCLSID((*iter)->pclsid, rclsid) && (*iter)->pfnGetClassObject) {
410 hres = (*iter)->pfnGetClassObject((*iter)->pfnCreateInstance, &IID_IUnknown, (void**)&(*iter)->pCF);
412 hres = IUnknown_QueryInterface((*iter)->pCF, riid, ppv);
413 TRACE("returning %p (%08x)\n", *ppv, hres);
418 WARN("Class %s not found\n", debugstr_guid(rclsid));
419 return CLASS_E_CLASSNOTAVAILABLE;
422 /***********************************************************************
423 * AtlRegisterClassCategoriesHelper [atl100.49]
425 HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg)
427 const struct _ATL_CATMAP_ENTRY *iter;
430 TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg);
436 ICatRegister *new_catreg;
438 hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
439 &IID_ICatRegister, (void**)&new_catreg);
443 if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL))
444 ICatRegister_Release(new_catreg);
447 for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) {
448 CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */
450 if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) {
452 hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid);
454 hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid);
457 hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid);
459 hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid);
466 WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6;
468 static const WCHAR implemented_catW[] =
469 {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
470 static const WCHAR required_catW[] =
471 {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0};
473 ptr += StringFromGUID2(clsid, ptr, 64)-1;
476 memcpy(ptr, implemented_catW, sizeof(implemented_catW));
477 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
479 memcpy(ptr, required_catW, sizeof(required_catW));
480 RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path);
486 /***********************************************************************
487 * AtlGetVersion [atl100.@]
489 DWORD WINAPI AtlGetVersion(void *pReserved)
494 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
496 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
499 case DLL_PROCESS_ATTACH:
500 DisableThreadLibraryCalls(hinstDLL);
502 case DLL_PROCESS_DETACH:
504 ICatRegister_Release(catreg);