]> code.delx.au - gnu-emacs/blob - nt/runemacs.c
*** empty log message ***
[gnu-emacs] / nt / runemacs.c
1 /*
2 Simple program to start Emacs with its console window hidden.
3
4 This program is provided purely for convenience, since most users will
5 use Emacs in windowing (GUI) mode, and will not want to have an extra
6 console window lying around. */
7
8 /*
9 You may want to define this if you want to be able to install updated
10 emacs binaries even when other users are using the current version.
11 The problem with some file servers (notably Novell) is that an open
12 file cannot be overwritten, deleted, or even renamed. So if someone
13 is running emacs.exe already, you cannot install a newer version.
14 By defining CHOOSE_NEWEST_EXE, you can name your new emacs.exe
15 something else which matches "emacs*.exe", and runemacs will
16 automatically select the newest emacs executeable in the bin directory.
17 (So you'll probably be able to delete the old version some hours/days
18 later).
19 */
20
21 /* #define CHOOSE_NEWEST_EXE */
22
23 #include <windows.h>
24 #include <string.h>
25 #include <malloc.h>
26
27 int WINAPI
28 WinMain (HINSTANCE hSelf, HINSTANCE hPrev, LPSTR cmdline, int nShow)
29 {
30 STARTUPINFO start;
31 SECURITY_ATTRIBUTES sec_attrs;
32 SECURITY_DESCRIPTOR sec_desc;
33 PROCESS_INFORMATION child;
34 int wait_for_child = FALSE;
35 DWORD priority_class = NORMAL_PRIORITY_CLASS;
36 DWORD ret_code = 0;
37 char *new_cmdline;
38 char *p;
39 char modname[MAX_PATH];
40
41 if (!GetModuleFileName (NULL, modname, MAX_PATH))
42 goto error;
43 if ((p = strrchr (modname, '\\')) == NULL)
44 goto error;
45 *p = 0;
46
47 new_cmdline = alloca (MAX_PATH + strlen (cmdline) + 1);
48 strcpy (new_cmdline, modname);
49
50 #ifdef CHOOSE_NEWEST_EXE
51 {
52 /* Silly hack to allow new versions to be installed on
53 server even when current version is in use. */
54
55 char * best_name = alloca (MAX_PATH + 1);
56 FILETIME best_time = {0,0};
57 WIN32_FIND_DATA wfd;
58 HANDLE fh;
59 p = new_cmdline + strlen (new_cmdline);
60 strcpy (p, "\\emacs*.exe ");
61 fh = FindFirstFile (new_cmdline, &wfd);
62 if (fh == INVALID_HANDLE_VALUE)
63 goto error;
64 do
65 {
66 if (wfd.ftLastWriteTime.dwHighDateTime > best_time.dwHighDateTime
67 || (wfd.ftLastWriteTime.dwHighDateTime == best_time.dwHighDateTime
68 && wfd.ftLastWriteTime.dwLowDateTime > best_time.dwLowDateTime))
69 {
70 best_time = wfd.ftLastWriteTime;
71 strcpy (best_name, wfd.cFileName);
72 }
73 }
74 while (FindNextFile (fh, &wfd));
75 FindClose (fh);
76 *p++ = '\\';
77 strcpy (p, best_name);
78 strcat (p, " ");
79 }
80 #else
81 strcat (new_cmdline, "\\emacs.exe ");
82 #endif
83
84 /* Append original arguments if any; first look for arguments we
85 recognise (-wait, -high, and -low), and apply them ourselves. */
86 while (cmdline[0] == '-' || cmdline[0] == '/')
87 {
88 if (strncmp (cmdline+1, "wait", 4) == 0)
89 {
90 wait_for_child = TRUE;
91 cmdline += 5;
92 }
93 else if (strncmp (cmdline+1, "high", 4) == 0)
94 {
95 priority_class = HIGH_PRIORITY_CLASS;
96 cmdline += 5;
97 }
98 else if (strncmp (cmdline+1, "low", 3) == 0)
99 {
100 priority_class = IDLE_PRIORITY_CLASS;
101 cmdline += 4;
102 }
103 else
104 break;
105 }
106 strcat (new_cmdline, cmdline);
107
108 /* Set emacs_dir variable if runemacs was in "%emacs_dir%\bin". */
109 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
110 {
111 *p = 0;
112 for (p = modname; *p; p++)
113 if (*p == '\\') *p = '/';
114 SetEnvironmentVariable ("emacs_dir", modname);
115 }
116
117 memset (&start, 0, sizeof (start));
118 start.cb = sizeof (start);
119 start.dwFlags = STARTF_USESHOWWINDOW;
120 start.wShowWindow = SW_HIDE;
121
122 sec_attrs.nLength = sizeof (sec_attrs);
123 sec_attrs.lpSecurityDescriptor = NULL;
124 sec_attrs.bInheritHandle = FALSE;
125
126 if (CreateProcess (NULL, new_cmdline, &sec_attrs, NULL, TRUE, priority_class,
127 GetEnvironmentStrings (), NULL, &start, &child))
128 {
129 if (wait_for_child)
130 {
131 WaitForSingleObject (child.hProcess, INFINITE);
132 GetExitCodeProcess (child.hProcess, &ret_code);
133 }
134 CloseHandle (child.hThread);
135 CloseHandle (child.hProcess);
136 }
137 else
138 goto error;
139 return (int) ret_code;
140
141 error:
142 MessageBox (NULL, "Could not start Emacs.", "Error", MB_ICONSTOP);
143 return 1;
144 }