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
Set(HWND hwndParent,int string_size,TCHAR * variables,stack_t ** stacktop)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
UninstallJumpLists(HWND hwndParent,int string_size,TCHAR * variables,stack_t ** stacktop)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
UninstallPinnedItem(HWND hwndParent,int string_size,TCHAR * variables,stack_t ** stacktop)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
popstring(TCHAR * str,int len)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
pushstring(const TCHAR * str,int len)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 }
220