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

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

restored old version

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