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

Last change on this file since 7502 was 7502, checked in by phaller, 24 years ago

Fixed out-of-scope FIXME,TRACE,WARN macros

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