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