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

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

Fixed desktop object creation during win32 app install

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