This source file includes following definitions.
- DdeCallback
- add_registry
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 #define DEFER_MS_W32_H
39 #include <config.h>
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <malloc.h>
44
45
46 #ifndef MINGW_W64
47 # ifdef _WIN32_IE
48 # undef _WIN32_IE
49 # endif
50 #define _WIN32_IE 0x0400
51 #endif
52
53 #define COBJMACROS 1
54
55 #include <windows.h>
56 #include <shlobj.h>
57 #include <ddeml.h>
58
59 #ifndef OLD_PATHS
60 #include "../src/epaths.h"
61 #endif
62
63 HDDEDATA CALLBACK DdeCallback (UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD_PTR,
64 DWORD_PTR);
65
66 HDDEDATA CALLBACK
67 DdeCallback (UINT uType, UINT uFmt, HCONV hconv,
68 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
69 DWORD_PTR dwData1, DWORD_PTR dwData2)
70 {
71 return ((HDDEDATA) NULL);
72 }
73
74 #define DdeCommand(str) \
75 DdeClientTransaction ((LPBYTE)str, strlen (str)+1, conversation, (HSZ)NULL, \
76 CF_TEXT, XTYP_EXECUTE, 30000, NULL)
77
78 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
79 #define REG_APP_PATH \
80 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\emacs.exe"
81
82 static struct entry
83 {
84 const char *name;
85 const char *value;
86 }
87 env_vars[] =
88 {
89 #ifdef OLD_PATHS
90 {"emacs_dir", NULL},
91 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp"},
92 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
93 {"EMACSDATA", "%emacs_dir%/etc"},
94 {"EMACSPATH", "%emacs_dir%/bin"},
95
96
97
98 {"EMACSDOC", "%emacs_dir%/etc"},
99 {"TERM", "cmd"}
100 #else
101 {"emacs_dir", NULL},
102 {"EMACSLOADPATH", PATH_SITELOADSEARCH ";" PATH_LOADSEARCH},
103 {"SHELL", PATH_EXEC "/cmdproxy.exe"},
104 {"EMACSDATA", PATH_DATA},
105 {"EMACSPATH", PATH_EXEC},
106
107
108
109 {"EMACSDOC", PATH_DOC},
110 {"TERM", "cmd"}
111 #endif
112 };
113
114 static void
115 add_registry (const char *path)
116 {
117 HKEY hrootkey = NULL;
118 int i;
119
120
121
122
123
124
125
126
127
128
129 if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, REG_APP_PATH, 0, NULL,
130 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
131 &hrootkey, NULL) == ERROR_SUCCESS)
132 {
133 int len;
134 char *emacs_path;
135
136 len = strlen (path) + 15;
137 emacs_path = (char *) alloca (len);
138 sprintf (emacs_path, "%s\\bin\\emacs.exe", path);
139
140 RegSetValueEx (hrootkey, NULL, 0, REG_EXPAND_SZ, emacs_path, len);
141 RegCloseKey (hrootkey);
142 }
143
144
145
146
147
148
149
150
151
152 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0,
153 KEY_WRITE | KEY_QUERY_VALUE, &hrootkey) != ERROR_SUCCESS
154 && RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0,
155 KEY_WRITE | KEY_QUERY_VALUE, &hrootkey) != ERROR_SUCCESS)
156 return;
157
158 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
159 {
160 const char * value = env_vars[i].value ? env_vars[i].value : path;
161
162
163 if (RegQueryValueEx (hrootkey, env_vars[i].name, NULL,
164 NULL, NULL, NULL) == ERROR_SUCCESS)
165 RegSetValueEx (hrootkey, env_vars[i].name, 0, REG_EXPAND_SZ,
166 value, lstrlen (value) + 1);
167 }
168
169 RegCloseKey (hrootkey);
170 }
171
172 int
173 main (int argc, char *argv[])
174 {
175 char start_folder[MAX_PATH + 1];
176 int shortcuts_created = 0;
177 int com_available = 1;
178 char modname[MAX_PATH];
179 const char *prog_name;
180 const char *emacs_path;
181 char *p;
182 int quiet = 0;
183 HRESULT result;
184 IShellLinkA *shortcut;
185
186
187
188 if (argc > 1
189 && (argv[1][0] == '/' || argv[1][0] == '-')
190 && argv[1][1] == 'q')
191 {
192 quiet = 1;
193 --argc;
194 ++argv;
195 }
196
197 if (argc > 1)
198 emacs_path = argv[1];
199 else
200 {
201 if (!GetModuleFileName (NULL, modname, MAX_PATH) ||
202 (p = strrchr (modname, '\\')) == NULL)
203 {
204 fprintf (stderr, "fatal error");
205 exit (1);
206 }
207 *p = 0;
208
209
210 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
211 {
212 *p = 0;
213 emacs_path = modname;
214 }
215 else
216 {
217 fprintf (stderr, "usage: addpm emacs_path\n");
218 exit (1);
219 }
220
221
222 if (!quiet)
223 {
224 int result;
225
226 const char install_msg[] = "Install Emacs at %s?\n";
227 char msg[ MAX_PATH + sizeof (install_msg) ];
228 sprintf (msg, install_msg, emacs_path);
229 result = MessageBox (NULL, msg, "Install Emacs",
230 MB_OKCANCEL | MB_ICONQUESTION);
231 if (result != IDOK)
232 {
233 fprintf (stderr, "Install canceled\n");
234 exit (1);
235 }
236 }
237 }
238
239 add_registry (emacs_path);
240 prog_name = "runemacs.exe";
241
242
243
244 if (!SUCCEEDED (CoInitialize (NULL))
245 || !SUCCEEDED (CoCreateInstance (&CLSID_ShellLink, NULL,
246 CLSCTX_INPROC_SERVER, &IID_IShellLinkA,
247 (void **) &shortcut)))
248 {
249 com_available = 0;
250 }
251
252 if (com_available
253 && SHGetSpecialFolderPath (NULL, start_folder, CSIDL_COMMON_PROGRAMS, 0))
254 {
255 if (strlen (start_folder) < (MAX_PATH - 20))
256 {
257 strcat (start_folder, "\\Gnu Emacs");
258 if (CreateDirectory (start_folder, NULL)
259 || GetLastError () == ERROR_ALREADY_EXISTS)
260 {
261 char full_emacs_path[MAX_PATH + 1];
262 IPersistFile *lnk;
263 strcat (start_folder, "\\Emacs.lnk");
264 sprintf (full_emacs_path, "%s\\bin\\%s", emacs_path, prog_name);
265 IShellLinkA_SetPath (shortcut, full_emacs_path);
266 IShellLinkA_SetDescription (shortcut, "GNU Emacs");
267 result = IShellLinkA_QueryInterface (shortcut, &IID_IPersistFile,
268 (void **) &lnk);
269 if (SUCCEEDED (result))
270 {
271 wchar_t unicode_path[MAX_PATH];
272 MultiByteToWideChar (CP_ACP, 0, start_folder, -1,
273 unicode_path, MAX_PATH);
274 if (SUCCEEDED (IPersistFile_Save (lnk, unicode_path, TRUE)))
275 shortcuts_created = 1;
276 IPersistFile_Release (lnk);
277 }
278 }
279 }
280 }
281
282 if (!shortcuts_created && com_available
283 && SHGetSpecialFolderPath (NULL, start_folder, CSIDL_PROGRAMS, 0))
284 {
285
286 if (strlen (start_folder) < (MAX_PATH - 20))
287 {
288 strcat (start_folder, "\\Gnu Emacs");
289 if (CreateDirectory (start_folder, NULL)
290 || GetLastError () == ERROR_ALREADY_EXISTS)
291 {
292 char full_emacs_path[MAX_PATH + 1];
293 IPersistFile *lnk;
294 strcat (start_folder, "\\Emacs.lnk");
295 sprintf (full_emacs_path, "%s\\bin\\%s", emacs_path, prog_name);
296 IShellLinkA_SetPath (shortcut, full_emacs_path);
297 IShellLinkA_SetDescription (shortcut, "GNU Emacs");
298 result = IShellLinkA_QueryInterface (shortcut, &IID_IPersistFile,
299 (void **) &lnk);
300 if (SUCCEEDED (result))
301 {
302 wchar_t unicode_path[MAX_PATH];
303 MultiByteToWideChar (CP_ACP, 0, start_folder, -1,
304 unicode_path, MAX_PATH);
305 if (SUCCEEDED (IPersistFile_Save (lnk, unicode_path, TRUE)))
306 shortcuts_created = 1;
307 IPersistFile_Release (lnk);
308
309 }
310 }
311 }
312 }
313
314 if (com_available)
315 IShellLinkA_Release (shortcut);
316
317
318 CoUninitialize ();
319
320
321 if (!shortcuts_created)
322 {
323 DWORD dde = 0;
324 HCONV conversation;
325 HSZ progman;
326 char add_item[MAX_PATH*2 + 100];
327
328 DdeInitialize (&dde, (PFNCALLBACK) DdeCallback, APPCMD_CLIENTONLY, 0);
329 progman = DdeCreateStringHandle (dde, "PROGMAN", CP_WINANSI);
330 conversation = DdeConnect (dde, progman, progman, NULL);
331 if (conversation)
332 {
333 DdeCommand ("[CreateGroup (\"Gnu Emacs\")]");
334 DdeCommand ("[ReplaceItem (Emacs)]");
335 sprintf (add_item, "[AddItem (\"%s\\bin\\%s\", Emacs)]",
336 emacs_path, prog_name);
337 DdeCommand (add_item);
338
339 DdeDisconnect (conversation);
340 }
341
342 DdeFreeStringHandle (dde, progman);
343 DdeUninitialize (dde);
344 }
345
346 return 0;
347 }