1 /*
2 Module : ShellLink.cpp
3 Purpose: NSIS Plug-in for retriving shell link information
4 Created: 12/16/2003
5 Last Update: 01/14/2004
6 
7 Copyright (c) 2004 Angelo Mandato.
8 See ShellLink.html for more information
9 
10 
11 Modified: 21/09/2005
12 Author:   Shengalts Aleksander aka Instructor (Shengalts@mail.ru)
13 Changes:  -code has been rewritten
14           -added functions to change shell link information
15           -reduced dll size 44Kb -> 4Kb
16 */
17 
18 //  Uncomment for debugging message boxes
19 //#define SHELLLINK_DEBUG
20 
21 #include <windows.h>
22 #include <shlobj.h>
23 
24 #define xatoi
25 #include "ConvFunc.h"
26 
27 #ifdef UNICODE
28 #include "nsis_unicode\pluginapi.h"
29 #else
30 #include "nsis_ansi\pluginapi.h"
31 #endif
32 
33 #define NSISFUNC(name) extern "C" void __declspec(dllexport) name(HWND hWndParent, int string_size, TCHAR* variables, stack_t** stacktop, extra_parameters* extra)
34 
35 #define SHELLLINKTYPE_GETARGS 1
36 #define SHELLLINKTYPE_GETDESC 2
37 #define SHELLLINKTYPE_GETHOTKEY 3
38 #define SHELLLINKTYPE_GETICONLOC 4
39 #define SHELLLINKTYPE_GETICONINDEX 5
40 #define SHELLLINKTYPE_GETPATH 6
41 #define SHELLLINKTYPE_GETSHOWMODE 7
42 #define SHELLLINKTYPE_GETWORKINGDIR 8
43 #define SHELLLINKTYPE_SETARGS 9
44 #define SHELLLINKTYPE_SETDESC 10
45 #define SHELLLINKTYPE_SETHOTKEY 11
46 #define SHELLLINKTYPE_SETICONLOC 12
47 #define SHELLLINKTYPE_SETICONINDEX 13
48 #define SHELLLINKTYPE_SETPATH 14
49 #define SHELLLINKTYPE_SETSHOWMODE 15
50 #define SHELLLINKTYPE_SETWORKINGDIR 16
51 #define SHELLLINKTYPE_SETRUNASADMIN 17
52 
53 void ShortCutData(int nType);
54 
55 //Get
NSISFUNC(GetShortCutArgs)56 NSISFUNC(GetShortCutArgs)
57 {
58   EXDLL_INIT();
59 	ShortCutData(SHELLLINKTYPE_GETARGS);
60 }
61 
NSISFUNC(GetShortCutDescription)62 NSISFUNC(GetShortCutDescription)
63 {
64   EXDLL_INIT();
65 	ShortCutData(SHELLLINKTYPE_GETDESC);
66 }
67 
NSISFUNC(GetShortCutHotkey)68 NSISFUNC(GetShortCutHotkey)
69 {
70   EXDLL_INIT();
71 	ShortCutData(SHELLLINKTYPE_GETHOTKEY);
72 }
73 
NSISFUNC(GetShortCutIconLocation)74 NSISFUNC(GetShortCutIconLocation)
75 {
76   EXDLL_INIT();
77 	ShortCutData(SHELLLINKTYPE_GETICONLOC);
78 }
79 
NSISFUNC(GetShortCutIconIndex)80 NSISFUNC(GetShortCutIconIndex)
81 {
82   EXDLL_INIT();
83 	ShortCutData(SHELLLINKTYPE_GETICONINDEX);
84 }
85 
NSISFUNC(GetShortCutTarget)86 NSISFUNC(GetShortCutTarget)
87 {
88   EXDLL_INIT();
89 	ShortCutData(SHELLLINKTYPE_GETPATH);
90 }
91 
NSISFUNC(GetShortCutShowMode)92 NSISFUNC(GetShortCutShowMode)
93 {
94   EXDLL_INIT();
95 	ShortCutData(SHELLLINKTYPE_GETSHOWMODE);
96 }
97 
NSISFUNC(GetShortCutWorkingDirectory)98 NSISFUNC(GetShortCutWorkingDirectory)
99 {
100   EXDLL_INIT();
101 	ShortCutData(SHELLLINKTYPE_GETWORKINGDIR);
102 }
103 
104 //Set
NSISFUNC(SetShortCutArgs)105 NSISFUNC(SetShortCutArgs)
106 {
107   EXDLL_INIT();
108 	ShortCutData(SHELLLINKTYPE_SETARGS);
109 }
110 
NSISFUNC(SetShortCutDescription)111 NSISFUNC(SetShortCutDescription)
112 {
113   EXDLL_INIT();
114 	ShortCutData(SHELLLINKTYPE_SETDESC);
115 }
116 
NSISFUNC(SetShortCutHotkey)117 NSISFUNC(SetShortCutHotkey)
118 {
119   EXDLL_INIT();
120 	ShortCutData(SHELLLINKTYPE_SETHOTKEY);
121 }
122 
NSISFUNC(SetShortCutIconLocation)123 NSISFUNC(SetShortCutIconLocation)
124 {
125   EXDLL_INIT();
126 	ShortCutData(SHELLLINKTYPE_SETICONLOC);
127 }
128 
NSISFUNC(SetShortCutIconIndex)129 NSISFUNC(SetShortCutIconIndex)
130 {
131   EXDLL_INIT();
132 	ShortCutData(SHELLLINKTYPE_SETICONINDEX);
133 }
134 
NSISFUNC(SetShortCutTarget)135 NSISFUNC(SetShortCutTarget)
136 {
137   EXDLL_INIT();
138 	ShortCutData(SHELLLINKTYPE_SETPATH);
139 }
140 
NSISFUNC(SetShortCutShowMode)141 NSISFUNC(SetShortCutShowMode)
142 {
143   EXDLL_INIT();
144 	ShortCutData(SHELLLINKTYPE_SETSHOWMODE);
145 }
146 
NSISFUNC(SetShortCutWorkingDirectory)147 NSISFUNC(SetShortCutWorkingDirectory)
148 {
149   EXDLL_INIT();
150 	ShortCutData(SHELLLINKTYPE_SETWORKINGDIR);
151 }
152 
NSISFUNC(SetRunAsAdministrator)153 NSISFUNC(SetRunAsAdministrator)
154 {
155   EXDLL_INIT();
156 	ShortCutData(SHELLLINKTYPE_SETRUNASADMIN);
157 }
158 
ShortCutData(int nType)159 void ShortCutData(int nType)
160 {
161 	HRESULT hRes;
162 	IShellLink* psl;
163 	IPersistFile* ppf;
164 
165   int nBuf;
166   WORD wHotkey;
167   TCHAR* szBuf = (TCHAR*)LocalAlloc(LPTR, sizeof(TCHAR)*MAX_PATH);
168   TCHAR* szBuf2 = (TCHAR*)LocalAlloc(LPTR, sizeof(TCHAR)*MAX_PATH);
169 
170 	popstring(szBuf);
171 	if (nType > SHELLLINKTYPE_GETWORKINGDIR) popstring(szBuf2);
172 
173 	hRes=CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) &psl);
174 	if (hRes == S_OK)
175 	{
176 		hRes=psl->QueryInterface(IID_IPersistFile, (LPVOID*) &ppf);
177 		if (hRes == S_OK)
178 		{
179 #ifdef UNICODE
180 			hRes=ppf->Load(szBuf, STGM_READWRITE);
181 #else
182       WCHAR* wszPath = (WCHAR*)LocalAlloc(LPTR, sizeof(WCHAR)*MAX_PATH);
183 			MultiByteToWideChar(CP_ACP, 0, szBuf, -1, wszPath, MAX_PATH);
184 			hRes=ppf->Load(wszPath, STGM_READWRITE);
185       LocalFree(wszPath);
186 #endif
187 			if (hRes == S_OK)
188 			{
189 				if (nType <= SHELLLINKTYPE_GETWORKINGDIR)
190 				{
191 					//Get
192 					switch(nType)
193 					{
194 						case SHELLLINKTYPE_GETARGS:
195 						{
196 							hRes=psl->GetArguments(szBuf, MAX_PATH);
197 							if (hRes != S_OK) szBuf[0]='\0';
198 						}; break;
199 						case SHELLLINKTYPE_GETDESC:
200 						{
201 							hRes=psl->GetDescription(szBuf, MAX_PATH);
202 							if (hRes != S_OK) szBuf[0]='\0';
203 						}; break;
204 						case SHELLLINKTYPE_GETHOTKEY:
205 						{
206 							hRes=psl->GetHotkey(&wHotkey);
207 							if (hRes == S_OK) wsprintf(szBuf, TEXT("%d"), wHotkey);
208 							else szBuf[0]='\0';
209 						}; break;
210 						case SHELLLINKTYPE_GETICONLOC:
211 						{
212 							hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf);
213 							if (hRes != S_OK) szBuf[0]='\0';
214 						}; break;
215 						case SHELLLINKTYPE_GETICONINDEX:
216 						{
217 							hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf);
218 							if (hRes == S_OK) wsprintf(szBuf, TEXT("%d"), nBuf);
219 							else szBuf[0]='\0';
220 						}; break;
221 						case SHELLLINKTYPE_GETPATH:
222 						{
223 							WIN32_FIND_DATA fd;
224 
225 							hRes=psl->GetPath(szBuf, MAX_PATH, &fd, SLGP_UNCPRIORITY);
226 							if (hRes != S_OK) szBuf[0]='\0';
227 						}; break;
228 						case SHELLLINKTYPE_GETSHOWMODE:
229 						{
230 							hRes=psl->GetShowCmd(&nBuf);
231 							if (hRes == S_OK) wsprintf(szBuf, TEXT("%d"), nBuf);
232 							else szBuf[0]='\0';
233 						}; break;
234 						case SHELLLINKTYPE_GETWORKINGDIR:
235 						{
236 							hRes=psl->GetWorkingDirectory(szBuf, MAX_PATH);
237 							if (hRes != S_OK) szBuf[0]='\0';
238 						}; break;
239 					}
240 				}
241 				else
242 				{
243 					//Set
244 					switch(nType)
245 					{
246 						case SHELLLINKTYPE_SETARGS:
247 						{
248 							hRes=psl->SetArguments(szBuf2);
249 						}; break;
250 						case SHELLLINKTYPE_SETDESC:
251 						{
252 							hRes=psl->SetDescription(szBuf2);
253 						}; break;
254 						case SHELLLINKTYPE_SETHOTKEY:
255 						{
256 							wHotkey=(unsigned short)myatoi(szBuf2);
257 							hRes=psl->SetHotkey(wHotkey);
258 						}; break;
259 						case SHELLLINKTYPE_SETICONLOC:
260 						{
261 							hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf);
262 							if (hRes == S_OK)
263 								hRes=psl->SetIconLocation(szBuf2, nBuf);
264 						}; break;
265 						case SHELLLINKTYPE_SETICONINDEX:
266 						{
267 							int nBuf2;
268 							nBuf=myatoi(szBuf2);
269 
270 							hRes=psl->GetIconLocation(szBuf, MAX_PATH, &nBuf2);
271 							if (hRes == S_OK)
272 								hRes=psl->SetIconLocation(szBuf, nBuf);
273 						}; break;
274 						case SHELLLINKTYPE_SETPATH:
275 						{
276 							hRes=psl->SetPath(szBuf2);
277 						}; break;
278 						case SHELLLINKTYPE_SETSHOWMODE:
279 						{
280 							nBuf=myatoi(szBuf2);
281 							hRes=psl->SetShowCmd(nBuf);
282 						}; break;
283 						case SHELLLINKTYPE_SETWORKINGDIR:
284 						{
285 							hRes=psl->SetWorkingDirectory(szBuf2);
286 						}; break;
287 						case SHELLLINKTYPE_SETRUNASADMIN:
288 						{
289               IShellLinkDataList* pdl;
290               hRes=psl->QueryInterface(IID_IShellLinkDataList, (void**)&pdl);
291               if (hRes == S_OK)
292               {
293                 DWORD dwFlags = 0;
294 							  hRes=pdl->GetFlags(&dwFlags);
295                 if (hRes == S_OK && (dwFlags & SLDF_RUNAS_USER) != SLDF_RUNAS_USER)
296                   hRes=pdl->SetFlags(dwFlags | SLDF_RUNAS_USER);
297                 pdl->Release();
298               }
299 						}; break;
300 					}
301 					if (hRes == S_OK) hRes=ppf->Save(NULL, FALSE);
302 					#ifdef SHELLLINK_DEBUG
303 					else MessageBox(hwndParent, TEXT("ERROR: Save()"), TEXT("ShellLink plug-in"), MB_OK);
304 					#endif
305 				}
306 			}
307 			#ifdef SHELLLINK_DEBUG
308 			else MessageBox(hwndParent, TEXT("ERROR: Load()"), TEXT("ShellLink plug-in"), MB_OK);
309 			#endif
310 		}
311 		#ifdef SHELLLINK_DEBUG
312 		else MessageBox(hwndParent, TEXT("CShellLink::Initialise, Failed in call to QueryInterface for IPersistFile, HRESULT was %x\n"), TEXT("ShellLink plug-in"), MB_OK);
313 		#endif
314 
315 		// Cleanup:
316 		if (ppf) ppf->Release();
317 		if (psl) psl->Release();
318 	}
319 	#ifdef SHELLLINK_DEBUG
320 	else MessageBox(hwndParent, TEXT("ERROR: CoCreateInstance()"), TEXT("ShellLink plug-in"), MB_OK);
321 	#endif
322 
323 	if (hRes == S_OK)
324 	{
325 		if (nType <= SHELLLINKTYPE_GETWORKINGDIR) pushstring(szBuf);
326 		else pushstring(TEXT("0"));
327 	}
328 	else
329 	{
330 		if (nType <= SHELLLINKTYPE_GETWORKINGDIR) pushstring(TEXT(""));
331 		else pushstring(TEXT("-1"));
332 	}
333 
334   LocalFree(szBuf);
335   LocalFree(szBuf2);
336 }
337 
DllMain(HANDLE hInst,ULONG ul_reason_for_call,LPVOID lpReserved)338 BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
339 {
340 	return TRUE;
341 }
342