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

Annotation of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 137 - (hide annotations)
Mon Jan 9 14:01:51 2006 UTC (19 years, 1 month ago) by twoaday
File size: 16561 byte(s)
2006-01-09  Timo Schulz  <ts@g10code.com>
 
        * WinPT.cpp (load_gettext): Remove file locking.
        (WinMain): Use pre-defined autoconf constants.
        * wptW32API.cpp (init_file_lock, release_file_lock): Deleted.
        * wptGPG.cpp (check_gnupg_engine): Add param @need_gpg_ver.
        Change all callers.

Remove all static version constants. The only place for
constants is now configure.c (config.h).


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26