Make the Wine trace facilities accessible from Winelib applications.
[wine/gsoc_dplay.git] / dlls / shell32 / shelllink.c
blobba0c96b6d6d1489baa8116d2311bb5f8d280d990
1 /*
3 * Copyright 1997 Marcus Meissner
4 * Copyright 1998 Juergen Schmied
6 */
8 #include "config.h"
10 #include <string.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #ifdef HAVE_SYS_WAIT_H
15 # include <sys/wait.h>
16 #endif
17 #include "debugtools.h"
18 #include "winerror.h"
19 #include "winbase.h"
20 #include "winnls.h"
21 #include "winreg.h"
23 #include "shlobj.h"
24 #include "undocshell.h"
25 #include "bitmaps/wine.xpm"
27 #include "heap.h"
28 #include "pidl.h"
29 #include "shell32_main.h"
30 #include "shlguid.h"
32 DEFAULT_DEBUG_CHANNEL(shell);
34 /* link file formats */
36 #include "pshpack1.h"
38 /* flag1: lnk elements: simple link has 0x0B */
39 #define WORKDIR 0x10
40 #define ARGUMENT 0x20
41 #define ICON 0x40
42 #define UNC 0x80
44 /* fStartup */
45 #define NORMAL 0x01
46 #define MAXIMIZED 0x03
47 #define MINIMIZED 0x07
49 typedef struct _LINK_HEADER
50 { DWORD MagicStr; /* 0x00 'L','\0','\0','\0' */
51 GUID MagicGuid; /* 0x04 is CLSID_ShellLink */
52 DWORD Flag1; /* 0x14 describes elements following */
53 DWORD Flag2; /* 0x18 */
54 FILETIME Time1; /* 0x1c */
55 FILETIME Time2; /* 0x24 */
56 FILETIME Time3; /* 0x2c */
57 DWORD Unknown1; /* 0x34 */
58 DWORD Unknown2; /* 0x38 icon number */
59 DWORD fStartup; /* 0x3c startup type */
60 DWORD wHotKey; /* 0x40 hotkey */
61 DWORD Unknown5; /* 0x44 */
62 DWORD Unknown6; /* 0x48 */
63 USHORT PidlSize; /* 0x4c */
64 ITEMIDLIST Pidl; /* 0x4e */
65 } LINK_HEADER, * PLINK_HEADER;
67 #define LINK_HEADER_SIZE (sizeof(LINK_HEADER)-sizeof(ITEMIDLIST))
69 typedef struct
71 BYTE bWidth;
72 BYTE bHeight;
73 BYTE bColorCount;
74 BYTE bReserved;
75 WORD wPlanes;
76 WORD wBitCount;
77 DWORD dwBytesInRes;
78 WORD nID;
79 } GRPICONDIRENTRY;
81 typedef struct
83 WORD idReserved;
84 WORD idType;
85 WORD idCount;
86 GRPICONDIRENTRY idEntries[1];
87 } GRPICONDIR;
89 typedef struct
91 BYTE bWidth;
92 BYTE bHeight;
93 BYTE bColorCount;
94 BYTE bReserved;
95 WORD wPlanes;
96 WORD wBitCount;
97 DWORD dwBytesInRes;
98 DWORD dwImageOffset;
99 } ICONDIRENTRY;
101 typedef struct
103 WORD idReserved;
104 WORD idType;
105 WORD idCount;
106 } ICONDIR;
109 #include "poppack.h"
111 typedef struct
113 HRSRC *pResInfo;
114 int nIndex;
115 } ENUMRESSTRUCT;
117 static ICOM_VTABLE(IShellLinkA) slvt;
118 static ICOM_VTABLE(IShellLinkW) slvtw;
119 static ICOM_VTABLE(IPersistFile) pfvt;
120 static ICOM_VTABLE(IPersistStream) psvt;
122 /* IShellLink Implementation */
124 typedef struct
126 ICOM_VFIELD(IShellLinkA);
127 DWORD ref;
129 ICOM_VTABLE(IShellLinkW)* lpvtblw;
130 ICOM_VTABLE(IPersistFile)* lpvtblPersistFile;
131 ICOM_VTABLE(IPersistStream)* lpvtblPersistStream;
133 /* internal stream of the IPersistFile interface */
134 IStream* lpFileStream;
136 /* data structures according to the informations in the lnk */
137 LPSTR sPath;
138 LPITEMIDLIST pPidl;
139 WORD wHotKey;
140 SYSTEMTIME time1;
141 SYSTEMTIME time2;
142 SYSTEMTIME time3;
144 LPSTR sIcoPath;
145 INT iIcoNdx;
146 LPSTR sArgs;
147 LPSTR sWorkDir;
148 LPSTR sDescription;
149 } IShellLinkImpl;
151 #define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw)))
152 #define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset);
154 #define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile)))
155 #define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset);
157 #define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream)))
158 #define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset);
159 #define _IPersistStream_From_ICOM_THIS(class, name) class* StreamThis = (class*)(((char*)name)+_IPersistStream_Offset);
162 /* strdup on the process heap */
163 inline static LPSTR heap_strdup( LPCSTR str )
165 INT len = strlen(str) + 1;
166 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
167 if (p) memcpy( p, str, len );
168 return p;
172 /**************************************************************************
173 * IPersistFile_QueryInterface
175 static HRESULT WINAPI IPersistFile_fnQueryInterface(
176 IPersistFile* iface,
177 REFIID riid,
178 LPVOID *ppvObj)
180 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
182 TRACE("(%p)\n",This);
184 return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj);
187 /******************************************************************************
188 * IPersistFile_AddRef
190 static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile* iface)
192 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
194 TRACE("(%p)->(count=%lu)\n",This,This->ref);
196 return IShellLinkA_AddRef((IShellLinkA*)This);
198 /******************************************************************************
199 * IPersistFile_Release
201 static ULONG WINAPI IPersistFile_fnRelease(IPersistFile* iface)
203 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
205 TRACE("(%p)->(count=%lu)\n",This,This->ref);
207 return IShellLinkA_Release((IShellLinkA*)This);
210 static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile* iface, CLSID *pClassID)
212 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
213 FIXME("(%p)\n",This);
214 return NOERROR;
216 static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile* iface)
218 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
219 FIXME("(%p)\n",This);
220 return NOERROR;
222 static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile* iface, LPCOLESTR pszFileName, DWORD dwMode)
224 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface)
225 _IPersistStream_From_ICOM_THIS(IPersistStream, This)
227 LPSTR sFile = HEAP_strdupWtoA ( GetProcessHeap(), 0, pszFileName);
228 HRESULT hRet = E_FAIL;
230 TRACE("(%p, %s)\n",This, sFile);
233 if (This->lpFileStream)
234 IStream_Release(This->lpFileStream);
236 if SUCCEEDED(CreateStreamOnFile(sFile, &(This->lpFileStream)))
238 if SUCCEEDED (IPersistStream_Load(StreamThis, This->lpFileStream))
240 return NOERROR;
244 return hRet;
248 /* Icon extraction routines
250 * FIXME: should use PrivateExtractIcons and friends
251 * FIXME: should not use stdio
254 static BOOL SaveIconResAsXPM(const BITMAPINFO *pIcon, const char *szXPMFileName)
256 FILE *fXPMFile;
257 int nHeight;
258 int nXORWidthBytes;
259 int nANDWidthBytes;
260 BOOL b8BitColors;
261 int nColors;
262 BYTE *pXOR;
263 BYTE *pAND;
264 BOOL aColorUsed[256] = {0};
265 int nColorsUsed = 0;
266 int i,j;
268 if (!((pIcon->bmiHeader.biBitCount == 4) || (pIcon->bmiHeader.biBitCount == 8)))
269 return 0;
271 if (!(fXPMFile = fopen(szXPMFileName, "w")))
272 return 0;
274 nHeight = pIcon->bmiHeader.biHeight / 2;
275 nXORWidthBytes = 4 * ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount / 32)
276 + ((pIcon->bmiHeader.biWidth * pIcon->bmiHeader.biBitCount % 32) > 0));
277 nANDWidthBytes = 4 * ((pIcon->bmiHeader.biWidth / 32)
278 + ((pIcon->bmiHeader.biWidth % 32) > 0));
279 b8BitColors = pIcon->bmiHeader.biBitCount == 8;
280 nColors = pIcon->bmiHeader.biClrUsed ? pIcon->bmiHeader.biClrUsed
281 : 1 << pIcon->bmiHeader.biBitCount;
282 pXOR = (BYTE*) pIcon + sizeof (BITMAPINFOHEADER) + (nColors * sizeof (RGBQUAD));
283 pAND = pXOR + nHeight * nXORWidthBytes;
285 #define MASK(x,y) (pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8)))
286 #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)
288 for (i = 0; i < nHeight; i++)
289 for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
290 if (!aColorUsed[COLOR(j,i)] && !MASK(j,i))
292 aColorUsed[COLOR(j,i)] = TRUE;
293 nColorsUsed++;
296 if (fprintf(fXPMFile, "/* XPM */\nstatic char *icon[] = {\n") <= 0)
297 goto error;
298 if (fprintf(fXPMFile, "\"%d %d %d %d\",\n",
299 (int) pIcon->bmiHeader.biWidth, nHeight, nColorsUsed + 1, 2) <=0)
300 goto error;
302 for (i = 0; i < nColors; i++)
303 if (aColorUsed[i])
304 if (fprintf(fXPMFile, "\"%.2X c #%.2X%.2X%.2X\",\n", i, pIcon->bmiColors[i].rgbRed,
305 pIcon->bmiColors[i].rgbGreen, pIcon->bmiColors[i].rgbBlue) <= 0)
306 goto error;
307 if (fprintf(fXPMFile, "\" c None\"") <= 0)
308 goto error;
310 for (i = 0; i < nHeight; i++)
312 if (fprintf(fXPMFile, ",\n\"") <= 0)
313 goto error;
314 for (j = 0; j < pIcon->bmiHeader.biWidth; j++)
316 if MASK(j,i)
318 if (fprintf(fXPMFile, " ") <= 0)
319 goto error;
321 else
322 if (fprintf(fXPMFile, "%.2X", COLOR(j,i)) <= 0)
323 goto error;
325 if (fprintf(fXPMFile, "\"") <= 0)
326 goto error;
328 if (fprintf(fXPMFile, "};\n") <= 0)
329 goto error;
331 #undef MASK
332 #undef COLOR
334 fclose(fXPMFile);
335 return 1;
337 error:
338 fclose(fXPMFile);
339 unlink( szXPMFileName );
340 return 0;
343 static BOOL CALLBACK EnumResNameProc(HANDLE hModule, const char *lpszType, char *lpszName, LONG lParam)
345 ENUMRESSTRUCT *sEnumRes = (ENUMRESSTRUCT *) lParam;
347 if (!sEnumRes->nIndex--)
349 *sEnumRes->pResInfo = FindResourceA(hModule, lpszName, RT_GROUP_ICONA);
350 return FALSE;
352 else
353 return TRUE;
356 static int ExtractFromEXEDLL(const char *szFileName, int nIndex, const char *szXPMFileName)
358 HMODULE hModule;
359 HRSRC hResInfo;
360 char *lpName = NULL;
361 HGLOBAL hResData;
362 GRPICONDIR *pIconDir;
363 BITMAPINFO *pIcon;
364 ENUMRESSTRUCT sEnumRes;
365 int nMax = 0;
366 int nMaxBits = 0;
367 int i;
369 if (!(hModule = LoadLibraryExA(szFileName, 0, LOAD_LIBRARY_AS_DATAFILE)))
371 TRACE("LoadLibraryExA (%s) failed, error %ld\n", szFileName, GetLastError());
372 goto error1;
375 if (nIndex < 0)
377 hResInfo = FindResourceA(hModule, MAKEINTRESOURCEA(-nIndex), RT_GROUP_ICONA);
378 TRACE("FindResourceA (%s) called, return 0x%x, error %ld\n", szFileName, hResInfo, GetLastError());
380 else
382 sEnumRes.pResInfo = &hResInfo;
383 sEnumRes.nIndex = nIndex;
384 if (EnumResourceNamesA(hModule, RT_GROUP_ICONA, &EnumResNameProc, (LONG) &sEnumRes))
386 TRACE("EnumResourceNamesA failed, error %ld\n", GetLastError());
387 goto error2;
391 if (!hResInfo)
393 TRACE("ExtractFromEXEDLL failed, error %ld\n", GetLastError());
394 goto error2;
397 if (!(hResData = LoadResource(hModule, hResInfo)))
399 TRACE("LoadResource failed, error %ld\n", GetLastError());
400 goto error2;
402 if (!(pIconDir = LockResource(hResData)))
404 TRACE("LockResource failed, error %ld\n", GetLastError());
405 goto error3;
408 for (i = 0; i < pIconDir->idCount; i++)
409 if ((pIconDir->idEntries[i].wBitCount >= nMaxBits) && (pIconDir->idEntries[i].wBitCount <= 8))
411 if (pIconDir->idEntries[i].wBitCount > nMaxBits)
413 nMaxBits = pIconDir->idEntries[i].wBitCount;
414 nMax = 0;
416 if ((pIconDir->idEntries[i].bHeight * pIconDir->idEntries[i].bWidth) > nMax)
418 lpName = MAKEINTRESOURCEA(pIconDir->idEntries[i].nID);
419 nMax = pIconDir->idEntries[i].bHeight * pIconDir->idEntries[i].bWidth;
423 FreeResource(hResData);
425 if (!(hResInfo = FindResourceA(hModule, lpName, RT_ICONA)))
427 TRACE("Second FindResourceA failed, error %ld\n", GetLastError());
428 goto error2;
430 if (!(hResData = LoadResource(hModule, hResInfo)))
432 TRACE("Second LoadResource failed, error %ld\n", GetLastError());
433 goto error2;
435 if (!(pIcon = LockResource(hResData)))
437 TRACE("Second LockResource failed, error %ld\n", GetLastError());
438 goto error3;
441 if(!SaveIconResAsXPM(pIcon, szXPMFileName))
443 TRACE("Failed saving icon as XPM, error %ld\n", GetLastError());
444 goto error3;
447 FreeResource(hResData);
448 FreeLibrary(hModule);
450 return 1;
452 error3:
453 FreeResource(hResData);
454 error2:
455 FreeLibrary(hModule);
456 error1:
457 return 0;
460 static int ExtractFromICO(const char *szFileName, const char *szXPMFileName)
462 FILE *fICOFile;
463 ICONDIR iconDir;
464 ICONDIRENTRY *pIconDirEntry;
465 int nMax = 0;
466 int nIndex = 0;
467 void *pIcon;
468 int i;
470 if (!(fICOFile = fopen(szFileName, "r")))
471 goto error1;
473 if (fread(&iconDir, sizeof (ICONDIR), 1, fICOFile) != 1)
474 goto error2;
475 if ((iconDir.idReserved != 0) || (iconDir.idType != 1))
476 goto error2;
478 if ((pIconDirEntry = malloc(iconDir.idCount * sizeof (ICONDIRENTRY))) == NULL)
479 goto error2;
480 if (fread(pIconDirEntry, sizeof (ICONDIRENTRY), iconDir.idCount, fICOFile) != iconDir.idCount)
481 goto error3;
483 for (i = 0; i < iconDir.idCount; i++)
484 if ((pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth) > nMax)
486 nIndex = i;
487 nMax = pIconDirEntry[i].bHeight * pIconDirEntry[i].bWidth;
489 if ((pIcon = malloc(pIconDirEntry[nIndex].dwBytesInRes)) == NULL)
490 goto error3;
491 if (fseek(fICOFile, pIconDirEntry[nIndex].dwImageOffset, SEEK_SET))
492 goto error4;
493 if (fread(pIcon, pIconDirEntry[nIndex].dwBytesInRes, 1, fICOFile) != 1)
494 goto error4;
496 if(!SaveIconResAsXPM(pIcon, szXPMFileName))
497 goto error4;
499 free(pIcon);
500 free(pIconDirEntry);
501 fclose(fICOFile);
503 return 1;
505 error4:
506 free(pIcon);
507 error3:
508 free(pIconDirEntry);
509 error2:
510 fclose(fICOFile);
511 error1:
512 return 0;
515 /* get the Unix file name for a given path, allocating the string */
516 inline static char *get_unix_file_name( const char *dos )
518 char buffer[MAX_PATH];
520 if (!wine_get_unix_file_name( dos, buffer, sizeof(buffer) )) return NULL;
521 return heap_strdup( buffer );
524 static BOOL create_default_icon( const char *filename )
526 FILE *fXPM;
527 int i;
529 if (!(fXPM = fopen(filename, "w"))) return FALSE;
530 fprintf(fXPM, "/* XPM */\nstatic char * icon[] = {");
531 for (i = 0; i < sizeof(wine_xpm)/sizeof(wine_xpm[0]); i++)
532 fprintf( fXPM, "\n\"%s\",", wine_xpm[i]);
533 fprintf( fXPM, "};\n" );
534 fclose( fXPM );
535 return TRUE;
538 /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
539 static char *extract_icon( const char *path, int index )
541 char *filename = heap_strdup( tmpnam(NULL) );
542 if (ExtractFromEXEDLL( path, index, filename )) return filename;
543 if (ExtractFromICO( path, filename )) return filename;
544 if (create_default_icon( filename )) return filename;
545 HeapFree( GetProcessHeap(), 0, filename );
546 return NULL;
550 static HRESULT WINAPI IPersistFile_fnSave(IPersistFile* iface, LPCOLESTR pszFileName, BOOL fRemember)
552 HRESULT ret = NOERROR;
553 int pid, status;
554 char buffer[MAX_PATH], buff2[MAX_PATH];
555 char *filename, *link_name, *p;
556 char *shell_link_app = NULL;
557 char *icon_name = NULL;
558 char *path_name = NULL;
559 char *work_dir = NULL;
560 BOOL bDesktop;
561 HKEY hkey;
563 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
565 TRACE("(%p)->(%s)\n",This,debugstr_w(pszFileName));
567 if (!pszFileName || !This->sPath)
568 return ERROR_UNKNOWN;
570 /* check for .exe extension */
571 if (!(p = strrchr( This->sPath, '.' ))) return NOERROR;
572 if (strchr( p, '\\' ) || strchr( p, '/' )) return NOERROR;
573 if (strcasecmp( p, ".exe" )) return NOERROR;
575 /* check if ShellLinker configured */
576 buffer[0] = 0;
577 if (!RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Wine",
578 0, KEY_ALL_ACCESS, &hkey ))
580 DWORD type, count = sizeof(buffer);
581 if (RegQueryValueExA( hkey, "ShellLinker", 0, &type, buffer, &count )) buffer[0] = 0;
582 RegCloseKey( hkey );
584 if (!*buffer) return NOERROR;
585 shell_link_app = heap_strdup( buffer );
587 if (!WideCharToMultiByte( CP_ACP, 0, pszFileName, -1, buffer, sizeof(buffer), NULL, NULL))
588 return ERROR_UNKNOWN;
589 GetFullPathNameA( buffer, sizeof(buff2), buff2, NULL );
590 filename = heap_strdup( buff2 );
592 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_STARTUP, FALSE ))
594 /* ignore startup for now */
595 if (!strncasecmp( filename, buffer, strlen(buffer) )) goto done;
597 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_DESKTOPDIRECTORY, FALSE ))
599 if (!strncasecmp( filename, buffer, strlen(buffer) ))
601 link_name = filename + strlen(buffer);
602 bDesktop = TRUE;
603 goto found;
606 if (SHGetSpecialFolderPathA( 0, buffer, CSIDL_STARTMENU, FALSE ))
608 if (!strncasecmp( filename, buffer, strlen(buffer) ))
610 link_name = filename + strlen(buffer);
611 bDesktop = FALSE;
612 goto found;
615 goto done;
617 found:
618 /* make link name a Unix name */
619 for (p = link_name; *p; p++) if (*p == '\\') *p = '/';
620 /* strip leading slashes */
621 while (*link_name == '/') link_name++;
622 /* remove extension */
623 if ((p = strrchr( link_name, '.' ))) *p = 0;
625 /* convert app path name */
626 path_name = get_unix_file_name( This->sPath );
628 /* convert app working dir */
629 if (This->sWorkDir) work_dir = get_unix_file_name( This->sWorkDir );
631 /* extract the icon */
632 if (!(icon_name = extract_icon( This->sIcoPath && strlen(This->sIcoPath) ?
633 This->sIcoPath : This->sPath,
634 This->iIcoNdx ))) goto done;
637 TRACE("linker app='%s' link='%s' mode=%s path='%s' args='%s' icon='%s' workdir='%s' descr='%s'\n",
638 shell_link_app, link_name, bDesktop ? "desktop" : "menu", path_name,
639 This->sArgs ? This->sArgs : "", icon_name, work_dir ? work_dir : "",
640 This->sDescription ? This->sDescription : "" );
642 if ((pid = fork()) == -1) goto done;
643 if (!pid)
645 int pos = 0;
646 char *argv[20];
647 argv[pos++] = shell_link_app;
648 argv[pos++] = "--link";
649 argv[pos++] = link_name;
650 argv[pos++] = "--path";
651 argv[pos++] = path_name;
652 argv[pos++] = bDesktop ? "--desktop" : "--menu";
653 if (This->sArgs && strlen(This->sArgs))
655 argv[pos++] = "--args";
656 argv[pos++] = This->sArgs;
658 if (icon_name)
660 argv[pos++] = "--icon";
661 argv[pos++] = icon_name;
663 if (This->sWorkDir && strlen(This->sWorkDir))
665 argv[pos++] = "--workdir";
666 argv[pos++] = This->sWorkDir;
668 if (This->sDescription && strlen(This->sDescription))
670 argv[pos++] = "--descr";
671 argv[pos++] = This->sDescription;
673 argv[pos] = NULL;
674 execvp( shell_link_app, argv );
675 _exit(1);
678 while (waitpid( pid, &status, 0 ) == -1)
680 if (errno != EINTR)
682 ret = ERROR_UNKNOWN;
683 goto done;
686 if (status) ret = E_ACCESSDENIED;
688 done:
689 if (icon_name) unlink( icon_name );
690 HeapFree( GetProcessHeap(), 0, shell_link_app );
691 HeapFree( GetProcessHeap(), 0, filename );
692 HeapFree( GetProcessHeap(), 0, icon_name );
693 HeapFree( GetProcessHeap(), 0, path_name );
694 HeapFree( GetProcessHeap(), 0, work_dir );
695 return ret;
698 static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile* iface, LPCOLESTR pszFileName)
700 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
701 FIXME("(%p)->(%s)\n",This,debugstr_w(pszFileName));
702 return NOERROR;
704 static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile* iface, LPOLESTR *ppszFileName)
706 _ICOM_THIS_From_IPersistFile(IShellLinkImpl, iface);
707 FIXME("(%p)\n",This);
708 return NOERROR;
711 static ICOM_VTABLE(IPersistFile) pfvt =
713 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
714 IPersistFile_fnQueryInterface,
715 IPersistFile_fnAddRef,
716 IPersistFile_fnRelease,
717 IPersistFile_fnGetClassID,
718 IPersistFile_fnIsDirty,
719 IPersistFile_fnLoad,
720 IPersistFile_fnSave,
721 IPersistFile_fnSaveCompleted,
722 IPersistFile_fnGetCurFile
725 /************************************************************************
726 * IPersistStream_QueryInterface
728 static HRESULT WINAPI IPersistStream_fnQueryInterface(
729 IPersistStream* iface,
730 REFIID riid,
731 VOID** ppvoid)
733 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
735 TRACE("(%p)\n",This);
737 return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvoid);
740 /************************************************************************
741 * IPersistStream_Release
743 static ULONG WINAPI IPersistStream_fnRelease(
744 IPersistStream* iface)
746 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
748 TRACE("(%p)\n",This);
750 return IShellLinkA_Release((IShellLinkA*)This);
753 /************************************************************************
754 * IPersistStream_AddRef
756 static ULONG WINAPI IPersistStream_fnAddRef(
757 IPersistStream* iface)
759 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
761 TRACE("(%p)\n",This);
763 return IShellLinkA_AddRef((IShellLinkA*)This);
766 /************************************************************************
767 * IPersistStream_GetClassID
770 static HRESULT WINAPI IPersistStream_fnGetClassID(
771 IPersistStream* iface,
772 CLSID* pClassID)
774 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
776 TRACE("(%p)\n", This);
778 if (pClassID==0)
779 return E_POINTER;
781 /* memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */
783 return S_OK;
786 /************************************************************************
787 * IPersistStream_IsDirty (IPersistStream)
789 static HRESULT WINAPI IPersistStream_fnIsDirty(
790 IPersistStream* iface)
792 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
794 TRACE("(%p)\n", This);
796 return S_OK;
798 /************************************************************************
799 * IPersistStream_Load (IPersistStream)
802 static HRESULT WINAPI IPersistStream_fnLoad(
803 IPersistStream* iface,
804 IStream* pLoadStream)
806 PLINK_HEADER lpLinkHeader = HeapAlloc(GetProcessHeap(), 0, LINK_HEADER_SIZE);
807 ULONG dwBytesRead;
808 DWORD ret = E_FAIL;
809 char sTemp[MAX_PATH];
811 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
813 TRACE("(%p)(%p)\n", This, pLoadStream);
815 if ( ! pLoadStream)
817 return STG_E_INVALIDPOINTER;
820 IStream_AddRef (pLoadStream);
821 if(lpLinkHeader)
823 if (SUCCEEDED(IStream_Read(pLoadStream, lpLinkHeader, LINK_HEADER_SIZE, &dwBytesRead)))
825 if ((lpLinkHeader->MagicStr == 0x0000004CL) && IsEqualIID(&lpLinkHeader->MagicGuid, &CLSID_ShellLink))
827 lpLinkHeader = HeapReAlloc(GetProcessHeap(), 0, lpLinkHeader, LINK_HEADER_SIZE+lpLinkHeader->PidlSize);
828 if (lpLinkHeader)
830 if (SUCCEEDED(IStream_Read(pLoadStream, &(lpLinkHeader->Pidl), lpLinkHeader->PidlSize, &dwBytesRead)))
832 if (pcheck (&lpLinkHeader->Pidl))
834 This->pPidl = ILClone (&lpLinkHeader->Pidl);
836 SHGetPathFromIDListA(&lpLinkHeader->Pidl, sTemp);
837 This->sPath = heap_strdup( sTemp );
839 This->wHotKey = lpLinkHeader->wHotKey;
840 FileTimeToSystemTime (&lpLinkHeader->Time1, &This->time1);
841 FileTimeToSystemTime (&lpLinkHeader->Time2, &This->time2);
842 FileTimeToSystemTime (&lpLinkHeader->Time3, &This->time3);
843 #if 1
844 GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time1, NULL, sTemp, 256);
845 TRACE("-- time1: %s\n", sTemp);
846 GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time2, NULL, sTemp, 256);
847 TRACE("-- time1: %s\n", sTemp);
848 GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&This->time3, NULL, sTemp, 256);
849 TRACE("-- time1: %s\n", sTemp);
850 pdump (This->pPidl);
851 #endif
852 ret = S_OK;
856 else
858 WARN("stream contains no link!\n");
863 IStream_Release (pLoadStream);
865 pdump(This->pPidl);
867 HeapFree(GetProcessHeap(), 0, lpLinkHeader);
869 return ret;
872 /************************************************************************
873 * IPersistStream_Save (IPersistStream)
875 static HRESULT WINAPI IPersistStream_fnSave(
876 IPersistStream* iface,
877 IStream* pOutStream,
878 BOOL fClearDirty)
880 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
882 TRACE("(%p) %p %x\n", This, pOutStream, fClearDirty);
884 return E_NOTIMPL;
887 /************************************************************************
888 * IPersistStream_GetSizeMax (IPersistStream)
890 static HRESULT WINAPI IPersistStream_fnGetSizeMax(
891 IPersistStream* iface,
892 ULARGE_INTEGER* pcbSize)
894 _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
896 TRACE("(%p)\n", This);
898 return E_NOTIMPL;
901 static ICOM_VTABLE(IPersistStream) psvt =
903 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
904 IPersistStream_fnQueryInterface,
905 IPersistStream_fnAddRef,
906 IPersistStream_fnRelease,
907 IPersistStream_fnGetClassID,
908 IPersistStream_fnIsDirty,
909 IPersistStream_fnLoad,
910 IPersistStream_fnSave,
911 IPersistStream_fnGetSizeMax
914 /**************************************************************************
915 * IShellLink_Constructor
917 IShellLinkA * IShellLink_Constructor(BOOL bUnicode)
918 { IShellLinkImpl * sl;
920 sl = (IShellLinkImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellLinkImpl));
921 sl->ref = 1;
922 ICOM_VTBL(sl) = &slvt;
923 sl->lpvtblw = &slvtw;
924 sl->lpvtblPersistFile = &pfvt;
925 sl->lpvtblPersistStream = &psvt;
927 TRACE("(%p)->()\n",sl);
928 shell32_ObjCount++;
929 return bUnicode ? (IShellLinkA *) &(sl->lpvtblw) : (IShellLinkA *)sl;
932 /**************************************************************************
933 * IShellLinkA_QueryInterface
935 static HRESULT WINAPI IShellLinkA_fnQueryInterface( IShellLinkA * iface, REFIID riid, LPVOID *ppvObj)
937 ICOM_THIS(IShellLinkImpl, iface);
939 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
941 *ppvObj = NULL;
943 if(IsEqualIID(riid, &IID_IUnknown) ||
944 IsEqualIID(riid, &IID_IShellLinkA))
946 *ppvObj = This;
948 else if(IsEqualIID(riid, &IID_IShellLinkW))
950 *ppvObj = (IShellLinkW *)&(This->lpvtblw);
952 else if(IsEqualIID(riid, &IID_IPersistFile))
954 *ppvObj = (IPersistFile *)&(This->lpvtblPersistFile);
956 else if(IsEqualIID(riid, &IID_IPersistStream))
958 *ppvObj = (IPersistStream *)&(This->lpvtblPersistStream);
961 if(*ppvObj)
963 IUnknown_AddRef((IUnknown*)(*ppvObj));
964 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
965 return S_OK;
967 TRACE("-- Interface: E_NOINTERFACE\n");
968 return E_NOINTERFACE;
970 /******************************************************************************
971 * IShellLinkA_AddRef
973 static ULONG WINAPI IShellLinkA_fnAddRef(IShellLinkA * iface)
975 ICOM_THIS(IShellLinkImpl, iface);
977 TRACE("(%p)->(count=%lu)\n",This,This->ref);
979 shell32_ObjCount++;
980 return ++(This->ref);
982 /******************************************************************************
983 * IShellLinkA_Release
985 static ULONG WINAPI IShellLinkA_fnRelease(IShellLinkA * iface)
987 ICOM_THIS(IShellLinkImpl, iface);
989 TRACE("(%p)->(count=%lu)\n",This,This->ref);
991 shell32_ObjCount--;
992 if (!--(This->ref))
993 { TRACE("-- destroying IShellLink(%p)\n",This);
995 if (This->sIcoPath)
996 HeapFree(GetProcessHeap(), 0, This->sIcoPath);
998 if (This->sArgs)
999 HeapFree(GetProcessHeap(), 0, This->sArgs);
1001 if (This->sWorkDir)
1002 HeapFree(GetProcessHeap(), 0, This->sWorkDir);
1004 if (This->sDescription)
1005 HeapFree(GetProcessHeap(), 0, This->sDescription);
1007 if (This->sPath)
1008 HeapFree(GetProcessHeap(),0,This->sPath);
1010 if (This->pPidl)
1011 SHFree(This->pPidl);
1013 if (This->lpFileStream)
1014 IStream_Release(This->lpFileStream);
1016 This->iIcoNdx = 0;
1018 HeapFree(GetProcessHeap(),0,This);
1019 return 0;
1021 return This->ref;
1024 static HRESULT WINAPI IShellLinkA_fnGetPath(IShellLinkA * iface, LPSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
1026 ICOM_THIS(IShellLinkImpl, iface);
1028 TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n",This, pszFile, cchMaxPath, pfd, fFlags, debugstr_a(This->sPath));
1030 if (This->sPath)
1031 lstrcpynA(pszFile,This->sPath, cchMaxPath);
1032 else
1033 return E_FAIL;
1035 return NOERROR;
1037 static HRESULT WINAPI IShellLinkA_fnGetIDList(IShellLinkA * iface, LPITEMIDLIST * ppidl)
1039 ICOM_THIS(IShellLinkImpl, iface);
1041 TRACE("(%p)->(ppidl=%p)\n",This, ppidl);
1043 *ppidl = ILClone(This->pPidl);
1044 return NOERROR;
1046 static HRESULT WINAPI IShellLinkA_fnSetIDList(IShellLinkA * iface, LPCITEMIDLIST pidl)
1048 ICOM_THIS(IShellLinkImpl, iface);
1050 TRACE("(%p)->(pidl=%p)\n",This, pidl);
1052 if (This->pPidl)
1053 SHFree(This->pPidl);
1054 This->pPidl = ILClone (pidl);
1055 return NOERROR;
1057 static HRESULT WINAPI IShellLinkA_fnGetDescription(IShellLinkA * iface, LPSTR pszName,INT cchMaxName)
1059 ICOM_THIS(IShellLinkImpl, iface);
1061 FIXME("(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
1062 lstrcpynA(pszName,"Description, FIXME",cchMaxName);
1063 return NOERROR;
1065 static HRESULT WINAPI IShellLinkA_fnSetDescription(IShellLinkA * iface, LPCSTR pszName)
1067 ICOM_THIS(IShellLinkImpl, iface);
1069 TRACE("(%p)->(pName=%s)\n", This, pszName);
1071 if (This->sDescription)
1072 HeapFree(GetProcessHeap(), 0, This->sDescription);
1073 if (!(This->sDescription = heap_strdup(pszName)))
1074 return E_OUTOFMEMORY;
1076 return NOERROR;
1078 static HRESULT WINAPI IShellLinkA_fnGetWorkingDirectory(IShellLinkA * iface, LPSTR pszDir,INT cchMaxPath)
1080 ICOM_THIS(IShellLinkImpl, iface);
1082 TRACE("(%p)->(%p len=%u)\n", This, pszDir, cchMaxPath);
1084 lstrcpynA( pszDir, This->sWorkDir ? This->sWorkDir : "", cchMaxPath );
1086 return NOERROR;
1088 static HRESULT WINAPI IShellLinkA_fnSetWorkingDirectory(IShellLinkA * iface, LPCSTR pszDir)
1090 ICOM_THIS(IShellLinkImpl, iface);
1092 TRACE("(%p)->(dir=%s)\n",This, pszDir);
1094 if (This->sWorkDir)
1095 HeapFree(GetProcessHeap(), 0, This->sWorkDir);
1096 if (!(This->sWorkDir = heap_strdup(pszDir)))
1097 return E_OUTOFMEMORY;
1099 return NOERROR;
1101 static HRESULT WINAPI IShellLinkA_fnGetArguments(IShellLinkA * iface, LPSTR pszArgs,INT cchMaxPath)
1103 ICOM_THIS(IShellLinkImpl, iface);
1105 TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath);
1107 lstrcpynA( pszArgs, This->sArgs ? This->sArgs : "", cchMaxPath );
1109 return NOERROR;
1111 static HRESULT WINAPI IShellLinkA_fnSetArguments(IShellLinkA * iface, LPCSTR pszArgs)
1113 ICOM_THIS(IShellLinkImpl, iface);
1115 TRACE("(%p)->(args=%s)\n",This, pszArgs);
1117 if (This->sArgs)
1118 HeapFree(GetProcessHeap(), 0, This->sArgs);
1119 if (!(This->sArgs = heap_strdup(pszArgs)))
1120 return E_OUTOFMEMORY;
1122 return NOERROR;
1124 static HRESULT WINAPI IShellLinkA_fnGetHotkey(IShellLinkA * iface, WORD *pwHotkey)
1126 ICOM_THIS(IShellLinkImpl, iface);
1128 TRACE("(%p)->(%p)(0x%08x)\n",This, pwHotkey, This->wHotKey);
1130 *pwHotkey = This->wHotKey;
1132 return NOERROR;
1134 static HRESULT WINAPI IShellLinkA_fnSetHotkey(IShellLinkA * iface, WORD wHotkey)
1136 ICOM_THIS(IShellLinkImpl, iface);
1138 TRACE("(%p)->(hotkey=%x)\n",This, wHotkey);
1140 This->wHotKey = wHotkey;
1142 return NOERROR;
1144 static HRESULT WINAPI IShellLinkA_fnGetShowCmd(IShellLinkA * iface, INT *piShowCmd)
1146 ICOM_THIS(IShellLinkImpl, iface);
1148 FIXME("(%p)->(%p)\n",This, piShowCmd);
1149 *piShowCmd=0;
1150 return NOERROR;
1152 static HRESULT WINAPI IShellLinkA_fnSetShowCmd(IShellLinkA * iface, INT iShowCmd)
1154 ICOM_THIS(IShellLinkImpl, iface);
1156 FIXME("(%p)->(showcmd=%x)\n",This, iShowCmd);
1157 return NOERROR;
1159 static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR pszIconPath,INT cchIconPath,INT *piIcon)
1161 ICOM_THIS(IShellLinkImpl, iface);
1163 TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon);
1165 lstrcpynA( pszIconPath, This->sIcoPath ? This->sIcoPath : "", cchIconPath );
1166 *piIcon = This->iIcoNdx;
1168 return NOERROR;
1170 static HRESULT WINAPI IShellLinkA_fnSetIconLocation(IShellLinkA * iface, LPCSTR pszIconPath,INT iIcon)
1172 ICOM_THIS(IShellLinkImpl, iface);
1174 TRACE("(%p)->(path=%s iicon=%u)\n",This, pszIconPath, iIcon);
1176 if (This->sIcoPath)
1177 HeapFree(GetProcessHeap(), 0, This->sIcoPath);
1178 if (!(This->sIcoPath = heap_strdup(pszIconPath)))
1179 return E_OUTOFMEMORY;
1180 This->iIcoNdx = iIcon;
1182 return NOERROR;
1184 static HRESULT WINAPI IShellLinkA_fnSetRelativePath(IShellLinkA * iface, LPCSTR pszPathRel, DWORD dwReserved)
1186 ICOM_THIS(IShellLinkImpl, iface);
1188 FIXME("(%p)->(path=%s %lx)\n",This, pszPathRel, dwReserved);
1189 return NOERROR;
1191 static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags)
1193 ICOM_THIS(IShellLinkImpl, iface);
1195 FIXME("(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
1196 return NOERROR;
1198 static HRESULT WINAPI IShellLinkA_fnSetPath(IShellLinkA * iface, LPCSTR pszFile)
1200 ICOM_THIS(IShellLinkImpl, iface);
1202 TRACE("(%p)->(path=%s)\n",This, pszFile);
1204 if (This->sPath)
1205 HeapFree(GetProcessHeap(), 0, This->sPath);
1206 if (!(This->sPath = heap_strdup(pszFile)))
1207 return E_OUTOFMEMORY;
1209 return NOERROR;
1212 /**************************************************************************
1213 * IShellLink Implementation
1216 static ICOM_VTABLE(IShellLinkA) slvt =
1218 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1219 IShellLinkA_fnQueryInterface,
1220 IShellLinkA_fnAddRef,
1221 IShellLinkA_fnRelease,
1222 IShellLinkA_fnGetPath,
1223 IShellLinkA_fnGetIDList,
1224 IShellLinkA_fnSetIDList,
1225 IShellLinkA_fnGetDescription,
1226 IShellLinkA_fnSetDescription,
1227 IShellLinkA_fnGetWorkingDirectory,
1228 IShellLinkA_fnSetWorkingDirectory,
1229 IShellLinkA_fnGetArguments,
1230 IShellLinkA_fnSetArguments,
1231 IShellLinkA_fnGetHotkey,
1232 IShellLinkA_fnSetHotkey,
1233 IShellLinkA_fnGetShowCmd,
1234 IShellLinkA_fnSetShowCmd,
1235 IShellLinkA_fnGetIconLocation,
1236 IShellLinkA_fnSetIconLocation,
1237 IShellLinkA_fnSetRelativePath,
1238 IShellLinkA_fnResolve,
1239 IShellLinkA_fnSetPath
1243 /**************************************************************************
1244 * IShellLinkW_fnQueryInterface
1246 static HRESULT WINAPI IShellLinkW_fnQueryInterface(
1247 IShellLinkW * iface, REFIID riid, LPVOID *ppvObj)
1249 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1251 return IShellLinkA_QueryInterface((IShellLinkA*)This, riid, ppvObj);
1254 /******************************************************************************
1255 * IShellLinkW_fnAddRef
1257 static ULONG WINAPI IShellLinkW_fnAddRef(IShellLinkW * iface)
1259 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1261 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1263 return IShellLinkA_AddRef((IShellLinkA*)This);
1265 /******************************************************************************
1266 * IShellLinkW_fnRelease
1269 static ULONG WINAPI IShellLinkW_fnRelease(IShellLinkW * iface)
1271 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1273 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1275 return IShellLinkA_Release((IShellLinkA*)This);
1278 static HRESULT WINAPI IShellLinkW_fnGetPath(IShellLinkW * iface, LPWSTR pszFile,INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags)
1280 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1282 FIXME("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This, pszFile, cchMaxPath, pfd, fFlags);
1283 MultiByteToWideChar( CP_ACP, 0, "c:\\foo.bar", -1, pszFile, cchMaxPath );
1284 return NOERROR;
1287 static HRESULT WINAPI IShellLinkW_fnGetIDList(IShellLinkW * iface, LPITEMIDLIST * ppidl)
1289 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1291 FIXME("(%p)->(ppidl=%p)\n",This, ppidl);
1292 *ppidl = _ILCreateDesktop();
1293 return NOERROR;
1296 static HRESULT WINAPI IShellLinkW_fnSetIDList(IShellLinkW * iface, LPCITEMIDLIST pidl)
1298 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1300 FIXME("(%p)->(pidl=%p)\n",This, pidl);
1301 return NOERROR;
1304 static HRESULT WINAPI IShellLinkW_fnGetDescription(IShellLinkW * iface, LPWSTR pszName,INT cchMaxName)
1306 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1308 FIXME("(%p)->(%p len=%u)\n",This, pszName, cchMaxName);
1309 MultiByteToWideChar( CP_ACP, 0, "Description, FIXME", -1, pszName, cchMaxName );
1310 return NOERROR;
1313 static HRESULT WINAPI IShellLinkW_fnSetDescription(IShellLinkW * iface, LPCWSTR pszName)
1315 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1317 TRACE("(%p)->(desc=%s)\n",This, debugstr_w(pszName));
1319 if (This->sDescription)
1320 HeapFree(GetProcessHeap(), 0, This->sDescription);
1321 if (!(This->sDescription = HEAP_strdupWtoA(GetProcessHeap(), 0, pszName)))
1322 return E_OUTOFMEMORY;
1324 return NOERROR;
1327 static HRESULT WINAPI IShellLinkW_fnGetWorkingDirectory(IShellLinkW * iface, LPWSTR pszDir,INT cchMaxPath)
1329 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1331 TRACE("(%p)->(%p len %u)\n", This, pszDir, cchMaxPath);
1333 MultiByteToWideChar( CP_ACP, 0, This->sWorkDir ? This->sWorkDir : "", -1, pszDir, cchMaxPath );
1335 return NOERROR;
1338 static HRESULT WINAPI IShellLinkW_fnSetWorkingDirectory(IShellLinkW * iface, LPCWSTR pszDir)
1340 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1342 TRACE("(%p)->(dir=%s)\n",This, debugstr_w(pszDir));
1344 if (This->sWorkDir)
1345 HeapFree(GetProcessHeap(), 0, This->sWorkDir);
1346 if (!(This->sWorkDir = HEAP_strdupWtoA(GetProcessHeap(), 0, pszDir)))
1347 return E_OUTOFMEMORY;
1349 return NOERROR;
1352 static HRESULT WINAPI IShellLinkW_fnGetArguments(IShellLinkW * iface, LPWSTR pszArgs,INT cchMaxPath)
1354 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1356 TRACE("(%p)->(%p len=%u)\n", This, pszArgs, cchMaxPath);
1358 MultiByteToWideChar( CP_ACP, 0, This->sArgs ? This->sArgs : "", -1, pszArgs, cchMaxPath );
1360 return NOERROR;
1363 static HRESULT WINAPI IShellLinkW_fnSetArguments(IShellLinkW * iface, LPCWSTR pszArgs)
1365 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1367 TRACE("(%p)->(args=%s)\n",This, debugstr_w(pszArgs));
1369 if (This->sArgs)
1370 HeapFree(GetProcessHeap(), 0, This->sArgs);
1371 if (!(This->sArgs = HEAP_strdupWtoA(GetProcessHeap(), 0, pszArgs)))
1372 return E_OUTOFMEMORY;
1374 return NOERROR;
1377 static HRESULT WINAPI IShellLinkW_fnGetHotkey(IShellLinkW * iface, WORD *pwHotkey)
1379 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1381 FIXME("(%p)->(%p)\n",This, pwHotkey);
1382 *pwHotkey=0x0;
1383 return NOERROR;
1386 static HRESULT WINAPI IShellLinkW_fnSetHotkey(IShellLinkW * iface, WORD wHotkey)
1388 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1390 FIXME("(%p)->(hotkey=%x)\n",This, wHotkey);
1391 return NOERROR;
1394 static HRESULT WINAPI IShellLinkW_fnGetShowCmd(IShellLinkW * iface, INT *piShowCmd)
1396 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1398 FIXME("(%p)->(%p)\n",This, piShowCmd);
1399 *piShowCmd=0;
1400 return NOERROR;
1403 static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd)
1405 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1407 FIXME("(%p)->(showcmd=%x)\n",This, iShowCmd);
1408 return NOERROR;
1411 static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR pszIconPath,INT cchIconPath,INT *piIcon)
1413 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1415 TRACE("(%p)->(%p len=%u iicon=%p)\n", This, pszIconPath, cchIconPath, piIcon);
1417 MultiByteToWideChar( CP_ACP, 0, This->sIcoPath ? This->sIcoPath : "", -1, pszIconPath, cchIconPath );
1418 *piIcon = This->iIcoNdx;
1420 return NOERROR;
1423 static HRESULT WINAPI IShellLinkW_fnSetIconLocation(IShellLinkW * iface, LPCWSTR pszIconPath,INT iIcon)
1425 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1427 TRACE("(%p)->(path=%s iicon=%u)\n",This, debugstr_w(pszIconPath), iIcon);
1429 if (This->sIcoPath)
1430 HeapFree(GetProcessHeap(), 0, This->sIcoPath);
1431 if (!(This->sIcoPath = HEAP_strdupWtoA(GetProcessHeap(), 0, pszIconPath)))
1432 return E_OUTOFMEMORY;
1433 This->iIcoNdx = iIcon;
1435 return NOERROR;
1438 static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR pszPathRel, DWORD dwReserved)
1440 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1442 FIXME("(%p)->(path=%s %lx)\n",This, debugstr_w(pszPathRel), dwReserved);
1443 return NOERROR;
1446 static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags)
1448 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1450 FIXME("(%p)->(hwnd=%x flags=%lx)\n",This, hwnd, fFlags);
1451 return NOERROR;
1454 static HRESULT WINAPI IShellLinkW_fnSetPath(IShellLinkW * iface, LPCWSTR pszFile)
1456 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, iface);
1458 TRACE("(%p)->(path=%s)\n",This, debugstr_w(pszFile));
1460 if (This->sPath)
1461 HeapFree(GetProcessHeap(), 0, This->sPath);
1462 if (!(This->sPath = HEAP_strdupWtoA(GetProcessHeap(), 0, pszFile)))
1463 return E_OUTOFMEMORY;
1465 return NOERROR;
1468 /**************************************************************************
1469 * IShellLinkW Implementation
1472 static ICOM_VTABLE(IShellLinkW) slvtw =
1474 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1475 IShellLinkW_fnQueryInterface,
1476 IShellLinkW_fnAddRef,
1477 IShellLinkW_fnRelease,
1478 IShellLinkW_fnGetPath,
1479 IShellLinkW_fnGetIDList,
1480 IShellLinkW_fnSetIDList,
1481 IShellLinkW_fnGetDescription,
1482 IShellLinkW_fnSetDescription,
1483 IShellLinkW_fnGetWorkingDirectory,
1484 IShellLinkW_fnSetWorkingDirectory,
1485 IShellLinkW_fnGetArguments,
1486 IShellLinkW_fnSetArguments,
1487 IShellLinkW_fnGetHotkey,
1488 IShellLinkW_fnSetHotkey,
1489 IShellLinkW_fnGetShowCmd,
1490 IShellLinkW_fnSetShowCmd,
1491 IShellLinkW_fnGetIconLocation,
1492 IShellLinkW_fnSetIconLocation,
1493 IShellLinkW_fnSetRelativePath,
1494 IShellLinkW_fnResolve,
1495 IShellLinkW_fnSetPath