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

Last change on this file since 9851 was 9851, checked in by sandervl, 23 years ago

Convert win32 icon file to os2 format when creating a shell link

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