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

Annotation of /trunk/Src/WinPT.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 128 - (hide annotations)
Mon Dec 19 13:05:59 2005 UTC (19 years, 2 months ago) by twoaday
File size: 16472 byte(s)
2005-12-17  Timo Schulz  <ts@g10code.com>
 
        * wptUTF8.cpp: Removed unused charset array.
        * wptSigList.cpp (siglist_build): Increase size for 'class'
        column.
        * wptGPG.cpp (get_gnupg_path): Simplified.
        * WinPT.cpp (load_gpg_env): New.
        (check_crypto_engine): Return type is now bool.
        * wptRegistry.cpp (is_gpg4win_installed): New.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): More consistent
        dialog design.
        * wptKeyManagerDlg.cpp (translate_menu_strings): New.
        (translate_popupmenu_strings): New.
        * wptKeyEditDlgs.cpp (is_jpg_file): New.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26