3 * Copyright 1997 Marcus Meissner
4 * Copyright 1998 Juergen Schmied
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #ifdef HAVE_SYS_WAIT_H
28 # include <sys/wait.h>
30 #include "wine/debug.h"
37 #include "undocshell.h"
38 #include "bitmaps/wine.xpm"
42 #include "shell32_main.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
47 /* link file formats */
51 /* flag1: lnk elements: simple link has 0x0B */
59 #define MAXIMIZED 0x03
60 #define MINIMIZED 0x07
62 typedef struct _LINK_HEADER
63 { DWORD MagicStr
; /* 0x00 'L','\0','\0','\0' */
64 GUID MagicGuid
; /* 0x04 is CLSID_ShellLink */
65 DWORD Flag1
; /* 0x14 describes elements following */
66 DWORD Flag2
; /* 0x18 */
67 FILETIME Time1
; /* 0x1c */
68 FILETIME Time2
; /* 0x24 */
69 FILETIME Time3
; /* 0x2c */
70 DWORD Unknown1
; /* 0x34 */
71 DWORD Unknown2
; /* 0x38 icon number */
72 DWORD fStartup
; /* 0x3c startup type */
73 DWORD wHotKey
; /* 0x40 hotkey */
74 DWORD Unknown5
; /* 0x44 */
75 DWORD Unknown6
; /* 0x48 */
76 USHORT PidlSize
; /* 0x4c */
77 ITEMIDLIST Pidl
; /* 0x4e */
78 } LINK_HEADER
, * PLINK_HEADER
;
80 #define LINK_HEADER_SIZE (sizeof(LINK_HEADER)-sizeof(ITEMIDLIST))
99 GRPICONDIRENTRY idEntries
[1];
130 static ICOM_VTABLE(IShellLinkA
) slvt
;
131 static ICOM_VTABLE(IShellLinkW
) slvtw
;
132 static ICOM_VTABLE(IPersistFile
) pfvt
;
133 static ICOM_VTABLE(IPersistStream
) psvt
;
135 /* IShellLink Implementation */
139 ICOM_VFIELD(IShellLinkA
);
142 ICOM_VTABLE(IShellLinkW
)* lpvtblw
;
143 ICOM_VTABLE(IPersistFile
)* lpvtblPersistFile
;
144 ICOM_VTABLE(IPersistStream
)* lpvtblPersistStream
;
146 /* internal stream of the IPersistFile interface */
147 IStream
* lpFileStream
;
149 /* data structures according to the informations in the lnk */
164 #define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw)))
165 #define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset);
167 #define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile)))
168 #define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset);
170 #define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream)))
171 #define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset);
172 #define _IPersistStream_From_ICOM_THIS(class, name) class* StreamThis = (class*)(((char*)name)+_IPersistStream_Offset);
175 /* strdup on the process heap */
176 inline static LPSTR
heap_strdup( LPCSTR str
)
178 INT len
= strlen(str
) + 1;
179 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, len
);
180 if (p
) memcpy( p
, str
, len
);
185 /**************************************************************************
186 * IPersistFile_QueryInterface
188 static HRESULT WINAPI
IPersistFile_fnQueryInterface(
193 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
195 TRACE("(%p)\n",This
);
197 return IShellLinkA_QueryInterface((IShellLinkA
*)This
, riid
, ppvObj
);
200 /******************************************************************************
201 * IPersistFile_AddRef
203 static ULONG WINAPI
IPersistFile_fnAddRef(IPersistFile
* iface
)
205 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
207 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
209 return IShellLinkA_AddRef((IShellLinkA
*)This
);
211 /******************************************************************************
212 * IPersistFile_Release
214 static ULONG WINAPI
IPersistFile_fnRelease(IPersistFile
* iface
)
216 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
218 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
220 return IShellLinkA_Release((IShellLinkA
*)This
);
223 static HRESULT WINAPI
IPersistFile_fnGetClassID(IPersistFile
* iface
, CLSID
*pClassID
)
225 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
226 FIXME("(%p)\n",This
);
229 static HRESULT WINAPI
IPersistFile_fnIsDirty(IPersistFile
* iface
)
231 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
232 FIXME("(%p)\n",This
);
235 static HRESULT WINAPI
IPersistFile_fnLoad(IPersistFile
* iface
, LPCOLESTR pszFileName
, DWORD dwMode
)
237 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
238 _IPersistStream_From_ICOM_THIS(IPersistStream
, This
)
240 LPSTR sFile
= HEAP_strdupWtoA ( GetProcessHeap(), 0, pszFileName
);
241 HRESULT hRet
= E_FAIL
;
243 TRACE("(%p, %s)\n",This
, sFile
);
246 if (This
->lpFileStream
)
247 IStream_Release(This
->lpFileStream
);
249 if SUCCEEDED(CreateStreamOnFile(sFile
, &(This
->lpFileStream
)))
251 if SUCCEEDED (IPersistStream_Load(StreamThis
, This
->lpFileStream
))
261 /* Icon extraction routines
263 * FIXME: should use PrivateExtractIcons and friends
264 * FIXME: should not use stdio
267 static BOOL
SaveIconResAsXPM(const BITMAPINFO
*pIcon
, const char *szXPMFileName
)
277 BOOL aColorUsed
[256] = {0};
281 if (!((pIcon
->bmiHeader
.biBitCount
== 4) || (pIcon
->bmiHeader
.biBitCount
== 8)))
284 if (!(fXPMFile
= fopen(szXPMFileName
, "w")))
287 nHeight
= pIcon
->bmiHeader
.biHeight
/ 2;
288 nXORWidthBytes
= 4 * ((pIcon
->bmiHeader
.biWidth
* pIcon
->bmiHeader
.biBitCount
/ 32)
289 + ((pIcon
->bmiHeader
.biWidth
* pIcon
->bmiHeader
.biBitCount
% 32) > 0));
290 nANDWidthBytes
= 4 * ((pIcon
->bmiHeader
.biWidth
/ 32)
291 + ((pIcon
->bmiHeader
.biWidth
% 32) > 0));
292 b8BitColors
= pIcon
->bmiHeader
.biBitCount
== 8;
293 nColors
= pIcon
->bmiHeader
.biClrUsed
? pIcon
->bmiHeader
.biClrUsed
294 : 1 << pIcon
->bmiHeader
.biBitCount
;
295 pXOR
= (BYTE
*) pIcon
+ sizeof (BITMAPINFOHEADER
) + (nColors
* sizeof (RGBQUAD
));
296 pAND
= pXOR
+ nHeight
* nXORWidthBytes
;
298 #define MASK(x,y) (pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8)))
299 #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)
301 for (i
= 0; i
< nHeight
; i
++)
302 for (j
= 0; j
< pIcon
->bmiHeader
.biWidth
; j
++)
303 if (!aColorUsed
[COLOR(j
,i
)] && !MASK(j
,i
))
305 aColorUsed
[COLOR(j
,i
)] = TRUE
;
309 if (fprintf(fXPMFile
, "/* XPM */\nstatic char *icon[] = {\n") <= 0)
311 if (fprintf(fXPMFile
, "\"%d %d %d %d\",\n",
312 (int) pIcon
->bmiHeader
.biWidth
, nHeight
, nColorsUsed
+ 1, 2) <=0)
315 for (i
= 0; i
< nColors
; i
++)
317 if (fprintf(fXPMFile
, "\"%.2X c #%.2X%.2X%.2X\",\n", i
, pIcon
->bmiColors
[i
].rgbRed
,
318 pIcon
->bmiColors
[i
].rgbGreen
, pIcon
->bmiColors
[i
].rgbBlue
) <= 0)
320 if (fprintf(fXPMFile
, "\" c None\"") <= 0)
323 for (i
= 0; i
< nHeight
; i
++)
325 if (fprintf(fXPMFile
, ",\n\"") <= 0)
327 for (j
= 0; j
< pIcon
->bmiHeader
.biWidth
; j
++)
331 if (fprintf(fXPMFile
, " ") <= 0)
335 if (fprintf(fXPMFile
, "%.2X", COLOR(j
,i
)) <= 0)
338 if (fprintf(fXPMFile
, "\"") <= 0)
341 if (fprintf(fXPMFile
, "};\n") <= 0)
352 unlink( szXPMFileName
);
356 static BOOL CALLBACK
EnumResNameProc(HANDLE hModule
, const char *lpszType
, char *lpszName
, LONG lParam
)
358 ENUMRESSTRUCT
*sEnumRes
= (ENUMRESSTRUCT
*) lParam
;
360 if (!sEnumRes
->nIndex
--)
362 *sEnumRes
->pResInfo
= FindResourceA(hModule
, lpszName
, RT_GROUP_ICONA
);
369 static int ExtractFromEXEDLL(const char *szFileName
, int nIndex
, const char *szXPMFileName
)
375 GRPICONDIR
*pIconDir
;
377 ENUMRESSTRUCT sEnumRes
;
382 if (!(hModule
= LoadLibraryExA(szFileName
, 0, LOAD_LIBRARY_AS_DATAFILE
)))
384 TRACE("LoadLibraryExA (%s) failed, error %ld\n", szFileName
, GetLastError());
390 hResInfo
= FindResourceA(hModule
, MAKEINTRESOURCEA(-nIndex
), RT_GROUP_ICONA
);
391 TRACE("FindResourceA (%s) called, return 0x%x, error %ld\n", szFileName
, hResInfo
, GetLastError());
395 sEnumRes
.pResInfo
= &hResInfo
;
396 sEnumRes
.nIndex
= nIndex
;
397 if (EnumResourceNamesA(hModule
, RT_GROUP_ICONA
, &EnumResNameProc
, (LONG
) &sEnumRes
))
399 TRACE("EnumResourceNamesA failed, error %ld\n", GetLastError());
406 TRACE("ExtractFromEXEDLL failed, error %ld\n", GetLastError());
410 if (!(hResData
= LoadResource(hModule
, hResInfo
)))
412 TRACE("LoadResource failed, error %ld\n", GetLastError());
415 if (!(pIconDir
= LockResource(hResData
)))
417 TRACE("LockResource failed, error %ld\n", GetLastError());
421 for (i
= 0; i
< pIconDir
->idCount
; i
++)
422 if ((pIconDir
->idEntries
[i
].wBitCount
>= nMaxBits
) && (pIconDir
->idEntries
[i
].wBitCount
<= 8))
424 if (pIconDir
->idEntries
[i
].wBitCount
> nMaxBits
)
426 nMaxBits
= pIconDir
->idEntries
[i
].wBitCount
;
429 if ((pIconDir
->idEntries
[i
].bHeight
* pIconDir
->idEntries
[i
].bWidth
) > nMax
)
431 lpName
= MAKEINTRESOURCEA(pIconDir
->idEntries
[i
].nID
);
432 nMax
= pIconDir
->idEntries
[i
].bHeight
* pIconDir
->idEntries
[i
].bWidth
;
436 FreeResource(hResData
);
438 if (!(hResInfo
= FindResourceA(hModule
, lpName
, RT_ICONA
)))
440 TRACE("Second FindResourceA failed, error %ld\n", GetLastError());
443 if (!(hResData
= LoadResource(hModule
, hResInfo
)))
445 TRACE("Second LoadResource failed, error %ld\n", GetLastError());
448 if (!(pIcon
= LockResource(hResData
)))
450 TRACE("Second LockResource failed, error %ld\n", GetLastError());
454 if(!SaveIconResAsXPM(pIcon
, szXPMFileName
))
456 TRACE("Failed saving icon as XPM, error %ld\n", GetLastError());
460 FreeResource(hResData
);
461 FreeLibrary(hModule
);
466 FreeResource(hResData
);
468 FreeLibrary(hModule
);
473 static int ExtractFromICO(const char *szFileName
, const char *szXPMFileName
)
477 ICONDIRENTRY
*pIconDirEntry
;
483 if (!(fICOFile
= fopen(szFileName
, "r")))
486 if (fread(&iconDir
, sizeof (ICONDIR
), 1, fICOFile
) != 1)
488 if ((iconDir
.idReserved
!= 0) || (iconDir
.idType
!= 1))
491 if ((pIconDirEntry
= malloc(iconDir
.idCount
* sizeof (ICONDIRENTRY
))) == NULL
)
493 if (fread(pIconDirEntry
, sizeof (ICONDIRENTRY
), iconDir
.idCount
, fICOFile
) != iconDir
.idCount
)
496 for (i
= 0; i
< iconDir
.idCount
; i
++)
497 if ((pIconDirEntry
[i
].bHeight
* pIconDirEntry
[i
].bWidth
) > nMax
)
500 nMax
= pIconDirEntry
[i
].bHeight
* pIconDirEntry
[i
].bWidth
;
502 if ((pIcon
= malloc(pIconDirEntry
[nIndex
].dwBytesInRes
)) == NULL
)
504 if (fseek(fICOFile
, pIconDirEntry
[nIndex
].dwImageOffset
, SEEK_SET
))
506 if (fread(pIcon
, pIconDirEntry
[nIndex
].dwBytesInRes
, 1, fICOFile
) != 1)
509 if(!SaveIconResAsXPM(pIcon
, szXPMFileName
))
528 /* get the Unix file name for a given path, allocating the string */
529 inline static char *get_unix_file_name( const char *dos
)
531 char buffer
[MAX_PATH
];
533 if (!wine_get_unix_file_name( dos
, buffer
, sizeof(buffer
) )) return NULL
;
534 return heap_strdup( buffer
);
537 static BOOL
create_default_icon( const char *filename
)
542 if (!(fXPM
= fopen(filename
, "w"))) return FALSE
;
543 fprintf(fXPM
, "/* XPM */\nstatic char * icon[] = {");
544 for (i
= 0; i
< sizeof(wine_xpm
)/sizeof(wine_xpm
[0]); i
++)
545 fprintf( fXPM
, "\n\"%s\",", wine_xpm
[i
]);
546 fprintf( fXPM
, "};\n" );
551 /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
552 static char *extract_icon( const char *path
, int index
)
554 char *filename
= heap_strdup( tmpnam(NULL
) );
555 if (ExtractFromEXEDLL( path
, index
, filename
)) return filename
;
556 if (ExtractFromICO( path
, filename
)) return filename
;
557 if (create_default_icon( filename
)) return filename
;
558 HeapFree( GetProcessHeap(), 0, filename
);
563 static HRESULT WINAPI
IPersistFile_fnSave(IPersistFile
* iface
, LPCOLESTR pszFileName
, BOOL fRemember
)
565 HRESULT ret
= NOERROR
;
567 char buffer
[MAX_PATH
], buff2
[MAX_PATH
];
568 char *filename
, *link_name
, *p
;
569 char *shell_link_app
= NULL
;
570 char *icon_name
= NULL
;
571 char *path_name
= NULL
;
572 char *work_dir
= NULL
;
576 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
);
578 TRACE("(%p)->(%s)\n",This
,debugstr_w(pszFileName
));
580 if (!pszFileName
|| !This
->sPath
)
581 return ERROR_UNKNOWN
;
583 /* check for .exe extension */
584 if (!(p
= strrchr( This
->sPath
, '.' ))) return NOERROR
;
585 if (strchr( p
, '\\' ) || strchr( p
, '/' )) return NOERROR
;
586 if (strcasecmp( p
, ".exe" )) return NOERROR
;
588 /* check if ShellLinker configured */
590 if (!RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\Wine",
591 0, KEY_ALL_ACCESS
, &hkey
))
593 DWORD type
, count
= sizeof(buffer
);
594 if (RegQueryValueExA( hkey
, "ShellLinker", 0, &type
, buffer
, &count
)) buffer
[0] = 0;
597 if (!*buffer
) return NOERROR
;
598 shell_link_app
= heap_strdup( buffer
);
600 if (!WideCharToMultiByte( CP_ACP
, 0, pszFileName
, -1, buffer
, sizeof(buffer
), NULL
, NULL
))
601 return ERROR_UNKNOWN
;
602 GetFullPathNameA( buffer
, sizeof(buff2
), buff2
, NULL
);
603 filename
= heap_strdup( buff2
);
605 if (SHGetSpecialFolderPathA( 0, buffer
, CSIDL_STARTUP
, FALSE
))
607 /* ignore startup for now */
608 if (!strncasecmp( filename
, buffer
, strlen(buffer
) )) goto done
;
610 if (SHGetSpecialFolderPathA( 0, buffer
, CSIDL_DESKTOPDIRECTORY
, FALSE
))
612 if (!strncasecmp( filename
, buffer
, strlen(buffer
) ))
614 link_name
= filename
+ strlen(buffer
);
619 if (SHGetSpecialFolderPathA( 0, buffer
, CSIDL_STARTMENU
, FALSE
))
621 if (!strncasecmp( filename
, buffer
, strlen(buffer
) ))
623 link_name
= filename
+ strlen(buffer
);
631 /* make link name a Unix name */
632 for (p
= link_name
; *p
; p
++) if (*p
== '\\') *p
= '/';
633 /* strip leading slashes */
634 while (*link_name
== '/') link_name
++;
635 /* remove extension */
636 if ((p
= strrchr( link_name
, '.' ))) *p
= 0;
638 /* convert app path name */
639 path_name
= get_unix_file_name( This
->sPath
);
641 /* convert app working dir */
642 if (This
->sWorkDir
) work_dir
= get_unix_file_name( This
->sWorkDir
);
644 /* extract the icon */
645 if (!(icon_name
= extract_icon( This
->sIcoPath
&& strlen(This
->sIcoPath
) ?
646 This
->sIcoPath
: This
->sPath
,
647 This
->iIcoNdx
))) goto done
;
650 TRACE("linker app='%s' link='%s' mode=%s path='%s' args='%s' icon='%s' workdir='%s' descr='%s'\n",
651 shell_link_app
, link_name
, bDesktop
? "desktop" : "menu", path_name
,
652 This
->sArgs
? This
->sArgs
: "", icon_name
, work_dir
? work_dir
: "",
653 This
->sDescription
? This
->sDescription
: "" );
655 if ((pid
= fork()) == -1) goto done
;
660 argv
[pos
++] = shell_link_app
;
661 argv
[pos
++] = "--link";
662 argv
[pos
++] = link_name
;
663 argv
[pos
++] = "--path";
664 argv
[pos
++] = path_name
;
665 argv
[pos
++] = bDesktop
? "--desktop" : "--menu";
666 if (This
->sArgs
&& strlen(This
->sArgs
))
668 argv
[pos
++] = "--args";
669 argv
[pos
++] = This
->sArgs
;
673 argv
[pos
++] = "--icon";
674 argv
[pos
++] = icon_name
;
676 if (This
->sWorkDir
&& strlen(This
->sWorkDir
))
678 argv
[pos
++] = "--workdir";
679 argv
[pos
++] = This
->sWorkDir
;
681 if (This
->sDescription
&& strlen(This
->sDescription
))
683 argv
[pos
++] = "--descr";
684 argv
[pos
++] = This
->sDescription
;
687 execvp( shell_link_app
, argv
);
691 while (waitpid( pid
, &status
, 0 ) == -1)
699 if (status
) ret
= E_ACCESSDENIED
;
702 if (icon_name
) unlink( icon_name
);
703 HeapFree( GetProcessHeap(), 0, shell_link_app
);
704 HeapFree( GetProcessHeap(), 0, filename
);
705 HeapFree( GetProcessHeap(), 0, icon_name
);
706 HeapFree( GetProcessHeap(), 0, path_name
);
707 HeapFree( GetProcessHeap(), 0, work_dir
);
711 static HRESULT WINAPI
IPersistFile_fnSaveCompleted(IPersistFile
* iface
, LPCOLESTR pszFileName
)
713 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
);
714 FIXME("(%p)->(%s)\n",This
,debugstr_w(pszFileName
));
717 static HRESULT WINAPI
IPersistFile_fnGetCurFile(IPersistFile
* iface
, LPOLESTR
*ppszFileName
)
719 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
);
720 FIXME("(%p)\n",This
);
724 static ICOM_VTABLE(IPersistFile
) pfvt
=
726 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
727 IPersistFile_fnQueryInterface
,
728 IPersistFile_fnAddRef
,
729 IPersistFile_fnRelease
,
730 IPersistFile_fnGetClassID
,
731 IPersistFile_fnIsDirty
,
734 IPersistFile_fnSaveCompleted
,
735 IPersistFile_fnGetCurFile
738 /************************************************************************
739 * IPersistStream_QueryInterface
741 static HRESULT WINAPI
IPersistStream_fnQueryInterface(
742 IPersistStream
* iface
,
746 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
748 TRACE("(%p)\n",This
);
750 return IShellLinkA_QueryInterface((IShellLinkA
*)This
, riid
, ppvoid
);
753 /************************************************************************
754 * IPersistStream_Release
756 static ULONG WINAPI
IPersistStream_fnRelease(
757 IPersistStream
* iface
)
759 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
761 TRACE("(%p)\n",This
);
763 return IShellLinkA_Release((IShellLinkA
*)This
);
766 /************************************************************************
767 * IPersistStream_AddRef
769 static ULONG WINAPI
IPersistStream_fnAddRef(
770 IPersistStream
* iface
)
772 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
774 TRACE("(%p)\n",This
);
776 return IShellLinkA_AddRef((IShellLinkA
*)This
);
779 /************************************************************************
780 * IPersistStream_GetClassID
783 static HRESULT WINAPI
IPersistStream_fnGetClassID(
784 IPersistStream
* iface
,
787 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
789 TRACE("(%p)\n", This
);
794 /* memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */
799 /************************************************************************
800 * IPersistStream_IsDirty (IPersistStream)
802 static HRESULT WINAPI
IPersistStream_fnIsDirty(
803 IPersistStream
* iface
)
805 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
807 TRACE("(%p)\n", This
);
811 /************************************************************************
812 * IPersistStream_Load (IPersistStream)
815 static HRESULT WINAPI
IPersistStream_fnLoad(
816 IPersistStream
* iface
,
817 IStream
* pLoadStream
)
819 PLINK_HEADER lpLinkHeader
= HeapAlloc(GetProcessHeap(), 0, LINK_HEADER_SIZE
);
822 char sTemp
[MAX_PATH
];
824 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
826 TRACE("(%p)(%p)\n", This
, pLoadStream
);
830 return STG_E_INVALIDPOINTER
;
833 IStream_AddRef (pLoadStream
);
836 if (SUCCEEDED(IStream_Read(pLoadStream
, lpLinkHeader
, LINK_HEADER_SIZE
, &dwBytesRead
)))
838 if ((lpLinkHeader
->MagicStr
== 0x0000004CL
) && IsEqualIID(&lpLinkHeader
->MagicGuid
, &CLSID_ShellLink
))
840 lpLinkHeader
= HeapReAlloc(GetProcessHeap(), 0, lpLinkHeader
, LINK_HEADER_SIZE
+lpLinkHeader
->PidlSize
);
843 if (SUCCEEDED(IStream_Read(pLoadStream
, &(lpLinkHeader
->Pidl
), lpLinkHeader
->PidlSize
, &dwBytesRead
)))
845 if (pcheck (&lpLinkHeader
->Pidl
))
847 This
->pPidl
= ILClone (&lpLinkHeader
->Pidl
);
849 SHGetPathFromIDListA(&lpLinkHeader
->Pidl
, sTemp
);
850 This
->sPath
= heap_strdup( sTemp
);
852 This
->wHotKey
= lpLinkHeader
->wHotKey
;
853 FileTimeToSystemTime (&lpLinkHeader
->Time1
, &This
->time1
);
854 FileTimeToSystemTime (&lpLinkHeader
->Time2
, &This
->time2
);
855 FileTimeToSystemTime (&lpLinkHeader
->Time3
, &This
->time3
);
857 GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&This
->time1
, NULL
, sTemp
, 256);
858 TRACE("-- time1: %s\n", sTemp
);
859 GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&This
->time2
, NULL
, sTemp
, 256);
860 TRACE("-- time1: %s\n", sTemp
);
861 GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&This
->time3
, NULL
, sTemp
, 256);
862 TRACE("-- time1: %s\n", sTemp
);
871 WARN("stream contains no link!\n");
876 IStream_Release (pLoadStream
);
880 HeapFree(GetProcessHeap(), 0, lpLinkHeader
);
885 /************************************************************************
886 * IPersistStream_Save (IPersistStream)
888 static HRESULT WINAPI
IPersistStream_fnSave(
889 IPersistStream
* iface
,
893 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
895 TRACE("(%p) %p %x\n", This
, pOutStream
, fClearDirty
);
900 /************************************************************************
901 * IPersistStream_GetSizeMax (IPersistStream)
903 static HRESULT WINAPI
IPersistStream_fnGetSizeMax(
904 IPersistStream
* iface
,
905 ULARGE_INTEGER
* pcbSize
)
907 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
909 TRACE("(%p)\n", This
);
914 static ICOM_VTABLE(IPersistStream
) psvt
=
916 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
917 IPersistStream_fnQueryInterface
,
918 IPersistStream_fnAddRef
,
919 IPersistStream_fnRelease
,
920 IPersistStream_fnGetClassID
,
921 IPersistStream_fnIsDirty
,
922 IPersistStream_fnLoad
,
923 IPersistStream_fnSave
,
924 IPersistStream_fnGetSizeMax
927 /**************************************************************************
928 * IShellLink_Constructor
930 IShellLinkA
* IShellLink_Constructor(BOOL bUnicode
)
931 { IShellLinkImpl
* sl
;
933 sl
= (IShellLinkImpl
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellLinkImpl
));
935 ICOM_VTBL(sl
) = &slvt
;
936 sl
->lpvtblw
= &slvtw
;
937 sl
->lpvtblPersistFile
= &pfvt
;
938 sl
->lpvtblPersistStream
= &psvt
;
940 TRACE("(%p)->()\n",sl
);
942 return bUnicode
? (IShellLinkA
*) &(sl
->lpvtblw
) : (IShellLinkA
*)sl
;
945 /**************************************************************************
946 * IShellLinkA_QueryInterface
948 static HRESULT WINAPI
IShellLinkA_fnQueryInterface( IShellLinkA
* iface
, REFIID riid
, LPVOID
*ppvObj
)
950 ICOM_THIS(IShellLinkImpl
, iface
);
952 TRACE("(%p)->(\n\tIID:\t%s)\n",This
,debugstr_guid(riid
));
956 if(IsEqualIID(riid
, &IID_IUnknown
) ||
957 IsEqualIID(riid
, &IID_IShellLinkA
))
961 else if(IsEqualIID(riid
, &IID_IShellLinkW
))
963 *ppvObj
= (IShellLinkW
*)&(This
->lpvtblw
);
965 else if(IsEqualIID(riid
, &IID_IPersistFile
))
967 *ppvObj
= (IPersistFile
*)&(This
->lpvtblPersistFile
);
969 else if(IsEqualIID(riid
, &IID_IPersistStream
))
971 *ppvObj
= (IPersistStream
*)&(This
->lpvtblPersistStream
);
976 IUnknown_AddRef((IUnknown
*)(*ppvObj
));
977 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
980 TRACE("-- Interface: E_NOINTERFACE\n");
981 return E_NOINTERFACE
;
983 /******************************************************************************
986 static ULONG WINAPI
IShellLinkA_fnAddRef(IShellLinkA
* iface
)
988 ICOM_THIS(IShellLinkImpl
, iface
);
990 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
993 return ++(This
->ref
);
995 /******************************************************************************
996 * IShellLinkA_Release
998 static ULONG WINAPI
IShellLinkA_fnRelease(IShellLinkA
* iface
)
1000 ICOM_THIS(IShellLinkImpl
, iface
);
1002 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1006 { TRACE("-- destroying IShellLink(%p)\n",This
);
1009 HeapFree(GetProcessHeap(), 0, This
->sIcoPath
);
1012 HeapFree(GetProcessHeap(), 0, This
->sArgs
);
1015 HeapFree(GetProcessHeap(), 0, This
->sWorkDir
);
1017 if (This
->sDescription
)
1018 HeapFree(GetProcessHeap(), 0, This
->sDescription
);
1021 HeapFree(GetProcessHeap(),0,This
->sPath
);
1024 SHFree(This
->pPidl
);
1026 if (This
->lpFileStream
)
1027 IStream_Release(This
->lpFileStream
);
1031 HeapFree(GetProcessHeap(),0,This
);
1037 static HRESULT WINAPI
IShellLinkA_fnGetPath(IShellLinkA
* iface
, LPSTR pszFile
,INT cchMaxPath
, WIN32_FIND_DATAA
*pfd
, DWORD fFlags
)
1039 ICOM_THIS(IShellLinkImpl
, iface
);
1041 TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n",This
, pszFile
, cchMaxPath
, pfd
, fFlags
, debugstr_a(This
->sPath
));
1044 lstrcpynA(pszFile
,This
->sPath
, cchMaxPath
);
1050 static HRESULT WINAPI
IShellLinkA_fnGetIDList(IShellLinkA
* iface
, LPITEMIDLIST
* ppidl
)
1052 ICOM_THIS(IShellLinkImpl
, iface
);
1054 TRACE("(%p)->(ppidl=%p)\n",This
, ppidl
);
1056 *ppidl
= ILClone(This
->pPidl
);
1059 static HRESULT WINAPI
IShellLinkA_fnSetIDList(IShellLinkA
* iface
, LPCITEMIDLIST pidl
)
1061 ICOM_THIS(IShellLinkImpl
, iface
);
1063 TRACE("(%p)->(pidl=%p)\n",This
, pidl
);
1066 SHFree(This
->pPidl
);
1067 This
->pPidl
= ILClone (pidl
);
1070 static HRESULT WINAPI
IShellLinkA_fnGetDescription(IShellLinkA
* iface
, LPSTR pszName
,INT cchMaxName
)
1072 ICOM_THIS(IShellLinkImpl
, iface
);
1074 FIXME("(%p)->(%p len=%u)\n",This
, pszName
, cchMaxName
);
1075 lstrcpynA(pszName
,"Description, FIXME",cchMaxName
);
1078 static HRESULT WINAPI
IShellLinkA_fnSetDescription(IShellLinkA
* iface
, LPCSTR pszName
)
1080 ICOM_THIS(IShellLinkImpl
, iface
);
1082 TRACE("(%p)->(pName=%s)\n", This
, pszName
);
1084 if (This
->sDescription
)
1085 HeapFree(GetProcessHeap(), 0, This
->sDescription
);
1086 if (!(This
->sDescription
= heap_strdup(pszName
)))
1087 return E_OUTOFMEMORY
;
1091 static HRESULT WINAPI
IShellLinkA_fnGetWorkingDirectory(IShellLinkA
* iface
, LPSTR pszDir
,INT cchMaxPath
)
1093 ICOM_THIS(IShellLinkImpl
, iface
);
1095 TRACE("(%p)->(%p len=%u)\n", This
, pszDir
, cchMaxPath
);
1097 lstrcpynA( pszDir
, This
->sWorkDir
? This
->sWorkDir
: "", cchMaxPath
);
1101 static HRESULT WINAPI
IShellLinkA_fnSetWorkingDirectory(IShellLinkA
* iface
, LPCSTR pszDir
)
1103 ICOM_THIS(IShellLinkImpl
, iface
);
1105 TRACE("(%p)->(dir=%s)\n",This
, pszDir
);
1108 HeapFree(GetProcessHeap(), 0, This
->sWorkDir
);
1109 if (!(This
->sWorkDir
= heap_strdup(pszDir
)))
1110 return E_OUTOFMEMORY
;
1114 static HRESULT WINAPI
IShellLinkA_fnGetArguments(IShellLinkA
* iface
, LPSTR pszArgs
,INT cchMaxPath
)
1116 ICOM_THIS(IShellLinkImpl
, iface
);
1118 TRACE("(%p)->(%p len=%u)\n", This
, pszArgs
, cchMaxPath
);
1120 lstrcpynA( pszArgs
, This
->sArgs
? This
->sArgs
: "", cchMaxPath
);
1124 static HRESULT WINAPI
IShellLinkA_fnSetArguments(IShellLinkA
* iface
, LPCSTR pszArgs
)
1126 ICOM_THIS(IShellLinkImpl
, iface
);
1128 TRACE("(%p)->(args=%s)\n",This
, pszArgs
);
1131 HeapFree(GetProcessHeap(), 0, This
->sArgs
);
1132 if (!(This
->sArgs
= heap_strdup(pszArgs
)))
1133 return E_OUTOFMEMORY
;
1137 static HRESULT WINAPI
IShellLinkA_fnGetHotkey(IShellLinkA
* iface
, WORD
*pwHotkey
)
1139 ICOM_THIS(IShellLinkImpl
, iface
);
1141 TRACE("(%p)->(%p)(0x%08x)\n",This
, pwHotkey
, This
->wHotKey
);
1143 *pwHotkey
= This
->wHotKey
;
1147 static HRESULT WINAPI
IShellLinkA_fnSetHotkey(IShellLinkA
* iface
, WORD wHotkey
)
1149 ICOM_THIS(IShellLinkImpl
, iface
);
1151 TRACE("(%p)->(hotkey=%x)\n",This
, wHotkey
);
1153 This
->wHotKey
= wHotkey
;
1157 static HRESULT WINAPI
IShellLinkA_fnGetShowCmd(IShellLinkA
* iface
, INT
*piShowCmd
)
1159 ICOM_THIS(IShellLinkImpl
, iface
);
1161 FIXME("(%p)->(%p)\n",This
, piShowCmd
);
1165 static HRESULT WINAPI
IShellLinkA_fnSetShowCmd(IShellLinkA
* iface
, INT iShowCmd
)
1167 ICOM_THIS(IShellLinkImpl
, iface
);
1169 FIXME("(%p)->(showcmd=%x)\n",This
, iShowCmd
);
1172 static HRESULT WINAPI
IShellLinkA_fnGetIconLocation(IShellLinkA
* iface
, LPSTR pszIconPath
,INT cchIconPath
,INT
*piIcon
)
1174 ICOM_THIS(IShellLinkImpl
, iface
);
1176 TRACE("(%p)->(%p len=%u iicon=%p)\n", This
, pszIconPath
, cchIconPath
, piIcon
);
1178 lstrcpynA( pszIconPath
, This
->sIcoPath
? This
->sIcoPath
: "", cchIconPath
);
1179 *piIcon
= This
->iIcoNdx
;
1183 static HRESULT WINAPI
IShellLinkA_fnSetIconLocation(IShellLinkA
* iface
, LPCSTR pszIconPath
,INT iIcon
)
1185 ICOM_THIS(IShellLinkImpl
, iface
);
1187 TRACE("(%p)->(path=%s iicon=%u)\n",This
, pszIconPath
, iIcon
);
1190 HeapFree(GetProcessHeap(), 0, This
->sIcoPath
);
1191 if (!(This
->sIcoPath
= heap_strdup(pszIconPath
)))
1192 return E_OUTOFMEMORY
;
1193 This
->iIcoNdx
= iIcon
;
1197 static HRESULT WINAPI
IShellLinkA_fnSetRelativePath(IShellLinkA
* iface
, LPCSTR pszPathRel
, DWORD dwReserved
)
1199 ICOM_THIS(IShellLinkImpl
, iface
);
1201 FIXME("(%p)->(path=%s %lx)\n",This
, pszPathRel
, dwReserved
);
1204 static HRESULT WINAPI
IShellLinkA_fnResolve(IShellLinkA
* iface
, HWND hwnd
, DWORD fFlags
)
1206 ICOM_THIS(IShellLinkImpl
, iface
);
1208 FIXME("(%p)->(hwnd=%x flags=%lx)\n",This
, hwnd
, fFlags
);
1211 static HRESULT WINAPI
IShellLinkA_fnSetPath(IShellLinkA
* iface
, LPCSTR pszFile
)
1213 ICOM_THIS(IShellLinkImpl
, iface
);
1215 TRACE("(%p)->(path=%s)\n",This
, pszFile
);
1218 HeapFree(GetProcessHeap(), 0, This
->sPath
);
1219 if (!(This
->sPath
= heap_strdup(pszFile
)))
1220 return E_OUTOFMEMORY
;
1225 /**************************************************************************
1226 * IShellLink Implementation
1229 static ICOM_VTABLE(IShellLinkA
) slvt
=
1231 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1232 IShellLinkA_fnQueryInterface
,
1233 IShellLinkA_fnAddRef
,
1234 IShellLinkA_fnRelease
,
1235 IShellLinkA_fnGetPath
,
1236 IShellLinkA_fnGetIDList
,
1237 IShellLinkA_fnSetIDList
,
1238 IShellLinkA_fnGetDescription
,
1239 IShellLinkA_fnSetDescription
,
1240 IShellLinkA_fnGetWorkingDirectory
,
1241 IShellLinkA_fnSetWorkingDirectory
,
1242 IShellLinkA_fnGetArguments
,
1243 IShellLinkA_fnSetArguments
,
1244 IShellLinkA_fnGetHotkey
,
1245 IShellLinkA_fnSetHotkey
,
1246 IShellLinkA_fnGetShowCmd
,
1247 IShellLinkA_fnSetShowCmd
,
1248 IShellLinkA_fnGetIconLocation
,
1249 IShellLinkA_fnSetIconLocation
,
1250 IShellLinkA_fnSetRelativePath
,
1251 IShellLinkA_fnResolve
,
1252 IShellLinkA_fnSetPath
1256 /**************************************************************************
1257 * IShellLinkW_fnQueryInterface
1259 static HRESULT WINAPI
IShellLinkW_fnQueryInterface(
1260 IShellLinkW
* iface
, REFIID riid
, LPVOID
*ppvObj
)
1262 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1264 return IShellLinkA_QueryInterface((IShellLinkA
*)This
, riid
, ppvObj
);
1267 /******************************************************************************
1268 * IShellLinkW_fnAddRef
1270 static ULONG WINAPI
IShellLinkW_fnAddRef(IShellLinkW
* iface
)
1272 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1274 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1276 return IShellLinkA_AddRef((IShellLinkA
*)This
);
1278 /******************************************************************************
1279 * IShellLinkW_fnRelease
1282 static ULONG WINAPI
IShellLinkW_fnRelease(IShellLinkW
* iface
)
1284 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1286 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1288 return IShellLinkA_Release((IShellLinkA
*)This
);
1291 static HRESULT WINAPI
IShellLinkW_fnGetPath(IShellLinkW
* iface
, LPWSTR pszFile
,INT cchMaxPath
, WIN32_FIND_DATAA
*pfd
, DWORD fFlags
)
1293 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1295 FIXME("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This
, pszFile
, cchMaxPath
, pfd
, fFlags
);
1296 MultiByteToWideChar( CP_ACP
, 0, "c:\\foo.bar", -1, pszFile
, cchMaxPath
);
1300 static HRESULT WINAPI
IShellLinkW_fnGetIDList(IShellLinkW
* iface
, LPITEMIDLIST
* ppidl
)
1302 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1304 FIXME("(%p)->(ppidl=%p)\n",This
, ppidl
);
1305 *ppidl
= _ILCreateDesktop();
1309 static HRESULT WINAPI
IShellLinkW_fnSetIDList(IShellLinkW
* iface
, LPCITEMIDLIST pidl
)
1311 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1313 FIXME("(%p)->(pidl=%p)\n",This
, pidl
);
1317 static HRESULT WINAPI
IShellLinkW_fnGetDescription(IShellLinkW
* iface
, LPWSTR pszName
,INT cchMaxName
)
1319 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1321 FIXME("(%p)->(%p len=%u)\n",This
, pszName
, cchMaxName
);
1322 MultiByteToWideChar( CP_ACP
, 0, "Description, FIXME", -1, pszName
, cchMaxName
);
1326 static HRESULT WINAPI
IShellLinkW_fnSetDescription(IShellLinkW
* iface
, LPCWSTR pszName
)
1328 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1330 TRACE("(%p)->(desc=%s)\n",This
, debugstr_w(pszName
));
1332 if (This
->sDescription
)
1333 HeapFree(GetProcessHeap(), 0, This
->sDescription
);
1334 if (!(This
->sDescription
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszName
)))
1335 return E_OUTOFMEMORY
;
1340 static HRESULT WINAPI
IShellLinkW_fnGetWorkingDirectory(IShellLinkW
* iface
, LPWSTR pszDir
,INT cchMaxPath
)
1342 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1344 TRACE("(%p)->(%p len %u)\n", This
, pszDir
, cchMaxPath
);
1346 MultiByteToWideChar( CP_ACP
, 0, This
->sWorkDir
? This
->sWorkDir
: "", -1, pszDir
, cchMaxPath
);
1351 static HRESULT WINAPI
IShellLinkW_fnSetWorkingDirectory(IShellLinkW
* iface
, LPCWSTR pszDir
)
1353 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1355 TRACE("(%p)->(dir=%s)\n",This
, debugstr_w(pszDir
));
1358 HeapFree(GetProcessHeap(), 0, This
->sWorkDir
);
1359 if (!(This
->sWorkDir
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszDir
)))
1360 return E_OUTOFMEMORY
;
1365 static HRESULT WINAPI
IShellLinkW_fnGetArguments(IShellLinkW
* iface
, LPWSTR pszArgs
,INT cchMaxPath
)
1367 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1369 TRACE("(%p)->(%p len=%u)\n", This
, pszArgs
, cchMaxPath
);
1371 MultiByteToWideChar( CP_ACP
, 0, This
->sArgs
? This
->sArgs
: "", -1, pszArgs
, cchMaxPath
);
1376 static HRESULT WINAPI
IShellLinkW_fnSetArguments(IShellLinkW
* iface
, LPCWSTR pszArgs
)
1378 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1380 TRACE("(%p)->(args=%s)\n",This
, debugstr_w(pszArgs
));
1383 HeapFree(GetProcessHeap(), 0, This
->sArgs
);
1384 if (!(This
->sArgs
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszArgs
)))
1385 return E_OUTOFMEMORY
;
1390 static HRESULT WINAPI
IShellLinkW_fnGetHotkey(IShellLinkW
* iface
, WORD
*pwHotkey
)
1392 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1394 FIXME("(%p)->(%p)\n",This
, pwHotkey
);
1399 static HRESULT WINAPI
IShellLinkW_fnSetHotkey(IShellLinkW
* iface
, WORD wHotkey
)
1401 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1403 FIXME("(%p)->(hotkey=%x)\n",This
, wHotkey
);
1407 static HRESULT WINAPI
IShellLinkW_fnGetShowCmd(IShellLinkW
* iface
, INT
*piShowCmd
)
1409 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1411 FIXME("(%p)->(%p)\n",This
, piShowCmd
);
1416 static HRESULT WINAPI
IShellLinkW_fnSetShowCmd(IShellLinkW
* iface
, INT iShowCmd
)
1418 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1420 FIXME("(%p)->(showcmd=%x)\n",This
, iShowCmd
);
1424 static HRESULT WINAPI
IShellLinkW_fnGetIconLocation(IShellLinkW
* iface
, LPWSTR pszIconPath
,INT cchIconPath
,INT
*piIcon
)
1426 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1428 TRACE("(%p)->(%p len=%u iicon=%p)\n", This
, pszIconPath
, cchIconPath
, piIcon
);
1430 MultiByteToWideChar( CP_ACP
, 0, This
->sIcoPath
? This
->sIcoPath
: "", -1, pszIconPath
, cchIconPath
);
1431 *piIcon
= This
->iIcoNdx
;
1436 static HRESULT WINAPI
IShellLinkW_fnSetIconLocation(IShellLinkW
* iface
, LPCWSTR pszIconPath
,INT iIcon
)
1438 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1440 TRACE("(%p)->(path=%s iicon=%u)\n",This
, debugstr_w(pszIconPath
), iIcon
);
1443 HeapFree(GetProcessHeap(), 0, This
->sIcoPath
);
1444 if (!(This
->sIcoPath
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszIconPath
)))
1445 return E_OUTOFMEMORY
;
1446 This
->iIcoNdx
= iIcon
;
1451 static HRESULT WINAPI
IShellLinkW_fnSetRelativePath(IShellLinkW
* iface
, LPCWSTR pszPathRel
, DWORD dwReserved
)
1453 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1455 FIXME("(%p)->(path=%s %lx)\n",This
, debugstr_w(pszPathRel
), dwReserved
);
1459 static HRESULT WINAPI
IShellLinkW_fnResolve(IShellLinkW
* iface
, HWND hwnd
, DWORD fFlags
)
1461 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1463 FIXME("(%p)->(hwnd=%x flags=%lx)\n",This
, hwnd
, fFlags
);
1467 static HRESULT WINAPI
IShellLinkW_fnSetPath(IShellLinkW
* iface
, LPCWSTR pszFile
)
1469 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1471 TRACE("(%p)->(path=%s)\n",This
, debugstr_w(pszFile
));
1474 HeapFree(GetProcessHeap(), 0, This
->sPath
);
1475 if (!(This
->sPath
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszFile
)))
1476 return E_OUTOFMEMORY
;
1481 /**************************************************************************
1482 * IShellLinkW Implementation
1485 static ICOM_VTABLE(IShellLinkW
) slvtw
=
1487 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1488 IShellLinkW_fnQueryInterface
,
1489 IShellLinkW_fnAddRef
,
1490 IShellLinkW_fnRelease
,
1491 IShellLinkW_fnGetPath
,
1492 IShellLinkW_fnGetIDList
,
1493 IShellLinkW_fnSetIDList
,
1494 IShellLinkW_fnGetDescription
,
1495 IShellLinkW_fnSetDescription
,
1496 IShellLinkW_fnGetWorkingDirectory
,
1497 IShellLinkW_fnSetWorkingDirectory
,
1498 IShellLinkW_fnGetArguments
,
1499 IShellLinkW_fnSetArguments
,
1500 IShellLinkW_fnGetHotkey
,
1501 IShellLinkW_fnSetHotkey
,
1502 IShellLinkW_fnGetShowCmd
,
1503 IShellLinkW_fnSetShowCmd
,
1504 IShellLinkW_fnGetIconLocation
,
1505 IShellLinkW_fnSetIconLocation
,
1506 IShellLinkW_fnSetRelativePath
,
1507 IShellLinkW_fnResolve
,
1508 IShellLinkW_fnSetPath