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

Last change on this file since 6666 was 6650, checked in by bird, 24 years ago

Added $Id:$ keyword.

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