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

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

update for single icon link

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