New debug scheme with explicit debug channels declaration.
[wine] / dlls / shell32 / shelllink.c
1 /*
2  *
3  *      Copyright 1997  Marcus Meissner
4  *      Copyright 1998  Juergen Schmied
5  *
6  */
7
8 #include <string.h>
9 #include "debug.h"
10 #include "winerror.h"
11
12 #include "wine/obj_base.h"
13 #include "wine/obj_storage.h"
14 #include "wine/obj_shelllink.h"
15
16 #include "heap.h"
17 #include "winnls.h"
18 #include "pidl.h"
19 #include "shell32_main.h"
20 #include "shlguid.h"
21
22 DEFAULT_DEBUG_CHANNEL(shell)
23
24 /* link file formats */
25
26 #pragma (1);
27
28 /* lnk elements: simple link has 0x0B */
29 #define WORKDIR         0x10
30 #define ARGUMENT        0x20
31 #define ICON            0x40
32 /* startup type */
33 #define NORMAL          0x01
34 #define MAXIMIZED       0x03
35 #define MINIMIZED       0x07
36
37 typedef struct _LINK_HEADER     
38 {       DWORD   MagicStr;       /* 0x00 'L','\0','\0','\0' */
39         GUID    MagicGuid;      /* 0x04 is CLSID_ShellLink */
40         DWORD   Flag1;          /* 0x14 describes elements following */
41         DWORD   Flag2;          /* 0x18 */
42         FILETIME Time1;         /* 0x1c */
43         FILETIME Time2;         /* 0x24 */
44         FILETIME Time3;         /* 0x2c */
45         DWORD   Unknown1;       /* 0x34 */
46         DWORD   Unknown2;       /* 0x38 icon number */
47         DWORD   Flag3;          /* 0x3c startup type */
48         DWORD   Unknown4;       /* 0x40 hotkey */
49         DWORD   Unknown5;       /* 0x44 */
50         DWORD   Unknown6;       /* 0x48 */
51         USHORT  PidlSize;       /* 0x4c */
52         ITEMIDLIST Pidl;        /* 0x4e */
53 } LINK_HEADER, * PLINK_HEADER;
54
55 #pragma (4);
56
57 /* IPersistFile Implementation */
58 typedef struct
59 {
60         /* IUnknown fields */
61         ICOM_VTABLE(IPersistFile)*      lpvtbl;
62         DWORD           ref;
63         LPSTR           sPath;
64         LPITEMIDLIST    pPidl;
65
66 } IPersistFileImpl;
67
68 static struct ICOM_VTABLE(IPersistFile) pfvt;
69
70
71 /**************************************************************************
72  *        IPersistFile_Constructor
73  */
74 IPersistFileImpl * IPersistFile_Constructor(void) 
75 {
76         IPersistFileImpl* sl;
77
78         sl = (IPersistFileImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IPersistFileImpl));
79         sl->ref = 1;
80         sl->lpvtbl = &pfvt;
81         sl->sPath = NULL;
82         sl->pPidl = NULL;
83                         
84         TRACE(shell,"(%p)->()\n",sl);
85         shell32_ObjCount++;
86         return sl;
87 }
88
89 /**************************************************************************
90  *  IPersistFile_QueryInterface
91  */
92 static HRESULT WINAPI IPersistFile_fnQueryInterface(
93   IPersistFile* iface, REFIID riid, LPVOID *ppvObj)
94 {
95         ICOM_THIS(IPersistFileImpl,iface);
96
97         char    xriid[50];
98         WINE_StringFromCLSID((LPCLSID)riid,xriid);
99         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
100
101         *ppvObj = NULL;
102
103         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
104         { *ppvObj = This; 
105         }
106         else if(IsEqualIID(riid, &IID_IPersistFile))  /*IPersistFile*/
107         {    *ppvObj = (LPPERSISTFILE)This;
108         }   
109
110         if(*ppvObj)
111         { IPersistFile_AddRef((IPersistFile*)*ppvObj);      
112           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
113           return S_OK;
114         }
115         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
116         return E_NOINTERFACE;
117 }  
118 /******************************************************************************
119  * IPersistFile_AddRef
120  */
121 static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile* iface)
122 {
123         ICOM_THIS(IPersistFileImpl,iface);
124
125         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
126
127         shell32_ObjCount++;
128         return ++(This->ref);
129 }
130 /******************************************************************************
131  * IPersistFile_Release
132  */
133 static ULONG WINAPI IPersistFile_fnRelease(IPersistFile* iface)
134 {
135         ICOM_THIS(IPersistFileImpl,iface);
136
137         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
138
139         shell32_ObjCount--;
140
141         if (!--(This->ref)) 
142         { TRACE(shell,"-- destroying IPersistFile(%p)\n",This);
143           if (This->sPath)
144             HeapFree(GetProcessHeap(),0,This->sPath);
145           if (This->pPidl)
146             SHFree(This->pPidl);
147           HeapFree(GetProcessHeap(),0,This);
148           return 0;
149         }
150         return This->ref;
151 }
152
153 static HRESULT WINAPI IPersistFile_fnGetClassID(const IPersistFile* iface, CLSID *pClassID)
154 {
155         ICOM_CTHIS(IPersistFile,iface);
156         FIXME(shell,"(%p)\n",This);
157         return NOERROR;
158 }
159 static HRESULT WINAPI IPersistFile_fnIsDirty(const IPersistFile* iface)
160 {
161         ICOM_CTHIS(IPersistFile,iface);
162         FIXME(shell,"(%p)\n",This);
163         return NOERROR;
164 }
165 static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode)
166 {
167         ICOM_THIS(IPersistFileImpl,iface);
168
169         OFSTRUCT        ofs;
170         LPSTR   sFile = HEAP_strdupWtoA ( GetProcessHeap(), 0, pszFileName);
171         HFILE   hFile = OpenFile( sFile, &ofs, OF_READ );
172         HANDLE  hMapping;
173         PLINK_HEADER    pImage;
174         HRESULT         hRet = E_FAIL;
175         CHAR            sTemp[512];
176         
177         TRACE(shell,"(%p)->(%s)\n",This,sFile); 
178
179         HeapFree(GetProcessHeap(),0,sFile);
180
181         if ( !(hMapping = CreateFileMappingA(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL))) 
182         { WARN(shell,"failed to create filemap.\n");
183           goto end_1;
184         }
185
186         if ( !(pImage = (PLINK_HEADER) MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0))) 
187         { WARN(shell,"failed to mmap filemap.\n");
188           goto end_2;   
189         }
190         
191         if (!( (pImage->MagicStr == 0x0000004CL) && IsEqualIID(&pImage->MagicGuid, &CLSID_ShellLink)))
192         { TRACE(shell,"file isn't a lnk\n");
193           goto end_3;
194         }
195         
196         { /* for debugging */
197           SYSTEMTIME time;
198           FileTimeToSystemTime (&pImage->Time1, &time);
199           GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL,  sTemp, 256);
200           TRACE(shell, "-- time1: %s\n", sTemp);
201
202           FileTimeToSystemTime (&pImage->Time2, &time);
203           GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL,  sTemp, 256);
204           TRACE(shell, "-- time2: %s\n", sTemp);
205
206           FileTimeToSystemTime (&pImage->Time3, &time);
207           GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL,  sTemp, 256);
208           TRACE(shell, "-- time3: %s\n", sTemp);
209           pdump (&pImage->Pidl);
210         }
211
212         This->pPidl = ILClone (&pImage->Pidl);
213
214         _ILGetPidlPath(&pImage->Pidl, sTemp, 512);
215         This->sPath = HEAP_strdupA ( GetProcessHeap(), 0, sTemp);
216                 
217         hRet = NOERROR;
218 end_3:  UnmapViewOfFile(pImage);
219 end_2:  CloseHandle(hMapping);
220 end_1:  _lclose( hFile);
221
222         return hRet;
223 }
224
225 static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember)
226 {
227         ICOM_THIS(IPersistFileImpl,iface);
228         FIXME(shell,"(%p)->(%s)\n",This,debugstr_w(pszFileName));
229         return NOERROR;
230 }
231 static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName)
232 {
233         ICOM_THIS(IPersistFileImpl,iface);
234         FIXME(shell,"(%p)->(%s)\n",This,debugstr_w(pszFileName));
235         return NOERROR;
236 }
237 static HRESULT WINAPI IPersistFile_fnGetCurFile(const IPersistFile* iface, LPOLESTR *ppszFileName)
238 {
239         ICOM_CTHIS(IPersistFileImpl,iface);
240         FIXME(shell,"(%p)\n",This);
241         return NOERROR;
242 }
243   
244 static struct ICOM_VTABLE(IPersistFile) pfvt = 
245 {
246         IPersistFile_fnQueryInterface,
247         IPersistFile_fnAddRef,
248         IPersistFile_fnRelease,
249         IPersistFile_fnGetClassID,
250         IPersistFile_fnIsDirty,
251         IPersistFile_fnLoad,
252         IPersistFile_fnSave,
253         IPersistFile_fnSaveCompleted,
254         IPersistFile_fnGetCurFile
255 };
256
257
258 /**************************************************************************
259 *  IShellLink's IClassFactory implementation
260  */
261 typedef struct
262 {
263     /* IUnknown fields */
264     ICOM_VTABLE(IClassFactory)* lpvtbl;
265     DWORD                       ref;
266 } IClassFactoryImpl;
267
268 static ICOM_VTABLE(IClassFactory) slcfvt;
269
270 /**************************************************************************
271  *  IShellLink_CF_Constructor
272  */
273
274 LPCLASSFACTORY IShellLink_CF_Constructor(void)
275 {
276         IClassFactoryImpl* lpclf;
277
278         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
279         lpclf->ref = 1;
280         lpclf->lpvtbl = &slcfvt;
281         TRACE(shell,"(%p)->()\n",lpclf);
282         shell32_ObjCount++;
283         return (LPCLASSFACTORY)lpclf;
284 }
285 /**************************************************************************
286  *  IShellLink_CF_QueryInterface
287  */
288 static HRESULT WINAPI IShellLink_CF_QueryInterface(
289   IClassFactory* iface, REFIID riid, LPVOID *ppvObj)
290 {
291         ICOM_THIS(IClassFactoryImpl,iface);
292         char    xriid[50];
293         WINE_StringFromCLSID((LPCLSID)riid,xriid);
294         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
295
296         *ppvObj = NULL;
297
298         if(IsEqualIID(riid, &IID_IUnknown))             /*IUnknown*/
299         { *ppvObj = (LPUNKNOWN)This; 
300         }
301         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
302         { *ppvObj = (LPCLASSFACTORY)This;
303         }   
304
305         if(*ppvObj)
306         { IUnknown_AddRef((IUnknown*)*ppvObj);          
307           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
308           return S_OK;
309         }
310         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
311         return E_NOINTERFACE;
312 }  
313 /******************************************************************************
314  * IShellLink_CF_AddRef
315  */
316 static ULONG WINAPI IShellLink_CF_AddRef(IClassFactory* iface)
317 {
318         ICOM_THIS(IClassFactoryImpl,iface);
319         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
320
321         shell32_ObjCount++;
322         return ++(This->ref);
323 }
324 /******************************************************************************
325  * IShellLink_CF_Release
326  */
327 static ULONG WINAPI IShellLink_CF_Release(IClassFactory* iface)
328 {
329         ICOM_THIS(IClassFactoryImpl,iface);
330         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
331
332         shell32_ObjCount--;
333         if (!--(This->ref)) 
334         { TRACE(shell,"-- destroying IClassFactory(%p)\n",This);
335                 HeapFree(GetProcessHeap(),0,This);
336                 return 0;
337         }
338         return This->ref;
339 }
340 /******************************************************************************
341  * IShellLink_CF_CreateInstance
342  */
343 static HRESULT WINAPI IShellLink_CF_CreateInstance(
344   IClassFactory* iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
345 {
346         ICOM_THIS(IClassFactoryImpl,iface);
347         IUnknown *pObj = NULL;
348         HRESULT hres;
349         char    xriid[50];
350
351         WINE_StringFromCLSID((LPCLSID)riid,xriid);
352         TRACE(shell,"%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
353
354         *ppObject = NULL;
355                 
356         if(pUnknown)
357         {       return(CLASS_E_NOAGGREGATION);
358         }
359
360         if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellLink))
361         { pObj = (IUnknown *)IShellLink_Constructor();
362         } 
363         else
364         { ERR(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
365           return(E_NOINTERFACE);
366         }
367         
368         if (!pObj)
369         { return(E_OUTOFMEMORY);
370         }
371          
372         hres = IUnknown_QueryInterface(pObj,riid, ppObject);
373         IUnknown_Release(pObj);
374         TRACE(shell,"-- Object created: (%p)->%p\n",This,*ppObject);
375
376         return hres;
377 }
378 /******************************************************************************
379  * IShellLink_CF_LockServer
380  */
381 static HRESULT WINAPI IShellLink_CF_LockServer(IClassFactory* iface, BOOL fLock)
382 {
383         ICOM_THIS(IClassFactoryImpl,iface);
384         TRACE(shell,"%p->(0x%x), not implemented\n",This, fLock);
385         return E_NOTIMPL;
386 }
387 static ICOM_VTABLE(IClassFactory) slcfvt = 
388 {
389     IShellLink_CF_QueryInterface,
390     IShellLink_CF_AddRef,
391   IShellLink_CF_Release,
392   IShellLink_CF_CreateInstance,
393   IShellLink_CF_LockServer
394 };
395
396 /**************************************************************************
397  * IShellLink Implementation 
398  */
399
400 typedef struct
401 {
402         ICOM_VTABLE(IShellLink)*        lpvtbl;
403         DWORD                           ref;
404         IPersistFileImpl*               lppf;
405
406 } IShellLinkImpl;
407
408 static ICOM_VTABLE(IShellLink) slvt;
409
410 /**************************************************************************
411  *        IShellLink_Constructor
412  */
413 IShellLink * IShellLink_Constructor(void) 
414 {       IShellLinkImpl * sl;
415
416         sl = (IShellLinkImpl *)HeapAlloc(GetProcessHeap(),0,sizeof(IShellLinkImpl));
417         sl->ref = 1;
418         sl->lpvtbl = &slvt;
419
420         sl->lppf = IPersistFile_Constructor();
421
422         TRACE(shell,"(%p)->()\n",sl);
423         shell32_ObjCount++;
424         return (IShellLink *)sl;
425 }
426
427 /**************************************************************************
428  *  IShellLink::QueryInterface
429  */
430 static HRESULT WINAPI IShellLink_fnQueryInterface( IShellLink * iface, REFIID riid,  LPVOID *ppvObj)
431 {
432         ICOM_THIS(IShellLinkImpl, iface);
433         
434         char    xriid[50];
435         WINE_StringFromCLSID((LPCLSID)riid,xriid);
436         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
437
438         *ppvObj = NULL;
439
440         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
441         { *ppvObj = This; 
442         }
443         else if(IsEqualIID(riid, &IID_IShellLink))  /*IShellLink*/
444         {    *ppvObj = (IShellLink *)This;
445         }   
446         else if(IsEqualIID(riid, &IID_IPersistFile))  /*IPersistFile*/
447         {    *ppvObj = (IPersistFile *)This->lppf;
448         }   
449
450         if(*ppvObj)
451         { IShellLink_AddRef((IShellLink*)*ppvObj);      
452           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
453           return S_OK;
454         }
455         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
456         return E_NOINTERFACE;
457 }  
458 /******************************************************************************
459  * IShellLink_AddRef
460  */
461 static ULONG WINAPI IShellLink_fnAddRef(IShellLink * iface)
462 {
463         ICOM_THIS(IShellLinkImpl, iface);
464         
465         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
466
467         shell32_ObjCount++;
468         return ++(This->ref);
469 }
470 /******************************************************************************
471  *      IShellLink_Release
472  */
473 static ULONG WINAPI IShellLink_fnRelease(IShellLink * iface)
474 {
475         ICOM_THIS(IShellLinkImpl, iface);
476         
477         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
478
479         shell32_ObjCount--;
480         if (!--(This->ref)) 
481         { TRACE(shell,"-- destroying IShellLink(%p)\n",This);
482           IPersistFile_Release((IPersistFile*) This->lppf);     /* IPersistFile*/
483           HeapFree(GetProcessHeap(),0,This);
484           return 0;
485         }
486         return This->ref;
487 }
488
489 static HRESULT WINAPI IShellLink_fnGetPath(IShellLink * iface, LPSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
490 {
491         ICOM_THIS(IShellLinkImpl, iface);
492         
493         TRACE(shell,"(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This, pszFile, cchMaxPath, pfd, fFlags);
494
495         strncpy(pszFile,This->lppf->sPath, cchMaxPath);
496         return NOERROR;
497 }
498 static HRESULT WINAPI IShellLink_fnGetIDList(IShellLink * iface, LPITEMIDLIST * ppidl)
499 {
500         ICOM_THIS(IShellLinkImpl, iface);
501         
502         TRACE(shell,"(%p)->(ppidl=%p)\n",This, ppidl);
503
504         *ppidl = ILClone(This->lppf->pPidl);
505         return NOERROR;
506 }
507 static HRESULT WINAPI IShellLink_fnSetIDList(IShellLink * iface, LPCITEMIDLIST pidl)
508 {
509         ICOM_THIS(IShellLinkImpl, iface);
510         
511         TRACE (shell,"(%p)->(pidl=%p)\n",This, pidl);
512
513         if (This->lppf->pPidl)
514             SHFree(This->lppf->pPidl);
515         This->lppf->pPidl = ILClone (pidl);
516         return NOERROR;
517 }
518 static HRESULT WINAPI IShellLink_fnGetDescription(IShellLink * iface, LPSTR pszName,INT cchMaxName)
519 {
520         ICOM_THIS(IShellLinkImpl, iface);
521         
522         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
523         strncpy(pszName,"Description, FIXME",cchMaxName);
524         return NOERROR;
525 }
526 static HRESULT WINAPI IShellLink_fnSetDescription(IShellLink * iface, LPCSTR pszName)
527 {
528         ICOM_THIS(IShellLinkImpl, iface);
529         
530         FIXME(shell,"(%p)->(desc=%s)\n",This, pszName);
531         return NOERROR;
532 }
533 static HRESULT WINAPI IShellLink_fnGetWorkingDirectory(IShellLink * iface, LPSTR pszDir,INT cchMaxPath)
534 {
535         ICOM_THIS(IShellLinkImpl, iface);
536         
537         FIXME(shell,"(%p)->()\n",This);
538         strncpy(pszDir,"c:\\", cchMaxPath);
539         return NOERROR;
540 }
541 static HRESULT WINAPI IShellLink_fnSetWorkingDirectory(IShellLink * iface, LPCSTR pszDir)
542 {
543         ICOM_THIS(IShellLinkImpl, iface);
544         
545         FIXME(shell,"(%p)->(dir=%s)\n",This, pszDir);
546         return NOERROR;
547 }
548 static HRESULT WINAPI IShellLink_fnGetArguments(IShellLink * iface, LPSTR pszArgs,INT cchMaxPath)
549 {
550         ICOM_THIS(IShellLinkImpl, iface);
551         
552         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszArgs, cchMaxPath);
553         strncpy(pszArgs, "", cchMaxPath);
554         return NOERROR;
555 }
556 static HRESULT WINAPI IShellLink_fnSetArguments(IShellLink * iface, LPCSTR pszArgs)
557 {
558         ICOM_THIS(IShellLinkImpl, iface);
559         
560         FIXME(shell,"(%p)->(args=%s)\n",This, pszArgs);
561         return NOERROR;
562 }
563 static HRESULT WINAPI IShellLink_fnGetHotkey(IShellLink * iface, WORD *pwHotkey)
564 {
565         ICOM_THIS(IShellLinkImpl, iface);
566         
567         FIXME(shell,"(%p)->(%p) returning 0\n",This, pwHotkey);
568         *pwHotkey=0x0;
569         return NOERROR;
570 }
571 static HRESULT WINAPI IShellLink_fnSetHotkey(IShellLink * iface, WORD wHotkey)
572 {
573         ICOM_THIS(IShellLinkImpl, iface);
574         
575         FIXME(shell,"(%p)->(hotkey=%x)\n",This, wHotkey);
576         return NOERROR;
577 }
578 static HRESULT WINAPI IShellLink_fnGetShowCmd(IShellLink * iface, INT *piShowCmd)
579 {
580         ICOM_THIS(IShellLinkImpl, iface);
581         
582         FIXME(shell,"(%p)->(%p)\n",This, piShowCmd);
583         *piShowCmd=0;
584         return NOERROR;
585 }
586 static HRESULT WINAPI IShellLink_fnSetShowCmd(IShellLink * iface, INT iShowCmd)
587 {
588         ICOM_THIS(IShellLinkImpl, iface);
589         
590         FIXME(shell,"(%p)->(showcmd=%x)\n",This, iShowCmd);
591         return NOERROR;
592 }
593 static HRESULT WINAPI IShellLink_fnGetIconLocation(IShellLink * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon)
594 {
595         ICOM_THIS(IShellLinkImpl, iface);
596         
597         FIXME(shell,"(%p)->(%p len=%u iicon=%p)\n",This, pszIconPath, cchIconPath, piIcon);
598         strncpy(pszIconPath,"shell32.dll",cchIconPath);
599         *piIcon=1;
600         return NOERROR;
601 }
602 static HRESULT WINAPI IShellLink_fnSetIconLocation(IShellLink * iface, LPCSTR pszIconPath,INT iIcon)
603 {
604         ICOM_THIS(IShellLinkImpl, iface);
605         
606         FIXME(shell,"(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon);
607         return NOERROR;
608 }
609 static HRESULT WINAPI IShellLink_fnSetRelativePath(IShellLink * iface, LPCSTR pszPathRel, DWORD dwReserved)
610 {
611         ICOM_THIS(IShellLinkImpl, iface);
612         
613         FIXME(shell,"(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved);
614         return NOERROR;
615 }
616 static HRESULT WINAPI IShellLink_fnResolve(IShellLink * iface, HWND hwnd, DWORD fFlags)
617 {
618         ICOM_THIS(IShellLinkImpl, iface);
619         
620         FIXME(shell,"(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
621         return NOERROR;
622 }
623 static HRESULT WINAPI IShellLink_fnSetPath(IShellLink * iface, LPCSTR pszFile)
624 {
625         ICOM_THIS(IShellLinkImpl, iface);
626         
627         FIXME(shell,"(%p)->(path=%s)\n",This, pszFile);
628         return NOERROR;
629 }
630
631 /**************************************************************************
632 * IShellLink Implementation
633 */
634
635 static ICOM_VTABLE(IShellLink) slvt = 
636 {       IShellLink_fnQueryInterface,
637         IShellLink_fnAddRef,
638         IShellLink_fnRelease,
639         IShellLink_fnGetPath,
640         IShellLink_fnGetIDList,
641         IShellLink_fnSetIDList,
642         IShellLink_fnGetDescription,
643         IShellLink_fnSetDescription,
644         IShellLink_fnGetWorkingDirectory,
645         IShellLink_fnSetWorkingDirectory,
646         IShellLink_fnGetArguments,
647         IShellLink_fnSetArguments,
648         IShellLink_fnGetHotkey,
649         IShellLink_fnSetHotkey,
650         IShellLink_fnGetShowCmd,
651         IShellLink_fnSetShowCmd,
652         IShellLink_fnGetIconLocation,
653         IShellLink_fnSetIconLocation,
654         IShellLink_fnSetRelativePath,
655         IShellLink_fnResolve,
656         IShellLink_fnSetPath
657 };
658
659 /**************************************************************************
660 *  IShellLink's IClassFactory implementation
661 */
662
663 static ICOM_VTABLE(IClassFactory) slwcfvt;
664
665 /**************************************************************************
666  *  IShellLinkW_CF_Constructor
667  */
668
669 LPCLASSFACTORY IShellLinkW_CF_Constructor(void)
670 {
671         IClassFactoryImpl* lpclf;
672
673         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
674         lpclf->ref = 1;
675         lpclf->lpvtbl = &slwcfvt;
676         TRACE(shell,"(%p)->()\n",lpclf);
677         shell32_ObjCount++;
678         return (LPCLASSFACTORY)lpclf;
679 }
680 /**************************************************************************
681  *  IShellLinkW_CF_QueryInterface
682  */
683 static HRESULT WINAPI IShellLinkW_CF_QueryInterface(
684   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
685 {
686         ICOM_THIS(IClassFactoryImpl,iface);
687         char    xriid[50];
688         WINE_StringFromCLSID((LPCLSID)riid,xriid);
689         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
690
691         *ppvObj = NULL;
692
693         if(IsEqualIID(riid, &IID_IUnknown))             /*IUnknown*/
694         { *ppvObj = (LPUNKNOWN)This; 
695         }
696         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
697         { *ppvObj = (LPCLASSFACTORY)This;
698         }   
699
700         if(*ppvObj) {
701           IUnknown_AddRef((IUnknown*)*ppvObj);          
702           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
703           return S_OK;
704         }
705         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
706         return E_NOINTERFACE;
707 }  
708 /******************************************************************************
709  * IShellLinkW_CF_AddRef
710  */
711 static ULONG WINAPI IShellLinkW_CF_AddRef(LPCLASSFACTORY iface)
712 {
713         ICOM_THIS(IClassFactoryImpl,iface);
714         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
715
716         shell32_ObjCount++;
717         return ++(This->ref);
718 }
719 /******************************************************************************
720  * IShellLinkW_CF_Release
721  */
722 static ULONG WINAPI IShellLinkW_CF_Release(LPCLASSFACTORY iface)
723 {
724         ICOM_THIS(IClassFactoryImpl,iface);
725         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
726
727         shell32_ObjCount--;
728         if (!--(This->ref)) 
729         { TRACE(shell,"-- destroying IClassFactory(%p)\n",This);
730                 HeapFree(GetProcessHeap(),0,This);
731                 return 0;
732         }
733         return This->ref;
734 }
735 /******************************************************************************
736  * IShellLinkW_CF_CreateInstance
737  */
738 static HRESULT WINAPI IShellLinkW_CF_CreateInstance(
739   LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
740 {
741         ICOM_THIS(IClassFactoryImpl,iface);
742         IUnknown *pObj = NULL;
743         HRESULT hres;
744         char    xriid[50];
745
746         WINE_StringFromCLSID((LPCLSID)riid,xriid);
747         TRACE(shell,"%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
748
749         *ppObject = NULL;
750                 
751         if(pUnknown)
752         { return(CLASS_E_NOAGGREGATION);
753         }
754
755         if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellLinkW))
756         { pObj = (IUnknown *)IShellLinkW_Constructor();
757         } 
758         else
759         { ERR(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
760           return(E_NOINTERFACE);
761         }
762         
763         if (!pObj)
764         { return(E_OUTOFMEMORY);
765         }
766          
767         hres = pObj->lpvtbl->fnQueryInterface(pObj,riid, ppObject);
768         pObj->lpvtbl->fnRelease(pObj);
769         TRACE(shell,"-- Object created: (%p)->%p\n",This,*ppObject);
770
771         return hres;
772 }
773 /******************************************************************************
774  * IShellLinkW_CF_LockServer
775  */
776
777 static HRESULT WINAPI IShellLinkW_CF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
778 {
779         ICOM_THIS(IClassFactoryImpl,iface);
780         TRACE(shell,"%p->(0x%x), not implemented\n",This, fLock);
781         return E_NOTIMPL;
782 }
783
784 static ICOM_VTABLE(IClassFactory) slwcfvt = 
785 {
786     IShellLinkW_CF_QueryInterface,
787     IShellLinkW_CF_AddRef,
788   IShellLinkW_CF_Release,
789   IShellLinkW_CF_CreateInstance,
790   IShellLinkW_CF_LockServer
791 };
792
793
794 /**************************************************************************
795  * IShellLink Implementation 
796  */
797
798 typedef struct 
799 {
800         ICOM_VTABLE(IShellLinkW)*       lpvtbl;
801         DWORD                           ref;
802         IPersistFileImpl*               lppf;
803
804 } IShellLinkWImpl;
805
806 static ICOM_VTABLE(IShellLinkW) slvtw;
807
808 /**************************************************************************
809  *        IShellLinkW_fnConstructor
810  */
811 IShellLinkW * IShellLinkW_Constructor(void) 
812 {       IShellLinkWImpl* sl;
813
814         sl = (IShellLinkWImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IShellLinkWImpl));
815         sl->ref = 1;
816         sl->lpvtbl = &slvtw;
817
818         sl->lppf = IPersistFile_Constructor();
819
820         TRACE(shell,"(%p)->()\n",sl);
821         shell32_ObjCount++;
822         return (IShellLinkW*)sl;
823 }
824
825 /**************************************************************************
826  *  IShellLinkW_fnQueryInterface
827  */
828 static HRESULT WINAPI IShellLinkW_fnQueryInterface(
829   IShellLinkW * iface, REFIID riid, LPVOID *ppvObj)
830 {
831         ICOM_THIS(IShellLinkWImpl, iface);
832         
833         char    xriid[50];
834         WINE_StringFromCLSID((LPCLSID)riid,xriid);
835         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
836
837         *ppvObj = NULL;
838
839         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
840         { *ppvObj = This; 
841         }
842         else if(IsEqualIID(riid, &IID_IShellLinkW))  /*IShellLinkW*/
843         {    *ppvObj = (IShellLinkW *)This;
844         }   
845         else if(IsEqualIID(riid, &IID_IPersistFile))  /*IPersistFile*/
846         {    *ppvObj = (IPersistFile *)This->lppf;
847         }   
848
849         if(*ppvObj)
850         { IShellLink_AddRef((IShellLinkW*)*ppvObj);      
851           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
852           return S_OK;
853         }
854
855         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
856
857         return E_NOINTERFACE;
858 }  
859 /******************************************************************************
860  * IShellLinkW_fnAddRef
861  */
862 static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface)
863 {
864         ICOM_THIS(IShellLinkWImpl, iface);
865         
866         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
867
868         shell32_ObjCount++;
869         return ++(This->ref);
870 }
871 /******************************************************************************
872  * IShellLinkW_fnRelease
873  */
874
875 static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface)
876 {
877         ICOM_THIS(IShellLinkWImpl, iface);
878         
879         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
880
881         shell32_ObjCount--;
882         if (!--(This->ref)) 
883         { TRACE(shell,"-- destroying IShellLinkW(%p)\n",This);
884           IPersistFile_Release((IPersistFile*)This->lppf);      /* IPersistFile*/
885           HeapFree(GetProcessHeap(),0,This);
886           return 0;
887         }
888         return This->ref;
889 }
890
891 static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
892 {
893         ICOM_THIS(IShellLinkWImpl, iface);
894         
895         FIXME(shell,"(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This, pszFile, cchMaxPath, pfd, fFlags);
896         lstrcpynAtoW(pszFile,"c:\\foo.bar", cchMaxPath);
897         return NOERROR;
898 }
899
900 static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl)
901 {
902         ICOM_THIS(IShellLinkWImpl, iface);
903         
904         FIXME(shell,"(%p)->(ppidl=%p)\n",This, ppidl);
905         *ppidl = _ILCreateDesktop();
906         return NOERROR;
907 }
908
909 static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl)
910 {
911         ICOM_THIS(IShellLinkWImpl, iface);
912         
913         FIXME(shell,"(%p)->(pidl=%p)\n",This, pidl);
914         return NOERROR;
915 }
916
917 static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName)
918 {
919         ICOM_THIS(IShellLinkWImpl, iface);
920         
921         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
922         lstrcpynAtoW(pszName,"Description, FIXME",cchMaxName);
923         return NOERROR;
924 }
925
926 static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName)
927 {
928         ICOM_THIS(IShellLinkWImpl, iface);
929         
930         FIXME(shell,"(%p)->(desc=%s)\n",This, debugstr_w(pszName));
931         return NOERROR;
932 }
933
934 static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath)
935 {
936         ICOM_THIS(IShellLinkWImpl, iface);
937         
938         FIXME(shell,"(%p)->()\n",This);
939         lstrcpynAtoW(pszDir,"c:\\", cchMaxPath);
940         return NOERROR;
941 }
942
943 static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir)
944 {
945         ICOM_THIS(IShellLinkWImpl, iface);
946         
947         FIXME(shell,"(%p)->(dir=%s)\n",This, debugstr_w(pszDir));
948         return NOERROR;
949 }
950
951 static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath)
952 {
953         ICOM_THIS(IShellLinkWImpl, iface);
954         
955         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszArgs, cchMaxPath);
956         lstrcpynAtoW(pszArgs, "", cchMaxPath);
957         return NOERROR;
958 }
959
960 static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs)
961 {
962         ICOM_THIS(IShellLinkWImpl, iface);
963         
964         FIXME(shell,"(%p)->(args=%s)\n",This, debugstr_w(pszArgs));
965         return NOERROR;
966 }
967
968 static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey)
969 {
970         ICOM_THIS(IShellLinkWImpl, iface);
971         
972         FIXME(shell,"(%p)->(%p)\n",This, pwHotkey);
973         *pwHotkey=0x0;
974         return NOERROR;
975 }
976
977 static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey)
978 {
979         ICOM_THIS(IShellLinkWImpl, iface);
980         
981         FIXME(shell,"(%p)->(hotkey=%x)\n",This, wHotkey);
982         return NOERROR;
983 }
984
985 static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd)
986 {
987         ICOM_THIS(IShellLinkWImpl, iface);
988         
989         FIXME(shell,"(%p)->(%p)\n",This, piShowCmd);
990         *piShowCmd=0;
991         return NOERROR;
992 }
993
994 static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd)
995 {
996         ICOM_THIS(IShellLinkWImpl, iface);
997         
998         FIXME(shell,"(%p)->(showcmd=%x)\n",This, iShowCmd);
999         return NOERROR;
1000 }
1001
1002 static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon)
1003 {
1004         ICOM_THIS(IShellLinkWImpl, iface);
1005         
1006         FIXME(shell,"(%p)->(%p len=%u iicon=%p)\n",This, pszIconPath, cchIconPath, piIcon);
1007         lstrcpynAtoW(pszIconPath,"shell32.dll",cchIconPath);
1008         *piIcon=1;
1009         return NOERROR;
1010 }
1011
1012 static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon)
1013 {
1014         ICOM_THIS(IShellLinkWImpl, iface);
1015         
1016         FIXME(shell,"(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon);
1017         return NOERROR;
1018 }
1019
1020 static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved)
1021 {
1022         ICOM_THIS(IShellLinkWImpl, iface);
1023         
1024         FIXME(shell,"(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved);
1025         return NOERROR;
1026 }
1027
1028 static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags)
1029 {
1030         ICOM_THIS(IShellLinkWImpl, iface);
1031         
1032         FIXME(shell,"(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
1033         return NOERROR;
1034 }
1035
1036 static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile)
1037 {
1038         ICOM_THIS(IShellLinkWImpl, iface);
1039         
1040         FIXME(shell,"(%p)->(path=%s)\n",This, debugstr_w(pszFile));
1041         return NOERROR;
1042 }
1043
1044 /**************************************************************************
1045 * IShellLinkW Implementation
1046 */
1047
1048 static ICOM_VTABLE(IShellLinkW) slvtw = 
1049 {       IShellLinkW_fnQueryInterface,
1050         IShellLinkW_fnAddRef,
1051         IShellLinkW_fnRelease,
1052         IShellLinkW_fnGetPath,
1053         IShellLinkW_fnGetIDList,
1054         IShellLinkW_fnSetIDList,
1055         IShellLinkW_fnGetDescription,
1056         IShellLinkW_fnSetDescription,
1057         IShellLinkW_fnGetWorkingDirectory,
1058         IShellLinkW_fnSetWorkingDirectory,
1059         IShellLinkW_fnGetArguments,
1060         IShellLinkW_fnSetArguments,
1061         IShellLinkW_fnGetHotkey,
1062         IShellLinkW_fnSetHotkey,
1063         IShellLinkW_fnGetShowCmd,
1064         IShellLinkW_fnSetShowCmd,
1065         IShellLinkW_fnGetIconLocation,
1066         IShellLinkW_fnSetIconLocation,
1067         IShellLinkW_fnSetRelativePath,
1068         IShellLinkW_fnResolve,
1069         IShellLinkW_fnSetPath
1070 };
1071