24b1c0c13a80a25aa4183f785d6f4c27e1306591
[obnox/wireshark/wip.git] / win32 / file_dlg_win32.c
1 /* win32-file-dlg.c
2  * Native Windows file dialog routines
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 2004 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdio.h>
30 #include <tchar.h>
31 #include <wchar.h>
32 #include <stdlib.h>
33 #include <sys/stat.h>
34 #include <io.h>
35 #include <fcntl.h>
36
37 #include <windows.h>
38 #include <windowsx.h>
39 #include <commdlg.h>
40 #include <richedit.h>
41
42 #include <gtk/gtk.h>
43
44 #include "epan/filesystem.h"
45 #include "epan/addr_resolv.h"
46 #include "epan/prefs.h"
47 #include "epan/dissectors/packet-ssl.h"
48 #include "epan/dissectors/packet-ssl-utils.h"
49 #include "wsutil/file_util.h"
50 #include "wsutil/unicode-utils.h"
51
52 #include "../alert_box.h"
53 #include "../color.h"
54 #include "../print.h"
55 #include "../simple_dialog.h"
56 #include "../util.h"
57 #include "../color_filters.h"
58 #include "../merge.h"
59
60 #include "gtk/file_dlg.h"
61 #include "gtk/capture_file_dlg.h"
62 #include "gtk/main.h"
63 #include "gtk/menus.h"
64 #include "gtk/drag_and_drop.h"
65 #include "gtk/capture_dlg.h"
66 #include "win32/file_dlg_win32.h"
67 #include "gtk/help_dlg.h"
68 #include "gtk/export_sslkeys.h"
69
70 typedef enum {
71     merge_append,
72     merge_chrono,
73     merge_prepend
74 } merge_action_e;
75
76 #define FILE_OPEN_DEFAULT 1 /* All Files */
77
78 #define FILE_MERGE_DEFAULT FILE_OPEN_DEFAULT
79
80 #define FILE_SAVE_DEFAULT 1 /* Wireshark/tcpdump */
81
82 #define FILE_TYPES_EXPORT \
83     _T("Plain text (*.txt)\0")                           _T("*.txt\0")   \
84     _T("PostScript (*.ps)\0")                            _T("*.ps\0")    \
85     _T("CSV (Comma Separated Values summary) (*.csv)\0") _T("*.csv\0")   \
86     _T("PSML (XML packet summary) (*.psml)\0")           _T("*.psml\0")  \
87     _T("PDML (XML packet detail) (*.pdml)\0")            _T("*.pdml\0")  \
88     _T("C Arrays (packet bytes) (*.c)\0")                _T("*.c\0")
89
90 #define FILE_TYPES_RAW \
91     _T("Raw data (*.bin, *.dat, *.raw)\0")               _T("*.bin;*.dat;*.raw\0") \
92     _T("All Files (*.*)\0")                              _T("*.*\0")
93
94 #define FILE_RAW_DEFAULT 1
95
96 #define FILE_TYPES_SSLKEYS \
97     _T("SSL Session Keys (*.keys)\0")                    _T("*.keys\0") \
98     _T("All Files (*.*)\0")                              _T("*.*\0")
99
100 #define FILE_SSLKEYS_DEFAULT 1
101
102 #define FILE_TYPES_COLOR \
103     _T("Text Files (*.txt)\0")                           _T("*.txt\0")   \
104     _T("All Files (*.*)\0")                              _T("*.*\0")
105
106 #define FILE_DEFAULT_COLOR 2
107
108 /*
109  * We should probably test the SDK version instead of the compiler version,
110  * but this should work for our purposes.
111  */
112 #if (_MSC_VER <= 1200)
113 static UINT CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
114 static UINT CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
115 static UINT CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
116 static UINT CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
117 static UINT CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
118 static UINT CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
119 #else
120 static UINT_PTR CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
121 static UINT_PTR CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
122 static UINT_PTR CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
123 static UINT_PTR CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
124 static UINT_PTR CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
125 static UINT_PTR CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
126 #endif /* (_MSC_VER <= 1200) */
127
128 static void range_update_dynamics(HWND sf_hwnd, packet_range_t *range);
129 static void range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range);
130 static void range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range);
131
132 static TCHAR *build_file_type_list(gboolean save, int *item_to_select);
133 static int file_type_from_list_index(gboolean save, int index);
134
135 static int            filetype;
136 static packet_range_t g_range;
137 static merge_action_e merge_action;
138 static print_args_t   print_args;
139 /* XXX - The reason g_sf_hwnd exists is so that we can call
140  *       range_update_dynamics() from anywhere; it's currently
141  *       static, but if we move to using the native Windows
142  *       print dialog and put range widgets in it as well,
143  *       it might be moved to a separate file.
144  *
145  *       However, the save file dialog hogs the foreground, so
146  *       this may not be necessary (and, in fact, the file dialogs
147  *       should arguably be modal to the window for the file
148  *       being opened/saved/etc.).
149  */
150 static HWND           g_sf_hwnd = NULL;
151 static char *dfilter_str = NULL;
152
153 gboolean
154 win32_open_file (HWND h_wnd) {
155     OPENFILENAME *ofn;
156     TCHAR  file_name[MAX_PATH] = _T("");
157     int    err;
158     char  *dirname;
159     dfilter_t *dfp;
160     int    ofnsize;
161 #if (_MSC_VER >= 1500)
162     OSVERSIONINFO osvi;
163 #endif
164
165     /* Remarks on OPENFILENAME_SIZE_VERSION_400:
166      *
167      * MSDN states that OPENFILENAME_SIZE_VERSION_400 should be used with
168      * WINVER and _WIN32_WINNT >= 0x0500.
169      * Unfortunately all these are compiler constants, while the underlying is a
170      * problem based is a length check of the runtime version used.
171      *
172      * Instead of using OPENFILENAME_SIZE_VERSION_400, just malloc
173      * the OPENFILENAME size plus 12 bytes.
174      * These 12 bytes are the difference between the two versions of this struct.
175      *
176      * Interestingly this fixes a bug, so the places bar e.g. "My Documents"
177      * is displayed - which wasn't the case with the former implementation.
178      *
179      * XXX - It's unclear if this length+12 works on all supported platforms,
180      * NT4 is the question here. However, even if it fails, we must calculate
181      * the length based on the runtime, not the compiler version anyway ...
182      */
183     /* This assumption does not work when compiling with MSVC2008EE as
184      * the open dialog window does not appear.
185      * Instead detect Windows version at runtime and choose size accordingly */
186 #if (_MSC_VER >= 1500)
187     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
188     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
189     GetVersionEx(&osvi);
190     if (osvi.dwMajorVersion >= 5) {
191         ofnsize = sizeof(OPENFILENAME);
192     } else {
193         ofnsize = OPENFILENAME_SIZE_VERSION_400;
194     }
195 #else
196     ofnsize = sizeof(OPENFILENAME) + 12;
197 #endif
198     ofn = g_malloc0(ofnsize);
199
200     ofn->lStructSize = ofnsize;
201     ofn->hwndOwner = h_wnd;
202 #if (_MSC_VER <= 1200)
203     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
204 #else
205     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
206 #endif
207     ofn->lpstrFilter = build_file_type_list(FALSE /*!save*/, NULL);
208     ofn->lpstrCustomFilter = NULL;
209     ofn->nMaxCustFilter = 0;
210     ofn->nFilterIndex = FILE_OPEN_DEFAULT;
211     ofn->lpstrFile = file_name;
212     ofn->nMaxFile = MAX_PATH;
213     ofn->lpstrFileTitle = NULL;
214     ofn->nMaxFileTitle = 0;
215     if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
216         ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
217     } else {
218         ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
219     }
220     ofn->lpstrTitle = _T("Wireshark: Open Capture File");
221     ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER     |
222                  OFN_NOCHANGEDIR  | OFN_FILEMUSTEXIST  | OFN_HIDEREADONLY |
223                  OFN_ENABLEHOOK   | OFN_SHOWHELP;
224     ofn->lpstrDefExt = NULL;
225     ofn->lpfnHook = open_file_hook_proc;
226     ofn->lpTemplateName = _T("WIRESHARK_OPENFILENAME_TEMPLATE");
227
228     if (GetOpenFileName(ofn)) {
229         g_free( (void *) ofn->lpstrFilter);
230         g_free( (void *) ofn);
231
232         if (cf_open(&cfile, utf_16to8(file_name), FALSE, &err) != CF_OK) {
233             return FALSE;
234         }
235
236         /* apply our filter */
237         if (dfilter_compile(dfilter_str, &dfp)) {
238             cf_set_rfcode(&cfile, dfp);
239         }
240
241         switch (cf_read(&cfile, FALSE)) {
242             case CF_READ_OK:
243             case CF_READ_ERROR:
244                 dirname = get_dirname(utf_16to8(file_name));
245                 set_last_open_dir(dirname);
246                 return TRUE;
247                 break;
248         }
249     } else {
250         g_free( (void *) ofn->lpstrFilter);
251         g_free( (void *) ofn);
252     }
253     return FALSE;
254 }
255
256
257 void
258 win32_save_as_file(HWND h_wnd, action_after_save_e action_after_save, gpointer action_after_save_data) {
259     OPENFILENAME *ofn;
260     TCHAR  file_name16[MAX_PATH] = _T("");
261     GString *file_name8;
262     gchar *file_last_dot;
263     gchar *dirname;
264     int save_index;
265     int    ofnsize;
266 #if (_MSC_VER >= 1500)
267     OSVERSIONINFO osvi;
268 #endif
269
270     /* see OPENFILENAME comment in win32_open_file */
271 #if (_MSC_VER >= 1500)
272     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
273     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
274     GetVersionEx(&osvi);
275     if (osvi.dwMajorVersion >= 5) {
276         ofnsize = sizeof(OPENFILENAME);
277     } else {
278         ofnsize = OPENFILENAME_SIZE_VERSION_400;
279     }
280 #else
281     ofnsize = sizeof(OPENFILENAME) + 12;
282 #endif
283     ofn = g_malloc0(ofnsize);
284
285     ofn->lStructSize = ofnsize;
286     ofn->hwndOwner = h_wnd;
287 #if (_MSC_VER <= 1200)
288     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
289 #else
290     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
291 #endif
292     ofn->lpstrFilter = build_file_type_list(TRUE /*save*/, &save_index);
293     ofn->lpstrCustomFilter = NULL;
294     ofn->nMaxCustFilter = 0;
295     ofn->nFilterIndex = save_index;
296     ofn->lpstrFile = file_name16;
297     ofn->nMaxFile = MAX_PATH;
298     ofn->lpstrFileTitle = NULL;
299     ofn->nMaxFileTitle = 0;
300     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
301     ofn->lpstrTitle = _T("Wireshark: Save file as");
302     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
303                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
304                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
305     ofn->lpstrDefExt = NULL;
306     ofn->lpfnHook = save_as_file_hook_proc;
307     ofn->lpTemplateName = _T("WIRESHARK_SAVEFILENAME_TEMPLATE");
308
309     if (GetSaveFileName(ofn)) {
310         filetype = file_type_from_list_index(TRUE /*save*/, ofn->nFilterIndex);
311
312         /* append the default file extension if there's none given by the user */
313         /* (we expect a file extension to be at most 5 chars + the dot) */
314         file_name8 = g_string_new(utf_16to8(file_name16));
315         file_last_dot = strrchr(file_name8->str,'.');
316         if(file_last_dot == NULL || strlen(file_name8->str)-(file_last_dot-file_name8->str) > 5+1) {
317             if(wtap_file_extension_default_string(filetype) != NULL) {
318                 file_name8 = g_string_append(file_name8, wtap_file_extension_default_string(filetype));
319             }
320         }
321
322         g_sf_hwnd = NULL;
323         /* Write out the packets (all, or only the ones from the current
324            range) to the file with the specified name. */
325
326         /* GetSaveFileName() already asked the user if he wants to overwrite the old file,        */
327         /* so if we are here, user already confirmed to overwrite - just delete the old file now. */
328         /* Note: Windows ws_unlink cannot delete a currently open file; Therefore the             */
329         /*       GetSaveFileName dialog has been coded to prevent doing a 'save as' to the        */
330         /*       currently open capture file.                                                     */
331         /* XX: Windows Wireshark is built with GLIB >= 2.6 these       */
332         /*     days so ws_unlink will properly convert the             */
333         /*     UTF8 filename to UTF16 & then do a _wunlink.            */
334         /* XX: if the cf_save fails, it will do a GTK simple_dialog()  */
335         /*     which is not useful while doing a Windows dialog.       */
336         /*     (A GTK dialog box will be generated and basically will  */
337         /*     only appear when the redisplayed Windows 'save_as-file' */
338         /*     dialog is dismissed. It will then need to be dismissed. */
339         /*     This should be fixed even though the cf_save()          */
340         /*     presumably should rarely fail in this case.             */
341         if ((ws_unlink(file_name8->str) != 0) && (errno == EACCES)) {
342             /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
343             gchar *str = g_strdup_printf("Unable to delete file: %s\nPlease choose another name !", file_name8->str);
344             MessageBox( NULL, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
345             g_free(str);
346             goto AGAIN;
347         }
348         if (cf_save(&cfile, file_name8->str, &g_range, filetype, FALSE) != CF_OK) {
349             /* The write failed.  Try again. */
350         AGAIN:
351             g_string_free(file_name8, TRUE /* free_segment */);
352             g_free( (void *) ofn->lpstrFilter);
353             g_free( (void *) ofn);
354             win32_save_as_file(h_wnd, action_after_save, action_after_save_data);
355             return;
356         }
357
358         /* Save the directory name for future file dialogs. */
359         dirname = get_dirname(file_name8->str);  /* Overwrites cf_name */
360         set_last_open_dir(dirname);
361
362         g_string_free(file_name8, TRUE /* free_segment */);
363
364         /* we have finished saving, do we have pending things to do? */
365         switch(action_after_save) {
366             case(after_save_no_action):
367                 break;
368             case(after_save_open_dialog):
369                 win32_open_file(h_wnd);
370                 break;
371             case(after_save_open_recent_file):
372                 menu_open_recent_file_cmd(action_after_save_data);
373                 break;
374             case(after_save_open_dnd_file):
375                 dnd_open_file_cmd(action_after_save_data);
376                 break;
377             case(after_save_merge_dialog):
378                 win32_merge_file(h_wnd);
379                 break;
380 #ifdef HAVE_LIBPCAP
381             case(after_save_capture_dialog):
382                 capture_start_confirmed();
383                 break;
384 #endif
385             case(after_save_close_file):
386                 cf_close(&cfile);
387                 break;
388             case(after_save_exit):
389                 main_do_quit();
390                 break;
391             default:
392                 g_assert_not_reached();
393         }
394     }
395     g_sf_hwnd = NULL;
396     g_free( (void *) ofn->lpstrFilter);
397     g_free( (void *) ofn);
398 }
399
400
401 void
402 win32_merge_file (HWND h_wnd) {
403     OPENFILENAME *ofn;
404     TCHAR       file_name[MAX_PATH] = _T("");
405     char       *dirname;
406     cf_status_t merge_status = CF_ERROR;
407     char       *in_filenames[2];
408     int         err;
409     char       *tmpname;
410     dfilter_t  *dfp;
411     int         ofnsize;
412 #if (_MSC_VER >= 1500)
413     OSVERSIONINFO osvi;
414 #endif
415
416     /* see OPENFILENAME comment in win32_open_file */
417 #if (_MSC_VER >= 1500)
418     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
419     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
420     GetVersionEx(&osvi);
421     if (osvi.dwMajorVersion >= 5) {
422         ofnsize = sizeof(OPENFILENAME);
423     } else {
424         ofnsize = OPENFILENAME_SIZE_VERSION_400;
425     }
426 #else
427     ofnsize = sizeof(OPENFILENAME) + 12;
428 #endif
429     ofn = g_malloc0(ofnsize);
430
431     ofn->lStructSize = ofnsize;
432     ofn->hwndOwner = h_wnd;
433 #if (_MSC_VER <= 1200)
434     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
435 #else
436     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
437 #endif
438     ofn->lpstrFilter = build_file_type_list(FALSE /*!save*/, NULL);
439     ofn->lpstrCustomFilter = NULL;
440     ofn->nMaxCustFilter = 0;
441     ofn->nFilterIndex = FILE_MERGE_DEFAULT;
442     ofn->lpstrFile = file_name;
443     ofn->nMaxFile = MAX_PATH;
444     ofn->lpstrFileTitle = NULL;
445     ofn->nMaxFileTitle = 0;
446     if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
447         ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
448     } else {
449         ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
450     }
451     ofn->lpstrTitle = _T("Wireshark: Merge with capture file");
452     ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER     |
453                  OFN_NOCHANGEDIR  | OFN_FILEMUSTEXIST  | OFN_HIDEREADONLY |
454                  OFN_ENABLEHOOK   | OFN_SHOWHELP;
455     ofn->lpstrDefExt = NULL;
456     ofn->lpfnHook = merge_file_hook_proc;
457     ofn->lpTemplateName = _T("WIRESHARK_MERGEFILENAME_TEMPLATE");
458
459     if (GetOpenFileName(ofn)) {
460         filetype = cfile.cd_t;
461         g_free( (void *) ofn->lpstrFilter);
462         g_free( (void *) ofn);
463
464         /* merge or append the two files */
465
466         tmpname = NULL;
467         switch (merge_action) {
468             case merge_append:
469                 /* append file */
470                 in_filenames[0] = cfile.filename;
471                 in_filenames[1] = utf_16to8(file_name);
472                 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, TRUE);
473                 break;
474             case merge_chrono:
475                 /* chonological order */
476                 in_filenames[0] = cfile.filename;
477                 in_filenames[1] = utf_16to8(file_name);
478                 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, FALSE);
479                 break;
480             case merge_prepend:
481                 /* prepend file */
482                 in_filenames[0] = utf_16to8(file_name);
483                 in_filenames[1] = cfile.filename;
484                 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, TRUE);
485                 break;
486             default:
487                 g_assert_not_reached();
488         }
489
490         if(merge_status != CF_OK) {
491             /* merge failed */
492             g_free(tmpname);
493             return;
494         }
495
496         cf_close(&cfile);
497
498         /* Try to open the merged capture file. */
499         if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
500             /* We couldn't open it; don't dismiss the open dialog box,
501                just leave it around so that the user can, after they
502                dismiss the alert box popped up for the open error,
503                try again. */
504             return;
505         }
506
507         /* apply our filter */
508         if (dfilter_compile(dfilter_str, &dfp)) {
509             cf_set_rfcode(&cfile, dfp);
510         }
511
512         switch (cf_read(&cfile, FALSE)) {
513             case CF_READ_OK:
514             case CF_READ_ERROR:
515                 dirname = get_dirname(utf_16to8(file_name));
516                 set_last_open_dir(dirname);
517                 menu_name_resolution_changed();
518                 break;
519             case CF_READ_ABORTED:
520                 break;
521         }
522     } else {
523         g_free( (void *) ofn->lpstrFilter);
524         g_free( (void *) ofn);
525     }
526 }
527
528 void
529 win32_export_file(HWND h_wnd, export_type_e export_type) {
530     OPENFILENAME     *ofn;
531     TCHAR             file_name[MAX_PATH] = _T("");
532     char             *dirname;
533     cf_print_status_t status;
534     int               ofnsize;
535 #if (_MSC_VER >= 1500)
536     OSVERSIONINFO osvi;
537 #endif
538
539     /* see OPENFILENAME comment in win32_open_file */
540 #if (_MSC_VER >= 1500)
541     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
542     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
543     GetVersionEx(&osvi);
544     if (osvi.dwMajorVersion >= 5) {
545         ofnsize = sizeof(OPENFILENAME);
546     } else {
547         ofnsize = OPENFILENAME_SIZE_VERSION_400;
548     }
549 #else
550     ofnsize = sizeof(OPENFILENAME) + 12;
551 #endif
552     ofn = g_malloc0(ofnsize);
553
554     ofn->lStructSize = ofnsize;
555     ofn->hwndOwner = h_wnd;
556 #if (_MSC_VER <= 1200)
557     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
558 #else
559     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
560 #endif
561     ofn->lpstrFilter = FILE_TYPES_EXPORT;
562     ofn->lpstrCustomFilter = NULL;
563     ofn->nMaxCustFilter = 0;
564     ofn->nFilterIndex = export_type;
565     ofn->lpstrFile = file_name;
566     ofn->nMaxFile = MAX_PATH;
567     ofn->lpstrFileTitle = NULL;
568     ofn->nMaxFileTitle = 0;
569     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
570     ofn->lpstrTitle = _T("Wireshark: Export File");
571     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
572                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
573                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
574     ofn->lpstrDefExt = NULL;
575     ofn->lpfnHook = export_file_hook_proc;
576     ofn->lpTemplateName = _T("WIRESHARK_EXPORTFILENAME_TEMPLATE");
577
578     /* Fill in our print (and export) args */
579
580     print_args.format              = PR_FMT_TEXT;
581     print_args.to_file             = TRUE;
582     print_args.cmd                 = NULL;
583     print_args.print_summary       = TRUE;
584     print_args.print_dissections   = print_dissections_as_displayed;
585     print_args.print_hex           = FALSE;
586     print_args.print_formfeed      = FALSE;
587
588     if (GetSaveFileName(ofn)) {
589         print_args.file = utf_16to8(file_name);
590         switch (ofn->nFilterIndex) {
591             case export_type_text:      /* Text */
592                 print_args.stream = print_stream_text_new(TRUE, print_args.file);
593                 if (print_args.stream == NULL) {
594                     open_failure_alert_box(print_args.file, errno, TRUE);
595                     g_free( (void *) ofn);
596                     return;
597                 }
598                 status = cf_print_packets(&cfile, &print_args);
599                 break;
600             case export_type_ps:        /* PostScript (r) */
601                 print_args.stream = print_stream_ps_new(TRUE, print_args.file);
602                 if (print_args.stream == NULL) {
603                     open_failure_alert_box(print_args.file, errno, TRUE);
604                     g_free( (void *) ofn);
605                     return;
606                 }
607                 status = cf_print_packets(&cfile, &print_args);
608                 break;
609             case export_type_csv:       /* CSV */
610                 status = cf_write_csv_packets(&cfile, &print_args);
611                 break;
612             case export_type_carrays:   /* C Arrays */
613                 status = cf_write_carrays_packets(&cfile, &print_args);
614                 break;
615             case export_type_psml:      /* PSML */
616                 status = cf_write_psml_packets(&cfile, &print_args);
617                 break;
618             case export_type_pdml:      /* PDML */
619                 status = cf_write_pdml_packets(&cfile, &print_args);
620                 break;
621             default:
622                 g_free( (void *) ofn);
623                 return;
624         }
625
626         switch (status) {
627             case CF_PRINT_OK:
628                 break;
629             case CF_PRINT_OPEN_ERROR:
630                 open_failure_alert_box(print_args.file, errno, TRUE);
631                 break;
632             case CF_PRINT_WRITE_ERROR:
633                 write_failure_alert_box(print_args.file, errno);
634                 break;
635         }
636         /* Save the directory name for future file dialogs. */
637         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
638         set_last_open_dir(dirname);
639     }
640
641     g_free( (void *) ofn);
642 }
643
644 void
645 win32_export_raw_file(HWND h_wnd) {
646     OPENFILENAME *ofn;
647     TCHAR         file_name[MAX_PATH] = _T("");
648     char         *dirname;
649     const guint8 *data_p;
650     char         *file_name8;
651     int           fd;
652     int           ofnsize;
653 #if (_MSC_VER >= 1500)
654     OSVERSIONINFO osvi;
655 #endif
656
657     if (!cfile.finfo_selected) {
658         /* This shouldn't happen */
659         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No bytes were selected.");
660         return;
661     }
662
663     /* see OPENFILENAME comment in win32_open_file */
664 #if (_MSC_VER >= 1500)
665     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
666     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
667     GetVersionEx(&osvi);
668     if (osvi.dwMajorVersion >= 5) {
669         ofnsize = sizeof(OPENFILENAME);
670     } else {
671         ofnsize = OPENFILENAME_SIZE_VERSION_400;
672     }
673 #else
674     ofnsize = sizeof(OPENFILENAME) + 12;
675 #endif
676     ofn = g_malloc0(ofnsize);
677
678     ofn->lStructSize = ofnsize;
679     ofn->hwndOwner = h_wnd;
680 #if (_MSC_VER <= 1200)
681     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
682 #else
683     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
684 #endif
685     ofn->lpstrFilter = FILE_TYPES_RAW;
686     ofn->lpstrCustomFilter = NULL;
687     ofn->nMaxCustFilter = 0;
688     ofn->nFilterIndex = FILE_RAW_DEFAULT;
689     ofn->lpstrFile = file_name;
690     ofn->nMaxFile = MAX_PATH;
691     ofn->lpstrFileTitle = NULL;
692     ofn->nMaxFileTitle = 0;
693     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
694     ofn->lpstrTitle = _T("Wireshark: Export Raw Data");
695     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
696                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
697                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
698     ofn->lpstrDefExt = NULL;
699     ofn->lCustData = cfile.finfo_selected->length;
700     ofn->lpfnHook = export_raw_file_hook_proc;
701     ofn->lpTemplateName = _T("WIRESHARK_EXPORTRAWFILENAME_TEMPLATE");
702
703     /*
704      * XXX - The GTK+ code uses get_byte_view_data_and_length().  We just
705      * grab the info from cfile.finfo_selected.  Which is more "correct"?
706      */
707
708     if (GetSaveFileName(ofn)) {
709         g_free( (void *) ofn);
710         file_name8 = utf_16to8(file_name);
711         data_p = tvb_get_ptr(cfile.finfo_selected->ds_tvb, 0, -1) +
712                 cfile.finfo_selected->start;
713         fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
714         if (fd == -1) {
715             open_failure_alert_box(file_name8, errno, TRUE);
716             return;
717         }
718         if (write(fd, data_p, cfile.finfo_selected->length) < 0) {
719             write_failure_alert_box(file_name8, errno);
720             close(fd);
721             return;
722         }
723         if (close(fd) < 0) {
724             write_failure_alert_box(file_name8, errno);
725             return;
726         }
727
728         /* Save the directory name for future file dialogs. */
729         dirname = get_dirname(file_name8);  /* Overwrites cf_name */
730         set_last_open_dir(dirname);
731     } else {
732         g_free( (void *) ofn);
733     }
734 }
735
736 void
737 win32_export_sslkeys_file(HWND h_wnd) {
738     OPENFILENAME *ofn;
739     TCHAR         file_name[MAX_PATH] = _T("");
740     char         *dirname;
741     StringInfo   *keylist;
742     char         *file_name8;
743     int           fd;
744     int           ofnsize;
745     int           keylist_size;
746 #if (_MSC_VER >= 1500)
747     OSVERSIONINFO osvi;
748 #endif
749
750     keylist_size = g_hash_table_size(ssl_session_hash);
751     if (keylist_size==0) {
752         /* This shouldn't happen */
753         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No SSL Session Keys to export.");
754         return;
755     }
756
757     /* see OPENFILENAME comment in win32_open_file */
758 #if (_MSC_VER >= 1500)
759     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
760     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
761     GetVersionEx(&osvi);
762     if (osvi.dwMajorVersion >= 5) {
763         ofnsize = sizeof(OPENFILENAME);
764     } else {
765         ofnsize = OPENFILENAME_SIZE_VERSION_400;
766     }
767 #else
768     ofnsize = sizeof(OPENFILENAME) + 12;
769 #endif
770     ofn = g_malloc0(ofnsize);
771
772     ofn->lStructSize = ofnsize;
773     ofn->hwndOwner = h_wnd;
774 #if (_MSC_VER <= 1200)
775     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
776 #else
777     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
778 #endif
779     ofn->lpstrFilter = FILE_TYPES_SSLKEYS;
780     ofn->lpstrCustomFilter = NULL;
781     ofn->nMaxCustFilter = 0;
782     ofn->nFilterIndex = FILE_SSLKEYS_DEFAULT;
783     ofn->lpstrFile = file_name;
784     ofn->nMaxFile = MAX_PATH;
785     ofn->lpstrFileTitle = NULL;
786     ofn->nMaxFileTitle = 0;
787     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
788     ofn->lpstrTitle = _T("Wireshark: Export SSL Session Keys");
789     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
790                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
791                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
792     ofn->lpstrDefExt = NULL;
793     ofn->lCustData = keylist_size;
794     ofn->lpfnHook = export_sslkeys_file_hook_proc;
795     ofn->lpTemplateName = _T("WIRESHARK_EXPORTSSLKEYSFILENAME_TEMPLATE");
796
797     if (GetSaveFileName(ofn)) {
798         g_free( (void *) ofn);
799         file_name8 = utf_16to8(file_name);
800         keylist = ssl_export_sessions(ssl_session_hash);
801         fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
802         if (fd == -1) {
803             open_failure_alert_box(file_name8, errno, TRUE);
804             g_free(keylist);
805             return;
806         }
807         /*
808          * Thanks, Microsoft, for not using size_t for the third argument to
809          * _write().  Presumably this string will be <= 4GiB long....
810          */
811         if (ws_write(fd, keylist->data, (unsigned int)strlen(keylist->data)) < 0) {
812             write_failure_alert_box(file_name8, errno);
813             ws_close(fd);
814             g_free(keylist);
815             return;
816         }
817         if (ws_close(fd) < 0) {
818             write_failure_alert_box(file_name8, errno);
819             g_free(keylist);
820             return;
821         }
822
823         /* Save the directory name for future file dialogs. */
824         dirname = get_dirname(file_name8);  /* Overwrites cf_name */
825         set_last_open_dir(dirname);
826     } else {
827         g_free( (void *) ofn);
828     }
829     g_free(keylist);
830 }
831
832 void
833 win32_export_color_file(HWND h_wnd, gpointer filter_list) {
834     OPENFILENAME *ofn;
835     TCHAR  file_name[MAX_PATH] = _T("");
836     gchar *dirname;
837     int    ofnsize;
838 #if (_MSC_VER >= 1500)
839     OSVERSIONINFO osvi;
840 #endif
841
842     /* see OPENFILENAME comment in win32_open_file */
843 #if (_MSC_VER >= 1500)
844     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
845     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
846     GetVersionEx(&osvi);
847     if (osvi.dwMajorVersion >= 5) {
848         ofnsize = sizeof(OPENFILENAME);
849     } else {
850         ofnsize = OPENFILENAME_SIZE_VERSION_400;
851     }
852 #else
853     ofnsize = sizeof(OPENFILENAME) + 12;
854 #endif
855     ofn = g_malloc0(ofnsize);
856
857     ofn->lStructSize = ofnsize;
858     ofn->hwndOwner = h_wnd;
859 #if (_MSC_VER <= 1200)
860     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
861 #else
862     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
863 #endif
864     ofn->lpstrFilter = FILE_TYPES_COLOR;
865     ofn->lpstrCustomFilter = NULL;
866     ofn->nMaxCustFilter = 0;
867     ofn->nFilterIndex = FILE_DEFAULT_COLOR;
868     ofn->lpstrFile = file_name;
869     ofn->nMaxFile = MAX_PATH;
870     ofn->lpstrFileTitle = NULL;
871     ofn->nMaxFileTitle = 0;
872     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
873     ofn->lpstrTitle = _T("Wireshark: Export Color Filters");
874     ofn->Flags = OFN_ENABLESIZING  | OFN_EXPLORER        |
875                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
876                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
877     ofn->lpstrDefExt = NULL;
878     ofn->lpfnHook = NULL;
879     ofn->lpTemplateName = NULL;
880
881     filetype = cfile.cd_t;
882
883     /* XXX - Support marked filters */
884     if (GetSaveFileName(ofn)) {
885         g_free( (void *) ofn);
886         if (!color_filters_export(utf_16to8(file_name), filter_list, FALSE /* all filters */))
887             return;
888
889         /* Save the directory name for future file dialogs. */
890         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
891         set_last_open_dir(dirname);
892     } else {
893         g_free( (void *) ofn);
894     }
895 }
896
897 void
898 win32_import_color_file(HWND h_wnd, gpointer color_filters) {
899     OPENFILENAME *ofn;
900     TCHAR  file_name[MAX_PATH] = _T("");
901     gchar *dirname;
902     int    ofnsize;
903 #if (_MSC_VER >= 1500)
904     OSVERSIONINFO osvi;
905 #endif
906
907     /* see OPENFILENAME comment in win32_open_file */
908 #if (_MSC_VER >= 1500)
909     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
910     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
911     GetVersionEx(&osvi);
912     if (osvi.dwMajorVersion >= 5) {
913         ofnsize = sizeof(OPENFILENAME);
914     } else {
915         ofnsize = OPENFILENAME_SIZE_VERSION_400;
916     }
917 #else
918     ofnsize = sizeof(OPENFILENAME) + 12;
919 #endif
920     ofn = g_malloc0(ofnsize);
921
922     ofn->lStructSize = ofnsize;
923     ofn->hwndOwner = h_wnd;
924 #if (_MSC_VER <= 1200)
925     ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
926 #else
927     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
928 #endif
929     ofn->lpstrFilter = FILE_TYPES_COLOR;
930     ofn->lpstrCustomFilter = NULL;
931     ofn->nMaxCustFilter = 0;
932     ofn->nFilterIndex = FILE_DEFAULT_COLOR;
933     ofn->lpstrFile = file_name;
934     ofn->nMaxFile = MAX_PATH;
935     ofn->lpstrFileTitle = NULL;
936     ofn->nMaxFileTitle = 0;
937     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
938     ofn->lpstrTitle = _T("Wireshark: Import Color Filters");
939     ofn->Flags = OFN_ENABLESIZING  | OFN_EXPLORER        |
940                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
941                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
942     ofn->lpstrDefExt = NULL;
943     ofn->lpfnHook = NULL;
944     ofn->lpTemplateName = NULL;
945
946     /* XXX - Support export limited to selected filters */
947     if (GetOpenFileName(ofn)) {
948         g_free( (void *) ofn);
949         if (!color_filters_import(utf_16to8(file_name), color_filters))
950             return;
951
952         /* Save the directory name for future file dialogs. */
953         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
954         set_last_open_dir(dirname);
955     } else {
956         g_free( (void *) ofn);
957     }
958 }
959
960
961 /*
962  * Private routines
963  */
964
965 /** Given a print_args_t struct, update a set of print/export format controls
966  *  accordingly.
967  *
968  * @param dlg_hwnd HWND of the dialog in question.
969  * @param args Pointer to a print args struct.
970  */
971 static void
972 print_update_dynamic(HWND dlg_hwnd, print_args_t *args) {
973     HWND cur_ctrl;
974
975     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
976     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
977         args->print_summary = TRUE;
978     else
979         args->print_summary = FALSE;
980
981     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
982     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
983         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
984         switch (SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0)) {
985             case 0:
986                 args->print_dissections = print_dissections_collapsed;
987                 break;
988             case 1:
989                 args->print_dissections = print_dissections_as_displayed;
990                 break;
991             case 2:
992                 args->print_dissections = print_dissections_expanded;
993                 break;
994             default:
995                 g_assert_not_reached();
996         }
997         EnableWindow(cur_ctrl, TRUE);
998     } else {
999         args->print_dissections = print_dissections_none;
1000         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
1001         EnableWindow(cur_ctrl, FALSE);
1002     }
1003
1004     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
1005     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1006         args->print_hex = TRUE;
1007     else
1008         args->print_hex = FALSE;
1009
1010     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
1011     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1012         args->print_formfeed = TRUE;
1013     else
1014         args->print_formfeed = FALSE;
1015 }
1016
1017 static void
1018 format_handle_wm_initdialog(HWND dlg_hwnd, print_args_t *args) {
1019     HWND cur_ctrl;
1020
1021     /* Set the "Packet summary" box */
1022     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
1023     SendMessage(cur_ctrl, BM_SETCHECK, args->print_summary, 0);
1024
1025     /* Set the "Packet details" box */
1026     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
1027     SendMessage(cur_ctrl, BM_SETCHECK, args->print_dissections != print_dissections_none, 0);
1028
1029     /* Set the "Packet details" combo */
1030     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
1031     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All collapsed"));
1032     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("As displayed"));
1033     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All expanded"));
1034
1035     switch (args->print_dissections) {
1036         case print_dissections_none:
1037         case print_dissections_collapsed:
1038             SendMessage(cur_ctrl, CB_SETCURSEL, 0, 0);
1039             break;
1040         case print_dissections_as_displayed:
1041             SendMessage(cur_ctrl, CB_SETCURSEL, 1, 0);
1042             break;
1043         case print_dissections_expanded:
1044             SendMessage(cur_ctrl, CB_SETCURSEL, 2, 0);
1045         default:
1046             g_assert_not_reached();
1047     }
1048
1049     /* Set the "Packet bytes" box */
1050     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
1051     SendMessage(cur_ctrl, BM_SETCHECK, args->print_hex, 0);
1052
1053     /* Set the "Each packet on a new page" box */
1054     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
1055     SendMessage(cur_ctrl, BM_SETCHECK, args->print_formfeed, 0);
1056
1057     print_update_dynamic(dlg_hwnd, args);
1058 }
1059
1060
1061 #define PREVIEW_STR_MAX      200
1062
1063 /* If preview_file is NULL, disable the elements.  If not, enable and
1064  * show the preview info. */
1065 static gboolean
1066 preview_set_filename(HWND of_hwnd, gchar *preview_file) {
1067     HWND        cur_ctrl;
1068     int         i;
1069     gboolean    enable = FALSE;
1070     wtap       *wth;
1071     const struct wtap_pkthdr *phdr;
1072     int         err = 0;
1073     gchar      *err_info;
1074     TCHAR       string_buff[PREVIEW_STR_MAX];
1075     gint64      data_offset;
1076     guint       packet = 0;
1077     gint64      filesize;
1078     time_t      ti_time;
1079     struct tm  *ti_tm;
1080     guint       elapsed_time;
1081     time_t      time_preview;
1082     time_t      time_current;
1083     double      start_time = 0;
1084     double      stop_time = 0;
1085     double      cur_time;
1086     gboolean    is_breaked = FALSE;
1087
1088     if (preview_file != NULL && strlen(preview_file) > 0) {
1089         enable = TRUE;
1090     }
1091
1092     for (i = EWFD_PT_FILENAME; i <= EWFD_PTX_ELAPSED; i++) {
1093         cur_ctrl = GetDlgItem(of_hwnd, i);
1094         if (cur_ctrl) {
1095             EnableWindow(cur_ctrl, enable);
1096         }
1097     }
1098
1099     for (i = EWFD_PTX_FILENAME; i <= EWFD_PTX_ELAPSED; i++) {
1100         cur_ctrl = GetDlgItem(of_hwnd, i);
1101         if (cur_ctrl) {
1102             SetWindowText(cur_ctrl, _T("-"));
1103         }
1104     }
1105
1106     if (enable) {
1107         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FILENAME);
1108         SetWindowText(cur_ctrl, utf_8to16(get_basename(preview_file)));
1109
1110         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
1111         wth = wtap_open_offline(preview_file, &err, &err_info, TRUE);
1112         if (cur_ctrl && wth == NULL) {
1113             if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
1114                 SetWindowText(cur_ctrl, _T("unknown file format"));
1115             } else {
1116                 SetWindowText(cur_ctrl, _T("error opening file"));
1117             }
1118             return FALSE;
1119         }
1120
1121         /* size */
1122         filesize = wtap_file_size(wth, &err);
1123         utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_FORMAT " bytes", filesize);
1124         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
1125         SetWindowText(cur_ctrl, string_buff);
1126
1127         /* type */
1128         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
1129         SetWindowText(cur_ctrl, utf_8to16(wtap_file_type_string(wtap_file_type(wth))));
1130
1131         time(&time_preview);
1132         while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
1133             phdr = wtap_phdr(wth);
1134             cur_time = nstime_to_sec( (const nstime_t *) &phdr->ts );
1135             if(packet == 0) {
1136                 start_time  = cur_time;
1137                 stop_time = cur_time;
1138             }
1139             if (cur_time < start_time) {
1140                 start_time = cur_time;
1141             }
1142             if (cur_time > stop_time){
1143                 stop_time = cur_time;
1144             }
1145             packet++;
1146             if(packet%100 == 0) {
1147                 time(&time_current);
1148                 if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
1149                     is_breaked = TRUE;
1150                     break;
1151                 }
1152             }
1153         }
1154
1155         if(err != 0) {
1156             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("error after reading %u packets"), packet);
1157             cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
1158             SetWindowText(cur_ctrl, string_buff);
1159             wtap_close(wth);
1160             return TRUE;
1161         }
1162
1163         /* packet count */
1164         if(is_breaked) {
1165             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("more than %u packets (preview timeout)"), packet);
1166         } else {
1167             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%u"), packet);
1168         }
1169         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
1170         SetWindowText(cur_ctrl, string_buff);
1171
1172         /* first packet */
1173         ti_time = (long)start_time;
1174         ti_tm = localtime( &ti_time );
1175         if(ti_tm) {
1176             _snwprintf(string_buff, PREVIEW_STR_MAX,
1177                      _T("%04d-%02d-%02d %02d:%02d:%02d"),
1178                      ti_tm->tm_year + 1900,
1179                      ti_tm->tm_mon + 1,
1180                      ti_tm->tm_mday,
1181                      ti_tm->tm_hour,
1182                      ti_tm->tm_min,
1183                      ti_tm->tm_sec);
1184         } else {
1185             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("?"));
1186         }
1187         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FIRST_PKT);
1188         SetWindowText(cur_ctrl, string_buff);
1189
1190         /* elapsed time */
1191         elapsed_time = (unsigned int)(stop_time-start_time);
1192         if(elapsed_time/86400) {
1193             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%02u days %02u:%02u:%02u"),
1194             elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
1195         } else {
1196             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%02u:%02u:%02u"),
1197             elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
1198         }
1199         if(is_breaked) {
1200             _snwprintf(string_buff, PREVIEW_STR_MAX, _T("unknown"));
1201         }
1202         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_ELAPSED);
1203         SetWindowText(cur_ctrl, string_buff);
1204
1205         wtap_close(wth);
1206     }
1207
1208     return TRUE;
1209
1210 }
1211
1212
1213 static char *
1214 filter_tb_get(HWND hwnd) {
1215     TCHAR     *strval = NULL;
1216     gint       len;
1217     char *ret;
1218
1219     /* If filter_text is non-NULL, use it.  Otherwise, grab the text from
1220      * the window */
1221     len = GetWindowTextLength(hwnd);
1222     if (len > 0) {
1223         len++;
1224         strval = g_malloc(len*sizeof(TCHAR));
1225         len = GetWindowText(hwnd, strval, len);
1226         ret = g_utf16_to_utf8(strval, -1, NULL, NULL, NULL);
1227         g_free(strval);
1228         return ret;
1229     } else {
1230         return NULL;
1231     }
1232 }
1233
1234
1235 /* XXX - Copied from "filter-util.c" in the wireshark-win32 branch */
1236 /* XXX - The only reason for the "filter_text" parameter is to be able to feed
1237  * in the "real" filter string in the case of a CBN_SELCHANGE notification message.
1238  */
1239 static void
1240 filter_tb_syntax_check(HWND hwnd, TCHAR *filter_text) {
1241     TCHAR     *strval = NULL;
1242     gint       len;
1243     dfilter_t *dfp;
1244
1245     /* If filter_text is non-NULL, use it.  Otherwise, grab the text from
1246      * the window */
1247     if (filter_text) {
1248         len = (lstrlen(filter_text) + 1) * sizeof(TCHAR);
1249         strval = g_malloc(len);
1250         memcpy(strval, filter_text, len);
1251     } else {
1252         len = GetWindowTextLength(hwnd);
1253         if (len > 0) {
1254             len++;
1255             strval = g_malloc(len*sizeof(TCHAR));
1256             len = GetWindowText(hwnd, strval, len);
1257         }
1258     }
1259
1260     if (len == 0) {
1261         /* Default window background */
1262         SendMessage(hwnd, EM_SETBKGNDCOLOR, (WPARAM) 1, COLOR_WINDOW);
1263         return;
1264     } else if (dfilter_compile(utf_16to8(strval), &dfp)) { /* colorize filter string entry */
1265         if (dfp != NULL)
1266             dfilter_free(dfp);
1267         /* Valid (light green) */
1268         SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, 0x00afffaf);
1269     } else {
1270         /* Invalid (light red) */
1271         SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, 0x00afafff);
1272     }
1273
1274     if (strval) g_free(strval);
1275 }
1276
1277
1278 #if (_MSC_VER <= 1200)
1279 static UINT CALLBACK
1280 #else
1281 static UINT_PTR CALLBACK
1282 #endif
1283 open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1284     HWND      cur_ctrl, parent;
1285     OFNOTIFY *notify = (OFNOTIFY *) l_param;
1286     TCHAR     sel_name[MAX_PATH];
1287
1288     switch(msg) {
1289         case WM_INITDIALOG:
1290             /* Retain the filter text, and fill it in. */
1291             if(dfilter_str != NULL) {
1292                 cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
1293                 SetWindowText(cur_ctrl, utf_8to16(dfilter_str));
1294             }
1295
1296             /* Fill in our resolution values */
1297             cur_ctrl = GetDlgItem(of_hwnd, EWFD_MAC_NR_CB);
1298             SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags & RESOLV_MAC, 0);
1299             cur_ctrl = GetDlgItem(of_hwnd, EWFD_NET_NR_CB);
1300             SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags & RESOLV_NETWORK, 0);
1301             cur_ctrl = GetDlgItem(of_hwnd, EWFD_TRANS_NR_CB);
1302             SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags & RESOLV_TRANSPORT, 0);
1303
1304             preview_set_filename(of_hwnd, NULL);
1305             break;
1306         case WM_NOTIFY:
1307             switch (notify->hdr.code) {
1308                 case CDN_FILEOK:
1309                     /* Fetch the read filter */
1310                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
1311                     if (dfilter_str)
1312                         g_free(dfilter_str);
1313                     dfilter_str = filter_tb_get(cur_ctrl);
1314
1315                     /* Fetch our resolution values */
1316                     gbl_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
1317                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_MAC_NR_CB);
1318                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1319                         gbl_resolv_flags |= RESOLV_MAC;
1320                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_NET_NR_CB);
1321                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1322                         gbl_resolv_flags |= RESOLV_NETWORK;
1323                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_TRANS_NR_CB);
1324                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1325                         gbl_resolv_flags |= RESOLV_TRANSPORT;
1326                     break;
1327                 case CDN_SELCHANGE:
1328                     /* This _almost_ works correctly. We need to handle directory
1329                        selections, etc. */
1330                     parent = GetParent(of_hwnd);
1331                     CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
1332                     preview_set_filename(of_hwnd, utf_16to8(sel_name));
1333                     break;
1334                 case CDN_HELP:
1335                     topic_cb(NULL, HELP_OPEN_WIN32_DIALOG);
1336                     break;
1337                 default:
1338                     break;
1339             }
1340             break;
1341         case WM_COMMAND:
1342             cur_ctrl = (HWND) l_param;
1343             switch(w_param) {
1344                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
1345                     filter_tb_syntax_check(cur_ctrl, NULL);
1346                     break;
1347                     /*
1348                      * If we ever figure out a way to integrate the Windows
1349                      * and GTK+ event loops (or make a native filter dialog),
1350                      * we can re-enable the "Filter" button.
1351                      */
1352                     /*
1353                 case EWFD_FILTER_BTN:
1354                     break;
1355                      */
1356                 default:
1357                     break;
1358             }
1359             break;
1360         default:
1361             break;
1362     }
1363     return 0;
1364 }
1365
1366 /* XXX - Copied verbatim from gtk/capture_file_dlg.c.  Perhaps it
1367  * should be in wiretap instead?
1368  */
1369
1370 static gboolean
1371 can_save_with_wiretap(int ft)
1372 {
1373     /* To save a file with Wiretap, Wiretap has to handle that format,
1374      and its code to handle that format must be able to write a file
1375      with this file's encapsulation type. */
1376     return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
1377 }
1378
1379 /* Generate a list of the file types we can save this file as.
1380
1381    "filetype" is the type it has now.
1382
1383    "encap" is the encapsulation for its packets (which could be
1384    "unknown" or "per-packet").
1385
1386    "filtered" is TRUE if we're to save only the packets that passed
1387    the display filter (in which case we have to save it using Wiretap)
1388    and FALSE if we're to save the entire file (in which case, if we're
1389    saving it in the type it has already, we can just copy it).
1390
1391    The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
1392 */
1393
1394 static int
1395 file_type_from_list_index(gboolean save, int index) {
1396     int   ft;
1397     int curr_index;
1398
1399     /* Check all file types. */
1400     curr_index = 0;
1401     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1402         if (save && (!packet_range_process_all(&g_range) || ft != cfile.cd_t)) {
1403             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1404             if (!can_save_with_wiretap(ft))
1405                 continue;       /* We can't. */
1406         }
1407
1408         /* OK, we can write it out in this type. */
1409         if(wtap_file_type_string(ft) == NULL) {
1410             continue;
1411         }
1412
1413         curr_index++;
1414         if(curr_index == index) {
1415             return ft;
1416         }
1417     }
1418
1419     return -1;
1420 }
1421
1422
1423 static TCHAR *
1424 build_file_type_list(gboolean save, int *item_to_select) {
1425     int   ft;
1426     guint index;
1427     GString* str = g_string_new("");
1428     TCHAR *str16;
1429     GArray* sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
1430     guint16 zero = 0;
1431
1432
1433     /* Default to the first supported file type, if the file's current
1434        type isn't supported. */
1435     if(item_to_select) {
1436         if(save) {
1437             *item_to_select = FILE_SAVE_DEFAULT;
1438         } else {
1439             *item_to_select = FILE_OPEN_DEFAULT;
1440         }
1441     }
1442
1443     /* append the "All Files" entry */
1444     if (!save) {
1445         str16 = utf_8to16("All Files (*.*)");
1446         sa = g_array_append_vals(sa, str16, (guint) strlen("All Files (*.*)"));
1447         sa = g_array_append_val(sa, zero);
1448         str16 = utf_8to16("*.*");
1449         sa = g_array_append_vals(sa, str16, (guint) strlen("*.*"));
1450         sa = g_array_append_val(sa, zero);
1451     }
1452
1453     /* Check all file types. */
1454     index = 1;  /* the index is one based! */
1455     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1456         if (save && (!packet_range_process_all(&g_range) || ft != cfile.cd_t)) {
1457             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1458             if (!can_save_with_wiretap(ft))
1459                 continue;       /* We can't. */
1460         }
1461
1462         /* OK, we can write it out in this type. */
1463         if(wtap_file_type_string(ft) != NULL) {
1464             g_string_printf(str, "%s (%s)", wtap_file_type_string(ft), wtap_file_extensions_string(ft));
1465         } else {
1466             continue;
1467         }
1468         str16 = utf_8to16(str->str);
1469         sa = g_array_append_vals(sa, str16, (guint) strlen(str->str));
1470         sa = g_array_append_val(sa, zero);
1471
1472         g_string_printf(str, "%s", wtap_file_extensions_string(ft));
1473         str16 = utf_8to16(str->str);
1474         sa = g_array_append_vals(sa, str16, (guint) strlen(str->str));
1475         sa = g_array_append_val(sa, zero);
1476
1477         if (ft == cfile.cd_t && item_to_select != NULL) {
1478             /* Default to the same format as the file, if it's supported. */
1479             *item_to_select = index;
1480         }
1481         index++;
1482     }
1483
1484     /* terminate the array */
1485     sa = g_array_append_val(sa, zero);
1486
1487     return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
1488 }
1489
1490
1491 #if 0
1492 static void
1493 build_file_format_list(HWND sf_hwnd) {
1494     HWND  format_cb;
1495     int   ft;
1496     guint index;
1497     guint item_to_select;
1498     gchar *s;
1499
1500     /* Default to the first supported file type, if the file's current
1501        type isn't supported. */
1502     item_to_select = 0;
1503
1504     format_cb = GetDlgItem(sf_hwnd, EWFD_FILE_TYPE_COMBO);
1505     SendMessage(format_cb, CB_RESETCONTENT, 0, 0);
1506
1507     /* Check all file types. */
1508     index = 0;
1509     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1510         if (!packet_range_process_all(&g_range) || ft != cfile.cd_t) {
1511             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1512             if (!can_save_with_wiretap(ft))
1513                 continue;       /* We can't. */
1514         }
1515
1516         /* OK, we can write it out in this type. */
1517         if(wtap_file_extensions_string(ft) != NULL) {
1518             s = g_strdup_printf("%s (%s)", wtap_file_type_string(ft), wtap_file_extensions_string(ft));
1519         } else {
1520             s = g_strdup_printf("%s (*.*)", wtap_file_type_string(ft));
1521         }
1522         SendMessage(format_cb, CB_ADDSTRING, 0, (LPARAM) utf_8to16(s));
1523         g_free(s);
1524         SendMessage(format_cb, CB_SETITEMDATA, (LPARAM) index, (WPARAM) ft);
1525         if (ft == filetype) {
1526             /* Default to the same format as the file, if it's supported. */
1527             item_to_select = index;
1528         }
1529         index++;
1530     }
1531
1532     SendMessage(format_cb, CB_SETCURSEL, (WPARAM) item_to_select, 0);
1533 }
1534 #endif
1535
1536 #define RANGE_TEXT_MAX 128
1537 #if (_MSC_VER <= 1200)
1538 static UINT CALLBACK
1539 #else
1540 static UINT_PTR CALLBACK
1541 #endif
1542 save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1543     HWND           cur_ctrl;
1544     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1545     /*int            new_filetype, index;*/
1546
1547     switch(msg) {
1548         case WM_INITDIALOG:
1549             g_sf_hwnd = sf_hwnd;
1550
1551             /* Default to saving packets in the file's current format. */
1552             filetype = cfile.cd_t;
1553
1554             /* init the packet range */
1555             packet_range_init(&g_range);
1556
1557             /* Fill in the file format list */
1558             /*build_file_format_list(sf_hwnd);*/
1559
1560             range_handle_wm_initdialog(sf_hwnd, &g_range);
1561
1562             break;
1563         case WM_COMMAND:
1564             cur_ctrl = (HWND) l_param;
1565
1566             switch (w_param) {
1567 #if 0
1568                 case (CBN_SELCHANGE << 16) | EWFD_FILE_TYPE_COMBO:
1569                     index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
1570                     if (index != CB_ERR) {
1571                         new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) index, 0);
1572                         if (new_filetype != CB_ERR) {
1573                             if (filetype != new_filetype) {
1574                                 if (can_save_with_wiretap(new_filetype)) {
1575                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1576                                     EnableWindow(cur_ctrl, TRUE);
1577                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1578                                     EnableWindow(cur_ctrl, TRUE);
1579                                 } else {
1580                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1581                                     SendMessage(cur_ctrl, BM_SETCHECK, 0, 0);
1582                                     EnableWindow(cur_ctrl, FALSE);
1583                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1584                                     EnableWindow(cur_ctrl, FALSE);
1585                                 }
1586                                 filetype = new_filetype;
1587                             }
1588                         }
1589                     }
1590                     break;
1591 #endif
1592                 default:
1593                     range_handle_wm_command(sf_hwnd, cur_ctrl, w_param, &g_range);
1594                     break;
1595             }
1596             break;
1597         case WM_NOTIFY:
1598             switch (notify->hdr.code) {
1599                 case CDN_HELP:
1600                     topic_cb(NULL, HELP_SAVE_WIN32_DIALOG);
1601                     break;
1602                 case CDN_FILEOK: {
1603                     HWND   parent;
1604                     TCHAR  file_name16_selected[MAX_PATH];
1605                     char  *file_name8_selected;
1606                     int    selected_size;
1607
1608                     /* Check if trying to do 'save as' to the currently open file */
1609                     parent = GetParent(sf_hwnd);
1610                     selected_size = CommDlg_OpenSave_GetSpec(parent, file_name16_selected, MAX_PATH);
1611                     if (selected_size > 0) {
1612                         file_name8_selected = utf_16to8(file_name16_selected);
1613                         if (files_identical(cfile.filename, file_name8_selected)) {
1614                             /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
1615                             gchar *str = g_strdup_printf(
1616                                 "Capture File \"%s\" identical to loaded file !!\n\n"
1617                                 "Please choose a different filename.",
1618                                 file_name8_selected);
1619                             MessageBox( parent, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
1620                             g_free(str);
1621                             SetWindowLongPtr(sf_hwnd, DWLP_MSGRESULT, 1L); /* Don't allow ! */
1622                             return 1;
1623                         }
1624                     }
1625                 }
1626                     break;
1627                 default:
1628                     break;
1629             }
1630             break;
1631         default:
1632             break;
1633     }
1634     return 0;
1635 }
1636
1637
1638 #define STATIC_LABEL_CHARS 100
1639 /* For each range static control, fill in its value and enable/disable it. */
1640 static void
1641 range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
1642     HWND     cur_ctrl;
1643     gboolean filtered_active = FALSE;
1644     TCHAR    static_val[STATIC_LABEL_CHARS];
1645     gint     selected_num;
1646     guint32  ignored_cnt = 0, displayed_ignored_cnt = 0;
1647
1648     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1649     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1650         filtered_active = TRUE;
1651
1652     /* RANGE_SELECT_ALL */
1653     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_CAP);
1654     EnableWindow(cur_ctrl, !filtered_active);
1655     if (range->remove_ignored) {
1656         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.count - range->ignored_cnt);
1657     } else {
1658         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.count);
1659     }
1660     SetWindowText(cur_ctrl, static_val);
1661
1662     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_DISP);
1663     EnableWindow(cur_ctrl, filtered_active);
1664     if (range->remove_ignored) {
1665         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_cnt - range->displayed_ignored_cnt);
1666     } else {
1667         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_cnt);
1668     }
1669     SetWindowText(cur_ctrl, static_val);
1670
1671     /* RANGE_SELECT_CURR */
1672     selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
1673     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_CAP);
1674     EnableWindow(cur_ctrl, selected_num && !filtered_active);
1675     if (range->remove_ignored && cfile.current_frame && cfile.current_frame->flags.ignored) {
1676         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("0"));
1677     } else {
1678         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), selected_num ? 1 : 0);
1679     }
1680     SetWindowText(cur_ctrl, static_val);
1681
1682     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_DISP);
1683     EnableWindow(cur_ctrl, selected_num && filtered_active);
1684     if (range->remove_ignored && cfile.current_frame && cfile.current_frame->flags.ignored) {
1685         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("0"));
1686     } else {
1687         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), selected_num ? 1 : 0);
1688     }
1689     SetWindowText(cur_ctrl, static_val);
1690
1691     /* RANGE_SELECT_MARKED */
1692     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1693     EnableWindow(cur_ctrl, cfile.marked_count);
1694
1695     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_CAP);
1696     EnableWindow(cur_ctrl, cfile.marked_count && !filtered_active);
1697     if (range->remove_ignored) {
1698         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.marked_count - range->ignored_marked_cnt);
1699     } else {
1700         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.marked_count);
1701     }
1702     SetWindowText(cur_ctrl, static_val);
1703
1704     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_DISP);
1705     EnableWindow(cur_ctrl, cfile.marked_count && filtered_active);
1706     if (range->remove_ignored) {
1707         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt - range->displayed_ignored_marked_cnt);
1708     } else {
1709         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt);
1710     }
1711     SetWindowText(cur_ctrl, static_val);
1712
1713     /* RANGE_SELECT_MARKED_RANGE */
1714     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1715     EnableWindow(cur_ctrl, range->mark_range_cnt);
1716
1717     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_CAP);
1718     EnableWindow(cur_ctrl, range->mark_range_cnt && !filtered_active);
1719     if (range->remove_ignored) {
1720         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt - range->ignored_mark_range_cnt);
1721     } else {
1722         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt);
1723     }
1724     SetWindowText(cur_ctrl, static_val);
1725
1726     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_DISP);
1727     EnableWindow(cur_ctrl, range->displayed_mark_range_cnt && filtered_active);
1728     if (range->remove_ignored) {
1729         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt - range->displayed_ignored_mark_range_cnt);
1730     } else {
1731         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt);
1732     }
1733     SetWindowText(cur_ctrl, static_val);
1734
1735     /* RANGE_SELECT_USER */
1736     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
1737     EnableWindow(cur_ctrl, !filtered_active);
1738     if (range->remove_ignored) {
1739         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt - range->ignored_user_range_cnt);
1740     } else {
1741         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt);
1742     }
1743     SetWindowText(cur_ctrl, static_val);
1744
1745     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
1746     EnableWindow(cur_ctrl, filtered_active);
1747     if (range->remove_ignored) {
1748         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt - range->displayed_ignored_user_range_cnt);
1749     } else {
1750         _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt);
1751     }
1752     SetWindowText(cur_ctrl, static_val);
1753
1754     /* RANGE_REMOVE_IGNORED_PACKETS */
1755     switch(range->process) {
1756         case(range_process_all):
1757             ignored_cnt = range->ignored_cnt;
1758             displayed_ignored_cnt = range->displayed_ignored_cnt;
1759             break;
1760         case(range_process_selected):
1761             ignored_cnt = (cfile.current_frame && cfile.current_frame->flags.ignored) ? 1 : 0;
1762             displayed_ignored_cnt = ignored_cnt;
1763             break;
1764         case(range_process_marked):
1765             ignored_cnt = range->ignored_marked_cnt;
1766             displayed_ignored_cnt = range->displayed_ignored_marked_cnt;
1767             break;
1768         case(range_process_marked_range):
1769             ignored_cnt = range->ignored_mark_range_cnt;
1770             displayed_ignored_cnt = range->displayed_ignored_mark_range_cnt;
1771             break;
1772         case(range_process_user_range):
1773             ignored_cnt = range->ignored_user_range_cnt;
1774             displayed_ignored_cnt = range->displayed_ignored_user_range_cnt;
1775             break;
1776         default:
1777             g_assert_not_reached();
1778     }
1779
1780     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_REMOVE_IGN_CB);
1781     EnableWindow(cur_ctrl, ignored_cnt);
1782
1783     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_CAP);
1784     EnableWindow(cur_ctrl, ignored_cnt && !filtered_active);
1785     _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), ignored_cnt);
1786     SetWindowText(cur_ctrl, static_val);
1787
1788     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_DISP);
1789     EnableWindow(cur_ctrl, displayed_ignored_cnt && filtered_active);
1790     _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_ignored_cnt);
1791     SetWindowText(cur_ctrl, static_val);
1792 }
1793
1794 static void
1795 range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range) {
1796     HWND cur_ctrl;
1797
1798     /* Set the appropriate captured/displayed radio */
1799     if (range->process_filtered)
1800         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1801     else
1802         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
1803     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1804
1805     /* dynamic values in the range frame */
1806     range_update_dynamics(dlg_hwnd, range);
1807
1808     /* Set the appropriate range radio */
1809     switch(range->process) {
1810         case(range_process_all):
1811             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_BTN);
1812             break;
1813         case(range_process_selected):
1814             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_BTN);
1815             break;
1816         case(range_process_marked):
1817             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1818             break;
1819         case(range_process_marked_range):
1820             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1821             break;
1822         case(range_process_user_range):
1823             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
1824             break;
1825         default:
1826             g_assert_not_reached();
1827     }
1828     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1829 }
1830
1831 static void
1832 range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range) {
1833     HWND  cur_ctrl;
1834     TCHAR range_text[RANGE_TEXT_MAX];
1835
1836     switch(w_param) {
1837         case (BN_CLICKED << 16) | EWFD_CAPTURED_BTN:
1838         case (BN_CLICKED << 16) | EWFD_DISPLAYED_BTN:
1839             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
1840             if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1841                 range->process_filtered = FALSE;
1842             else
1843                 range->process_filtered = TRUE;
1844             range_update_dynamics(dlg_hwnd, range);
1845             break;
1846         case (BN_CLICKED << 16) | EWFD_ALL_PKTS_BTN:
1847             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1848                 range->process = range_process_all;
1849                 range_update_dynamics(dlg_hwnd, range);
1850             }
1851             break;
1852         case (BN_CLICKED << 16) | EWFD_SEL_PKT_BTN:
1853             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1854                 range->process = range_process_selected;
1855                 range_update_dynamics(dlg_hwnd, range);
1856             }
1857             break;
1858         case (BN_CLICKED << 16) | EWFD_MARKED_BTN:
1859             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1860                 range->process = range_process_marked;
1861                 range_update_dynamics(dlg_hwnd, range);
1862             }
1863             break;
1864         case (BN_CLICKED << 16) | EWFD_FIRST_LAST_BTN:
1865             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1866                 range->process = range_process_marked_range;
1867                 range_update_dynamics(dlg_hwnd, range);
1868             }
1869             break;
1870         case (BN_CLICKED << 16) | EWFD_RANGE_BTN:
1871             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1872                 range->process = range_process_user_range;
1873                 range_update_dynamics(dlg_hwnd, range);
1874                 cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
1875                 SetFocus(cur_ctrl);
1876             }
1877             break;
1878         case (EN_SETFOCUS << 16) | EWFD_RANGE_EDIT:
1879             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
1880             SendMessage(cur_ctrl, BM_CLICK, 0, 0);
1881             break;
1882         case (EN_CHANGE << 16) | EWFD_RANGE_EDIT:
1883             SendMessage(ctrl, WM_GETTEXT, (WPARAM) RANGE_TEXT_MAX, (LPARAM) range_text);
1884             packet_range_convert_str(range, utf_16to8(range_text));
1885             range_update_dynamics(dlg_hwnd, range);
1886             break;
1887         case (BN_CLICKED << 16) | EWFD_REMOVE_IGN_CB:
1888             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1889                 range->remove_ignored = TRUE;
1890             } else {
1891                 range->remove_ignored = FALSE;
1892             }
1893             range_update_dynamics(dlg_hwnd, range);
1894             break;
1895     }
1896 }
1897
1898 #if (_MSC_VER <= 1200)
1899 static UINT CALLBACK
1900 #else
1901 static UINT_PTR CALLBACK
1902 #endif
1903 merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1904     HWND      cur_ctrl, parent;
1905     OFNOTIFY *notify = (OFNOTIFY *) l_param;
1906     TCHAR     sel_name[MAX_PATH];
1907
1908     switch(msg) {
1909         case WM_INITDIALOG:
1910             /* Retain the filter text, and fill it in. */
1911             if(dfilter_str != NULL) {
1912                 cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
1913                 SetWindowText(cur_ctrl, utf_8to16(dfilter_str));
1914             }
1915
1916             /* Append by default */
1917             cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
1918             SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
1919             merge_action = merge_append;
1920
1921             preview_set_filename(mf_hwnd, NULL);
1922             break;
1923         case WM_NOTIFY:
1924             switch (notify->hdr.code) {
1925                 case CDN_FILEOK:
1926                     /* Fetch the read filter */
1927                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
1928                     if (dfilter_str)
1929                         g_free(dfilter_str);
1930                     dfilter_str = filter_tb_get(cur_ctrl);
1931
1932                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
1933                     if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1934                         merge_action = merge_chrono;
1935                     } else {
1936                         cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
1937                         if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1938                             merge_action = merge_prepend;
1939                         }
1940                     }
1941
1942                     break;
1943                 case CDN_SELCHANGE:
1944                     /* This _almost_ works correctly.  We need to handle directory
1945                        selections, etc. */
1946                     parent = GetParent(mf_hwnd);
1947                     CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
1948                     preview_set_filename(mf_hwnd, utf_16to8(sel_name));
1949                     break;
1950                 case CDN_HELP:
1951                     topic_cb(NULL, HELP_MERGE_WIN32_DIALOG);
1952                     break;
1953                 default:
1954                     break;
1955             }
1956             break;
1957         case WM_COMMAND:
1958             cur_ctrl = (HWND) l_param;
1959             switch(w_param) {
1960                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
1961                     filter_tb_syntax_check(cur_ctrl, NULL);
1962                     break;
1963                 default:
1964                     break;
1965             }
1966             break;
1967         default:
1968             break;
1969     }
1970     return 0;
1971 }
1972
1973
1974 #if (_MSC_VER <= 1200)
1975 static UINT CALLBACK
1976 #else
1977 static UINT_PTR CALLBACK
1978 #endif
1979 export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1980     HWND           cur_ctrl;
1981     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1982     gboolean       pkt_fmt_enable;
1983     int            i, index;
1984
1985     switch(msg) {
1986         case WM_INITDIALOG:
1987             /* init the printing range */
1988             packet_range_init(&print_args.range);
1989             range_handle_wm_initdialog(ef_hwnd, &print_args.range);
1990             format_handle_wm_initdialog(ef_hwnd, &print_args);
1991
1992             break;
1993         case WM_COMMAND:
1994             cur_ctrl = (HWND) l_param;
1995             switch (w_param) {
1996                 case (CBN_SELCHANGE << 16) | EWFD_PKT_DETAIL_COMBO:
1997                 default:
1998                     range_handle_wm_command(ef_hwnd, cur_ctrl, w_param, &print_args.range);
1999                     print_update_dynamic(ef_hwnd, &print_args);
2000                     break;
2001             }
2002             break;
2003         case WM_NOTIFY:
2004             switch (notify->hdr.code) {
2005                 case CDN_FILEOK:
2006                     break;
2007                 case CDN_TYPECHANGE:
2008                     index = notify->lpOFN->nFilterIndex;
2009
2010                     if (index == 2)     /* PostScript */
2011                         print_args.format = PR_FMT_TEXT;
2012                     else
2013                         print_args.format = PR_FMT_PS;
2014                     if (index == 3 || index == 4 || index == 5 || index == 6)
2015                         pkt_fmt_enable = FALSE;
2016                     else
2017                         pkt_fmt_enable = TRUE;
2018                     for (i = EWFD_PKT_FORMAT_GB; i <= EWFD_PKT_NEW_PAGE_CB; i++) {
2019                         cur_ctrl = GetDlgItem(ef_hwnd, i);
2020                         EnableWindow(cur_ctrl, pkt_fmt_enable);
2021                     }
2022                     break;
2023                 case CDN_HELP:
2024                     topic_cb(NULL, HELP_EXPORT_FILE_WIN32_DIALOG);
2025                     break;
2026                 default:
2027                     break;
2028             }
2029             break;
2030         default:
2031             break;
2032     }
2033     return 0;
2034 }
2035
2036 #if (_MSC_VER <= 1200)
2037 static UINT CALLBACK
2038 #else
2039 static UINT_PTR CALLBACK
2040 #endif
2041 export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
2042     HWND          cur_ctrl;
2043     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
2044     TCHAR         raw_msg[STATIC_LABEL_CHARS];
2045     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
2046
2047     switch(msg) {
2048         case WM_INITDIALOG:
2049             _snwprintf(raw_msg, STATIC_LABEL_CHARS, _T("%d byte%s of raw binary data will be written"),
2050                     ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s")));
2051             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTRAW_ST);
2052             SetWindowText(cur_ctrl, raw_msg);
2053             break;
2054         case WM_NOTIFY:
2055             switch (notify->hdr.code) {
2056                 case CDN_HELP:
2057                     topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG);
2058                     break;
2059                 default:
2060                     break;
2061             }
2062         default:
2063             break;
2064     }
2065     return 0;
2066 }
2067
2068 #if (_MSC_VER <= 1200)
2069 static UINT CALLBACK
2070 #else
2071 static UINT_PTR CALLBACK
2072 #endif
2073 export_sslkeys_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
2074     HWND          cur_ctrl;
2075     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
2076     TCHAR         sslkeys_msg[STATIC_LABEL_CHARS];
2077     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
2078
2079     switch(msg) {
2080         case WM_INITDIALOG:
2081             _snwprintf(sslkeys_msg, STATIC_LABEL_CHARS, _T("%d SSL Session Key%s will be written"),
2082                     ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s")));
2083             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTSSLKEYS_ST);
2084             SetWindowText(cur_ctrl, sslkeys_msg);
2085             break;
2086         case WM_NOTIFY:
2087             switch (notify->hdr.code) {
2088                 case CDN_HELP:
2089                     topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG);
2090                     break;
2091                 default:
2092                     break;
2093             }
2094         default:
2095             break;
2096     }
2097     return 0;
2098 }
2099
2100 /*
2101  * Editor modelines
2102  *
2103  * Local Variables:
2104  * c-basic-offset: 4
2105  * tab-width: 8
2106  * indent-tabs-mode: nil
2107  * End:
2108  *
2109  * ex: set shiftwidth=4 tabstop=8 expandtab
2110  * :indentSize=4:tabSize=8:noTabs=true:
2111  */
2112