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

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

resync with latest wine

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