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

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

fixed memory leak and replaced heap alloc by stack alloc

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