3 * (Originally part of the Wiretap Library, now part of the Wireshark
5 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * File wrapper functions to replace the file functions from GLib like
27 * With MSVC, code using the C support library from one version of MSVC
28 * cannot use file descriptors or FILE *'s returned from code using
29 * the C support library from another version of MSVC.
31 * We therefore provide our own versions of the routines to open files,
32 * so that they're built to use the same C support library as our code
35 * (If both were built to use the Universal CRT:
37 * http://blogs.msdn.com/b/vcblog/archive/2015/03/03/introducing-the-universal-crt.aspx
39 * this would not be a problem.)
41 * DO NOT USE THESE FUNCTIONS DIRECTLY, USE ws_open() AND ALIKE FUNCTIONS
42 * FROM file_util.h INSTEAD!!!
44 * The following code is stripped down code copied from the GLib file
45 * glib/gstdio.h - stripped down because this is used only on Windows
46 * and we use only wide char functions.
48 * In addition, we have our own ws_stdio_stat64(), which uses
49 * _wstati64(), so that we can get file sizes for files > 4 GB in size.
51 * XXX - is there any reason why we supply our own versions of routines
52 * that *don't* return file descriptors, other than ws_stdio_stat64()?
53 * Is there an issue with UTF-16 support in _wmkdir() with some versions
54 * of the C runtime, so that if GLib is built to use that version, it
55 * won't handle UTF-16 paths?
59 #error "This is only for Windows"
72 #include "file_util.h"
74 static gchar *program_path = NULL;
75 static gchar *system_path = NULL;
76 static gchar *npcap_path = NULL;
80 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
81 * @flags: as in open()
84 * A wrapper for the POSIX open() function. The open() function is
85 * used to convert a pathname into a file descriptor. Note that on
86 * POSIX systems file descriptors are implemented by the operating
87 * system. On Windows, it's the C library that implements open() and
88 * file descriptors. The actual Windows API for opening files is
89 * something different.
91 * See the C library manual for more details about open().
93 * Returns: a new file descriptor, or -1 if an error occurred. The
94 * return value can be used exactly like the return value from open().
99 ws_stdio_open (const gchar *filename,
103 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
107 if (wfilename == NULL)
113 retval = _wopen (wfilename, flags, mode);
125 * @oldfilename: a pathname in the GLib file name encoding (UTF-8 on Windows)
126 * @newfilename: a pathname in the GLib file name encoding
128 * A wrapper for the POSIX rename() function. The rename() function
129 * renames a file, moving it between directories if required.
131 * See your C library manual for more details about how rename() works
132 * on your system. Note in particular that on Win9x it is not possible
133 * to rename a file if a file with the new name already exists. Also
134 * it is not possible in general on Windows to rename an open file.
136 * Returns: 0 if the renaming succeeded, -1 if an error occurred
141 ws_stdio_rename (const gchar *oldfilename,
142 const gchar *newfilename)
144 wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
145 wchar_t *wnewfilename;
149 if (woldfilename == NULL)
155 wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
157 if (wnewfilename == NULL)
159 g_free (woldfilename);
164 if (MoveFileExW (woldfilename, wnewfilename, MOVEFILE_REPLACE_EXISTING))
169 switch (GetLastError ())
171 #define CASE(a,b) case ERROR_##a: save_errno = b; break
172 CASE (FILE_NOT_FOUND, ENOENT);
173 CASE (PATH_NOT_FOUND, ENOENT);
174 CASE (ACCESS_DENIED, EACCES);
175 CASE (NOT_SAME_DEVICE, EXDEV);
176 CASE (LOCK_VIOLATION, EACCES);
177 CASE (SHARING_VIOLATION, EACCES);
178 CASE (FILE_EXISTS, EEXIST);
179 CASE (ALREADY_EXISTS, EEXIST);
181 default: save_errno = EIO;
185 g_free (woldfilename);
186 g_free (wnewfilename);
194 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
195 * @mode: permissions to use for the newly created directory
197 * A wrapper for the POSIX mkdir() function. The mkdir() function
198 * attempts to create a directory with the given name and permissions.
200 * See the C library manual for more details about mkdir().
202 * Returns: 0 if the directory was successfully created, -1 if an error
208 ws_stdio_mkdir (const gchar *filename,
211 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
215 if (wfilename == NULL)
221 retval = _wmkdir (wfilename);
232 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
233 * @buf: a pointer to a <structname>stat</structname> struct, which
234 * will be filled with the file information
236 * A wrapper for the POSIX stat() function. The stat() function
237 * returns information about a file.
239 * See the C library manual for more details about stat().
241 * Returns: 0 if the information was successfully retrieved, -1 if an error
247 ws_stdio_stat64 (const gchar *filename,
250 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
255 if (wfilename == NULL)
261 len = wcslen (wfilename);
262 while (len > 0 && G_IS_DIR_SEPARATOR (wfilename[len-1]))
265 (!g_path_is_absolute (filename) || len > (size_t) (g_path_skip_root (filename) - filename)))
266 wfilename[len] = '\0';
268 retval = _wstati64 (wfilename, buf);
278 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
280 * A wrapper for the POSIX unlink() function. The unlink() function
281 * deletes a name from the filesystem. If this was the last link to the
282 * file and no processes have it opened, the diskspace occupied by the
285 * See your C library manual for more details about unlink(). Note
286 * that on Windows, it is in general not possible to delete files that
287 * are open to some process, or mapped into memory.
289 * Returns: 0 if the name was successfully deleted, -1 if an error
296 ws_stdio_unlink (const gchar *filename)
298 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
302 if (wfilename == NULL)
308 retval = _wunlink (wfilename);
319 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
321 * A wrapper for the POSIX remove() function. The remove() function
322 * deletes a name from the filesystem.
324 * See your C library manual for more details about how remove() works
325 * on your system. On Unix, remove() removes also directories, as it
326 * calls unlink() for files and rmdir() for directories. On Windows,
327 * although remove() in the C library only works for files, this
328 * function tries first remove() and then if that fails rmdir(), and
329 * thus works for both files and directories. Note however, that on
330 * Windows, it is in general not possible to remove a file that is
331 * open to some process, or mapped into memory.
333 * If this function fails on Windows you can't infer too much from the
334 * errno value. rmdir() is tried regardless of what caused remove() to
335 * fail. Any errno value set by remove() will be overwritten by that
338 * Returns: 0 if the file was successfully removed, -1 if an error
344 ws_stdio_remove (const gchar *filename)
346 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
350 if (wfilename == NULL)
356 retval = _wremove (wfilename);
358 retval = _wrmdir (wfilename);
369 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
370 * @mode: a string describing the mode in which the file should be
373 * A wrapper for the POSIX fopen() function. The fopen() function opens
374 * a file and associates a new stream with it.
376 * See the C library manual for more details about fopen().
378 * Returns: A <type>FILE</type> pointer if the file was successfully
379 * opened, or %NULL if an error occurred
384 ws_stdio_fopen (const gchar *filename,
387 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
392 if (wfilename == NULL)
398 wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
407 retval = _wfopen (wfilename, wmode);
419 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
420 * @mode: a string describing the mode in which the file should be
422 * @stream: an existing stream which will be reused, or %NULL
424 * A wrapper for the POSIX freopen() function. The freopen() function
425 * opens a file and associates it with an existing stream.
427 * See the C library manual for more details about freopen().
429 * Returns: A <type>FILE</type> pointer if the file was successfully
430 * opened, or %NULL if an error occurred.
435 ws_stdio_freopen (const gchar *filename,
439 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
444 if (wfilename == NULL)
450 wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
459 retval = _wfreopen (wfilename, wmode, stream);
472 init_dll_load_paths()
474 TCHAR path_w[MAX_PATH];
476 if (program_path && system_path && npcap_path)
479 /* XXX - Duplicate code in filesystem.c:init_progfile_dir */
480 if (GetModuleFileName(NULL, path_w, MAX_PATH) == 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
486 app_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
487 /* We could use PathRemoveFileSpec here but we'd have to link to Shlwapi.dll */
488 program_path = g_path_get_dirname(app_path);
492 if (GetSystemDirectory(path_w, MAX_PATH) == 0) {
497 system_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
500 _tcscat_s(path_w, MAX_PATH, _T("\\Npcap"));
503 npcap_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
506 if (program_path && system_path && npcap_path)
513 ws_init_dll_search_path()
515 gboolean dll_dir_set = FALSE;
516 wchar_t *program_path_w;
517 wchar_t npcap_path_w[MAX_PATH];
520 typedef BOOL (WINAPI *SetDllDirectoryHandler)(LPCTSTR);
521 SetDllDirectoryHandler PSetDllDirectory;
523 PSetDllDirectory = (SetDllDirectoryHandler) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "SetDllDirectoryW");
524 if (PSetDllDirectory) {
525 dll_dir_set = PSetDllDirectory(_T(""));
527 retval = GetSystemDirectoryW(npcap_path_w, MAX_PATH);
528 if (0 < retval && retval <= MAX_PATH) {
529 wcscat_s(npcap_path_w, MAX_PATH, L"\\Npcap");
530 dll_dir_set = PSetDllDirectory(npcap_path_w);
535 if (!dll_dir_set && init_dll_load_paths()) {
536 program_path_w = g_utf8_to_utf16(program_path, -1, NULL, NULL, NULL);
537 SetCurrentDirectory(program_path_w);
538 g_free(program_path_w);
545 * Internally g_module_open uses LoadLibrary on Windows and returns an
546 * HMODULE cast to a GModule *. However there's no guarantee that this
547 * will always be the case, so we call LoadLibrary and g_module_open
552 ws_load_library(const gchar *library_name)
555 wchar_t *full_path_w;
558 if (!init_dll_load_paths() || !library_name)
561 /* First try the program directory */
562 full_path = g_module_build_path(program_path, library_name);
563 full_path_w = g_utf8_to_utf16(full_path, -1, NULL, NULL, NULL);
565 if (full_path && full_path_w) {
566 dll_h = LoadLibraryW(full_path_w);
574 /* Next try the system directory */
575 full_path = g_module_build_path(system_path, library_name);
576 full_path_w = g_utf8_to_utf16(full_path, -1, NULL, NULL, NULL);
578 if (full_path && full_path_w) {
579 dll_h = LoadLibraryW(full_path_w);
591 ws_module_open(gchar *module_name, GModuleFlags flags)
596 if (!init_dll_load_paths() || !module_name)
599 /* First try the program directory */
600 full_path = g_module_build_path(program_path, module_name);
603 mod = g_module_open(full_path, flags);
610 /* Next try the system directory */
611 full_path = g_module_build_path(system_path, module_name);
614 mod = g_module_open(full_path, flags);
621 /* At last try the Npcap directory */
622 full_path = g_module_build_path(npcap_path, module_name);
625 mod = g_module_open(full_path, flags);
635 /** Create or open a "Wireshark is running" mutex.
637 #define WIRESHARK_IS_RUNNING_UUID "9CA78EEA-EA4D-4490-9240-FC01FCEF464B"
639 static SECURITY_ATTRIBUTES *sec_attributes_;
641 void create_app_running_mutex() {
642 SECURITY_ATTRIBUTES *sa = NULL;
644 if (!sec_attributes_) sec_attributes_ = g_new0(SECURITY_ATTRIBUTES, 1);
646 sec_attributes_->nLength = sizeof(SECURITY_ATTRIBUTES);
647 sec_attributes_->lpSecurityDescriptor = g_new0(SECURITY_DESCRIPTOR, 1);
648 sec_attributes_->bInheritHandle = TRUE;
649 if (InitializeSecurityDescriptor(sec_attributes_->lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) {
650 if (SetSecurityDescriptorDacl(sec_attributes_->lpSecurityDescriptor, TRUE, NULL, FALSE)) {
651 sa = sec_attributes_;
656 g_free(sec_attributes_->lpSecurityDescriptor);
657 g_free(sec_attributes_);
658 sec_attributes_ = NULL;
660 CreateMutex(sa, FALSE, _T("Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID) _T("}"));
661 CreateMutex(sa, FALSE, _T("Global\\Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID) _T("}"));
665 * Editor modelines - http://www.wireshark.org/tools/modelines.html
670 * indent-tabs-mode: nil
673 * vi: set shiftwidth=6 tabstop=8 expandtab:
674 * :indentSize=6:tabSize=8:noTabs=true: