/[winpt]/trunk/Src/WinPT.cpp
ViewVC logotype

Annotation of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 133 - (hide annotations)
Mon Jan 9 09:15:29 2006 UTC (19 years, 1 month ago) by twoaday
File size: 16974 byte(s)
A lot of minor bug fixes.
New icons.

For a complete history, see the ChangeLog entries.


1 werner 36 /* WinPT.cpp - Windows Privacy Tray (WinPT)
2 twoaday 133 * Copyright (C) 2000-2006 Timo Schulz
3 werner 36 *
4     * This file is part of WinPT.
5     *
6     * WinPT is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * WinPT is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with WinPT; if not, write to the Free Software Foundation,
18     * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19     */
20 werner 42 #ifdef HAVE_CONFIG_H
21     #include <config.h>
22     #endif
23    
24 werner 36 #include <windows.h>
25    
26 werner 47 #include "resource.h"
27 werner 36 #include "wptTypes.h"
28     #include "wptW32API.h"
29     #include "wptVersion.h"
30     #include "wptErrors.h"
31     #include "wptGPG.h"
32     #include "wptRegistry.h"
33     #include "wptCommonCtl.h"
34     #include "wptDlgs.h"
35     #include "wptNLS.h"
36     #include "wptKeyserver.h"
37     #include "wptCard.h"
38     #include "wptFileManager.h"
39     #include "wptContext.h"
40     #include "wptCardEdit.h"
41 werner 48 #include "wptCrypto.h"
42 werner 36
43 twoaday 80 #define MIN_GPG_VER "1.4.2" /* Minimal GPG version. */
44 werner 36 #define MIN_GPGME_VER "1.2.0" /* Minimal GPGME version. */
45    
46    
47     HINSTANCE glob_hinst; /* global instance for the dialogs */
48     HWND glob_hwnd; /* global window handle for the dialogs */
49     HWND activ_hwnd;
50     LOCK mo_file;
51     int scard_support = 0;
52     int debug = 0;
53     int mobile = 0;
54     int gpg_read_only = 0;
55     char gpgver[3];
56    
57    
58     /* Load the key cache and rebuild the signature cache. */
59     static void
60     update_keycache (HWND hwnd)
61     {
62     refresh_cache_s rcs = {0};
63     rcs.kr_reload = 0;
64     rcs.kr_update = 1;
65     rcs.tr_update = 1;
66     DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYCACHE, hwnd,
67     keycache_dlg_proc, (LPARAM)&rcs);
68     }
69    
70    
71     /* Set GPGME debug mode. If @val is 0, the debug mode is disabled. */
72     void
73     gpg_set_debug_mode (int val)
74     {
75     if (val)
76     putenv ("GPGME_DEBUG=5:gpgme.dbg");
77     else
78     putenv ("GPGME_DEBUG=");
79     }
80    
81    
82     /* Return the name of the gettext language file. */
83     static char*
84     get_gettext_lang (void)
85     {
86     char *fname;
87     fname = get_reg_entry_mo ();
88     if (!fname)
89     return NULL;
90     return fname;
91     }
92    
93    
94     /* Initialize the gettext sub system. */
95     static void
96     load_gettext (int prev_inst)
97     {
98     char *nls = NULL;
99     char *file = NULL;
100    
101     nls = get_gettext_lang ();
102     if (nls) {
103     set_gettext_file ("winpt", nls);
104     file = make_filename (nls, "winpt", "mo");
105     if (!file_exist_check (nls) && init_file_lock (&mo_file, file)) {
106     if (!prev_inst)
107     msg_box (NULL, _("Could not initizalize file lock.\n"
108     "Native Language Support"),
109     _("WinPT Error"), MB_ERR);
110     }
111     free_if_alloc (nls);
112     free_if_alloc (file);
113     }
114     }
115    
116    
117 twoaday 128 /* Load the GPG environment. On the first start, some
118     checks are performed to find out in what state GPG is.
119     Return value: 0 everything OK.
120     >0 fatal error.
121     -1 public keyring is empty or does not exist. */
122     static int
123     load_gpg_env (void)
124     {
125     SECURITY_ATTRIBUTES sec_attr;
126     char *p;
127     char *pkr;
128    
129     p = get_reg_entry_gpg4win ("gpg.exe");
130     if (!p)
131     return (1);
132     if (file_exist_check (p)) {
133     free_if_alloc (p);
134     return (1);
135     }
136     free_if_alloc (p);
137     p = multi_gnupg_path (0);
138     if (p && dir_exist_check (p)) {
139     memset (&sec_attr, 0, sizeof (sec_attr));
140     sec_attr.nLength = sizeof (sec_attr);
141     if (!CreateDirectory (p, &sec_attr)) {
142     msg_box (NULL, _("Could not create GPG home directory"),
143     _("WinPT Error"), MB_ERR);
144     free_if_alloc (p);
145     return (2);
146     }
147     }
148     pkr = make_filename (p, "pubring", "gpg");
149     free_if_alloc (p);
150     if (!pkr)
151     return -1;
152     if (get_file_size (pkr) == 0) {
153     free_if_alloc (pkr);
154     return -1;
155     }
156     return 0;
157     }
158    
159 twoaday 133
160 werner 36 /* check if the default key from the gpg.conf file is available in the
161     keyring. if not, bail out because encryption won't work properly then. */
162     static int
163     check_default_key (gpg_keycache_t kc)
164     {
165     gpgme_key_t key;
166     gpgme_error_t err = GPG_ERR_NO_ERROR;
167 twoaday 128 char *defkey;
168 werner 36
169     defkey = get_gnupg_default_key ();
170     if (defkey)
171     err = gpg_keycache_find_key (kc, defkey, 0, &key);
172 twoaday 66 else
173 twoaday 121 msg_box (NULL, _("No useable secret key found."),
174     _("WinPT Error"), MB_ERR);
175 werner 36 free_if_alloc (defkey);
176     return err? -1 : 0;
177     }
178    
179    
180     /* Return the WinPT program file name (with full pathname). */
181 twoaday 121 static const char*
182 werner 36 get_prog_part (const char * fname, int use_cwd)
183     {
184     static char program[512];
185     char currdir[256];
186     char *cmd = NULL;
187     int j;
188    
189     memset (currdir, 0, DIM (currdir));
190     memset (program, 0, DIM (program));
191    
192     if (use_cwd) {
193     GetCurrentDirectory (DIM (currdir)-1, currdir);
194     _snprintf (program, DIM (program)-1, "%s\\%s", currdir, fname);
195     }
196     else {
197     cmd = GetCommandLine ();
198     if (cmd == NULL)
199     return NULL;
200     strncpy (currdir, cmd, sizeof (currdir)-1);
201     j = strlen (currdir);
202     while (j--) {
203     if (currdir[j] == '\\')
204     break;
205     }
206     currdir[j] = 0;
207     _snprintf (program, DIM (program)-1, "%s\\%s", currdir + 1, fname);
208     }
209     return program;
210     }
211    
212    
213     /* Check that the underlying crypto engine fullfills the minimal
214     requirements so all commands work properly. */
215 twoaday 128 static bool
216 werner 36 check_crypto_engine (void)
217     {
218 twoaday 80 int ma=1, mi=4, pa=2; /* GPG 1.4.2 */
219 werner 36 int rc;
220    
221     rc = check_gnupg_engine (&ma, &mi, &pa);
222     if (rc == -1) {
223     msg_box (NULL, _("Could not read GnuPG version."),
224     _("WinPT Error"), MB_ERR);
225 twoaday 128 return false;
226 werner 36 }
227     else if (rc) {
228     log_box (_("WinPT Error"), MB_ERR,
229     _("Sorry, you need a newer GPG version.\n"
230     "GPG version %d.%d.%d required GPG version "MIN_GPG_VER),
231     ma, mi, pa);
232 twoaday 128 return false;
233 werner 36 }
234 twoaday 80 /* We enable smartcard support for GPG: >= 2 or >= 1.4.3 */
235 twoaday 121 if (ma > 1 || pa >= 3)
236 werner 36 scard_support = 1;
237    
238     gpgver[0] = ma;
239     gpgver[1] = mi;
240     gpgver[2] = pa;
241 twoaday 128 return true;
242 werner 36 }
243    
244    
245     /* Try to load the keyserver config file. If @quiet is 1
246     do not show any errors. */
247     static int
248     load_keyserver_conf (int quiet)
249     {
250 twoaday 121 const char *t;
251 werner 36 int rc;
252    
253     if (reg_prefs.kserv_conf)
254     t = reg_prefs.kserv_conf;
255     else if (!file_exist_check (get_prog_part ("keyserver.conf", 0)))
256     t = get_prog_part ("keyserver.conf", 0);
257     else
258     t = "keyserver.conf";
259     rc = kserver_load_conf (t);
260     if (rc && !quiet)
261     msg_box (NULL, winpt_strerror (rc), _("Keyserver"), MB_ERR);
262     return rc;
263     }
264    
265    
266 twoaday 133 /* Check if both keyrings are empty. This indicates that
267     WinPT should offer to generate a key pair. */
268     static bool
269     check_for_empty_keyrings (bool pub_only)
270     {
271     char *p;
272     int n = 0;
273    
274     p = get_gnupg_keyring (1, 0);
275     if (file_exist_check (p) == 0 && get_file_size (p) == 0)
276     n++;
277     free_if_alloc (p);
278     if (pub_only)
279     return n == 1? true : false;
280     p = get_gnupg_keyring (0, 0);
281     if (file_exist_check (p) == 0 && get_file_size (p) == 0)
282     n++;
283     free_if_alloc (p);
284     return n==2? true : false;
285     }
286    
287    
288 werner 36 /* Enable the mobility mode. */
289     static void
290     enable_mobile_mode (void)
291     {
292     memset (&reg_prefs, 0, sizeof (reg_prefs));
293     reg_prefs.always_trust = 0;
294     reg_prefs.auto_backup = 0;
295     reg_prefs.cache_time = 0;
296     reg_prefs.expert = 0;
297     reg_prefs.keylist_mode = 1;
298     reg_prefs.kserv_conf = m_strdup ("keyserver.conf");
299     reg_prefs.no_zip_mmedia = 1;
300     reg_prefs.use_tmpfiles = 1;
301     reg_prefs.word_wrap = 80;
302     reg_prefs.use_viewer = 0; /* XXX */
303     }
304    
305    
306     /* Main entry point. */
307     int WINAPI
308     WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
309     {
310     WNDCLASS wc = {0, winpt_main_proc, 0, 0, hinst, 0, 0, 0, 0, PGM_NAME};
311     HACCEL accel_tab;
312 twoaday 121 MSG msg;
313     HWND hwnd = NULL;
314     WORD ver[3], ptdver[4];
315     int rc, ec, created = 0;
316 werner 36 int first_start = 0, start_gpgprefs = 0;
317     int winpt_inst_found = 0;
318 twoaday 121 int start_manager = 0;
319 werner 36 const char *s;
320    
321     glob_hinst = hinst;
322 twoaday 87 if (cmdline && stristr (cmdline, "--stop")) {
323     hwnd = FindWindow ("WinPT", "WinPT");
324     if (hwnd != NULL)
325     PostMessage (hwnd, WM_DESTROY, 0, 0);
326     return 0;
327     }
328 twoaday 121
329     /*
330     OSVERSIONINFO osinf;
331     memset (&osinf, 0, sizeof (osinf));
332     if (GetVersionEx (&osinf) &&
333     osinf.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
334     osinf.dwMinorVersion == 0) {
335     msg_box (NULL, "WinPT propably does not work on Windows 95 without restrictions",
336     "WinPT Warning", MB_INFO);
337     }
338     */
339    
340     #ifdef _DEBUG
341 werner 36 gpg_set_debug_mode (1);
342     debug = 1;
343 twoaday 121 #endif
344 werner 36
345 twoaday 121 get_file_version ("WinPT.exe", &ver[0], &ver[1], &ver[2], &ver[3]);
346     get_file_version ("PTD.dll", &ptdver[0], &ptdver[1],
347     &ptdver[2], &ptdver[3]);
348     /* XXX
349     if (ptdver[0] != ver[0] || ptdver[1] != ver[1]|| ptdver[2] != ver[2]) {
350     log_box (_("WinPT Error"), MB_ERR,
351     _("The PTD.dll file has a different version than WinPT.exe\n"
352     "Please update the PTD.dll to version %d.%d.%d"),
353     ver[0], ver[1], ver[2]);
354     return 0;
355     }
356     */
357 twoaday 128
358 werner 36 if (gpg_md_selftest ()) {
359     msg_box (NULL, _("Cryptographic selftest failed."),
360     _("WinPT Error"), MB_ERR);
361     return 0;
362     }
363    
364     s = gpgme_check_version (MIN_GPGME_VER);
365     if (!s || !*s) {
366     msg_box (NULL, _("A newer GPGME version is needed; at least "MIN_GPGME_VER),
367     _("WinPT Error"), MB_ERR);
368     return 0;
369     }
370    
371     CreateMutex (NULL, TRUE, PGM_NAME);
372     if (GetLastError () == ERROR_ALREADY_EXISTS)
373     winpt_inst_found = 1;
374    
375     if (cmdline && stristr (cmdline, "--mobile")) {
376     msg_box (NULL, "WARNING: mobile modus is not fully implemented yet!",
377     "WinPT", MB_INFO);
378     mobile = 1;
379     }
380    
381     set_default_kserver ();
382 twoaday 121 load_gettext (winpt_inst_found);
383 werner 36
384     if (!mobile) {
385     regist_inst_gnupg (1);
386     regist_inst_winpt (1, &created);
387     }
388     else {
389     enable_mobile_mode ();
390     /* XXX: ask for GPG path */
391     created = 1; /* Disable registry writing */
392     }
393    
394     if (!created) {
395     memset (&reg_prefs, 0, sizeof (reg_prefs));
396     reg_prefs.use_tmpfiles = 1; /* default */
397     reg_prefs.fm.progress = 0; /* XXX: fix the bug and enable it again */
398     get_reg_winpt_prefs (&reg_prefs);
399     if (!reg_prefs.no_hotkeys)
400     hotkeys_modify ();
401 twoaday 41 gnupg_load_config ();
402 werner 36 }
403    
404 twoaday 128 if (is_gpg4win_installed ())
405     load_gpg_env (); /* XXX: check return code. */
406    
407 werner 36 rc = gnupg_check_homedir ();
408     if (rc) {
409     log_box (_("WinPT Error"), MB_ERR,
410     _("GPG home directory is not set correctly.\n"
411     "Please check the GPG registry settings:\n%s."),
412     winpt_strerror (rc));
413 werner 48 s = get_fileopen_dlg (GetActiveWindow (),
414 twoaday 121 _("Select GPG Public Keyring"),
415     _("GPG Keyrings (*.gpg)\0*.gpg\0\0"),
416     NULL);
417 werner 36 if (s != NULL) {
418     size_t n;
419 twoaday 121 char *p = strrchr (s, '\\');
420 werner 36 if (!p)
421     BUG (0);
422     n = p - s;
423     if (n) {
424 twoaday 121 char *file = new char[n+1];
425 werner 36 if (!file)
426     BUG (NULL);
427     memset (file, 0, n);
428     memcpy (file, s, n);
429     file[n] = '\0';
430     set_reg_entry_gpg ("HomeDir", file);
431     free_if_alloc (file);
432     gnupg_check_homedir (); /* change gpgProgram if needed */
433     }
434     }
435     else {
436     msg_box (NULL, _("GPG home directory could not be determited."),
437     _("WinPT Error"), MB_ERR);
438     goto start;
439     }
440     }
441    
442     rc = check_gnupg_prog ();
443     if (rc) {
444     if (msg_box (NULL, _("Could not find the GPG binary (gpg.exe).\n"
445     "Do you want to start the GPG preferences to "
446     "correct this problem?"), _("WinPT Error"),
447     MB_INFO|MB_YESNO) == IDYES)
448     start_gpgprefs = 1;
449 twoaday 121 else {
450 werner 36 msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
451     return 0;
452     }
453     }
454    
455     rc = gnupg_access_files ();
456     if (!start_gpgprefs && rc) {
457     if (rc == WPTERR_GPG_KEYRINGS || rc == WPTERR_GPG_OPT_KEYRINGS) {
458     ec = msg_box (NULL,
459     _("Could not access and/or find the public and secret keyring.\n"
460     "If this is an accident, quit the program and fix it.\n\n"
461     "Continue if you want that WinPT offers you more choices.\n"),
462     "WinPT", MB_INFO|MB_YESNO);
463     if (ec == IDYES)
464     first_start = 1;
465     }
466     if (!first_start) {
467     msg_box (NULL, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
468     return 0;
469     }
470     }
471 twoaday 133 if (check_for_empty_keyrings (false))
472     first_start = 1;
473 werner 36
474     if (!first_start) {
475     rc = gpg_check_permissions (1);
476     if (rc && rc == 2)
477     gpg_read_only = 1;
478     else if (rc)
479     return 0;
480     }
481 twoaday 121
482 werner 36 init_gnupg_table ();
483    
484 twoaday 121 if (fm_parse_command_line (cmdline) > 0) {
485 werner 36 free_gnupg_table ();
486     return 0;
487     }
488    
489     if (cmdline && stristr (cmdline, "--wipe-freespace")) {
490     dialog_box_param (glob_hinst, (LPCTSTR)IDD_WINPT_SPACE_SECDEL,
491 twoaday 73 GetDesktopWindow(), space_wipefrees_dlg_proc, 0,
492 werner 36 _("Wipe Free Space"), IDS_WINPT_SPACE_SECDEL);
493     free_gnupg_table ();
494     return 0;
495     }
496    
497     load_keyserver_conf (cmdline? 1 : 0);
498    
499     if (cmdline && (stristr (cmdline, "--keymanager")
500     || stristr (cmdline, "--cardmanager"))) {
501 twoaday 102 /* If an instance of WinPT is running, just send the command
502     to open the key manager. Otherwise start a new instance.
503     */
504     HWND tray = FindWindow ("WinPT", "WinPT");
505 twoaday 121 if (stristr (cmdline, "keymanager"))
506     start_manager = ID_WINPT_KEY;
507     else
508     start_manager = ID_WINPT_CARD;
509 twoaday 102 if (tray != NULL) {
510 twoaday 121 PostMessage (tray, WM_COMMAND, start_manager, 0);
511 twoaday 102 free_gnupg_table ();
512     return 0;
513     }
514 werner 36 }
515    
516     /* If we found another WinPT instance, just quit to avoid it
517     will be executed twice. */
518     if (winpt_inst_found) {
519     log_debug ("%s", "WinMain: WinPT is already running.");
520     free_gnupg_table ();
521     return 0;
522     }
523    
524     if (cmdline) {
525 twoaday 121 if (stristr (cmdline, "--enable-debug") ||
526     stristr (cmdline, "--debug")) {
527 werner 36 gpg_set_debug_mode (1);
528     winpt_debug_msg ();
529     debug = 1;
530     }
531     }
532    
533     wc.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_WINPT));
534     rc = RegisterClass (&wc);
535     if (rc == FALSE) {
536     msg_box (NULL, _("Could not register window class"),
537     _("WinPT Error"), MB_ERR);
538     free_gnupg_table ();
539     return 0;
540     }
541    
542     hwnd = CreateWindow (PGM_NAME,
543     PGM_NAME,
544     0, 0, 0, 0, 0,
545     NULL,
546     NULL,
547     hinst,
548     NULL);
549     if (hwnd == NULL) {
550     msg_box (NULL, _("Could not create window"), _("WinPT Error"), MB_ERR);
551     free_gnupg_table ();
552     return 0;
553     }
554     glob_hwnd = hwnd;
555     UpdateWindow (hwnd);
556    
557     if (!first_start && !start_gpgprefs) {
558     gnupg_backup_options ();
559 twoaday 128 if (!check_crypto_engine ()) {
560 werner 36 DestroyWindow (hwnd);
561     free_gnupg_table ();
562     return 0;
563     }
564     }
565    
566     if (start_gpgprefs) {
567     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
568 twoaday 41 gpgprefs_dlg_proc, 0);
569 twoaday 133 if (check_for_empty_keyrings (true))
570     first_start = 1; /* The public keyring is empty! */
571 werner 36 }
572    
573     if (first_start) {
574     struct first_start_s fs;
575     struct genkey_s c;
576     HWND h;
577     start:
578     h = GetDesktopWindow ();
579     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, h,
580 twoaday 41 gpgprefs_dlg_proc, 0);
581 werner 36 DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_FIRST, h,
582     first_run_dlg_proc, (LPARAM)&fs);
583     switch (fs.choice) {
584     case SETUP_KEYGEN:
585     c.interactive = 1;
586     c.first_start = 1;
587     rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_KEYWIZARD,
588     h, keygen_wizard_dlg_proc, (LPARAM)&c);
589     if (!rc)
590     goto start;
591     break;
592    
593     case SETUP_IMPORT:
594     rc = gnupg_copy_keyrings ();
595     if (rc) {
596     msg_box (hwnd, winpt_strerror (rc), _("WinPT Error"), MB_ERR);
597     goto start;
598     }
599     break;
600    
601 twoaday 133 case -1: /* Cancel/Abort. */
602 werner 36 DestroyWindow (hwnd);
603     free_gnupg_table ();
604     return 0;
605     }
606     update_keycache (hwnd);
607     check_crypto_engine ();
608     }
609     else {
610     gpg_keycache_t c;
611     update_keycache (hwnd);
612     c = keycache_get_ctx (1);
613     if (!c || !gpg_keycache_get_size (c)) {
614     gnupg_display_error ();
615     msg_box (hwnd, _("The keycache was not initialized or is empty.\n"
616     "Please check your GPG config (keyrings, pathes...)"),
617     _("WinPT Error"), MB_ERR);
618     ec = msg_box (NULL, _("It seems that GPG is not set properly.\n"
619     "Do you want to start the GPG preferences dialog?"),
620     "WinPT", MB_INFO|MB_YESNO);
621     if (ec == IDYES) {
622     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_GPGPREFS, hwnd,
623 twoaday 41 gpgprefs_dlg_proc, 0);
624 werner 36 update_keycache (hwnd);
625     }
626     else {
627     DestroyWindow (hwnd);
628     free_gnupg_table ();
629     return 0;
630     }
631     }
632     if (check_default_key (c)) {
633 twoaday 121 char *p = get_gnupg_default_key ();
634 werner 36 log_box (_("WinPT Error"), MB_ERR,
635     _("Default key from the GPG options file could not be found.\n"
636     "Please check your gpg.conf (options) to correct this:\n\n"
637     "%s: public key not found."), p? p : "[null]");
638     free_if_alloc (p);
639     DestroyWindow (hwnd);
640     free_gnupg_table ();
641     return 0;
642     }
643     if (count_insecure_elgkeys ())
644     DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_ELGWARN, glob_hwnd,
645 twoaday 41 elgamal_warn_dlg_proc, 0);
646 werner 36 }
647    
648 twoaday 121 if (start_manager)
649     PostMessage (hwnd, WM_COMMAND, start_manager, 0);
650    
651 werner 36 accel_tab = LoadAccelerators (glob_hinst, (LPCTSTR)IDR_WINPT_ACCELERATOR);
652     keyring_check_last_access (); /* init */
653     while (GetMessage (&msg, hwnd, 0, 0)) {
654     if (!TranslateAccelerator (msg.hwnd, accel_tab, &msg)) {
655     TranslateMessage (&msg);
656     DispatchMessage (&msg);
657     }
658     }
659    
660     return 0;
661     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26