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