source: trunk/gsinstaller/gsProgman.cpp@ 1475

Last change on this file since 1475 was 1475, checked in by cs025, 24 years ago

Updated sources with most of uninstall added

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