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