mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 12:49:45 +00:00
767e6f6f9d
Sat Aug 8 19:11:46 1998 Marcus Meissner <marcus@jet.franken.de> * [*/*] Added some missing WINAPI and some missing prototypes for functions. * [controls/static.c] Got rid of the MODULE32_LookupHMODULE error showing up for every message box. * [windows/winproc.c] WM_NOTIFY 16->32 mapping (AOL Instant Messenger or however it is called). * [misc/winsock.c] hostent/servent/protoent should not use the same static buffers. (has broken nt3.15 finger.exe which does hp=gethostbyname(), then getservbyname("finger","tcp") and the references hp->h_addr_list[0]). Sat Aug 8 13:21:24 1998 Alexandre Julliard <julliard@lrc.epfl.ch> * [include/server.h] [tools/make_requests] [server/request.c] [server/trace.c] Automated part of the client/server request code generation. Added tracing of client/server communication. * [scheduler/*.c] [server/process.c] Added support for server-side handles. * [scheduler/thread.c] Added DLL_THREAD_ATTACH/DETACH notifications. * [configure.in] Added check for -lsocket. * [windows/winproc.c] Return the thunk address in WINPROC_GetProc if the function types don't match. Sat Aug 8 02:44:04 1998 Douglas Ridgway <ridgway@winehq.com> * [windows/winproc.c][windows/win.c][windows/message.c] Documentation for CallWindowProc, SetWindowLong, DispatchMessage, WaitMessage, GetMessage, and PeekMessage. Sat Aug 8 01:00:00 1998 Juergen Schmied <juergen.schmied@metronet.de> * [controls/commctrl.c][controls/widgets.c][include/builtin32.h] [include/commctrl.h][relay32/builtin32.c][relay32/comctl32.spec] [tools/build.c] [relay32/shell32.spec] Added the functionality of the LibMain function. The common controls are properly initialized now. * [controls/treeview.c][memory/atom.c][scheduler/thread.c][windows/class.c] [windows/msgbox.c][windows/win.c] Put TRACE in, put SetLastError() in. * [include/interfaces.h] Added IClassFactory::LockServer. * [include/ole2.h] Added struct for LPOLEMENUGROUPWIDTHS32, HOLEMENU32. * [include/shell.h][include/shlobj.h][misc/shell.c][ole/folders.c] Reorganized and many structs and classes (IShellBrowser,IShellView) added. shell32.dll should work in many cases now. Started SHGetFileInfoA implementeation, rewrote SHGetPathFromIDList32A. New Shell32LibMain started ShellIconCache Implementation. * [misc/shellord.c] Rewrote ILCombine, ILGetSize New stubs SHFind_InitMenuPopup, FileMenu_Create, ShellExecuteEx, SHSetInstanceExplorer, SHGetInstanceExplorer, SHFreeUnusedLibraries. * [include/winerror.h] Class and window related error codes added. * [memory/heap.c] Changed lstrlen32A to strlen to get rid of milions of TRACE lines. * [misc/ddeml.c] First lines for DdeCreateStringHandle32A / DdeFreeStringHandle32. * [misc/network.c][relay32/mpr.spec] Fixed some bugs, changed ordinals. * [windows/class.c] Workarounds for incorrect hInstance handling. Fixes parts of MSWord95/Excel95 and Money95. Thu Aug 6 21:05:35 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de> * [windows/nonclient.c][misc/tweak.c][include/tweak.h] [documentation/win95look] Removed some tweak variables. They are no longer needed. * [files/dos_fs.c] Added check for null pointer in DOSFS_GetDevice(). * [controls/tooltips.c][include/commctrl.h] Improved tooltips. * [controls/status.c][include/commctrl.h] Cleaned up code and added tooltip support. * [controls/toolbar.c][include/commctrl.h] Added tooltip support. * [documentation/common_controls] Updated. Thu Aug 6 00:05:22 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de> * [include/ver.h] [misc/ver.c] Write VIF_BUFFTOOSMALL, not VIF_BUFTOSMALL. * [debugger/hash.c] [debugger/stabs.c] Make debug output more friendly for posting. * [files/file.c] Partial implementation of OF_SHARE_EXCLUSIVE. Needed for Quicklogic/QuickChip (InstallShield). * [files/profile.c] When a cached-only entry is found, return it. * [graphics/x11drv/xfont.c] Accept a space as delimiter for a fontname and inhibit overrun (Make xplasim.ex from the Phillips Coolrunner CPLD suite proceed). * [miscemu/main.c] Delay setting IF1632_CallLargeStack after loading the executables. Stops fpgaexp.exe from the Viewlogic FPGA suite from crashing when showing the Blinker error Message Box. * [misc/network.c] Make WNetGetConnection16 recognise a CDROM as a local drive. * [multimedia/mmsystem.c] Preliminary check for MCI_ALL_DEVICE_ID in MCI_Close by a FIXME. Tue Aug 4 21:15:23 1998 James Juran <jrj120@psu.edu> * [ole/ole2nls.c] Fixed bug in CompareString32A. strcmp() doesn't necessarily return -1, 0, or 1, which the previous code depended on. Changed name of is_punctuation to OLE2NLS_isPunctuation. Made NORM_IGNOREWIDTH not print a FIXME message in LCMapString32A. Other debugging messages, documentation, and code cleanups. * [objects/font.c] [relay32/gdi32.spec] [include/winerror.h] Added stub for GetFontData32, and added GDI_ERROR constant to winerror.h. Tue Aug 4 07:44:43 1998 Ove Kaaven <ovek@arcticnet.no> * [multimedia/mmio.c] Implemented mmioSetBuffer, mmioAdvance, mmioAscend, and mmioCreateChunk to the best of my knowledge. But watch out, there's bound to be bugs in there... * [include/mmsystem.h] [multimedia/mmsystem.c] Hacked in support for 32-bit multimedia function callbacks. * [AUTHORS] [misc/shell.c] Selfishly credited my authorship. Hopefully I'm excused. * [include/dosexe.h] [include/module.h] [loader/dos/*] [loader/module.c] [loader/task.c] [Makefile.in] [configure.in] [Makefile.in] Added DOS EXE (MZ) loader and virtual machine. Task structure integration thanks to Ulrich Weigand. * [files/dos_fs.c] Work around a null pointer dereference if ioctlGetDeviceInfo-ing a FILE_DupUnixHandle'd file (i.e. GetStdHandle'd). * [include/miscemu.h] [include/winnt.h] [loader/main.c] [memory/global.c] [msdos/dpmi.c] [msdos/dosmem.c] Added support for DOS memory images, and added DOSMEM_ResizeBlock() and DOSMEM_Available(). * [msdos/int21.c] Added support for the DOS virtual machine, tweaked handle assignment to avoid stdio clashes, forced INT21_FindNext to exit wildcardless searches after finding one entry, added AH=7, 8, 9, C, 48, 49, 4A, and 7160 CL=1 (Get Short Filename), and made the long filename calls only respond if running with with -winver win95. * [objects/cursoricon.c] DestroyCursor32 and DestroyIcon32 should now free the objects (hopefully) correctly. Sun Aug 2 21:42:09 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk> * [graphics/psdrv/*] [include/psdrv.h] Added PPD file parsing - at the moment it reads a file called default.ppd from the directory in which you start Wine. Page sizes other than A4 should now work (landscape may not). All fonts that are present on your printer (according to the PPD) should be available, providing you have the AFM files. Fonts should now be the correct size. Graphics is still basically lines only. See graphics/psdrv/README . * [misc/printdrv.c] Yet more Drv[Get/Set]PrinterData fixes. Fri Jul 31 21:33:22 1998 Per Lindström <pelinstr@algonet.se> * [relay32/crtdll.spec] [misc/crtdll.c] Added stub for freopen, _findfirst, _findnext, _fstat and _read. * [files/directory.c] Modified warning message. Wed Jul 29 11:25:28 1998 Luiz Otavio L. Zorzella <zorzella@nr.conexware.com> * [objects/font.c] Added stub for GetFontData. * [multimedia/msvideo.c] Created this file to hold the msvideo.dll calls (and maybe also msvfw32.dll). * [objects/cursoricon.c] Added search in Global Heap for cursor when trying to destroy it with DestroyCursor16. This test should be done in many (all?) other functions that use FreeResource. * [controls/treeview.c] [include/commctrl.h] Minor correction in name and addition of many placeholders for TVM messages in TREEVIEW_WindowProc. * [msdos/dpmi.c] Fixed a bug in DPMI_xrealloc where in a copy of a memory region "A" of size "a" to a region "B" of size "b", "b" bytes were being copied, instead of "a", as the new version does. This both increases speed, as well as avoids segfaults.
572 lines
16 KiB
C
572 lines
16 KiB
C
/*
|
|
* asynchronous DNS services
|
|
*
|
|
* (C) 1996,1997 Alex Korobka.
|
|
*
|
|
* TODO: Fork dns lookup helper during the startup (with a pipe
|
|
* for communication) and make it fork for a database request
|
|
* instead of forking the main process (i.e. something like
|
|
* Netscape 4.0).
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/msg.h>
|
|
#include <sys/wait.h>
|
|
#include <errno.h>
|
|
#ifdef __EMX__
|
|
# include <sys/so_ioctl.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
# include <sys/param.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_FILIO_H
|
|
# include <sys/filio.h>
|
|
#endif
|
|
#ifdef __svr4__
|
|
# include <sys/file.h>
|
|
#endif
|
|
|
|
#include "winsock.h"
|
|
#include "windows.h"
|
|
#include "heap.h"
|
|
#include "ldt.h"
|
|
#include "message.h"
|
|
#include "selectors.h"
|
|
#include "miscemu.h"
|
|
#include "sig_context.h"
|
|
#include "debug.h"
|
|
|
|
#ifndef FASYNC
|
|
#define FASYNC FIOASYNC
|
|
#endif
|
|
|
|
/* async DNS op control struct */
|
|
typedef struct
|
|
{
|
|
ws_async_op* ws_aop;
|
|
char* buffer;
|
|
int type;
|
|
union
|
|
{
|
|
char* init;
|
|
char* name;
|
|
char* addr;
|
|
} rq;
|
|
unsigned ilength;
|
|
} ws_async_ctl;
|
|
|
|
extern HANDLE16 __ws_gethandle( void* ptr );
|
|
extern void* __ws_memalloc( int size );
|
|
extern void __ws_memfree( void* ptr );
|
|
|
|
/* NOTE: ws_async_op list is traversed inside the SIGIO handler! */
|
|
|
|
static int __async_io_max_fd = 0;
|
|
static fd_set __async_io_fdset;
|
|
static ws_async_op* __async_op_list = NULL;
|
|
|
|
static void fixup_wshe(struct ws_hostent* p_wshe, void* base);
|
|
static void fixup_wspe(struct ws_protoent* p_wspe, void* base);
|
|
static void fixup_wsse(struct ws_servent* p_wsse, void* base);
|
|
|
|
/* ----------------------------------- async/non-blocking I/O */
|
|
|
|
int WINSOCK_async_io(int fd, int async)
|
|
{
|
|
int fd_flags;
|
|
|
|
#ifndef __EMX__
|
|
fcntl(fd, F_SETOWN, getpid());
|
|
#endif
|
|
|
|
fd_flags = fcntl(fd, F_GETFL, 0);
|
|
if (fcntl(fd, F_SETFL, (async)? fd_flags | FASYNC
|
|
: fd_flags & ~FASYNC ) != -1) return 0;
|
|
return -1;
|
|
}
|
|
|
|
int WINSOCK_unblock_io(int fd, int noblock)
|
|
{
|
|
int fd_flags;
|
|
|
|
fd_flags = fcntl(fd, F_GETFL, 0);
|
|
if (fcntl(fd, F_SETFL, (noblock)? fd_flags | O_NONBLOCK
|
|
: fd_flags & ~O_NONBLOCK ) != -1) return 0;
|
|
return -1;
|
|
}
|
|
|
|
int WINSOCK_check_async_op(ws_async_op* p_aop)
|
|
{
|
|
ws_async_op* p = __async_op_list;
|
|
while( p ) if( p == p_aop ) return 1;
|
|
else p = p->next;
|
|
return 0;
|
|
}
|
|
|
|
int WINSOCK_cancel_async_op(ws_async_op* p_aop)
|
|
{
|
|
/* SIGIO unsafe! */
|
|
|
|
if( WINSOCK_check_async_op(p_aop) )
|
|
{
|
|
if( !(p_aop->flags & WSMSG_DEAD_AOP) )
|
|
{
|
|
kill(p_aop->pid, SIGKILL);
|
|
waitpid(p_aop->pid, NULL, 0); /* just in case */
|
|
close(p_aop->fd[0]);
|
|
}
|
|
WINSOCK_unlink_async_op(p_aop);
|
|
EVENT_DeleteIO( p_aop->fd[0], EVENT_IO_READ );
|
|
p_aop->flags = 0;
|
|
p_aop->hWnd = p_aop->uMsg = 0;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void WINSOCK_cancel_task_aops(HTASK16 hTask, void (*__opfree)(void*))
|
|
{
|
|
/* SIGIO safe, hTask == 0 cancels all outstanding async ops */
|
|
|
|
int num = 0, num_dead = 0;
|
|
ws_async_op* p, *next;
|
|
|
|
TRACE(winsock," cancelling async DNS requests... \n");
|
|
|
|
SIGNAL_MaskAsyncEvents( TRUE );
|
|
next = __async_op_list;
|
|
while( (p = next) )
|
|
{
|
|
HTASK16 hWndTask = GetWindowTask16(p->hWnd);
|
|
|
|
next = p->next;
|
|
if(!hTask || !hWndTask || (hTask == hWndTask))
|
|
{
|
|
num++;
|
|
if( p->flags & WSMSG_DEAD_AOP )
|
|
num_dead++;
|
|
|
|
WINSOCK_cancel_async_op(p);
|
|
if( __opfree ) __opfree(p);
|
|
}
|
|
}
|
|
SIGNAL_MaskAsyncEvents( FALSE );
|
|
TRACE(winsock," -> %i total (%i active)\n", num, num - num_dead );
|
|
}
|
|
|
|
void WINSOCK_link_async_op(ws_async_op* p_aop)
|
|
{
|
|
/* SIGIO safe */
|
|
|
|
p_aop->prev = NULL;
|
|
SIGNAL_MaskAsyncEvents( TRUE );
|
|
if( __async_op_list )
|
|
{
|
|
ws_async_op* p = __async_op_list;
|
|
__async_op_list->prev = p_aop;
|
|
|
|
/* traverse the list and retire dead ops created
|
|
* by the signal handler (see below). */
|
|
|
|
while( p )
|
|
{
|
|
if( p->flags & WSMSG_DEAD_AOP )
|
|
{
|
|
ws_async_op* dead = p;
|
|
|
|
TRACE(winsock,"\treaping dead aop [%08x]\n", (unsigned)p );
|
|
|
|
p = p->next;
|
|
WINSOCK_unlink_async_op( dead );
|
|
__ws_memfree( dead );
|
|
continue;
|
|
}
|
|
p = p->next;
|
|
}
|
|
}
|
|
else FD_ZERO(&__async_io_fdset);
|
|
p_aop->next = __async_op_list;
|
|
__async_op_list = p_aop;
|
|
SIGNAL_MaskAsyncEvents( FALSE );
|
|
|
|
FD_SET(p_aop->fd[0], &__async_io_fdset);
|
|
if( p_aop->fd[0] > __async_io_max_fd )
|
|
__async_io_max_fd = p_aop->fd[0];
|
|
}
|
|
|
|
void WINSOCK_unlink_async_op(ws_async_op* p_aop)
|
|
{
|
|
/* SIGIO unsafe! */
|
|
|
|
if( p_aop == __async_op_list ) __async_op_list = p_aop->next;
|
|
else
|
|
p_aop->prev->next = p_aop->next;
|
|
if( p_aop->next ) p_aop->next->prev = p_aop->prev;
|
|
|
|
FD_CLR(p_aop->fd[0], &__async_io_fdset);
|
|
if( p_aop->fd[0] == __async_io_max_fd )
|
|
__async_io_max_fd--;
|
|
}
|
|
|
|
/* ----------------------------------- SIGIO handler -
|
|
*
|
|
* link_async_op/unlink_async_op allow to install generic
|
|
* async IO handlers (provided that aop_control function is defined).
|
|
*
|
|
* Note: pipe-based handlers must raise explicit SIGIO with kill(2).
|
|
*/
|
|
|
|
HANDLER_DEF(WINSOCK_sigio)
|
|
{
|
|
struct timeval timeout;
|
|
fd_set check_set;
|
|
ws_async_op* p_aop;
|
|
|
|
HANDLER_INIT();
|
|
|
|
check_set = __async_io_fdset;
|
|
memset(&timeout, 0, sizeof(timeout));
|
|
|
|
while( select(__async_io_max_fd + 1,
|
|
&check_set, NULL, NULL, &timeout) > 0)
|
|
{
|
|
for( p_aop = __async_op_list;
|
|
p_aop ; p_aop = p_aop->next )
|
|
if( FD_ISSET(p_aop->fd[0], &check_set) )
|
|
if( p_aop->aop_control(p_aop, AOP_IO) == AOP_CONTROL_REMOVE )
|
|
{
|
|
/* NOTE: memory management is signal-unsafe, therefore
|
|
* we can only set a flag to remove this p_aop later on.
|
|
*/
|
|
|
|
p_aop->flags = WSMSG_DEAD_AOP;
|
|
close(p_aop->fd[0]);
|
|
FD_CLR(p_aop->fd[0],&__async_io_fdset);
|
|
if( p_aop->fd[0] == __async_io_max_fd )
|
|
__async_io_max_fd = p_aop->fd[0];
|
|
if( p_aop->pid )
|
|
{
|
|
kill(p_aop->pid, SIGKILL);
|
|
waitpid(p_aop->pid, NULL, WNOHANG);
|
|
p_aop->pid = 0;
|
|
}
|
|
}
|
|
check_set = __async_io_fdset;
|
|
}
|
|
}
|
|
|
|
/* ----------------------------------- getXbyY requests */
|
|
|
|
/* child process control struct */
|
|
static ws_async_ctl async_ctl;
|
|
|
|
static int aop_control(ws_async_op* p_aop, int flag )
|
|
{
|
|
unsigned lLength;
|
|
|
|
/* success: LOWORD(lLength) has the length of the struct
|
|
* to read.
|
|
* failure: LOWORD(lLength) is zero, HIWORD(lLength) contains
|
|
* the error code.
|
|
*/
|
|
|
|
read(p_aop->fd[0], &lLength, sizeof(unsigned));
|
|
if( LOWORD(lLength) )
|
|
{
|
|
if( (int)LOWORD(lLength) <= p_aop->buflen )
|
|
{
|
|
char* buffer = (p_aop->flags & WSMSG_WIN32_AOP)
|
|
? p_aop->b.lin_base : (char*)PTR_SEG_TO_LIN(p_aop->b.seg_base);
|
|
|
|
read(p_aop->fd[0], buffer, LOWORD(lLength));
|
|
switch( p_aop->flags & WSMSG_ASYNC_RQMASK )
|
|
{
|
|
case WSMSG_ASYNC_HOSTBYNAME:
|
|
case WSMSG_ASYNC_HOSTBYADDR:
|
|
fixup_wshe((struct ws_hostent*)buffer, p_aop->b.ptr_base); break;
|
|
case WSMSG_ASYNC_PROTOBYNAME:
|
|
case WSMSG_ASYNC_PROTOBYNUM:
|
|
fixup_wspe((struct ws_protoent*)buffer, p_aop->b.ptr_base); break;
|
|
case WSMSG_ASYNC_SERVBYNAME:
|
|
case WSMSG_ASYNC_SERVBYPORT:
|
|
fixup_wsse((struct ws_servent*)buffer, p_aop->b.ptr_base); break;
|
|
default:
|
|
if( p_aop->flags ) WARN(winsock,"Received unknown async request!\n");
|
|
return AOP_CONTROL_REMOVE;
|
|
}
|
|
}
|
|
else lLength = ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
|
|
} /* failure */
|
|
|
|
/* was a __WS_ASYNC_DEBUG statement */
|
|
TRACE(winsock, "DNS aop completed: hWnd [%04x], uMsg [%04x], "
|
|
"aop [%04x], event [%08lx]\n",
|
|
p_aop->hWnd, p_aop->uMsg, __ws_gethandle(p_aop), (LPARAM)lLength);
|
|
|
|
/* FIXME: update num_async_rq */
|
|
EVENT_DeleteIO( p_aop->fd[0], EVENT_IO_READ );
|
|
PostMessage32A( p_aop->hWnd, p_aop->uMsg, __ws_gethandle(p_aop), (LPARAM)lLength );
|
|
|
|
return AOP_CONTROL_REMOVE; /* one-shot request */
|
|
}
|
|
|
|
|
|
HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND32 hWnd, UINT32 uMsg, INT32 type,
|
|
LPCSTR init, INT32 len, LPCSTR proto, void* sbuf, INT32 buflen, UINT32 flag)
|
|
{
|
|
/* queue 'flag' request and fork off its handler */
|
|
|
|
async_ctl.ws_aop = (ws_async_op*)__ws_memalloc(sizeof(ws_async_op));
|
|
|
|
if( async_ctl.ws_aop )
|
|
{
|
|
HANDLE16 handle = __ws_gethandle(async_ctl.ws_aop);
|
|
|
|
if( pipe(async_ctl.ws_aop->fd) == 0 )
|
|
{
|
|
async_ctl.rq.init = (char*)init;
|
|
async_ctl.ilength = len;
|
|
async_ctl.buffer = (char*)proto;
|
|
async_ctl.type = type;
|
|
|
|
async_ctl.ws_aop->hWnd = hWnd;
|
|
async_ctl.ws_aop->uMsg = uMsg;
|
|
async_ctl.ws_aop->b.ptr_base = sbuf;
|
|
async_ctl.ws_aop->buflen = buflen;
|
|
async_ctl.ws_aop->flags = flag;
|
|
async_ctl.ws_aop->aop_control = &aop_control;
|
|
|
|
WINSOCK_link_async_op( async_ctl.ws_aop );
|
|
|
|
EVENT_AddIO( async_ctl.ws_aop->fd[0], EVENT_IO_READ );
|
|
pwsi->num_async_rq++;
|
|
|
|
async_ctl.ws_aop->pid = fork();
|
|
if( async_ctl.ws_aop->pid )
|
|
{
|
|
TRACE(winsock, "\tasync_op = %04x (child %i)\n",
|
|
handle, async_ctl.ws_aop->pid);
|
|
|
|
close(async_ctl.ws_aop->fd[1]); /* write endpoint */
|
|
if( async_ctl.ws_aop->pid > 0 )
|
|
return __ws_gethandle(async_ctl.ws_aop);
|
|
|
|
/* fork() failed */
|
|
|
|
pwsi->num_async_rq--;
|
|
EVENT_DeleteIO( async_ctl.ws_aop->fd[0], EVENT_IO_READ );
|
|
close(async_ctl.ws_aop->fd[0]);
|
|
pwsi->err = WSAEWOULDBLOCK;
|
|
}
|
|
else
|
|
{
|
|
extern BOOL32 THREAD_InitDone;
|
|
|
|
THREAD_InitDone = FALSE;
|
|
/* child process */
|
|
|
|
close(async_ctl.ws_aop->fd[0]); /* read endpoint */
|
|
switch( flag & WSMSG_ASYNC_RQMASK )
|
|
{
|
|
case WSMSG_ASYNC_HOSTBYADDR:
|
|
case WSMSG_ASYNC_HOSTBYNAME:
|
|
WS_do_async_gethost(pwsi, flag);
|
|
break;
|
|
case WSMSG_ASYNC_PROTOBYNUM:
|
|
case WSMSG_ASYNC_PROTOBYNAME:
|
|
WS_do_async_getproto(pwsi, flag);
|
|
break;
|
|
case WSMSG_ASYNC_SERVBYPORT:
|
|
case WSMSG_ASYNC_SERVBYNAME:
|
|
WS_do_async_getserv(pwsi, flag);
|
|
break;
|
|
}
|
|
_exit(0); /* skip atexit()'ed cleanup */
|
|
}
|
|
}
|
|
else pwsi->err = wsaErrno(); /* failed to create pipe */
|
|
|
|
__ws_memfree((void*)async_ctl.ws_aop);
|
|
} else pwsi->err = WSAEWOULDBLOCK;
|
|
return 0;
|
|
}
|
|
|
|
static int _async_notify()
|
|
{
|
|
/* use half-duplex pipe to send variable length packets
|
|
* to the parent process */
|
|
|
|
write(async_ctl.ws_aop->fd[1], &async_ctl.ilength, sizeof(unsigned));
|
|
write(async_ctl.ws_aop->fd[1], async_ctl.buffer, async_ctl.ilength );
|
|
|
|
#ifndef __EMX__
|
|
kill(getppid(), SIGIO); /* simulate async I/O */
|
|
#endif
|
|
|
|
/* was a __WS_ASYNC_DEBUG statement */
|
|
TRACE(winsock, "handler - notify aop [%d, buf %d]\n",
|
|
async_ctl.ilength, async_ctl.ws_aop->buflen);
|
|
return 1;
|
|
}
|
|
|
|
static void _async_fail()
|
|
{
|
|
/* write a DWORD with error code (low word is zero) */
|
|
|
|
async_ctl.ilength =
|
|
(h_errno < 0) ? (unsigned)WSAMAKEASYNCREPLY( 0, wsaErrno() )
|
|
: (unsigned)WSAMAKEASYNCREPLY( 0, wsaHerrno() );
|
|
write(async_ctl.ws_aop->fd[1], &async_ctl.ilength, sizeof(unsigned) );
|
|
#ifndef __EMX__
|
|
kill(getppid(), SIGIO); /* simulate async I/O */
|
|
#endif
|
|
|
|
/* was a __WS_ASYNC_DEBUG statement */
|
|
TRACE(winsock, "handler - failed aop [%d, buf %d]\n",
|
|
async_ctl.ilength, async_ctl.ws_aop->buflen);
|
|
}
|
|
|
|
void dump_ws_hostent_offset(struct ws_hostent* wshe)
|
|
{
|
|
int i;
|
|
char* base = (char*)wshe;
|
|
unsigned* ptr;
|
|
|
|
DUMP("h_name = %08x\t[%s]\n",
|
|
(unsigned)wshe->h_name, base + (unsigned)wshe->h_name);
|
|
DUMP("h_aliases = %08x\t[%08x]\n",
|
|
(unsigned)wshe->h_aliases, (unsigned)(base+(unsigned)wshe->h_aliases));
|
|
ptr = (unsigned*)(base + (unsigned)wshe->h_aliases);
|
|
for(i = 0; ptr[i]; i++ )
|
|
{
|
|
DUMP("%i - %08x [%s]\n", i + 1, ptr[i], ((char*)base) + ptr[i]);
|
|
}
|
|
DUMP("h_length = %i\n", wshe->h_length);
|
|
}
|
|
|
|
void WS_do_async_gethost(LPWSINFO pwsi, unsigned flag )
|
|
{
|
|
int size = 0;
|
|
struct hostent* p_he;
|
|
|
|
close(async_ctl.ws_aop->fd[0]);
|
|
|
|
p_he = (flag & WSMSG_ASYNC_HOSTBYNAME)
|
|
? gethostbyname(async_ctl.rq.name)
|
|
: gethostbyaddr(async_ctl.rq.name,
|
|
async_ctl.ilength, async_ctl.type);
|
|
|
|
TRACE(winsock,"DNS: got hostent for [%s]\n", async_ctl.rq.name );
|
|
|
|
if( p_he ) /* convert to the Winsock format with internal pointers as offsets */
|
|
size = WS_dup_he(pwsi, p_he, WS_DUP_OFFSET |
|
|
((flag & WSMSG_WIN32_AOP) ? WS_DUP_LINEAR : WS_DUP_SEGPTR) );
|
|
if( size )
|
|
{
|
|
async_ctl.buffer = (char*)pwsi->he;
|
|
async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
|
|
_async_notify( flag );
|
|
}
|
|
else _async_fail();
|
|
}
|
|
|
|
void WS_do_async_getproto(LPWSINFO pwsi, unsigned flag )
|
|
{
|
|
int size = 0;
|
|
struct protoent* p_pe;
|
|
|
|
close(async_ctl.ws_aop->fd[0]);
|
|
p_pe = (flag & WSMSG_ASYNC_PROTOBYNAME)
|
|
? getprotobyname(async_ctl.rq.name)
|
|
: getprotobynumber(async_ctl.type);
|
|
|
|
TRACE(winsock,"DNS: got protoent for [%s]\n", async_ctl.rq.name );
|
|
|
|
if( p_pe ) /* convert to the Winsock format with internal pointers as offsets */
|
|
size = WS_dup_pe(pwsi, p_pe, WS_DUP_OFFSET |
|
|
((flag & WSMSG_WIN32_AOP) ? WS_DUP_LINEAR : WS_DUP_SEGPTR) );
|
|
if( size )
|
|
{
|
|
async_ctl.buffer = (char*)pwsi->pe;
|
|
async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
|
|
_async_notify( flag );
|
|
}
|
|
else _async_fail();
|
|
}
|
|
|
|
void WS_do_async_getserv(LPWSINFO pwsi, unsigned flag )
|
|
{
|
|
int size = 0;
|
|
struct servent* p_se;
|
|
|
|
close(async_ctl.ws_aop->fd[0]);
|
|
p_se = (flag & WSMSG_ASYNC_SERVBYNAME)
|
|
? getservbyname(async_ctl.rq.name, async_ctl.buffer)
|
|
: getservbyport(async_ctl.type, async_ctl.buffer);
|
|
|
|
if( p_se ) /* convert to the Winsock format with internal pointers as offsets */
|
|
size = WS_dup_se(pwsi, p_se, WS_DUP_OFFSET |
|
|
((flag & WSMSG_WIN32_AOP) ? WS_DUP_LINEAR : WS_DUP_SEGPTR) );
|
|
if( size )
|
|
{
|
|
async_ctl.buffer = (char*)pwsi->se;
|
|
async_ctl.ilength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
|
|
_async_notify( flag );
|
|
}
|
|
else _async_fail();
|
|
}
|
|
|
|
/* ----------------------------------- helper functions -
|
|
*
|
|
* Raw results from the pipe contain internal pointers stored as
|
|
* offsets relative to the beginning of the buffer and we need
|
|
* to apply a fixup before passing them to applications.
|
|
*
|
|
* NOTE: It is possible to exploit the fact that fork() doesn't
|
|
* change the buffer address by storing fixed up pointers right
|
|
* in the handler. However, this will get in the way if we ever
|
|
* get around to implementing DNS helper daemon a-la Netscape 4.x.
|
|
*/
|
|
|
|
void fixup_wshe(struct ws_hostent* p_wshe, void* base)
|
|
{
|
|
/* add 'base' to ws_hostent pointers to convert them from offsets */
|
|
|
|
int i;
|
|
unsigned* p_aliases,*p_addr;
|
|
|
|
p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases);
|
|
p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list);
|
|
((unsigned)(p_wshe->h_name)) += (unsigned)base;
|
|
((unsigned)(p_wshe->h_aliases)) += (unsigned)base;
|
|
((unsigned)(p_wshe->h_addr_list)) += (unsigned)base;
|
|
for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
|
|
for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
|
|
}
|
|
|
|
void fixup_wspe(struct ws_protoent* p_wspe, void* base)
|
|
{
|
|
int i;
|
|
unsigned* p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases);
|
|
((unsigned)(p_wspe->p_name)) += (unsigned)base;
|
|
((unsigned)(p_wspe->p_aliases)) += (unsigned)base;
|
|
for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
|
|
}
|
|
|
|
void fixup_wsse(struct ws_servent* p_wsse, void* base)
|
|
{
|
|
int i;
|
|
unsigned* p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
|
|
((unsigned)(p_wsse->s_name)) += (unsigned)base;
|
|
((p_wsse->s_proto)) += (unsigned)base;
|
|
((p_wsse->s_aliases)) += (unsigned)base;
|
|
for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
|
|
}
|