1 // mzcom.cxx : Implementation of WinMain
2
3 // This file is not xformed for 3m. There's just one
4 // bit of conditional compilation on MZCOM_3M.
5
6 #include "../version/racket_version.h"
7 #include "resource.h"
8
9 #include <objbase.h>
10 extern "C" {
11 #include "com_glue.h"
12 };
13
14 // time to wait for threads to finish up
15 #define dwPause (1000)
16
17 HINSTANCE globHinst;
18
19 /* A monitor thread might be a good idea to make sure the process
20 terminates if it's somehow started and not used. It also creates
21 a race condition, though, so it's disabled for now. */
22
23 #if 0
24
25 // time for EXE to be idle before shutting down
26 #define dwTimeOut (5000)
27
28 static HANDLE hEventShutdown;
29 static DWORD dwThreadID;
30
31 // Polls for idle state
32 static DWORD WINAPI MonitorProc(void* pv)
33 {
34 while (1) {
35 DWORD dwWait=0;
36 do
37 {
38 dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
39 } while (dwWait == WAIT_OBJECT_0);
40
41 if (com_can_unregister())
42 break;
43 }
44 CloseHandle(hEventShutdown);
45 PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
46
47 return 0;
48 }
49
50 static bool StartMonitor()
51 {
52 dwThreadID = GetCurrentThreadId();
53 hEventShutdown = CreateEvent(NULL, false, false, NULL);
54 if (hEventShutdown == NULL)
55 return false;
56
57 DWORD subThreadID;
58 HANDLE h = CreateThread(NULL, 0, MonitorProc, NULL, 0, &subThreadID);
59 return (h != NULL);
60 }
61
62 #else
63
StartMonitor()64 static bool StartMonitor() { return TRUE; }
65
66 #endif
67
set_reg_string(HKEY sub,const char * name,const char * s)68 static int set_reg_string(HKEY sub, const char *name, const char *s)
69 {
70 return RegSetValueExA(sub, name, 0, REG_SZ, (const BYTE *)s, strlen(s));
71 }
72
set_reg_sub_string(HKEY sub,const char * name,const char * s)73 static int set_reg_sub_string(HKEY sub, const char *name, const char *s)
74 {
75 HKEY sub2;
76 int nRet;
77
78 nRet = RegCreateKeyExA(sub, name, 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
79 if (!nRet) {
80 nRet |= set_reg_string(sub2, NULL, s);
81 nRet |= RegCloseKey(sub2);
82 }
83
84 return nRet;
85 }
86
FindOneOf(LPCTSTR p1,LPCTSTR p2)87 LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
88 {
89 while (p1 != NULL && *p1 != 0)
90 {
91 LPCTSTR p = p2;
92 while (p != NULL && *p != 0)
93 {
94 if (*p1 == *p)
95 return CharNext(p1);
96 p = CharNext(p);
97 }
98 p1 = CharNext(p1);
99 }
100 return NULL;
101 }
102
IsFlag(LPCTSTR cmd,LPCTSTR flag)103 int IsFlag(LPCTSTR cmd, LPCTSTR flag)
104 {
105 if ((*cmd == '-') || (*cmd == '/'))
106 cmd++;
107 else
108 return 0;
109
110 while (*flag) {
111 if (toupper(*cmd) != toupper(*flag))
112 return 0;
113 cmd++;
114 flag++;
115 }
116 if (!*cmd || (*cmd == ' '))
117 return 1;
118 return 0;
119 }
120
121 #define DLL_RELATIVE_PATH L"."
122 #include "../start/delayed.inc"
123
124 #include "../start/cmdl_to_argv.inc"
125
126 /////////////////////////////////////////////////////////////////////////////
127 //
WinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR lpCmdLine,int)128 extern "C" int WINAPI WinMain(HINSTANCE hInstance,
129 HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) {
130
131 globHinst = hInstance;
132
133 lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
134
135 #ifdef MZCOM_3M
136 load_delayed_dll(hInstance, "libracket3mxxxxxxx.dll");
137 #else
138 load_delayed_dll(hInstance, "libmzgcxxxxxxx.dll");
139 load_delayed_dll(hInstance, "libracketxxxxxxx.dll");
140 #endif
141
142 HRESULT nRet = CoInitialize(NULL);
143
144 int argc, i;
145 char **argv, *normalized_path;
146
147 argv = cmdline_to_argv(&argc, &normalized_path);
148
149 int verbose = 0;
150 BOOL bRun = TRUE;
151 LPCTSTR lpszToken;
152 for (i = 1; i < argc; i++)
153 {
154 lpszToken = argv[i];
155 if (IsFlag(lpszToken, "UnregServer"))
156 {
157 if (!nRet) {
158 HKEY sub;
159
160 nRet |= RegDeleteKeyA(HKEY_CLASSES_ROOT, "MzCOM.MzObj");
161 nRet |= RegDeleteKeyA(HKEY_CLASSES_ROOT, "MzCOM.MzObj." MZSCHEME_VERSION);
162
163 if (!nRet) {
164 nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
165 if (!nRet) {
166 nRet |= RegDeleteKeyA(sub, "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}");
167 nRet |= RegCloseKey(sub);
168 }
169 }
170
171 if (!nRet) {
172 nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "AppID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
173 if (!nRet) {
174 nRet |= RegDeleteKeyA(sub, "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}");
175 nRet |= RegCloseKey(sub);
176 }
177 }
178
179 bRun = FALSE;
180 }
181 }
182 else if (IsFlag(lpszToken, "RegServer"))
183 {
184 if (!nRet) {
185 HKEY sub, sub2;
186
187 nRet |= RegCreateKeyExA(HKEY_CLASSES_ROOT, "MzCOM.MzObj", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
188
189 if (!nRet) {
190 nRet |= set_reg_string(sub, NULL, "MzObj Class");
191 nRet |= set_reg_sub_string(sub, "CLSID", "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}");
192 nRet |= set_reg_sub_string(sub, "CurVer", "MzCOM.MzObj." MZSCHEME_VERSION);
193 nRet |= RegCloseKey(sub);
194 }
195
196 if (!nRet) {
197 nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "MzCOM.MzObj." MZSCHEME_VERSION, 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
198 if (!nRet) {
199 nRet |= set_reg_string(sub, NULL, "MzObj Class");
200 nRet |= set_reg_sub_string(sub, "CLSID", "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}");
201 nRet |= RegCloseKey(sub);
202 }
203 }
204
205 if (!nRet) {
206 nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
207 if (!nRet) {
208 nRet = RegCreateKeyExA(sub, "{A3B0AF9E-2AB0-11D4-B6D2-0060089002FE}", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
209 if (!nRet) {
210 nRet |= set_reg_string(sub2, NULL, "MzObj Class");
211 nRet |= set_reg_string(sub2, "AppId", "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}");
212 nRet |= set_reg_sub_string(sub2, "ProgID", "MzCOM.MzObj." MZSCHEME_VERSION);
213 nRet |= set_reg_sub_string(sub2, "VersionIndependentProgID", "MzCOM.MzObj");
214 nRet |= set_reg_sub_string(sub2, "Programmable", "");
215
216 char *path;
217 path = (char *)malloc(1024 * sizeof(wchar_t));
218 GetModuleFileNameA(NULL, path, 1024);
219 nRet |= set_reg_sub_string(sub2, "LocalServer32", path);
220 free(path);
221
222 nRet |= set_reg_sub_string(sub2, "TypeLib", "{A604CB9C-2AB5-11D4-B6D3-0060089002FE}");
223 nRet |= RegCloseKey(sub2);
224 }
225 nRet |= RegCloseKey(sub);
226 }
227 }
228
229 if (!nRet) {
230 nRet = RegCreateKeyExA(HKEY_CLASSES_ROOT, "AppID", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub, NULL);
231 if (!nRet) {
232 nRet = RegCreateKeyExA(sub, "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
233 if (!nRet) {
234 nRet |= set_reg_string(sub2, NULL, "MzCOM");
235 nRet |= RegCloseKey(sub2);
236 }
237 }
238 if (!nRet) {
239 nRet = RegCreateKeyExA(sub, "MzCOM.EXE", 0, NULL, 0, KEY_SET_VALUE, NULL, &sub2, NULL);
240 if (!nRet) {
241 nRet |= set_reg_string(sub2, "AppID", "{A604CB9D-2AB5-11D4-B6D3-0060089002FE}");
242 nRet |= RegCloseKey(sub2);
243 }
244 }
245 nRet |= RegCloseKey(sub);
246 }
247
248 if (!nRet) {
249 ITypeLib *typelib;
250 wchar_t *path;
251 path = (wchar_t *)malloc(1024 * sizeof(wchar_t));
252 GetModuleFileNameW(NULL, path, 1024);
253 nRet = LoadTypeLibEx(path, REGKIND_REGISTER, &typelib);
254 if (!nRet)
255 typelib->Release();
256 free(path);
257 }
258
259 bRun = FALSE;
260 }
261 }
262 else if (IsFlag(lpszToken, "v"))
263 {
264 verbose = 1;
265 }
266 else if (IsFlag(lpszToken, "?"))
267 {
268 MessageBox(NULL,
269 "/RegServer - register\n"
270 "/UnregServer - unregister\n"
271 "/Embedding - ignored\n"
272 "/v - report failures\n"
273 "/? - show this help",
274 "Help",
275 MB_OK);
276 bRun = FALSE;
277 }
278 else if (IsFlag(lpszToken, "Embedding"))
279 {
280 /* ??? */
281 }
282 else
283 {
284 if (verbose)
285 MessageBox(NULL, lpszToken, "Unknown Flag", MB_OK);
286 bRun = FALSE;
287 break;
288 }
289 }
290
291 if (bRun) {
292 StartMonitor();
293
294 nRet = com_register();
295
296 if (!nRet) {
297 MSG msg;
298 while (GetMessage(&msg, 0, 0, 0))
299 DispatchMessage(&msg);
300
301 while (!com_unregister()) {
302 Sleep(dwPause); // wait for any objects to finish
303 }
304 }
305 }
306
307 if (verbose && (nRet != 0)) {
308 wchar_t *res;
309 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
310 | FORMAT_MESSAGE_FROM_SYSTEM,
311 NULL,
312 nRet,
313 0,
314 (wchar_t *)&res,
315 0,
316 0);
317 MessageBoxW(NULL, res, L"Registration Failed", MB_OK);
318 }
319
320 CoUninitialize();
321
322 return nRet;
323 }
324