root/trunk/nt/install.c

Revision 4013, 15.1 kB (checked in by fujii, 3 years ago)

install.exe registers shortcuts to desktop and quick launch bar.
Add two options (-d and -q) to install.exe.
Fix ticket:154.

* makefile.mw32-in ($(BLD)/install.exe): Add import libraries.

* nmake.mw32.defs (OLE32): New variable.
(UUID): Ditto.

* gmake.mw32.defs (OLE32): New variable.
(UUID): Ditto.

* install.c (make_shortcut): New function.
(register_to_quicklaunch): Ditto.
(register_to_desktop): Ditto.
(register_to_shell): call make_shortcut instead of using DDE.
(main): add two options (-d and -q) and shortcuts to Desktop and
Quick Launch.

  • Property svn:eol-style set to native
Line 
1 /* Meadow Install Program */
2 #include <windows.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <stdarg.h>
6 #include <io.h>
7 #include <direct.h>
8 #include <mbstring.h>
9 #include <shlobj.h>
10
11 #include "../src/mw32reg.h"
12
13 /* alias old names */
14 #if _MSC_VER >= 1300
15 #define stricmp _stricmp
16 #define access _access
17 #define chdir _chdir
18 #endif
19
20 #ifndef CSIDL_COMMON_APPDATA
21 #define CSIDL_COMMON_APPDATA 0x0023
22 #endif
23
24 #define MEADOW_SHORTCUT_FILENAME "Meadow3.lnk"
25
26 LPCTSTR meadow_version_string = MEADOW;
27 LPCTSTR meadow_version_root = REG_VERSION_ROOT;
28 LPCTSTR meadow_version_env_root = REG_VERSION_ENV_ROOT;
29
30 int w32_platform_id = -1;       /* 0=WinNT/2000/XP, 1=Win9x, -1=(unknown) */
31 int codepage;
32 int verbose_flag = 0;           /* 0...normal, 1...verbose */
33
34 typedef struct slmessage
35 {
36   int cp;
37   unsigned char *message;
38 } slmessage;
39
40 /* US CP is 437,.... -1 must be last entry. It is default...*/
41
42 #define ENGLISH -1
43 #define NIHONGO 932
44
45 slmessage access_denied[] =
46 {
47 #ifndef __MINGW32__
48   {NIHONGO, "ƒAƒNƒZƒX‚ª‹‘”Û‚³‚ê‚Ü‚µ‚œB\n"
49    "AdministratorŒ ŒÀ‚ÅŽÀs‚µ‚Ä‚­‚Ÿ‚³‚¢B\n"},
50 #endif
51   {ENGLISH, "Access denied.\n"
52    "Run this program with administrator privilege."}
53 };
54 slmessage undetect_error[] =
55 {
56 #ifndef __MINGW32__
57   {NIHONGO, "ŒŽˆö•s–Ÿ‚̃VƒXƒeƒ€ƒGƒ‰[B\n"},
58 #endif
59   {ENGLISH, "Undetected system error.\n"},
60 };
61 slmessage usage[] =
62 {
63   {ENGLISH, "Usage: install [-s] [-r] [-h dir] [-v]\n"
64    "        -q          do not add shortcut to Quick Launch.\n"
65    "        -d          do not add shortcut to Desktop.\n"
66    "        -s          do not add shortcut to Start Menu.\n"
67    "        -r          remove information from Registry Database.\n"
68    "        -h dir      specify home directory name.\n"
69    "        -v          verbose mode (for debug).\n"},
70 };
71 slmessage lt_check_error[] =
72 {
73 #ifndef __MINGW32__
74   {NIHONGO, "ƒA[ƒJƒCƒu‚Ì“WŠJ‚ÉŽž”s‚µ‚Ä‚¢‚Ü‚·B\n"
75    "INSTALL.Meadow ‚ÌWinZip‚Ì’ˆÓ“_‚ð—Ç‚­“Ç‚ñ‚Å‚­‚Ÿ‚³‚¢B\n"},
76 #endif
77   {ENGLISH, "Some files not extracted correctly from the archive.\n"
78    "Read the description about WinZip in INSTALL.Meadow.\n"},
79 };
80 slmessage lfn_check_error[] =
81 {
82 #ifndef __MINGW32__
83   {NIHONGO, "ƒA[ƒJƒCƒu‚Ì“WŠJ‚ÉŽž”s‚µ‚Ä‚¢‚Ü‚·B\n"
84    "Long File Name‚ÌŽg‚Š‚étar & gzip ‚ðŽg‚Á‚ĉº‚³‚¢B\n"},
85 #endif
86   {ENGLISH, "Some files not extracted correctly from the archive.\n"
87    "Use tar & gzip which can handle Long File Names properly.\n"},
88 };
89 slmessage pf_error[] =
90 {
91 #ifndef __MINGW32__
92   {NIHONGO, "‚±‚̃vƒƒOƒ‰ƒ€‚ÍWindows 95/98/Me/NT/2000‚ł̂ݓ®ì‚µ‚Ü‚·B\n"},
93 #endif
94   {ENGLISH, "This program can run only on Windows 95/98/Me/NT/2000.\n"},
95 };
96 slmessage illegal_comspec[] =
97 {
98 #ifndef __MINGW32__
99   {NIHONGO, "ƒVƒXƒeƒ€‚ªWindows NTŒn‚Å‚ ‚é‚̂ɁAŠÂ‹«•ϐ”COMSPEC‚ÉCOMMAND.COM‚ªŽw’肳‚ê‚Ä‚¢‚é‰Â”\«‚ª‚ ‚è‚Ü‚·BAUTOEXEC.BAT“™‚ÅCOMSPEC‚ªŽw’肵‚Ä‚ ‚éê‡A‚»‚Ì‹Lq‚ðíœ‚µ‚Ä‚­‚Ÿ‚³‚¢B\n"},
100 #endif
101   {ENGLISH, "This system is Windows NT, but environment variable COMSPEC may point to COMMAND.COM.  If COMSPEC is specified in AUTOEXEC.BAT and etc, please remove it.\n"},
102 };
103 slmessage no_comspec[] =
104 {
105 #ifndef __MINGW32__
106   {NIHONGO, "ŠÂ‹«•ϐ”COMSPEC‚ª’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñB\n"},
107 #endif
108   {ENGLISH, "Environment variable COMSPEC is not defined.\n"},
109 };
110 slmessage nd_homedrive[] =
111 {
112 #ifndef __MINGW32__
113   {NIHONGO, "HOMEDRIVE‚ª’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñB\n"},
114 #endif
115   {ENGLISH, "HOMEDRIVE is not defined. \n"},
116 };
117 slmessage nd_homepath[] =
118 {
119 #ifndef __MINGW32__
120   {NIHONGO, "HOMEPATH‚ª’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñB\n"},
121 #endif
122   {ENGLISH, "HOMEPATH is not defined. \n"},
123 };
124 slmessage nd_homedir[] =
125 {
126 #ifndef __MINGW32__
127   {NIHONGO, "ŠÂ‹«•ϐ”HOME‚ªÝ’è‚Å‚«‚Ü‚¹‚ñB\n"},
128 #endif
129   {ENGLISH, "Cannot set an environment variable HOME. \n"},
130 };
131 slmessage home_prompt[] =
132 {
133 #ifndef __MINGW32__
134   {NIHONGO, "Meadow‚ª.emacsƒtƒ@ƒCƒ‹‚ð“ǂݍž‚ÞƒfƒBƒŒƒNƒgƒŠ‚ðŽw’肵‚Ä‚­‚Ÿ‚³‚¢B\n"
135    "‰œ‚àÝ’肵‚È‚¢ê‡‚́AMeadow‚͈ȉº‚̃fƒBƒŒƒNƒgƒŠ‚É‘¶Ý‚·‚é.emacsƒtƒ@ƒCƒ‹‚ð“ǂݍž‚݂܂·B\n"},
136 #endif
137   {ENGLISH, "Enter the directory which Meadow read .emacs file from.\n"
138    "If you do not specify, Meadow reads .emacs file in following directory.\n"},
139 };
140 slmessage quicklaunch_not_found[] =
141 {
142 #ifndef __MINGW32__
143   {NIHONGO, "Quick Launch ƒfƒBƒŒƒNƒgƒŠ‚ª‘¶Ý‚µ‚Ü‚¹‚ñB"
144    "ƒNƒCƒbƒN‹N“®ƒo[‚ւ̃Vƒ‡[ƒgƒJƒbƒg“o˜^‚ÍŽæ‚èŽ~‚߂܂µ‚œB\n"},
145 #endif
146   {ENGLISH, "Quick Launch folder is not found. "
147    "Registration to Quick Launch is cancelled.\n"},
148 };
149 void slmessage_fprintf(int lang, FILE *stream, slmessage* slfmt, ...)
150 {
151   va_list va;
152
153   va_start(va, slfmt);
154   for (;!(slfmt->cp == lang || slfmt->cp == -1);slfmt++);
155   vfprintf(stream, slfmt->message, va);
156   va_end(va);
157 }
158
159 #define MULE_CLASS ""
160
161 void error_op(int errorflag)
162 {
163   if (errorflag != ERROR_SUCCESS){
164     switch(errorflag) {
165     case ERROR_ACCESS_DENIED:
166       slmessage_fprintf(codepage, stderr, access_denied);
167       break;
168     default:
169       slmessage_fprintf(codepage, stderr, undetect_error);
170       break;
171     }
172     exit(100);
173   }
174   return;
175 }
176
177 void error_usage(void)
178 {
179   fprintf(stderr, "installer for %s\n", MEADOW_VERSION_STRING);
180   slmessage_fprintf(codepage, stderr, usage);
181   exit(1);
182 }
183
184 void init_current_environment()
185 {
186   int version;
187
188   codepage = GetConsoleCP();
189
190   version = GetVersion();
191   if ( 0 == (version & 0x80000000) )
192     w32_platform_id = 0;
193   else if ((version & 0xC0000000) == 0xC0000000)
194     w32_platform_id = 1;
195   else {
196     slmessage_fprintf(codepage, stderr, pf_error);
197     exit(1);
198   }
199 }
200
201 HKEY create_key(HKEY hrootkey, LPCTSTR entry)
202 {
203   HKEY hkey;
204   DWORD result;
205   int errorflag;
206
207   errorflag = RegCreateKeyEx(hrootkey, entry,
208                              0, MULE_CLASS, REG_OPTION_NON_VOLATILE,
209                              KEY_WRITE, NULL, &hkey, &result);
210
211   error_op(errorflag);
212
213   return hkey;
214 }
215
216 void check_files(unsigned char *mule_root)
217 {
218   unsigned char buf[MAX_PATH];
219   FILE *handle;
220   int data, flag;
221
222   sprintf(buf, "%slisp\\mw32scroll.elc", mule_root);
223   flag = access(buf, 0);
224   if (flag != 0) {
225     if (verbose_flag)
226       perror(buf);
227     slmessage_fprintf(codepage, stderr, lfn_check_error);
228     exit(100);
229   }
230   sprintf(buf, "%slisp\\loaddefs.el", mule_root);
231   handle = fopen(buf, "rb");
232   while ((data = fgetc(handle)) != EOF) {
233     if (data == '\n') break;
234     if (data == '\r') {
235       slmessage_fprintf(codepage, stderr, lt_check_error);
236       exit(100);
237     }
238   }
239   return;
240 }
241
242 void set_value(HKEY hkey, unsigned char *name, unsigned char *value)
243 {
244   int errorflag;
245
246   errorflag = RegSetValueEx (hkey, name, 0, REG_SZ,
247                              value, lstrlen (value) + 1);
248   error_op(errorflag);
249 }
250
251 void set_value_path(HKEY hkey,
252                     unsigned char *name,
253                     unsigned char *dir_name,
254                     unsigned char *subdir)
255 {
256   unsigned char full_name[MAX_PATH];
257   strcpy(full_name, dir_name);
258   strcat(full_name, subdir);
259   set_value(hkey, name, full_name);
260 }
261
262 void get_root(unsigned char *program, unsigned char *result)
263 {
264   unsigned char dir_name[_MAX_DIR];
265   unsigned char drive_name[_MAX_DRIVE];
266   unsigned char file_name[_MAX_FNAME];
267   unsigned char ext_name[_MAX_EXT];
268
269   _splitpath(program, drive_name, dir_name, file_name, ext_name);
270
271   sprintf(result, "%s%s", drive_name, dir_name);
272 }
273
274 void get_shell_name(unsigned char *result)
275 {
276   unsigned char dir_name[_MAX_DIR];
277   unsigned char drive_name[_MAX_DRIVE];
278   unsigned char file_name[_MAX_FNAME];
279   unsigned char ext_name[_MAX_EXT];
280   unsigned char *shell_name;
281
282 #if 0
283   shell_name = getenv("COMSPEC");
284   if (!shell_name) {
285     if (w32_platform_id == 1)
286       strcpy(result, "cmdproxy");
287     else
288       strcpy(result, "cmdproxy");
289   } else {
290     _splitpath(shell_name, drive_name, dir_name, file_name, ext_name);
291     sprintf(result, "%s%s", file_name, ext_name);
292   }
293 #else
294   shell_name = getenv("COMSPEC");
295   if (shell_name){
296     /* if COMSPEC is specified, system is NT and shell_name has
297        "command.com" */
298     if (w32_platform_id == 0){
299       _splitpath(shell_name, drive_name, dir_name, file_name, ext_name);
300       if (stricmp(ext_name, ".COM") == 0){
301         slmessage_fprintf(codepage, stdout, illegal_comspec);
302         exit(100);
303       }
304     }
305   } else {
306     slmessage_fprintf(codepage, stdout, no_comspec);
307     exit(100);
308   }
309   strcpy(result, "cmdproxy");
310 #endif
311 }
312
313 void set_registry_data(char *main_root,
314                        char *shell_name,
315                        char *home_dir)
316 {
317   HKEY hkey;
318   TCHAR tmpstr[MAX_PATH];
319   unsigned char buffer[2048];
320   unsigned char main_top_root[MAX_PATH];
321   int i;
322
323   sprintf(tmpstr, meadow_version_env_root, meadow_version_string);
324
325   i = strlen(main_root) - 2;
326   for (;i >= 0;i--) if (main_root[i] == '\\') break;
327
328   if (i > 0)
329     {
330       memcpy(main_top_root, main_root, i + 1);
331       main_top_root[i + 1] = '\0';
332     }
333   else
334     strcpy(main_top_root, main_root);
335
336   hkey = create_key(HKEY_LOCAL_MACHINE, tmpstr);
337   sprintf(buffer, "%ssite-lisp;%ssite-lisp;%spackages\\lisp;%slisp;%sleim",
338           main_root, main_top_root, main_root, main_root, main_root);
339   set_value(hkey,      "EMACSLOADPATH", buffer);
340   set_value_path(hkey, "EMACSDATA",     main_root, "etc");
341   set_value_path(hkey, "EMACSPATH",     main_root, "bin");
342   set_value_path(hkey, "EMACSLOCKDIR",  main_root, "lock");
343   set_value_path(hkey, "INFOPATH",      main_root, "info");
344   set_value_path(hkey, "BITMAPPATH",    main_root, "bitmap");
345   set_value_path(hkey, "EMACSDOC",      main_root, "etc");
346   set_value(hkey,      "TERM",          "CMD");
347   set_value(hkey,      "SHELL",         shell_name);
348   set_value(hkey,      "HOME",          home_dir);
349
350   RegCloseKey(hkey);
351 }
352
353 void remove_registry_data(void)
354 {
355   RegDeleteKey(HKEY_LOCAL_MACHINE, meadow_version_root);
356 }
357
358 /* make shortcut of Meadow in a specified directory */
359 void make_shortcut(const char *path, const char *main_root)
360 {
361   char exec_path[MAX_PATH];
362   char icon_path[MAX_PATH];
363   char work_dir[MAX_PATH];
364   IShellLink *sl;
365   IPersistFile *pf;
366   WCHAR wpath[MAX_PATH];
367
368   /* main_root has a trailing backslash. */
369   sprintf (exec_path, "%sbin\\RunMW32.exe", main_root);
370   sprintf (icon_path, "%sbin\\meadow.ico", main_root);
371   sprintf (work_dir, "%sbin", main_root);
372
373   CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
374                     &IID_IShellLink, (LPVOID *) &sl);
375  
376   sl->lpVtbl->QueryInterface (sl, &IID_IPersistFile, (void **) &pf);
377  
378   sl->lpVtbl->SetPath (sl, exec_path);
379   sl->lpVtbl->SetArguments (sl, "");
380   sl->lpVtbl->SetIconLocation (sl, icon_path, 0);
381   sl->lpVtbl->SetWorkingDirectory (sl, work_dir);
382  
383   MultiByteToWideChar (CP_ACP, 0, path, -1, wpath, MAX_PATH);
384   pf->lpVtbl->Save (pf, wpath, TRUE);
385
386   pf->lpVtbl->Release (pf);
387   sl->lpVtbl->Release (sl);
388 }
389
390 /* make shortcut of Meadow in Quick Launch folder */
391 void register_to_quicklaunch(const char *main_root)
392 {
393   LPITEMIDLIST id;
394   OSVERSIONINFO verinfo = { sizeof verinfo };
395   char path[MAX_PATH];
396   int folder;
397
398   GetVersionEx (&verinfo);
399
400   folder = verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ?
401            CSIDL_COMMON_APPDATA : CSIDL_APPDATA;
402
403   SHGetSpecialFolderLocation (NULL, folder, &id);
404   SHGetPathFromIDList (id, path);
405
406   strcat (path, "\\Microsoft\\Internet Explorer\\Quick Launch");
407
408   if (_access (path, 0) != 0)
409     {
410       if (folder == CSIDL_APPDATA)
411         {
412           slmessage_fprintf (codepage, stderr, quicklaunch_not_found);
413           return;
414         }
415
416       /* if folder is CSIDL_COMMON_APPDATA, try CSIDL_APPDATA */
417       SHGetSpecialFolderLocation (NULL, CSIDL_APPDATA, &id);
418       SHGetPathFromIDList (id, path);
419
420       strcat (path, "\\Microsoft\\Internet Explorer\\Quick Launch");
421
422       if (_access (path, 0) != 0)
423         {
424           slmessage_fprintf (codepage, stderr, quicklaunch_not_found);
425           return;
426         }
427     }
428
429   strcat (path, "\\");
430   strcat (path, MEADOW_SHORTCUT_FILENAME);
431
432   make_shortcut (path, main_root);
433 }
434
435 /* make shortcut of Meadow in Desktop folder */
436 void register_to_desktop(const char *main_root)
437 {
438   LPITEMIDLIST id;
439   OSVERSIONINFO verinfo = { sizeof verinfo };
440   char path[MAX_PATH];
441
442   GetVersionEx (&verinfo);
443
444   SHGetSpecialFolderLocation (NULL,
445                               verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ?
446                               CSIDL_COMMON_DESKTOPDIRECTORY :
447                               CSIDL_DESKTOPDIRECTORY,
448                               &id);
449
450   SHGetPathFromIDList (id, path);
451
452   strcat (path, "\\");
453   strcat (path, MEADOW_SHORTCUT_FILENAME);
454
455   make_shortcut (path, main_root);
456 }
457
458 /* make shortcut of Meadow in Programs folder */
459 void register_to_shell(const char *main_root)
460 {
461   LPITEMIDLIST id;
462   OSVERSIONINFO verinfo = { sizeof verinfo };
463   char path[MAX_PATH];
464
465   GetVersionEx (&verinfo);
466
467   SHGetSpecialFolderLocation (NULL,
468                               verinfo.dwPlatformId == VER_PLATFORM_WIN32_NT ?
469                               CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS,
470                               &id);
471
472   SHGetPathFromIDList (id, path);
473
474   strcat (path, "\\Meadow");
475
476   if (_access (path, 0) != 0)
477     CreateDirectory (path, 0);
478
479   strcat (path, "\\");
480   strcat (path, MEADOW_SHORTCUT_FILENAME);
481
482   make_shortcut (path, main_root);
483 }
484
485 int check_opt(char *arg, char *opt)
486 {
487   if ((arg[0] != '/')
488       && (arg[0] != '-')) return 0;
489
490   if (strcmp(&arg[1], opt) == 0) return 1;
491   return 0;
492 }
493
494 /* convert '/' -> '\' */
495 void r_convert_path_separator(unsigned char *pathname)
496 {
497   char *pt;
498
499   while ( 1 ){
500     pt = strrchr(pathname, '/');
501     if (pt == NULL) break;
502     if (pt == (char *) pathname){
503       *pt = '\\';
504       break;
505     }
506     if (_ismbblead(*(pt-1)) == 0) *pt = '\\'; /* replace */
507   }
508 }
509
510 int main (int argc, char **argv)
511 {
512   unsigned char main_root[MAX_PATH];
513   unsigned char this_prog[MAX_PATH];
514   unsigned char home_dir[MAX_PATH];
515   unsigned char pre_home_dir[MAX_PATH];
516   unsigned char shell_name[MAX_PATH];
517   unsigned char *p;
518   int remove_flag = 0;
519   int register_flag = 1;
520   int quicklaunch_flag = 1;
521   int desktop_flag = 1;
522
523   CoInitialize (NULL);
524
525   init_current_environment();
526
527   GetModuleFileName(NULL, this_prog, MAX_PATH);
528   get_root(this_prog, main_root);
529
530   check_files(main_root);
531
532   {
533     int i;
534     int set_home_dir = 0;
535
536     for (i = 1;i < argc;i++)
537       {
538         if (check_opt(argv[i], "r"))
539           {
540             remove_flag = 1;
541             set_home_dir = 1;
542           }
543         else if (check_opt(argv[i], "s"))
544           {
545             register_flag = 0;
546           }
547         else if (check_opt(argv[i], "v"))
548           {
549             verbose_flag = 1;
550           }
551         else if (check_opt(argv[i], "h"))
552           {
553             if ((i+1) < argc)
554               {
555                 strcpy(home_dir, argv[i+1]);
556                 set_home_dir = 1;
557                 i++;
558               }
559             else
560               {
561                 error_usage();
562               }
563           }
564         else if (check_opt(argv[i], "d"))
565           {
566             desktop_flag = 0;
567           }
568         else if (check_opt(argv[i], "q"))