|
1 /* |
|
2 * Module : Set.cpp |
|
3 * Purpose: NSIS Plug-in for setting shortcut ApplicationID property |
|
4 * Created: 27/12/2009 |
|
5 * Original code Copyright (c) 2009 Mike Anchor. |
|
6 */ |
|
7 |
|
8 /* |
|
9 * Additional Mozilla contributions: |
|
10 * Unicode support |
|
11 * Jump list deletion on uninstall |
|
12 * Pinned item removal on uninstall |
|
13 * contrib: <jmathies@mozilla.com> |
|
14 */ |
|
15 |
|
16 #define INITGUID |
|
17 |
|
18 #include <windows.h> |
|
19 #include <shlobj.h> |
|
20 #include <propvarutil.h> |
|
21 #include <propkey.h> |
|
22 #include <stdio.h> |
|
23 |
|
24 #pragma comment (lib, "shlwapi.lib") |
|
25 |
|
26 #define MAX_STRLEN 1024 |
|
27 |
|
28 typedef struct _stack_t { |
|
29 struct _stack_t *next; |
|
30 TCHAR text[MAX_PATH]; |
|
31 } stack_t; |
|
32 |
|
33 stack_t **g_stacktop; |
|
34 unsigned int g_stringsize; |
|
35 TCHAR *g_variables; |
|
36 |
|
37 // Indicates that an application supports dual desktop and immersive modes. In Windows 8, this property is only applicable for web browsers. |
|
38 DEFINE_PROPERTYKEY(PKEY_AppUserModel_IsDualMode, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 11); |
|
39 |
|
40 int popstring(TCHAR *str, int len); |
|
41 void pushstring(const TCHAR *str, int len); |
|
42 |
|
43 extern "C" void __declspec(dllexport) Set(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) |
|
44 { |
|
45 g_stringsize = string_size; |
|
46 g_stacktop = stacktop; |
|
47 g_variables = variables; |
|
48 |
|
49 { |
|
50 IPropertyStore *m_pps = NULL; |
|
51 WCHAR wszPath[MAX_PATH]; |
|
52 WCHAR wszAppID[MAX_PATH]; |
|
53 TCHAR szPath[MAX_PATH]; |
|
54 TCHAR szAppID[MAX_PATH]; |
|
55 TCHAR szDualMode[MAX_PATH]; |
|
56 bool success = false; |
|
57 |
|
58 ZeroMemory(wszPath, sizeof(wszPath)); |
|
59 ZeroMemory(wszAppID, sizeof(wszAppID)); |
|
60 ZeroMemory(szPath, sizeof(szPath)); |
|
61 ZeroMemory(szAppID, sizeof(szAppID)); |
|
62 ZeroMemory(szDualMode, sizeof(szDualMode)); |
|
63 |
|
64 popstring(szPath, MAX_PATH); |
|
65 popstring(szAppID, MAX_PATH); |
|
66 bool dualMode = (popstring(szDualMode, MAX_PATH) == 0); // optional |
|
67 #if !defined(UNICODE) |
|
68 MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); |
|
69 MultiByteToWideChar(CP_ACP, 0, szAppID, -1, wszAppID, MAX_PATH); |
|
70 if (dualMode && stricmp(szDualMode, "true") != 0) { |
|
71 dualMode = false; |
|
72 } |
|
73 #else |
|
74 wcscpy_s(wszPath, szPath); |
|
75 wcscpy_s(wszAppID, szAppID); |
|
76 if (dualMode && _wcsicmp(szDualMode, L"true") != 0) { |
|
77 dualMode = false; |
|
78 } |
|
79 #endif |
|
80 |
|
81 CoInitialize(NULL); |
|
82 |
|
83 if (SUCCEEDED(SHGetPropertyStoreFromParsingName(wszPath, NULL, GPS_READWRITE, IID_PPV_ARGS(&m_pps)))) |
|
84 { |
|
85 PROPVARIANT propvar; |
|
86 if (SUCCEEDED(InitPropVariantFromString(wszAppID, &propvar))) { |
|
87 if (SUCCEEDED(m_pps->SetValue(PKEY_AppUserModel_ID, propvar))) { |
|
88 if (dualMode) { |
|
89 InitPropVariantFromBoolean(true, &propvar); |
|
90 m_pps->SetValue(PKEY_AppUserModel_IsDualMode, propvar); |
|
91 } |
|
92 if (SUCCEEDED(m_pps->Commit())) { |
|
93 success = true; |
|
94 } |
|
95 } |
|
96 } |
|
97 } |
|
98 if (m_pps != NULL) |
|
99 m_pps->Release(); |
|
100 |
|
101 CoUninitialize(); |
|
102 |
|
103 pushstring(success == true ? TEXT("0") : TEXT("-1"), MAX_PATH); |
|
104 } |
|
105 } |
|
106 |
|
107 extern "C" void __declspec(dllexport) UninstallJumpLists(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) |
|
108 { |
|
109 g_stringsize = string_size; |
|
110 g_stacktop = stacktop; |
|
111 g_variables = variables; |
|
112 |
|
113 ICustomDestinationList *m_cdl = NULL; |
|
114 WCHAR wszAppID[MAX_PATH]; |
|
115 TCHAR szAppID[MAX_PATH]; |
|
116 bool success = false; |
|
117 |
|
118 ZeroMemory(wszAppID, sizeof(wszAppID)); |
|
119 ZeroMemory(szAppID, sizeof(szAppID)); |
|
120 |
|
121 popstring(szAppID, MAX_PATH); |
|
122 |
|
123 #if !defined(UNICODE) |
|
124 MultiByteToWideChar(CP_ACP, 0, szAppID, -1, wszAppID, MAX_PATH); |
|
125 #else |
|
126 wcscpy_s(wszAppID, szAppID); |
|
127 #endif |
|
128 |
|
129 CoInitialize(NULL); |
|
130 |
|
131 CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, |
|
132 IID_ICustomDestinationList, (void**)&m_cdl); |
|
133 |
|
134 if (m_cdl) { |
|
135 if (SUCCEEDED(m_cdl->DeleteList(wszAppID))) { |
|
136 success = true; |
|
137 } |
|
138 } |
|
139 |
|
140 if (m_cdl) |
|
141 m_cdl->Release(); |
|
142 |
|
143 CoUninitialize(); |
|
144 |
|
145 pushstring(success == true ? TEXT("0") : TEXT("-1"), MAX_PATH); |
|
146 } |
|
147 |
|
148 extern "C" void __declspec(dllexport) UninstallPinnedItem(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop) |
|
149 { |
|
150 g_stringsize = string_size; |
|
151 g_stacktop = stacktop; |
|
152 g_variables = variables; |
|
153 |
|
154 IShellItem *pItem = NULL; |
|
155 IStartMenuPinnedList *pPinnedList = NULL; |
|
156 WCHAR wszPath[MAX_PATH]; |
|
157 TCHAR szPath[MAX_PATH]; |
|
158 bool success = false; |
|
159 |
|
160 ZeroMemory(wszPath, sizeof(wszPath)); |
|
161 ZeroMemory(szPath, sizeof(szPath)); |
|
162 |
|
163 popstring(szPath, MAX_PATH); |
|
164 |
|
165 #if !defined(UNICODE) |
|
166 MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); |
|
167 #else |
|
168 wcscpy_s(wszPath, szPath); |
|
169 #endif |
|
170 |
|
171 CoInitialize(NULL); |
|
172 |
|
173 HRESULT hr; |
|
174 hr = SHCreateItemFromParsingName(wszPath, NULL, IID_PPV_ARGS(&pItem)); |
|
175 |
|
176 if (SUCCEEDED(hr)) { |
|
177 |
|
178 hr = CoCreateInstance(CLSID_StartMenuPin, |
|
179 NULL, |
|
180 CLSCTX_INPROC_SERVER, |
|
181 IID_PPV_ARGS(&pPinnedList)); |
|
182 |
|
183 if (SUCCEEDED(hr)) { |
|
184 hr = pPinnedList->RemoveFromList(pItem); |
|
185 pPinnedList->Release(); |
|
186 success = true; |
|
187 } |
|
188 |
|
189 pItem->Release(); |
|
190 } |
|
191 |
|
192 CoUninitialize(); |
|
193 |
|
194 pushstring(success == true ? TEXT("0") : TEXT("-1"), MAX_PATH); |
|
195 } |
|
196 |
|
197 //Function: Removes the element from the top of the NSIS stack and puts it in the buffer |
|
198 int popstring(TCHAR *str, int len) |
|
199 { |
|
200 stack_t *th; |
|
201 if (!g_stacktop || !*g_stacktop) return 1; |
|
202 th=(*g_stacktop); |
|
203 lstrcpyn(str,th->text, len); |
|
204 *g_stacktop=th->next; |
|
205 GlobalFree((HGLOBAL)th); |
|
206 return 0; |
|
207 } |
|
208 |
|
209 //Function: Adds an element to the top of the NSIS stack |
|
210 void pushstring(const TCHAR *str, int len) |
|
211 { |
|
212 stack_t *th; |
|
213 |
|
214 if (!g_stacktop) return; |
|
215 th=(stack_t*)GlobalAlloc(GPTR, sizeof(stack_t) + len); |
|
216 lstrcpyn(th->text, str, len); |
|
217 th->next=*g_stacktop; |
|
218 *g_stacktop=th; |
|
219 } |