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
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
32 #include "wine/debug.h"
33 #include "wine/port.h"
40 #include "undocshell.h"
41 #include "bitmaps/wine.xpm"
45 #include "shell32_main.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
50 /* link file formats */
54 /* flag1: lnk elements: simple link has 0x0B */
62 #define MAXIMIZED 0x03
63 #define MINIMIZED 0x07
65 typedef struct _LINK_HEADER
66 { DWORD MagicStr
; /* 0x00 'L','\0','\0','\0' */
67 GUID MagicGuid
; /* 0x04 is CLSID_ShellLink */
68 DWORD Flag1
; /* 0x14 describes elements following */
69 DWORD Flag2
; /* 0x18 */
70 FILETIME Time1
; /* 0x1c */
71 FILETIME Time2
; /* 0x24 */
72 FILETIME Time3
; /* 0x2c */
73 DWORD Unknown1
; /* 0x34 */
74 DWORD Unknown2
; /* 0x38 icon number */
75 DWORD fStartup
; /* 0x3c startup type */
76 DWORD wHotKey
; /* 0x40 hotkey */
77 DWORD Unknown5
; /* 0x44 */
78 DWORD Unknown6
; /* 0x48 */
79 USHORT PidlSize
; /* 0x4c */
80 ITEMIDLIST Pidl
; /* 0x4e */
81 } LINK_HEADER
, * PLINK_HEADER
;
83 #define LINK_HEADER_SIZE (sizeof(LINK_HEADER)-sizeof(ITEMIDLIST))
102 GRPICONDIRENTRY idEntries
[1];
133 static ICOM_VTABLE(IShellLinkA
) slvt
;
134 static ICOM_VTABLE(IShellLinkW
) slvtw
;
135 static ICOM_VTABLE(IPersistFile
) pfvt
;
136 static ICOM_VTABLE(IPersistStream
) psvt
;
138 /* IShellLink Implementation */
142 ICOM_VFIELD(IShellLinkA
);
145 ICOM_VTABLE(IShellLinkW
)* lpvtblw
;
146 ICOM_VTABLE(IPersistFile
)* lpvtblPersistFile
;
147 ICOM_VTABLE(IPersistStream
)* lpvtblPersistStream
;
149 /* internal stream of the IPersistFile interface */
150 IStream
* lpFileStream
;
152 /* data structures according to the informations in the lnk */
167 #define _IShellLinkW_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblw)))
168 #define _ICOM_THIS_From_IShellLinkW(class, name) class* This = (class*)(((char*)name)-_IShellLinkW_Offset);
170 #define _IPersistFile_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistFile)))
171 #define _ICOM_THIS_From_IPersistFile(class, name) class* This = (class*)(((char*)name)-_IPersistFile_Offset);
173 #define _IPersistStream_Offset ((int)(&(((IShellLinkImpl*)0)->lpvtblPersistStream)))
174 #define _ICOM_THIS_From_IPersistStream(class, name) class* This = (class*)(((char*)name)-_IPersistStream_Offset);
175 #define _IPersistStream_From_ICOM_THIS(class, name) class* StreamThis = (class*)(((char*)name)+_IPersistStream_Offset);
178 /* strdup on the process heap */
179 inline static LPSTR
heap_strdup( LPCSTR str
)
181 INT len
= strlen(str
) + 1;
182 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, len
);
183 if (p
) memcpy( p
, str
, len
);
188 /**************************************************************************
189 * IPersistFile_QueryInterface
191 static HRESULT WINAPI
IPersistFile_fnQueryInterface(
196 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
198 TRACE("(%p)\n",This
);
200 return IShellLinkA_QueryInterface((IShellLinkA
*)This
, riid
, ppvObj
);
203 /******************************************************************************
204 * IPersistFile_AddRef
206 static ULONG WINAPI
IPersistFile_fnAddRef(IPersistFile
* iface
)
208 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
210 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
212 return IShellLinkA_AddRef((IShellLinkA
*)This
);
214 /******************************************************************************
215 * IPersistFile_Release
217 static ULONG WINAPI
IPersistFile_fnRelease(IPersistFile
* iface
)
219 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
221 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
223 return IShellLinkA_Release((IShellLinkA
*)This
);
226 static HRESULT WINAPI
IPersistFile_fnGetClassID(IPersistFile
* iface
, CLSID
*pClassID
)
228 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
229 FIXME("(%p)\n",This
);
232 static HRESULT WINAPI
IPersistFile_fnIsDirty(IPersistFile
* iface
)
234 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
235 FIXME("(%p)\n",This
);
238 static HRESULT WINAPI
IPersistFile_fnLoad(IPersistFile
* iface
, LPCOLESTR pszFileName
, DWORD dwMode
)
240 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
)
241 _IPersistStream_From_ICOM_THIS(IPersistStream
, This
)
243 LPSTR sFile
= HEAP_strdupWtoA ( GetProcessHeap(), 0, pszFileName
);
244 HRESULT hRet
= E_FAIL
;
246 TRACE("(%p, %s)\n",This
, sFile
);
249 if (This
->lpFileStream
)
250 IStream_Release(This
->lpFileStream
);
252 if SUCCEEDED(CreateStreamOnFile(sFile
, &(This
->lpFileStream
)))
254 if SUCCEEDED (IPersistStream_Load(StreamThis
, This
->lpFileStream
))
264 /* Icon extraction routines
266 * FIXME: should use PrivateExtractIcons and friends
267 * FIXME: should not use stdio
270 static BOOL
SaveIconResAsXPM(const BITMAPINFO
*pIcon
, const char *szXPMFileName
)
280 BOOL aColorUsed
[256] = {0};
284 if (!((pIcon
->bmiHeader
.biBitCount
== 4) || (pIcon
->bmiHeader
.biBitCount
== 8)))
287 if (!(fXPMFile
= fopen(szXPMFileName
, "w")))
290 nHeight
= pIcon
->bmiHeader
.biHeight
/ 2;
291 nXORWidthBytes
= 4 * ((pIcon
->bmiHeader
.biWidth
* pIcon
->bmiHeader
.biBitCount
/ 32)
292 + ((pIcon
->bmiHeader
.biWidth
* pIcon
->bmiHeader
.biBitCount
% 32) > 0));
293 nANDWidthBytes
= 4 * ((pIcon
->bmiHeader
.biWidth
/ 32)
294 + ((pIcon
->bmiHeader
.biWidth
% 32) > 0));
295 b8BitColors
= pIcon
->bmiHeader
.biBitCount
== 8;
296 nColors
= pIcon
->bmiHeader
.biClrUsed
? pIcon
->bmiHeader
.biClrUsed
297 : 1 << pIcon
->bmiHeader
.biBitCount
;
298 pXOR
= (BYTE
*) pIcon
+ sizeof (BITMAPINFOHEADER
) + (nColors
* sizeof (RGBQUAD
));
299 pAND
= pXOR
+ nHeight
* nXORWidthBytes
;
301 #define MASK(x,y) (pAND[(x) / 8 + (nHeight - (y) - 1) * nANDWidthBytes] & (1 << (7 - (x) % 8)))
302 #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)
304 for (i
= 0; i
< nHeight
; i
++)
305 for (j
= 0; j
< pIcon
->bmiHeader
.biWidth
; j
++)
306 if (!aColorUsed
[COLOR(j
,i
)] && !MASK(j
,i
))
308 aColorUsed
[COLOR(j
,i
)] = TRUE
;
312 if (fprintf(fXPMFile
, "/* XPM */\nstatic char *icon[] = {\n") <= 0)
314 if (fprintf(fXPMFile
, "\"%d %d %d %d\",\n",
315 (int) pIcon
->bmiHeader
.biWidth
, nHeight
, nColorsUsed
+ 1, 2) <=0)
318 for (i
= 0; i
< nColors
; i
++)
320 if (fprintf(fXPMFile
, "\"%.2X c #%.2X%.2X%.2X\",\n", i
, pIcon
->bmiColors
[i
].rgbRed
,
321 pIcon
->bmiColors
[i
].rgbGreen
, pIcon
->bmiColors
[i
].rgbBlue
) <= 0)
323 if (fprintf(fXPMFile
, "\" c None\"") <= 0)
326 for (i
= 0; i
< nHeight
; i
++)
328 if (fprintf(fXPMFile
, ",\n\"") <= 0)
330 for (j
= 0; j
< pIcon
->bmiHeader
.biWidth
; j
++)
334 if (fprintf(fXPMFile
, " ") <= 0)
338 if (fprintf(fXPMFile
, "%.2X", COLOR(j
,i
)) <= 0)
341 if (fprintf(fXPMFile
, "\"") <= 0)
344 if (fprintf(fXPMFile
, "};\n") <= 0)
355 unlink( szXPMFileName
);
359 static BOOL CALLBACK
EnumResNameProc(HANDLE hModule
, const char *lpszType
, char *lpszName
, LONG lParam
)
361 ENUMRESSTRUCT
*sEnumRes
= (ENUMRESSTRUCT
*) lParam
;
363 if (!sEnumRes
->nIndex
--)
365 *sEnumRes
->pResInfo
= FindResourceA(hModule
, lpszName
, RT_GROUP_ICONA
);
372 static int ExtractFromEXEDLL(const char *szFileName
, int nIndex
, const char *szXPMFileName
)
378 GRPICONDIR
*pIconDir
;
380 ENUMRESSTRUCT sEnumRes
;
385 if (!(hModule
= LoadLibraryExA(szFileName
, 0, LOAD_LIBRARY_AS_DATAFILE
)))
387 TRACE("LoadLibraryExA (%s) failed, error %ld\n", szFileName
, GetLastError());
393 hResInfo
= FindResourceA(hModule
, MAKEINTRESOURCEA(-nIndex
), RT_GROUP_ICONA
);
394 TRACE("FindResourceA (%s) called, return %p, error %ld\n", szFileName
, hResInfo
, GetLastError());
398 sEnumRes
.pResInfo
= &hResInfo
;
399 sEnumRes
.nIndex
= nIndex
;
400 if (EnumResourceNamesA(hModule
, RT_GROUP_ICONA
,
401 (ENUMRESNAMEPROCA
)&EnumResNameProc
,
404 TRACE("EnumResourceNamesA failed, error %ld\n", GetLastError());
411 TRACE("ExtractFromEXEDLL failed, error %ld\n", GetLastError());
415 if (!(hResData
= LoadResource(hModule
, hResInfo
)))
417 TRACE("LoadResource failed, error %ld\n", GetLastError());
420 if (!(pIconDir
= LockResource(hResData
)))
422 TRACE("LockResource failed, error %ld\n", GetLastError());
426 for (i
= 0; i
< pIconDir
->idCount
; i
++)
427 if ((pIconDir
->idEntries
[i
].wBitCount
>= nMaxBits
) && (pIconDir
->idEntries
[i
].wBitCount
<= 8))
429 if (pIconDir
->idEntries
[i
].wBitCount
> nMaxBits
)
431 nMaxBits
= pIconDir
->idEntries
[i
].wBitCount
;
434 if ((pIconDir
->idEntries
[i
].bHeight
* pIconDir
->idEntries
[i
].bWidth
) > nMax
)
436 lpName
= MAKEINTRESOURCEA(pIconDir
->idEntries
[i
].nID
);
437 nMax
= pIconDir
->idEntries
[i
].bHeight
* pIconDir
->idEntries
[i
].bWidth
;
441 FreeResource(hResData
);
443 if (!(hResInfo
= FindResourceA(hModule
, lpName
, RT_ICONA
)))
445 TRACE("Second FindResourceA failed, error %ld\n", GetLastError());
448 if (!(hResData
= LoadResource(hModule
, hResInfo
)))
450 TRACE("Second LoadResource failed, error %ld\n", GetLastError());
453 if (!(pIcon
= LockResource(hResData
)))
455 TRACE("Second LockResource failed, error %ld\n", GetLastError());
459 if(!SaveIconResAsXPM(pIcon
, szXPMFileName
))
461 TRACE("Failed saving icon as XPM, error %ld\n", GetLastError());
465 FreeResource(hResData
);
466 FreeLibrary(hModule
);
471 FreeResource(hResData
);
473 FreeLibrary(hModule
);
478 /* get the Unix file name for a given path, allocating the string */
479 inline static char *get_unix_file_name( const char *dos
)
481 char buffer
[MAX_PATH
];
483 if (!wine_get_unix_file_name( dos
, buffer
, sizeof(buffer
) )) return NULL
;
484 return heap_strdup( buffer
);
487 static int ExtractFromICO(const char *szFileName
, const char *szXPMFileName
)
491 ICONDIRENTRY
*pIconDirEntry
;
498 filename
= get_unix_file_name(szFileName
);
499 if (!(fICOFile
= fopen(filename
, "r")))
502 if (fread(&iconDir
, sizeof (ICONDIR
), 1, fICOFile
) != 1)
504 if ((iconDir
.idReserved
!= 0) || (iconDir
.idType
!= 1))
507 if ((pIconDirEntry
= malloc(iconDir
.idCount
* sizeof (ICONDIRENTRY
))) == NULL
)
509 if (fread(pIconDirEntry
, sizeof (ICONDIRENTRY
), iconDir
.idCount
, fICOFile
) != iconDir
.idCount
)
512 for (i
= 0; i
< iconDir
.idCount
; i
++)
513 if ((pIconDirEntry
[i
].bHeight
* pIconDirEntry
[i
].bWidth
) > nMax
)
516 nMax
= pIconDirEntry
[i
].bHeight
* pIconDirEntry
[i
].bWidth
;
518 if ((pIcon
= malloc(pIconDirEntry
[nIndex
].dwBytesInRes
)) == NULL
)
520 if (fseek(fICOFile
, pIconDirEntry
[nIndex
].dwImageOffset
, SEEK_SET
))
522 if (fread(pIcon
, pIconDirEntry
[nIndex
].dwBytesInRes
, 1, fICOFile
) != 1)
525 if(!SaveIconResAsXPM(pIcon
, szXPMFileName
))
541 HeapFree(GetProcessHeap(), 0, filename
);
545 static BOOL
create_default_icon( const char *filename
)
550 if (!(fXPM
= fopen(filename
, "w"))) return FALSE
;
551 fprintf(fXPM
, "/* XPM */\nstatic char * icon[] = {");
552 for (i
= 0; i
< sizeof(wine_xpm
)/sizeof(wine_xpm
[0]); i
++)
553 fprintf( fXPM
, "\n\"%s\",", wine_xpm
[i
]);
554 fprintf( fXPM
, "};\n" );
559 /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
560 static char *extract_icon( const char *path
, int index
)
562 int fd
, nodefault
= 1;
563 char *filename
, tmpfn
[25];
565 strcpy(tmpfn
,"/tmp/icon.XXXXXX.xpm");
566 fd
= mkstemps( tmpfn
, 4 );
569 filename
= heap_strdup( tmpfn
);
570 close(fd
); /* not needed */
572 /* If icon path begins with a '*' then this is a deferred call */
578 if (ExtractFromEXEDLL( path
, index
, filename
)) return filename
;
579 if (ExtractFromICO( path
, filename
)) return filename
;
581 if (create_default_icon( filename
)) return filename
;
582 HeapFree( GetProcessHeap(), 0, filename
);
586 /* This escapes \ in filenames */
591 narg
= HeapAlloc(GetProcessHeap(),0,2*strlen(arg
)+2);
596 *x
++='\\'; /* escape \ */
603 static HRESULT WINAPI
IPersistFile_fnSave(IPersistFile
* iface
, LPCOLESTR pszFileName
, BOOL fRemember
)
605 HRESULT ret
= NOERROR
;
607 char buffer
[MAX_PATH
], buff2
[MAX_PATH
], ascii_filename
[MAX_PATH
];
608 char *filename
, *link_name
, *p
;
609 char *shell_link_app
= NULL
;
610 char *icon_name
= NULL
;
611 char *work_dir
= NULL
;
612 char *escaped_path
= NULL
;
613 char *escaped_args
= NULL
;
617 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
);
619 TRACE("(%p)->(%s)\n",This
,debugstr_w(pszFileName
));
621 if (!pszFileName
|| !This
->sPath
)
622 return ERROR_UNKNOWN
;
624 /* check for .exe extension */
625 if (!(p
= strrchr( This
->sPath
, '.' ))) return NOERROR
;
626 if (strchr( p
, '\\' ) || strchr( p
, '/' )) return NOERROR
;
627 if (strcasecmp( p
, ".exe" )) return NOERROR
;
629 /* check if ShellLinker configured */
631 if (!RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "Software\\Wine\\Wine\\Config\\Wine",
632 0, KEY_ALL_ACCESS
, &hkey
))
634 DWORD type
, count
= sizeof(buffer
);
635 if (RegQueryValueExA( hkey
, "ShellLinker", 0, &type
, buffer
, &count
)) buffer
[0] = 0;
638 if (!*buffer
) return NOERROR
;
639 shell_link_app
= heap_strdup( buffer
);
641 if (!WideCharToMultiByte( CP_ACP
, 0, pszFileName
, -1, ascii_filename
, sizeof(ascii_filename
), NULL
, NULL
))
642 return ERROR_UNKNOWN
;
643 GetFullPathNameA( ascii_filename
, sizeof(buff2
), buff2
, NULL
);
644 filename
= heap_strdup( buff2
);
646 if (SHGetSpecialFolderPathA( 0, buffer
, CSIDL_STARTUP
, FALSE
))
648 /* ignore startup for now */
649 if (!strncasecmp( filename
, buffer
, strlen(buffer
) )) goto done
;
651 if (SHGetSpecialFolderPathA( 0, buffer
, CSIDL_DESKTOPDIRECTORY
, FALSE
))
653 if (!strncasecmp( filename
, buffer
, strlen(buffer
) ))
655 link_name
= filename
+ strlen(buffer
);
660 if (SHGetSpecialFolderPathA( 0, buffer
, CSIDL_STARTMENU
, FALSE
))
662 if (!strncasecmp( filename
, buffer
, strlen(buffer
) ))
664 link_name
= filename
+ strlen(buffer
);
672 /* make link name a Unix name */
673 for (p
= link_name
; *p
; p
++) if (*p
== '\\') *p
= '/';
674 /* strip leading slashes */
675 while (*link_name
== '/') link_name
++;
676 /* remove extension */
677 if ((p
= strrchr( link_name
, '.' ))) *p
= 0;
679 /* convert app working dir */
680 if (This
->sWorkDir
) work_dir
= get_unix_file_name( This
->sWorkDir
);
682 /* extract the icon */
683 if (!(icon_name
= extract_icon( This
->sIcoPath
&& strlen(This
->sIcoPath
) ?
684 This
->sIcoPath
: This
->sPath
,
687 /* Couldn't extract icon -- defer this menu entry to runonce. */
691 TRACE("Deferring icon creation to reboot.\n");
692 if (RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce", 0,
693 NULL
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hRunOnce
, NULL
) != ERROR_SUCCESS
)
698 buffer
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* 3 + (This
->sArgs
? strlen(This
->sArgs
) : 0) +
699 (This
->sDescription
? strlen(This
->sDescription
) : 0) + 200);
700 sprintf(buffer
, "link:%s\xff*%s\xff%d\xff%s\xff%s\xff%s", This
->sPath
, This
->sIcoPath
, This
->iIcoNdx
,
701 This
->sArgs
? This
->sArgs
: "", This
->sDescription
? This
->sDescription
: "",
702 This
->sWorkDir
? This
->sWorkDir
: "");
703 if (RegSetValueExA(hRunOnce
, ascii_filename
, 0, REG_SZ
, buffer
, strlen(buffer
) + 1) != ERROR_SUCCESS
)
705 HeapFree(GetProcessHeap(), 0, buffer
);
706 RegCloseKey(hRunOnce
);
710 HeapFree(GetProcessHeap(), 0, buffer
);
711 RegCloseKey(hRunOnce
);
715 TRACE("linker app='%s' link='%s' mode=%s path='%s' args='%s' icon='%s' workdir='%s' descr='%s'\n",
716 shell_link_app
, link_name
, bDesktop
? "desktop" : "menu", This
->sPath
,
717 This
->sArgs
? This
->sArgs
: "", icon_name
, work_dir
? work_dir
: "",
718 This
->sDescription
? This
->sDescription
: "" );
720 if ((pid
= fork()) == -1) goto done
;
722 escaped_path
= escape(This
->sPath
);
724 escaped_args
= escape(This
->sArgs
);
730 argv
[pos
++] = shell_link_app
;
731 argv
[pos
++] = "--link";
732 argv
[pos
++] = link_name
;
733 argv
[pos
++] = "--path";
734 argv
[pos
++] = escaped_path
;
735 argv
[pos
++] = bDesktop
? "--desktop" : "--menu";
736 if (This
->sArgs
&& strlen(This
->sArgs
))
738 argv
[pos
++] = "--args";
739 argv
[pos
++] = escaped_args
;
743 argv
[pos
++] = "--icon";
744 argv
[pos
++] = icon_name
;
746 if (This
->sWorkDir
&& strlen(This
->sWorkDir
))
748 argv
[pos
++] = "--workdir";
749 argv
[pos
++] = work_dir
;
751 if (This
->sDescription
&& strlen(This
->sDescription
))
753 argv
[pos
++] = "--descr";
754 argv
[pos
++] = This
->sDescription
;
757 execvp( shell_link_app
, argv
);
761 while (waitpid( pid
, &status
, 0 ) == -1)
769 if (status
) ret
= E_ACCESSDENIED
;
772 if (icon_name
) unlink( icon_name
);
773 HeapFree( GetProcessHeap(), 0, shell_link_app
);
774 HeapFree( GetProcessHeap(), 0, filename
);
775 HeapFree( GetProcessHeap(), 0, icon_name
);
776 HeapFree( GetProcessHeap(), 0, work_dir
);
777 if (escaped_args
) HeapFree( GetProcessHeap(), 0, escaped_args
);
778 if (escaped_path
) HeapFree( GetProcessHeap(), 0, escaped_path
);
782 static HRESULT WINAPI
IPersistFile_fnSaveCompleted(IPersistFile
* iface
, LPCOLESTR pszFileName
)
784 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
);
785 FIXME("(%p)->(%s)\n",This
,debugstr_w(pszFileName
));
788 static HRESULT WINAPI
IPersistFile_fnGetCurFile(IPersistFile
* iface
, LPOLESTR
*ppszFileName
)
790 _ICOM_THIS_From_IPersistFile(IShellLinkImpl
, iface
);
791 FIXME("(%p)\n",This
);
795 static ICOM_VTABLE(IPersistFile
) pfvt
=
797 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
798 IPersistFile_fnQueryInterface
,
799 IPersistFile_fnAddRef
,
800 IPersistFile_fnRelease
,
801 IPersistFile_fnGetClassID
,
802 IPersistFile_fnIsDirty
,
805 IPersistFile_fnSaveCompleted
,
806 IPersistFile_fnGetCurFile
809 /************************************************************************
810 * IPersistStream_QueryInterface
812 static HRESULT WINAPI
IPersistStream_fnQueryInterface(
813 IPersistStream
* iface
,
817 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
819 TRACE("(%p)\n",This
);
821 return IShellLinkA_QueryInterface((IShellLinkA
*)This
, riid
, ppvoid
);
824 /************************************************************************
825 * IPersistStream_Release
827 static ULONG WINAPI
IPersistStream_fnRelease(
828 IPersistStream
* iface
)
830 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
832 TRACE("(%p)\n",This
);
834 return IShellLinkA_Release((IShellLinkA
*)This
);
837 /************************************************************************
838 * IPersistStream_AddRef
840 static ULONG WINAPI
IPersistStream_fnAddRef(
841 IPersistStream
* iface
)
843 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
845 TRACE("(%p)\n",This
);
847 return IShellLinkA_AddRef((IShellLinkA
*)This
);
850 /************************************************************************
851 * IPersistStream_GetClassID
854 static HRESULT WINAPI
IPersistStream_fnGetClassID(
855 IPersistStream
* iface
,
858 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
860 TRACE("(%p)\n", This
);
865 /* memcpy(pClassID, &CLSID_???, sizeof(CLSID_???)); */
870 /************************************************************************
871 * IPersistStream_IsDirty (IPersistStream)
873 static HRESULT WINAPI
IPersistStream_fnIsDirty(
874 IPersistStream
* iface
)
876 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
878 TRACE("(%p)\n", This
);
882 /************************************************************************
883 * IPersistStream_Load (IPersistStream)
886 static HRESULT WINAPI
IPersistStream_fnLoad(
887 IPersistStream
* iface
,
888 IStream
* pLoadStream
)
890 PLINK_HEADER lpLinkHeader
= HeapAlloc(GetProcessHeap(), 0, LINK_HEADER_SIZE
);
893 char sTemp
[MAX_PATH
];
895 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
897 TRACE("(%p)(%p)\n", This
, pLoadStream
);
901 return STG_E_INVALIDPOINTER
;
904 IStream_AddRef (pLoadStream
);
909 if (!(SUCCEEDED(IStream_Read(pLoadStream
, lpLinkHeader
, LINK_HEADER_SIZE
, &dwBytesRead
))))
912 if (dwBytesRead
!= LINK_HEADER_SIZE
)
915 if ( (lpLinkHeader
->MagicStr
!= 0x0000004CL
) || !IsEqualIID(&lpLinkHeader
->MagicGuid
, &CLSID_ShellLink
) )
918 if(lpLinkHeader
->PidlSize
)
920 lpLinkHeader
= HeapReAlloc(GetProcessHeap(), 0, lpLinkHeader
, LINK_HEADER_SIZE
+lpLinkHeader
->PidlSize
);
924 if (!(SUCCEEDED(IStream_Read(pLoadStream
, &(lpLinkHeader
->Pidl
), lpLinkHeader
->PidlSize
, &dwBytesRead
))))
926 if(dwBytesRead
!= lpLinkHeader
->PidlSize
)
929 if (pcheck (&lpLinkHeader
->Pidl
))
931 This
->pPidl
= ILClone (&lpLinkHeader
->Pidl
);
933 SHGetPathFromIDListA(&lpLinkHeader
->Pidl
, sTemp
);
934 This
->sPath
= heap_strdup( sTemp
);
937 This
->wHotKey
= lpLinkHeader
->wHotKey
;
938 FileTimeToSystemTime (&lpLinkHeader
->Time1
, &This
->time1
);
939 FileTimeToSystemTime (&lpLinkHeader
->Time2
, &This
->time2
);
940 FileTimeToSystemTime (&lpLinkHeader
->Time3
, &This
->time3
);
942 GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&This
->time1
, NULL
, sTemp
, 256);
943 TRACE("-- time1: %s\n", sTemp
);
944 GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&This
->time2
, NULL
, sTemp
, 256);
945 TRACE("-- time1: %s\n", sTemp
);
946 GetDateFormatA(LOCALE_USER_DEFAULT
,DATE_SHORTDATE
,&This
->time3
, NULL
, sTemp
, 256);
947 TRACE("-- time1: %s\n", sTemp
);
953 IStream_Release (pLoadStream
);
957 HeapFree(GetProcessHeap(), 0, lpLinkHeader
);
962 /************************************************************************
963 * IPersistStream_Save (IPersistStream)
965 static HRESULT WINAPI
IPersistStream_fnSave(
966 IPersistStream
* iface
,
970 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
972 TRACE("(%p) %p %x\n", This
, pOutStream
, fClearDirty
);
977 /************************************************************************
978 * IPersistStream_GetSizeMax (IPersistStream)
980 static HRESULT WINAPI
IPersistStream_fnGetSizeMax(
981 IPersistStream
* iface
,
982 ULARGE_INTEGER
* pcbSize
)
984 _ICOM_THIS_From_IPersistStream(IShellLinkImpl
, iface
);
986 TRACE("(%p)\n", This
);
991 static ICOM_VTABLE(IPersistStream
) psvt
=
993 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
994 IPersistStream_fnQueryInterface
,
995 IPersistStream_fnAddRef
,
996 IPersistStream_fnRelease
,
997 IPersistStream_fnGetClassID
,
998 IPersistStream_fnIsDirty
,
999 IPersistStream_fnLoad
,
1000 IPersistStream_fnSave
,
1001 IPersistStream_fnGetSizeMax
1004 /**************************************************************************
1005 * IShellLink_Constructor
1007 HRESULT WINAPI
IShellLink_Constructor (
1008 IUnknown
* pUnkOuter
,
1012 IShellLinkImpl
* sl
;
1014 TRACE("unkOut=%p riid=%s\n",pUnkOuter
, debugstr_guid(riid
));
1018 if(pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1019 sl
= (IShellLinkImpl
*) LocalAlloc(GMEM_ZEROINIT
,sizeof(IShellLinkImpl
));
1020 if (!sl
) return E_OUTOFMEMORY
;
1023 ICOM_VTBL(sl
) = &slvt
;
1024 sl
->lpvtblw
= &slvtw
;
1025 sl
->lpvtblPersistFile
= &pfvt
;
1026 sl
->lpvtblPersistStream
= &psvt
;
1028 TRACE("(%p)->()\n",sl
);
1030 if (IsEqualIID(riid
, &IID_IUnknown
) ||
1031 IsEqualIID(riid
, &IID_IShellLinkA
))
1033 else if (IsEqualIID(riid
, &IID_IShellLinkW
))
1034 *ppv
= &(sl
->lpvtblw
);
1036 LocalFree((HLOCAL
)sl
);
1037 ERR("E_NOINTERFACE\n");
1038 return E_NOINTERFACE
;
1044 /**************************************************************************
1045 * IShellLinkA_QueryInterface
1047 static HRESULT WINAPI
IShellLinkA_fnQueryInterface( IShellLinkA
* iface
, REFIID riid
, LPVOID
*ppvObj
)
1049 ICOM_THIS(IShellLinkImpl
, iface
);
1051 TRACE("(%p)->(\n\tIID:\t%s)\n",This
,debugstr_guid(riid
));
1055 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1056 IsEqualIID(riid
, &IID_IShellLinkA
))
1060 else if(IsEqualIID(riid
, &IID_IShellLinkW
))
1062 *ppvObj
= (IShellLinkW
*)&(This
->lpvtblw
);
1064 else if(IsEqualIID(riid
, &IID_IPersistFile
))
1066 *ppvObj
= (IPersistFile
*)&(This
->lpvtblPersistFile
);
1068 else if(IsEqualIID(riid
, &IID_IPersistStream
))
1070 *ppvObj
= (IPersistStream
*)&(This
->lpvtblPersistStream
);
1075 IUnknown_AddRef((IUnknown
*)(*ppvObj
));
1076 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1079 TRACE("-- Interface: E_NOINTERFACE\n");
1080 return E_NOINTERFACE
;
1082 /******************************************************************************
1083 * IShellLinkA_AddRef
1085 static ULONG WINAPI
IShellLinkA_fnAddRef(IShellLinkA
* iface
)
1087 ICOM_THIS(IShellLinkImpl
, iface
);
1089 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1091 return ++(This
->ref
);
1093 /******************************************************************************
1094 * IShellLinkA_Release
1096 static ULONG WINAPI
IShellLinkA_fnRelease(IShellLinkA
* iface
)
1098 ICOM_THIS(IShellLinkImpl
, iface
);
1100 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1103 { TRACE("-- destroying IShellLink(%p)\n",This
);
1106 HeapFree(GetProcessHeap(), 0, This
->sIcoPath
);
1109 HeapFree(GetProcessHeap(), 0, This
->sArgs
);
1112 HeapFree(GetProcessHeap(), 0, This
->sWorkDir
);
1114 if (This
->sDescription
)
1115 HeapFree(GetProcessHeap(), 0, This
->sDescription
);
1118 HeapFree(GetProcessHeap(),0,This
->sPath
);
1121 SHFree(This
->pPidl
);
1123 if (This
->lpFileStream
)
1124 IStream_Release(This
->lpFileStream
);
1128 LocalFree((HANDLE
)This
);
1134 static HRESULT WINAPI
IShellLinkA_fnGetPath(IShellLinkA
* iface
, LPSTR pszFile
,INT cchMaxPath
, WIN32_FIND_DATAA
*pfd
, DWORD fFlags
)
1136 ICOM_THIS(IShellLinkImpl
, iface
);
1138 TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)(%s)\n",This
, pszFile
, cchMaxPath
, pfd
, fFlags
, debugstr_a(This
->sPath
));
1141 lstrcpynA(pszFile
,This
->sPath
, cchMaxPath
);
1147 static HRESULT WINAPI
IShellLinkA_fnGetIDList(IShellLinkA
* iface
, LPITEMIDLIST
* ppidl
)
1149 ICOM_THIS(IShellLinkImpl
, iface
);
1151 TRACE("(%p)->(ppidl=%p)\n",This
, ppidl
);
1153 *ppidl
= ILClone(This
->pPidl
);
1156 static HRESULT WINAPI
IShellLinkA_fnSetIDList(IShellLinkA
* iface
, LPCITEMIDLIST pidl
)
1158 ICOM_THIS(IShellLinkImpl
, iface
);
1160 TRACE("(%p)->(pidl=%p)\n",This
, pidl
);
1163 SHFree(This
->pPidl
);
1164 This
->pPidl
= ILClone (pidl
);
1167 static HRESULT WINAPI
IShellLinkA_fnGetDescription(IShellLinkA
* iface
, LPSTR pszName
,INT cchMaxName
)
1169 ICOM_THIS(IShellLinkImpl
, iface
);
1171 FIXME("(%p)->(%p len=%u)\n",This
, pszName
, cchMaxName
);
1172 lstrcpynA(pszName
,"Description, FIXME",cchMaxName
);
1175 static HRESULT WINAPI
IShellLinkA_fnSetDescription(IShellLinkA
* iface
, LPCSTR pszName
)
1177 ICOM_THIS(IShellLinkImpl
, iface
);
1179 TRACE("(%p)->(pName=%s)\n", This
, pszName
);
1181 if (This
->sDescription
)
1182 HeapFree(GetProcessHeap(), 0, This
->sDescription
);
1183 if (!(This
->sDescription
= heap_strdup(pszName
)))
1184 return E_OUTOFMEMORY
;
1188 static HRESULT WINAPI
IShellLinkA_fnGetWorkingDirectory(IShellLinkA
* iface
, LPSTR pszDir
,INT cchMaxPath
)
1190 ICOM_THIS(IShellLinkImpl
, iface
);
1192 TRACE("(%p)->(%p len=%u)\n", This
, pszDir
, cchMaxPath
);
1194 lstrcpynA( pszDir
, This
->sWorkDir
? This
->sWorkDir
: "", cchMaxPath
);
1198 static HRESULT WINAPI
IShellLinkA_fnSetWorkingDirectory(IShellLinkA
* iface
, LPCSTR pszDir
)
1200 ICOM_THIS(IShellLinkImpl
, iface
);
1202 TRACE("(%p)->(dir=%s)\n",This
, pszDir
);
1205 HeapFree(GetProcessHeap(), 0, This
->sWorkDir
);
1206 if (!(This
->sWorkDir
= heap_strdup(pszDir
)))
1207 return E_OUTOFMEMORY
;
1211 static HRESULT WINAPI
IShellLinkA_fnGetArguments(IShellLinkA
* iface
, LPSTR pszArgs
,INT cchMaxPath
)
1213 ICOM_THIS(IShellLinkImpl
, iface
);
1215 TRACE("(%p)->(%p len=%u)\n", This
, pszArgs
, cchMaxPath
);
1217 lstrcpynA( pszArgs
, This
->sArgs
? This
->sArgs
: "", cchMaxPath
);
1221 static HRESULT WINAPI
IShellLinkA_fnSetArguments(IShellLinkA
* iface
, LPCSTR pszArgs
)
1223 ICOM_THIS(IShellLinkImpl
, iface
);
1225 TRACE("(%p)->(args=%s)\n",This
, pszArgs
);
1228 HeapFree(GetProcessHeap(), 0, This
->sArgs
);
1229 if (!(This
->sArgs
= heap_strdup(pszArgs
)))
1230 return E_OUTOFMEMORY
;
1234 static HRESULT WINAPI
IShellLinkA_fnGetHotkey(IShellLinkA
* iface
, WORD
*pwHotkey
)
1236 ICOM_THIS(IShellLinkImpl
, iface
);
1238 TRACE("(%p)->(%p)(0x%08x)\n",This
, pwHotkey
, This
->wHotKey
);
1240 *pwHotkey
= This
->wHotKey
;
1244 static HRESULT WINAPI
IShellLinkA_fnSetHotkey(IShellLinkA
* iface
, WORD wHotkey
)
1246 ICOM_THIS(IShellLinkImpl
, iface
);
1248 TRACE("(%p)->(hotkey=%x)\n",This
, wHotkey
);
1250 This
->wHotKey
= wHotkey
;
1254 static HRESULT WINAPI
IShellLinkA_fnGetShowCmd(IShellLinkA
* iface
, INT
*piShowCmd
)
1256 ICOM_THIS(IShellLinkImpl
, iface
);
1258 FIXME("(%p)->(%p)\n",This
, piShowCmd
);
1262 static HRESULT WINAPI
IShellLinkA_fnSetShowCmd(IShellLinkA
* iface
, INT iShowCmd
)
1264 ICOM_THIS(IShellLinkImpl
, iface
);
1266 /* SW_SHOWNORMAL is the default ... The others would have
1267 * to be somehow passed through the link file ... We can't
1268 * do that currently.
1270 if (iShowCmd
!= SW_SHOWNORMAL
)
1271 FIXME("(%p)->(showcmd=%x)\n",This
, iShowCmd
);
1274 static HRESULT WINAPI
IShellLinkA_fnGetIconLocation(IShellLinkA
* iface
, LPSTR pszIconPath
,INT cchIconPath
,INT
*piIcon
)
1276 ICOM_THIS(IShellLinkImpl
, iface
);
1278 TRACE("(%p)->(%p len=%u iicon=%p)\n", This
, pszIconPath
, cchIconPath
, piIcon
);
1280 lstrcpynA( pszIconPath
, This
->sIcoPath
? This
->sIcoPath
: "", cchIconPath
);
1281 *piIcon
= This
->iIcoNdx
;
1285 static HRESULT WINAPI
IShellLinkA_fnSetIconLocation(IShellLinkA
* iface
, LPCSTR pszIconPath
,INT iIcon
)
1287 ICOM_THIS(IShellLinkImpl
, iface
);
1289 TRACE("(%p)->(path=%s iicon=%u)\n",This
, pszIconPath
, iIcon
);
1292 HeapFree(GetProcessHeap(), 0, This
->sIcoPath
);
1293 if (!(This
->sIcoPath
= heap_strdup(pszIconPath
)))
1294 return E_OUTOFMEMORY
;
1295 This
->iIcoNdx
= iIcon
;
1299 static HRESULT WINAPI
IShellLinkA_fnSetRelativePath(IShellLinkA
* iface
, LPCSTR pszPathRel
, DWORD dwReserved
)
1301 ICOM_THIS(IShellLinkImpl
, iface
);
1303 FIXME("(%p)->(path=%s %lx)\n",This
, pszPathRel
, dwReserved
);
1306 static HRESULT WINAPI
IShellLinkA_fnResolve(IShellLinkA
* iface
, HWND hwnd
, DWORD fFlags
)
1308 ICOM_THIS(IShellLinkImpl
, iface
);
1310 FIXME("(%p)->(hwnd=%p flags=%lx)\n",This
, hwnd
, fFlags
);
1313 static HRESULT WINAPI
IShellLinkA_fnSetPath(IShellLinkA
* iface
, LPCSTR pszFile
)
1315 ICOM_THIS(IShellLinkImpl
, iface
);
1317 TRACE("(%p)->(path=%s)\n",This
, pszFile
);
1320 HeapFree(GetProcessHeap(), 0, This
->sPath
);
1321 if (!(This
->sPath
= heap_strdup(pszFile
)))
1322 return E_OUTOFMEMORY
;
1327 /**************************************************************************
1328 * IShellLink Implementation
1331 static ICOM_VTABLE(IShellLinkA
) slvt
=
1333 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1334 IShellLinkA_fnQueryInterface
,
1335 IShellLinkA_fnAddRef
,
1336 IShellLinkA_fnRelease
,
1337 IShellLinkA_fnGetPath
,
1338 IShellLinkA_fnGetIDList
,
1339 IShellLinkA_fnSetIDList
,
1340 IShellLinkA_fnGetDescription
,
1341 IShellLinkA_fnSetDescription
,
1342 IShellLinkA_fnGetWorkingDirectory
,
1343 IShellLinkA_fnSetWorkingDirectory
,
1344 IShellLinkA_fnGetArguments
,
1345 IShellLinkA_fnSetArguments
,
1346 IShellLinkA_fnGetHotkey
,
1347 IShellLinkA_fnSetHotkey
,
1348 IShellLinkA_fnGetShowCmd
,
1349 IShellLinkA_fnSetShowCmd
,
1350 IShellLinkA_fnGetIconLocation
,
1351 IShellLinkA_fnSetIconLocation
,
1352 IShellLinkA_fnSetRelativePath
,
1353 IShellLinkA_fnResolve
,
1354 IShellLinkA_fnSetPath
1358 /**************************************************************************
1359 * IShellLinkW_fnQueryInterface
1361 static HRESULT WINAPI
IShellLinkW_fnQueryInterface(
1362 IShellLinkW
* iface
, REFIID riid
, LPVOID
*ppvObj
)
1364 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1366 return IShellLinkA_QueryInterface((IShellLinkA
*)This
, riid
, ppvObj
);
1369 /******************************************************************************
1370 * IShellLinkW_fnAddRef
1372 static ULONG WINAPI
IShellLinkW_fnAddRef(IShellLinkW
* iface
)
1374 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1376 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1378 return IShellLinkA_AddRef((IShellLinkA
*)This
);
1380 /******************************************************************************
1381 * IShellLinkW_fnRelease
1384 static ULONG WINAPI
IShellLinkW_fnRelease(IShellLinkW
* iface
)
1386 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1388 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
1390 return IShellLinkA_Release((IShellLinkA
*)This
);
1393 static HRESULT WINAPI
IShellLinkW_fnGetPath(IShellLinkW
* iface
, LPWSTR pszFile
,INT cchMaxPath
, WIN32_FIND_DATAA
*pfd
, DWORD fFlags
)
1395 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1397 FIXME("(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",This
, pszFile
, cchMaxPath
, pfd
, fFlags
);
1398 MultiByteToWideChar( CP_ACP
, 0, "c:\\foo.bar", -1, pszFile
, cchMaxPath
);
1402 static HRESULT WINAPI
IShellLinkW_fnGetIDList(IShellLinkW
* iface
, LPITEMIDLIST
* ppidl
)
1404 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1406 FIXME("(%p)->(ppidl=%p)\n",This
, ppidl
);
1407 *ppidl
= _ILCreateDesktop();
1411 static HRESULT WINAPI
IShellLinkW_fnSetIDList(IShellLinkW
* iface
, LPCITEMIDLIST pidl
)
1413 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1415 FIXME("(%p)->(pidl=%p)\n",This
, pidl
);
1419 static HRESULT WINAPI
IShellLinkW_fnGetDescription(IShellLinkW
* iface
, LPWSTR pszName
,INT cchMaxName
)
1421 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1423 FIXME("(%p)->(%p len=%u)\n",This
, pszName
, cchMaxName
);
1424 MultiByteToWideChar( CP_ACP
, 0, "Description, FIXME", -1, pszName
, cchMaxName
);
1428 static HRESULT WINAPI
IShellLinkW_fnSetDescription(IShellLinkW
* iface
, LPCWSTR pszName
)
1430 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1432 TRACE("(%p)->(desc=%s)\n",This
, debugstr_w(pszName
));
1434 if (This
->sDescription
)
1435 HeapFree(GetProcessHeap(), 0, This
->sDescription
);
1436 if (!(This
->sDescription
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszName
)))
1437 return E_OUTOFMEMORY
;
1442 static HRESULT WINAPI
IShellLinkW_fnGetWorkingDirectory(IShellLinkW
* iface
, LPWSTR pszDir
,INT cchMaxPath
)
1444 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1446 TRACE("(%p)->(%p len %u)\n", This
, pszDir
, cchMaxPath
);
1448 MultiByteToWideChar( CP_ACP
, 0, This
->sWorkDir
? This
->sWorkDir
: "", -1, pszDir
, cchMaxPath
);
1453 static HRESULT WINAPI
IShellLinkW_fnSetWorkingDirectory(IShellLinkW
* iface
, LPCWSTR pszDir
)
1455 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1457 TRACE("(%p)->(dir=%s)\n",This
, debugstr_w(pszDir
));
1460 HeapFree(GetProcessHeap(), 0, This
->sWorkDir
);
1461 if (!(This
->sWorkDir
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszDir
)))
1462 return E_OUTOFMEMORY
;
1467 static HRESULT WINAPI
IShellLinkW_fnGetArguments(IShellLinkW
* iface
, LPWSTR pszArgs
,INT cchMaxPath
)
1469 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1471 TRACE("(%p)->(%p len=%u)\n", This
, pszArgs
, cchMaxPath
);
1473 MultiByteToWideChar( CP_ACP
, 0, This
->sArgs
? This
->sArgs
: "", -1, pszArgs
, cchMaxPath
);
1478 static HRESULT WINAPI
IShellLinkW_fnSetArguments(IShellLinkW
* iface
, LPCWSTR pszArgs
)
1480 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1482 TRACE("(%p)->(args=%s)\n",This
, debugstr_w(pszArgs
));
1485 HeapFree(GetProcessHeap(), 0, This
->sArgs
);
1486 if (!(This
->sArgs
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszArgs
)))
1487 return E_OUTOFMEMORY
;
1492 static HRESULT WINAPI
IShellLinkW_fnGetHotkey(IShellLinkW
* iface
, WORD
*pwHotkey
)
1494 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1496 FIXME("(%p)->(%p)\n",This
, pwHotkey
);
1501 static HRESULT WINAPI
IShellLinkW_fnSetHotkey(IShellLinkW
* iface
, WORD wHotkey
)
1503 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1505 FIXME("(%p)->(hotkey=%x)\n",This
, wHotkey
);
1509 static HRESULT WINAPI
IShellLinkW_fnGetShowCmd(IShellLinkW
* iface
, INT
*piShowCmd
)
1511 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1513 FIXME("(%p)->(%p)\n",This
, piShowCmd
);
1518 static HRESULT WINAPI
IShellLinkW_fnSetShowCmd(IShellLinkW
* iface
, INT iShowCmd
)
1520 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1522 /* SW_SHOWNORMAL is the default ... The others would have
1523 * to be somehow passed through the link file ... We can't
1524 * do that currently.
1526 if (iShowCmd
!= SW_SHOWNORMAL
)
1527 FIXME("(%p)->(showcmd=%x)\n",This
, iShowCmd
);
1531 static HRESULT WINAPI
IShellLinkW_fnGetIconLocation(IShellLinkW
* iface
, LPWSTR pszIconPath
,INT cchIconPath
,INT
*piIcon
)
1533 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1535 TRACE("(%p)->(%p len=%u iicon=%p)\n", This
, pszIconPath
, cchIconPath
, piIcon
);
1537 MultiByteToWideChar( CP_ACP
, 0, This
->sIcoPath
? This
->sIcoPath
: "", -1, pszIconPath
, cchIconPath
);
1538 *piIcon
= This
->iIcoNdx
;
1543 static HRESULT WINAPI
IShellLinkW_fnSetIconLocation(IShellLinkW
* iface
, LPCWSTR pszIconPath
,INT iIcon
)
1545 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1547 TRACE("(%p)->(path=%s iicon=%u)\n",This
, debugstr_w(pszIconPath
), iIcon
);
1550 HeapFree(GetProcessHeap(), 0, This
->sIcoPath
);
1551 if (!(This
->sIcoPath
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszIconPath
)))
1552 return E_OUTOFMEMORY
;
1553 This
->iIcoNdx
= iIcon
;
1558 static HRESULT WINAPI
IShellLinkW_fnSetRelativePath(IShellLinkW
* iface
, LPCWSTR pszPathRel
, DWORD dwReserved
)
1560 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1562 FIXME("(%p)->(path=%s %lx)\n",This
, debugstr_w(pszPathRel
), dwReserved
);
1566 static HRESULT WINAPI
IShellLinkW_fnResolve(IShellLinkW
* iface
, HWND hwnd
, DWORD fFlags
)
1568 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1570 FIXME("(%p)->(hwnd=%p flags=%lx)\n",This
, hwnd
, fFlags
);
1574 static HRESULT WINAPI
IShellLinkW_fnSetPath(IShellLinkW
* iface
, LPCWSTR pszFile
)
1576 _ICOM_THIS_From_IShellLinkW(IShellLinkImpl
, iface
);
1578 TRACE("(%p)->(path=%s)\n",This
, debugstr_w(pszFile
));
1581 HeapFree(GetProcessHeap(), 0, This
->sPath
);
1582 if (!(This
->sPath
= HEAP_strdupWtoA(GetProcessHeap(), 0, pszFile
)))
1583 return E_OUTOFMEMORY
;
1588 /**************************************************************************
1589 * IShellLinkW Implementation
1592 static ICOM_VTABLE(IShellLinkW
) slvtw
=
1594 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1595 IShellLinkW_fnQueryInterface
,
1596 IShellLinkW_fnAddRef
,
1597 IShellLinkW_fnRelease
,
1598 IShellLinkW_fnGetPath
,
1599 IShellLinkW_fnGetIDList
,
1600 IShellLinkW_fnSetIDList
,
1601 IShellLinkW_fnGetDescription
,
1602 IShellLinkW_fnSetDescription
,
1603 IShellLinkW_fnGetWorkingDirectory
,
1604 IShellLinkW_fnSetWorkingDirectory
,
1605 IShellLinkW_fnGetArguments
,
1606 IShellLinkW_fnSetArguments
,
1607 IShellLinkW_fnGetHotkey
,
1608 IShellLinkW_fnSetHotkey
,
1609 IShellLinkW_fnGetShowCmd
,
1610 IShellLinkW_fnSetShowCmd
,
1611 IShellLinkW_fnGetIconLocation
,
1612 IShellLinkW_fnSetIconLocation
,
1613 IShellLinkW_fnSetRelativePath
,
1614 IShellLinkW_fnResolve
,
1615 IShellLinkW_fnSetPath