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