source: trunk/src/shell32/shelllink.c@ 7343

Last change on this file since 7343 was 7343, checked in by sandervl, 24 years ago

removed unnecessary changes

File size: 44.4 KB
Line 
1/*
2 *
3 * Copyright 1997 Marcus Meissner
4 * Copyright 1998 Juergen Schmied
5 *
6 */
7
8#include "config.h"
9
10#include <string.h>
11#include <sys/stat.h>
12#include <stdio.h>
13#ifndef __WIN32OS2__
14#include <unistd.h>
15#endif
16#include <errno.h>
17#ifdef HAVE_SYS_WAIT_H
18# include <sys/wait.h>
19#endif
20#include "debugtools.h"
21#include "winerror.h"
22#include "winbase.h"
23#include "winnls.h"
24#include "winreg.h"
25
26#include "shlobj.h"
27#include "wine/undocshell.h"
28#ifdef __WIN32OS2__
29#define NO_DCDATA
30#include <winuser32.h>
31#include <winres.h>
32
33#undef WARN
34#undef TRACE
35#ifdef DEBUG
36#define TRACE WriteLog("SHELL32: %s", __FUNCTION__); WriteLog
37#define WARN WriteLog("WARNING: SHELL32: %s", __FUNCTION__); WriteLog
38#else
39#define TRACE 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
40#define WARN 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
41#endif
42
43#else
44#include "bitmaps/wine.xpm"
45#endif
46
47#include "heap.h"
48#include "pidl.h"
49#include "shell32_main.h"
50#include "shlguid.h"
51
52DEFAULT_DEBUG_CHANNEL(shell);
53
54/* link file formats */
55
56#include "pshpack1.h"
57
58/* flag1: lnk elements: simple link has 0x0B */
59#define WORKDIR 0x10
60#define ARGUMENT 0x20
61#define ICON 0x40
62#define UNC 0x80
63
64/* fStartup */
65#define NORMAL 0x01
66#define MAXIMIZED 0x03
67#define MINIMIZED 0x07
68
69typedef struct _LINK_HEADER
70{ DWORD MagicStr; /* 0x00 'L','\0','\0','\0' */
71 GUID MagicGuid; /* 0x04 is CLSID_ShellLink */
72 DWORD Flag1; /* 0x14 describes elements following */
73 DWORD Flag2; /* 0x18 */
74 FILETIME Time1; /* 0x1c */
75 FILETIME Time2; /* 0x24 */
76 FILETIME Time3; /* 0x2c */
77 DWORD Unknown1; /* 0x34 */
78 DWORD Unknown2; /* 0x38 icon number */
79 DWORD fStartup; /* 0x3c startup type */
80 DWORD wHotKey; /* 0x40 hotkey */
81 DWORD Unknown5; /* 0x44 */
82 DWORD Unknown6; /* 0x48 */
83 USHORT PidlSize; /* 0x4c */
84 ITEMIDLIST Pidl; /* 0x4e */
85} LINK_HEADER, * PLINK_HEADER;
86
87#define LINK_HEADER_SIZE (sizeof(LINK_HEADER)-sizeof(ITEMIDLIST))
88
89typedef struct
90{
91 BYTE bWidth;
92 BYTE bHeight;
93 BYTE bColorCount;
94 BYTE bReserved;
95 WORD wPlanes;
96 WORD wBitCount;
97 DWORD dwBytesInRes;
98 WORD nID;
99} GRPICONDIRENTRY;
100
101typedef struct
102{
103 WORD idReserved;
104 WORD idType;
105 WORD idCount;
106 GRPICONDIRENTRY idEntries[1];
107} GRPICONDIR;
108
109typedef struct
110{
111 BYTE bWidth;
112 BYTE bHeight;
113 BYTE bColorCount;
114 BYTE bReserved;
115 WORD wPlanes;
116 WORD wBitCount;
117 DWORD dwBytesInRes;
118 DWORD dwImageOffset;
119} ICONDIRENTRY;
120
121typedef struct
122{
123 WORD idReserved;
124 WORD idType;
125 WORD idCount;
126} ICONDIR;
127
128
129#include "poppack.h"
130
131
132static ICOM_VTABLE(IShellLinkA) slvt;
133static ICOM_VTABLE(IShellLinkW) slvtw;
134static ICOM_VTABLE(IPersistFile) pfvt;
135static ICOM_VTABLE(IPersistStream) psvt;
136
137/* IShellLink Implementation */
138
139typedef struct
140{
141 ICOM_VFIELD(IShellLinkA);
142 DWORD ref;
143
144 ICOM_VTABLE(IShellLinkW)* lpvtblw;
145 ICOM_VTABLE(IPersistFile)* lpvtblPersistFile;
146 ICOM_VTABLE(IPersistStream)* lpvtblPersistStream;
147
148 /* internal stream of the IPersistFile interface */
149 IStream* lpFileStream;
150
151 /* data structures according to the informations in the lnk */
152 LPSTR sPath;
153 LPITEMIDLIST pPidl;
154 WORD wHotKey;
155 SYSTEMTIME time1;
156 SYSTEMTIME time2;
157 SYSTEMTIME time3;
158
159 LPSTR sIcoPath;
160 INT iIcoNdx;
161 LPSTR sArgs;
162 LPSTR sWorkDir;
163 LPSTR sDescription;
164} IShellLinkImpl;
165
166#define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw)))
167#define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset);
168
169#define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile)))
170#define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset);
171
172#define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream)))
173#define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset);
174#define _IPersistStream_From_ICOM_THIS(class, name) class* StreamThis = (class*)(((char*)name)+_IPersistStream_Offset);
175
176/**************************************************************************
177 * IPersistFile_QueryInterface
178 */
179static HRESULT WINAPI IPersistFile_fnQueryInterface(
180 IPersistFile* iface,
181 REFIID riid,
182 LPVOID *ppvObj)
183{
184 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
185
186 TRACE("(%p)\n",This);
187
188 return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj);
189}
190
191/******************************************************************************
192 * IPersistFile_AddRef
193 */
194static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile* iface)
195{
196 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
197
198 TRACE("(%p)->(count=%lu)\n",This,This->ref);
199
200 return IShellLinkA_AddRef((IShellLinkA*)This);
201}
202/******************************************************************************
203 * IPersistFile_Release
204 */
205static ULONG WINAPI IPersistFile_fnRelease(IPersistFile* iface)
206{
207 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
208
209 TRACE("(%p)->(count=%lu)\n",This,This->ref);
210
211 return IShellLinkA_Release((IShellLinkA*)This);
212}
213
214static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile* iface, CLSID *pClassID)
215{
216 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
217 FIXME("(%p)\n",This);
218 return NOERROR;
219}
220static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile* iface)
221{
222 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
223 FIXME("(%p)\n",This);
224 return NOERROR;
225}
226static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode)
227{
228 HRESULT hRet = E_FAIL;
229 LPSTR sFile;
230
231 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
232 _IPersistStream_From_ICOM_THIS(IPersistStream, This)
233
234 sFile = HEAP_strdupWtoA ( GetProcessHeap(), 0, pszFileName);
235
236 TRACE("(%p, %s)\n",This, sFile);
237
238
239 if (This->lpFileStream)
240 IStream_Release(This->lpFileStream);
241
242 if SUCCEEDED(CreateStreamOnFile(sFile, &(This->lpFileStream)))
243 {
244 if SUCCEEDED (IPersistStream_Load(StreamThis, This->lpFileStream))
245 {
246 hRet = NOERROR;
247 }
248 }
249
250#ifdef __WIN32OS2__
251 // PH 2001-11-13 memory leak in WINE?
252 HeapFree( GetProcessHeap(), 0, sFile);
253#endif
254
255 return hRet;
256}
257
258
259#ifdef __WIN32OS2__
260static BOOL SaveIconResAsOS2ICO(GRPICONDIR *pIconDir, HINSTANCE hInstance,
261 const char *szXPMFileName)
262{
263 FILE *fXPMFile;
264 void *lpOS2Icon;
265 DWORD ressize;
266
267 if (!(fXPMFile = fopen(szXPMFileName, "wb")))
268 return 0;
269
270 lpOS2Icon = ConvertIconGroup((void *)pIconDir, hInstance, &ressize);
271 if(lpOS2Icon) {
272 fwrite(lpOS2Icon, 1, ressize, fXPMFile);
273 free(lpOS2Icon);
274 }
275 fclose(fXPMFile);
276 return 1;
277}
278#else
279/* Icon extraction routines
280 *
281 * FIXME: should use PrivateExtractIcons and friends
282 * FIXME: should not use stdio
283 */
284
285static BOOL SaveIconResAsXPM(const BITMAPINFO *pIcon, const char *szXPMFileName)
286{
287 FILE *fXPMFile;
288 int nHeight;
289 int nXORWidthBytes;
290 int nANDWidthBytes;
291 BOOL b8BitColors;
292 int nColors;
293 BYTE *pXOR;
294 BYTE *pAND;
295 BOOL aColorUsed[256] = {0};
296 int nColorsUsed = 0;
297 int i,j;
298
299 if (!((pIcon->bmiHeader.biBitCount == 4) || (pIcon->bmiHeader.biBitCount == 8)))
300 return 0;
301
302 if (!(fXPMFile = fopen(szXPMFileName, "w")))
303 return 0;
304
305 nHeight = pIcon->bmiHeader.biHeight / 2;
306 nXORWidthBytes = 4 * ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount / 32)
307 + ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount % 32) > 0));
308 nANDWidthBytes = 4 * ((pIcon->bmiHeader.biWidth / 32)
309 + ((pIcon->bmiHeader.biWidth % 32) > 0));
310 b8BitColors = pIcon->bmiHeader.biBitCount == 8;
311 nColors = pIcon->bmiHeader.biClrUsed ? pIcon->bmiHeader.biClrUsed
312 : 1 << pIcon->bmiHeader.biBitCount;
313 pXOR = (BYTE*) pIcon + sizeof (BITMAPINFOHEADER) + (nColors * sizeof (RGBQUAD));
314 pAND = pXOR + nHeight * nXORWidthBytes;
315
316#define MASK(x,y) (pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8)))
317#define COLOR(x,y) (b8BitColors ? pXOR[(x) + (nHeight - (y) - 1) * nXORWidthBytes] : (x) % 2 ? pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF : (pXOR[(x) / 2 + (nHeight - (y) - 1) * nXORWidthBytes] & 0xF0) >> 4)
318
319 for (i = 0; i < nHeight; i++)
320 for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
321 if (!aColorUsed[COLOR(j,i)] && !MASK(j,i))
322 {
323 aColorUsed[COLOR(j,i)] = TRUE;
324 nColorsUsed++;
325 }
326
327 if (fprintf(fXPMFile, "/* XPM */\nstatic char *icon[] = {\n") <= 0)
328 goto error;
329 if (fprintf(fXPMFile, "\"%d %d %d %d\",\n",
330 (int) pIcon->bmiHeader.biWidth, nHeight, nColorsUsed + 1, 2) <=0)
331 goto error;
332
333 for (i = 0; i < nColors; i++)
334 if (aColorUsed[i])
335 if (fprintf(fXPMFile, "\"%.2X c #%.2X%.2X%.2X\",\n", i, pIcon->bmiColors[i].rgbRed,
336 pIcon->bmiColors[i].rgbGreen, pIcon->bmiColors[i].rgbBlue) <= 0)
337 goto error;
338 if (fprintf(fXPMFile, "\" c None\"") <= 0)
339 goto error;
340
341 for (i = 0; i < nHeight; i++)
342 {
343 if (fprintf(fXPMFile, ",\n\"") <= 0)
344 goto error;
345 for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
346 {
347 if MASK(j,i)
348 {
349 if (fprintf(fXPMFile, " ") <= 0)
350 goto error;
351 }
352 else
353 if (fprintf(fXPMFile, "%.2X", COLOR(j,i)) <= 0)
354 goto error;
355 }
356 if (fprintf(fXPMFile, "\"") <= 0)
357 goto error;
358 }
359 if (fprintf(fXPMFile, "};\n") <= 0)
360 goto error;
361
362#undef MASK
363#undef COLOR
364
365 fclose(fXPMFile);
366 return 1;
367
368 error:
369 fclose(fXPMFile);
370 unlink( szXPMFileName );
371 return 0;
372}
373#endif //__WIN32OS2__
374
375static BOOL CALLBACK EnumResNameProc(HANDLE hModule, const char *lpszType, char *lpszName, LONG lParam)
376{
377 *(HRSRC *) lParam = FindResourceA(hModule, lpszName, RT_GROUP_ICONA);
378 return FALSE;
379}
380
381static int ExtractFromEXEDLL(const char *szFileName, int nIndex, const char *szXPMFileName)
382{
383 HMODULE hModule;
384 HRSRC hResInfo;
385 char *lpName = NULL;
386 HGLOBAL hResData;
387 GRPICONDIR *pIconDir;
388 BITMAPINFO *pIcon;
389 int nMax = 0;
390 int i;
391
392 if (!(hModule = LoadLibraryExA(szFileName, 0, LOAD_LIBRARY_AS_DATAFILE)))
393 {
394 TRACE("LoadLibraryExA (%s) failed, error %ld\n", szFileName, GetLastError());
395 goto error1;
396 }
397
398 if (nIndex)
399 {
400 hResInfo = FindResourceA(hModule, MAKEINTRESOURCEA(nIndex), RT_GROUP_ICONA);
401#ifdef __WIN32OS2__
402 if(!hResInfo) {
403 hResInfo = FindResourceA(hModule, MAKEINTRESOURCEA(nIndex), RT_ICONA);
404 if(hResInfo) {
405 GRPICONDIR icondir = {0};
406 BITMAPINFO *bmi;
407
408 bmi = (BITMAPINFO *)LockResource(LoadResource(hModule, hResInfo));
409
410 icondir.idReserved = 0;
411 icondir.idType = 1;
412 icondir.idCount = 1;
413 icondir.idEntries[0].nID = nIndex;
414 icondir.idEntries[0].bHeight = bmi->bmiHeader.biHeight/2;
415 icondir.idEntries[0].bWidth = bmi->bmiHeader.biWidth;
416 icondir.idEntries[0].wBitCount = bmi->bmiHeader.biBitCount;
417
418 if(!SaveIconResAsOS2ICO(&icondir, hModule, szXPMFileName))
419 {
420 TRACE("Failed saving icon as XPM, error %ld\n", GetLastError());
421 goto error3;
422 }
423 goto done;
424 }
425 }
426#endif
427 TRACE("FindResourceA (%s) called, return 0x%x, error %ld\n", szFileName, hResInfo, GetLastError());
428 }
429 else
430 if (EnumResourceNamesA(hModule, RT_GROUP_ICONA, &EnumResNameProc, (LONG) &hResInfo))
431 {
432 TRACE("EnumResourceNamesA failed, error %ld\n", GetLastError());
433 goto error2;
434 }
435
436 if (!hResInfo)
437 {
438 TRACE("ExtractFromEXEDLL failed, error %ld\n", GetLastError());
439 goto error2;
440 }
441
442 if (!(hResData = LoadResource(hModule, hResInfo)))
443 {
444 TRACE("LoadResource failed, error %ld\n", GetLastError());
445 goto error2;
446 }
447 if (!(pIconDir = LockResource(hResData)))
448 {
449 TRACE("LockResource failed, error %ld\n", GetLastError());
450 goto error3;
451 }
452
453#ifdef __WIN32OS2__
454 if(!SaveIconResAsOS2ICO(pIconDir, hModule, szXPMFileName))
455 {
456 TRACE("Failed saving icon as XPM, error %ld\n", GetLastError());
457 goto error3;
458 }
459#else
460 for (i = 0; i < pIconDir->idCount; i++)
461 if ((pIconDir->idEntries[i].bHeight * pIconDir->idEntries[i].bWidth) > nMax)
462 {
463 lpName = MAKEINTRESOURCEA(pIconDir->idEntries[i].nID);
464 nMax = pIconDir->idEntries[i].bHeight * pIconDir->idEntries[i].bWidth;
465 }
466
467 FreeResource(hResData);
468
469 if (!(hResInfo = FindResourceA(hModule, lpName, RT_ICONA)))
470 {
471 TRACE("Second FindResourceA failed, error %ld\n", GetLastError());
472 goto error2;
473 }
474 if (!(hResData = LoadResource(hModule, hResInfo)))
475 {
476 TRACE("Second LoadResource failed, error %ld\n", GetLastError());
477 goto error2;
478 }
479 if (!(pIcon = LockResource(hResData)))
480 {
481 TRACE("Second LockResource failed, error %ld\n", GetLastError());
482 goto error3;
483 }
484
485 if(!SaveIconResAsXPM(pIcon, szXPMFileName))
486 {
487 TRACE("Failed saving icon as XPM, error %ld\n", GetLastError());
488 goto error3;
489 }
490#endif
491
492done:
493 FreeResource(hResData);
494 FreeLibrary(hModule);
495
496 return 1;
497
498 error3:
499 FreeResource(hResData);
500 error2:
501 FreeLibrary(hModule);
502 error1:
503 return 0;
504}
505
506static int ExtractFromICO(const char *szFileName, const char *szXPMFileName)
507{
508 FILE *fICOFile;
509 ICONDIR iconDir;
510 ICONDIRENTRY *pIconDirEntry;
511 int nMax = 0;
512 int nIndex = 0;
513 void *pIcon;
514 int i;
515#ifdef __WIN32OS2__
516 int size;
517#endif
518
519 if (!(fICOFile = fopen(szFileName, "r")))
520 goto error1;
521
522#ifdef __WIN32OS2__
523 //TODO:
524 dprintf(("TODO: Icon file conversion not yet supported!!"));
525 goto error2;
526#else
527
528 if (fread(&iconDir, sizeof (ICONDIR), 1, fICOFile) != 1)
529 goto error2;
530 if ((iconDir.idReserved != 0) || (iconDir.idType != 1))
531 goto error2;
532
533 if ((pIconDirEntry = malloc(iconDir.idCount * sizeof (ICONDIRENTRY))) == NULL)
534 goto error2;
535 if (fread(pIconDirEntry, sizeof (ICONDIRENTRY), iconDir.idCount, fICOFile) != iconDir.idCount)
536 goto error3;
537
538 for (i = 0; i < iconDir.idCount; i++)
539 if ((pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth) > nMax)
540 {
541 nIndex = i;
542 nMax = pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth;
543 }
544 if ((pIcon = malloc(pIconDirEntry[nIndex].dwBytesInRes)) == NULL)
545 goto error3;
546 if (fseek(fICOFile, pIconDirEntry[nIndex].dwImageOffset, SEEK_SET))
547 goto error4;
548 if (fread(pIcon, pIconDirEntry[nIndex].dwBytesInRes, 1, fICOFile) != 1)
549 goto error4;
550
551 if(!SaveIconResAsXPM(pIcon, szXPMFileName))
552 goto error4;
553
554#endif
555 free(pIcon);
556 free(pIconDirEntry);
557 fclose(fICOFile);
558
559 return 1;
560
561 error4:
562 free(pIcon);
563 error3:
564 free(pIconDirEntry);
565 error2:
566 fclose(fICOFile);
567 error1:
568 return 0;
569}
570
571#ifndef __WIN32OS2__
572/* get the Unix file name for a given path, allocating the string */
573inline static char *get_unix_file_name( const char *dos )
574{
575 char buffer[MAX_PATH];
576
577 if (!wine_get_unix_file_name( dos, buffer, sizeof(buffer) )) return NULL;
578 return HEAP_strdupA( GetProcessHeap(), 0, buffer );
579}
580
581static BOOL create_default_icon( const char *filename )
582{
583 FILE *fXPM;
584 int i;
585
586 if (!(fXPM = fopen(filename, "w"))) return FALSE;
587 fprintf(fXPM, "/* XPM */\nstatic char * icon[] = {");
588 for (i = 0; i < sizeof(wine_xpm)/sizeof(wine_xpm[0]); i++)
589 fprintf( fXPM, "\n\"%s\",", wine_xpm[i]);
590 fprintf( fXPM, "};\n" );
591 fclose( fXPM );
592 return TRUE;
593}
594#endif //__WIN32OS2__
595
596/* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
597#ifdef __WIN32OS2__
598static char *extract_icon( const char *path, char *filename, int index)
599{
600 if (ExtractFromEXEDLL( path, index, filename )) return filename;
601 if (ExtractFromICO( path, filename )) return filename;
602 return NULL;
603}
604#else
605static char *extract_icon( const char *path, int index)
606{
607 char *filename = HEAP_strdupA( GetProcessHeap(), 0, tmpnam(NULL) );
608 if (ExtractFromEXEDLL( path, index, filename )) return filename;
609 if (ExtractFromICO( path, filename )) return filename;
610 if (create_default_icon( filename )) return filename;
611 HeapFree( GetProcessHeap(), 0, filename );
612 return NULL;
613}
614#endif
615
616static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember)
617{
618 HRESULT ret = NOERROR;
619 int pid, status;
620 char buffer[MAX_PATH], buff2[MAX_PATH];
621 char *filename, *link_name, *p;
622 char *shell_link_app = NULL;
623 char *icon_name = NULL;
624 char *path_name = NULL;
625 char *work_dir = NULL;
626 BOOL bDesktop;
627 HKEY hkey;
628#ifdef __WIN32OS2__
629 char *tmp;
630#endif
631
632 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
633
634 TRACE("(%p)->(%s)\n",This,debugstr_w(pszFileName));
635
636 if (!pszFileName || !This->sPath)
637 return ERROR_UNKNOWN;
638
639 /* check for .exe extension */
640 if (!(p = strrchr( This->sPath, '.' ))) return NOERROR;
641 if (strchr( p, '\\' ) || strchr( p, '/' )) return NOERROR;
642 if (strcasecmp( p, ".exe" )) return NOERROR;
643
644 /* check if ShellLinker configured */
645#ifdef __WIN32OS2__
646 dprintf(("IPersistFile_fnSave %ls", pszFileName));
647 filename = link_name = NULL;
648 bDesktop = 0;
649
650 if (!WideCharToMultiByte( CP_ACP, 0, pszFileName, -1, buffer, sizeof(buffer), NULL, NULL))
651 return ERROR_UNKNOWN;
652 GetFullPathNameA( buffer, sizeof(buff2), buff2, NULL );
653 filename = HEAP_strdupA( GetProcessHeap(), 0, buff2 );
654
655 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_STARTUP, FALSE ))
656 {
657 /* ignore startup for now */
658 if (!strncasecmp( filename, buffer, strlen(buffer) )) goto done;
659 }
660 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_DESKTOPDIRECTORY, FALSE ))
661 {
662 if (!strncasecmp( filename, buffer, strlen(buffer) ))
663 {
664 link_name = filename + strlen(buffer);
665 bDesktop = TRUE;
666 goto found;
667 }
668 }
669 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_STARTMENU, FALSE ))
670 {
671 if (!strncasecmp( filename, buffer, strlen(buffer) ))
672 {
673 link_name = filename + strlen(buffer);
674 bDesktop = FALSE;
675 goto found;
676 }
677 }
678 goto done;
679
680 found:
681
682 icon_name = HEAP_strdupA( GetProcessHeap(), 0, filename );
683 strupr(icon_name);
684 tmp = strstr(icon_name, ".LNK");
685 if(!tmp) {
686 dprintf(("ERROR: Unexpected name %s", icon_name));
687 goto done;
688 }
689 tmp[1] = 'I';
690 tmp[2] = 'C';
691 tmp[3] = 'O';
692 /* extract the icon */
693 if (!extract_icon( This->sIcoPath && strlen(This->sIcoPath) ?
694 This->sIcoPath : This->sPath,
695 icon_name, This->iIcoNdx)) goto done;
696
697 if(OSLibWinCreateObject(This->sPath, This->sArgs, This->sWorkDir, filename,
698 This->sDescription, icon_name,
699 This->iIcoNdx, bDesktop) == FALSE)
700 {
701 ret = E_ACCESSDENIED;
702 }
703
704 done:
705 if(shell_link_app) HeapFree( GetProcessHeap(), 0, shell_link_app );
706 if(filename) HeapFree( GetProcessHeap(), 0, filename );
707 if(icon_name) HeapFree( GetProcessHeap(), 0, icon_name );
708 if(path_name) HeapFree( GetProcessHeap(), 0, path_name );
709 if(work_dir) HeapFree( GetProcessHeap(), 0, work_dir );
710 return ret;
711
712#else
713 buffer[0] = 0;
714 if (!RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Wine",
715 0, KEY_ALL_ACCESS, &hkey ))
716 {
717 DWORD type, count = sizeof(buffer);
718 if (RegQueryValueExA( hkey, "ShellLinker", 0, &type, buffer, &count )) buffer[0] = 0;
719 RegCloseKey( hkey );
720 }
721 if (!*buffer) return NOERROR;
722 shell_link_app = HEAP_strdupA( GetProcessHeap(), 0, buffer );
723
724 if (!WideCharToMultiByte( CP_ACP, 0, pszFileName, -1, buffer, sizeof(buffer), NULL, NULL))
725 return ERROR_UNKNOWN;
726 GetFullPathNameA( buffer, sizeof(buff2), buff2, NULL );
727 filename = HEAP_strdupA( GetProcessHeap(), 0, buff2 );
728
729 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_STARTUP, FALSE ))
730 {
731 /* ignore startup for now */
732 if (!strncasecmp( filename, buffer, strlen(buffer) )) goto done;
733 }
734 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_DESKTOPDIRECTORY, FALSE ))
735 {
736 if (!strncasecmp( filename, buffer, strlen(buffer) ))
737 {
738 link_name = filename + strlen(buffer);
739 bDesktop = TRUE;
740 goto found;
741 }
742 }
743 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_STARTMENU, FALSE ))
744 {
745 if (!strncasecmp( filename, buffer, strlen(buffer) ))
746 {
747 link_name = filename + strlen(buffer);
748 bDesktop = FALSE;
749 goto found;
750 }
751 }
752 goto done;
753
754 found:
755 /* make link name a Unix name */
756 for (p = link_name; *p; p++) if (*p == '\\') *p = '/';
757 /* strip leading slashes */
758 while (*link_name == '/') link_name++;
759 /* remove extension */
760 if ((p = strrchr( link_name, '.' ))) *p = 0;
761
762 /* convert app path name */
763 path_name = get_unix_file_name( This->sPath );
764
765 /* convert app working dir */
766 if (This->sWorkDir) work_dir = get_unix_file_name( This->sWorkDir );
767
768 /* extract the icon */
769 if (!(icon_name = extract_icon( This->sIcoPath && strlen(This->sIcoPath) ?
770 This->sIcoPath : This->sPath,
771 This->iIcoNdx ))) goto done;
772
773
774 TRACE("linker app='%s' link='%s' mode=%s path='%s' args='%s' icon='%s' workdir='%s' descr='%s'\n",
775 shell_link_app, link_name, bDesktop ? "desktop" : "menu", path_name,
776 This->sArgs ? This->sArgs : "", icon_name, work_dir ? work_dir : "",
777 This->sDescription ? This->sDescription : "" );
778
779 if ((pid = fork()) == -1) goto done;
780 if (!pid)
781 {
782 int pos = 0;
783 char *argv[20];
784 argv[pos++] = shell_link_app;
785 argv[pos++] = "--link";
786 argv[pos++] = link_name;
787 argv[pos++] = "--path";
788 argv[pos++] = path_name;
789 argv[pos++] = bDesktop ? "--desktop" : "--menu";
790 if (This->sArgs && strlen(This->sArgs))
791 {
792 argv[pos++] = "--args";
793 argv[pos++] = This->sArgs;
794 }
795 if (icon_name)
796 {
797 argv[pos++] = "--icon";
798 argv[pos++] = icon_name;
799 }
800 if (This->sWorkDir && strlen(This->sWorkDir))
801 {
802 argv[pos++] = "--workdir";
803 argv[pos++] = This->sWorkDir;
804 }
805 if (This->sDescription && strlen(This->sDescription))
806 {
807 argv[pos++] = "--descr";
808 argv[pos++] = This->sDescription;
809 }
810 argv[pos] = NULL;
811 execvp( shell_link_app, argv );
812 _exit(1);
813 }
814
815 while (waitpid( pid, &status, 0 ) == -1)
816 {
817 if (errno != EINTR)
818 {
819 ret = ERROR_UNKNOWN;
820 goto done;
821 }
822 }
823 if (status) ret = E_ACCESSDENIED;
824
825 done:
826 if (icon_name) unlink( icon_name );
827 HeapFree( GetProcessHeap(), 0, shell_link_app );
828 HeapFree( GetProcessHeap(), 0, filename );
829 HeapFree( GetProcessHeap(), 0, icon_name );
830 HeapFree( GetProcessHeap(), 0, path_name );
831 HeapFree( GetProcessHeap(), 0, work_dir );
832 return ret;
833#endif
834}
835
836static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName)
837{
838 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
839 FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName));
840 return NOERROR;
841}
842static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName)
843{
844 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
845 FIXME("(%p)\n",This);
846 return NOERROR;
847}
848
849static ICOM_VTABLE(IPersistFile) pfvt =
850{
851 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
852 IPersistFile_fnQueryInterface,
853 IPersistFile_fnAddRef,
854 IPersistFile_fnRelease,
855 IPersistFile_fnGetClassID,
856 IPersistFile_fnIsDirty,
857 IPersistFile_fnLoad,
858 IPersistFile_fnSave,
859 IPersistFile_fnSaveCompleted,
860 IPersistFile_fnGetCurFile
861};
862
863/************************************************************************
864 * IPersistStream_QueryInterface
865 */
866static HRESULT WINAPI IPersistStream_fnQueryInterface(
867 IPersistStream* iface,
868 REFIID riid,
869 VOID** ppvoid)
870{
871 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
872
873 TRACE("(%p)\n",This);
874
875 return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvoid);
876}
877
878/************************************************************************
879 * IPersistStream_Release
880 */
881static ULONG WINAPI IPersistStream_fnRelease(
882 IPersistStream* iface)
883{
884 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
885
886 TRACE("(%p)\n",This);
887
888 return IShellLinkA_Release((IShellLinkA*)This);
889}
890
891/************************************************************************
892 * IPersistStream_AddRef
893 */
894static ULONG WINAPI IPersistStream_fnAddRef(
895 IPersistStream* iface)
896{
897 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
898
899 TRACE("(%p)\n",This);
900
901 return IShellLinkA_AddRef((IShellLinkA*)This);
902}
903
904/************************************************************************
905 * IPersistStream_GetClassID
906 *
907 */
908static HRESULT WINAPI IPersistStream_fnGetClassID(
909 IPersistStream* iface,
910 CLSID* pClassID)
911{
912 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
913
914 TRACE("(%p)\n", This);
915
916 if (pClassID==0)
917 return E_POINTER;
918
919/* memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */
920
921 return S_OK;
922}
923
924/************************************************************************
925 * IPersistStream_IsDirty (IPersistStream)
926 */
927static HRESULT WINAPI IPersistStream_fnIsDirty(
928 IPersistStream* iface)
929{
930 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
931
932 TRACE("(%p)\n", This);
933
934 return S_OK;
935}
936/************************************************************************
937 * IPersistStream_Load (IPersistStream)
938 */
939
940static HRESULT WINAPI IPersistStream_fnLoad(
941 IPersistStream* iface,
942 IStream* pLoadStream)
943{
944 PLINK_HEADER lpLinkHeader = HeapAlloc(GetProcessHeap(), 0, LINK_HEADER_SIZE);
945 ULONG dwBytesRead;
946 DWORD ret = E_FAIL;
947 char sTemp[MAX_PATH];
948
949 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
950
951 TRACE("(%p)(%p)\n", This, pLoadStream);
952
953 if ( ! pLoadStream)
954 {
955 return STG_E_INVALIDPOINTER;
956 }
957
958 IStream_AddRef (pLoadStream);
959 if(lpLinkHeader)
960 {
961 if (SUCCEEDED(IStream_Read(pLoadStream, lpLinkHeader, LINK_HEADER_SIZE, &dwBytesRead)))
962 {
963 if ((lpLinkHeader->MagicStr == 0x0000004CL) && IsEqualIID(&lpLinkHeader->MagicGuid, &CLSID_ShellLink))
964 {
965 lpLinkHeader = HeapReAlloc(GetProcessHeap(), 0, lpLinkHeader, LINK_HEADER_SIZE+lpLinkHeader->PidlSize);
966 if (lpLinkHeader)
967 {
968 if (SUCCEEDED(IStream_Read(pLoadStream, &(lpLinkHeader->Pidl), lpLinkHeader->PidlSize, &dwBytesRead)))
969 {
970 if (pcheck (&lpLinkHeader->Pidl))
971 {
972 This->pPidl = ILClone (&lpLinkHeader->Pidl);
973
974 SHGetPathFromIDListA(&lpLinkHeader->Pidl, sTemp);
975 This->sPath = HEAP_strdupA ( GetProcessHeap(), 0, sTemp);
976 }
977 This->wHotKey = lpLinkHeader->wHotKey;
978 FileTimeToSystemTime (&lpLinkHeader->Time1, &This->time1);
979 FileTimeToSystemTime (&lpLinkHeader->Time2, &This->time2);
980 FileTimeToSystemTime (&lpLinkHeader->Time3, &This->time3);
981#if 1
982 GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time1, NULL, sTemp, 256);
983 TRACE("-- time1: %s\n", sTemp);
984 GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time2, NULL, sTemp, 256);
985 TRACE("-- time1: %s\n", sTemp);
986 GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time3, NULL, sTemp, 256);
987 TRACE("-- time1: %s\n", sTemp);
988 pdump (This->pPidl);
989#endif
990 ret = S_OK;
991 }
992 }
993 }
994 else
995 {
996 WARN("stream contains no link!\n");
997 }
998 }
999 }
1000
1001 IStream_Release (pLoadStream);
1002
1003 pdump(This->pPidl);
1004
1005 HeapFree(GetProcessHeap(), 0, lpLinkHeader);
1006
1007 return ret;
1008}
1009
1010/************************************************************************
1011 * IPersistStream_Save (IPersistStream)
1012 */
1013static HRESULT WINAPI IPersistStream_fnSave(
1014 IPersistStream* iface,
1015 IStream* pOutStream,
1016 BOOL fClearDirty)
1017{
1018 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
1019
1020 TRACE("(%p) %p %x\n", This, pOutStream, fClearDirty);
1021
1022 return E_NOTIMPL;
1023}
1024
1025/************************************************************************
1026 * IPersistStream_GetSizeMax (IPersistStream)
1027 */
1028static HRESULT WINAPI IPersistStream_fnGetSizeMax(
1029 IPersistStream* iface,
1030 ULARGE_INTEGER* pcbSize)
1031{
1032 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
1033
1034 TRACE("(%p)\n", This);
1035
1036 return E_NOTIMPL;
1037}
1038
1039static ICOM_VTABLE(IPersistStream) psvt =
1040{
1041 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1042 IPersistStream_fnQueryInterface,
1043 IPersistStream_fnAddRef,
1044 IPersistStream_fnRelease,
1045 IPersistStream_fnGetClassID,
1046 IPersistStream_fnIsDirty,
1047 IPersistStream_fnLoad,
1048 IPersistStream_fnSave,
1049 IPersistStream_fnGetSizeMax
1050};
1051
1052/**************************************************************************
1053 * IShellLink_Constructor
1054 */
1055IShellLinkA * IShellLink_Constructor(BOOL bUnicode)
1056{ IShellLinkImpl * sl;
1057
1058 sl = (IShellLinkImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellLinkImpl));
1059 sl->ref = 1;
1060 ICOM_VTBL(sl) = &slvt;
1061 sl->lpvtblw = &slvtw;
1062 sl->lpvtblPersistFile = &pfvt;
1063 sl->lpvtblPersistStream = &psvt;
1064
1065 TRACE("(%p)->()\n",sl);
1066 shell32_ObjCount++;
1067 return bUnicode ? (IShellLinkA *) &(sl->lpvtblw) : (IShellLinkA *)sl;
1068}
1069
1070/**************************************************************************
1071 * IShellLinkA_QueryInterface
1072 */
1073static HRESULT WINAPI IShellLinkA_fnQueryInterface( IShellLinkA * iface, REFIID riid, LPVOID *ppvObj)
1074{
1075 ICOM_THIS(IShellLinkImpl, iface);
1076
1077 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
1078
1079 *ppvObj = NULL;
1080
1081 if(IsEqualIID(riid, &IID_IUnknown) ||
1082 IsEqualIID(riid, &IID_IShellLinkA))
1083 {
1084 *ppvObj = This;
1085 }
1086 else if(IsEqualIID(riid, &IID_IShellLinkW))
1087 {
1088 *ppvObj = (IShellLinkW *)&(This->lpvtblw);
1089 }
1090 else if(IsEqualIID(riid, &IID_IPersistFile))
1091 {
1092 *ppvObj = (IPersistFile *)&(This->lpvtblPersistFile);
1093 }
1094 else if(IsEqualIID(riid, &IID_IPersistStream))
1095 {
1096 *ppvObj = (IPersistStream *)&(This->lpvtblPersistStream);
1097 }
1098
1099 if(*ppvObj)
1100 {
1101 IUnknown_AddRef((IUnknown*)(*ppvObj));
1102 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1103 return S_OK;
1104 }
1105 TRACE("-- Interface: E_NOINTERFACE\n");
1106 return E_NOINTERFACE;
1107}
1108/******************************************************************************
1109 * IShellLinkA_AddRef
1110 */
1111static ULONG WINAPI IShellLinkA_fnAddRef(IShellLinkA * iface)
1112{
1113 ICOM_THIS(IShellLinkImpl, iface);
1114
1115 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1116
1117 shell32_ObjCount++;
1118 return ++(This->ref);
1119}
1120/******************************************************************************
1121 * IShellLinkA_Release
1122 */
1123static ULONG WINAPI IShellLinkA_fnRelease(IShellLinkA * iface)
1124{
1125 ICOM_THIS(IShellLinkImpl, iface);
1126
1127 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1128
1129 shell32_ObjCount--;
1130 if (!--(This->ref))
1131 { TRACE("-- destroying IShellLink(%p)\n",This);
1132
1133 if (This->sIcoPath)
1134 HeapFree(GetProcessHeap(), 0, This->sIcoPath);
1135
1136 if (This->sArgs)
1137 HeapFree(GetProcessHeap(), 0, This->sArgs);
1138
1139
1140 if (This->sWorkDir)
1141 HeapFree(GetProcessHeap(), 0, This->sWorkDir);
1142
1143 if (This->sDescription)
1144 HeapFree(GetProcessHeap(), 0, This->sDescription);
1145
1146 if (This->sPath)
1147 HeapFree(GetProcessHeap(),0,This->sPath);
1148
1149 if (This->pPidl)
1150 SHFree(This->pPidl);
1151
1152 if (This->lpFileStream)
1153 IStream_Release(This->lpFileStream);
1154
1155 This->iIcoNdx = 0;
1156
1157 HeapFree(GetProcessHeap(),0,This);
1158 return 0;
1159 }
1160 return This->ref;
1161}
1162
1163static HRESULT WINAPI IShellLinkA_fnGetPath(IShellLinkA * iface, LPSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
1164{
1165 ICOM_THIS(IShellLinkImpl, iface);
1166
1167 TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n",This, pszFile, cchMaxPath, pfd, fFlags, debugstr_a(This->sPath));
1168
1169 if (This->sPath)
1170 lstrcpynA(pszFile,This->sPath, cchMaxPath);
1171 else
1172 return E_FAIL;
1173
1174 return NOERROR;
1175}
1176static HRESULT WINAPI IShellLinkA_fnGetIDList(IShellLinkA * iface, LPITEMIDLIST * ppidl)
1177{
1178 ICOM_THIS(IShellLinkImpl, iface);
1179
1180 TRACE("(%p)->(ppidl=%p)\n",This, ppidl);
1181
1182 *ppidl = ILClone(This->pPidl);
1183 return NOERROR;
1184}
1185static HRESULT WINAPI IShellLinkA_fnSetIDList(IShellLinkA * iface, LPCITEMIDLIST pidl)
1186{
1187 ICOM_THIS(IShellLinkImpl, iface);
1188
1189 TRACE("(%p)->(pidl=%p)\n",This, pidl);
1190
1191 if (This->pPidl)
1192 SHFree(This->pPidl);
1193 This->pPidl = ILClone (pidl);
1194 return NOERROR;
1195}
1196static HRESULT WINAPI IShellLinkA_fnGetDescription(IShellLinkA * iface, LPSTR pszName,INT cchMaxName)
1197{
1198 ICOM_THIS(IShellLinkImpl, iface);
1199
1200 FIXME("(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
1201 lstrcpynA(pszName,"Description, FIXME",cchMaxName);
1202 return NOERROR;
1203}
1204static HRESULT WINAPI IShellLinkA_fnSetDescription(IShellLinkA * iface, LPCSTR pszName)
1205{
1206 ICOM_THIS(IShellLinkImpl, iface);
1207
1208 TRACE("(%p)->(pName=%s)\n", This, pszName);
1209
1210 if (This->sDescription)
1211 HeapFree(GetProcessHeap(), 0, This->sDescription);
1212 if (!(This->sDescription = HEAP_strdupA(GetProcessHeap(), 0, pszName)))
1213 return E_OUTOFMEMORY;
1214
1215 return NOERROR;
1216}
1217static HRESULT WINAPI IShellLinkA_fnGetWorkingDirectory(IShellLinkA * iface, LPSTR pszDir,INT cchMaxPath)
1218{
1219 ICOM_THIS(IShellLinkImpl, iface);
1220
1221 TRACE("(%p)->(%p len=%u)\n", This, pszDir, cchMaxPath);
1222
1223 lstrcpynA( pszDir, This->sWorkDir ? This->sWorkDir : "", cchMaxPath );
1224
1225 return NOERROR;
1226}
1227static HRESULT WINAPI IShellLinkA_fnSetWorkingDirectory(IShellLinkA * iface, LPCSTR pszDir)
1228{
1229 ICOM_THIS(IShellLinkImpl, iface);
1230
1231 TRACE("(%p)->(dir=%s)\n",This, pszDir);
1232
1233 if (This->sWorkDir)
1234 HeapFree(GetProcessHeap(), 0, This->sWorkDir);
1235 if (!(This->sWorkDir = HEAP_strdupA(GetProcessHeap(), 0, pszDir)))
1236 return E_OUTOFMEMORY;
1237
1238 return NOERROR;
1239}
1240static HRESULT WINAPI IShellLinkA_fnGetArguments(IShellLinkA * iface, LPSTR pszArgs,INT cchMaxPath)
1241{
1242 ICOM_THIS(IShellLinkImpl, iface);
1243
1244 TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath);
1245
1246 lstrcpynA( pszArgs, This->sArgs ? This->sArgs : "", cchMaxPath );
1247
1248 return NOERROR;
1249}
1250static HRESULT WINAPI IShellLinkA_fnSetArguments(IShellLinkA * iface, LPCSTR pszArgs)
1251{
1252 ICOM_THIS(IShellLinkImpl, iface);
1253
1254 TRACE("(%p)->(args=%s)\n",This, pszArgs);
1255
1256 if (This->sArgs)
1257 HeapFree(GetProcessHeap(), 0, This->sArgs);
1258 if (!(This->sArgs = HEAP_strdupA(GetProcessHeap(), 0, pszArgs)))
1259 return E_OUTOFMEMORY;
1260
1261 return NOERROR;
1262}
1263static HRESULT WINAPI IShellLinkA_fnGetHotkey(IShellLinkA * iface, WORD *pwHotkey)
1264{
1265 ICOM_THIS(IShellLinkImpl, iface);
1266
1267 TRACE("(%p)->(%p)(0x%08x)\n",This, pwHotkey, This->wHotKey);
1268
1269 *pwHotkey = This->wHotKey;
1270
1271 return NOERROR;
1272}
1273static HRESULT WINAPI IShellLinkA_fnSetHotkey(IShellLinkA * iface, WORD wHotkey)
1274{
1275 ICOM_THIS(IShellLinkImpl, iface);
1276
1277 TRACE("(%p)->(hotkey=%x)\n",This, wHotkey);
1278
1279 This->wHotKey = wHotkey;
1280
1281 return NOERROR;
1282}
1283static HRESULT WINAPI IShellLinkA_fnGetShowCmd(IShellLinkA * iface, INT *piShowCmd)
1284{
1285 ICOM_THIS(IShellLinkImpl, iface);
1286
1287 FIXME("(%p)->(%p)\n",This, piShowCmd);
1288 *piShowCmd=0;
1289 return NOERROR;
1290}
1291static HRESULT WINAPI IShellLinkA_fnSetShowCmd(IShellLinkA * iface, INT iShowCmd)
1292{
1293 ICOM_THIS(IShellLinkImpl, iface);
1294
1295 FIXME("(%p)->(showcmd=%x)\n",This, iShowCmd);
1296 return NOERROR;
1297}
1298static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon)
1299{
1300 ICOM_THIS(IShellLinkImpl, iface);
1301
1302 TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon);
1303
1304 lstrcpynA( pszIconPath, This->sIcoPath ? This->sIcoPath : "", cchIconPath );
1305 *piIcon = This->iIcoNdx;
1306
1307 return NOERROR;
1308}
1309static HRESULT WINAPI IShellLinkA_fnSetIconLocation(IShellLinkA * iface, LPCSTR pszIconPath,INT iIcon)
1310{
1311 ICOM_THIS(IShellLinkImpl, iface);
1312
1313 TRACE("(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon);
1314
1315 if (This->sIcoPath)
1316 HeapFree(GetProcessHeap(), 0, This->sIcoPath);
1317 if (!(This->sIcoPath = HEAP_strdupA(GetProcessHeap(), 0, pszIconPath)))
1318 return E_OUTOFMEMORY;
1319 This->iIcoNdx = iIcon;
1320
1321 return NOERROR;
1322}
1323static HRESULT WINAPI IShellLinkA_fnSetRelativePath(IShellLinkA * iface, LPCSTR pszPathRel, DWORD dwReserved)
1324{
1325 ICOM_THIS(IShellLinkImpl, iface);
1326
1327 FIXME("(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved);
1328 return NOERROR;
1329}
1330static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags)
1331{
1332 ICOM_THIS(IShellLinkImpl, iface);
1333
1334 FIXME("(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
1335 return NOERROR;
1336}
1337static HRESULT WINAPI IShellLinkA_fnSetPath(IShellLinkA * iface, LPCSTR pszFile)
1338{
1339 ICOM_THIS(IShellLinkImpl, iface);
1340
1341 TRACE("(%p)->(path=%s)\n",This, pszFile);
1342
1343 if (This->sPath)
1344 HeapFree(GetProcessHeap(), 0, This->sPath);
1345 if (!(This->sPath = HEAP_strdupA(GetProcessHeap(), 0, pszFile)))
1346 return E_OUTOFMEMORY;
1347
1348 return NOERROR;
1349}
1350
1351/**************************************************************************
1352* IShellLink Implementation
1353*/
1354
1355static ICOM_VTABLE(IShellLinkA) slvt =
1356{
1357 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1358 IShellLinkA_fnQueryInterface,
1359 IShellLinkA_fnAddRef,
1360 IShellLinkA_fnRelease,
1361 IShellLinkA_fnGetPath,
1362 IShellLinkA_fnGetIDList,
1363 IShellLinkA_fnSetIDList,
1364 IShellLinkA_fnGetDescription,
1365 IShellLinkA_fnSetDescription,
1366 IShellLinkA_fnGetWorkingDirectory,
1367 IShellLinkA_fnSetWorkingDirectory,
1368 IShellLinkA_fnGetArguments,
1369 IShellLinkA_fnSetArguments,
1370 IShellLinkA_fnGetHotkey,
1371 IShellLinkA_fnSetHotkey,
1372 IShellLinkA_fnGetShowCmd,
1373 IShellLinkA_fnSetShowCmd,
1374 IShellLinkA_fnGetIconLocation,
1375 IShellLinkA_fnSetIconLocation,
1376 IShellLinkA_fnSetRelativePath,
1377 IShellLinkA_fnResolve,
1378 IShellLinkA_fnSetPath
1379};
1380
1381
1382/**************************************************************************
1383 * IShellLinkW_fnQueryInterface
1384 */
1385static HRESULT WINAPI IShellLinkW_fnQueryInterface(
1386 IShellLinkW * iface, REFIID riid, LPVOID *ppvObj)
1387{
1388 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1389
1390 return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj);
1391}
1392
1393/******************************************************************************
1394 * IShellLinkW_fnAddRef
1395 */
1396static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface)
1397{
1398 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1399
1400 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1401
1402 return IShellLinkA_AddRef((IShellLinkA*)This);
1403}
1404/******************************************************************************
1405 * IShellLinkW_fnRelease
1406 */
1407
1408static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface)
1409{
1410 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1411
1412 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1413
1414 return IShellLinkA_Release((IShellLinkA*)This);
1415}
1416
1417static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
1418{
1419 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1420
1421 FIXME("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This, pszFile, cchMaxPath, pfd, fFlags);
1422 MultiByteToWideChar( CP_ACP, 0, "c:\\foo.bar", -1, pszFile, cchMaxPath );
1423 return NOERROR;
1424}
1425
1426static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl)
1427{
1428 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1429
1430 FIXME("(%p)->(ppidl=%p)\n",This, ppidl);
1431 *ppidl = _ILCreateDesktop();
1432 return NOERROR;
1433}
1434
1435static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl)
1436{
1437 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1438
1439 FIXME("(%p)->(pidl=%p)\n",This, pidl);
1440 return NOERROR;
1441}
1442
1443static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName)
1444{
1445 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1446
1447 FIXME("(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
1448 MultiByteToWideChar( CP_ACP, 0, "Description, FIXME", -1, pszName, cchMaxName );
1449 return NOERROR;
1450}
1451
1452static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName)
1453{
1454 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1455
1456 TRACE("(%p)->(desc=%s)\n",This, debugstr_w(pszName));
1457
1458 if (This->sDescription)
1459 HeapFree(GetProcessHeap(), 0, This->sDescription);
1460 if (!(This->sDescription = HEAP_strdupWtoA(GetProcessHeap(), 0, pszName)))
1461 return E_OUTOFMEMORY;
1462
1463 return NOERROR;
1464}
1465
1466static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath)
1467{
1468 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1469
1470 TRACE("(%p)->(%p len %u)\n", This, pszDir, cchMaxPath);
1471
1472 MultiByteToWideChar( CP_ACP, 0, This->sWorkDir ? This->sWorkDir : "", -1, pszDir, cchMaxPath );
1473
1474 return NOERROR;
1475}
1476
1477static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir)
1478{
1479 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1480
1481 TRACE("(%p)->(dir=%s)\n",This, debugstr_w(pszDir));
1482
1483 if (This->sWorkDir)
1484 HeapFree(GetProcessHeap(), 0, This->sWorkDir);
1485 if (!(This->sWorkDir = HEAP_strdupWtoA(GetProcessHeap(), 0, pszDir)))
1486 return E_OUTOFMEMORY;
1487
1488 return NOERROR;
1489}
1490
1491static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath)
1492{
1493 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1494
1495 TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath);
1496
1497 MultiByteToWideChar( CP_ACP, 0, This->sArgs ? This->sArgs : "", -1, pszArgs, cchMaxPath );
1498
1499 return NOERROR;
1500}
1501
1502static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs)
1503{
1504 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1505
1506 TRACE("(%p)->(args=%s)\n",This, debugstr_w(pszArgs));
1507
1508 if (This->sArgs)
1509 HeapFree(GetProcessHeap(), 0, This->sArgs);
1510 if (!(This->sArgs = HEAP_strdupWtoA(GetProcessHeap(), 0, pszArgs)))
1511 return E_OUTOFMEMORY;
1512
1513 return NOERROR;
1514}
1515
1516static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey)
1517{
1518 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1519
1520 FIXME("(%p)->(%p)\n",This, pwHotkey);
1521 *pwHotkey=0x0;
1522 return NOERROR;
1523}
1524
1525static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey)
1526{
1527 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1528
1529 FIXME("(%p)->(hotkey=%x)\n",This, wHotkey);
1530 return NOERROR;
1531}
1532
1533static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd)
1534{
1535 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1536
1537 FIXME("(%p)->(%p)\n",This, piShowCmd);
1538 *piShowCmd=0;
1539 return NOERROR;
1540}
1541
1542static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd)
1543{
1544 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1545
1546 FIXME("(%p)->(showcmd=%x)\n",This, iShowCmd);
1547 return NOERROR;
1548}
1549
1550static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon)
1551{
1552 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1553
1554 TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon);
1555
1556 MultiByteToWideChar( CP_ACP, 0, This->sIcoPath ? This->sIcoPath : "", -1, pszIconPath, cchIconPath );
1557 *piIcon = This->iIcoNdx;
1558
1559 return NOERROR;
1560}
1561
1562static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon)
1563{
1564 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1565
1566 TRACE("(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon);
1567
1568 if (This->sIcoPath)
1569 HeapFree(GetProcessHeap(), 0, This->sIcoPath);
1570 if (!(This->sIcoPath = HEAP_strdupWtoA(GetProcessHeap(), 0, pszIconPath)))
1571 return E_OUTOFMEMORY;
1572 This->iIcoNdx = iIcon;
1573
1574 return NOERROR;
1575}
1576
1577static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved)
1578{
1579 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1580
1581 FIXME("(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved);
1582 return NOERROR;
1583}
1584
1585static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags)
1586{
1587 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1588
1589 FIXME("(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
1590 return NOERROR;
1591}
1592
1593static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile)
1594{
1595 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1596
1597 TRACE("(%p)->(path=%s)\n",This, debugstr_w(pszFile));
1598
1599 if (This->sPath)
1600 HeapFree(GetProcessHeap(), 0, This->sPath);
1601 if (!(This->sPath = HEAP_strdupWtoA(GetProcessHeap(), 0, pszFile)))
1602 return E_OUTOFMEMORY;
1603
1604 return NOERROR;
1605}
1606
1607/**************************************************************************
1608* IShellLinkW Implementation
1609*/
1610
1611static ICOM_VTABLE(IShellLinkW) slvtw =
1612{
1613 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1614 IShellLinkW_fnQueryInterface,
1615 IShellLinkW_fnAddRef,
1616 IShellLinkW_fnRelease,
1617 IShellLinkW_fnGetPath,
1618 IShellLinkW_fnGetIDList,
1619 IShellLinkW_fnSetIDList,
1620 IShellLinkW_fnGetDescription,
1621 IShellLinkW_fnSetDescription,
1622 IShellLinkW_fnGetWorkingDirectory,
1623 IShellLinkW_fnSetWorkingDirectory,
1624 IShellLinkW_fnGetArguments,
1625 IShellLinkW_fnSetArguments,
1626 IShellLinkW_fnGetHotkey,
1627 IShellLinkW_fnSetHotkey,
1628 IShellLinkW_fnGetShowCmd,
1629 IShellLinkW_fnSetShowCmd,
1630 IShellLinkW_fnGetIconLocation,
1631 IShellLinkW_fnSetIconLocation,
1632 IShellLinkW_fnSetRelativePath,
1633 IShellLinkW_fnResolve,
1634 IShellLinkW_fnSetPath
1635};
1636
Note: See TracBrowser for help on using the repository browser.