Converted to the new debugging interface (done with the help of the
[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 #include "pshpack1.h"
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 #include "poppack.h"
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         if (!pcheck (&pImage->Pidl))
213           goto end_3;
214         
215         This->pPidl = ILClone (&pImage->Pidl);
216
217         _ILGetPidlPath(&pImage->Pidl, sTemp, 512);
218         This->sPath = HEAP_strdupA ( GetProcessHeap(), 0, sTemp);
219                         
220         hRet = NOERROR;
221 end_3:  UnmapViewOfFile(pImage);
222 end_2:  CloseHandle(hMapping);
223 end_1:  _lclose( hFile);
224
225         return hRet;
226 }
227
228 static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember)
229 {
230         ICOM_THIS(IPersistFileImpl,iface);
231         FIXME(shell,"(%p)->(%s)\n",This,debugstr_w(pszFileName));
232         return NOERROR;
233 }
234 static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName)
235 {
236         ICOM_THIS(IPersistFileImpl,iface);
237         FIXME(shell,"(%p)->(%s)\n",This,debugstr_w(pszFileName));
238         return NOERROR;
239 }
240 static HRESULT WINAPI IPersistFile_fnGetCurFile(const IPersistFile* iface, LPOLESTR *ppszFileName)
241 {
242         ICOM_CTHIS(IPersistFileImpl,iface);
243         FIXME(shell,"(%p)\n",This);
244         return NOERROR;
245 }
246   
247 static struct ICOM_VTABLE(IPersistFile) pfvt = 
248 {
249         IPersistFile_fnQueryInterface,
250         IPersistFile_fnAddRef,
251         IPersistFile_fnRelease,
252         IPersistFile_fnGetClassID,
253         IPersistFile_fnIsDirty,
254         IPersistFile_fnLoad,
255         IPersistFile_fnSave,
256         IPersistFile_fnSaveCompleted,
257         IPersistFile_fnGetCurFile
258 };
259
260
261 /**************************************************************************
262 *  IShellLink's IClassFactory implementation
263  */
264 typedef struct
265 {
266     /* IUnknown fields */
267     ICOM_VTABLE(IClassFactory)* lpvtbl;
268     DWORD                       ref;
269 } IClassFactoryImpl;
270
271 static ICOM_VTABLE(IClassFactory) slcfvt;
272
273 /**************************************************************************
274  *  IShellLink_CF_Constructor
275  */
276
277 LPCLASSFACTORY IShellLink_CF_Constructor(void)
278 {
279         IClassFactoryImpl* lpclf;
280
281         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
282         lpclf->ref = 1;
283         lpclf->lpvtbl = &slcfvt;
284         TRACE(shell,"(%p)->()\n",lpclf);
285         shell32_ObjCount++;
286         return (LPCLASSFACTORY)lpclf;
287 }
288 /**************************************************************************
289  *  IShellLink_CF_QueryInterface
290  */
291 static HRESULT WINAPI IShellLink_CF_QueryInterface(
292   IClassFactory* iface, REFIID riid, LPVOID *ppvObj)
293 {
294         ICOM_THIS(IClassFactoryImpl,iface);
295         char    xriid[50];
296         WINE_StringFromCLSID((LPCLSID)riid,xriid);
297         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
298
299         *ppvObj = NULL;
300
301         if(IsEqualIID(riid, &IID_IUnknown))             /*IUnknown*/
302         { *ppvObj = (LPUNKNOWN)This; 
303         }
304         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
305         { *ppvObj = (LPCLASSFACTORY)This;
306         }   
307
308         if(*ppvObj)
309         { IUnknown_AddRef((IUnknown*)*ppvObj);          
310           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
311           return S_OK;
312         }
313         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
314         return E_NOINTERFACE;
315 }  
316 /******************************************************************************
317  * IShellLink_CF_AddRef
318  */
319 static ULONG WINAPI IShellLink_CF_AddRef(IClassFactory* iface)
320 {
321         ICOM_THIS(IClassFactoryImpl,iface);
322         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
323
324         shell32_ObjCount++;
325         return ++(This->ref);
326 }
327 /******************************************************************************
328  * IShellLink_CF_Release
329  */
330 static ULONG WINAPI IShellLink_CF_Release(IClassFactory* iface)
331 {
332         ICOM_THIS(IClassFactoryImpl,iface);
333         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
334
335         shell32_ObjCount--;
336         if (!--(This->ref)) 
337         { TRACE(shell,"-- destroying IClassFactory(%p)\n",This);
338                 HeapFree(GetProcessHeap(),0,This);
339                 return 0;
340         }
341         return This->ref;
342 }
343 /******************************************************************************
344  * IShellLink_CF_CreateInstance
345  */
346 static HRESULT WINAPI IShellLink_CF_CreateInstance(
347   IClassFactory* iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
348 {
349         ICOM_THIS(IClassFactoryImpl,iface);
350         IUnknown *pObj = NULL;
351         HRESULT hres;
352         char    xriid[50];
353
354         WINE_StringFromCLSID((LPCLSID)riid,xriid);
355         TRACE(shell,"%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
356
357         *ppObject = NULL;
358                 
359         if(pUnknown)
360         {       return(CLASS_E_NOAGGREGATION);
361         }
362
363         if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellLink))
364         { pObj = (IUnknown *)IShellLink_Constructor();
365         } 
366         else
367         { ERR(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
368           return(E_NOINTERFACE);
369         }
370         
371         if (!pObj)
372         { return(E_OUTOFMEMORY);
373         }
374          
375         hres = IUnknown_QueryInterface(pObj,riid, ppObject);
376         IUnknown_Release(pObj);
377         TRACE(shell,"-- Object created: (%p)->%p\n",This,*ppObject);
378
379         return hres;
380 }
381 /******************************************************************************
382  * IShellLink_CF_LockServer
383  */
384 static HRESULT WINAPI IShellLink_CF_LockServer(IClassFactory* iface, BOOL fLock)
385 {
386         ICOM_THIS(IClassFactoryImpl,iface);
387         TRACE(shell,"%p->(0x%x), not implemented\n",This, fLock);
388         return E_NOTIMPL;
389 }
390 static ICOM_VTABLE(IClassFactory) slcfvt = 
391 {
392     IShellLink_CF_QueryInterface,
393     IShellLink_CF_AddRef,
394   IShellLink_CF_Release,
395   IShellLink_CF_CreateInstance,
396   IShellLink_CF_LockServer
397 };
398
399 /**************************************************************************
400  * IShellLink Implementation 
401  */
402
403 typedef struct
404 {
405         ICOM_VTABLE(IShellLink)*        lpvtbl;
406         DWORD                           ref;
407         IPersistFileImpl*               lppf;
408
409 } IShellLinkImpl;
410
411 static ICOM_VTABLE(IShellLink) slvt;
412
413 /**************************************************************************
414  *        IShellLink_Constructor
415  */
416 IShellLink * IShellLink_Constructor(void) 
417 {       IShellLinkImpl * sl;
418
419         sl = (IShellLinkImpl *)HeapAlloc(GetProcessHeap(),0,sizeof(IShellLinkImpl));
420         sl->ref = 1;
421         sl->lpvtbl = &slvt;
422
423         sl->lppf = IPersistFile_Constructor();
424
425         TRACE(shell,"(%p)->()\n",sl);
426         shell32_ObjCount++;
427         return (IShellLink *)sl;
428 }
429
430 /**************************************************************************
431  *  IShellLink::QueryInterface
432  */
433 static HRESULT WINAPI IShellLink_fnQueryInterface( IShellLink * iface, REFIID riid,  LPVOID *ppvObj)
434 {
435         ICOM_THIS(IShellLinkImpl, iface);
436         
437         char    xriid[50];
438         WINE_StringFromCLSID((LPCLSID)riid,xriid);
439         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
440
441         *ppvObj = NULL;
442
443         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
444         { *ppvObj = This; 
445         }
446         else if(IsEqualIID(riid, &IID_IShellLink))  /*IShellLink*/
447         {    *ppvObj = (IShellLink *)This;
448         }   
449         else if(IsEqualIID(riid, &IID_IPersistFile))  /*IPersistFile*/
450         {    *ppvObj = (IPersistFile *)This->lppf;
451         }   
452
453         if(*ppvObj)
454         { IShellLink_AddRef((IShellLink*)*ppvObj);      
455           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
456           return S_OK;
457         }
458         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
459         return E_NOINTERFACE;
460 }  
461 /******************************************************************************
462  * IShellLink_AddRef
463  */
464 static ULONG WINAPI IShellLink_fnAddRef(IShellLink * iface)
465 {
466         ICOM_THIS(IShellLinkImpl, iface);
467         
468         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
469
470         shell32_ObjCount++;
471         return ++(This->ref);
472 }
473 /******************************************************************************
474  *      IShellLink_Release
475  */
476 static ULONG WINAPI IShellLink_fnRelease(IShellLink * iface)
477 {
478         ICOM_THIS(IShellLinkImpl, iface);
479         
480         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
481
482         shell32_ObjCount--;
483         if (!--(This->ref)) 
484         { TRACE(shell,"-- destroying IShellLink(%p)\n",This);
485           IPersistFile_Release((IPersistFile*) This->lppf);     /* IPersistFile*/
486           HeapFree(GetProcessHeap(),0,This);
487           return 0;
488         }
489         return This->ref;
490 }
491
492 static HRESULT WINAPI IShellLink_fnGetPath(IShellLink * iface, LPSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
493 {
494         ICOM_THIS(IShellLinkImpl, iface);
495         
496         TRACE(shell,"(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This, pszFile, cchMaxPath, pfd, fFlags);
497
498         strncpy(pszFile,This->lppf->sPath, cchMaxPath);
499         return NOERROR;
500 }
501 static HRESULT WINAPI IShellLink_fnGetIDList(IShellLink * iface, LPITEMIDLIST * ppidl)
502 {
503         ICOM_THIS(IShellLinkImpl, iface);
504         
505         TRACE(shell,"(%p)->(ppidl=%p)\n",This, ppidl);
506
507         *ppidl = ILClone(This->lppf->pPidl);
508         return NOERROR;
509 }
510 static HRESULT WINAPI IShellLink_fnSetIDList(IShellLink * iface, LPCITEMIDLIST pidl)
511 {
512         ICOM_THIS(IShellLinkImpl, iface);
513         
514         TRACE (shell,"(%p)->(pidl=%p)\n",This, pidl);
515
516         if (This->lppf->pPidl)
517             SHFree(This->lppf->pPidl);
518         This->lppf->pPidl = ILClone (pidl);
519         return NOERROR;
520 }
521 static HRESULT WINAPI IShellLink_fnGetDescription(IShellLink * iface, LPSTR pszName,INT cchMaxName)
522 {
523         ICOM_THIS(IShellLinkImpl, iface);
524         
525         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
526         strncpy(pszName,"Description, FIXME",cchMaxName);
527         return NOERROR;
528 }
529 static HRESULT WINAPI IShellLink_fnSetDescription(IShellLink * iface, LPCSTR pszName)
530 {
531         ICOM_THIS(IShellLinkImpl, iface);
532         
533         FIXME(shell,"(%p)->(desc=%s)\n",This, pszName);
534         return NOERROR;
535 }
536 static HRESULT WINAPI IShellLink_fnGetWorkingDirectory(IShellLink * iface, LPSTR pszDir,INT cchMaxPath)
537 {
538         ICOM_THIS(IShellLinkImpl, iface);
539         
540         FIXME(shell,"(%p)->()\n",This);
541         strncpy(pszDir,"c:\\", cchMaxPath);
542         return NOERROR;
543 }
544 static HRESULT WINAPI IShellLink_fnSetWorkingDirectory(IShellLink * iface, LPCSTR pszDir)
545 {
546         ICOM_THIS(IShellLinkImpl, iface);
547         
548         FIXME(shell,"(%p)->(dir=%s)\n",This, pszDir);
549         return NOERROR;
550 }
551 static HRESULT WINAPI IShellLink_fnGetArguments(IShellLink * iface, LPSTR pszArgs,INT cchMaxPath)
552 {
553         ICOM_THIS(IShellLinkImpl, iface);
554         
555         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszArgs, cchMaxPath);
556         strncpy(pszArgs, "", cchMaxPath);
557         return NOERROR;
558 }
559 static HRESULT WINAPI IShellLink_fnSetArguments(IShellLink * iface, LPCSTR pszArgs)
560 {
561         ICOM_THIS(IShellLinkImpl, iface);
562         
563         FIXME(shell,"(%p)->(args=%s)\n",This, pszArgs);
564         return NOERROR;
565 }
566 static HRESULT WINAPI IShellLink_fnGetHotkey(IShellLink * iface, WORD *pwHotkey)
567 {
568         ICOM_THIS(IShellLinkImpl, iface);
569         
570         FIXME(shell,"(%p)->(%p) returning 0\n",This, pwHotkey);
571         *pwHotkey=0x0;
572         return NOERROR;
573 }
574 static HRESULT WINAPI IShellLink_fnSetHotkey(IShellLink * iface, WORD wHotkey)
575 {
576         ICOM_THIS(IShellLinkImpl, iface);
577         
578         FIXME(shell,"(%p)->(hotkey=%x)\n",This, wHotkey);
579         return NOERROR;
580 }
581 static HRESULT WINAPI IShellLink_fnGetShowCmd(IShellLink * iface, INT *piShowCmd)
582 {
583         ICOM_THIS(IShellLinkImpl, iface);
584         
585         FIXME(shell,"(%p)->(%p)\n",This, piShowCmd);
586         *piShowCmd=0;
587         return NOERROR;
588 }
589 static HRESULT WINAPI IShellLink_fnSetShowCmd(IShellLink * iface, INT iShowCmd)
590 {
591         ICOM_THIS(IShellLinkImpl, iface);
592         
593         FIXME(shell,"(%p)->(showcmd=%x)\n",This, iShowCmd);
594         return NOERROR;
595 }
596 static HRESULT WINAPI IShellLink_fnGetIconLocation(IShellLink * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon)
597 {
598         ICOM_THIS(IShellLinkImpl, iface);
599         
600         FIXME(shell,"(%p)->(%p len=%u iicon=%p)\n",This, pszIconPath, cchIconPath, piIcon);
601         strncpy(pszIconPath,"shell32.dll",cchIconPath);
602         *piIcon=1;
603         return NOERROR;
604 }
605 static HRESULT WINAPI IShellLink_fnSetIconLocation(IShellLink * iface, LPCSTR pszIconPath,INT iIcon)
606 {
607         ICOM_THIS(IShellLinkImpl, iface);
608         
609         FIXME(shell,"(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon);
610         return NOERROR;
611 }
612 static HRESULT WINAPI IShellLink_fnSetRelativePath(IShellLink * iface, LPCSTR pszPathRel, DWORD dwReserved)
613 {
614         ICOM_THIS(IShellLinkImpl, iface);
615         
616         FIXME(shell,"(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved);
617         return NOERROR;
618 }
619 static HRESULT WINAPI IShellLink_fnResolve(IShellLink * iface, HWND hwnd, DWORD fFlags)
620 {
621         ICOM_THIS(IShellLinkImpl, iface);
622         
623         FIXME(shell,"(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
624         return NOERROR;
625 }
626 static HRESULT WINAPI IShellLink_fnSetPath(IShellLink * iface, LPCSTR pszFile)
627 {
628         ICOM_THIS(IShellLinkImpl, iface);
629         
630         FIXME(shell,"(%p)->(path=%s)\n",This, pszFile);
631         return NOERROR;
632 }
633
634 /**************************************************************************
635 * IShellLink Implementation
636 */
637
638 static ICOM_VTABLE(IShellLink) slvt = 
639 {       IShellLink_fnQueryInterface,
640         IShellLink_fnAddRef,
641         IShellLink_fnRelease,
642         IShellLink_fnGetPath,
643         IShellLink_fnGetIDList,
644         IShellLink_fnSetIDList,
645         IShellLink_fnGetDescription,
646         IShellLink_fnSetDescription,
647         IShellLink_fnGetWorkingDirectory,
648         IShellLink_fnSetWorkingDirectory,
649         IShellLink_fnGetArguments,
650         IShellLink_fnSetArguments,
651         IShellLink_fnGetHotkey,
652         IShellLink_fnSetHotkey,
653         IShellLink_fnGetShowCmd,
654         IShellLink_fnSetShowCmd,
655         IShellLink_fnGetIconLocation,
656         IShellLink_fnSetIconLocation,
657         IShellLink_fnSetRelativePath,
658         IShellLink_fnResolve,
659         IShellLink_fnSetPath
660 };
661
662 /**************************************************************************
663 *  IShellLink's IClassFactory implementation
664 */
665
666 static ICOM_VTABLE(IClassFactory) slwcfvt;
667
668 /**************************************************************************
669  *  IShellLinkW_CF_Constructor
670  */
671
672 LPCLASSFACTORY IShellLinkW_CF_Constructor(void)
673 {
674         IClassFactoryImpl* lpclf;
675
676         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
677         lpclf->ref = 1;
678         lpclf->lpvtbl = &slwcfvt;
679         TRACE(shell,"(%p)->()\n",lpclf);
680         shell32_ObjCount++;
681         return (LPCLASSFACTORY)lpclf;
682 }
683 /**************************************************************************
684  *  IShellLinkW_CF_QueryInterface
685  */
686 static HRESULT WINAPI IShellLinkW_CF_QueryInterface(
687   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
688 {
689         ICOM_THIS(IClassFactoryImpl,iface);
690         char    xriid[50];
691         WINE_StringFromCLSID((LPCLSID)riid,xriid);
692         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
693
694         *ppvObj = NULL;
695
696         if(IsEqualIID(riid, &IID_IUnknown))             /*IUnknown*/
697         { *ppvObj = (LPUNKNOWN)This; 
698         }
699         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
700         { *ppvObj = (LPCLASSFACTORY)This;
701         }   
702
703         if(*ppvObj) {
704           IUnknown_AddRef((IUnknown*)*ppvObj);          
705           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
706           return S_OK;
707         }
708         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
709         return E_NOINTERFACE;
710 }  
711 /******************************************************************************
712  * IShellLinkW_CF_AddRef
713  */
714 static ULONG WINAPI IShellLinkW_CF_AddRef(LPCLASSFACTORY iface)
715 {
716         ICOM_THIS(IClassFactoryImpl,iface);
717         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
718
719         shell32_ObjCount++;
720         return ++(This->ref);
721 }
722 /******************************************************************************
723  * IShellLinkW_CF_Release
724  */
725 static ULONG WINAPI IShellLinkW_CF_Release(LPCLASSFACTORY iface)
726 {
727         ICOM_THIS(IClassFactoryImpl,iface);
728         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
729
730         shell32_ObjCount--;
731         if (!--(This->ref)) 
732         { TRACE(shell,"-- destroying IClassFactory(%p)\n",This);
733                 HeapFree(GetProcessHeap(),0,This);
734                 return 0;
735         }
736         return This->ref;
737 }
738 /******************************************************************************
739  * IShellLinkW_CF_CreateInstance
740  */
741 static HRESULT WINAPI IShellLinkW_CF_CreateInstance(
742   LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
743 {
744         ICOM_THIS(IClassFactoryImpl,iface);
745         IUnknown *pObj = NULL;
746         HRESULT hres;
747         char    xriid[50];
748
749         WINE_StringFromCLSID((LPCLSID)riid,xriid);
750         TRACE(shell,"%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
751
752         *ppObject = NULL;
753                 
754         if(pUnknown)
755         { return(CLASS_E_NOAGGREGATION);
756         }
757
758         if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellLinkW))
759         { pObj = (IUnknown *)IShellLinkW_Constructor();
760         } 
761         else
762         { ERR(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
763           return(E_NOINTERFACE);
764         }
765         
766         if (!pObj)
767         { return(E_OUTOFMEMORY);
768         }
769          
770         hres = pObj->lpvtbl->fnQueryInterface(pObj,riid, ppObject);
771         pObj->lpvtbl->fnRelease(pObj);
772         TRACE(shell,"-- Object created: (%p)->%p\n",This,*ppObject);
773
774         return hres;
775 }
776 /******************************************************************************
777  * IShellLinkW_CF_LockServer
778  */
779
780 static HRESULT WINAPI IShellLinkW_CF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
781 {
782         ICOM_THIS(IClassFactoryImpl,iface);
783         TRACE(shell,"%p->(0x%x), not implemented\n",This, fLock);
784         return E_NOTIMPL;
785 }
786
787 static ICOM_VTABLE(IClassFactory) slwcfvt = 
788 {
789     IShellLinkW_CF_QueryInterface,
790     IShellLinkW_CF_AddRef,
791   IShellLinkW_CF_Release,
792   IShellLinkW_CF_CreateInstance,
793   IShellLinkW_CF_LockServer
794 };
795
796
797 /**************************************************************************
798  * IShellLink Implementation 
799  */
800
801 typedef struct 
802 {
803         ICOM_VTABLE(IShellLinkW)*       lpvtbl;
804         DWORD                           ref;
805         IPersistFileImpl*               lppf;
806
807 } IShellLinkWImpl;
808
809 static ICOM_VTABLE(IShellLinkW) slvtw;
810
811 /**************************************************************************
812  *        IShellLinkW_fnConstructor
813  */
814 IShellLinkW * IShellLinkW_Constructor(void) 
815 {       IShellLinkWImpl* sl;
816
817         sl = (IShellLinkWImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IShellLinkWImpl));
818         sl->ref = 1;
819         sl->lpvtbl = &slvtw;
820
821         sl->lppf = IPersistFile_Constructor();
822
823         TRACE(shell,"(%p)->()\n",sl);
824         shell32_ObjCount++;
825         return (IShellLinkW*)sl;
826 }
827
828 /**************************************************************************
829  *  IShellLinkW_fnQueryInterface
830  */
831 static HRESULT WINAPI IShellLinkW_fnQueryInterface(
832   IShellLinkW * iface, REFIID riid, LPVOID *ppvObj)
833 {
834         ICOM_THIS(IShellLinkWImpl, iface);
835         
836         char    xriid[50];
837         WINE_StringFromCLSID((LPCLSID)riid,xriid);
838         TRACE(shell,"(%p)->(\n\tIID:\t%s)\n",This,xriid);
839
840         *ppvObj = NULL;
841
842         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
843         { *ppvObj = This; 
844         }
845         else if(IsEqualIID(riid, &IID_IShellLinkW))  /*IShellLinkW*/
846         {    *ppvObj = (IShellLinkW *)This;
847         }   
848         else if(IsEqualIID(riid, &IID_IPersistFile))  /*IPersistFile*/
849         {    *ppvObj = (IPersistFile *)This->lppf;
850         }   
851
852         if(*ppvObj)
853         { IShellLink_AddRef((IShellLinkW*)*ppvObj);      
854           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
855           return S_OK;
856         }
857
858         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
859
860         return E_NOINTERFACE;
861 }  
862 /******************************************************************************
863  * IShellLinkW_fnAddRef
864  */
865 static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface)
866 {
867         ICOM_THIS(IShellLinkWImpl, iface);
868         
869         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
870
871         shell32_ObjCount++;
872         return ++(This->ref);
873 }
874 /******************************************************************************
875  * IShellLinkW_fnRelease
876  */
877
878 static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface)
879 {
880         ICOM_THIS(IShellLinkWImpl, iface);
881         
882         TRACE(shell,"(%p)->(count=%lu)\n",This,This->ref);
883
884         shell32_ObjCount--;
885         if (!--(This->ref)) 
886         { TRACE(shell,"-- destroying IShellLinkW(%p)\n",This);
887           IPersistFile_Release((IPersistFile*)This->lppf);      /* IPersistFile*/
888           HeapFree(GetProcessHeap(),0,This);
889           return 0;
890         }
891         return This->ref;
892 }
893
894 static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
895 {
896         ICOM_THIS(IShellLinkWImpl, iface);
897         
898         FIXME(shell,"(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This, pszFile, cchMaxPath, pfd, fFlags);
899         lstrcpynAtoW(pszFile,"c:\\foo.bar", cchMaxPath);
900         return NOERROR;
901 }
902
903 static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl)
904 {
905         ICOM_THIS(IShellLinkWImpl, iface);
906         
907         FIXME(shell,"(%p)->(ppidl=%p)\n",This, ppidl);
908         *ppidl = _ILCreateDesktop();
909         return NOERROR;
910 }
911
912 static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl)
913 {
914         ICOM_THIS(IShellLinkWImpl, iface);
915         
916         FIXME(shell,"(%p)->(pidl=%p)\n",This, pidl);
917         return NOERROR;
918 }
919
920 static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName)
921 {
922         ICOM_THIS(IShellLinkWImpl, iface);
923         
924         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
925         lstrcpynAtoW(pszName,"Description, FIXME",cchMaxName);
926         return NOERROR;
927 }
928
929 static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName)
930 {
931         ICOM_THIS(IShellLinkWImpl, iface);
932         
933         FIXME(shell,"(%p)->(desc=%s)\n",This, debugstr_w(pszName));
934         return NOERROR;
935 }
936
937 static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath)
938 {
939         ICOM_THIS(IShellLinkWImpl, iface);
940         
941         FIXME(shell,"(%p)->()\n",This);
942         lstrcpynAtoW(pszDir,"c:\\", cchMaxPath);
943         return NOERROR;
944 }
945
946 static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir)
947 {
948         ICOM_THIS(IShellLinkWImpl, iface);
949         
950         FIXME(shell,"(%p)->(dir=%s)\n",This, debugstr_w(pszDir));
951         return NOERROR;
952 }
953
954 static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath)
955 {
956         ICOM_THIS(IShellLinkWImpl, iface);
957         
958         FIXME(shell,"(%p)->(%p len=%u)\n",This, pszArgs, cchMaxPath);
959         lstrcpynAtoW(pszArgs, "", cchMaxPath);
960         return NOERROR;
961 }
962
963 static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs)
964 {
965         ICOM_THIS(IShellLinkWImpl, iface);
966         
967         FIXME(shell,"(%p)->(args=%s)\n",This, debugstr_w(pszArgs));
968         return NOERROR;
969 }
970
971 static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey)
972 {
973         ICOM_THIS(IShellLinkWImpl, iface);
974         
975         FIXME(shell,"(%p)->(%p)\n",This, pwHotkey);
976         *pwHotkey=0x0;
977         return NOERROR;
978 }
979
980 static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey)
981 {
982         ICOM_THIS(IShellLinkWImpl, iface);
983         
984         FIXME(shell,"(%p)->(hotkey=%x)\n",This, wHotkey);
985         return NOERROR;
986 }
987
988 static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd)
989 {
990         ICOM_THIS(IShellLinkWImpl, iface);
991         
992         FIXME(shell,"(%p)->(%p)\n",This, piShowCmd);
993         *piShowCmd=0;
994         return NOERROR;
995 }
996
997 static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd)
998 {
999         ICOM_THIS(IShellLinkWImpl, iface);
1000         
1001         FIXME(shell,"(%p)->(showcmd=%x)\n",This, iShowCmd);
1002         return NOERROR;
1003 }
1004
1005 static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon)
1006 {
1007         ICOM_THIS(IShellLinkWImpl, iface);
1008         
1009         FIXME(shell,"(%p)->(%p len=%u iicon=%p)\n",This, pszIconPath, cchIconPath, piIcon);
1010         lstrcpynAtoW(pszIconPath,"shell32.dll",cchIconPath);
1011         *piIcon=1;
1012         return NOERROR;
1013 }
1014
1015 static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon)
1016 {
1017         ICOM_THIS(IShellLinkWImpl, iface);
1018         
1019         FIXME(shell,"(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon);
1020         return NOERROR;
1021 }
1022
1023 static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved)
1024 {
1025         ICOM_THIS(IShellLinkWImpl, iface);
1026         
1027         FIXME(shell,"(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved);
1028         return NOERROR;
1029 }
1030
1031 static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags)
1032 {
1033         ICOM_THIS(IShellLinkWImpl, iface);
1034         
1035         FIXME(shell,"(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
1036         return NOERROR;
1037 }
1038
1039 static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile)
1040 {
1041         ICOM_THIS(IShellLinkWImpl, iface);
1042         
1043         FIXME(shell,"(%p)->(path=%s)\n",This, debugstr_w(pszFile));
1044         return NOERROR;
1045 }
1046
1047 /**************************************************************************
1048 * IShellLinkW Implementation
1049 */
1050
1051 static ICOM_VTABLE(IShellLinkW) slvtw = 
1052 {       IShellLinkW_fnQueryInterface,
1053         IShellLinkW_fnAddRef,
1054         IShellLinkW_fnRelease,
1055         IShellLinkW_fnGetPath,
1056         IShellLinkW_fnGetIDList,
1057         IShellLinkW_fnSetIDList,
1058         IShellLinkW_fnGetDescription,
1059         IShellLinkW_fnSetDescription,
1060         IShellLinkW_fnGetWorkingDirectory,
1061         IShellLinkW_fnSetWorkingDirectory,
1062         IShellLinkW_fnGetArguments,
1063         IShellLinkW_fnSetArguments,
1064         IShellLinkW_fnGetHotkey,
1065         IShellLinkW_fnSetHotkey,
1066         IShellLinkW_fnGetShowCmd,
1067         IShellLinkW_fnSetShowCmd,
1068         IShellLinkW_fnGetIconLocation,
1069         IShellLinkW_fnSetIconLocation,
1070         IShellLinkW_fnSetRelativePath,
1071         IShellLinkW_fnResolve,
1072         IShellLinkW_fnSetPath
1073 };
1074