source: trunk/gsinstaller/gsProgman.cpp@ 1537

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

Changes to get compiling on VC++ and gcc

  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 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(
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 */
34bool 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
82gsProgramManager::gsProgramManager(installManager &manager)
83 : installAgent(manager)
84{ this->platform = new gsPlatform();
85 this->connected = false;
86}
87
88void gsProgramManager::logAction(string actionName, string group)
89{ unInstallCommand command(actionName);
90 command.addParameter(group);
91 manager->storeCommand(command);
92}
93
94void gsProgramManager::logAction(string actionName, string group, string item, string parameter)
95{ unInstallCommand command(actionName);
96 command.addParameter(group);
97 command.addParameter(item);
98 command.addParameter(parameter);
99 manager->storeCommand(command);
100}
101
102bool gsProgramManager::undoAction(string actionName, stringArray &params)
103{ if (actionName == "ProgManCreateGroup")
104 { this->removeProgramGroup(params[0]);
105 return true;
106 }
107 else if (actionName == "ProgManAddItem")
108 { this->removeIcon(params[0], params[1]);
109 return true;
110 }
111 return false;
112}
113
114bool gsProgramManager::connect()
115{ HRESULT response;
116
117 if (this->platform->isExplorerShell())
118 { // Initialise the shell connection
119 response = CoInitialize(NULL);
120 if (response < 0)
121 { return false;
122 }
123 }
124 else
125 { FARPROC procPtr;
126
127 procPtr = MakeProcInstance((FARPROC) DdeCallBack, app_instance);
128
129 instance = 0L;
130 if (DdeInitialize(&instance, (PFNCALLBACK) procPtr, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
131 { MessageBox(0, "DDE failed to initialise", "GSInstall", MB_OK);
132 return false;
133 }
134 }
135 this->connected = true;
136 return true;
137}
138
139bool gsProgramManager::disconnect()
140{ if (this->connected)
141 { if (this->platform->isExplorerShell())
142 { CoUninitialize();
143 }
144 else
145 { DdeUninitialize(instance);
146 }
147 }
148 this->connected = false;
149 return true;
150}
151
152bool gsProgramManager::addProgramGroup(string groupName)
153{ //CreateGroup(groupName);
154 char buffer[256];
155
156 if (this->platform->isExplorerShell())
157 { // add using shell controls
158 LPITEMIDLIST pidl;
159
160 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) == NOERROR)
161 { SHGetPathFromIDList(pidl, buffer);
162
163 // Create the folder as required
164 FilePath *path = new FilePath(buffer, groupName);
165 if (!CreateDirectory((char *) path->cString(), NULL))
166 { // it probably existed already - if so skip it!
167 DWORD reason = GetLastError();
168 if (reason != ERROR_ALREADY_EXISTS)
169 { return false;
170 }
171 }
172 }
173 }
174 else
175 { // add using program manager DDE
176 sprintf(buffer, "[CreateGroup (%s)]", groupName.c_str());
177 if (!DDEShellCommand(this->instance, buffer))
178 { // flag error by returning false
179 return false;
180 }
181 }
182
183 this->logAction("ProgManCreateGroup", groupName);
184 return true;
185}
186
187bool gsProgramManager::addIcon( string groupName, // group of the icon
188 string iconName, // name of the icon
189 string iconDestination, // destination file of the icon
190 string description) // the textual description
191 // of the icon (not usually displayed)
192{ bool reply = false;
193 char buffer[MAX_PATH];
194
195 if (this->platform->isExplorerShell())
196 { // create item using the shell
197 LPITEMIDLIST pidl;
198 HRESULT hres;
199 IShellLink* psl;
200 FilePath * fullPath;
201
202 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
203 { return false;
204 }
205
206 SHGetPathFromIDList(pidl, buffer);
207 fullPath = new FilePath(4, buffer, groupName.c_str(), iconName.c_str(), ".lnk");
208
209 // check if the shortcut already exists then don't create this again
210 if (fullPath->exists())
211 { delete fullPath;
212 return true;
213 }
214
215 // Get a pointer to the IShellLink interface.
216 hres = CoCreateInstance(CLSID_ShellLink, NULL,
217 CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl);
218 if (SUCCEEDED(hres))
219 { IPersistFile* ppf;
220
221 // Set the path to the shortcut target, and add the
222 // description.
223 psl->SetPath(iconDestination.c_str());
224
225 psl->SetDescription(description.c_str());
226
227 // Query IShellLink for the IPersistFile interface for saving the
228 // shortcut in persistent storage.
229 hres = psl->QueryInterface(IID_IPersistFile, (void **) &ppf);
230
231 if (SUCCEEDED(hres))
232 { WCHAR wsz[MAX_PATH];
233
234 // Ensure that the string is ANSI.
235 MultiByteToWideChar(CP_ACP, 0, fullPath->cString(), -1, wsz, MAX_PATH);
236
237 // store the link in the "persistent" file
238 reply = ppf->Save(wsz, TRUE);
239
240 // release the persistent file handle
241 ppf->Release();
242 }
243 psl->Release();
244 }
245 delete fullPath;
246 }
247 else
248 { // Back to the dark ages with win 3.1!
249
250 // ensure that the requisite group is active; the add icon command will
251 // use the active group.
252 sprintf(buffer, "[ShowGroup(%s,5)]", groupName.c_str());
253 if (!DDEShellCommand(this->instance, buffer))
254 { // TODO: articulate/determine possible errors; expand error handling
255 return false;
256 }
257
258 // and now add the item itself to the active (given) group
259 sprintf(buffer, "[AddItem(%s,%s)]", iconDestination.c_str(), iconName.c_str());
260 if (!DDEShellCommand(this->instance, buffer))
261 { // TODO: again work out what the problems could be
262 return false;
263 }
264 reply = true;
265 }
266
267 if (reply)
268 { this->logAction("ProgManAddItem", groupName, iconName, iconDestination);
269 }
270 return reply;
271}
272
273bool gsProgramManager::removeProgramGroup(string groupName)
274{ //CreateGroup(groupName);
275 char buffer[256];
276
277 if (this->platform->isExplorerShell())
278 { // add using shell controls
279 LPITEMIDLIST pidl;
280
281 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) == NOERROR)
282 { SHGetPathFromIDList(pidl, buffer);
283
284 // Create the folder as required
285 FilePath *path = new FilePath(buffer, groupName);
286 if (!RemoveDirectory((char *) path->cString()))
287 { // TODO: find cause of failure to remove
288 DWORD reason = GetLastError();
289 if (reason != 0)
290 { return false;
291 }
292 }
293 }
294 }
295 else
296 { // add using program manager DDE
297 sprintf(buffer, "[DeleteGroup (%s)]", groupName.c_str());
298 if (!DDEShellCommand(this->instance, buffer))
299 { // flag error by returning false
300 return false;
301 }
302 }
303 return true;
304}
305
306bool gsProgramManager::removeIcon(string groupName, // group of the icon
307 string iconName) // name of the icon
308{ bool reply = false;
309 char buffer[MAX_PATH];
310
311 if (this->platform->isExplorerShell())
312 { // create item using the shell
313 LPITEMIDLIST pidl;
314 HRESULT hres;
315 IShellLink* psl;
316 FilePath * fullPath;
317
318 if (SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &pidl) != NOERROR)
319 { return false;
320 }
321
322 // get path of folder from shell
323 SHGetPathFromIDList(pidl, buffer);
324
325 // delete file
326 fullPath = new FilePath(4, buffer, groupName.c_str(), iconName.c_str(), "!.lnk");
327 if (!DeleteFile(fullPath->cString()))
328 { reply = false;
329 }
330 delete fullPath;
331 }
332 else
333 { // Back to the dark ages with win 3.1!
334
335 // ensure that the requisite group is active; the add icon command will
336 // use the active group.
337 sprintf(buffer, "[ShowGroup(%s,5)]", groupName.c_str());
338 if (!DDEShellCommand(this->instance, buffer))
339 { // TODO: articulate/determine possible errors; expand error handling
340 return false;
341 }
342
343 // and now add the item itself to the active (given) group
344 sprintf(buffer, "[DeleteItem(%s)]", iconName.c_str());
345 if (!DDEShellCommand(this->instance, buffer))
346 { // TODO: again work out what the problems could be
347 return false;
348 }
349 }
350 return reply;
351}
Note: See TracBrowser for help on using the repository browser.