source: trunk/src/shell32/shellole.c@ 8552

Last change on this file since 8552 was 8552, checked in by sandervl, 23 years ago

Added automatic asii/unicode conversion to DragQueryFileA/W

File size: 16.8 KB
Line 
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 */
8
9#include <stdlib.h>
10#include <string.h>
11
12#include "shlobj.h"
13#include "shellapi.h"
14#include "shlguid.h"
15#include "winreg.h"
16#include "wine/unicode.h"
17#include "winerror.h"
18#include "debugtools.h"
19
20#include "shell32_main.h"
21
22DEFAULT_DEBUG_CHANNEL(shell);
23
24DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id);
25extern IShellFolder * IShellFolder_Constructor(
26 IShellFolder * psf,
27 LPITEMIDLIST pidl);
28extern HRESULT IFSFolder_Constructor(
29 IUnknown * pUnkOuter,
30 REFIID riid,
31 LPVOID * ppv);
32
33/*************************************************************************
34 * SHCoCreateInstance [SHELL32.102]
35 *
36 * NOTES
37 * exported by ordinal
38 */
39LRESULT WINAPI SHCoCreateInstance(
40 LPSTR aclsid,
41 REFCLSID clsid,
42 LPUNKNOWN unknownouter,
43 REFIID refiid,
44 LPVOID *ppv)
45{
46 DWORD hres;
47 IID iid;
48 CLSID * myclsid = (CLSID*)clsid;
49
50 if (!clsid)
51 {
52 if (!aclsid) return REGDB_E_CLASSNOTREG;
53 SHCLSIDFromStringA(aclsid, &iid);
54 myclsid = &iid;
55 }
56
57 TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
58 aclsid,debugstr_guid(myclsid),unknownouter,debugstr_guid(refiid),ppv);
59
60 if IsEqualCLSID(myclsid, &CLSID_ShellFSFolder)
61 {
62 hres = IFSFolder_Constructor(unknownouter, refiid, ppv);
63 }
64 else
65 {
66 CoInitialize(NULL);
67 hres = CoCreateInstance(myclsid, unknownouter, CLSCTX_INPROC_SERVER, refiid, ppv);
68 }
69
70 if(hres!=S_OK)
71 {
72 ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
73 hres, debugstr_guid(myclsid), debugstr_guid(refiid));
74 ERR("class not found in registry\n");
75 }
76
77 TRACE("-- instance: %p\n",*ppv);
78 return hres;
79}
80
81/*************************************************************************
82 * SHELL32_DllGetClassObject [SHELL32.128]
83 */
84HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
85{ HRESULT hres = E_OUTOFMEMORY;
86 LPCLASSFACTORY lpclf;
87
88 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
89
90 *ppv = NULL;
91
92 if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)||
93 IsEqualCLSID(rclsid, &CLSID_ShellLink))
94 {
95 lpclf = IClassFactory_Constructor( rclsid );
96
97 if(lpclf)
98 {
99 hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
100 IClassFactory_Release(lpclf);
101 }
102 }
103 else
104 {
105 WARN("-- CLSID not found\n");
106 hres = CLASS_E_CLASSNOTAVAILABLE;
107 }
108 TRACE("-- pointer to class factory: %p\n",*ppv);
109 return hres;
110}
111
112/*************************************************************************
113 * SHCLSIDFromString [SHELL32.147]
114 *
115 * NOTES
116 * exported by ordinal
117 */
118DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id)
119{
120 WCHAR buffer[40];
121 TRACE("(%p(%s) %p)\n", clsid, clsid, id);
122 if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
123 return CO_E_CLASSSTRING;
124 return CLSIDFromString( buffer, id );
125}
126DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
127{
128 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
129 return CLSIDFromString(clsid, id);
130}
131DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
132{
133 if (SHELL_OsIsUnicode())
134 return SHCLSIDFromStringW (clsid, id);
135 return SHCLSIDFromStringA (clsid, id);
136}
137
138/*************************************************************************
139 * SHGetMalloc [SHELL32.220]
140 * returns the interface to shell malloc.
141 *
142 * [SDK header win95/shlobj.h:
143 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
144 * ]
145 * What we are currently doing is not very wrong, since we always use the same
146 * heap (ProcessHeap).
147 */
148DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal)
149{
150 TRACE("(%p)\n", lpmal);
151 return CoGetMalloc(MEMCTX_TASK, lpmal);
152}
153
154/*************************************************************************
155 * SHGetDesktopFolder [SHELL32.216]
156 */
157LPSHELLFOLDER pdesktopfolder=NULL;
158
159DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
160{
161 HRESULT hres = S_OK;
162 LPCLASSFACTORY lpclf;
163 TRACE("%p->(%p)\n",psf,*psf);
164
165 *psf=NULL;
166
167 if (!pdesktopfolder)
168 {
169 lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
170 if(lpclf)
171 {
172 hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
173 IClassFactory_Release(lpclf);
174 }
175 }
176
177 if (pdesktopfolder)
178 {
179 /* even if we create the folder, add a ref so the application canŽt destroy the folder*/
180 IShellFolder_AddRef(pdesktopfolder);
181 *psf = pdesktopfolder;
182 }
183
184 TRACE("-- %p->(%p)\n",psf, *psf);
185 return hres;
186}
187
188/**************************************************************************
189* IClassFactory Implementation
190*/
191
192typedef struct
193{
194 /* IUnknown fields */
195 ICOM_VFIELD(IClassFactory);
196 DWORD ref;
197 CLSID *rclsid;
198} IClassFactoryImpl;
199
200static ICOM_VTABLE(IClassFactory) clfvt;
201
202/**************************************************************************
203 * IClassFactory_Constructor
204 */
205
206LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
207{
208 IClassFactoryImpl* lpclf;
209
210 lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
211 lpclf->ref = 1;
212 ICOM_VTBL(lpclf) = &clfvt;
213 lpclf->rclsid = (CLSID*)rclsid;
214
215 TRACE("(%p)->()\n",lpclf);
216 InterlockedIncrement(&shell32_ObjCount);
217 return (LPCLASSFACTORY)lpclf;
218}
219/**************************************************************************
220 * IClassFactory_QueryInterface
221 */
222static HRESULT WINAPI IClassFactory_fnQueryInterface(
223 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
224{
225 ICOM_THIS(IClassFactoryImpl,iface);
226 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
227
228 *ppvObj = NULL;
229
230 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
231 { *ppvObj = This;
232 }
233 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
234 { *ppvObj = (IClassFactory*)This;
235 }
236
237 if(*ppvObj)
238 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
239 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
240 return S_OK;
241 }
242 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
243 return E_NOINTERFACE;
244}
245/******************************************************************************
246 * IClassFactory_AddRef
247 */
248static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
249{
250 ICOM_THIS(IClassFactoryImpl,iface);
251 TRACE("(%p)->(count=%lu)\n",This,This->ref);
252
253 InterlockedIncrement(&shell32_ObjCount);
254 return InterlockedIncrement(&This->ref);
255}
256/******************************************************************************
257 * IClassFactory_Release
258 */
259static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
260{
261 ICOM_THIS(IClassFactoryImpl,iface);
262 TRACE("(%p)->(count=%lu)\n",This,This->ref);
263
264 InterlockedDecrement(&shell32_ObjCount);
265 if (!InterlockedDecrement(&This->ref))
266 {
267 TRACE("-- destroying IClassFactory(%p)\n",This);
268 HeapFree(GetProcessHeap(),0,This);
269 return 0;
270 }
271 return This->ref;
272}
273/******************************************************************************
274 * IClassFactory_CreateInstance
275 */
276static HRESULT WINAPI IClassFactory_fnCreateInstance(
277 LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
278{
279 ICOM_THIS(IClassFactoryImpl,iface);
280 IUnknown *pObj = NULL;
281 HRESULT hres;
282
283 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,debugstr_guid(riid),ppObject);
284
285 *ppObject = NULL;
286
287 if(pUnknown)
288 {
289 return(CLASS_E_NOAGGREGATION);
290 }
291
292 if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
293 {
294 pObj = (IUnknown *)ISF_Desktop_Constructor();
295 }
296 else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
297 {
298 pObj = (IUnknown *)IShellLink_Constructor(FALSE);
299 }
300 else
301 {
302 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
303 return(E_NOINTERFACE);
304 }
305
306 if (!pObj)
307 {
308 return(E_OUTOFMEMORY);
309 }
310
311 hres = IUnknown_QueryInterface(pObj,riid, ppObject);
312 IUnknown_Release(pObj);
313
314 TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
315
316 return hres;
317}
318/******************************************************************************
319 * IClassFactory_LockServer
320 */
321static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
322{
323 ICOM_THIS(IClassFactoryImpl,iface);
324 TRACE("%p->(0x%x), not implemented\n",This, fLock);
325 return E_NOTIMPL;
326}
327
328static ICOM_VTABLE(IClassFactory) clfvt =
329{
330 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
331 IClassFactory_fnQueryInterface,
332 IClassFactory_fnAddRef,
333 IClassFactory_fnRelease,
334 IClassFactory_fnCreateInstance,
335 IClassFactory_fnLockServer
336};
337
338/**************************************************************************
339 * Default ClassFactory Implementation
340 *
341 * SHCreateDefClassObject
342 *
343 * NOTES
344 * helper function for dll's without a own classfactory
345 * a generic classfactory is returned
346 * when the CreateInstance of the cf is called the callback is executed
347 */
348#ifdef __WIN32OS2__
349typedef HRESULT (* CALLBACK LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
350#else
351typedef HRESULT CALLBACK (*LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
352#endif
353
354typedef struct
355{
356 ICOM_VFIELD(IClassFactory);
357 DWORD ref;
358 CLSID *rclsid;
359 LPFNCREATEINSTANCE lpfnCI;
360 const IID * riidInst;
361 ULONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
362} IDefClFImpl;
363
364static ICOM_VTABLE(IClassFactory) dclfvt;
365
366/**************************************************************************
367 * IDefClF_fnConstructor
368 */
369
370IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst)
371{
372 IDefClFImpl* lpclf;
373
374 lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
375 lpclf->ref = 1;
376 ICOM_VTBL(lpclf) = &dclfvt;
377 lpclf->lpfnCI = lpfnCI;
378 lpclf->pcRefDll = pcRefDll;
379
380 if (pcRefDll) InterlockedIncrement(pcRefDll);
381 lpclf->riidInst = riidInst;
382
383 TRACE("(%p)\n\tIID:\t%s\n",lpclf, debugstr_guid(riidInst));
384 InterlockedIncrement(&shell32_ObjCount);
385 return (LPCLASSFACTORY)lpclf;
386}
387/**************************************************************************
388 * IDefClF_fnQueryInterface
389 */
390static HRESULT WINAPI IDefClF_fnQueryInterface(
391 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
392{
393 ICOM_THIS(IDefClFImpl,iface);
394
395 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
396
397 *ppvObj = NULL;
398
399 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
400 { *ppvObj = This;
401 }
402 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
403 { *ppvObj = (IClassFactory*)This;
404 }
405
406 if(*ppvObj)
407 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
408 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
409 return S_OK;
410 }
411 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
412 return E_NOINTERFACE;
413}
414/******************************************************************************
415 * IDefClF_fnAddRef
416 */
417static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
418{
419 ICOM_THIS(IDefClFImpl,iface);
420 TRACE("(%p)->(count=%lu)\n",This,This->ref);
421
422 InterlockedIncrement(&shell32_ObjCount);
423 return InterlockedIncrement(&This->ref);
424}
425/******************************************************************************
426 * IDefClF_fnRelease
427 */
428static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
429{
430 ICOM_THIS(IDefClFImpl,iface);
431 TRACE("(%p)->(count=%lu)\n",This,This->ref);
432
433 InterlockedDecrement(&shell32_ObjCount);
434
435 if (!InterlockedDecrement(&This->ref))
436 {
437 if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
438
439 TRACE("-- destroying IClassFactory(%p)\n",This);
440 HeapFree(GetProcessHeap(),0,This);
441 return 0;
442 }
443 return This->ref;
444}
445/******************************************************************************
446 * IDefClF_fnCreateInstance
447 */
448static HRESULT WINAPI IDefClF_fnCreateInstance(
449 LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
450{
451 ICOM_THIS(IDefClFImpl,iface);
452
453 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,debugstr_guid(riid),ppvObject);
454
455 *ppvObject = NULL;
456
457 if(pUnkOuter)
458 return(CLASS_E_NOAGGREGATION);
459
460 if ( This->riidInst==NULL ||
461 IsEqualCLSID(riid, This->riidInst) ||
462 IsEqualCLSID(riid, &IID_IUnknown) )
463 {
464 return This->lpfnCI(pUnkOuter, riid, ppvObject);
465 }
466
467 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
468 return E_NOINTERFACE;
469}
470/******************************************************************************
471 * IDefClF_fnLockServer
472 */
473static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
474{
475 ICOM_THIS(IDefClFImpl,iface);
476 TRACE("%p->(0x%x), not implemented\n",This, fLock);
477 return E_NOTIMPL;
478}
479
480static ICOM_VTABLE(IClassFactory) dclfvt =
481{
482 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
483 IDefClF_fnQueryInterface,
484 IDefClF_fnAddRef,
485 IDefClF_fnRelease,
486 IDefClF_fnCreateInstance,
487 IDefClF_fnLockServer
488};
489
490/******************************************************************************
491 * SHCreateDefClassObject [SHELL32.70]
492 */
493HRESULT WINAPI SHCreateDefClassObject(
494 REFIID riid,
495 LPVOID* ppv,
496 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */
497 PLONG pcRefDll, /* [in/out] ref count of the dll */
498 REFIID riidInst) /* [in] optional interface to the instance */
499{
500 TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
501 debugstr_guid(riid), ppv, lpfnCI, pcRefDll, debugstr_guid(riidInst));
502
503 if ( IsEqualCLSID(riid, &IID_IClassFactory) )
504 {
505 IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
506 if (pcf)
507 {
508 *ppv = pcf;
509 return NOERROR;
510 }
511 return E_OUTOFMEMORY;
512 }
513 return E_NOINTERFACE;
514}
515
516/*************************************************************************
517 * DragAcceptFiles [SHELL32.54]
518 */
519void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
520{
521 LONG exstyle;
522
523 if( !IsWindow(hWnd) ) return;
524 exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
525 if (b)
526 exstyle |= WS_EX_ACCEPTFILES;
527 else
528 exstyle &= ~WS_EX_ACCEPTFILES;
529 SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
530}
531
532/*************************************************************************
533 * DragFinish [SHELL32.80]
534 */
535void WINAPI DragFinish(HDROP h)
536{
537 TRACE("\n");
538 GlobalFree((HGLOBAL)h);
539}
540
541/*************************************************************************
542 * DragQueryPoint [SHELL32.135]
543 */
544BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
545{
546 DROPFILES *lpDropFileStruct;
547 BOOL bRet;
548
549 TRACE("\n");
550
551 lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
552
553 *p = lpDropFileStruct->pt;
554 bRet = lpDropFileStruct->fNC;
555
556 GlobalUnlock(hDrop);
557 return bRet;
558}
559
560/*************************************************************************
561 * DragQueryFileA [SHELL32.81] [shell32.82]
562 */
563UINT WINAPI DragQueryFileA(
564 HDROP hDrop,
565 UINT lFile,
566 LPSTR lpszFile,
567 UINT lLength)
568{
569 LPSTR lpDrop;
570 UINT i = 0;
571 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
572
573 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
574
575 if(!lpDropFileStruct) goto end;
576
577 lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
578
579 if(lpDropFileStruct->fWide == TRUE) {
580 LPWSTR lpszFileW = NULL;
581
582 if(lpszFile) {
583 lpszFileW = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, lLength*sizeof(WCHAR));
584 if(lpszFileW == NULL) {
585 goto end;
586 }
587 }
588 i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength);
589
590 if(lpszFileW) {
591 WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL);
592 HeapFree(GetProcessHeap(), 0, lpszFileW);
593 }
594 goto end;
595 }
596
597 while (i++ < lFile)
598 {
599 while (*lpDrop++); /* skip filename */
600 if (!*lpDrop)
601 {
602 i = (lFile == 0xFFFFFFFF) ? i : 0;
603 goto end;
604 }
605 }
606
607 i = strlen(lpDrop);
608 i++;
609 if (!lpszFile ) goto end; /* needed buffer size */
610 i = (lLength > i) ? i : lLength;
611 lstrcpynA (lpszFile, lpDrop, i);
612end:
613 GlobalUnlock(hDrop);
614 return i;
615}
616
617/*************************************************************************
618 * DragQueryFileW [shell32.133]
619 */
620UINT WINAPI DragQueryFileW(
621 HDROP hDrop,
622 UINT lFile,
623 LPWSTR lpszwFile,
624 UINT lLength)
625{
626 LPWSTR lpwDrop;
627 UINT i = 0;
628 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
629
630 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
631
632 if(!lpDropFileStruct) goto end;
633
634 if(lpDropFileStruct->fWide == FALSE) {
635 LPSTR lpszFileA = NULL;
636
637 if(lpszwFile) {
638 lpszFileA = (LPSTR) HeapAlloc(GetProcessHeap(), 0, lLength);
639 if(lpszFileA == NULL) {
640 goto end;
641 }
642 }
643 i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength);
644
645 if(lpszFileA) {
646 MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength);
647 HeapFree(GetProcessHeap(), 0, lpszFileA);
648 }
649 goto end;
650 }
651
652 lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles);
653
654 i = 0;
655 while (i++ < lFile)
656 {
657 while (*lpwDrop++); /* skip filename */
658 if (!*lpwDrop)
659 {
660 i = (lFile == 0xFFFFFFFF) ? i : 0;
661 goto end;
662 }
663 }
664
665 i = strlenW(lpwDrop);
666 i++;
667 if ( !lpszwFile) goto end; /* needed buffer size */
668
669 i = (lLength > i) ? i : lLength;
670 lstrcpynW (lpszwFile, lpwDrop, i);
671end:
672 GlobalUnlock(hDrop);
673 return i;
674}
Note: See TracBrowser for help on using the repository browser.