5 * (Originally part of the Wiretap Library, now part of the Wireshark
7 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 /* file wrapper functions to prevent the file functions from GLib like g_open(),
26 * as code compiled with MSVC 7 and above will collide with libs linked with msvcrt.dll (MSVC 6), lib GLib is
28 * DO NOT USE THESE FUNCTIONS DIRECTLY, USE ws_open() AND ALIKE FUNCTIONS FROM file_util.h INSTEAD!!!
30 * the following code is stripped down code copied from the GLib file glib/gstdio.h
31 * stripped down, because this is used on _WIN32 only and we use only wide char functions */
34 #error "This is only for Windows"
45 /*#include <direct.h>*/
49 #include "file_util.h"
51 static gchar
*program_path
= NULL
;
52 static gchar
*system_path
= NULL
;
56 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
57 * @flags: as in open()
60 * A wrapper for the POSIX open() function. The open() function is
61 * used to convert a pathname into a file descriptor. Note that on
62 * POSIX systems file descriptors are implemented by the operating
63 * system. On Windows, it's the C library that implements open() and
64 * file descriptors. The actual Windows API for opening files is
65 * something different.
67 * See the C library manual for more details about open().
69 * Returns: a new file descriptor, or -1 if an error occurred. The
70 * return value can be used exactly like the return value from open().
75 ws_stdio_open (const gchar
*filename
,
79 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
83 if (wfilename
== NULL
)
89 retval
= _wopen (wfilename
, flags
, mode
);
101 * @oldfilename: a pathname in the GLib file name encoding (UTF-8 on Windows)
102 * @newfilename: a pathname in the GLib file name encoding
104 * A wrapper for the POSIX rename() function. The rename() function
105 * renames a file, moving it between directories if required.
107 * See your C library manual for more details about how rename() works
108 * on your system. Note in particular that on Win9x it is not possible
109 * to rename a file if a file with the new name already exists. Also
110 * it is not possible in general on Windows to rename an open file.
112 * Returns: 0 if the renaming succeeded, -1 if an error occurred
117 ws_stdio_rename (const gchar
*oldfilename
,
118 const gchar
*newfilename
)
120 wchar_t *woldfilename
= g_utf8_to_utf16 (oldfilename
, -1, NULL
, NULL
, NULL
);
121 wchar_t *wnewfilename
;
125 if (woldfilename
== NULL
)
131 wnewfilename
= g_utf8_to_utf16 (newfilename
, -1, NULL
, NULL
, NULL
);
133 if (wnewfilename
== NULL
)
135 g_free (woldfilename
);
140 if (MoveFileExW (woldfilename
, wnewfilename
, MOVEFILE_REPLACE_EXISTING
))
145 switch (GetLastError ())
147 #define CASE(a,b) case ERROR_##a: save_errno = b; break
148 CASE (FILE_NOT_FOUND
, ENOENT
);
149 CASE (PATH_NOT_FOUND
, ENOENT
);
150 CASE (ACCESS_DENIED
, EACCES
);
151 CASE (NOT_SAME_DEVICE
, EXDEV
);
152 CASE (LOCK_VIOLATION
, EACCES
);
153 CASE (SHARING_VIOLATION
, EACCES
);
154 CASE (FILE_EXISTS
, EEXIST
);
155 CASE (ALREADY_EXISTS
, EEXIST
);
157 default: save_errno
= EIO
;
161 g_free (woldfilename
);
162 g_free (wnewfilename
);
170 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
171 * @mode: permissions to use for the newly created directory
173 * A wrapper for the POSIX mkdir() function. The mkdir() function
174 * attempts to create a directory with the given name and permissions.
176 * See the C library manual for more details about mkdir().
178 * Returns: 0 if the directory was successfully created, -1 if an error
184 ws_stdio_mkdir (const gchar
*filename
,
187 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
191 if (wfilename
== NULL
)
197 retval
= _wmkdir (wfilename
);
208 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
209 * @buf: a pointer to a <structname>stat</structname> struct, which
210 * will be filled with the file information
212 * A wrapper for the POSIX stat() function. The stat() function
213 * returns information about a file.
215 * See the C library manual for more details about stat().
217 * Returns: 0 if the information was successfully retrieved, -1 if an error
223 ws_stdio_stat64 (const gchar
*filename
,
226 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
231 if (wfilename
== NULL
)
237 len
= wcslen (wfilename
);
238 while (len
> 0 && G_IS_DIR_SEPARATOR (wfilename
[len
-1]))
241 (!g_path_is_absolute (filename
) || len
> (size_t) (g_path_skip_root (filename
) - filename
)))
242 wfilename
[len
] = '\0';
244 retval
= _wstati64 (wfilename
, buf
);
254 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
256 * A wrapper for the POSIX unlink() function. The unlink() function
257 * deletes a name from the filesystem. If this was the last link to the
258 * file and no processes have it opened, the diskspace occupied by the
261 * See your C library manual for more details about unlink(). Note
262 * that on Windows, it is in general not possible to delete files that
263 * are open to some process, or mapped into memory.
265 * Returns: 0 if the name was successfully deleted, -1 if an error
272 ws_stdio_unlink (const gchar
*filename
)
274 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
278 if (wfilename
== NULL
)
284 retval
= _wunlink (wfilename
);
295 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
297 * A wrapper for the POSIX remove() function. The remove() function
298 * deletes a name from the filesystem.
300 * See your C library manual for more details about how remove() works
301 * on your system. On Unix, remove() removes also directories, as it
302 * calls unlink() for files and rmdir() for directories. On Windows,
303 * although remove() in the C library only works for files, this
304 * function tries first remove() and then if that fails rmdir(), and
305 * thus works for both files and directories. Note however, that on
306 * Windows, it is in general not possible to remove a file that is
307 * open to some process, or mapped into memory.
309 * If this function fails on Windows you can't infer too much from the
310 * errno value. rmdir() is tried regardless of what caused remove() to
311 * fail. Any errno value set by remove() will be overwritten by that
314 * Returns: 0 if the file was successfully removed, -1 if an error
320 ws_stdio_remove (const gchar
*filename
)
322 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
326 if (wfilename
== NULL
)
332 retval
= _wremove (wfilename
);
334 retval
= _wrmdir (wfilename
);
345 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
346 * @mode: a string describing the mode in which the file should be
349 * A wrapper for the POSIX fopen() function. The fopen() function opens
350 * a file and associates a new stream with it.
352 * See the C library manual for more details about fopen().
354 * Returns: A <type>FILE</type> pointer if the file was successfully
355 * opened, or %NULL if an error occurred
360 ws_stdio_fopen (const gchar
*filename
,
363 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
368 if (wfilename
== NULL
)
374 wmode
= g_utf8_to_utf16 (mode
, -1, NULL
, NULL
, NULL
);
383 retval
= _wfopen (wfilename
, wmode
);
395 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows)
396 * @mode: a string describing the mode in which the file should be
398 * @stream: an existing stream which will be reused, or %NULL
400 * A wrapper for the POSIX freopen() function. The freopen() function
401 * opens a file and associates it with an existing stream.
403 * See the C library manual for more details about freopen().
405 * Returns: A <type>FILE</type> pointer if the file was successfully
406 * opened, or %NULL if an error occurred.
411 ws_stdio_freopen (const gchar
*filename
,
415 wchar_t *wfilename
= g_utf8_to_utf16 (filename
, -1, NULL
, NULL
, NULL
);
420 if (wfilename
== NULL
)
426 wmode
= g_utf8_to_utf16 (mode
, -1, NULL
, NULL
, NULL
);
435 retval
= _wfreopen (wfilename
, wmode
, stream
);
448 init_dll_load_paths()
450 TCHAR path_w
[MAX_PATH
];
452 if (program_path
&& system_path
)
455 /* XXX - Duplicate code in filesystem.c:init_progfile_dir */
456 if (GetModuleFileName(NULL
, path_w
, MAX_PATH
) == 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER
) {
462 app_path
= g_utf16_to_utf8(path_w
, -1, NULL
, NULL
, NULL
);
463 /* We could use PathRemoveFileSpec here but we'd have to link to Shlwapi.dll */
464 program_path
= g_path_get_dirname(app_path
);
468 if (GetSystemDirectory(path_w
, MAX_PATH
) == 0) {
473 system_path
= g_utf16_to_utf8(path_w
, -1, NULL
, NULL
, NULL
);
476 if (program_path
&& system_path
)
483 ws_init_dll_search_path()
485 gboolean dll_dir_set
= FALSE
;
486 wchar_t *program_path_w
;
488 typedef BOOL (WINAPI
*SetDllDirectoryHandler
)(LPCTSTR
);
489 SetDllDirectoryHandler PSetDllDirectory
;
491 PSetDllDirectory
= (SetDllDirectoryHandler
) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "SetDllDirectoryW");
492 if (PSetDllDirectory
) {
493 dll_dir_set
= PSetDllDirectory(_T(""));
496 if (!dll_dir_set
&& init_dll_load_paths()) {
497 program_path_w
= g_utf8_to_utf16(program_path
, -1, NULL
, NULL
, NULL
);
498 SetCurrentDirectory(program_path_w
);
499 g_free(program_path_w
);
506 * Internally g_module_open uses LoadLibrary on Windows and returns an
507 * HMODULE cast to a GModule *. However there's no guarantee that this
508 * will always be the case, so we call LoadLibrary and g_module_open
513 ws_load_library(gchar
*library_name
)
516 wchar_t *full_path_w
;
519 if (!init_dll_load_paths() || !library_name
)
522 /* First try the program directory */
523 full_path
= g_module_build_path(program_path
, library_name
);
524 full_path_w
= g_utf8_to_utf16(full_path
, -1, NULL
, NULL
, NULL
);
526 if (full_path
&& full_path_w
) {
527 dll_h
= LoadLibraryW(full_path_w
);
535 /* Next try the system directory */
536 full_path
= g_module_build_path(system_path
, library_name
);
537 full_path_w
= g_utf8_to_utf16(full_path
, -1, NULL
, NULL
, NULL
);
539 if (full_path
&& full_path_w
) {
540 dll_h
= LoadLibraryW(full_path_w
);
552 ws_module_open(gchar
*module_name
, GModuleFlags flags
)
557 if (!init_dll_load_paths() || !module_name
)
560 /* First try the program directory */
561 full_path
= g_module_build_path(program_path
, module_name
);
564 mod
= g_module_open(full_path
, flags
);
571 /* Next try the system directory */
572 full_path
= g_module_build_path(system_path
, module_name
);
575 mod
= g_module_open(full_path
, flags
);
585 /* utf8 version of getenv, needed to get win32 filename paths */
587 getenv_utf8(const char *varname
)
593 envvar
= getenv(varname
);
595 /* since GLib 2.6 we need an utf8 version of the filename */
596 /* using the wide char version of getenv should work under all circumstances */
598 /* convert given varname to utf16, needed by _wgetenv */
599 varnamew
= g_utf8_to_utf16(varname
, -1, NULL
, NULL
, NULL
);
600 if (varnamew
== NULL
) {
604 /* use wide char version of getenv */
605 envvarw
= _wgetenv(varnamew
);
607 if (envvarw
== NULL
) {
611 /* convert value to utf8 */
612 envvar
= g_utf16_to_utf8(envvarw
, -1, NULL
, NULL
, NULL
);
618 /** Create or open a "Wireshark is running" mutex.
620 #define WIRESHARK_IS_RUNNING_UUID "9CA78EEA-EA4D-4490-9240-FC01FCEF464B"
622 static SECURITY_ATTRIBUTES
*sec_attributes_
;
624 void create_app_running_mutex() {
625 SECURITY_ATTRIBUTES
*sa
= NULL
;
627 if (!sec_attributes_
) sec_attributes_
= g_new0(SECURITY_ATTRIBUTES
, 1);
629 sec_attributes_
->nLength
= sizeof(SECURITY_ATTRIBUTES
);
630 sec_attributes_
->lpSecurityDescriptor
= g_new0(SECURITY_DESCRIPTOR
, 1);
631 sec_attributes_
->bInheritHandle
= TRUE
;
632 if (InitializeSecurityDescriptor(sec_attributes_
->lpSecurityDescriptor
, SECURITY_DESCRIPTOR_REVISION
)) {
633 if (SetSecurityDescriptorDacl(sec_attributes_
->lpSecurityDescriptor
, TRUE
, NULL
, FALSE
)) {
634 sa
= sec_attributes_
;
639 g_free(sec_attributes_
->lpSecurityDescriptor
);
640 g_free(sec_attributes_
);
641 sec_attributes_
= NULL
;
643 CreateMutex(sa
, FALSE
, _T("Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID
) _T("}"));
644 CreateMutex(sa
, FALSE
, _T("Global\\Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID
) _T("}"));