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

Last change on this file since 10547 was 10547, checked in by sandervl, 21 years ago

Allow shell links to be placed in arbitrary directories

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