source: trunk/gsinstaller/gsProgman.cpp@ 1547

Last change on this file since 1547 was 1547, checked in by sjboddie, 24 years ago

An attempt to get compiling under gcc

  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
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
12extern 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 */
18HDDEDATA CALLBACK DdeCallBack(UINT uType, // transaction type
19 UINT uFmt, // clipboard data format
20 HCONV hconv, // handle to the conversation
21 HSZ hsz1, // handle to a string
22 HSZ hsz2, // handle to a string
23 HDDEDATA hdata, // handle to a global memory object
24 DWORD dwData1, // transaction-specific data
25 DWORD dwData2 // transaction-specific data
26 )
27{
28 return NULL;
29}
30
31 /**
32 * A private little function to do DDE activity
33 */
34bool DDEShellCommand(DWORD instance, char *command)
35{
36 HSZ serviceName;
37 HCONV conversation;
38 int commandLength;
39 HDDEDATA ddeData;
40 DWORD result;
41 bool reply = false;
42
43 // create DDE string from service request
44 serviceName = DdeCreateStringHandle(instance, "PROGMAN", CP_WINANSI);
45 if (serviceName == NULL)
46 {
47 /*char buffer[20];
48 sprintf(buffer, "%d %d", DdeGetLastError(instance), instance);
49 MessageBox(0, buffer, "GSInstall", MB_OK);*/
50 return FALSE;
51 }
52
53 // strike up a conversation with the DDE service
54 if ((conversation = DdeConnect(instance, serviceName, serviceName, NULL)) != NULL)
55 {
56 commandLength = lstrlen(command);
57
58 // send the message via DDE
59 // MessageBox(0, command, "Executing", MB_OK);
60 ddeData = DdeClientTransaction((LPBYTE) command, commandLength + 1,
61 conversation, NULL, CF_TEXT, XTYP_EXECUTE,
62 1000, &result);
63 // if our reply isn't NULL, it succeeded
64 reply = (ddeData != NULL);
65 if (reply == false)
66 { /*
67 char buffer[20];
68
69 sprintf(buffer, "%d", DdeGetLastError(instance));
70 MessageBox(0, buffer, "DDE Error", MB_OK);*/
71 }
72
73 // disconnect the conversation
74 DdeDisconnect(conversation);
75 }
76 else
77 {
78 MessageBox(0, "DDE Connect failed", "GSInstall", MB_OK);
79 }
80
81 // free DDE string
82 DdeFreeStringHandle(instance, serviceName);
83 return reply;
84}
85
86gsProgramManager::gsProgramManager(installManager &manager)
87 : installAgent(manager)
88{
89 this->platform = new gsPlatform();
90 this->connected = false;
91}
92
93void gsProgramManager::logAction(string actionName, string group)
94{
95 unInstallCommand command(actionName);
96 command.addParameter(group);
97 manager->storeCommand(command);
98}
99
100void gsProgramManager::logAction(string actionName, string group, string item, string parameter)
101{
102 unInstallCommand command(actionName);
103 command.addParameter(group);
104 command.addParameter(item);
105 command.addParameter(parameter);
106 manager->storeCommand(command);
107}
108
109bool gsProgramManager::undoAction(string actionName, stringArray &params)
110{
111 if (actionName == "ProgManCreateGroup")
112 {
113 this->removeProgramGroup(params[0]);
114 return true;
115 }
116 else if (actionName == "ProgManAddItem")
117 {
118 this->removeIcon(params[0], params[1]);
119 return true;
120 }
121 return false;
122}
123
124bool gsProgramManager::connect()
125{
126 HRESULT response;
127
128 if (this->platform->isExplorerShell())
129 {
130 // Initialise the shell connection
131 response = CoInitialize(NULL);
132 if (response < 0)
133 {
134 return false;
135 }
136 }
137 else
138 {
139 FARPROC procPtr;
140
141 procPtr = MakeProcInstance((FARPROC) DdeCallBack, app_instance);
142
143 instance = 0L;
144 if (DdeInitialize(&instance, (PFNCALLBACK) procPtr, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
145 {
146 MessageBox(0, "DDE failed to initialise", "GSInstall", MB_OK);
147 return false;
148 }
149 }
150 this->connected = true;
151 return true;
152}
153
154bool gsProgramManager::disconnect()
155{
156 if (this->connected)
157 {
158 if (this->platform->isExplorerShell())
159 {
160 CoUninitialize();
161 }
162 else
163 {
164 DdeUninitialize(instance);
165 }
166 }
167 this->connected = false;
168 return true;
169}
170
171bool gsProgramManager::addProgramGroup(string groupName)
172{
173 //CreateGroup(groupName);
174 char buffer[256];
175
176 if (this->platform->isExplorerShell())
177 {
178 // add using shell controls
179 LPITEMIDLIST pidl;
180
181 if (this->platform->isUserAdministrator())
182 {
183#if defined (__GNUC__)
184 // this is a hack as windows port of gcc doesn't have CSIDL_COMMON_PROGRAMS defined
185 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
186#else
187 if (SHGetSpecialFolderLocation(0, CSIDL_COMMON_PROGRAMS, &pidl) != NOERROR)
188#endif
189 {
190 return false;
191 }
192 }
193 else
194 {
195 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
196 {
197 return false;
198 }
199 }
200 SHGetPathFromIDList(pidl, buffer);
201
202 // Create the folder as required
203 FilePath *path = new FilePath(buffer, groupName);
204 if (!CreateDirectory((char *) path->cString(), NULL))
205 {
206 // it probably existed already - if so skip it!
207 DWORD reason = GetLastError();
208 if (reason != ERROR_ALREADY_EXISTS)
209 {
210 return false;
211 }
212 }
213 }
214 else
215 {
216 // add using program manager DDE
217 sprintf(buffer, "[CreateGroup (%s)]", groupName.c_str());
218 if (!DDEShellCommand(this->instance, buffer))
219 {
220 // flag error by returning false
221 return false;
222 }
223 }
224
225 this->logAction("ProgManCreateGroup", groupName);
226 return true;
227}
228
229bool gsProgramManager::addIcon(string groupName, // group of the icon
230 string iconName, // name of the icon
231 string iconDestination, // destination file of the icon
232 string description) // the textual description
233 // of the icon (not usually displayed)
234{
235 bool reply = false;
236 char buffer[MAX_PATH];
237
238 if (this->platform->isExplorerShell())
239 {
240 // create item using the shell
241 LPITEMIDLIST pidl;
242 HRESULT hres;
243 IShellLink* psl;
244 FilePath *fullPath;
245
246 if (this->platform->isUserAdministrator())
247 {
248#if defined (__GNUC__)
249 // this is a hack as windows port of gcc doesn't have CSIDL_COMMON_PROGRAMS defined
250 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
251#else
252 if (SHGetSpecialFolderLocation(0, CSIDL_COMMON_PROGRAMS, &pidl) != NOERROR)
253#endif
254
255 {
256 return false;
257 }
258 }
259 else
260 {
261 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
262 {
263 return false;
264 }
265 }
266
267 SHGetPathFromIDList(pidl, buffer);
268 fullPath = new FilePath(4, buffer, groupName.c_str(), iconName.c_str(), "!.lnk");
269
270 // check if the shortcut already exists then don't create this again
271 if (fullPath->exists())
272 {
273 delete fullPath;
274 return true;
275 }
276
277 // Get a pointer to the IShellLink interface.
278 hres = CoCreateInstance(CLSID_ShellLink, NULL,
279 CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl);
280 if (SUCCEEDED(hres))
281 {
282 IPersistFile* ppf;
283
284 // Set the path to the shortcut target, and add the
285 // description.
286 psl->SetPath(iconDestination.c_str());
287
288 psl->SetDescription(description.c_str());
289
290 // Query IShellLink for the IPersistFile interface for saving the
291 // shortcut in persistent storage.
292 hres = psl->QueryInterface(IID_IPersistFile, (void **) &ppf);
293
294 if (SUCCEEDED(hres))
295 {
296 WCHAR wsz[MAX_PATH];
297
298 // Ensure that the string is ANSI.
299 MultiByteToWideChar(CP_ACP, 0, fullPath->cString(), -1, wsz, MAX_PATH);
300
301 // store the link in the "persistent" file
302 reply = ppf->Save(wsz, TRUE);
303
304 // release the persistent file handle
305 ppf->Release();
306 }
307 psl->Release();
308 }
309 delete fullPath;
310 }
311 else
312 {
313 // Back to the dark ages with win 3.1!
314
315 // ensure that the requisite group is active; the add icon command will
316 // use the active group.
317 sprintf(buffer, "[ShowGroup(%s,5)]", groupName.c_str());
318 if (!DDEShellCommand(this->instance, buffer))
319 {
320 // TODO: articulate/determine possible errors; expand error handling
321 return false;
322 }
323
324 // and now add the item itself to the active (given) group
325 sprintf(buffer, "[AddItem(%s,%s)]", iconDestination.c_str(), iconName.c_str());
326 if (!DDEShellCommand(this->instance, buffer))
327 {
328 // TODO: again work out what the problems could be
329 return false;
330 }
331 reply = true;
332 }
333
334 if (reply)
335 {
336 this->logAction("ProgManAddItem", groupName, iconName, iconDestination);
337 }
338 return reply;
339}
340
341bool gsProgramManager::removeProgramGroup(string groupName)
342{
343 //CreateGroup(groupName);
344 char buffer[256];
345
346 if (this->platform->isExplorerShell())
347 {
348 // add using shell controls
349 LPITEMIDLIST pidl;
350
351 if (this->platform->isUserAdministrator())
352 {
353#if defined (__GNUC__)
354 // this is a hack as windows port of gcc doesn't have CSIDL_COMMON_PROGRAMS defined
355 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
356#else
357 if (SHGetSpecialFolderLocation(0, CSIDL_COMMON_PROGRAMS, &pidl) != NOERROR)
358#endif
359 {
360 return false;
361 }
362 }
363 else
364 {
365 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
366 {
367 return false;
368 }
369 }
370 SHGetPathFromIDList(pidl, buffer);
371
372 // Create the folder as required
373 FilePath *path = new FilePath(buffer, groupName);
374 if (!RemoveDirectory((char *) path->cString()))
375 {
376 // TODO: find cause of failure to remove
377 DWORD reason = GetLastError();
378 if (reason != 0)
379 {
380 return false;
381 }
382 }
383 }
384 else
385 {
386 // add using program manager DDE
387 sprintf(buffer, "[DeleteGroup (%s)]", groupName.c_str());
388 if (!DDEShellCommand(this->instance, buffer))
389 {
390 // flag error by returning false
391 return false;
392 }
393 }
394 return true;
395}
396
397bool gsProgramManager::removeIcon(string groupName, // group of the icon
398 string iconName) // name of the icon
399{
400 bool reply = false;
401 char buffer[MAX_PATH];
402
403 if (this->platform->isExplorerShell())
404 {
405 // create item using the shell
406 LPITEMIDLIST pidl;
407 // HRESULT hres;
408 // IShellLink * psl;
409 FilePath * fullPath;
410
411 // if the user is adminstrator, take the folder from the common programs folder
412 // (in the "All Users" profile)
413 if (this->platform->isUserAdministrator())
414 {
415#if defined (__GNUC__)
416 // this is a hack as windows port of gcc doesn't have CSIDL_COMMON_PROGRAMS defined
417 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
418#else
419 if (SHGetSpecialFolderLocation(0, CSIDL_COMMON_PROGRAMS, &pidl) != NOERROR)
420#endif
421 {
422 return false;
423 }
424 }
425 // otherwise get it from the user's own programs folder in their profile
426 else
427 {
428 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
429 {
430 return false;
431 }
432 }
433
434 // get path of folder from shell
435 SHGetPathFromIDList(pidl, buffer);
436
437 // delete file
438 fullPath = new FilePath(4, buffer, groupName.c_str(), iconName.c_str(), "!.lnk");
439 if (!DeleteFile(fullPath->cString()))
440 {
441 reply = false;
442 }
443 delete fullPath;
444 }
445 else
446 {
447 // Back to the dark ages with win 3.1!
448
449 // ensure that the requisite group is active; the add icon command will
450 // use the active group.
451 sprintf(buffer, "[ShowGroup(%s,5)]", groupName.c_str());
452 if (!DDEShellCommand(this->instance, buffer))
453 {
454 // TODO: articulate/determine possible errors; expand error handling
455 return false;
456 }
457
458 // and now add the item itself to the active (given) group
459 sprintf(buffer, "[DeleteItem(%s)]", iconName.c_str());
460 if (!DDEShellCommand(this->instance, buffer))
461 {
462 // TODO: again work out what the problems could be
463 return false;
464 }
465 }
466 return reply;
467}
Note: See TracBrowser for help on using the repository browser.