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

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

removed TRACE/WARN macro redefinition

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