Handle ascii & unicode drag and drop structures in DragQueryFileA &
[wine/dcerpc.git] / dlls / shell32 / shellole.c
blobeec9f0671d3f8d07133e19425a25e773a13c48c3
1 /*
2 * handling of SHELL32.DLL OLE-Objects
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
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.
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.
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
22 #include "config.h"
24 #include <stdlib.h>
25 #include <string.h>
27 #include "shellapi.h"
28 #include "shlobj.h"
29 #include "shlguid.h"
30 #include "winreg.h"
31 #include "winerror.h"
33 #include "undocshell.h"
34 #include "wine/unicode.h"
35 #include "shell32_main.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id);
42 extern IShellFolder * IShellFolder_Constructor(
43 IShellFolder * psf,
44 LPITEMIDLIST pidl);
45 extern HRESULT IFSFolder_Constructor(
46 IUnknown * pUnkOuter,
47 REFIID riid,
48 LPVOID * ppv);
50 /*************************************************************************
51 * SHCoCreateInstance [SHELL32.102]
53 * NOTES
54 * exported by ordinal
56 LRESULT WINAPI SHCoCreateInstance(
57 LPCSTR aclsid,
58 REFCLSID clsid,
59 LPUNKNOWN unknownouter,
60 REFIID refiid,
61 LPVOID *ppv)
63 DWORD hres;
64 IID iid;
65 CLSID * myclsid = (CLSID*)clsid;
67 if (!clsid)
69 if (!aclsid) return REGDB_E_CLASSNOTREG;
70 SHCLSIDFromStringA(aclsid, &iid);
71 myclsid = &iid;
74 TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
75 aclsid,debugstr_guid(myclsid),unknownouter,debugstr_guid(refiid),ppv);
77 if IsEqualCLSID(myclsid, &CLSID_ShellFSFolder)
79 hres = IFSFolder_Constructor(unknownouter, refiid, ppv);
81 else
83 CoInitialize(NULL);
84 hres = CoCreateInstance(myclsid, unknownouter, CLSCTX_INPROC_SERVER, refiid, ppv);
87 if(hres!=S_OK)
89 ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
90 hres, debugstr_guid(myclsid), debugstr_guid(refiid));
91 ERR("class not found in registry\n");
94 TRACE("-- instance: %p\n",*ppv);
95 return hres;
98 /*************************************************************************
99 * DllGetClassObject [SHELL32.128]
101 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
102 { HRESULT hres = E_OUTOFMEMORY;
103 LPCLASSFACTORY lpclf;
105 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
107 *ppv = NULL;
109 if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)||
110 IsEqualCLSID(rclsid, &CLSID_ShellLink))
112 lpclf = IClassFactory_Constructor( rclsid );
114 if(lpclf)
116 hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
117 IClassFactory_Release(lpclf);
120 else
122 WARN("-- CLSID not found\n");
123 hres = CLASS_E_CLASSNOTAVAILABLE;
125 TRACE("-- pointer to class factory: %p\n",*ppv);
126 return hres;
129 /*************************************************************************
130 * SHCLSIDFromString [SHELL32.147]
132 * NOTES
133 * exported by ordinal
135 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id)
137 WCHAR buffer[40];
138 TRACE("(%p(%s) %p)\n", clsid, clsid, id);
139 if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
140 return CO_E_CLASSSTRING;
141 return CLSIDFromString( buffer, id );
143 DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
145 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
146 return CLSIDFromString(clsid, id);
148 DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
150 if (SHELL_OsIsUnicode())
151 return SHCLSIDFromStringW (clsid, id);
152 return SHCLSIDFromStringA (clsid, id);
155 /*************************************************************************
156 * SHGetMalloc [SHELL32.@]
157 * returns the interface to shell malloc.
159 * [SDK header win95/shlobj.h:
160 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
162 * What we are currently doing is not very wrong, since we always use the same
163 * heap (ProcessHeap).
165 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal)
167 TRACE("(%p)\n", lpmal);
168 return CoGetMalloc(MEMCTX_TASK, lpmal);
171 /*************************************************************************
172 * SHGetDesktopFolder [SHELL32.@]
174 LPSHELLFOLDER pdesktopfolder=NULL;
176 DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
178 HRESULT hres = S_OK;
179 LPCLASSFACTORY lpclf;
180 TRACE("%p->(%p)\n",psf,*psf);
182 *psf=NULL;
184 if (!pdesktopfolder)
186 lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
187 if(lpclf)
189 hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
190 IClassFactory_Release(lpclf);
194 if (pdesktopfolder)
196 /* even if we create the folder, add a ref so the application canĀ“t destroy the folder*/
197 IShellFolder_AddRef(pdesktopfolder);
198 *psf = pdesktopfolder;
201 TRACE("-- %p->(%p)\n",psf, *psf);
202 return hres;
205 /**************************************************************************
206 * IClassFactory Implementation
209 typedef struct
211 /* IUnknown fields */
212 ICOM_VFIELD(IClassFactory);
213 DWORD ref;
214 CLSID *rclsid;
215 } IClassFactoryImpl;
217 static ICOM_VTABLE(IClassFactory) clfvt;
219 /**************************************************************************
220 * IClassFactory_Constructor
223 LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
225 IClassFactoryImpl* lpclf;
227 lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
228 lpclf->ref = 1;
229 ICOM_VTBL(lpclf) = &clfvt;
230 lpclf->rclsid = (CLSID*)rclsid;
232 TRACE("(%p)->()\n",lpclf);
233 InterlockedIncrement(&shell32_ObjCount);
234 return (LPCLASSFACTORY)lpclf;
236 /**************************************************************************
237 * IClassFactory_QueryInterface
239 static HRESULT WINAPI IClassFactory_fnQueryInterface(
240 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
242 ICOM_THIS(IClassFactoryImpl,iface);
243 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
245 *ppvObj = NULL;
247 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
248 { *ppvObj = This;
250 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
251 { *ppvObj = (IClassFactory*)This;
254 if(*ppvObj)
255 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
256 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
257 return S_OK;
259 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
260 return E_NOINTERFACE;
262 /******************************************************************************
263 * IClassFactory_AddRef
265 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
267 ICOM_THIS(IClassFactoryImpl,iface);
268 TRACE("(%p)->(count=%lu)\n",This,This->ref);
270 InterlockedIncrement(&shell32_ObjCount);
271 return InterlockedIncrement(&This->ref);
273 /******************************************************************************
274 * IClassFactory_Release
276 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
278 ICOM_THIS(IClassFactoryImpl,iface);
279 TRACE("(%p)->(count=%lu)\n",This,This->ref);
281 InterlockedDecrement(&shell32_ObjCount);
282 if (!InterlockedDecrement(&This->ref))
284 TRACE("-- destroying IClassFactory(%p)\n",This);
285 HeapFree(GetProcessHeap(),0,This);
286 return 0;
288 return This->ref;
290 /******************************************************************************
291 * IClassFactory_CreateInstance
293 static HRESULT WINAPI IClassFactory_fnCreateInstance(
294 LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
296 ICOM_THIS(IClassFactoryImpl,iface);
297 IUnknown *pObj = NULL;
298 HRESULT hres;
300 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,debugstr_guid(riid),ppObject);
302 *ppObject = NULL;
304 if(pUnknown)
306 return(CLASS_E_NOAGGREGATION);
309 if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
311 pObj = (IUnknown *)ISF_Desktop_Constructor();
313 else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
315 pObj = (IUnknown *)IShellLink_Constructor(FALSE);
317 else
319 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
320 return(E_NOINTERFACE);
323 if (!pObj)
325 return(E_OUTOFMEMORY);
328 hres = IUnknown_QueryInterface(pObj,riid, ppObject);
329 IUnknown_Release(pObj);
331 TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
333 return hres;
335 /******************************************************************************
336 * IClassFactory_LockServer
338 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
340 ICOM_THIS(IClassFactoryImpl,iface);
341 TRACE("%p->(0x%x), not implemented\n",This, fLock);
342 return E_NOTIMPL;
345 static ICOM_VTABLE(IClassFactory) clfvt =
347 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
348 IClassFactory_fnQueryInterface,
349 IClassFactory_fnAddRef,
350 IClassFactory_fnRelease,
351 IClassFactory_fnCreateInstance,
352 IClassFactory_fnLockServer
355 /**************************************************************************
356 * Default ClassFactory Implementation
358 * SHCreateDefClassObject
360 * NOTES
361 * helper function for dll's without a own classfactory
362 * a generic classfactory is returned
363 * when the CreateInstance of the cf is called the callback is executed
365 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
367 typedef struct
369 ICOM_VFIELD(IClassFactory);
370 DWORD ref;
371 CLSID *rclsid;
372 LPFNCREATEINSTANCE lpfnCI;
373 const IID * riidInst;
374 ULONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
375 } IDefClFImpl;
377 static ICOM_VTABLE(IClassFactory) dclfvt;
379 /**************************************************************************
380 * IDefClF_fnConstructor
383 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst)
385 IDefClFImpl* lpclf;
387 lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
388 lpclf->ref = 1;
389 ICOM_VTBL(lpclf) = &dclfvt;
390 lpclf->lpfnCI = lpfnCI;
391 lpclf->pcRefDll = pcRefDll;
393 if (pcRefDll) InterlockedIncrement(pcRefDll);
394 lpclf->riidInst = riidInst;
396 TRACE("(%p)\n\tIID:\t%s\n",lpclf, debugstr_guid(riidInst));
397 InterlockedIncrement(&shell32_ObjCount);
398 return (LPCLASSFACTORY)lpclf;
400 /**************************************************************************
401 * IDefClF_fnQueryInterface
403 static HRESULT WINAPI IDefClF_fnQueryInterface(
404 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
406 ICOM_THIS(IDefClFImpl,iface);
408 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
410 *ppvObj = NULL;
412 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
413 { *ppvObj = This;
415 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
416 { *ppvObj = (IClassFactory*)This;
419 if(*ppvObj)
420 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
421 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
422 return S_OK;
424 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
425 return E_NOINTERFACE;
427 /******************************************************************************
428 * IDefClF_fnAddRef
430 static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
432 ICOM_THIS(IDefClFImpl,iface);
433 TRACE("(%p)->(count=%lu)\n",This,This->ref);
435 InterlockedIncrement(&shell32_ObjCount);
436 return InterlockedIncrement(&This->ref);
438 /******************************************************************************
439 * IDefClF_fnRelease
441 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
443 ICOM_THIS(IDefClFImpl,iface);
444 TRACE("(%p)->(count=%lu)\n",This,This->ref);
446 InterlockedDecrement(&shell32_ObjCount);
448 if (!InterlockedDecrement(&This->ref))
450 if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
452 TRACE("-- destroying IClassFactory(%p)\n",This);
453 HeapFree(GetProcessHeap(),0,This);
454 return 0;
456 return This->ref;
458 /******************************************************************************
459 * IDefClF_fnCreateInstance
461 static HRESULT WINAPI IDefClF_fnCreateInstance(
462 LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
464 ICOM_THIS(IDefClFImpl,iface);
466 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,debugstr_guid(riid),ppvObject);
468 *ppvObject = NULL;
470 if(pUnkOuter)
471 return(CLASS_E_NOAGGREGATION);
473 if ( This->riidInst==NULL ||
474 IsEqualCLSID(riid, This->riidInst) ||
475 IsEqualCLSID(riid, &IID_IUnknown) )
477 return This->lpfnCI(pUnkOuter, riid, ppvObject);
480 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
481 return E_NOINTERFACE;
483 /******************************************************************************
484 * IDefClF_fnLockServer
486 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
488 ICOM_THIS(IDefClFImpl,iface);
489 TRACE("%p->(0x%x), not implemented\n",This, fLock);
490 return E_NOTIMPL;
493 static ICOM_VTABLE(IClassFactory) dclfvt =
495 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
496 IDefClF_fnQueryInterface,
497 IDefClF_fnAddRef,
498 IDefClF_fnRelease,
499 IDefClF_fnCreateInstance,
500 IDefClF_fnLockServer
503 /******************************************************************************
504 * SHCreateDefClassObject [SHELL32.70]
506 HRESULT WINAPI SHCreateDefClassObject(
507 REFIID riid,
508 LPVOID* ppv,
509 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */
510 LPDWORD pcRefDll, /* [in/out] ref count of the dll */
511 REFIID riidInst) /* [in] optional interface to the instance */
513 TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
514 debugstr_guid(riid), ppv, lpfnCI, pcRefDll, debugstr_guid(riidInst));
516 if ( IsEqualCLSID(riid, &IID_IClassFactory) )
518 IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
519 if (pcf)
521 *ppv = pcf;
522 return NOERROR;
524 return E_OUTOFMEMORY;
526 return E_NOINTERFACE;
529 /*************************************************************************
530 * DragAcceptFiles [SHELL32.54]
532 void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
534 LONG exstyle;
536 if( !IsWindow(hWnd) ) return;
537 exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
538 if (b)
539 exstyle |= WS_EX_ACCEPTFILES;
540 else
541 exstyle &= ~WS_EX_ACCEPTFILES;
542 SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
545 /*************************************************************************
546 * DragFinish [SHELL32.80]
548 void WINAPI DragFinish(HDROP h)
550 TRACE("\n");
551 GlobalFree((HGLOBAL)h);
554 /*************************************************************************
555 * DragQueryPoint [SHELL32.135]
557 BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
559 DROPFILES *lpDropFileStruct;
560 BOOL bRet;
562 TRACE("\n");
564 lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
566 *p = lpDropFileStruct->pt;
567 bRet = lpDropFileStruct->fNC;
569 GlobalUnlock(hDrop);
570 return bRet;
573 /*************************************************************************
574 * DragQueryFile [SHELL32.81]
575 * DragQueryFileA [SHELL32.82]
577 UINT WINAPI DragQueryFileA(
578 HDROP hDrop,
579 UINT lFile,
580 LPSTR lpszFile,
581 UINT lLength)
583 LPSTR lpDrop;
584 UINT i = 0;
585 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
587 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
589 if(!lpDropFileStruct) goto end;
591 lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
593 if(lpDropFileStruct->fWide == TRUE) {
594 LPWSTR lpszFileW = NULL;
596 if(lpszFile) {
597 lpszFileW = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, lLength*sizeof(WCHAR));
598 if(lpszFileW == NULL) {
599 goto end;
602 i = DragQueryFileW(hDrop, lFile, lpszFileW, lLength);
604 if(lpszFileW) {
605 WideCharToMultiByte(CP_ACP, 0, lpszFileW, -1, lpszFile, lLength, 0, NULL);
606 HeapFree(GetProcessHeap(), 0, lpszFileW);
608 goto end;
611 while (i++ < lFile)
613 while (*lpDrop++); /* skip filename */
614 if (!*lpDrop)
616 i = (lFile == 0xFFFFFFFF) ? i : 0;
617 goto end;
621 i = strlen(lpDrop);
622 i++;
623 if (!lpszFile ) goto end; /* needed buffer size */
624 i = (lLength > i) ? i : lLength;
625 lstrcpynA (lpszFile, lpDrop, i);
626 end:
627 GlobalUnlock(hDrop);
628 return i;
631 /*************************************************************************
632 * DragQueryFileW [SHELL32.133]
634 UINT WINAPI DragQueryFileW(
635 HDROP hDrop,
636 UINT lFile,
637 LPWSTR lpszwFile,
638 UINT lLength)
640 LPWSTR lpwDrop;
641 UINT i = 0;
642 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
644 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
646 if(!lpDropFileStruct) goto end;
648 lpwDrop = (LPWSTR) ((LPSTR)lpDropFileStruct + lpDropFileStruct->pFiles);
650 if(lpDropFileStruct->fWide == FALSE) {
651 LPSTR lpszFileA = NULL;
653 if(lpszwFile) {
654 lpszFileA = (LPSTR) HeapAlloc(GetProcessHeap(), 0, lLength);
655 if(lpszFileA == NULL) {
656 goto end;
659 i = DragQueryFileA(hDrop, lFile, lpszFileA, lLength);
661 if(lpszFileA) {
662 MultiByteToWideChar(CP_ACP, 0, lpszFileA, -1, lpszwFile, lLength);
663 HeapFree(GetProcessHeap(), 0, lpszFileA);
665 goto end;
668 i = 0;
669 while (i++ < lFile)
671 while (*lpwDrop++); /* skip filename */
672 if (!*lpwDrop)
674 i = (lFile == 0xFFFFFFFF) ? i : 0;
675 goto end;
679 i = strlenW(lpwDrop);
680 i++;
681 if ( !lpszwFile) goto end; /* needed buffer size */
683 i = (lLength > i) ? i : lLength;
684 lstrcpynW (lpszwFile, lpwDrop, i);
685 end:
686 GlobalUnlock(hDrop);
687 return i;