1 | #include "gsProgman.h"
|
---|
2 |
|
---|
3 | #include <stdio.h>
|
---|
4 |
|
---|
5 | // include shell for explorer-based OS'es
|
---|
6 | #include <shlobj.h>
|
---|
7 | // include dde for old (win 3.1/winNT 3.5) OS'es
|
---|
8 | #include <ddeml.h>
|
---|
9 |
|
---|
10 | #include "FilePath.h"
|
---|
11 |
|
---|
12 | extern HINSTANCE app_instance;
|
---|
13 |
|
---|
14 | /**
|
---|
15 | * A private function for Dde callbacks; in practice it needs to be here,
|
---|
16 | * but does nothing whatsoever
|
---|
17 | */
|
---|
18 | HDDEDATA CALLBACK DdeCallBack(
|
---|
19 | UINT uType, // transaction type
|
---|
20 | UINT uFmt, // clipboard data format
|
---|
21 | HCONV hconv, // handle to the conversation
|
---|
22 | HSZ hsz1, // handle to a string
|
---|
23 | HSZ hsz2, // handle to a string
|
---|
24 | HDDEDATA hdata, // handle to a global memory object
|
---|
25 | DWORD dwData1, // transaction-specific data
|
---|
26 | DWORD dwData2 // transaction-specific data
|
---|
27 | )
|
---|
28 | { return NULL;
|
---|
29 | }
|
---|
30 |
|
---|
31 | /**
|
---|
32 | * A private little function to do DDE activity
|
---|
33 | */
|
---|
34 | bool DDEShellCommand(DWORD instance, char *command)
|
---|
35 | { HSZ serviceName;
|
---|
36 | HCONV conversation;
|
---|
37 | int commandLength;
|
---|
38 | HDDEDATA ddeData;
|
---|
39 | DWORD result;
|
---|
40 | bool reply = false;
|
---|
41 |
|
---|
42 | // create DDE string from service request
|
---|
43 | serviceName = DdeCreateStringHandle(instance, "PROGMAN", CP_WINANSI);
|
---|
44 | if (serviceName == NULL)
|
---|
45 | { /*char buffer[20];
|
---|
46 | sprintf(buffer, "%d %d", DdeGetLastError(instance), instance);
|
---|
47 | MessageBox(0, buffer, "GSInstall", MB_OK);*/
|
---|
48 | return FALSE;
|
---|
49 | }
|
---|
50 |
|
---|
51 | // strike up a conversation with the DDE service
|
---|
52 | if ((conversation = DdeConnect(instance, serviceName, serviceName, NULL)) != NULL)
|
---|
53 | { commandLength = lstrlen(command);
|
---|
54 |
|
---|
55 | // send the message via DDE
|
---|
56 | // MessageBox(0, command, "Executing", MB_OK);
|
---|
57 | ddeData = DdeClientTransaction((LPBYTE) command, commandLength + 1,
|
---|
58 | conversation, NULL, CF_TEXT, XTYP_EXECUTE,
|
---|
59 | 1000, &result);
|
---|
60 | // if our reply isn't NULL, it succeeded
|
---|
61 | reply = (ddeData != NULL);
|
---|
62 | if (reply == false)
|
---|
63 | { /*
|
---|
64 | char buffer[20];
|
---|
65 |
|
---|
66 | sprintf(buffer, "%d", DdeGetLastError(instance));
|
---|
67 | MessageBox(0, buffer, "DDE Error", MB_OK);*/
|
---|
68 | }
|
---|
69 |
|
---|
70 | // disconnect the conversation
|
---|
71 | DdeDisconnect(conversation);
|
---|
72 | }
|
---|
73 | else
|
---|
74 | { MessageBox(0, "DDE Connect failed", "GSInstall", MB_OK);
|
---|
75 | }
|
---|
76 |
|
---|
77 | // free DDE string
|
---|
78 | DdeFreeStringHandle(instance, serviceName);
|
---|
79 | return reply;
|
---|
80 | }
|
---|
81 |
|
---|
82 | gsProgramManager::gsProgramManager()
|
---|
83 | { this->platform = new gsPlatform();
|
---|
84 | this->connected = false;
|
---|
85 | }
|
---|
86 |
|
---|
87 | bool gsProgramManager::connect()
|
---|
88 | { HRESULT response;
|
---|
89 |
|
---|
90 | if (this->platform->isExplorerShell())
|
---|
91 | { // Initialise the shell connection
|
---|
92 | response = CoInitialize(NULL);
|
---|
93 | if (response < 0)
|
---|
94 | { return false;
|
---|
95 | }
|
---|
96 | }
|
---|
97 | else
|
---|
98 | { FARPROC procPtr;
|
---|
99 |
|
---|
100 | procPtr = MakeProcInstance((FARPROC) DdeCallBack, app_instance);
|
---|
101 |
|
---|
102 | instance = 0L;
|
---|
103 | if (DdeInitialize(&instance, (PFNCALLBACK) procPtr, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
|
---|
104 | { MessageBox(0, "DDE failed to initialise", "GSInstall", MB_OK);
|
---|
105 | return false;
|
---|
106 | }
|
---|
107 | }
|
---|
108 | this->connected = true;
|
---|
109 | return true;
|
---|
110 | }
|
---|
111 |
|
---|
112 | bool gsProgramManager::disconnect()
|
---|
113 | { if (this->connected)
|
---|
114 | { if (this->platform->isExplorerShell())
|
---|
115 | { CoUninitialize();
|
---|
116 | }
|
---|
117 | else
|
---|
118 | { DdeUninitialize(instance);
|
---|
119 | }
|
---|
120 | }
|
---|
121 | this->connected = false;
|
---|
122 | return true;
|
---|
123 | }
|
---|
124 |
|
---|
125 | bool gsProgramManager::addProgramGroup(const char *groupName)
|
---|
126 | { //CreateGroup(groupName);
|
---|
127 | char buffer[256];
|
---|
128 |
|
---|
129 | if (this->platform->isExplorerShell())
|
---|
130 | { // add using shell controls
|
---|
131 | LPITEMIDLIST pidl;
|
---|
132 |
|
---|
133 | if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) == NOERROR)
|
---|
134 | { SHGetPathFromIDList(pidl, buffer);
|
---|
135 |
|
---|
136 | // Create the folder as required
|
---|
137 | FilePath *path = new FilePath(buffer, groupName);
|
---|
138 | if (!CreateDirectory((char *) path->cString(), NULL))
|
---|
139 | { // it probably existed already - if so skip it!
|
---|
140 | DWORD reason = GetLastError();
|
---|
141 | if (reason != ERROR_ALREADY_EXISTS)
|
---|
142 | { return false;
|
---|
143 | }
|
---|
144 | }
|
---|
145 | }
|
---|
146 | }
|
---|
147 | else
|
---|
148 | { // add using program manager DDE
|
---|
149 | sprintf(buffer, "[CreateGroup (%s)]", groupName);
|
---|
150 | if (!DDEShellCommand(this->instance, buffer))
|
---|
151 | { // flag error by returning false
|
---|
152 | return false;
|
---|
153 | }
|
---|
154 | }
|
---|
155 | return true;
|
---|
156 | }
|
---|
157 |
|
---|
158 | bool gsProgramManager::addIcon( const char *groupName, // group of the icon
|
---|
159 | const char *iconName, // name of the icon
|
---|
160 | const char *iconDestination, // destination file of the icon
|
---|
161 | const char *description) // the textual description
|
---|
162 | // of the icon (not usually displayed)
|
---|
163 | { bool reply = false;
|
---|
164 | char buffer[MAX_PATH];
|
---|
165 |
|
---|
166 | if (this->platform->isExplorerShell())
|
---|
167 | { // create item using the shell
|
---|
168 | LPITEMIDLIST pidl;
|
---|
169 | HRESULT hres;
|
---|
170 | IShellLink* psl;
|
---|
171 | FilePath * fullPath;
|
---|
172 |
|
---|
173 | if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
|
---|
174 | { return false;
|
---|
175 | }
|
---|
176 |
|
---|
177 | SHGetPathFromIDList(pidl, buffer);
|
---|
178 | fullPath = new FilePath(4, buffer, groupName, iconName, "!.lnk");
|
---|
179 |
|
---|
180 | // Get a pointer to the IShellLink interface.
|
---|
181 | hres = CoCreateInstance(CLSID_ShellLink, NULL,
|
---|
182 | CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl);
|
---|
183 | if (SUCCEEDED(hres))
|
---|
184 | { IPersistFile* ppf;
|
---|
185 |
|
---|
186 | // Set the path to the shortcut target, and add the
|
---|
187 | // description.
|
---|
188 | psl->SetPath(iconDestination);
|
---|
189 |
|
---|
190 | psl->SetDescription(description);
|
---|
191 |
|
---|
192 | // Query IShellLink for the IPersistFile interface for saving the
|
---|
193 | // shortcut in persistent storage.
|
---|
194 | hres = psl->QueryInterface(IID_IPersistFile, (void **) &ppf);
|
---|
195 |
|
---|
196 | if (SUCCEEDED(hres))
|
---|
197 | { WCHAR wsz[MAX_PATH];
|
---|
198 |
|
---|
199 | // Ensure that the string is ANSI.
|
---|
200 | MultiByteToWideChar(CP_ACP, 0, fullPath->cString(), -1, wsz, MAX_PATH);
|
---|
201 |
|
---|
202 | // store the link in the "persistent" file
|
---|
203 | reply = ppf->Save(wsz, TRUE);
|
---|
204 |
|
---|
205 | // release the persistent file handle
|
---|
206 | ppf->Release();
|
---|
207 | }
|
---|
208 | psl->Release();
|
---|
209 | }
|
---|
210 | }
|
---|
211 | else
|
---|
212 | { // Back to the dark ages with win 3.1!
|
---|
213 |
|
---|
214 | // ensure that the requisite group is active; the add icon command will
|
---|
215 | // use the active group.
|
---|
216 | sprintf(buffer, "[ShowGroup(%s,5)]", groupName);
|
---|
217 | if (!DDEShellCommand(this->instance, buffer))
|
---|
218 | { // TODO: articulate/determine possible errors; expand error handling
|
---|
219 | return false;
|
---|
220 | }
|
---|
221 |
|
---|
222 | // and now add the item itself to the active (given) group
|
---|
223 | sprintf(buffer, "[AddItem(%s,%s)]", iconDestination, iconName);
|
---|
224 | if (!DDEShellCommand(this->instance, buffer))
|
---|
225 | { // TODO: again work out what the problems could be
|
---|
226 | return false;
|
---|
227 | }
|
---|
228 | reply = true;
|
---|
229 | }
|
---|
230 | return reply;
|
---|
231 | }
|
---|
232 |
|
---|
233 | bool gsProgramManager::removeProgramGroup(const char *groupName)
|
---|
234 | { //CreateGroup(groupName);
|
---|
235 | char buffer[256];
|
---|
236 |
|
---|
237 | if (this->platform->isExplorerShell())
|
---|
238 | { // add using shell controls
|
---|
239 | LPITEMIDLIST pidl;
|
---|
240 |
|
---|
241 | if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) == NOERROR)
|
---|
242 | { SHGetPathFromIDList(pidl, buffer);
|
---|
243 |
|
---|
244 | // Create the folder as required
|
---|
245 | FilePath *path = new FilePath(buffer, groupName);
|
---|
246 | if (!RemoveDirectory((char *) path->cString()))
|
---|
247 | { // TODO: find cause of failure to remove
|
---|
248 | DWORD reason = GetLastError();
|
---|
249 | if (reason != 0)
|
---|
250 | { return false;
|
---|
251 | }
|
---|
252 | }
|
---|
253 | }
|
---|
254 | }
|
---|
255 | else
|
---|
256 | { // add using program manager DDE
|
---|
257 | sprintf(buffer, "[DeleteGroup (%s)]", groupName);
|
---|
258 | if (!DDEShellCommand(this->instance, buffer))
|
---|
259 | { // flag error by returning false
|
---|
260 | return false;
|
---|
261 | }
|
---|
262 | }
|
---|
263 | return true;
|
---|
264 | }
|
---|
265 |
|
---|
266 | bool gsProgramManager::removeIcon(const char *groupName, // group of the icon
|
---|
267 | const char *iconName) // name of the icon
|
---|
268 | { bool reply = false;
|
---|
269 | char buffer[MAX_PATH];
|
---|
270 |
|
---|
271 | if (this->platform->isExplorerShell())
|
---|
272 | { // create item using the shell
|
---|
273 | LPITEMIDLIST pidl;
|
---|
274 | HRESULT hres;
|
---|
275 | IShellLink* psl;
|
---|
276 | FilePath * fullPath;
|
---|
277 |
|
---|
278 | if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
|
---|
279 | { return false;
|
---|
280 | }
|
---|
281 |
|
---|
282 | SHGetPathFromIDList(pidl, buffer);
|
---|
283 | fullPath = new FilePath(4, buffer, groupName, iconName, "!.lnk");
|
---|
284 |
|
---|
285 | // TODO: delete file
|
---|
286 | }
|
---|
287 | else
|
---|
288 | { // Back to the dark ages with win 3.1!
|
---|
289 |
|
---|
290 | // ensure that the requisite group is active; the add icon command will
|
---|
291 | // use the active group.
|
---|
292 | sprintf(buffer, "[ShowGroup(%s,5)]", groupName);
|
---|
293 | if (!DDEShellCommand(this->instance, buffer))
|
---|
294 | { // TODO: articulate/determine possible errors; expand error handling
|
---|
295 | return false;
|
---|
296 | }
|
---|
297 |
|
---|
298 | // and now add the item itself to the active (given) group
|
---|
299 | sprintf(buffer, "[DeleteItem(%s)]", iconName);
|
---|
300 | if (!DDEShellCommand(this->instance, buffer))
|
---|
301 | { // TODO: again work out what the problems could be
|
---|
302 | return false;
|
---|
303 | }
|
---|
304 | }
|
---|
305 | return reply;
|
---|
306 | }
|
---|
307 |
|
---|
308 |
|
---|