dkulwin 702daceea7 Minor changes to assertion handling
Changed the code to bring back assertion popups for everyone, but turn
off assertions around the _get_osfhandle() call in allocate_sfd().  The
original port code was designed knowing that some of the passed
parameters would be invalid, but was expecting that the call would just
fail instead of generating an assert dialog.  Turning off Asserts around
this call results in behavior similar to mingw.

Also, turn off Incremental Linking for ssh.exe since half the time, the
linker would trap on this project.
2015-12-08 12:47:35 -06:00

460 lines
8.0 KiB
C

/*
* Author: NoMachine <developers@nomachine.com>
*
* Copyright (c) 2009, 2012 NoMachine
* All rights reserved
*
* Support functions and system calls' replacements needed to let the
* software run on Win32 based operating systems.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <winsock2.h>
#include <io.h>
#include "sfds.h"
#ifndef __MINGW32__
#include <Crtdbg.h>
#endif
extern void debug(const char *fmt,...);
extern void debug2(const char *fmt,...);
extern void debug3(const char *fmt,...);
extern void error(const char *fmt,...);
extern void fatal(const char *fmt,...);
/*
* structure to store real file descriptor and type for sfd
*/
static struct
{
int fd;
HANDLE handle;
sfd_type type;
} sfd_map[SFD_MAP_SIZE];
static int sfd_map_init = 0;
static int sfd_count = 0;
int sfd_start = 0;
#ifndef __MINGW32__
void myInvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
return;
}
#endif
/*
* store real fd in map, detect fd type and return sfd number.
*/
int allocate_sfd(int fd_or_handle)
{
int slot = SFD_FD_INVALID;
int i;
int real_fd;
HANDLE real_handle;
DWORD handle_type;
/*
* Init the map once
*/
if (!sfd_map_init)
{
sfd_map_init = 1;
for (i = 0; i < SFD_MAP_SIZE; ++i)
{
sfd_map[i].fd = SFD_FD_INVALID;
sfd_map[i].type = SFD_TYPE_NONE;
}
}
/*
* Find an open slot
*/
for (i = sfd_start; i < SFD_MAP_SIZE; ++i)
{
/*
* Is this slot open?
*/
if (sfd_map[i].fd == SFD_FD_INVALID)
{
slot = i;
break;
}
}
/*
* Bail if no slot found
*/
if (slot == SFD_FD_INVALID)
{
error("ERROR: Too many connections.");
return -1;
}
#if 0
/*
* Detect and save real fd and real handle
*/
int optVal;
int optLen = sizeof(int);
BOOL bIsSocket = TRUE;
HRESULT hr = S_OK;
int ret = getsockopt(fd_or_handle,
SOL_SOCKET,
SO_DEBUG,
(char*)&optVal,
&optLen);
if (ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK)
{
bIsSocket = FALSE;
}
// if (!bIsSocket && fd_or_handle > 600)
// bIsSocket = TRUE;
if (bIsSocket == TRUE)
real_handle = (HANDLE)fd_or_handle;
else
#endif
#ifndef __MINGW32__
_invalid_parameter_handler oldHandler, newHandler;
newHandler = myInvalidParameterHandler;
oldHandler = _set_invalid_parameter_handler(newHandler);
int iPrev = _CrtSetReportMode(_CRT_ASSERT, 0);
#endif
real_handle = (HANDLE)_get_osfhandle(fd_or_handle);
#ifndef __MINGW32__
_set_invalid_parameter_handler(oldHandler);
_CrtSetReportMode(_CRT_ASSERT, iPrev);
#endif
if (real_handle == INVALID_HANDLE_VALUE)
{
/*
* fd_or_handle was a handle, we can try to create a fd for it
*/
real_handle = (HANDLE) fd_or_handle;
real_fd = _open_osfhandle((long) real_handle, 0);
}
else
{
/*
* fd_or_handle was a fd
*/
real_fd = fd_or_handle;
}
debug3("_get_osfhandle() for real_fd [%d] returned [%d]", real_fd, real_handle);
/*
* Detect and save type
*/
handle_type = GetFileType(real_handle);
debug3("GetFileType() for handle [%d] returned [%d]", real_handle, handle_type);
switch (handle_type)
{
case FILE_TYPE_CHAR:
{
sfd_map[slot].type = SFD_TYPE_CONSOLE;
break;
}
case FILE_TYPE_PIPE:
{
int optVal = 0;
int optLen = sizeof(optVal);
if (getsockopt((SOCKET) real_handle, SOL_SOCKET,
SO_ACCEPTCONN, (char *) &optVal, &optLen))
{
sfd_map[slot].type = SFD_TYPE_PIPE;
}
else
{
sfd_map[slot].type = SFD_TYPE_SOCKET;
}
break;
}
case FILE_TYPE_DISK:
{
sfd_map[slot].type = SFD_TYPE_FD;
break;
}
case FILE_TYPE_UNKNOWN:
{
error("unknown type for handle [%d]", real_handle);
return SFD_FD_INVALID;
break;
}
default:
{
error("cannot detect a type for handle [%d]", real_handle);
return SFD_FD_INVALID;
break;
}
}
/*
* Save the fd and handle
*/
sfd_map[slot].fd = (int) real_fd;
sfd_map[slot].handle = (HANDLE) real_handle;
debug("allocating new sfd, sfd [%i] fd [%i] handle [%d] type [%i]",
slot, real_fd, real_handle, sfd_map[slot].type);
sfd_count++;
/*
* Return the slot as the sfd
*/
return (slot);
}
/*
* For a real fd, get our sfd
*/
int fd_to_sfd(int real_fd)
{
int i;
int sfds;
/*
* Walk the list.
*/
for (i = 0, sfds = 0; i < SFD_MAP_SIZE && sfds < sfd_count; i++)
{
/*
* Increment the count of sfds that we have encountered in our walk,
*/
if (sfd_map[i].fd != SFD_FD_INVALID)
{
sfds++;
}
if (sfd_map[i].fd == real_fd)
{
return i;
}
}
fatal("cannot convert fd to sfd");
return SFD_FD_INVALID;
}
/*
* For an sfd, get the real descriptor behind it.
*/
int sfd_to_fd(int sfd)
{
return sfd_map[sfd].fd;
}
// set the sfd type to console. GetFileType() in Windows seem to return wrong type for a console returning PIPE (3) in place of CHARTYPE (2)
void sfd_set_to_console(int sfd)
{
sfd_map[sfd].type = SFD_TYPE_CONSOLE;
}
/*
* For an sfd, get the real handle behind it
*/
HANDLE sfd_to_handle(int sfd)
{
return sfd_map[sfd].handle;
}
void sfd_replace(int sfd, HANDLE handle, int type)
{
//_close(sfd_map[sfd].handle);
sfd_map[sfd].handle = handle;
sfd_map[sfd].type = type;
}
/*
* For an sfd, get the type
*/
int get_sfd_type(int sfd)
{
if(sfd < sizeof(sfd_map) / sizeof(sfd_map[0]))
{
return sfd_map[sfd].type;
}
else
{
return -1;
}
}
/*
* Free an sfd from the map.
*/
void free_sfd(int sfd)
{
if (sfd_map[sfd].type != SFD_TYPE_NONE
&& sfd < sizeof(sfd_map) / sizeof(sfd_map[0]))
{
/*
* Blank the slot
*/
sfd_map[sfd].fd = SFD_FD_INVALID;
sfd_map[sfd].handle = (HANDLE) SFD_HANDLE_INVALID;
sfd_map[sfd].type = SFD_TYPE_NONE;
sfd_count--;
}
}
/*
* Check if sfd is file.
*/
int
sfd_is_fd(int sfd)
{
if (sfd_map[sfd].type == SFD_TYPE_FD)
{
return 1;
}
return 0;
}
/*
* Check if sfd is socket.
*/
int sfd_is_socket(int sfd)
{
if (sfd_map[sfd].type == SFD_TYPE_SOCKET)
{
return 1;
}
return 0;
}
/*
* Check if sfd is pipe.
*/
int sfd_is_pipe(int sfd)
{
if (sfd_map[sfd].type == SFD_TYPE_PIPE)
{
return 1;
}
return 0;
}
/*
* Check if sfd is console.
*/
int sfd_is_console(int sfd)
{
if (sfd_map[sfd].type == SFD_TYPE_CONSOLE)
{
return 1;
}
return 0;
}
/*
* Check if sfd is file or console.
*/
int sfd_is_fd_or_console(int sfd)
{
if (sfd_is_fd(sfd) || sfd_is_console(sfd))
{
return 1;
}
return 0;
}
/*
* Check if sfd is socket or pipe.
*/
int sfd_is_socket_or_pipe(int sfd)
{
if (sfd_is_socket(sfd) || sfd_is_pipe(sfd))
{
return 1;
}
return 0;
}