1 #include <wchar.h>
2
3 #define OEMRESOURCE
4 #include <windows.h>
5 #include <accctrl.h>
6 #include <aclapi.h>
7 #include <commctrl.h>
8 #include <shlwapi.h>
9 #include <shlobj.h>
10
11 #define WC_mainWindow L"V1541CommanderSetup"
12 #define CID_register 0x101
13 #define CID_cancel 0x102
14 #define CID_d64 0x103
15 #define CID_lynx 0x104
16 #define CID_zipcode 0x105
17
18 static HINSTANCE instance;
19 static HWND mainWindow;
20 static NONCLIENTMETRICSW ncm;
21 static HFONT messageFont;
22 static TEXTMETRICW messageFontMetrics;
23 static int buttonWidth;
24 static int buttonHeight;
25
26 static int ftD64 = 1;
27 static int ftLynx = 1;
28 static int ftZipcode = 0;
29
30 static WCHAR commanderPath[MAX_PATH];
31 static WCHAR commanderQuotedPath[MAX_PATH+2];
32 static WCHAR commanderRegCommand[MAX_PATH+7];
33 static DWORD commanderRegCommandSize;
34 static WCHAR regValTmp[MAX_PATH+16];
35
36 #define FEXIDX (sizeof "SOFTWARE\\Microsoft\\Windows\\" \
37 "CurrentVersion\\Explorer\\FileExts\\" - 1)
38 #define UCNLEN ((FEXIDX) + sizeof ".xxxxxxxx\\UserChoice")
39
40 static WCHAR userChoiceName[UCNLEN] = L"SOFTWARE\\Microsoft\\"
41 "Windows\\CurrentVersion\\Explorer\\FileExts\\";
42
43 static PSID sid = 0;
44
45 static const WCHAR *locales[] = {
46 L"C",
47 L"de",
48 };
49
50 enum textid {
51 TID_title,
52 TID_notfound_title,
53 TID_notfound_message,
54 TID_regsuccess_title,
55 TID_regsuccess_message,
56 TID_regfailure_title,
57 TID_regfailure_message,
58 TID_select_types,
59 TID_prg_warn,
60 TID_register,
61 TID_cancel,
62 TID_d64,
63 TID_lynx,
64 TID_zipcode,
65
66 TID_N_texts
67 };
68
69 static const WCHAR *locale_texts[][TID_N_texts] = {
70 {
71 L"V1541Commander Setup",
72 L"v1541commander.exe not found",
73 L"Please run this from the same directory\n"
74 L"where v1541commander.exe is located.",
75 L"File types registered",
76 L"The selected file types were associated\n"
77 L"to V1541Commander successfully.",
78 L"Registration failed",
79 L"There was an unexpected error registering\n"
80 L"the selected file types to V1541Commander.",
81 L"This tool registers V1541Commander with windows\n"
82 L"and associates it with all file types that can be\n"
83 L"opened or imported.\n"
84 L"\n"
85 L"Select here for which file types V1541Commander\n"
86 L"should be set as the default application:",
87 L"It's not recommended to set V1541Commander as the\n"
88 L"default application for .prg files, as most .prg files\n"
89 L"aren't Zipcode files.",
90 L"Register",
91 L"Cancel",
92 L"1541 disk images (.d64)",
93 L"LyNX archives (.lnx)",
94 L"Zipcode files (.prg)",
95 },
96 {
97 L"V1541Commander Einrichtung",
98 L"v1541commander.exe nicht gefunden",
99 L"Bitte starten Sie dieses Programm aus dem\n"
100 L"gleichen Verzeichnis, in dem sich auch\n"
101 L"v1541commander.exe befindet.",
102 L"Dateitypen registriert",
103 L"Die gewählten Dateitypen wurden erfolgreich\n"
104 L"V1541Commander zugeordnet.",
105 L"Registrierung fehlgeschlagen",
106 L"Bei der Registrierung der gewählten Dateitypen\n"
107 L"für V1541Commander ist ein unerwarteter Fehler\n"
108 L"aufgetreten.",
109 L"Dieses Programm registriert V1541Commander in Windows\n"
110 L"und verknüpft es mit allen Dateitypen, die geöffnet oder\n"
111 L"importiert werden können.\n"
112 L"\n"
113 L"Wählen Sie hier die Dateitypen, für die V1541Commander\n"
114 L"als Standardanwendung gesetzt werden soll:",
115 L"Es wird nicht empfohlen, V1541Commander als Standard-\n"
116 L"anwendung für .prg-Dateien zu setzen, da die meisten .prg-\n"
117 L"Dateien keine Zipcode Dateien sind.",
118 L"Registrieren",
119 L"Abbrechen",
120 L"1541 Diskettenabbilddateien (.d64)",
121 L"LyNX Archive (.lnx)",
122 L"Zipcode Dateien (.prg)",
123 },
124 };
125
126 static const WCHAR **texts = locale_texts[0];
127
init(void)128 static void init(void)
129 {
130 INITCOMMONCONTROLSEX icx;
131 icx.dwSize = sizeof icx;
132 icx.dwICC = ICC_WIN95_CLASSES;
133 InitCommonControlsEx(&icx);
134 ncm.cbSize = sizeof ncm;
135 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
136 messageFont = CreateFontIndirectW(&ncm.lfMessageFont);
137 HDC dc = GetDC(0);
138 SelectObject(dc, (HGDIOBJ) messageFont);
139 GetTextMetricsW(dc, &messageFontMetrics);
140 SIZE sampleSize;
141 GetTextExtentExPointW(dc,
142 L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
143 52, 0, 0, 0, &sampleSize);
144 ReleaseDC(0, dc);
145 buttonWidth = MulDiv(sampleSize.cx, 50, 4 * 52);
146 buttonHeight = MulDiv(messageFontMetrics.tmHeight, 14, 8);
147 instance = GetModuleHandleW(0);
148
149 WCHAR lang[10];
150 if (GetLocaleInfoW(LOCALE_USER_DEFAULT,
151 LOCALE_SISO639LANGNAME, lang, 10) > 0)
152 {
153 for (size_t i = 1; i < sizeof locales / sizeof *locales; ++i)
154 {
155 if (!wcscmp(locales[i], lang))
156 {
157 texts = locale_texts[i];
158 break;
159 }
160 }
161 }
162
163 HANDLE token;
164 if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
165 {
166 DWORD size = 0;
167 GetTokenInformation(token, TokenUser, 0, 0, &size);
168 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
169 {
170 TOKEN_USER *user = malloc(size);
171 if (GetTokenInformation(token, TokenUser, user, size, &size))
172 {
173 if (IsValidSid(user->User.Sid))
174 {
175 DWORD sidSize = GetLengthSid(user->User.Sid);
176 sid = malloc(sidSize);
177 CopySid(sidSize, sid, user->User.Sid);
178 }
179 }
180 free(user);
181 }
182 CloseHandle(token);
183 }
184 }
185
getCommanderPath(void)186 static int getCommanderPath(void)
187 {
188 GetModuleFileNameW(instance, commanderPath, MAX_PATH);
189 WCHAR *pos = wcsrchr(commanderPath, L'\\');
190 if (!pos) return 0;
191 wcscpy(pos+1, L"v1541commander.exe");
192 int rc = PathFileExistsW(commanderPath);
193 if (rc)
194 {
195 size_t pathlen = wcslen(commanderPath);
196 commanderQuotedPath[0] = L'"';
197 wcscpy(commanderQuotedPath+1, commanderPath);
198 commanderQuotedPath[pathlen+1] = L'"';
199 commanderQuotedPath[pathlen+2] = L'\0';
200 wcscpy(commanderRegCommand, commanderQuotedPath);
201 wcscpy(commanderRegCommand + pathlen + 2, L" \"%1\"");
202 commanderRegCommandSize = (pathlen + 8)
203 * sizeof *commanderRegCommand;
204 }
205 return rc;
206 }
207
regTreeDel(HKEY key,LPCWSTR subKey)208 static void regTreeDel(HKEY key, LPCWSTR subKey)
209 {
210 HKEY sub;
211 if (RegOpenKeyExW(key, subKey, 0, DELETE|KEY_ENUMERATE_SUB_KEYS, &sub)
212 == ERROR_SUCCESS)
213 {
214 WCHAR subName[256];
215 DWORD subNameLen;
216 while (subNameLen = 256,
217 RegEnumKeyExW(sub, 0, subName, &subNameLen, 0, 0, 0, 0)
218 == ERROR_SUCCESS)
219 {
220 regTreeDel(sub, subName);
221 }
222 RegCloseKey(sub);
223 RegDeleteKeyW(key, subKey);
224 }
225 }
226
regUnprotect(LPCWSTR subKey)227 static void regUnprotect(LPCWSTR subKey)
228 {
229 if (!sid) return;
230 SECURITY_DESCRIPTOR sd;
231 HKEY sub;
232 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
233 {
234 return;
235 }
236 if (RegOpenKeyExW(HKEY_CURRENT_USER, subKey, 0, WRITE_DAC, &sub)
237 != ERROR_SUCCESS) return;
238 EXPLICIT_ACCESS_W ea[1] = { 0 };
239 PACL acl = 0;
240 ea[0].grfAccessPermissions = GENERIC_ALL;
241 ea[0].grfAccessMode = SET_ACCESS;
242 ea[0].grfInheritance = SUB_OBJECTS_ONLY_INHERIT;
243 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
244 ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER;
245 ea[0].Trustee.ptstrName = (void *)sid;
246 if (SetEntriesInAclW(1, ea, 0, &acl) != ERROR_SUCCESS)
247 {
248 RegCloseKey(sub);
249 return;
250 }
251 if (!SetSecurityDescriptorDacl(&sd, 1, acl, 0))
252 {
253 LocalFree(acl);
254 RegCloseKey(sub);
255 return;
256 }
257 RegSetKeySecurity(sub, DACL_SECURITY_INFORMATION, &sd);
258 LocalFree(acl);
259 RegCloseKey(sub);
260 }
261
setFriendlyTypeNameAndIcon(HKEY tkey,int nameId)262 static int setFriendlyTypeNameAndIcon(HKEY tkey, int nameId)
263 {
264 DWORD valSize = wcslen(commanderQuotedPath) + 2;
265 regValTmp[0] = L'@';
266 wcscpy(regValTmp+1, commanderQuotedPath);
267 int numlen = swprintf(regValTmp + valSize - 1, PATH_MAX - valSize,
268 L",-%d", nameId);
269 if (numlen < 1) return 0;
270 valSize += numlen;
271 valSize *= sizeof *regValTmp;
272 if (RegSetValueExW(tkey, L"FriendlyTypeName", 0, REG_SZ,
273 (const BYTE *)regValTmp, valSize) != ERROR_SUCCESS)
274 {
275 return 0;
276 }
277
278 HKEY tmp;
279 if (RegCreateKeyExW(tkey, L"DefaultIcon", 0, 0, 0, KEY_WRITE, 0, &tmp, 0)
280 != ERROR_SUCCESS) return 0;
281
282 valSize = wcslen(commanderQuotedPath) + 1;
283 wcscpy(regValTmp, commanderQuotedPath);
284 numlen = swprintf(regValTmp + valSize - 1, PATH_MAX - valSize,
285 L",%d", nameId);
286 if (numlen < 1)
287 {
288 RegCloseKey(tmp);
289 return 0;
290 }
291 valSize += numlen;
292 valSize *= sizeof *regValTmp;
293 if (RegSetValueExW(tmp, 0, 0, REG_SZ,
294 (const BYTE *)regValTmp, valSize) != ERROR_SUCCESS)
295 {
296 RegCloseKey(tmp);
297 return 0;
298 }
299 RegCloseKey(tmp);
300 return 1;
301 }
302
registerAutoType(HKEY classes,LPCWSTR ext,int nameId)303 static void registerAutoType(HKEY classes, LPCWSTR ext, int nameId)
304 {
305 HKEY tmp;
306 if (RegOpenKeyExW(classes, ext, 0, KEY_QUERY_VALUE, &tmp)
307 != ERROR_SUCCESS) return;
308
309 WCHAR value[128];
310 DWORD len = 128;
311 DWORD valueType;
312 if (RegQueryValueExW(tmp, 0, 0, &valueType, (LPBYTE)&value, &len)
313 == ERROR_SUCCESS)
314 {
315 if (valueType != REG_SZ)
316 {
317 RegCloseKey(tmp);
318 return;
319 }
320 value[len] = L'\0';
321 WCHAR autoTypeKeyName[18];
322 wcscpy(autoTypeKeyName, ext+1);
323 wcscat(autoTypeKeyName, L"_auto_file");
324 if (!wcscmp(value, autoTypeKeyName))
325 {
326 RegCloseKey(tmp);
327 if (RegOpenKeyExW(classes, autoTypeKeyName, 0, KEY_WRITE, &tmp)
328 != ERROR_SUCCESS) return;
329 HKEY ico;
330 if (RegOpenKeyExW(tmp, L"DefaultIcon", 0, KEY_WRITE, &ico)
331 == ERROR_SUCCESS)
332 {
333 RegCloseKey(ico);
334 }
335 else
336 {
337 setFriendlyTypeNameAndIcon(tmp, nameId);
338 }
339 }
340 }
341 RegCloseKey(tmp);
342 }
343
registerType(HKEY classes,HKEY suppTypes,LPCWSTR ext,LPCWSTR name,LPCWSTR desc,LPCWSTR contentType,int nameId,int associate)344 static int registerType(HKEY classes, HKEY suppTypes, LPCWSTR ext,
345 LPCWSTR name, LPCWSTR desc, LPCWSTR contentType, int nameId,
346 int associate)
347 {
348 HKEY tkey = 0;
349 HKEY ekey = 0;
350 HKEY tmp;
351 int rc = 0;
352
353 if (RegCreateKeyExW(suppTypes, ext, 0, 0, 0, KEY_WRITE,
354 0, &tmp, 0) == ERROR_SUCCESS)
355 {
356 RegCloseKey(tmp);
357 }
358 else goto done;
359
360 if (RegCreateKeyExW(classes, ext, 0, 0, 0, KEY_WRITE, 0, &ekey, 0)
361 != ERROR_SUCCESS) goto done;
362
363 if (RegCreateKeyExW(classes, name, 0, 0, 0, KEY_WRITE, 0, &tkey, 0)
364 != ERROR_SUCCESS) goto done;
365
366 if (RegCreateKeyExW(tkey, L"shell\\open\\command", 0, 0, 0, KEY_WRITE,
367 0, &tmp, 0) == ERROR_SUCCESS)
368 {
369 if (RegSetValueExW(tmp, 0, 0, REG_SZ,
370 (const BYTE *)commanderRegCommand,
371 commanderRegCommandSize)
372 != ERROR_SUCCESS)
373 {
374 RegCloseKey(tmp);
375 goto done;
376 }
377 RegCloseKey(tmp);
378 }
379 else goto done;
380
381 DWORD valSize = (wcslen(desc)+1) * sizeof *desc;
382 if (RegSetValueExW(tkey, 0, 0, REG_SZ,
383 (const BYTE *)desc, valSize) != ERROR_SUCCESS)
384 {
385 goto done;
386 }
387 valSize = (wcslen(contentType)+1) * sizeof *contentType;
388 if (RegSetValueExW(tkey, L"Content Type", 0, REG_SZ,
389 (const BYTE *)contentType, valSize) != ERROR_SUCCESS)
390 {
391 goto done;
392 }
393
394 if (!setFriendlyTypeNameAndIcon(tkey, nameId)) goto done;
395
396 if (RegOpenKeyExW(tkey, L"shell", 0, KEY_WRITE, &tmp) == ERROR_SUCCESS)
397 {
398 if (RegSetValueExW(tmp, 0, 0, REG_SZ, (const BYTE *)L"open",
399 sizeof L"open") != ERROR_SUCCESS)
400 {
401 RegCloseKey(tmp);
402 goto done;
403 }
404 RegCloseKey(tmp);
405 }
406 else goto done;
407
408 if (RegCreateKeyExW(ekey, L"OpenWithProgids", 0, 0, 0,
409 KEY_WRITE, 0, &tmp, 0) == ERROR_SUCCESS)
410 {
411 if (RegSetValueExW(tmp, name, 0, REG_NONE, 0, 0) != ERROR_SUCCESS)
412 {
413 RegCloseKey(tmp);
414 goto done;
415 }
416 RegCloseKey(tmp);
417 }
418 else goto done;
419
420 registerAutoType(classes, ext, nameId);
421 if (!associate)
422 {
423 rc = 1;
424 goto done;
425 }
426
427 valSize = (wcslen(name)+1) * sizeof *name;
428 if (RegSetValueExW(ekey, 0, 0, REG_SZ, (const BYTE *)name, valSize)
429 != ERROR_SUCCESS)
430 {
431 goto done;
432 }
433 rc = 1;
434
435 size_t extLen = wcslen(ext);
436 wcscpy(userChoiceName + FEXIDX, ext);
437 userChoiceName[FEXIDX + extLen] = L'\\';
438 wcscpy(userChoiceName + FEXIDX + extLen + 1, L"UserChoice");
439 regUnprotect(userChoiceName);
440 userChoiceName[FEXIDX + extLen] = L'\0';
441 if (RegOpenKeyExW(HKEY_CURRENT_USER, userChoiceName, 0,
442 DELETE|KEY_ENUMERATE_SUB_KEYS, &tmp) == ERROR_SUCCESS)
443 {
444 regTreeDel(tmp, L"UserChoice");
445 RegCloseKey(tmp);
446 }
447
448 done:
449 if (ekey) RegCloseKey(ekey);
450 if (tkey) RegCloseKey(tkey);
451 return rc;
452 }
453
registerTypes(HWND w)454 static void registerTypes(HWND w)
455 {
456 int success = 0;
457 HKEY regkey = 0;
458 if (RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\"
459 "CurrentVersion\\App Paths\\v1541commander.exe", 0,
460 0, 0, KEY_WRITE, 0, ®key, 0) != ERROR_SUCCESS)
461 {
462 goto done;
463 }
464 DWORD valSize = (wcslen(commanderPath)+1) * sizeof *commanderPath;
465 if (RegSetValueExW(regkey, 0, 0, REG_SZ,
466 (const BYTE *)commanderPath, valSize) != ERROR_SUCCESS)
467 {
468 goto done;
469 }
470 RegCloseKey(regkey);
471 regkey = 0;
472
473 HKEY classes = 0;
474 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Classes", 0,
475 KEY_WRITE, &classes) == ERROR_SUCCESS)
476 {
477 if (RegCreateKeyExW(classes,
478 L"Applications\\v1541commander.exe\\shell\\open\\command",
479 0, 0, 0, KEY_WRITE, 0, ®key, 0) == ERROR_SUCCESS)
480 {
481 if (RegSetValueExW(regkey, 0, 0, REG_SZ,
482 (const BYTE *)commanderRegCommand,
483 commanderRegCommandSize)
484 != ERROR_SUCCESS)
485 {
486 goto done;
487 }
488 RegCloseKey(regkey);
489 regkey = 0;
490 }
491 else goto done;
492 if (RegCreateKeyExW(classes,
493 L"Applications\\v1541commander.exe\\SupportedTypes", 0,
494 0, 0, KEY_WRITE, 0, ®key, 0) == ERROR_SUCCESS)
495 {
496 if (!registerType(classes, regkey,
497 L".d64", L"V1541Commander.D64", L"D64 disk image",
498 L"application/vnd.cbm.d64-disk-image", 1, ftD64))
499 {
500 goto done;
501 }
502 if (!registerType(classes, regkey,
503 L".lnx", L"V1541Commander.LyNX", L"C64 LyNX archive",
504 L"application/x.willcorley.lynx-archive", 2, ftLynx))
505 {
506 goto done;
507 }
508 if (!registerType(classes, regkey,
509 L".prg", ftZipcode ? L"V1541Commander.Zipcode" :
510 L"V1541Commander.PRG", ftZipcode ?
511 L"C64 Zip-Code archive file" : L"Commodore program",
512 ftZipcode ? L"application/x.c64.zip-code" :
513 L"application/vnd.cbm.program-file",
514 ftZipcode ? 3 : 4, ftZipcode))
515 {
516 goto done;
517 }
518 success = 1;
519 }
520 }
521
522 done:
523 if (regkey) RegCloseKey(regkey);
524 if (classes) RegCloseKey(classes);
525 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
526 if (success)
527 {
528 MessageBoxW(w, texts[TID_regsuccess_message],
529 texts[TID_regsuccess_title], MB_OK|MB_ICONINFORMATION);
530 }
531 else
532 {
533 MessageBoxW(w, texts[TID_regfailure_message],
534 texts[TID_regfailure_title], MB_OK|MB_ICONERROR);
535 }
536 }
537
addFileTypeCheckbox(HWND w,int cid,LPCWSTR desc,int checked,HDC dc,int padding,int * ypos,int * fullwidth)538 static void addFileTypeCheckbox(HWND w, int cid, LPCWSTR desc, int checked,
539 HDC dc, int padding, int *ypos, int *fullwidth)
540 {
541 SIZE size;
542 GetTextExtentExPointW(dc, desc, wcslen(desc), 0, 0, 0, &size);
543 size.cx += 2*padding;
544 *fullwidth = size.cx > *fullwidth ? size.cx : *fullwidth;
545 HWND cb = CreateWindowExW(0, L"Button", desc,
546 WS_CHILD|WS_VISIBLE|BS_CHECKBOX, padding, *ypos,
547 size.cx, size.cy, w, (HMENU)cid, instance, 0);
548 *ypos += size.cy + padding;
549 SendMessageW(cb, WM_SETFONT, (WPARAM)messageFont, 0);
550 if (checked) CheckDlgButton(w, cid, BST_CHECKED);
551 }
552
wproc(HWND w,UINT msg,WPARAM wp,LPARAM lp)553 static LRESULT CALLBACK wproc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
554 {
555 switch (msg)
556 {
557 case WM_CREATE:
558 {
559 HDC dc = GetDC(0);
560 SelectObject(dc, (HGDIOBJ) messageFont);
561 RECT textrect = {0, 0, 0, 0};
562 int padding = messageFontMetrics.tmAveCharWidth * 3 / 2;
563 int ypos = padding;
564
565 const WCHAR *text = texts[TID_select_types];
566 DrawTextExW(dc, (WCHAR *)text, -1, &textrect, DT_CALCRECT, 0);
567 int fullwidth = textrect.right;
568 HWND ctrl = CreateWindowExW(0, L"Static", text,
569 WS_CHILD|WS_VISIBLE, padding, ypos,
570 textrect.right, textrect.bottom, w, 0, instance, 0);
571 SendMessageW(ctrl, WM_SETFONT, (WPARAM)messageFont, 0);
572 ypos += textrect.bottom + padding;
573
574 addFileTypeCheckbox(w, CID_d64, texts[TID_d64], 1,
575 dc, padding, &ypos, &fullwidth);
576 addFileTypeCheckbox(w, CID_lynx, texts[TID_lynx], 1,
577 dc, padding, &ypos, &fullwidth);
578 addFileTypeCheckbox(w, CID_zipcode, texts[TID_zipcode], 0,
579 dc, padding, &ypos, &fullwidth);
580
581 text = texts[TID_prg_warn];
582 memset(&textrect, 0, sizeof textrect);
583 DrawTextExW(dc, (WCHAR *)text, -1, &textrect, DT_CALCRECT, 0);
584 fullwidth = textrect.right > fullwidth
585 ? textrect.right : fullwidth;
586 ctrl = CreateWindowExW(0, L"Static", text,
587 WS_CHILD|WS_VISIBLE, padding, ypos,
588 textrect.right, textrect.bottom, w, 0, instance, 0);
589 SendMessageW(ctrl, WM_SETFONT, (WPARAM)messageFont, 0);
590 ypos += textrect.bottom + padding;
591
592 ctrl = CreateWindowExW(0, L"Button", texts[TID_register],
593 WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
594 fullwidth - 2*buttonWidth, ypos,
595 buttonWidth, buttonHeight,
596 w, (HMENU)CID_register, instance, 0);
597 SendMessageW(ctrl, WM_SETFONT, (WPARAM)messageFont, 0);
598 ctrl = CreateWindowExW(0, L"Button", texts[TID_cancel],
599 WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
600 padding + fullwidth - buttonWidth, ypos,
601 buttonWidth, buttonHeight,
602 w, (HMENU)CID_cancel, instance, 0);
603 SendMessageW(ctrl, WM_SETFONT, (WPARAM)messageFont, 0);
604 ypos += buttonHeight + padding;
605
606 ReleaseDC(0, dc);
607 RECT winRect = {0, 0, fullwidth + 2*padding, ypos};
608 AdjustWindowRect(&winRect, WS_CAPTION|WS_SYSMENU, 0);
609 SetWindowPos(w, HWND_TOP, 0, 0,
610 winRect.right - winRect.left,
611 winRect.bottom - winRect.top, SWP_NOMOVE);
612 }
613 break;
614
615 case WM_DESTROY:
616 PostQuitMessage(0);
617 break;
618
619 case WM_KEYDOWN:
620 if (wp == VK_RETURN)
621 {
622 registerTypes(w);
623 DestroyWindow(w);
624 }
625 else if (wp == VK_ESCAPE)
626 {
627 DestroyWindow(w);
628 }
629 break;
630
631 case WM_COMMAND:
632 switch (LOWORD(wp))
633 {
634 case CID_d64:
635 ftD64 = !ftD64;
636 CheckDlgButton(w, CID_d64,
637 ftD64 ? BST_CHECKED : BST_UNCHECKED);
638 break;
639
640 case CID_lynx:
641 ftLynx = !ftLynx;
642 CheckDlgButton(w, CID_lynx,
643 ftLynx ? BST_CHECKED : BST_UNCHECKED);
644 break;
645
646 case CID_zipcode:
647 ftZipcode = !ftZipcode;
648 CheckDlgButton(w, CID_zipcode,
649 ftZipcode ? BST_CHECKED : BST_UNCHECKED);
650 break;
651
652 case CID_register:
653 registerTypes(w);
654 /* fall through */
655 case CID_cancel:
656 DestroyWindow(w);
657 break;
658 }
659 break;
660 }
661 return DefWindowProcW(w, msg, wp, lp);
662 }
663
main(void)664 int main(void)
665 {
666 init();
667 if (!getCommanderPath())
668 {
669 MessageBoxW(0, texts[TID_notfound_title], texts[TID_notfound_message],
670 MB_OK|MB_ICONERROR);
671 return 0;
672 }
673
674 WNDCLASSEXW wc;
675 memset(&wc, 0, sizeof wc);
676 wc.cbSize = sizeof wc;
677 wc.hInstance = instance;
678 wc.lpszClassName = WC_mainWindow;
679 wc.lpfnWndProc = wproc;
680 wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
681 wc.hCursor = (HCURSOR) LoadImageW(0, MAKEINTRESOURCEW(OCR_NORMAL),
682 IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE|LR_SHARED);
683 RegisterClassExW(&wc);
684
685 mainWindow = CreateWindowExW(0, WC_mainWindow, texts[TID_title],
686 WS_CAPTION|WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT,
687 320, 100, 0, 0, instance, 0);
688 ShowWindow(mainWindow, SW_SHOWNORMAL);
689
690 MSG msg;
691 while (GetMessageW(&msg, 0, 0, 0) > 0)
692 {
693 TranslateMessage(&msg);
694 DispatchMessageW(&msg);
695 }
696 free(sid);
697 return (int)msg.wParam;
698 }
699
700