- Cleaned up the implementation of shell folders and put them into
[wine] / dlls / shell32 / shellole.c
1 /*
2  *      handling of SHELL32.DLL OLE-Objects
3  *
4  *      Copyright 1997  Marcus Meissner
5  *      Copyright 1998  Juergen Schmied  <juergen.schmied@metronet.de>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "shellapi.h"
28 #include "shlobj.h"
29 #include "shlguid.h"
30 #include "winreg.h"
31 #include "winerror.h"
32
33 #include "undocshell.h"
34 #include "wine/unicode.h"
35 #include "shell32_main.h"
36
37 #include "wine/debug.h"
38 #include "shlwapi.h"
39 #include "winuser.h"
40 #include "debughlp.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(shell);
43
44 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id);
45 extern HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
46
47 const WCHAR sShell32[12] = {'S','H','E','L','L','3','2','.','D','L','L','\0'};
48 const WCHAR sOLE32[10] = {'O','L','E','3','2','.','D','L','L','\0'};
49
50 HINSTANCE hShellOle32 = 0;
51 /**************************************************************************
52  * Default ClassFactory types
53  */
54 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
55 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst);
56
57 /* this table contains all CLSID's of shell32 objects */
58 struct {
59         REFIID                  riid;
60         LPFNCREATEINSTANCE      lpfnCI;
61 } InterfaceTable[5] = {
62         {&CLSID_ShellFSFolder,  &IFSFolder_Constructor},
63         {&CLSID_MyComputer,     &ISF_MyComputer_Constructor},
64         {&CLSID_ShellDesktop,   &ISF_Desktop_Constructor},
65         {&CLSID_ShellLink,      &IShellLink_Constructor},
66         {NULL,NULL}
67 };
68
69 /*************************************************************************
70  * __CoCreateInstance [internal]
71  *
72  * NOTES
73  *   wraper for late bound call to OLE32.DLL
74  *
75  */
76 HRESULT (WINAPI *pCoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv) = NULL;
77
78 void * __GetExternalFunc(HMODULE * phModule, LPCWSTR szModuleName, LPCSTR szProcName)
79 {
80         if (!*phModule) *phModule = GetModuleHandleW(szModuleName);
81         if (!*phModule) *phModule = LoadLibraryW(szModuleName);
82         if (*phModule) return GetProcAddress(*phModule, szProcName);
83         return NULL;
84 }
85
86 HRESULT  __CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
87 {
88         if(!pCoCreateInstance) pCoCreateInstance = __GetExternalFunc(&hShellOle32, sOLE32, "CoCreateInstance");
89         if(!pCoCreateInstance) return E_FAIL;
90         return pCoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
91 }
92
93 /*************************************************************************
94  * SHCoCreateInstance [SHELL32.102]
95  *
96  * NOTES
97  *     exported by ordinal
98  */
99
100 /* FIXME: this should be SHLWAPI.24 since we can't yet import by ordinal */
101
102 DWORD WINAPI __SHGUIDToStringW (REFGUID guid, LPWSTR str)
103 {
104     WCHAR sFormat[52] = {'{','%','0','8','l','x','-','%','0','4',
105                          'x','-','%','0','4','x','-','%','0','2',
106                          'x','%','0','2','x','-','%','0','2','x',
107                          '%','0','2','x','%','0','2','x','%','0',
108                          '2','x','%','0','2','x','%','0','2','x',
109                          '}','\0'};
110
111     return wsprintfW ( str, sFormat,
112              guid->Data1, guid->Data2, guid->Data3,
113              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
114              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
115
116 }
117
118 /************************************************************************/
119
120 LRESULT WINAPI SHCoCreateInstance(
121         LPCSTR aclsid,
122         REFCLSID clsid,
123         LPUNKNOWN pUnkOuter,
124         REFIID refiid,
125         LPVOID *ppv)
126 {
127         DWORD   hres;
128         IID     iid;
129         CLSID * myclsid = (CLSID*)clsid;
130         WCHAR   sKeyName[MAX_PATH];
131         const   WCHAR sCLSID[7] = {'C','L','S','I','D','\\','\0'};
132         WCHAR   sClassID[60];
133         const WCHAR sInProcServer32[16] ={'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2','\0'};
134         const WCHAR sLoadWithoutCOM[15] ={'L','o','a','d','W','i','t','h','o','u','t','C','O','M','\0'};
135         WCHAR   sDllPath[MAX_PATH];
136         HKEY    hKey;
137         DWORD   dwSize;
138         BOOLEAN bLoadFromShell32 = FALSE;
139         BOOLEAN bLoadWithoutCOM = FALSE;
140         IClassFactory * pcf = NULL;
141
142         if(!ppv) return E_POINTER;
143         *ppv=NULL;
144
145         /* if the clsid is a string, convert it */
146         if (!clsid)
147         {
148           if (!aclsid) return REGDB_E_CLASSNOTREG;
149           SHCLSIDFromStringA(aclsid, &iid);
150           myclsid = &iid;
151         }
152
153         TRACE("(%p,%s,unk:%p,%s,%p)\n",
154                 aclsid,shdebugstr_guid(myclsid),pUnkOuter,shdebugstr_guid(refiid),ppv);
155
156         /* we look up the dll path in the registry */
157         __SHGUIDToStringW(myclsid, sClassID);
158         lstrcpyW(sKeyName, sCLSID);
159         lstrcatW(sKeyName, sClassID);
160         lstrcatW(sKeyName, sInProcServer32);
161
162         if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_CLASSES_ROOT, sKeyName, 0, KEY_READ, &hKey)) {
163             dwSize = sizeof(sDllPath);
164             SHQueryValueExW(hKey, NULL, 0,0, sDllPath, &dwSize );
165
166             /* if a special registry key is set we loading a shell extension without help of OLE32 */
167             bLoadWithoutCOM = (ERROR_SUCCESS == SHQueryValueExW(hKey, sLoadWithoutCOM, 0, 0, 0, 0));
168
169             /* if the com object is inside shell32 omit use of ole32 */
170             bLoadFromShell32 = (0==lstrcmpiW( PathFindFileNameW(sDllPath), sShell32));
171
172             RegCloseKey (hKey);
173         } else {
174             /* since we can't find it in the registry we try internally */
175             bLoadFromShell32 = TRUE;
176         }
177
178         TRACE("WithoutCom=%u FromShell=%u\n", bLoadWithoutCOM, bLoadFromShell32);
179
180         /* now we create a instance */
181         if (bLoadFromShell32) {
182             if (! SUCCEEDED(SHELL32_DllGetClassObject(myclsid, &IID_IClassFactory,(LPVOID*)&pcf))) {
183                 ERR("LoadFromShell failed for CLSID=%s\n", shdebugstr_guid(myclsid));
184             }
185         } else if (bLoadWithoutCOM) {
186
187             /* load a external dll without ole32 */
188             HANDLE hLibrary;
189             typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
190             DllGetClassObjectFunc DllGetClassObject;
191
192             if ((hLibrary = LoadLibraryExW(sDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) {
193                 ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(sDllPath));
194                 hres = E_ACCESSDENIED;
195                 goto end;
196             } else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject"))) {
197                 ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(sDllPath));
198                 FreeLibrary( hLibrary );
199                 hres = E_ACCESSDENIED;
200                 goto end;
201             } else if (! SUCCEEDED(hres = DllGetClassObject(myclsid, &IID_IClassFactory, (LPVOID*)&pcf))) {
202                     TRACE("GetClassObject failed 0x%08lx\n", hres);
203                     goto end;
204             }
205
206         } else {
207
208             /* load a external dll in the usual way */
209             hres = __CoCreateInstance(myclsid, pUnkOuter, CLSCTX_INPROC_SERVER, refiid, ppv);
210             goto end;
211         }
212
213         /* here we should have a ClassFactory */
214         if (!pcf) return E_ACCESSDENIED;
215
216         hres = IClassFactory_CreateInstance(pcf, pUnkOuter, refiid, ppv);
217         IClassFactory_Release(pcf);
218 end:
219         if(hres!=S_OK)
220         {
221           ERR("failed (0x%08lx) to create CLSID:%s IID:%s\n",
222               hres, shdebugstr_guid(myclsid), shdebugstr_guid(refiid));
223           ERR("class not found in registry\n");
224         }
225
226         TRACE("-- instance: %p\n",*ppv);
227         return hres;
228 }
229
230 /*************************************************************************
231  * DllGetClassObject   [SHELL32.128]
232  */
233 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
234 {
235         HRESULT hres = E_OUTOFMEMORY;
236         IClassFactory * pcf = NULL;
237         int i;
238
239         TRACE("CLSID:%s,IID:%s\n",shdebugstr_guid(rclsid),shdebugstr_guid(iid));
240
241         if (!ppv) return E_INVALIDARG;
242         *ppv = NULL;
243
244         /* search our internal interface table */
245         for(i=0;InterfaceTable[i].riid;i++) {
246             if(IsEqualIID(InterfaceTable[i].riid, rclsid)) {
247                 TRACE("index[%u]\n", i);
248                 pcf = IDefClF_fnConstructor(InterfaceTable[i].lpfnCI, NULL, NULL);
249             }
250         }
251
252         if (!pcf) {
253             FIXME("failed for CLSID=%s\n", shdebugstr_guid(rclsid));
254             return CLASS_E_CLASSNOTAVAILABLE;
255         }
256
257         hres = IClassFactory_QueryInterface(pcf, iid, ppv);
258         IClassFactory_Release(pcf);
259
260         TRACE("-- pointer to class factory: %p\n",*ppv);
261         return hres;
262 }
263
264 /*************************************************************************
265  * SHCLSIDFromString                            [SHELL32.147]
266  *
267  * NOTES
268  *     exported by ordinal
269  */
270 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id)
271 {
272     WCHAR buffer[40];
273     TRACE("(%p(%s) %p)\n", clsid, clsid, id);
274     if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
275         return CO_E_CLASSSTRING;
276     return CLSIDFromString( buffer, id );
277 }
278 DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
279 {
280         TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
281         return CLSIDFromString(clsid, id);
282 }
283 DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
284 {
285         if (SHELL_OsIsUnicode())
286           return SHCLSIDFromStringW (clsid, id);
287         return SHCLSIDFromStringA (clsid, id);
288 }
289
290 /*************************************************************************
291  *      Shell Memory Allocator
292  */
293
294 /* set the vtable later */
295 extern ICOM_VTABLE(IMalloc) VT_Shell_IMalloc32;
296
297 /* this is the static object instance */
298 typedef struct {
299         ICOM_VFIELD(IMalloc);
300         DWORD dummy;
301 } _ShellMalloc;
302
303 _ShellMalloc Shell_Malloc = { &VT_Shell_IMalloc32,1};
304
305 /* this is the global allocator of shell32 */
306 IMalloc * ShellTaskAllocator = NULL;
307
308 /******************************************************************************
309  *              IShellMalloc_QueryInterface        [VTABLE]
310  */
311 static HRESULT WINAPI IShellMalloc_fnQueryInterface(LPMALLOC iface, REFIID refiid, LPVOID *obj)
312 {
313         TRACE("(%s,%p)\n",shdebugstr_guid(refiid),obj);
314         if (IsEqualIID(refiid, &IID_IUnknown) || IsEqualIID(refiid, &IID_IMalloc)) {
315                 *obj = (LPMALLOC) &Shell_Malloc;
316                 return S_OK;
317         }
318         return E_NOINTERFACE;
319 }
320
321 /******************************************************************************
322  *              IShellMalloc_AddRefRelease        [VTABLE]
323  */
324 static ULONG WINAPI IShellMalloc_fnAddRefRelease(LPMALLOC iface)
325 {
326         return 1;
327 }
328
329 /******************************************************************************
330  *              IShellMalloc_Alloc [VTABLE]
331  */
332 static LPVOID WINAPI IShellMalloc_fnAlloc(LPMALLOC iface, DWORD cb)
333 {
334         LPVOID addr;
335
336         addr = (LPVOID) LocalAlloc(GMEM_ZEROINIT, cb);
337         TRACE("(%p,%ld);\n",addr,cb);
338         return addr;
339 }
340
341 /******************************************************************************
342  *              IShellMalloc_Realloc [VTABLE]
343  */
344 static LPVOID WINAPI IShellMalloc_fnRealloc(LPMALLOC iface, LPVOID pv, DWORD cb)
345 {
346         LPVOID addr;
347
348         if (pv) {
349                 if (cb) {
350                         addr = (LPVOID) LocalReAlloc((HANDLE) pv, cb, GMEM_ZEROINIT | GMEM_MOVEABLE);
351                 } else {
352                         LocalFree((HANDLE) pv);
353                         addr = NULL;
354                 }
355         } else {
356                 if (cb) {
357                         addr = (LPVOID) LocalAlloc(GMEM_ZEROINIT, cb);
358                 } else {
359                         addr = NULL;
360                 }
361         }
362
363         TRACE("(%p->%p,%ld)\n",pv,addr,cb);
364         return addr;
365 }
366
367 /******************************************************************************
368  *              IShellMalloc_Free [VTABLE]
369  */
370 static VOID WINAPI IShellMalloc_fnFree(LPMALLOC iface, LPVOID pv)
371 {
372         TRACE("(%p)\n",pv);
373         LocalFree((HANDLE) pv);
374 }
375
376 /******************************************************************************
377  *              IShellMalloc_GetSize [VTABLE]
378  */
379 static DWORD WINAPI IShellMalloc_fnGetSize(LPMALLOC iface, LPVOID pv)
380 {
381         DWORD cb = (DWORD) LocalSize((HANDLE)pv);
382         TRACE("(%p,%ld)\n", pv, cb);
383         return cb;
384 }
385
386 /******************************************************************************
387  *              IShellMalloc_DidAlloc [VTABLE]
388  */
389 static INT WINAPI IShellMalloc_fnDidAlloc(LPMALLOC iface, LPVOID pv)
390 {
391         TRACE("(%p)\n",pv);
392         return -1;
393 }
394
395 /******************************************************************************
396  *              IShellMalloc_HeapMinimize [VTABLE]
397  */
398 static VOID WINAPI IShellMalloc_fnHeapMinimize(LPMALLOC iface)
399 {
400         TRACE("()\n");
401 }
402
403 static ICOM_VTABLE(IMalloc) VT_Shell_IMalloc32 =
404 {
405         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
406         IShellMalloc_fnQueryInterface,
407         IShellMalloc_fnAddRefRelease,
408         IShellMalloc_fnAddRefRelease,
409         IShellMalloc_fnAlloc,
410         IShellMalloc_fnRealloc,
411         IShellMalloc_fnFree,
412         IShellMalloc_fnGetSize,
413         IShellMalloc_fnDidAlloc,
414         IShellMalloc_fnHeapMinimize
415 };
416
417 /*************************************************************************
418  *                       SHGetMalloc                    [SHELL32.@]
419  * returns the interface to shell malloc.
420  *
421  * NOTES
422  *  uses OLE32.CoGetMalloc if OLE32.DLL is already loaded.
423  *  if not it uses a internal implementations as fallback.
424  */
425 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal)
426 {
427         HRESULT (WINAPI *pCoGetMalloc)(DWORD,LPMALLOC *);
428         HMODULE hOle32;
429
430         TRACE("(%p)\n", lpmal);
431
432         if (!ShellTaskAllocator)
433         {
434                 hOle32 = GetModuleHandleA("OLE32.DLL");
435                 if(hOle32) {
436                         pCoGetMalloc = (void*) GetProcAddress(hOle32, "CoGetMalloc");
437                         if (pCoGetMalloc) pCoGetMalloc(MEMCTX_TASK, &ShellTaskAllocator);
438                         TRACE("got ole32 IMalloc\n");
439                 }
440                 if(!ShellTaskAllocator) {
441                         ShellTaskAllocator = (IMalloc* ) &Shell_Malloc;
442                         TRACE("use fallback allocator\n");
443                 }
444         }
445         *lpmal = ShellTaskAllocator;
446         return  S_OK;
447 }
448
449 /*************************************************************************
450  * SHAlloc                                      [SHELL32.196]
451  *
452  * NOTES
453  *     exported by ordinal
454  */
455 LPVOID WINAPI SHAlloc(DWORD len)
456 {
457         IMalloc * ppv;
458         LPBYTE ret;
459
460         if (!ShellTaskAllocator) SHGetMalloc(&ppv);
461
462         ret = (LPVOID) IMalloc_Alloc(ShellTaskAllocator, len);
463         TRACE("%lu bytes at %p\n",len, ret);
464         return (LPVOID)ret;
465 }
466
467 /*************************************************************************
468  * SHFree                                       [SHELL32.195]
469  *
470  * NOTES
471  *     exported by ordinal
472  */
473 void WINAPI SHFree(LPVOID pv)
474 {
475         IMalloc * ppv;
476
477         TRACE("%p\n",pv);
478         if (!ShellTaskAllocator) SHGetMalloc(&ppv);
479         IMalloc_Free(ShellTaskAllocator, pv);
480 }
481
482 /*************************************************************************
483  * SHGetDesktopFolder                   [SHELL32.@]
484  */
485 DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
486 {
487         HRESULT hres = S_OK;
488         TRACE("\n");
489
490         if(!psf) return E_INVALIDARG;
491         *psf = NULL;
492         hres = ISF_Desktop_Constructor(NULL, &IID_IShellFolder,(LPVOID*)psf);
493
494         TRACE("-- %p->(%p)\n",psf, *psf);
495         return hres;
496 }
497 /**************************************************************************
498  * Default ClassFactory Implementation
499  *
500  * SHCreateDefClassObject
501  *
502  * NOTES
503  *  helper function for dll's without a own classfactory
504  *  a generic classfactory is returned
505  *  when the CreateInstance of the cf is called the callback is executed
506  */
507
508 typedef struct
509 {
510     ICOM_VFIELD(IClassFactory);
511     DWORD                       ref;
512     CLSID                       *rclsid;
513     LPFNCREATEINSTANCE          lpfnCI;
514     const IID *                 riidInst;
515     ULONG *                     pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
516 } IDefClFImpl;
517
518 static ICOM_VTABLE(IClassFactory) dclfvt;
519
520 /**************************************************************************
521  *  IDefClF_fnConstructor
522  */
523
524 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst)
525 {
526         IDefClFImpl* lpclf;
527
528         lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
529         lpclf->ref = 1;
530         ICOM_VTBL(lpclf) = &dclfvt;
531         lpclf->lpfnCI = lpfnCI;
532         lpclf->pcRefDll = pcRefDll;
533
534         if (pcRefDll) InterlockedIncrement(pcRefDll);
535         lpclf->riidInst = riidInst;
536
537         TRACE("(%p)%s\n",lpclf, shdebugstr_guid(riidInst));
538         return (LPCLASSFACTORY)lpclf;
539 }
540 /**************************************************************************
541  *  IDefClF_fnQueryInterface
542  */
543 static HRESULT WINAPI IDefClF_fnQueryInterface(
544   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
545 {
546         ICOM_THIS(IDefClFImpl,iface);
547
548         TRACE("(%p)->(%s)\n",This,shdebugstr_guid(riid));
549
550         *ppvObj = NULL;
551
552         if(IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) {
553           *ppvObj = This;
554           InterlockedIncrement(&This->ref);
555           return S_OK;
556         }
557
558         TRACE("-- E_NOINTERFACE\n");
559         return E_NOINTERFACE;
560 }
561 /******************************************************************************
562  * IDefClF_fnAddRef
563  */
564 static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
565 {
566         ICOM_THIS(IDefClFImpl,iface);
567         TRACE("(%p)->(count=%lu)\n",This,This->ref);
568
569         return InterlockedIncrement(&This->ref);
570 }
571 /******************************************************************************
572  * IDefClF_fnRelease
573  */
574 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
575 {
576         ICOM_THIS(IDefClFImpl,iface);
577         TRACE("(%p)->(count=%lu)\n",This,This->ref);
578
579         if (!InterlockedDecrement(&This->ref))
580         {
581           if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
582
583           TRACE("-- destroying IClassFactory(%p)\n",This);
584           HeapFree(GetProcessHeap(),0,This);
585           return 0;
586         }
587         return This->ref;
588 }
589 /******************************************************************************
590  * IDefClF_fnCreateInstance
591  */
592 static HRESULT WINAPI IDefClF_fnCreateInstance(
593   LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
594 {
595         ICOM_THIS(IDefClFImpl,iface);
596
597         TRACE("%p->(%p,%s,%p)\n",This,pUnkOuter,shdebugstr_guid(riid),ppvObject);
598
599         *ppvObject = NULL;
600
601         if ( This->riidInst==NULL ||
602              IsEqualCLSID(riid, This->riidInst) ||
603              IsEqualCLSID(riid, &IID_IUnknown) )
604         {
605           return This->lpfnCI(pUnkOuter, riid, ppvObject);
606         }
607
608         ERR("unknown IID requested %s\n",shdebugstr_guid(riid));
609         return E_NOINTERFACE;
610 }
611 /******************************************************************************
612  * IDefClF_fnLockServer
613  */
614 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
615 {
616         ICOM_THIS(IDefClFImpl,iface);
617         TRACE("%p->(0x%x), not implemented\n",This, fLock);
618         return E_NOTIMPL;
619 }
620
621 static ICOM_VTABLE(IClassFactory) dclfvt =
622 {
623     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
624     IDefClF_fnQueryInterface,
625     IDefClF_fnAddRef,
626   IDefClF_fnRelease,
627   IDefClF_fnCreateInstance,
628   IDefClF_fnLockServer
629 };
630
631 /******************************************************************************
632  * SHCreateDefClassObject                       [SHELL32.70]
633  */
634 HRESULT WINAPI SHCreateDefClassObject(
635         REFIID  riid,
636         LPVOID* ppv,
637         LPFNCREATEINSTANCE lpfnCI,      /* [in] create instance callback entry */
638         LPDWORD pcRefDll,               /* [in/out] ref count of the dll */
639         REFIID  riidInst)               /* [in] optional interface to the instance */
640 {
641         IClassFactory * pcf;
642
643         TRACE("%s %p %p %p %s\n",
644               shdebugstr_guid(riid), ppv, lpfnCI, pcRefDll, shdebugstr_guid(riidInst));
645
646         if (! IsEqualCLSID(riid, &IID_IClassFactory) ) return E_NOINTERFACE;
647         if (! (pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst))) return E_OUTOFMEMORY;
648         *ppv = pcf;
649         return NOERROR;
650 }
651
652 /*************************************************************************
653  *  DragAcceptFiles             [SHELL32.54]
654  */
655 void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
656 {
657         LONG exstyle;
658
659         if( !IsWindow(hWnd) ) return;
660         exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
661         if (b)
662           exstyle |= WS_EX_ACCEPTFILES;
663         else
664           exstyle &= ~WS_EX_ACCEPTFILES;
665         SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
666 }
667
668 /*************************************************************************
669  * DragFinish           [SHELL32.80]
670  */
671 void WINAPI DragFinish(HDROP h)
672 {
673         TRACE("\n");
674         GlobalFree((HGLOBAL)h);
675 }
676
677 /*************************************************************************
678  * DragQueryPoint               [SHELL32.135]
679  */
680 BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
681 {
682         DROPFILES *lpDropFileStruct;
683         BOOL bRet;
684
685         TRACE("\n");
686
687         lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
688
689         *p = lpDropFileStruct->pt;
690         bRet = lpDropFileStruct->fNC;
691
692         GlobalUnlock(hDrop);
693         return bRet;
694 }
695
696 /*************************************************************************
697  *  DragQueryFile               [SHELL32.81]
698  *  DragQueryFileA              [SHELL32.82]
699  */
700 UINT WINAPI DragQueryFileA(
701         HDROP hDrop,
702         UINT lFile,
703         LPSTR lpszFile,
704         UINT lLength)
705 {
706         LPSTR lpDrop;
707         UINT i = 0;
708         DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
709
710         TRACE("(%08x, %x, %p, %u)\n",   hDrop,lFile,lpszFile,lLength);
711
712         if(!lpDropFileStruct) goto end;
713
714         lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
715
716         if(lpDropFileStruct->fWide == TRUE) {
717             LPWSTR lpszFileW = NULL;
718
719             if(lpszFile) {
720                 lpszFileW = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, lLength*sizeof(WCHAR));
721                 if(lpszFileW == NULL) {
722                     goto end;
723                 }
724             }
725             i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength);
726
727             if(lpszFileW) {
728                 WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL);
729                 HeapFree(GetProcessHeap(), 0, lpszFileW);
730             }
731             goto end;
732         }
733
734         while (i++ < lFile)
735         {
736           while (*lpDrop++); /* skip filename */
737           if (!*lpDrop)
738           {
739             i = (lFile == 0xFFFFFFFF) ? i : 0;
740             goto end;
741           }
742         }
743
744         i = strlen(lpDrop);
745         i++;
746         if (!lpszFile ) goto end;   /* needed buffer size */
747         i = (lLength > i) ? i : lLength;
748         lstrcpynA (lpszFile,  lpDrop,  i);
749 end:
750         GlobalUnlock(hDrop);
751         return i;
752 }
753
754 /*************************************************************************
755  *  DragQueryFileW              [SHELL32.133]
756  */
757 UINT WINAPI DragQueryFileW(
758         HDROP hDrop,
759         UINT lFile,
760         LPWSTR lpszwFile,
761         UINT lLength)
762 {
763         LPWSTR lpwDrop;
764         UINT i = 0;
765         DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
766
767         TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
768
769         if(!lpDropFileStruct) goto end;
770
771         lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles);
772
773         if(lpDropFileStruct->fWide == FALSE) {
774             LPSTR lpszFileA = NULL;
775
776             if(lpszwFile) {
777                 lpszFileA = (LPSTR) HeapAlloc(GetProcessHeap(), 0, lLength);
778                 if(lpszFileA == NULL) {
779                     goto end;
780                 }
781             }
782             i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength);
783
784             if(lpszFileA) {
785                 MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength);
786                 HeapFree(GetProcessHeap(), 0, lpszFileA);
787             }
788             goto end;
789         }
790
791         i = 0;
792         while (i++ < lFile)
793         {
794           while (*lpwDrop++); /* skip filename */
795           if (!*lpwDrop)
796           {
797             i = (lFile == 0xFFFFFFFF) ? i : 0;
798             goto end;
799           }
800         }
801
802         i = strlenW(lpwDrop);
803         i++;
804         if ( !lpszwFile) goto end;   /* needed buffer size */
805
806         i = (lLength > i) ? i : lLength;
807         lstrcpynW (lpszwFile, lpwDrop, i);
808 end:
809         GlobalUnlock(hDrop);
810         return i;
811 }