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