/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Win32-specific OpenVPN code, targetted at the mingw
* development environment.
*/
#include "syshead.h"
#ifdef WIN32
#include "buffer.h"
#include "error.h"
#include "mtu.h"
#include "sig.h"
#include "win32.h"
#include "misc.h"
#include "memdbg.h"
/*
* Windows internal socket API state (opaque).
*/
static struct WSAData wsa_state; /* GLOBAL */
/*
* Should we call win32_pause() on program exit?
*/
static bool pause_exit_enabled = false; /* GLOBAL */
/*
* win32_signal is used to get input from the keyboard
* if we are running in a console, or get input from an
* event object if we are running as a service.
*/
struct win32_signal win32_signal; /* GLOBAL */
/*
* Save our old window title so we can restore
* it on exit.
*/
struct window_title window_title; /* GLOBAL*/
/*
* Special global semaphore used to protect network
* shell commands from simultaneous instantiation.
*/
struct semaphore netcmd_semaphore; /* GLOBAL */
/*
* Windows system pathname such as c:\windows
*/
static char *win_sys_path = NULL; /* GLOBAL */
/*
* Configure PATH. On Windows, sometimes PATH is not set correctly
* by default.
*/
static void
configure_win_path (void)
{
static bool done = false; /* GLOBAL */
if (!done)
{
FILE *fp;
fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
if (fp)
{
const int bufsiz = 4096;
struct gc_arena gc = gc_new ();
struct buffer oldpath = alloc_buf_gc (bufsiz, &gc);
struct buffer newpath = alloc_buf_gc (bufsiz, &gc);
const char* delim = ";";
DWORD status;
fclose (fp);
status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
#if 0
status = 0;
#endif
if (!status)
{
*BPTR(&oldpath) = '\0';
delim = "";
}
buf_printf (&newpath, "C:\\WINDOWS\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem%s%s",
delim,
BSTR(&oldpath));
SetEnvironmentVariable ("PATH", BSTR(&newpath));
#if 0
status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
if (status > 0)
printf ("PATH: %s\n", BSTR(&oldpath));
#endif
gc_free (&gc);
done = true;
}
}
}
void
init_win32 (void)
{
if (WSAStartup(0x0101, &wsa_state))
{
msg (M_ERR, "WSAStartup failed");
}
window_title_clear (&window_title);
win32_signal_clear (&win32_signal);
netcmd_semaphore_init ();
}
void
uninit_win32 (void)
{
netcmd_semaphore_close ();
if (pause_exit_enabled)
{
if (win32_signal.mode == WSO_MODE_UNDEF)
{
struct win32_signal w;
win32_signal_open (&w, WSO_FORCE_CONSOLE, NULL, false);
win32_pause (&w);
win32_signal_close (&w);
}
else
win32_pause (&win32_signal);
}
window_title_restore (&window_title);
win32_signal_close (&win32_signal);
WSACleanup ();
free (win_sys_path);
}
void
set_pause_exit_win32 (void)
{
pause_exit_enabled = true;
}
bool
init_security_attributes_allow_all (struct security_attributes *obj)
{
CLEAR (*obj);
obj->sa.nLength = sizeof (SECURITY_ATTRIBUTES);
obj->sa.lpSecurityDescriptor = &obj->sd;
obj->sa.bInheritHandle = FALSE;
if (!InitializeSecurityDescriptor (&obj->sd, SECURITY_DESCRIPTOR_REVISION))
return false;
if (!SetSecurityDescriptorDacl (&obj->sd, TRUE, NULL, FALSE))
return false;
return true;
}
void
overlapped_io_init (struct overlapped_io *o,
const struct frame *frame,
BOOL event_state,
bool tuntap_buffer) /* if true: tuntap buffer, if false: socket buffer */
{
CLEAR (*o);
/* manual reset event, initially set according to event_state */
o->overlapped.hEvent = CreateEvent (NULL, TRUE, event_state, NULL);
if (o->overlapped.hEvent == NULL)
msg (M_ERR, "Error: overlapped_io_init: CreateEvent failed");
/* allocate buffer for overlapped I/O */
alloc_buf_sock_tun (&o->buf_init, frame, tuntap_buffer, 0);
}
void
overlapped_io_close (struct overlapped_io *o)
{
if (o->overlapped.hEvent)
{
if (!CloseHandle (o->overlapped.hEvent))
msg (M_WARN | M_ERRNO, "Warning: CloseHandle failed on overlapped I/O event object");
}
free_buf (&o->buf_init);
}
char *
overlapped_io_state_ascii (const struct overlapped_io *o)
{
|