Release 961201
Sat Nov 30 19:21:17 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [configure]
Re-generated with autoconf 2.11. Let me know if you have
problems.
* [controls/listbox.c] [controls/oldlbox.c]
Listboxes rewritten from scratch. Moved old code still used by
comboboxes to oldlbox.c
* [misc/registry.c]
Use temporary file when saving registry.
* [windows/dialog.c]
Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
* [windows/winproc.c]
Added translation for listbox Win32 messages.
Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [controls/widgets.c] [controls/button.c]
Fixed some incompatibilities with CTL3D DLL.
* [windows/dialog.c]
Made dialog windows fit into the desktop.
* [misc/winsock.c] [misc/winsock_async.c]
New Winsock engine.
* [windows/message.c]
GetMessage() fixes.
* [windows/queue.c] [windows/hook.c] [windows/win.c]
SetMessageQueue() fixes.
Fri Nov 29 10:25:12 1996 Slaven Rezic <eserte@cs.tu-berlin.de>
* [objects/text.c]
DrawText16(): Fixed return value.
Tue Nov 26 14:47:09 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [files/profile.c] [*/*]
Added Win32 profile functions, updated to new naming standard.
* [objects/font.c] [if1632/thunk.c] [include/windows.h]
Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
structures.
* [misc/ole2nls.c] [if1632/thunk.c]
Added EnumSystemLocales() (winhelp.exe).
* [misc/registry.c]
Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
* [win32/file.c]
Partially fixed CreateFileMapping(), added UnmapViewOfFile().
Sat Nov 23 23:36:05 1996 Ronan Waide <waider@waider.ie>
* [misc/shell.c]
Fixed some FIXMEs relating to ShellExec() and FindExecutable().
* [misc/main.c]
Implemented a few more of the SystemParametersInfo() cases.
Tue Nov 19 01:24:34 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [include/keyboard.h]
New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
* [include/windows.h]
New [VK_A, VK_Z] and [VK_0, VK9] macros.
* [misc/keyboard.c]
Fixes in KeyTable and ToAscii.
* [objects/font.c]
FONT_init : Give default value for MSWIN "system" font.
FONT_MatchFont : Do not try every size of a font family if the
family does not exist.
* [windows/event.c]
lastEventChar hack removed.
KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
and QueueKeyStateTable (maintained in message.c).
EVENT_key : Corrections to the extended bit setting.
* [windows/message.c] [windows/keyboard.c]
Implementation of a new QueueKeyStateTable : table of key states
valid when messages are retrieved by GetMessage or PeekMessage,
and valid for TranslateMessage.
TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
and ToAscii.
Mon Nov 18 16:59:01 1996 Robert Pouliot <krynos@clic.net>
* [graphics/Makefile.in] [graphics/wing.c]
[if1632/wing.spec]
Some functions for WinG support, mostly empty stubs.
* [misc/crtdll.c] [if1632/crtdll.spec]
Many functions added to CRTDLL, mostly calls to Unix C library.
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 32b5cc2..e21b133 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -38,7 +38,8 @@
user.c \
ver.c \
w32sys.c \
- winsocket.c \
+ winsock.c \
+ winsock_async.c \
wsprintf.c \
xmalloc.c
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 80aa834..fddf5a9 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -166,22 +166,14 @@
*/
static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath)
{
- BOOL32 ret = FALSE;
int len;
- char *str = SEGPTR_ALLOC(512);
- if (!str) return TRUE;
+ char str[512];
lstrcpyn32A( str, newPath, 512 );
len = strlen(str);
- GetDlgItemText32A( hWnd, edt1, str + len, 512 - len );
- if (DlgDirList(hWnd, SEGPTR_GET(str), lst1, 0, 0x0000))
- {
- strcpy( str, "*.*" );
- DlgDirList(hWnd, SEGPTR_GET(str), lst2, stc1, 0x8010 );
- ret = TRUE;
- }
- SEGPTR_FREE(str);
- return ret;
+ GetDlgItemText32A( hWnd, edt1, str + len, sizeof(str) - len );
+ if (!DlgDirList32A( hWnd, str, lst1, 0, 0x0000 )) return FALSE;
+ return DlgDirList32A( hWnd, "*.*", lst2, stc1, 0x8010 );
}
/***********************************************************************
@@ -388,10 +380,7 @@
lpofn->nFilterIndex, tmpstr);
SetDlgItemText32A( hWnd, edt1, tmpstr );
/* get drive list */
- pstr = SEGPTR_ALLOC(1);
- *pstr = 0;
- DlgDirListComboBox16(hWnd, SEGPTR_GET(pstr), cmb2, 0, 0xC000);
- SEGPTR_FREE(pstr);
+ DlgDirListComboBox32A(hWnd, "", cmb2, 0, 0xC000);
/* read initial directory */
if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL)
{
diff --git a/misc/crtdll.c b/misc/crtdll.c
index e7a8be6..66b0549 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -616,6 +616,22 @@
}
/*********************************************************************
+ * calloc (CRTDLL.350)
+ */
+VOID* CRTDLL_calloc(DWORD size, DWORD count)
+{
+ return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
+}
+
+/*********************************************************************
+ * realloc (CRTDLL.447)
+ */
+VOID* CRTDLL_realloc( VOID *ptr, DWORD size )
+{
+ return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
+}
+
+/*********************************************************************
* free (CRTDLL.427)
*/
VOID CRTDLL_free(LPVOID ptr)
diff --git a/misc/driver.c b/misc/driver.c
index e09113b..c0a23b0 100644
--- a/misc/driver.c
+++ b/misc/driver.c
@@ -21,7 +21,7 @@
char str[256];
LPSTR ptr;
- if (GetPrivateProfileString( "drivers", NULL, "", str, sizeof(str),
+ if (GetPrivateProfileString32A( "drivers", NULL, "", str, sizeof(str),
"SYSTEM.INI" ) < 2)
{
fprintf( stderr,
@@ -84,7 +84,7 @@
lpDriverName, lpSectionName, lParam );
if (lpSectionName == NULL) lpSectionName = "drivers";
- GetPrivateProfileString( lpSectionName, lpDriverName, "", DrvName,
+ GetPrivateProfileString32A( lpSectionName, lpDriverName, "", DrvName,
sizeof(DrvName), "SYSTEM.INI" );
dprintf_driver( stddeb,"OpenDriver // DrvName='%s'\n", DrvName );
if (lstrlen32A(DrvName) < 1) return 0;
diff --git a/misc/keyboard.c b/misc/keyboard.c
index 750a645..cf0cbbe 100644
--- a/misc/keyboard.c
+++ b/misc/keyboard.c
@@ -8,6 +8,7 @@
#include <string.h>
#include <ctype.h>
#include "windows.h"
+#include "keyboard.h"
#include "stddebug.h"
/* #define DEBUG_KEYBOARD */
#include "debug.h"
@@ -22,105 +23,110 @@
static const struct KeyTableEntry KeyTable[] =
{
- { 0x3, 0x3, 0x0, "" },
- { 0x8, 0x8, 0xe, "Backspace" },
- { 0x9, 0x9, 0xf, "Tab" },
- { 0xc, 0x0, 0x4c, "Num 5" },
- { 0xd, 0xd, 0x1c, "Enter" },
- { 0x10, 0x0, 0x2a, "Shift" },
- { 0x11, 0x0, 0x1d, "Ctrl" },
- { 0x12, 0x0, 0x38, "Alt" },
- { 0x14, 0x0, 0x3a, "Caps Lock" },
- { 0x1b, 0x1b, 0x1, "Esc" },
- { 0x20, 0x20, 0x39, "Space" },
- { 0x21, 0x0, 0x49, "Num 9" },
- { 0x22, 0x0, 0x51, "Num 3" },
- { 0x23, 0x0, 0x4f, "Num 1" },
- { 0x24, 0x0, 0x47, "Num 7" },
- { 0x25, 0x0, 0x4b, "Num 4" },
- { 0x26, 0x0, 0x48, "Num 8" },
- { 0x27, 0x0, 0x4d, "Num 6" },
- { 0x28, 0x0, 0x50, "Num 2" },
- { 0x2d, 0x0, 0x52, "Num 0" },
- { 0x2e, 0x0, 0x53, "Num Del" },
- { 0x30, 0x30, 0xb, "0" },
- { 0x31, 0x31, 0x2, "1" },
- { 0x32, 0x32, 0x3, "2" },
- { 0x33, 0x33, 0x4, "3" },
- { 0x34, 0x34, 0x5, "4" },
- { 0x35, 0x35, 0x6, "5" },
- { 0x36, 0x36, 0x7, "6" },
- { 0x37, 0x37, 0x8, "7" },
- { 0x38, 0x38, 0x9, "8" },
- { 0x39, 0x39, 0xa, "9" },
- { 0x41, 0x41, 0x1e, "A" },
- { 0x42, 0x42, 0x30, "B" },
- { 0x43, 0x43, 0x2e, "C" },
- { 0x44, 0x44, 0x20, "D" },
- { 0x45, 0x45, 0x12, "E" },
- { 0x46, 0x46, 0x21, "F" },
- { 0x47, 0x47, 0x22, "G" },
- { 0x48, 0x48, 0x23, "H" },
- { 0x49, 0x49, 0x17, "I" },
- { 0x4a, 0x4a, 0x24, "J" },
- { 0x4b, 0x4b, 0x25, "K" },
- { 0x4c, 0x4c, 0x26, "L" },
- { 0x4d, 0x4d, 0x32, "M" },
- { 0x4e, 0x4e, 0x31, "N" },
- { 0x4f, 0x4f, 0x18, "O" },
- { 0x50, 0x50, 0x19, "P" },
- { 0x51, 0x51, 0x10, "Q" },
- { 0x52, 0x52, 0x13, "R" },
- { 0x53, 0x53, 0x1f, "S" },
- { 0x54, 0x54, 0x14, "T" },
- { 0x55, 0x55, 0x16, "U" },
- { 0x56, 0x56, 0x2f, "V" },
- { 0x57, 0x57, 0x11, "W" },
- { 0x58, 0x58, 0x2d, "X" },
- { 0x59, 0x59, 0x15, "Y" },
- { 0x5a, 0x5a, 0x2c, "Z" },
- { 0x60, 0x0, 0x52, "Num 0" },
- { 0x61, 0x0, 0x4f, "Num 1" },
- { 0x62, 0x0, 0x50, "Num 2" },
- { 0x63, 0x0, 0x51, "Num 3" },
- { 0x64, 0x0, 0x4b, "Num 4" },
- { 0x65, 0x0, 0x4c, "Num 5" },
- { 0x66, 0x0, 0x4d, "Num 6" },
- { 0x67, 0x0, 0x47, "Num 7" },
- { 0x68, 0x0, 0x48, "Num 8" },
- { 0x69, 0x0, 0x49, "Num 9" },
- { 0x6a, 0x2a, 0x37, "Num *" },
- { 0x6b, 0x2b, 0x4e, "Num +" },
- { 0x6c, 0x0, 0x0, "" },
- { 0x6d, 0x2d, 0x4a, "Num -" },
- { 0x6e, 0x2e, 0x53, "Num Del" },
- { 0x6f, 0x2f, 0x0, "" },
- { 0x70, 0x0, 0x3b, "F1" },
- { 0x71, 0x0, 0x3c, "F2" },
- { 0x72, 0x0, 0x3d, "F3" },
- { 0x73, 0x0, 0x3e, "F4" },
- { 0x74, 0x0, 0x3f, "F5" },
- { 0x75, 0x0, 0x40, "F6" },
- { 0x76, 0x0, 0x41, "F7" },
- { 0x77, 0x0, 0x42, "F8" },
- { 0x78, 0x0, 0x43, "F9" },
- { 0x79, 0x0, 0x44, "F10" },
- { 0x7a, 0x0, 0x57, "F11" },
- { 0x7b, 0x0, 0x58, "F12" },
- { 0x90, 0x0, 0x45, "Pause" },
- { 0x91, 0x0, 0x46, "Scroll Lock" },
- { 0xba, 0x3b, 0x27, ";" },
- { 0xbb, 0x3d, 0xd, "=" },
- { 0xbc, 0x2c, 0x33, "," },
- { 0xbd, 0x2d, 0xc, "-" },
- { 0xbe, 0x2e, 0x34, "." },
- { 0xbf, 0x2f, 0x35, "/" },
- { 0xc0, 0x60, 0x29, "`" },
- { 0xdb, 0x5b, 0x1a, "[" },
- { 0xdc, 0x5c, 0x2b, "\\" },
- { 0xdd, 0x5d, 0x1b, "]" },
- { 0xde, 0x27, 0x28, "\'" },
- { 0xe2, 0x5c, 0x56, "\\" },
+ { VK_CANCEL, 0x3, 0, "" },
+ { VK_BACK, 0x8, 0xe, "Backspace" },
+ { VK_TAB, 0x9, 0xf, "Tab" },
+ { VK_CLEAR, 0, 0x4c, "Clear" },
+ { VK_RETURN, 0xd, 0x1c, "Enter" },
+ { VK_SHIFT, 0, 0x2a, "Shift" },
+ { VK_CONTROL, 0, 0x1d, "Ctrl" },
+ { VK_MENU, 0, 0x38, "Alt" },
+ { VK_CAPITAL, 0, 0x3a, "Caps Lock" },
+ { VK_ESCAPE, 0x1b, 0x1, "Esc" },
+ { VK_SPACE, 0x20, 0x39, "Space" },
+ { VK_PRIOR, 0, 0x49, "Page Up" },
+ { VK_NEXT, 0, 0x51, "Page Down" },
+ { VK_END, 0, 0x4f, "End" },
+ { VK_HOME, 0, 0x47, "Home" },
+ { VK_LEFT, 0, 0x4b, "Left Arrow" },
+ { VK_UP, 0, 0x48, "Up Arrow" },
+ { VK_RIGHT, 0, 0x4d, "Right Arrow" },
+ { VK_DOWN, 0, 0x50, "Down Arrow" },
+ { VK_INSERT, 0, 0x52, "Ins" },
+ { VK_DELETE, 0, 0x53, "Del" },
+ { VK_0, 0x30, 0xb, "0" },
+ { VK_1, 0x31, 0x2, "1" },
+ { VK_2, 0x32, 0x3, "2" },
+ { VK_3, 0x33, 0x4, "3" },
+ { VK_4, 0x34, 0x5, "4" },
+ { VK_5, 0x35, 0x6, "5" },
+ { VK_6, 0x36, 0x7, "6" },
+ { VK_7, 0x37, 0x8, "7" },
+ { VK_8, 0x38, 0x9, "8" },
+ { VK_9, 0x39, 0xa, "9" },
+ { VK_A, 0x41, 0x1e, "A" },
+ { VK_B, 0x42, 0x30, "B" },
+ { VK_C, 0x43, 0x2e, "C" },
+ { VK_D, 0x44, 0x20, "D" },
+ { VK_E, 0x45, 0x12, "E" },
+ { VK_F, 0x46, 0x21, "F" },
+ { VK_G, 0x47, 0x22, "G" },
+ { VK_H, 0x48, 0x23, "H" },
+ { VK_I, 0x49, 0x17, "I" },
+ { VK_J, 0x4a, 0x24, "J" },
+ { VK_K, 0x4b, 0x25, "K" },
+ { VK_L, 0x4c, 0x26, "L" },
+ { VK_M, 0x4d, 0x32, "M" },
+ { VK_N, 0x4e, 0x31, "N" },
+ { VK_O, 0x4f, 0x18, "O" },
+ { VK_P, 0x50, 0x19, "P" },
+ { VK_Q, 0x51, 0x10, "Q" },
+ { VK_R, 0x52, 0x13, "R" },
+ { VK_S, 0x53, 0x1f, "S" },
+ { VK_T, 0x54, 0x14, "T" },
+ { VK_U, 0x55, 0x16, "U" },
+ { VK_V, 0x56, 0x2f, "V" },
+ { VK_W, 0x57, 0x11, "W" },
+ { VK_X, 0x58, 0x2d, "X" },
+ { VK_Y, 0x59, 0x15, "Y" },
+ { VK_Z, 0x5a, 0x2c, "Z" },
+ { VK_NUMPAD0, 0, 0x52, "Num 0" },
+ { VK_NUMPAD1, 0, 0x4f, "Num 1" },
+ { VK_NUMPAD2, 0, 0x50, "Num 2" },
+ { VK_NUMPAD3, 0, 0x51, "Num 3" },
+ { VK_NUMPAD4, 0, 0x4b, "Num 4" },
+ { VK_NUMPAD5, 0, 0x4c, "Num 5" },
+ { VK_NUMPAD6, 0, 0x4d, "Num 6" },
+ { VK_NUMPAD7, 0, 0x47, "Num 7" },
+ { VK_NUMPAD8, 0, 0x48, "Num 8" },
+ { VK_NUMPAD9, 0, 0x49, "Num 9" },
+ { VK_MULTIPLY, 0x2a, 0x37, "Num *" },
+ { VK_ADD, 0x2b, 0x4e, "Num +" },
+ { VK_SEPARATOR, 0, 0, "" },
+ { VK_SUBTRACT, 0x2d, 0x4a, "Num -" },
+ { VK_DECIMAL, 0x2e, 0x53, "Num Del" },
+ { VK_DIVIDE, 0x2f, 0, "Num /" },
+ { VK_F1, 0, 0x3b, "F1" },
+ { VK_F2, 0, 0x3c, "F2" },
+ { VK_F3, 0, 0x3d, "F3" },
+ { VK_F4, 0, 0x3e, "F4" },
+ { VK_F5, 0, 0x3f, "F5" },
+ { VK_F6, 0, 0x40, "F6" },
+ { VK_F7, 0, 0x41, "F7" },
+ { VK_F8, 0, 0x42, "F8" },
+ { VK_F9, 0, 0x43, "F9" },
+ { VK_F10, 0, 0x44, "F10" },
+ { VK_F11, 0, 0x57, "F11" },
+ { VK_F12, 0, 0x58, "F12" },
+ { VK_NUMLOCK, 0, 0x45, "Num Lock" },
+ { VK_SCROLL, 0, 0x46, "Scroll Lock" },
+ /* Allowable ranges for OEM-specific virtual-key codes */
+/* - 0xBA-0xC0 OEM specific */
+ { 0xba, 0x3b, 0x27, ";" },
+ { 0xbb, 0x3d, 0xd, "=" },
+ { 0xbc, 0x2c, 0x33, "," },
+ { 0xbd, 0x2d, 0xc, "-" },
+ { 0xbe, 0x2e, 0x34, "." },
+ { 0xbf, 0x2f, 0x35, "/" },
+ { 0xc0, 0x60, 0x29, "`" },
+/* - 0xDB-0xE4 OEM specific */
+ { 0xdb, 0x5b, 0x1a, "[" },
+ { 0xdc, 0x5c, 0x2b, "\\" },
+ { 0xdd, 0x5d, 0x1b, "]" },
+ { 0xde, 0x27, 0x28, "'" },
+ { 0xe2, 0x5c, 0x56, "\\" },
+/* - 0xE6 OEM specific */
+/* - 0xE9-0xF5 OEM specific */
};
#define KeyTableSize sizeof(KeyTable) / sizeof(struct KeyTableEntry)
@@ -128,34 +134,55 @@
int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState,
LPVOID lpChar, WORD wFlags)
{
+ char shift = lpKeyState[VK_SHIFT] < 0;
int i;
- dprintf_keyboard(stddeb,"ToAscii (%d,%d)\n",wVirtKey, wScanCode);
+ dprintf_keyboard(stddeb, "ToAscii (%x,%x) -> ", wVirtKey, wScanCode);
/* FIXME: codepage is broken */
- for (i = 0 ; i != KeyTableSize ; i++)
- if (KeyTable[i].virtualkey == wVirtKey)
- {
- dprintf_keyboard(stddeb,"\t\tchar = %s\n", KeyTable[i].name);
- if( isprint(KeyTable[i].ASCII) || isspace(KeyTable[i].ASCII) )
- {
- *(BYTE*)lpChar = KeyTable[i].ASCII;
- *(((BYTE*)lpChar) + 1) = 0;
-
- if( isalpha( *(BYTE*)lpChar ) )
- if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) ||
- (!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) )
- *(BYTE*)lpChar = toupper( *(BYTE*)lpChar );
- else
- *(BYTE*)lpChar = tolower( *(BYTE*)lpChar );
-
- return 1;
- }
- }
-
*(BYTE*)lpChar = 0;
- return 0;
+ switch (wVirtKey)
+ {
+#define vkcase2(k1,k2,val) case val : *(BYTE*)lpChar = shift ? k2 : k1; break;
+#define vkcase(k, val) vkcase2(val, k, val)
+ WINE_VKEY_MAPPINGS
+#undef vkcase
+#undef vkcase2
+ default :
+ for (i = 0 ; ; i++)
+ {
+ if (i == KeyTableSize)
+ {
+ dprintf_keyboard(stddeb, "0\n");
+ return 0;
+ }
+ if (KeyTable[i].virtualkey == wVirtKey)
+ {
+ if (!isprint(KeyTable[i].ASCII) && !isspace(KeyTable[i].ASCII))
+ {
+ dprintf_keyboard(stddeb, "0\n");
+ return 0;
+ }
+ dprintf_keyboard(stddeb,"\"%s\" ", KeyTable[i].name);
+
+ *(BYTE*)lpChar = KeyTable[i].ASCII;
+ *(((BYTE*)lpChar) + 1) = 0;
+
+ if (isalpha(*(BYTE*)lpChar))
+ if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) ||
+ (!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) )
+ *(BYTE*)lpChar = toupper( *(BYTE*)lpChar );
+ else
+ *(BYTE*)lpChar = tolower( *(BYTE*)lpChar );
+ break;
+ }
+ }
+ }
+ if (lpKeyState[VK_CONTROL] < 0)
+ *(BYTE*)lpChar = *(BYTE*)lpChar & 0x1f;
+ dprintf_keyboard(stddeb, "1 (%x)\n", *(BYTE*)lpChar);
+ return 1;
}
DWORD OemKeyScan(WORD wOemChar)
@@ -166,7 +193,16 @@
}
/* VkKeyScan translates an ANSI character to a virtual-key and shift code
- * for the current keyboard. */
+ * for the current keyboard.
+ * FIXME high-order byte should yield :
+ * 0 Unshifted
+ * 1 Shift
+ * 2 Ctrl
+ * 3-5 Shift-key combinations that are not used for characters
+ * 6 Ctrl-Alt
+ * 7 Ctrl-Alt-Shift
+ * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
+ */
WORD VkKeyScan(WORD cChar)
{
@@ -208,26 +244,28 @@
int i;
switch(wMapType) {
- case 0:
+ case 0: /* vkey-code to scan-code */
for (i = 0 ; i != KeyTableSize ; i++)
if (KeyTable[i].virtualkey == wCode)
return KeyTable[i].scancode;
return 0;
- case 1:
+ case 1: /* scan-code to vkey-code */
for (i = 0 ; i != KeyTableSize ; i++)
if (KeyTable[i].scancode == wCode)
return KeyTable[i].virtualkey;
return 0;
- case 2:
+ case 2: /* vkey-code to unshifted ANSI code */
+ /* FIXME : what does unshifted mean ? 'a' or 'A' ? */
for (i = 0 ; i != KeyTableSize ; i++)
if (KeyTable[i].virtualkey == wCode)
return KeyTable[i].ASCII;
return 0;
- default:
- fprintf(stderr, "MapVirtualKey: unknown wMapType!\n");
+ default: /* reserved */
+ fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
+ wMapType);
return 0;
}
return 0;
diff --git a/misc/main.c b/misc/main.c
index b9113a7..f8597ec 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -804,7 +804,8 @@
fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
break;
}
-
+ if( getVersionEx.dwPlatformId == VER_PLATFORM_WIN32_NT )
+ result |= 0x4000; /* undocumented WF_WINNT */
return result;
}
@@ -1076,18 +1077,21 @@
break;
case SPI_GETFASTTASKSWITCH:
- *(BOOL *) lpvParam = FALSE;
- /* FIXME GetProfileInt( "windows", "CoolSwitch", 1 ) */
+ if ( GetProfileInt32A( "windows", "CoolSwitch", 1 ) == 1 )
+ *(BOOL *) lpvParam = TRUE;
+ else
+ *(BOOL *) lpvParam = FALSE;
break;
case SPI_GETGRIDGRANULARITY:
- *(INT *) lpvParam = 1;
- /* FIXME GetProfileInt( "desktop", "GridGranularity", 1 ) */
- break;
+ *(INT *) lpvParam = GetProfileInt32A( "desktop",
+ "GridGranularity",
+ 1 );
+ break;
case SPI_GETICONTITLEWRAP:
*(BOOL *) lpvParam = FALSE;
- /* FIXME GetProfileInt( "desktop", "?", True ) */
+ /* FIXME GetProfileInt32A( "desktop", "?", True ) */
break;
case SPI_GETKEYBOARDDELAY:
@@ -1105,9 +1109,11 @@
break;
case SPI_GETSCREENSAVEACTIVE:
- /* FIXME GetProfileInt( "windows", "ScreenSaveActive", 1 ); */
- *(BOOL *) lpvParam = FALSE;
- break;
+ if ( GetProfileInt32A( "windows", "ScreenSaveActive", 1 ) == 1 )
+ *(BOOL *) lpvParam = TRUE;
+ else
+ *(BOOL *) lpvParam = FALSE;
+ break;
case SPI_GETSCREENSAVETIMEOUT:
/* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */
@@ -1116,18 +1122,20 @@
break;
case SPI_ICONHORIZONTALSPACING:
+ /* FIXME Get/SetProfileInt */
if (lpvParam == NULL)
- fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
- else
- *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
+ /*SetSystemMetrics( SM_CXICONSPACING, uParam )*/ ;
+ else
+ *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
break;
case SPI_ICONVERTICALSPACING:
- if (lpvParam == NULL)
- fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
- else
- *(INT *) lpvParam = GetSystemMetrics( SM_CYICONSPACING );
- break;
+ /* FIXME Get/SetProfileInt */
+ if (lpvParam == NULL)
+ /*SetSystemMetrics( SM_CYICONSPACING, uParam )*/ ;
+ else
+ *(INT *) lpvParam = GetSystemMetrics(SM_CYICONSPACING);
+ break;
case SPI_SETBEEP:
if (uParam == TRUE)
@@ -1147,7 +1155,7 @@
case SPI_SETSCREENSAVETIMEOUT:
XSetScreenSaver(display, uParam, 60, DefaultBlanking,
- DefaultExposures);
+ DefaultExposures);
break;
case SPI_SETDESKWALLPAPER:
@@ -1156,7 +1164,7 @@
case SPI_SETDESKPATTERN:
if ((INT) uParam == -1) {
- GetProfileString("Desktop", "Pattern",
+ GetProfileString32A("Desktop", "Pattern",
"170 85 170 85 170 85 170 85",
buffer, sizeof(buffer) );
return (DESKTOP_SetPattern((LPSTR) buffer));
@@ -1166,19 +1174,20 @@
case SPI_GETICONTITLELOGFONT:
{
- /* FIXME GetProfileString( "?", "?", "?" ) */
- LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
- lpLogFont->lfHeight = 10;
- lpLogFont->lfWidth = 0;
- lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
- lpLogFont->lfWeight = FW_NORMAL;
- lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
- lpLogFont->lfCharSet = ANSI_CHARSET;
- lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
- lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
- break;
- }
+ /* FIXME GetProfileString32A( "?", "?", "?" ) */
+ LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
+ lpLogFont->lfHeight = 10;
+ lpLogFont->lfWidth = 0;
+ lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
+ lpLogFont->lfWeight = FW_NORMAL;
+ lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
+ lpLogFont->lfCharSet = ANSI_CHARSET;
+ lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
+ break;
+ }
+
case SPI_LANGDRIVER:
case SPI_SETBORDER:
case SPI_SETDOUBLECLKHEIGHT:
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index 66a7a74..8669f50 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -4,16 +4,126 @@
* Copyright 1995 Martin von Loewis
*/
-/* At the moment, these are only empty stubs.
- */
-
#include <string.h>
+#include <malloc.h>
#include "windows.h"
#include "ole.h"
#include "options.h"
#include "winnls.h"
#include "stddebug.h"
#include "debug.h"
+#include "string32.h"
+
+/* Locale name to id map. used by EnumSystemLocales, GetLocalInfoA
+ * MUST contain all #defines from winnls.h
+ * last entry has NULL name, 0 id.
+ */
+#define LOCALE_ENTRY(x) {#x,LOCALE_##x}
+static struct tagLOCALE_NAME2ID {
+ char *name;
+ DWORD id;
+} locale_name2id[]= {
+ LOCALE_ENTRY(ILANGUAGE),
+ LOCALE_ENTRY(SLANGUAGE),
+ LOCALE_ENTRY(SENGLANGUAGE),
+ LOCALE_ENTRY(SABBREVLANGNAME),
+ LOCALE_ENTRY(SNATIVELANGNAME),
+ LOCALE_ENTRY(ICOUNTRY),
+ LOCALE_ENTRY(SCOUNTRY),
+ LOCALE_ENTRY(SENGCOUNTRY),
+ LOCALE_ENTRY(SABBREVCTRYNAME),
+ LOCALE_ENTRY(SNATIVECTRYNAME),
+ LOCALE_ENTRY(IDEFAULTLANGUAGE),
+ LOCALE_ENTRY(IDEFAULTCOUNTRY),
+ LOCALE_ENTRY(IDEFAULTCODEPAGE),
+ LOCALE_ENTRY(IDEFAULTANSICODEPAGE),
+ LOCALE_ENTRY(SLIST),
+ LOCALE_ENTRY(IMEASURE),
+ LOCALE_ENTRY(SDECIMAL),
+ LOCALE_ENTRY(STHOUSAND),
+ LOCALE_ENTRY(SGROUPING),
+ LOCALE_ENTRY(IDIGITS),
+ LOCALE_ENTRY(ILZERO),
+ LOCALE_ENTRY(INEGNUMBER),
+ LOCALE_ENTRY(SNATIVEDIGITS),
+ LOCALE_ENTRY(SCURRENCY),
+ LOCALE_ENTRY(SINTLSYMBOL),
+ LOCALE_ENTRY(SMONDECIMALSEP),
+ LOCALE_ENTRY(SMONTHOUSANDSEP),
+ LOCALE_ENTRY(SMONGROUPING),
+ LOCALE_ENTRY(ICURRDIGITS),
+ LOCALE_ENTRY(IINTLCURRDIGITS),
+ LOCALE_ENTRY(ICURRENCY),
+ LOCALE_ENTRY(INEGCURR),
+ LOCALE_ENTRY(SDATE),
+ LOCALE_ENTRY(STIME),
+ LOCALE_ENTRY(SSHORTDATE),
+ LOCALE_ENTRY(SLONGDATE),
+ LOCALE_ENTRY(STIMEFORMAT),
+ LOCALE_ENTRY(IDATE),
+ LOCALE_ENTRY(ILDATE),
+ LOCALE_ENTRY(ITIME),
+ LOCALE_ENTRY(ITIMEMARKPOSN),
+ LOCALE_ENTRY(ICENTURY),
+ LOCALE_ENTRY(ITLZERO),
+ LOCALE_ENTRY(IDAYLZERO),
+ LOCALE_ENTRY(IMONLZERO),
+ LOCALE_ENTRY(S1159),
+ LOCALE_ENTRY(S2359),
+ LOCALE_ENTRY(ICALENDARTYPE),
+ LOCALE_ENTRY(IOPTIONALCALENDAR),
+ LOCALE_ENTRY(IFIRSTDAYOFWEEK),
+ LOCALE_ENTRY(IFIRSTWEEKOFYEAR),
+ LOCALE_ENTRY(SDAYNAME1),
+ LOCALE_ENTRY(SDAYNAME2),
+ LOCALE_ENTRY(SDAYNAME3),
+ LOCALE_ENTRY(SDAYNAME4),
+ LOCALE_ENTRY(SDAYNAME5),
+ LOCALE_ENTRY(SDAYNAME6),
+ LOCALE_ENTRY(SDAYNAME7),
+ LOCALE_ENTRY(SABBREVDAYNAME1),
+ LOCALE_ENTRY(SABBREVDAYNAME2),
+ LOCALE_ENTRY(SABBREVDAYNAME3),
+ LOCALE_ENTRY(SABBREVDAYNAME4),
+ LOCALE_ENTRY(SABBREVDAYNAME5),
+ LOCALE_ENTRY(SABBREVDAYNAME6),
+ LOCALE_ENTRY(SABBREVDAYNAME7),
+ LOCALE_ENTRY(SMONTHNAME1),
+ LOCALE_ENTRY(SMONTHNAME2),
+ LOCALE_ENTRY(SMONTHNAME3),
+ LOCALE_ENTRY(SMONTHNAME4),
+ LOCALE_ENTRY(SMONTHNAME5),
+ LOCALE_ENTRY(SMONTHNAME6),
+ LOCALE_ENTRY(SMONTHNAME7),
+ LOCALE_ENTRY(SMONTHNAME8),
+ LOCALE_ENTRY(SMONTHNAME9),
+ LOCALE_ENTRY(SMONTHNAME10),
+ LOCALE_ENTRY(SMONTHNAME11),
+ LOCALE_ENTRY(SMONTHNAME12),
+ LOCALE_ENTRY(SMONTHNAME13),
+ LOCALE_ENTRY(SABBREVMONTHNAME1),
+ LOCALE_ENTRY(SABBREVMONTHNAME2),
+ LOCALE_ENTRY(SABBREVMONTHNAME3),
+ LOCALE_ENTRY(SABBREVMONTHNAME4),
+ LOCALE_ENTRY(SABBREVMONTHNAME5),
+ LOCALE_ENTRY(SABBREVMONTHNAME6),
+ LOCALE_ENTRY(SABBREVMONTHNAME7),
+ LOCALE_ENTRY(SABBREVMONTHNAME8),
+ LOCALE_ENTRY(SABBREVMONTHNAME9),
+ LOCALE_ENTRY(SABBREVMONTHNAME10),
+ LOCALE_ENTRY(SABBREVMONTHNAME11),
+ LOCALE_ENTRY(SABBREVMONTHNAME12),
+ LOCALE_ENTRY(SABBREVMONTHNAME13),
+ LOCALE_ENTRY(SPOSITIVESIGN),
+ LOCALE_ENTRY(SNEGATIVESIGN),
+ LOCALE_ENTRY(IPOSSIGNPOSN),
+ LOCALE_ENTRY(INEGSIGNPOSN),
+ LOCALE_ENTRY(IPOSSYMPRECEDES),
+ LOCALE_ENTRY(IPOSSEPBYSPACE),
+ LOCALE_ENTRY(INEGSYMPRECEDES),
+ LOCALE_ENTRY(INEGSEPBYSPACE),
+ {NULL,0},
+};
/***********************************************************************
* GetUserDefaultLCID (OLE2NLS.1)
@@ -86,137 +196,39 @@
*/
int GetLocaleInfoA(DWORD lcid,DWORD LCType,LPSTR buf,WORD len)
{
- char *retString;
- int retLen;
- dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n",
+ char *retString;
+ int found,i;
+
+ dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n",
lcid,LCType,buf,len);
-#if 0
- /* Wine is supporting only the default locale */
- if(lcid!=GetUserDefaultLCID())
- {
- dprintf_ole(stdnimp,"GetLocaleInfoA: Unknown locale\n");
- return 0;
- }
-#endif
/* As an option, we could obtain the value from win.ini.
This would not match the Wine compile-time option.
Also, not all identifiers are available from win.ini */
retString=0;
- retLen=0;
/* If we are through all of this, retLen should not be zero anymore.
If it is, the value is not supported */
-#define LOCVAL(type,value) if(type==LCType) \
- {retLen=strlen(value)+1;\
- retString=value; \
- }
-#define UNSUPPORTED(type) if(type==lcid)retString=#type;
+ i=0;
+ while (locale_name2id[i].name!=NULL) {
+ if (LCType == locale_name2id[i].id) {
+ retString = locale_name2id[i].name;
+ break;
+ }
+ i++;
+ }
+ if (!retString) {
+ fprintf(stderr,"Unkown LC type %lX\n",LCType);
+ return 0;
+ }
-/* I really wish I would know a better way to do this */
-UNSUPPORTED(LOCALE_ILANGUAGE)
-UNSUPPORTED(LOCALE_SLANGUAGE)
-UNSUPPORTED(LOCALE_SENGLANGUAGE)
-UNSUPPORTED(LOCALE_SABBREVLANGNAME)
-UNSUPPORTED(LOCALE_SNATIVELANGNAME)
-UNSUPPORTED(LOCALE_ICOUNTRY)
-UNSUPPORTED(LOCALE_SCOUNTRY)
-UNSUPPORTED(LOCALE_SENGCOUNTRY)
-UNSUPPORTED(LOCALE_SABBREVCTRYNAME)
-UNSUPPORTED(LOCALE_SNATIVECTRYNAME)
-UNSUPPORTED(LOCALE_IDEFAULTLANGUAGE)
-UNSUPPORTED(LOCALE_IDEFAULTCOUNTRY)
-UNSUPPORTED(LOCALE_IDEFAULTCODEPAGE)
-UNSUPPORTED(LOCALE_IDEFAULTANSICODEPAGE)
-UNSUPPORTED(LOCALE_SLIST)
-UNSUPPORTED(LOCALE_IMEASURE)
-UNSUPPORTED(LOCALE_SDECIMAL)
-UNSUPPORTED(LOCALE_STHOUSAND)
-UNSUPPORTED(LOCALE_SGROUPING)
-UNSUPPORTED(LOCALE_IDIGITS)
-UNSUPPORTED(LOCALE_ILZERO)
-UNSUPPORTED(LOCALE_INEGNUMBER)
-UNSUPPORTED(LOCALE_SNATIVEDIGITS)
-UNSUPPORTED(LOCALE_SCURRENCY)
-UNSUPPORTED(LOCALE_SINTLSYMBOL)
-UNSUPPORTED(LOCALE_SMONDECIMALSEP)
-UNSUPPORTED(LOCALE_SMONTHOUSANDSEP)
-UNSUPPORTED(LOCALE_SMONGROUPING)
-UNSUPPORTED(LOCALE_ICURRDIGITS)
-UNSUPPORTED(LOCALE_IINTLCURRDIGITS)
-UNSUPPORTED(LOCALE_ICURRENCY)
-UNSUPPORTED(LOCALE_INEGCURR)
-UNSUPPORTED(LOCALE_SDATE)
-UNSUPPORTED(LOCALE_STIME)
-UNSUPPORTED(LOCALE_SSHORTDATE)
-UNSUPPORTED(LOCALE_SLONGDATE)
-UNSUPPORTED(LOCALE_STIMEFORMAT)
-UNSUPPORTED(LOCALE_IDATE)
-UNSUPPORTED(LOCALE_ILDATE)
-UNSUPPORTED(LOCALE_ITIME)
-UNSUPPORTED(LOCALE_ITIMEMARKPOSN)
-UNSUPPORTED(LOCALE_ICENTURY)
-UNSUPPORTED(LOCALE_ITLZERO)
-UNSUPPORTED(LOCALE_IDAYLZERO)
-UNSUPPORTED(LOCALE_IMONLZERO)
-UNSUPPORTED(LOCALE_S1159)
-UNSUPPORTED(LOCALE_S2359)
-UNSUPPORTED(LOCALE_ICALENDARTYPE)
-UNSUPPORTED(LOCALE_IOPTIONALCALENDAR)
-UNSUPPORTED(LOCALE_IFIRSTDAYOFWEEK)
-UNSUPPORTED(LOCALE_IFIRSTWEEKOFYEAR)
-UNSUPPORTED(LOCALE_SDAYNAME1)
-UNSUPPORTED(LOCALE_SDAYNAME2)
-UNSUPPORTED(LOCALE_SDAYNAME3)
-UNSUPPORTED(LOCALE_SDAYNAME4)
-UNSUPPORTED(LOCALE_SDAYNAME5)
-UNSUPPORTED(LOCALE_SDAYNAME6)
-UNSUPPORTED(LOCALE_SDAYNAME7)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME1)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME2)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME3)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME4)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME5)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME6)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME7)
-UNSUPPORTED(LOCALE_SMONTHNAME1)
-UNSUPPORTED(LOCALE_SMONTHNAME2)
-UNSUPPORTED(LOCALE_SMONTHNAME3)
-UNSUPPORTED(LOCALE_SMONTHNAME4)
-UNSUPPORTED(LOCALE_SMONTHNAME5)
-UNSUPPORTED(LOCALE_SMONTHNAME6)
-UNSUPPORTED(LOCALE_SMONTHNAME7)
-UNSUPPORTED(LOCALE_SMONTHNAME8)
-UNSUPPORTED(LOCALE_SMONTHNAME9)
-UNSUPPORTED(LOCALE_SMONTHNAME10)
-UNSUPPORTED(LOCALE_SMONTHNAME11)
-UNSUPPORTED(LOCALE_SMONTHNAME12)
-UNSUPPORTED(LOCALE_SMONTHNAME13)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME1)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME2)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME3)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME4)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME5)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME6)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME7)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME8)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME9)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME10)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME11)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME12)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME13)
-UNSUPPORTED(LOCALE_SPOSITIVESIGN)
-UNSUPPORTED(LOCALE_SNEGATIVESIGN)
-UNSUPPORTED(LOCALE_IPOSSIGNPOSN)
-UNSUPPORTED(LOCALE_INEGSIGNPOSN)
-UNSUPPORTED(LOCALE_IPOSSYMPRECEDES)
-UNSUPPORTED(LOCALE_IPOSSEPBYSPACE)
-UNSUPPORTED(LOCALE_INEGSYMPRECEDES)
-UNSUPPORTED(LOCALE_INEGSEPBYSPACE)
+#define LOCVAL(type,value) case type:retString=value;break;
/* Now, the language specific definitions. They don't have to be
complete */
+ found=1;
switch(Options.language)
{
case LANG_De:
+ switch (LCType) {
/* This definitions apply to Germany only. Users in Austria
or Switzerland might want to modify them */
LOCVAL(LOCALE_ILANGUAGE,"9")
@@ -339,9 +351,12 @@
LOCVAL(LOCALE_INEGSYMPRECEDES)
LOCVAL(LOCALE_INEGSEPBYSPACE)
*/
+ default: found=0;break;
+ }
break; /* LANG(De) */
case LANG_Da:
+ switch (LCType) {
/* LOCVAL(LOCALE_ILANGUAGE,"9") */
LOCVAL(LOCALE_SLANGUAGE,"Dansk")
LOCVAL(LOCALE_SENGLANGUAGE,"Danish")
@@ -441,9 +456,12 @@
/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */
/* LOCVAL(LOCALE_INEGSYMPRECEDES) */
/* LOCVAL(LOCALE_INEGSEPBYSPACE) */
+ default: found=0;break;
+ }
break; /* LANG(Da) */
case LANG_En:
+ switch (LCType) {
/* This definitions apply to Germany only. Users in Austria
or Switzerland might want to modify them */
LOCVAL(LOCALE_ILANGUAGE,"9")
@@ -566,9 +584,12 @@
LOCVAL(LOCALE_INEGSYMPRECEDES)
LOCVAL(LOCALE_INEGSEPBYSPACE)
*/
+ default: found=0;break;
+ }
break; /* LANG(En) */
case LANG_Eo:
+ switch (LCType) {
/* LOCVAL(LOCALE_ILANGUAGE,"9") ISO numerical ID for language TODO */
LOCVAL(LOCALE_SLANGUAGE,"Esperanto")
LOCVAL(LOCALE_SENGLANGUAGE,"Esperanto")
@@ -668,9 +689,12 @@
/* LOCVAL(LOCALE_IPOSSEPBYSPACE) */
/* LOCVAL(LOCALE_INEGSYMPRECEDES) */
/* LOCVAL(LOCALE_INEGSEPBYSPACE) */
+ default: found=0;break;
+ }
break; /* LANG(Eo) */
case LANG_Fi:
+ switch (LCType) {
LOCVAL(LOCALE_ILANGUAGE,"11")
LOCVAL(LOCALE_SLANGUAGE,"Suomi")
LOCVAL(LOCALE_SENGLANGUAGE,"Finnish")
@@ -791,9 +815,12 @@
LOCVAL(LOCALE_INEGSYMPRECEDES)
LOCVAL(LOCALE_INEGSEPBYSPACE)
*/
+ default: found=0;break;
+ }
break; /* LANG(Fi) */
case LANG_It:
+ switch (LCType) {
LOCVAL(LOCALE_ILANGUAGE,"9")
LOCVAL(LOCALE_SLANGUAGE,"Italiano")
LOCVAL(LOCALE_SENGLANGUAGE,"Italian")
@@ -914,9 +941,12 @@
LOCVAL(LOCALE_INEGSYMPRECEDES)
LOCVAL(LOCALE_INEGSEPBYSPACE)
*/
+ default: found=0;break;
+ }
break; /* LANG(It) */
case 0x0409:
+ switch (LCType) {
LOCVAL(LOCALE_ILANGUAGE, "0409")
LOCVAL(LOCALE_SLANGUAGE, "English (United States)")
LOCVAL(LOCALE_SENGLANGUAGE, "English")
@@ -1016,9 +1046,12 @@
LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+ default: found=0;break;
+ }
break; /* LANG(0x0409) (U.S. English) */
case 0x0809:
+ switch (LCType) {
LOCVAL(LOCALE_ILANGUAGE, "0809")
LOCVAL(LOCALE_SLANGUAGE, "English (United Kingdom)")
LOCVAL(LOCALE_SENGLANGUAGE, "English")
@@ -1118,25 +1151,24 @@
LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+ default: found=0;break;
+ }
break; /* LANG(0x0809) (U.K. English) */
/*Insert other languages here*/
default:
+ found=0;
break;
} /* switch */
- if(!retLen)
- {
- if(!retString)fprintf(stderr,"Unkown LC type %lX\n",LCType);
- else fprintf(stderr,"'%s' not supported for your language.\n",
+ if(!found) {
+ fprintf(stderr,"'%s' not supported for your language.\n",
retString);
return 0;
}
-
- if(retLen>len)retLen=len;
lstrcpyn32A(buf,retString,len);
- return retLen;
+ return strlen(retString)+1;
}
/***********************************************************************
@@ -1230,7 +1262,57 @@
return TRUE;
}
-BOOL IsValidLocale(DWORD lcid,DWORD flags) {
- fprintf(stdnimp,"IsValidLocale(%ld,%ld)\n",lcid,flags);
+/***********************************************************************
+ * IsValidLocale (KERNEL32.361)
+ */
+BOOL32 IsValidLocale(DWORD lcid,DWORD flags) {
+ int i;
+
+ i=0;
+ while (locale_name2id[i].name!=NULL)
+ if (locale_name2id[i].id == lcid)
+ return TRUE;
+ return FALSE;
+}
+
+/***********************************************************************
+ * EnumSystemLocales32W (KERNEL32.93)
+ */
+BOOL32
+EnumSystemLocales32W(LOCALE_ENUMPROC32W lpfnLocaleEnum,DWORD flags) {
+ WCHAR *cp;
+ int i;
+ BOOL32 ret;
+
+ dprintf_win32(stddeb,"EnumSystemLocales32W(%p,%08lx)\n",
+ lpfnLocaleEnum,flags
+ );
+ i=0;
+ while (locale_name2id[i].name!=NULL) {
+ cp=(LPWSTR)STRING32_DupAnsiToUni(locale_name2id[i].name);
+ ret=lpfnLocaleEnum(cp);
+ free(cp);
+ if (!ret) break;
+ i++;
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ * EnumSystemLocales32A (KERNEL32.92)
+ */
+BOOL32
+EnumSystemLocales32A(LOCALE_ENUMPROC32A lpfnLocaleEnum,DWORD flags) {
+ int i;
+
+ dprintf_win32(stddeb,"EnumSystemLocales32A(%p,%08lx)\n",
+ lpfnLocaleEnum,flags
+ );
+ i=0;
+ while (locale_name2id[i].name!=NULL) {
+ if (!lpfnLocaleEnum(locale_name2id[i].name))
+ break;
+ i++;
+ }
return TRUE;
}
diff --git a/misc/registry.c b/misc/registry.c
index cdd6751..90c001a 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -450,7 +450,7 @@
return _savesubkey(F,lpkey->nextsub,0,all);
}
-static void
+static BOOL32
_savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
FILE *F;
@@ -459,15 +459,16 @@
fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
fn,strerror(errno)
);
- return;
+ return FALSE;
}
if (!_savesubreg(F,lpkey,all)) {
fclose(F);
unlink(fn);
fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
- return;
+ return FALSE;
}
fclose(F);
+ return TRUE;
}
void
@@ -500,19 +501,22 @@
if (lstrcmpi32A(buf,"yes"))
all=1;
pwd=getpwuid(getuid());
- if (pwd!=NULL && pwd->pw_dir!=NULL) {
- fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
+ if (pwd!=NULL && pwd->pw_dir!=NULL)
+ {
+ char *tmp = tmpnam(NULL);
+ fn=(char*)xmalloc( strlen(pwd->pw_dir) + strlen(WINE_PREFIX) +
+ strlen(SAVE_CURRENT_USER) + 2 );
strcpy(fn,pwd->pw_dir);
strcat(fn,WINE_PREFIX);
/* create the directory. don't care about errorcodes. */
mkdir(fn,0755); /* drwxr-xr-x */
strcat(fn,"/"SAVE_CURRENT_USER);
- _savereg(key_current_user,fn,all);
+ if (_savereg(key_current_user,tmp,all)) rename(tmp,fn);
free(fn);
fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
strcpy(fn,pwd->pw_dir);
strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
- _savereg(key_local_machine,fn,all);
+ if (_savereg(key_local_machine,tmp,all)) rename(tmp,fn);
free(fn);
} else
fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
@@ -1315,6 +1319,216 @@
free(keys);
}
+/* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
+
+/*
+ reghack - windows 3.11 registry data format demo program.
+
+ The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
+ a combined hash table and tree description, and finally a text table.
+
+ The header is obvious from the struct header. The taboff1 and taboff2
+ fields are always 0x20, and their usage is unknown.
+
+ The 8-byte entry table has various entry types.
+
+ tabent[0] is a root index. The second word has the index of the root of
+ the directory.
+ tabent[1..hashsize] is a hash table. The first word in the hash entry is
+ the index of the key/value that has that hash. Data with the same
+ hash value are on a circular list. The other three words in the
+ hash entry are always zero.
+ tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
+ entry: dirent and keyent/valent. They are identified by context.
+ tabent[freeidx] is the first free entry. The first word in a free entry
+ is the index of the next free entry. The last has 0 as a link.
+ The other three words in the free list are probably irrelevant.
+
+ Entries in text table are preceeded by a word at offset-2. This word
+ has the value (2*index)+1, where index is the referring keyent/valent
+ entry in the table. I have no suggestion for the 2* and the +1.
+ Following the word, there are N bytes of data, as per the keyent/valent
+ entry length. The offset of the keyent/valent entry is from the start
+ of the text table to the first data byte.
+
+ This information is not available from Microsoft. The data format is
+ deduced from the reg.dat file by me. Mistakes may
+ have been made. I claim no rights and give no guarantees for this program.
+
+ Tor Sjøwall, tor@sn.no
+*/
+
+/* reg.dat header format */
+struct _w31_header {
+ char cookie[8]; /* 'SHCC3.10' */
+ unsigned long taboff1; /* offset of hash table (??) = 0x20 */
+ unsigned long taboff2; /* offset of index table (??) = 0x20 */
+ unsigned long tabcnt; /* number of entries in index table */
+ unsigned long textoff; /* offset of text part */
+ unsigned long textsize; /* byte size of text part */
+ unsigned short hashsize; /* hash size */
+ unsigned short freeidx; /* free index */
+};
+
+/* generic format of table entries */
+struct _w31_tabent {
+ unsigned short w0, w1, w2, w3;
+};
+
+/* directory tabent: */
+struct _w31_dirent {
+ unsigned short sibling_idx; /* table index of sibling dirent */
+ unsigned short child_idx; /* table index of child dirent */
+ unsigned short key_idx; /* table index of key keyent */
+ unsigned short value_idx; /* table index of value valent */
+};
+
+/* key tabent: */
+struct _w31_keyent {
+ unsigned short hash_idx; /* hash chain index for string */
+ unsigned short refcnt; /* reference count */
+ unsigned short length; /* length of string */
+ unsigned short string_off; /* offset of string in text table */
+};
+
+/* value tabent: */
+struct _w31_valent {
+ unsigned short hash_idx; /* hash chain index for string */
+ unsigned short refcnt; /* reference count */
+ unsigned short length; /* length of string */
+ unsigned short string_off; /* offset of string in text table */
+};
+
+/* recursive helper function to display a directory tree */
+void
+__w31_dumptree( unsigned short idx,
+ unsigned char *txt,
+ struct _w31_tabent *tab,
+ struct _w31_header *head,
+ LPKEYSTRUCT lpkey,
+ time_t lastmodified,
+ int level
+) {
+ struct _w31_dirent *dir;
+ struct _w31_keyent *key;
+ struct _w31_valent *val;
+ LPKEYSTRUCT xlpkey;
+ LPWSTR name,value;
+ static char tail[400];
+
+ while (idx!=0) {
+ dir=(struct _w31_dirent*)&tab[idx];
+
+ if (dir->key_idx) {
+ key = (struct _w31_keyent*)&tab[dir->key_idx];
+
+ memcpy(tail,&txt[key->string_off],key->length);
+ tail[key->length]='\0';
+ /* all toplevel entries AND the entries in the
+ * toplevel subdirectory belong to \SOFTWARE\Classes
+ */
+ if (!level && !lstrcmp32A(tail,".classes")) {
+ __w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
+ idx=dir->sibling_idx;
+ continue;
+ }
+ name=STRING32_DupAnsiToUni(tail);
+
+ xlpkey=_find_or_add_key(lpkey,name);
+
+ /* only add if leaf node or valued node */
+ if (dir->value_idx!=0||dir->child_idx==0) {
+ if (dir->value_idx) {
+ val=(struct _w31_valent*)&tab[dir->value_idx];
+ memcpy(tail,&txt[val->string_off],val->length);
+ tail[val->length]='\0';
+ value=STRING32_DupAnsiToUni(tail);
+ _find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlen32W(value)*2+2,lastmodified);
+ }
+ }
+ } else {
+ dprintf_reg(stddeb,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx);
+ }
+ __w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
+ idx=dir->sibling_idx;
+ }
+}
+
+void
+_w31_loadreg() {
+ HFILE hf;
+ struct _w31_header head;
+ struct _w31_tabent *tab;
+ unsigned char *txt;
+ int len;
+ OFSTRUCT ofs;
+ BY_HANDLE_FILE_INFORMATION hfinfo;
+ time_t lastmodified;
+ HKEY hkey;
+ LPKEYSTRUCT lpkey;
+
+ hf = OpenFile("reg.dat",&ofs,OF_READ);
+ if (hf==HFILE_ERROR)
+ return;
+
+ /* read & dump header */
+ if (sizeof(head)!=_lread32(hf,&head,sizeof(head))) {
+ dprintf_reg(stddeb,"_w31_loadreg:reg.dat is too short.\n");
+ _lclose(hf);
+ return;
+ }
+ if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
+ dprintf_reg(stddeb,"_w31_loadreg:reg.dat has bad signature.\n");
+ _lclose(hf);
+ return;
+ }
+
+ len = head.tabcnt * sizeof(struct _w31_tabent);
+ /* read and dump index table */
+ tab = xmalloc(len);
+ if (len!=_lread32(hf,tab,len)) {
+ dprintf_reg(stderr,"_w31_loadreg:couldn't read %d bytes.\n",len);
+ free(tab);
+ _lclose(hf);
+ return;
+ }
+
+ /* read text */
+ txt = xmalloc(head.textsize);
+ if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
+ dprintf_reg(stderr,"_w31_loadreg:couldn't seek to textblock.\n");
+ free(tab);
+ free(txt);
+ _lclose(hf);
+ return;
+ }
+ if (head.textsize!=_lread32(hf,txt,head.textsize)) {
+ dprintf_reg(stderr,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len,head.textsize);
+ free(tab);
+ free(txt);
+ _lclose(hf);
+ return;
+ }
+
+ if (!GetFileInformationByHandle(hf,&hfinfo)) {
+ dprintf_reg(stderr,"_w31_loadreg:GetFileInformationByHandle failed?.\n");
+ free(tab);
+ free(txt);
+ _lclose(hf);
+ return;
+ }
+ lastmodified = DOSFS_FileTimeToUnixTime(&(hfinfo.ftLastWriteTime));
+
+ if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS)
+ return;
+ lpkey = lookup_hkey(hkey);
+ __w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
+ free(tab);
+ free(txt);
+ _lclose(hf);
+ return;
+}
+
void
SHELL_LoadRegistry() {
char *fn;
@@ -1326,13 +1540,13 @@
if (key_classes_root==NULL)
SHELL_Init();
+ /* Load windows 3.1 entries */
+ _w31_loadreg();
/* Load windows 95 entries */
_w95_loadreg("C:\\system.1st", key_local_machine);
_w95_loadreg("system.dat", key_local_machine);
_w95_loadreg("user.dat", key_users);
- /* FIXME: win3.1 reg.dat loader still missing */
-
/* the global user default is loaded under HKEY_USERS\\.Default */
RegCreateKey16(HKEY_USERS,".Default",&hkey);
lpkey = lookup_hkey(hkey);
diff --git a/misc/shell.c b/misc/shell.c
index 3a96897..2f9cc8b 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -195,29 +195,34 @@
/* extensions; however, it'd make sense to check the programs */
/* section first, so that's what happens here. */
- /* See if it's a program */
- GetProfileString("windows", "programs", "exe pif bat com",
- buffer, sizeof(buffer)); /* FIXME check return code! */
+ /* See if it's a program - if GetProfileString fails, we skip this
+ * section. Actually, if GetProfileString fails, we've probably
+ * got a lot more to worry about than running a program... */
+ if ( GetProfileString32A("windows", "programs", "exe pif bat com",
+ buffer, sizeof(buffer)) > 0 )
+ {
+ for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
- for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
+ tok = strtok(buffer, " \t"); /* ? */
+ while( tok!= NULL)
+ {
+ if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
+ {
+ strcpy(lpResult, xlpFile);
+ /* Need to perhaps check that the file has a path
+ * attached */
+ dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
+ lpResult);
+ return 33;
- tok = strtok(buffer, " \t"); /* ? */
- while( tok!= NULL)
- {
- if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
- {
- strcpy(lpResult, xlpFile); /* Need to perhaps check that */
- /* the file has a path attached */
- dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
- lpResult);
- return 33; /* Greater than 32 to indicate success FIXME */
- /* According to the docs, I should be returning */
- /* a handle for the executable. Does this mean */
- /* I'm supposed to open the executable file or */
- /* something? More RTFM, I guess... */
- }
- tok=strtok(NULL, " \t");
- }
+ /* Greater than 32 to indicate success FIXME According to the
+ * docs, I should be returning a handle for the
+ * executable. Does this mean I'm supposed to open the
+ * executable file or something? More RTFM, I guess... */
+ }
+ tok=strtok(NULL, " \t");
+ }
+ }
/* Check registry */
if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
@@ -249,32 +254,34 @@
strcat( lpResult, &tok[2] );
}
}
- retval=33;
+ retval=33; /* FIXME see above */
}
}
else /* Check win.ini */
{
/* Toss the leading dot */
extension++;
- GetProfileString( "extensions", extension, "", command,
- sizeof(command));
- if (strlen(command)!=0)
- {
- strcpy( lpResult, command );
- tok=strstr( lpResult, "^" ); /* should be ^.extension? */
- if (tok != NULL)
- {
- tok[0]='\0';
- strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
- tok=strstr( command, "^" ); /* see above */
- if ((tok != NULL) && (strlen(tok)>5))
- {
- strcat( lpResult, &tok[5]);
- }
- }
- retval=33;
+ if ( GetProfileString32A( "extensions", extension, "", command,
+ sizeof(command)) > 0)
+ {
+ if (strlen(command)!=0)
+ {
+ strcpy( lpResult, command );
+ tok=strstr( lpResult, "^" ); /* should be ^.extension? */
+ if (tok != NULL)
+ {
+ tok[0]='\0';
+ strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
+ tok=strstr( command, "^" ); /* see above */
+ if ((tok != NULL) && (strlen(tok)>5))
+ {
+ strcat( lpResult, &tok[5]);
+ }
+ }
+ retval=33; /* FIXME - see above */
+ }
+ }
}
- }
dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
return retval;
@@ -804,7 +811,7 @@
*/
int RegisterShellHook(void *ptr)
{
- fprintf(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
+ fprintf(stdnimp, "RegisterShellHook( %p ) : Empty Stub !!!\n", ptr);
return 0;
}
diff --git a/misc/spy.c b/misc/spy.c
index 57ce9d9..1b00d39 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -296,7 +296,8 @@
"LB_SETITEMHEIGHT32", /* 0x01a0 */
"LB_GETITEMHEIGHT32", /* 0x01a1 */
"LB_FINDSTRINGEXACT32", /* 0x01a2 */
- NULL, NULL,
+ "LB_CARETON32", /* 0x01a3 */
+ "LB_CARETOFF32", /* 0x01a4 */
"LB_SETLOCALE32", /* 0x01a5 */
"LB_GETLOCALE32", /* 0x01a6 */
"LB_SETCOUNT32", /* 0x01a7 */
diff --git a/misc/user.c b/misc/user.c
index 3516a78..68a91a5 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -101,7 +101,7 @@
int queueSize;
/* Create task message queue */
- queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
+ queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
if (!SetMessageQueue( queueSize )) return 0;
return 1;
@@ -112,8 +112,7 @@
*/
void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue )
{
- /* FIXME: flush send messages (which are not implemented yet),
- * empty clipboard if needed, maybe destroy menus (Windows
+ /* FIXME: empty clipboard if needed, maybe destroy menus (Windows
* only complains about them but does nothing);
*/
@@ -126,18 +125,13 @@
/* Patch resident popup menu window */
MENU_SwitchTPWndTo(0);
- /* Nuke timers */
-
TIMER_RemoveQueueTimers( hQueue );
+ QUEUE_FlushMessages( hQueue );
HOOK_FreeQueueHooks( hQueue );
QUEUE_SetDoomedQueue( hQueue );
-
- /* Nuke orphaned windows */
-
- WIN_DestroyQueueWindows( desktop->child, hQueue );
-
+ WIN_ResetQueueWindows( desktop->child, hQueue, (HQUEUE16)0);
QUEUE_SetDoomedQueue( 0 );
/* Free the message queue */
diff --git a/misc/winsock.c b/misc/winsock.c
new file mode 100644
index 0000000..cb22484
--- /dev/null
+++ b/misc/winsock.c
@@ -0,0 +1,1713 @@
+/*
+ * based on Windows Sockets 1.1 specs
+ * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
+ *
+ * (C) 1993,1994,1996 John Brezak, Erik Bos, Alex Korobka.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/ioctl.h>
+#if defined(__svr4__)
+#include <sys/filio.h>
+#include <sys/ioccom.h>
+#endif
+#include <sys/msg.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "windows.h"
+#include "winnt.h"
+#include "heap.h"
+#include "ldt.h"
+#include "winsock.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define dump_sockaddr(a) \
+ fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
+ ((struct sockaddr_in *)a)->sin_family, \
+ inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
+ ntohs(((struct sockaddr_in *)a)->sin_port))
+
+extern void SIGNAL_MaskAsyncEvents( BOOL32 );
+
+#pragma pack(4)
+
+/* ----------------------------------- internal data */
+
+extern int h_errno;
+extern void __sigio(int);
+
+ws_async_ctl async_ctl;
+int async_qid = -1;
+
+static HANDLE32 _WSHeap = 0;
+static unsigned char* _ws_stub = NULL;
+static LPWSINFO _wsi_list = NULL;
+
+#define WS_ALLOC(size) \
+ HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
+#define WS_FREE(ptr) \
+ HeapFree(_WSHeap, 0, (ptr) )
+
+#define WS_PTR2HANDLE(ptr) \
+ ((short)((int)(ptr) - (int)_ws_stub))
+#define WS_HANDLE2PTR(handle) \
+ ((unsigned)((int)_ws_stub + (int)handle))
+
+#define WSI_CHECK_RANGE(pwsi, pws) \
+ ( ((unsigned)(pws) > (unsigned)(pwsi)) && \
+ ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
+
+static INT16 _ws_sock_ops[] =
+ { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
+ WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
+ WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 };
+static int _px_sock_ops[] =
+ { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
+ SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
+ SO_LINGER };
+
+static INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent);
+static int notify_client(ws_socket* pws, unsigned flag);
+
+static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
+static int _check_buffer(LPWSINFO pwsi, int size);
+
+static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
+static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
+static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
+
+static int delete_async_op(ws_socket*);
+
+static void convert_sockopt(INT16 *level, INT16 *optname)
+{
+ int i;
+ switch (*level)
+ {
+ case WS_SOL_SOCKET:
+ *level = SOL_SOCKET;
+ for(i=0; _ws_sock_ops[i]; i++)
+ if( _ws_sock_ops[i] == *optname ) break;
+ if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i];
+ else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
+ break;
+ case WS_IPPROTO_TCP:
+ *optname = IPPROTO_TCP;
+ }
+}
+
+static void _ws_global_init()
+{
+ if( !_ws_stub )
+ {
+ _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
+ if( !(_ws_stub = WS_ALLOC(0x10)) )
+ fprintf(stderr,"Fatal: failed to create WinSock heap\n");
+ }
+ if( async_qid == -1 )
+ if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 )
+ fprintf(stderr,"Fatal: failed to create WinSock resource\n");
+}
+
+/* ----------------------------------- Per-thread info */
+
+static void wsi_link(LPWSINFO pwsi)
+{ if( _wsi_list ) _wsi_list->prev = pwsi;
+ pwsi->next = _wsi_list; _wsi_list = pwsi;
+}
+
+static void wsi_unlink(LPWSINFO pwsi)
+{
+ if( pwsi == _wsi_list ) _wsi_list = pwsi->next;
+ else
+ { pwsi->prev->next = pwsi->next;
+ if( pwsi->next ) pwsi->next->prev = pwsi->prev; }
+}
+
+static LPWSINFO wsi_find(HTASK16 hTask)
+{ LPWSINFO pwsi = _wsi_list;
+ while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
+ return pwsi;
+}
+
+static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
+{
+ if( pwsi->last_free >= 0 )
+ {
+ int i = pwsi->last_free;
+
+ pwsi->last_free = pwsi->sock[i].flags;
+ pwsi->sock[i].fd = fd;
+ pwsi->sock[i].flags = 0;
+ return &pwsi->sock[i];
+ }
+ return NULL;
+}
+
+static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd)
+{
+ FD_ZERO(fds);
+ if(ws)
+ {
+ int i;
+ ws_socket* pws;
+ for(i=0;i<(ws->fd_count);i++)
+ {
+ pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+ if( _check_ws(pwsi, pws) )
+ {
+ if( pws->fd > *highfd ) *highfd = pws->fd;
+ FD_SET(pws->fd, fds);
+ }
+ }
+ }
+}
+
+static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws)
+{
+ if( ws )
+ {
+ int i, j, count = ws->fd_count;
+ ws_socket* pws;
+ for( i = 0, j = 0; i < count; i++ )
+ {
+ pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+ if( _check_ws(pwsi, pws) )
+ if( FD_ISSET(pws->fd, fds) )
+ {
+ ws->fd_array[j++] = ws->fd_array[i];
+ continue;
+ }
+ ws->fd_count--;
+ }
+ }
+}
+
+/* ----------------------------------- API -----
+ *
+ * Init / cleanup / error checking.
+ */
+
+INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
+{
+ WSADATA WINSOCK_data = { 0x0101, 0x0101,
+ "WINE Sockets 1.1",
+ #ifdef linux
+ "Linux/i386",
+ #elif defined(__NetBSD__)
+ "NetBSD/i386",
+ #elif defined(sunos)
+ "SunOS",
+ #elif defined(__FreeBSD__)
+ "FreeBSD",
+ #else
+ "Unknown",
+ #endif
+ WS_MAX_SOCKETS_PER_THREAD,
+ WS_MAX_UDP_DATAGRAM, NULL };
+ HTASK16 tid = GetCurrentTask();
+ LPWSINFO pwsi;
+
+ dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
+
+ if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
+ HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
+
+ if (!lpWSAData) return WSAEINVAL;
+
+ _ws_global_init();
+ if( _WSHeap == 0 ) return WSASYSNOTREADY;
+
+ pwsi = wsi_find(GetCurrentTask());
+ if( pwsi == NULL )
+ {
+ if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
+ {
+ int i = 0;
+ pwsi->tid = tid;
+ for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
+ {
+ pwsi->sock[i].fd = -1;
+ pwsi->sock[i].flags = i + 1;
+ }
+ pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
+ }
+ else return WSASYSNOTREADY;
+ wsi_link(pwsi);
+ } else pwsi->num_startup++;
+
+ /* return winsock information */
+ memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
+
+ dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
+ return(0);
+}
+
+INT16 WSACleanup(void)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ /* FIXME: do global cleanup if no current task */
+
+ dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
+ if( pwsi )
+ {
+ int i, j, n;
+
+ if( pwsi->num_startup-- ) return 0;
+
+ SIGNAL_MaskAsyncEvents( TRUE );
+ WINSOCK_cancel_async_op(GetCurrentTask());
+ SIGNAL_MaskAsyncEvents( FALSE );
+
+ wsi_unlink(pwsi);
+ if( _wsi_list == NULL && async_qid != -1 )
+ if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
+ {
+ fprintf(stderr,"failed to delete WS message queue.\n");
+ } else async_qid = -1;
+
+ if( pwsi->flags & WSI_BLOCKINGCALL )
+ dprintf_winsock(stddeb,"\tinside blocking call!\n");
+ if( pwsi->num_async_rq )
+ dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
+
+ for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
+ if( pwsi->sock[i].fd != -1 )
+ {
+ n += delete_async_op(&pwsi->sock[i]);
+ close(pwsi->sock[i].fd); j++;
+ }
+ if( j )
+ dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
+
+ if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
+ WS_FREE(pwsi);
+ return 0;
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WSAGetLastError(void)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+ INT16 ret;
+
+ dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
+
+ ret = (pwsi) ? pwsi->errno : WSANOTINITIALISED;
+
+ dprintf_winsock(stddeb, " = %i\n", (int)ret);
+ return ret;
+}
+
+void WSASetLastError(INT16 iError)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
+
+ if( pwsi ) pwsi->errno = iError;
+}
+
+int _check_ws(LPWSINFO pwsi, ws_socket* pws)
+{
+ if( pwsi )
+ if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->errno = WSAEINPROGRESS;
+ else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
+ else pwsi->errno = WSAENOTSOCK;
+ return 0;
+}
+
+int _check_buffer(LPWSINFO pwsi, int size)
+{
+ if( pwsi->buffer && pwsi->buflen >= size ) return 1;
+ else SEGPTR_FREE(pwsi->buffer);
+ pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
+ return (pwsi->buffer != NULL);
+}
+
+/* ----- socket operations */
+
+SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n",
+ (unsigned)pwsi, (UINT16)s);
+ if( _check_ws(pwsi, pws) )
+ {
+ int sock, fd_flags, addrlen32 = *addrlen16;
+
+ /* this is how block info is supposed to be used -
+ * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit.
+ */
+
+ fd_flags = fcntl(pws->fd, F_GETFL, 0);
+ if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL;
+
+ if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 )
+ {
+ ws_socket* pnew = wsi_alloc_socket(pwsi, sock);
+ notify_client(pws, WS_FD_ACCEPT);
+ if( pnew )
+ {
+ if( pws->p_aop )
+ init_async_select(pnew, pws->p_aop->hWnd,
+ pws->p_aop->uMsg,
+ pws->p_aop->flags & ~WS_FD_ACCEPT );
+
+ pwsi->flags &= ~WSI_BLOCKINGCALL;
+ return (SOCKET16)WS_PTR2HANDLE(pnew);
+ }
+ else pwsi->errno = WSAENOBUFS;
+ }
+ else pwsi->errno = wsaErrno();
+
+ pwsi->flags &= ~WSI_BLOCKINGCALL;
+ }
+ return INVALID_SOCKET;
+}
+
+INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n",
+ (unsigned)pwsi, s, (int) name, namelen);
+#if 0
+ dump_sockaddr(name);
+#endif
+
+ if ( _check_ws(pwsi, pws) )
+ if (namelen >= sizeof(*name))
+ if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
+ if ( bind(pws->fd, name, namelen) < 0 )
+ {
+ int loc_errno = errno;
+ dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
+ errno = loc_errno;
+ switch(errno)
+ {
+ case EBADF: pwsi->errno = WSAENOTSOCK; break;
+ case EADDRNOTAVAIL: pwsi->errno = WSAEINVAL; break;
+ default: pwsi->errno = wsaErrno();
+ }
+ }
+ else return 0;
+ else pwsi->errno = WSAEAFNOSUPPORT;
+ else pwsi->errno = WSAEFAULT;
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_closesocket(SOCKET16 s)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
+
+ if( _check_ws(pwsi, pws) )
+ {
+ int fd = pws->fd;
+
+ delete_async_op(pws);
+ pws->p_aop = NULL; pws->fd = -1;
+ pws->flags = (unsigned)pwsi->last_free;
+ pwsi->last_free = pws - &pwsi->sock[0];
+ if (close(fd) < 0) pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+ else return 0;
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n",
+ (unsigned)pwsi, s, (int) name, namelen);
+#if 0
+ dump_sockaddr(name);
+#endif
+
+ if( _check_ws(pwsi, pws) )
+ {
+ if (connect(pws->fd, name, namelen) == 0)
+ {
+ if( pws->p_aop )
+ /* we need to notify handler process if
+ * connect() succeeded NOT in response to winsock message
+ */
+ notify_client(pws, WS_FD_CONNECTED);
+
+ pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT);
+ return 0;
+ }
+ pwsi->errno = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n",
+ (unsigned)pwsi, s, (int) name, *namelen);
+ if( _check_ws(pwsi, pws) )
+ {
+ int namelen32 = *namelen;
+ if (getpeername(pws->fd, name, &namelen32) == 0)
+ {
+#if 0
+ dump_sockaddr(name);
+#endif
+ *namelen = (INT16)namelen32;
+ return 0;
+ }
+ pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n",
+ (unsigned)pwsi, s, (int) name, (int) *namelen);
+ if( _check_ws(pwsi, pws) )
+ {
+ int namelen32 = *namelen;
+ if (getsockname(pws->fd, name, &namelen32) == 0)
+ {
+ *namelen = (INT16)namelen32;
+ return 0;
+ }
+ pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level,
+ INT16 optname, char *optval, INT16 *optlen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WSA_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
+ (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
+
+ if( _check_ws(pwsi, pws) )
+ {
+ int optlen32 = *optlen;
+
+ convert_sockopt(&level, &optname);
+ if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 )
+ { *optlen = (INT16)optlen32; return 0; }
+ pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+u_long WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
+u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
+u_long WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
+u_long WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
+u_short WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
+
+SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+ char* s = inet_ntoa(in);
+
+ if( pwsi )
+ {
+ if( s == NULL ) { pwsi->errno = wsaErrno(); return NULL; }
+ if( _check_buffer( pwsi, 32 ) )
+ {
+ strncpy(pwsi->buffer, s, 32 );
+ return SEGPTR_GET(pwsi->buffer);
+ }
+ pwsi->errno = WSAENOBUFS;
+ }
+ return (SEGPTR)NULL;
+}
+
+INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n",
+ (unsigned)pwsi, s, cmd, (unsigned) argp);
+ if( _check_ws(pwsi, pws) )
+ {
+ long newcmd = cmd;
+
+ switch( cmd )
+ {
+ case WS_FIONREAD: newcmd=FIONREAD; break;
+ case WS_FIONBIO: newcmd=FIONBIO;
+ if( pws->p_aop && *argp == 0 )
+ {
+ pwsi->errno = WSAEINVAL;
+ return SOCKET_ERROR;
+ }
+ break;
+ case WS_SIOCATMARK: newcmd=SIOCATMARK; break;
+ case WS_IOW('f',125,u_long):
+ fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
+ pwsi->errno = WSAEINVAL; return SOCKET_ERROR;
+ default: fprintf(stderr,"Warning: Unknown WS_IOCTL cmd (%08x)\n", cmd);
+ }
+ if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
+ pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n",
+ (unsigned)pwsi, s, backlog);
+ if( _check_ws(pwsi, pws) )
+ {
+ if( !pws->p_aop )
+ {
+ int fd_flags = fcntl(pws->fd, F_GETFL, 0);
+ if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
+ }
+ else notify_client(pws, WS_FD_ACCEPT);
+
+ if (listen(pws->fd, backlog) == 0) return 0;
+ pwsi->errno = wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
+ (unsigned)pwsi, s, (unsigned)buf, len, flags);
+ if( _check_ws(pwsi, pws) )
+ {
+ int length;
+ if ((length = recv(pws->fd, buf, len, flags)) >= 0)
+ {
+ dprintf_winsock(stddeb, " -> %i bytes\n", length);
+ notify_client(pws, WS_FD_READ);
+ return (INT16)length;
+ }
+ pwsi->errno = wsaErrno();
+ }
+ dprintf_winsock(stddeb, " -> ERROR\n");
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags,
+ struct sockaddr *from, INT16 *fromlen16)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n",
+ (unsigned)pwsi, s, (unsigned)buf, len, flags);
+ if( _check_ws(pwsi, pws) )
+ {
+ int length, fromlen32 = *fromlen16;
+ if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0)
+ {
+ *fromlen16 = fromlen32;
+ notify_client(pws, WS_FD_READ);
+ return (INT16)length;
+ }
+ pwsi->errno = wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds,
+ ws_fd_set *ws_writefds,
+ ws_fd_set *ws_exceptfds, struct timeval *timeout)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n",
+ (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
+
+ if( pwsi )
+ {
+ int highfd = 0;
+ fd_set readfds, writefds, exceptfds;
+
+ fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd);
+ fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd);
+ fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd);
+
+ if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 )
+ {
+ if( highfd )
+ {
+ fd_set_update(pwsi, &readfds, ws_readfds);
+ fd_set_update(pwsi, &writefds, ws_writefds);
+ fd_set_update(pwsi, &exceptfds, ws_exceptfds);
+ }
+ return highfd;
+ }
+ pwsi->errno = wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
+ (unsigned)pwsi, s, (unsigned) buf, len, flags);
+ if( _check_ws(pwsi, pws) )
+ {
+ int length;
+ if ((length = send(pws->fd, buf, len, flags)) < 0 )
+ {
+ length = SOCKET_ERROR;
+ pwsi->errno = wsaErrno();
+ }
+ notify_client(pws, WS_FD_WRITE);
+ return (INT16)length;
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
+ struct sockaddr *to, INT16 tolen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
+ (unsigned)pwsi, s, (unsigned) buf, len, flags);
+ if( _check_ws(pwsi, pws) )
+ {
+ int length;
+
+ if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
+ {
+ length = SOCKET_ERROR;
+ pwsi->errno = wsaErrno();
+ }
+ notify_client(pws, WS_FD_WRITE);
+ return (INT16)length;
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname,
+ char *optval, INT16 optlen)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n",
+ (unsigned)pwsi, s, level, optname, (int) optval, optlen);
+ if( _check_ws(pwsi, pws) )
+ {
+ int linger32[2];
+ convert_sockopt(&level, &optname);
+ if( optname == SO_LINGER )
+ {
+ INT16* ptr = (INT16*)optval;
+ linger32[0] = ptr[0];
+ linger32[1] = ptr[1];
+ optval = (char*)&linger32;
+ optlen = sizeof(linger32);
+ }
+ if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
+ pwsi->errno = wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
+ (unsigned)pwsi, s, how );
+ if( _check_ws(pwsi, pws) )
+ {
+ pws->flags = WS_FD_INACTIVE;
+ delete_async_op(pws);
+
+ if (shutdown(pws->fd, how) == 0) return 0;
+ pwsi->errno = wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n",
+ (unsigned)pwsi, af, type, protocol);
+
+ if( pwsi )
+ {
+ int sock;
+
+ /* check the socket family */
+ switch(af)
+ {
+ case AF_INET:
+ case AF_UNSPEC: break;
+ default: pwsi->errno = WSAEAFNOSUPPORT; return INVALID_SOCKET;
+ }
+
+ /* check the socket type */
+ switch(type)
+ {
+ case SOCK_STREAM:
+ case SOCK_DGRAM:
+ case SOCK_RAW: break;
+ default: pwsi->errno = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
+ }
+
+ /* check the protocol type */
+ if ( protocol < 0 ) /* don't support negative values */
+ { pwsi->errno = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
+
+ if ( af == AF_UNSPEC) /* did they not specify the address family? */
+ switch(protocol)
+ {
+ case IPPROTO_TCP:
+ if (type == SOCK_STREAM) { af = AF_INET; break; }
+ case IPPROTO_UDP:
+ if (type == SOCK_DGRAM) { af = AF_INET; break; }
+ default: pwsi->errno = WSAEPROTOTYPE; return INVALID_SOCKET;
+ }
+
+ if ((sock = socket(af, type, protocol)) >= 0)
+ {
+ ws_socket* pnew = wsi_alloc_socket(pwsi, sock);
+
+/* printf("created %04x (%i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
+ */
+ if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
+ else pwsi->errno = WSAENOBUFS;
+ }
+
+ if (errno == EPERM) /* raw socket denied */
+ {
+ fprintf(stderr, "WS_SOCKET: not enough privileges\n");
+ pwsi->errno = WSAESOCKTNOSUPPORT;
+ } pwsi->errno = wsaErrno();
+ }
+
+ dprintf_winsock(stddeb, "\t\tfailed!\n");
+ return INVALID_SOCKET;
+}
+
+
+/* ----- database functions
+ *
+ * Note that ws_...ent structures we return have SEGPTR pointers inside them.
+ */
+
+static char* NULL_STRING = "NULL";
+
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n",
+ (unsigned)pwsi, (unsigned) addr, len, type);
+ if( pwsi )
+ {
+ struct hostent* host;
+ if( (host = gethostbyaddr(addr, len, type)) != NULL )
+ if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
+ return SEGPTR_GET(pwsi->buffer);
+ else pwsi->errno = WSAENOBUFS;
+ else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return NULL;
+}
+
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyname(const char *name)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n",
+ (unsigned)pwsi, (name)?name:"NULL");
+ if( pwsi )
+ {
+ struct hostent* host;
+ if( (host = gethostbyname(name)) != NULL )
+ if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
+ return SEGPTR_GET(pwsi->buffer);
+ else pwsi->errno = WSAENOBUFS;
+ else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return NULL;
+}
+
+INT16 WINSOCK_gethostname(char *name, INT16 namelen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n",
+ (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
+ if( pwsi )
+ {
+ if (gethostname(name, namelen) == 0) return 0;
+ pwsi->errno = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
+ }
+ return SOCKET_ERROR;
+}
+
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobyname(char *name)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n",
+ (unsigned)pwsi, (name)?name:NULL_STRING);
+ if( pwsi )
+ {
+ struct protoent* proto;
+ if( (proto = getprotobyname(name)) != NULL )
+ if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
+ return SEGPTR_GET(pwsi->buffer);
+ else pwsi->errno = WSAENOBUFS;
+ else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return NULL;
+}
+
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobynumber(INT16 number)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number);
+
+ if( pwsi )
+ {
+ struct protoent* proto;
+ if( (proto = getprotobynumber(number)) != NULL )
+ if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
+ return SEGPTR_GET(pwsi->buffer);
+ else pwsi->errno = WSAENOBUFS;
+ else pwsi->errno = WSANO_DATA;
+ }
+ return NULL;
+}
+
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n",
+ (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
+
+ if( pwsi )
+ {
+ struct servent* serv;
+ if( (serv = getservbyname(name, proto)) != NULL )
+ if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
+ return SEGPTR_GET(pwsi->buffer);
+ else pwsi->errno = WSAENOBUFS;
+ else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return NULL;
+}
+
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n",
+ (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
+ if( pwsi )
+ {
+ struct servent* serv;
+ if( (serv = getservbyport(port, proto)) != NULL )
+ if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
+ return SEGPTR_GET(pwsi->buffer);
+ else pwsi->errno = WSAENOBUFS;
+ else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+ }
+ return NULL;
+}
+
+
+/* ----------------------------------- Windows sockets extensions -- *
+ * *
+ * ----------------------------------------------------------------- */
+
+static int aop_control(ws_async_op* p_aop, int flag )
+{
+ unsigned lLength;
+
+ read(p_aop->fd[0], &lLength, sizeof(unsigned));
+ if( LOWORD(lLength) )
+ if( LOWORD(lLength) <= p_aop->buflen )
+ {
+ char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
+ read(p_aop->fd[0], buffer, LOWORD(lLength));
+ switch( p_aop->flags )
+ {
+ case WSMSG_ASYNC_HOSTBYNAME:
+ case WSMSG_ASYNC_HOSTBYADDR:
+ fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
+ case WSMSG_ASYNC_PROTOBYNAME:
+ case WSMSG_ASYNC_PROTOBYNUM:
+ fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
+ case WSMSG_ASYNC_SERVBYNAME:
+ case WSMSG_ASYNC_SERVBYPORT:
+ fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
+ default:
+ if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n");
+ return AOP_CONTROL_REMOVE;
+ }
+ }
+ else lLength = ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
+
+#if 0
+ printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n",
+ p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
+#endif
+
+ PostMessage(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
+ return AOP_CONTROL_REMOVE;
+}
+
+
+static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
+ INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
+{
+ /* queue 'flag' request and fork off its handler */
+
+ async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op));
+
+ if( async_ctl.ws_aop )
+ {
+ HANDLE16 handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop);
+
+ if( pipe(async_ctl.ws_aop->fd) == 0 )
+ {
+ async_ctl.ws_aop->init = (char*)init;
+ async_ctl.lLength = len;
+ async_ctl.lEvent = type;
+
+ async_ctl.ws_aop->hWnd = hWnd;
+ async_ctl.ws_aop->uMsg = uMsg;
+
+ async_ctl.ws_aop->buffer_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 );
+
+ async_ctl.ws_aop->pid = fork();
+ if( async_ctl.ws_aop->pid )
+ {
+ close(async_ctl.ws_aop->fd[1]); /* write endpoint */
+
+ /* Damn, BSD'ish SIGIO doesn't work on pipes/streams
+ *
+ * async_io(async_ctl.ws_aop->fd[0], 1);
+ */
+
+ dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n",
+ handle, async_ctl.ws_aop->pid);
+ return handle;
+ } else
+ /* child process */
+ {
+ close(async_ctl.ws_aop->fd[0]); /* read endpoint */
+ switch(flag)
+ {
+ case WSMSG_ASYNC_HOSTBYADDR:
+ case WSMSG_ASYNC_HOSTBYNAME:
+ WS_do_async_gethost(pwsi,flag);
+ case WSMSG_ASYNC_PROTOBYNUM:
+ case WSMSG_ASYNC_PROTOBYNAME:
+ WS_do_async_getproto(pwsi,flag);
+ case WSMSG_ASYNC_SERVBYPORT:
+ case WSMSG_ASYNC_SERVBYNAME:
+ WS_do_async_getserv(pwsi,flag);
+ }
+ }
+ }
+ WS_FREE(async_ctl.ws_aop);
+ pwsi->errno = wsaErrno();
+ } else pwsi->errno = WSAEWOULDBLOCK;
+ return 0;
+}
+
+HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
+ INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
+ (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
+
+ if( pwsi )
+ return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
+ type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
+ return 0;
+}
+
+
+HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
+ SEGPTR sbuf, INT16 buflen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
+ (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
+
+ if( pwsi )
+ return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+ 0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
+ return 0;
+}
+
+
+HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
+ SEGPTR sbuf, INT16 buflen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
+ (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
+
+ if( pwsi )
+ return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+ 0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
+ return 0;
+}
+
+
+HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number,
+ SEGPTR sbuf, INT16 buflen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
+ (unsigned)pwsi, hWnd, uMsg, number );
+
+ if( pwsi )
+ return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
+ number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
+ return 0;
+}
+
+
+HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name,
+ LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
+ (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
+
+ if( pwsi )
+ {
+ async_ctl.buffer = (char*)proto;
+ return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+ 0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
+ }
+ return 0;
+}
+
+
+HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port,
+ LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
+ (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
+
+ if( pwsi )
+ return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0,
+ port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
+ return 0;
+}
+
+INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+ ws_async_op* p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
+
+ dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n",
+ (unsigned)pwsi, hAsyncTaskHandle);
+ if( pwsi )
+ if( WINSOCK_check_async_op(p_aop) )
+ {
+ kill(p_aop->pid, SIGKILL);
+ waitpid(p_aop->pid, NULL, 0);
+ close(p_aop->fd[0]);
+ WINSOCK_unlink_async_op(p_aop);
+ WS_FREE(p_aop);
+ return 0;
+ }
+ else pwsi->errno = WSAEINVAL;
+ return SOCKET_ERROR;
+}
+
+/* ----- asynchronous select() */
+
+int delete_async_op(ws_socket* pws)
+{
+ if( pws->p_aop )
+ {
+ kill(pws->p_aop->pid, SIGKILL);
+ waitpid(pws->p_aop->pid, NULL, 0);
+ WS_FREE(pws->p_aop); return 1;
+ pws->flags &= WS_FD_INTERNAL;
+ }
+ return 0;
+}
+
+void _sigusr1_handler_parent(int sig)
+{
+ /* child process puts MTYPE_CLIENT data packet into the
+ * 'async_qid' message queue and signals us with SIGUSR1.
+ * This handler reads the queue and posts 'uMsg' notification
+ * message.
+ */
+
+ ipc_packet ipack;
+
+ signal( SIGUSR1, _sigusr1_handler_parent);
+ while( msgrcv(async_qid, (struct msgbuf*)&ipack,
+ MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 )
+ {
+ if( ipack.wParam && abs((short)ipack.wParam) < 32768 )
+ {
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam);
+ if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 )
+ {
+ pws->flags &= ~(ipack.lParam);
+#if 0
+ printf("async event - hWnd %04x, uMsg %04x [%08x]\n",
+ pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam );
+#endif
+ PostMessage(pws->p_aop->hWnd, pws->p_aop->uMsg,
+ (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
+ }
+ else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
+ }
+ else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
+ }
+}
+
+int notify_client( ws_socket* pws, unsigned flag )
+{
+ if( pws->p_aop && ((pws->p_aop->flags & flag) ||
+ (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) )
+ {
+ async_ctl.ip.mtype = MTYPE_PARENT;
+ async_ctl.ip.lParam = flag;
+ while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
+ MTYPE_PARENT_SIZE, 0) == -1 )
+ {
+ if( errno == EINTR ) continue;
+ else
+ {
+ perror("AsyncSelect(parent)");
+ delete_async_op(pws);
+ pws->flags &= WS_FD_INTERNAL;
+ return 0;
+ }
+ }
+ kill(pws->p_aop->pid, SIGUSR1);
+ return 1;
+ }
+ return 0;
+}
+
+INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+{
+ ws_async_op* p_aop;
+
+ if( delete_async_op(pws) ) /* delete old async handler if any */
+ {
+ pws->p_aop = NULL;
+ pws->flags &= WS_FD_INTERNAL;
+ }
+ if( lEvent == 0 ) return 0;
+
+ /* setup async handler - some data may be redundant */
+
+ WINSOCK_unblock_io(pws->fd, 1);
+ if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) )
+ {
+ p_aop->hWnd = hWnd;
+ p_aop->uMsg = uMsg;
+ pws->p_aop = p_aop;
+
+ async_ctl.lEvent = p_aop->flags = lEvent;
+ async_ctl.ws_sock = pws;
+ async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws);
+ async_ctl.ip.lParam = 0;
+
+ p_aop->pid = fork();
+ if( p_aop->pid != -1 )
+ if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
+ else pws->flags |= lEvent;
+
+ signal( SIGUSR1, _sigusr1_handler_parent );
+ return 0; /* Wine process */
+ }
+ return SOCKET_ERROR;
+}
+
+INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+{
+ ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
+ (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
+ if( _check_ws(pwsi, pws) )
+ if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0;
+ else pwsi->errno = WSAENOBUFS;
+ return SOCKET_ERROR;
+}
+
+/* ----- miscellaneous */
+
+INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
+{
+ int i = set->fd_count;
+
+ dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
+
+ while (i--)
+ if (set->fd_array[i] == fd) return 1;
+ return 0;
+}
+
+BOOL16 WSAIsBlocking(void)
+{
+ /* By default WinSock should set all its sockets to non-blocking mode
+ * and poll in PeekMessage loop when processing "blocking" ones. This
+ * function * is supposed to tell if program is in this loop. Our
+ * blocking calls are truly blocking so we always return FALSE.
+ *
+ * Note: It is allowed to call this function without prior WSAStartup().
+ */
+
+ dprintf_winsock(stddeb, "WS_IsBlocking()\n");
+ return FALSE;
+}
+
+INT16 WSACancelBlockingCall(void)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
+
+ if( pwsi ) return 0;
+ return SOCKET_ERROR;
+}
+
+FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
+{
+ FARPROC16 prev;
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_SetBlockingHook(%08x): hook %08x\n",
+ (unsigned)pwsi, (unsigned) lpBlockFunc);
+
+ if( pwsi ) {
+ prev = pwsi->blocking_hook;
+ pwsi->blocking_hook = lpBlockFunc;
+ return prev;
+ }
+ return 0;
+}
+
+INT16 WSAUnhookBlockingHook(void)
+{
+ LPWSINFO pwsi = wsi_find(GetCurrentTask());
+
+ dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi);
+ if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL);
+ return SOCKET_ERROR;
+}
+
+VOID
+WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6)
+{
+ fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
+ x1,x2,x3,x4,x5,x6
+ );
+ fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
+ x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
+ );
+ return;
+}
+/* ----------------------------------- end of API stuff */
+
+
+
+/* ----------------------------------- helper functions */
+
+static int list_size(char** l, int item_size)
+{
+ int i,j = 0;
+ if(l)
+ { for(i=0;l[i];i++)
+ j += (item_size) ? item_size : strlen(l[i]) + 1;
+ j += (i + 1) * sizeof(char*); }
+ return j;
+}
+
+static int list_dup(char** l_src, char* ref, char* base, int item_size)
+{
+ /* base is either either equal to ref or 0 or SEGPTR */
+
+ char* p = ref;
+ char** l_to = (char**)ref;
+ int i,j,k;
+
+ for(j=0;l_src[j];j++) ;
+ p += (j + 1) * sizeof(char*);
+ for(i=0;i<j;i++)
+ { l_to[i] = base + (p - ref);
+ k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
+ memcpy(p, l_src[i], k); p += k; }
+ l_to[i] = NULL;
+ return (p - ref);
+}
+
+/* ----- hostent */
+
+static int hostent_size(struct hostent* p_he)
+{
+ int size = 0;
+ if( p_he )
+ { size = sizeof(struct hostent);
+ size += strlen(p_he->h_name) + 1;
+ size += list_size(p_he->h_aliases, 0);
+ size += list_size(p_he->h_addr_list, p_he->h_length ); }
+ return size;
+}
+
+int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
+{
+ /* Duplicate hostent structure and flatten data (with its pointers)
+ * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
+ * relative to 0 depending on "flag" value. Return data size (also
+ * in the pwsi->buflen).
+ */
+
+ int size = hostent_size(p_he);
+ if( size )
+ {
+ char* p_name,*p_aliases,*p_addr,*p_base,*p;
+
+ _check_buffer(pwsi, size);
+ p = pwsi->buffer;
+ p_base = (flag & WS_DUP_OFFSET) ? NULL
+ : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
+ p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent);
+ p_name = p;
+ strcpy(p, p_he->h_name); p += strlen(p) + 1;
+ p_aliases = p;
+ p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
+ p_addr = p;
+ list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
+ if( !(flag & WS_DUP_SEGPTR) )
+ { struct hostent* p_to = (struct hostent*)pwsi->buffer;
+ p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
+ p_to->h_name = p_base + (p_name - pwsi->buffer);
+ p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
+ p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
+ else
+ { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
+ p_to->h_addrtype = (INT16)p_he->h_addrtype;
+ p_to->h_length = (INT16)p_he->h_length;
+ p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+ p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
+ p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
+ return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
+ }
+ return size;
+}
+
+void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR 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;
+}
+
+/* ----- protoent */
+
+static int protoent_size(struct protoent* p_pe)
+{
+ int size = 0;
+ if( p_pe )
+ { size = sizeof(struct protoent);
+ size += strlen(p_pe->p_name) + 1;
+ size += list_size(p_pe->p_aliases, 0); }
+ return size;
+}
+
+int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
+{
+ int size = protoent_size(p_pe);
+ if( size )
+ {
+ char* p_name,*p_aliases,*p_base,*p;
+
+ _check_buffer(pwsi, size);
+ p = pwsi->buffer;
+ p_base = (flag & WS_DUP_OFFSET) ? NULL
+ : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
+ p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent);
+ p_name = p;
+ strcpy(p, p_pe->p_name); p += strlen(p) + 1;
+ p_aliases = p;
+ list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
+ if( !(flag & WS_DUP_NATIVE) )
+ { struct protoent* p_to = (struct protoent*)pwsi->buffer;
+ p_to->p_proto = p_pe->p_proto;
+ p_to->p_name = p_base + (p_name - pwsi->buffer);
+ p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
+ else
+ { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
+ p_to->p_proto = (INT16)p_pe->p_proto;
+ p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
+ p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer));
+ return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
+ }
+ return size;
+}
+
+void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR 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;
+}
+
+/* ----- servent */
+
+static int servent_size(struct servent* p_se)
+{
+ int size = 0;
+ if( p_se )
+ { size += sizeof(struct servent);
+ size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
+ size += list_size(p_se->s_aliases, 0); }
+ return size;
+}
+
+int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
+{
+ int size = servent_size(p_se);
+ if( size )
+ {
+ char* p_name,*p_aliases,*p_proto,*p_base,*p;
+
+ _check_buffer(pwsi, size);
+ p = pwsi->buffer;
+ p_base = (flag & WS_DUP_OFFSET) ? NULL
+ : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
+ p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent);
+ p_name = p;
+ strcpy(p, p_se->s_name); p += strlen(p) + 1;
+ p_proto = p;
+ strcpy(p, p_se->s_proto); p += strlen(p) + 1;
+ p_aliases = p;
+ list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
+
+ if( !(flag & WS_DUP_SEGPTR) )
+ { struct servent* p_to = (struct servent*)pwsi->buffer;
+ p_to->s_port = p_se->s_port;
+ p_to->s_name = p_base + (p_name - pwsi->buffer);
+ p_to->s_proto = p_base + (p_proto - pwsi->buffer);
+ p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
+ else
+ { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
+ p_to->s_port = (INT16)p_se->s_port;
+ p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+ p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
+ p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
+ return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
+ }
+ return size;
+}
+
+void fixup_wsse(struct ws_servent* p_wsse, SEGPTR 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;
+}
+
+/* ----------------------------------- error handling */
+
+UINT16 wsaErrno(void)
+{
+ int loc_errno = errno;
+#if defined(__FreeBSD__)
+ dprintf_winsock(stderr, "winsock: errno %d, (%s).\n",
+ errno, sys_errlist[errno]);
+#else
+ dprintf_winsock(stderr, "winsock: errno %d\n", errno);
+#endif
+
+ switch(loc_errno)
+ {
+ case EINTR: return WSAEINTR;
+ case EBADF: return WSAEBADF;
+ case EACCES: return WSAEACCES;
+ case EFAULT: return WSAEFAULT;
+ case EINVAL: return WSAEINVAL;
+ case EMFILE: return WSAEMFILE;
+ case EWOULDBLOCK: return WSAEWOULDBLOCK;
+ case EINPROGRESS: return WSAEINPROGRESS;
+ case EALREADY: return WSAEALREADY;
+ case ENOTSOCK: return WSAENOTSOCK;
+ case EDESTADDRREQ: return WSAEDESTADDRREQ;
+ case EMSGSIZE: return WSAEMSGSIZE;
+ case EPROTOTYPE: return WSAEPROTOTYPE;
+ case ENOPROTOOPT: return WSAENOPROTOOPT;
+ case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
+ case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
+ case EOPNOTSUPP: return WSAEOPNOTSUPP;
+ case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
+ case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
+ case EADDRINUSE: return WSAEADDRINUSE;
+ case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
+ case ENETDOWN: return WSAENETDOWN;
+ case ENETUNREACH: return WSAENETUNREACH;
+ case ENETRESET: return WSAENETRESET;
+ case ECONNABORTED: return WSAECONNABORTED;
+ case ECONNRESET: return WSAECONNRESET;
+ case ENOBUFS: return WSAENOBUFS;
+ case EISCONN: return WSAEISCONN;
+ case ENOTCONN: return WSAENOTCONN;
+ case ESHUTDOWN: return WSAESHUTDOWN;
+ case ETOOMANYREFS: return WSAETOOMANYREFS;
+ case ETIMEDOUT: return WSAETIMEDOUT;
+ case ECONNREFUSED: return WSAECONNREFUSED;
+ case ELOOP: return WSAELOOP;
+ case ENAMETOOLONG: return WSAENAMETOOLONG;
+ case EHOSTDOWN: return WSAEHOSTDOWN;
+ case EHOSTUNREACH: return WSAEHOSTUNREACH;
+ case ENOTEMPTY: return WSAENOTEMPTY;
+#ifdef EPROCLIM
+ case EPROCLIM: return WSAEPROCLIM;
+#endif
+#ifdef EUSERS
+ case EUSERS: return WSAEUSERS;
+#endif
+#ifdef EDQUOT
+ case EDQUOT: return WSAEDQUOT;
+#endif
+ case ESTALE: return WSAESTALE;
+ case EREMOTE: return WSAEREMOTE;
+
+ /* just in case we ever get here and there are no problems */
+ case 0: return 0;
+ default:
+ fprintf(stderr, "winsock: unknown errno %d!\n", errno);
+ return WSAEOPNOTSUPP;
+ }
+}
+
+UINT16 wsaHerrno(void)
+{
+ int loc_errno = h_errno;
+
+#if defined(__FreeBSD__)
+ dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n",
+ h_errno, sys_errlist[h_errno]);
+#else
+ dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
+#ifndef sun
+ if( debugging_winsock ) herror("wine: winsock: wsaherrno");
+#endif
+#endif
+
+ switch(loc_errno)
+ {
+ case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
+ case TRY_AGAIN: return WSATRY_AGAIN;
+ case NO_RECOVERY: return WSANO_RECOVERY;
+ case NO_DATA: return WSANO_DATA;
+
+ case 0: return 0;
+ default:
+ fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
+ return WSAEOPNOTSUPP;
+ }
+}
+
+
diff --git a/misc/winsock_async.c b/misc/winsock_async.c
new file mode 100644
index 0000000..6596b5f
--- /dev/null
+++ b/misc/winsock_async.c
@@ -0,0 +1,486 @@
+/*
+ * asynchronous winsock services
+ *
+ * (C) 1996 Alex Korobka.
+ *
+ * FIXME: telftp16 (ftp part) stalls on AsyncSelect with FD_ACCEPT.
+ */
+#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>
+
+#include "windows.h"
+#include "winsock.h"
+#include "debug.h"
+
+#define __WS_ASYNC_DEBUG 0
+
+static int _async_io_max_fd = 0;
+static fd_set __async_io_fdset;
+static ws_async_op* __async_op_list = NULL;
+
+extern ws_async_ctl async_ctl;
+extern int async_qid;
+
+fd_set fd_read, fd_write, fd_excp;
+
+/* ----------------------------------- async/non-blocking I/O */
+
+int WINSOCK_async_io(int fd, int async)
+{
+ int fd_flags;
+
+ fcntl(fd, F_SETOWN, getpid());
+
+ 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;
+}
+
+void WINSOCK_cancel_async_op(HTASK16 hTask)
+{
+ ws_async_op* p = __async_op_list;
+ while( p )
+ if(hTask == GetWindowTask16(p->hWnd))
+ p->flags = 0;
+}
+
+void WINSOCK_link_async_op(ws_async_op* p_aop)
+{
+ if( __async_op_list ) __async_op_list->prev = p_aop;
+ else FD_ZERO(&__async_io_fdset);
+
+ p_aop->next = __async_op_list;
+ p_aop->prev = NULL;
+ __async_op_list = p_aop;
+
+ 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)
+{
+ 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: AsyncGetXbyY expilicitly raise it.
+ */
+
+void WINSOCK_sigio(int signal)
+{
+ struct timeval timeout;
+ fd_set check_set;
+ ws_async_op* p_aop;
+
+ check_set = __async_io_fdset;
+ bzero(&timeout,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 )
+ {
+ if( p_aop->pid )
+ {
+ kill(p_aop->pid, SIGKILL);
+ waitpid(p_aop->pid, NULL, 0);
+ }
+ WINSOCK_unlink_async_op( p_aop );
+ }
+ check_set = __async_io_fdset;
+ }
+}
+
+/* ----------------------------------- child process IPC */
+
+static void _sigusr1_handler_child(int sig)
+{
+ /* read message queue to decide which
+ * async_ctl parameters to update
+ *
+ * Note: we don't want to have SA_RESTART on this signal
+ * handler, otherwise select() won't notice changed fd sets.
+ */
+
+ signal( SIGUSR1, _sigusr1_handler_child );
+ while( msgrcv(async_qid, (struct msgbuf*)&async_ctl.ip,
+ MTYPE_PARENT_SIZE, MTYPE_PARENT, IPC_NOWAIT) != -1 )
+ {
+ /* only ip.lParam is updated */
+#if __WS_ASYNC_DEBUG
+ printf("handler - event %08x\n", async_ctl.ip.lParam );
+#endif
+
+ switch( async_ctl.ip.lParam )
+ {
+ /* These are events we are notified of.
+ */
+
+ case WS_FD_CONNECTED: async_ctl.lEvent &= ~WS_FD_CONNECT;
+ FD_SET(async_ctl.ws_sock->fd, &fd_read);
+ FD_SET(async_ctl.ws_sock->fd, &fd_write);
+ break;
+
+ case WS_FD_ACCEPT: async_ctl.ws_sock->flags |= WS_FD_ACCEPT;
+ FD_SET(async_ctl.ws_sock->fd, &fd_read);
+ FD_SET(async_ctl.ws_sock->fd, &fd_write);
+ break;
+ case WS_FD_OOB: async_ctl.lEvent |= WS_FD_OOB;
+ FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+ break;
+ case WS_FD_READ: async_ctl.lEvent |= WS_FD_READ;
+ FD_SET(async_ctl.ws_sock->fd, &fd_read);
+ break;
+ case WS_FD_WRITE: async_ctl.lEvent |= WS_FD_WRITE;
+ FD_SET(async_ctl.ws_sock->fd, &fd_write);
+ break;
+ default:
+ }
+ }
+}
+
+static int notify_parent( unsigned flag )
+{
+ if( flag & WSMSG_ASYNC_SELECT )
+ {
+ async_ctl.ip.mtype = MTYPE_CLIENT;
+ while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
+ MTYPE_CLIENT_SIZE, 0) == -1 )
+ {
+ if( errno == EINTR ) continue;
+ else if( errno == EIDRM ) _exit(0);
+ else
+ {
+ perror("AsyncSelect(child)");
+ return 0;
+ }
+ }
+ kill(getppid(), SIGUSR1);
+
+#if __WS_ASYNC_DEBUG
+ printf("handler - notify [%08x]\n", async_ctl.ip.lParam);
+#endif
+ }
+ else /* use half-duplex pipe to handle variable length packets */
+ {
+ write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) );
+ write(async_ctl.ws_aop->fd[1], async_ctl.buffer, async_ctl.lLength );
+ kill(getppid(), SIGIO); /* simulate async I/O */
+#if __WS_ASYNC_DEBUG
+ printf("handler - notify aop [%d, buf %d]\n", async_ctl.lLength, async_ctl.ws_aop->buflen);
+#endif
+ pause();
+ }
+ return 1;
+}
+
+/* ----------------------------------- async select */
+
+static void setup_fd_sets()
+{
+ FD_ZERO(&fd_read); FD_ZERO(&fd_write); FD_ZERO(&fd_excp);
+
+ if( async_ctl.lEvent & WS_FD_OOB)
+ FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+ if( async_ctl.lEvent & (WS_FD_ACCEPT | WS_FD_READ |
+ WS_FD_CONNECT | WS_FD_CLOSE) )
+ FD_SET(async_ctl.ws_sock->fd, &fd_read);
+ if( async_ctl.lEvent & (WS_FD_WRITE | WS_FD_CONNECT) )
+ FD_SET(async_ctl.ws_sock->fd, &fd_write);
+}
+
+static void setup_sig_sets(sigset_t* sig_block)
+{
+ sigemptyset(sig_block);
+ sigaddset(sig_block, SIGUSR1);
+ sigprocmask( SIG_BLOCK, sig_block, NULL);
+ signal( SIGUSR1, _sigusr1_handler_child );
+}
+
+void WINSOCK_do_async_select()
+{
+ sigset_t sig_block;
+ int bytes;
+
+ setup_sig_sets(&sig_block);
+ setup_fd_sets();
+
+ while(1)
+ {
+ int val;
+
+ sigprocmask( SIG_UNBLOCK, &sig_block, NULL);
+
+#if __WS_ASYNC_DEBUG
+ printf("select(2)[%i,%i,%i]... ",
+ FD_ISSET(async_ctl.ws_sock->fd, &fd_read),
+ FD_ISSET(async_ctl.ws_sock->fd, &fd_write),
+ FD_ISSET(async_ctl.ws_sock->fd, &fd_excp));
+#endif
+ if( (val = select(async_ctl.ws_sock->fd + 1,
+ &fd_read, &fd_write, &fd_excp, NULL)) == -1 )
+ if( errno == EINTR ) continue;
+#if __WS_ASYNC_DEBUG
+ printf("got %i events\n", val);
+#endif
+
+#if __WS_ASYNC_DEBUG
+ if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+ printf("handler - read is READY! [%08x]\n", async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE));
+#endif
+
+ sigprocmask( SIG_BLOCK, &sig_block, NULL);
+ async_ctl.ip.lParam = 0;
+ if( async_ctl.ws_sock->flags & WS_FD_ACCEPT )
+ {
+ /* listening socket */
+
+ FD_CLR(async_ctl.ws_sock->fd, &fd_read);
+ FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 );
+ notify_parent( WSMSG_ASYNC_SELECT );
+ continue;
+ }
+ else /* I/O socket */
+ {
+ if( async_ctl.lEvent & WS_FD_CONNECT )
+ {
+ if( FD_ISSET(async_ctl.ws_sock->fd, &fd_write) )
+ {
+ /* success - reinit fd sets to start I/O */
+
+ if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE))
+ FD_SET(async_ctl.ws_sock->fd, &fd_read);
+ else FD_CLR(async_ctl.ws_sock->fd, &fd_read);
+ if( async_ctl.lEvent & WS_FD_WRITE )
+ FD_SET(async_ctl.ws_sock->fd, &fd_write);
+ else FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 );
+ async_ctl.lEvent &= ~WS_FD_CONNECT; /* one-shot */
+ }
+ else if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+ {
+ /* failure - do read() to get correct errno */
+
+ if( read(async_ctl.ws_sock->fd, &bytes, 4) == -1 )
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() );
+ else continue;
+ } else continue; /* OOB?? */
+
+ notify_parent( WSMSG_ASYNC_SELECT );
+ }
+ else /* connected socket */
+ {
+
+ if( async_ctl.lEvent & WS_FD_OOB )
+ if( FD_ISSET(async_ctl.ws_sock->fd, &fd_excp) )
+ {
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_OOB, 0 );
+ async_ctl.lEvent &= ~WS_FD_OOB;
+ FD_CLR(async_ctl.ws_sock->fd, &fd_excp);
+ notify_parent( WSMSG_ASYNC_SELECT );
+ }
+ else FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+
+ if( async_ctl.lEvent & WS_FD_WRITE )
+ if( FD_ISSET( async_ctl.ws_sock->fd, &fd_write ) )
+ {
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_WRITE, 0 );
+ async_ctl.lEvent &= ~WS_FD_WRITE;
+ FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+ notify_parent( WSMSG_ASYNC_SELECT );
+ }
+ else FD_SET(async_ctl.ws_sock->fd, &fd_write);
+
+ if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE) )
+ if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+ {
+ if( ioctl( async_ctl.ws_sock->fd, FIONREAD, (char*)&bytes) != -1 )
+ {
+ if( bytes ) /* got data */
+ {
+#if __WS_ASYNC_DEBUG
+ printf("\t%i bytes pending\n", bytes );
+#endif
+ if( async_ctl.lEvent & WS_FD_READ )
+ {
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, 0 );
+ async_ctl.lEvent &= ~WS_FD_READ;
+ if( !(async_ctl.lEvent & WS_FD_CLOSE) )
+ FD_CLR( async_ctl.ws_sock->fd, &fd_read );
+ }
+ else if( !(async_ctl.lEvent & (WS_FD_WRITE | WS_FD_OOB)) )
+ {
+ sigprocmask( SIG_UNBLOCK, &sig_block, NULL);
+ pause();
+ sigprocmask( SIG_BLOCK, &sig_block, NULL);
+ }
+ else continue;
+ }
+ else /* 0 bytes to read */
+ {
+ val = read( async_ctl.ws_sock->fd, (char*)&bytes, 4);
+ if( errno == EWOULDBLOCK || errno == EINTR )
+ {
+#if __WS_ASYNC_DEBUG
+ printf("\twould block..\n");
+#endif
+ continue;
+ }
+ switch( val )
+ {
+ case 0: errno = ENETDOWN; /* ENETDOWN */
+ case -1: /* ECONNRESET */
+ async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() );
+ break;
+ default: continue;
+ }
+ async_ctl.lEvent &= ~(WS_FD_CLOSE | WS_FD_READ); /* one-shot */
+ FD_ZERO(&fd_read); FD_ZERO(&fd_write);
+ }
+ }
+ else async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() );
+
+ notify_parent( WSMSG_ASYNC_SELECT );
+ }
+ else FD_SET(async_ctl.ws_sock->fd, &fd_read);
+
+ } /* connected socket */
+ } /* I/O socket */
+ } /* while */
+}
+
+
+/* ----------------------------------- getXbyY requests */
+
+static void _async_fail()
+{
+ async_ctl.lLength =
+ (h_errno < 0) ? (unsigned)WSAMAKEASYNCREPLY( 0, wsaErrno() )
+ : (unsigned)WSAMAKEASYNCREPLY( 0, wsaHerrno() );
+ write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) );
+ kill(getppid(), SIGIO); /* simulate async I/O */
+ pause();
+}
+
+void dump_ws_hostent_offset(struct ws_hostent* wshe)
+{
+ int i;
+ char* base = (char*)wshe;
+ unsigned* ptr;
+
+ printf("h_name = %08x\t[%s]\n", (unsigned)wshe->h_name, base + (unsigned)wshe->h_name);
+ printf("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++ )
+ {
+ printf("%i - %08x ", i + 1, ptr[i]);
+ printf(" [%s]\n", ((char*)base) + ptr[i]);
+ }
+ printf("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.ws_aop->init)
+ : gethostbyaddr(async_ctl.ws_aop->init,
+ async_ctl.lLength, async_ctl.lEvent);
+ if( p_he ) size = WS_dup_he(pwsi, p_he, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+ if( size )
+ {
+ async_ctl.buffer = pwsi->buffer;
+ async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+ notify_parent( flag );
+ }
+ else _async_fail();
+ _exit(0);
+}
+
+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.ws_aop->init)
+ : getprotobynumber(async_ctl.lEvent);
+ if( p_pe ) size = WS_dup_pe(pwsi, p_pe, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+ if( size )
+ {
+ async_ctl.buffer = pwsi->buffer;
+ async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+ notify_parent( flag );
+ }
+ else _async_fail();
+ _exit(0);
+}
+
+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.ws_aop->init, async_ctl.buffer)
+ : getservbyport(async_ctl.lEvent, async_ctl.ws_aop->init);
+ if( p_se ) size = WS_dup_se(pwsi, p_se, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+ if( size )
+ {
+ async_ctl.buffer = pwsi->buffer;
+ async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+ notify_parent( flag );
+ }
+ else _async_fail();
+ _exit(0);
+}
+
diff --git a/misc/winsocket.c b/misc/winsocket.c
deleted file mode 100644
index 1507a5e..0000000
--- a/misc/winsocket.c
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * based on Windows Sockets 1.1 specs
- * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
- *
- * (C) 1993,1994 John Brezak, Erik Bos.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/ioctl.h>
-#if defined(__svr4__)
-#include <sys/filio.h>
-#include <sys/ioccom.h>
-#endif
-#include <sys/msg.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <netdb.h>
-#include <unistd.h>
-
-#include "winsock.h"
-#include "global.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#ifdef _SCO_DS
-#define _IOR _IOSR
-#define _IOW _IOSW
-#endif
-
-static WORD wsa_errno;
-static int wsa_initted;
-static key_t wine_key = 0;
-static FARPROC16 BlockFunction;
-static fd_set fd_in_use;
-
-extern int h_errno;
-
-struct ipc_packet {
- long mtype;
- HANDLE16 handle;
- HWND hWnd;
- WORD wMsg;
- LONG lParam;
-};
-
-#ifndef WINELIB
-#pragma pack(1)
-#endif
-
-#define WINSOCK_MAX_SOCKETS 256
-#define WINSOCK_MAX_UDPDG 1024
-
-/* we are out by two with the following, is it due to byte alignment?
- * #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
- */
-#define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long) - 2)
-/*#define MTYPE 0xb0b0eb05*/
-#define MTYPE 0x30b0eb05
-
-/* These structures are Win16 only */
-
-struct WIN_hostent {
- SEGPTR h_name WINE_PACKED; /* official name of host */
- SEGPTR h_aliases WINE_PACKED; /* alias list */
- INT h_addrtype WINE_PACKED; /* host address type */
- INT h_length WINE_PACKED; /* length of address */
- char **h_addr_list WINE_PACKED; /* list of addresses from name server */
- char *names[2];
- char hostname[200];
-};
-
-struct WIN_protoent {
- SEGPTR p_name WINE_PACKED; /* official protocol name */
- SEGPTR p_aliases WINE_PACKED; /* alias list */
- INT p_proto WINE_PACKED; /* protocol # */
-};
-
-struct WIN_servent {
- SEGPTR s_name WINE_PACKED; /* official service name */
- SEGPTR s_aliases WINE_PACKED; /* alias list */
- INT s_port WINE_PACKED; /* port # */
- SEGPTR s_proto WINE_PACKED; /* protocol to use */
-};
-
-typedef struct WinSock_fd_set {
- u_short fd_count; /* how many are SET? */
- SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
-} WinSock_fd_set;
-
-struct WinSockHeap {
- char ntoa_buffer[32];
-
- struct WIN_hostent hostent_addr;
- struct WIN_hostent hostent_name;
- struct WIN_protoent protoent_name;
- struct WIN_protoent protoent_number;
- struct WIN_servent servent_name;
- struct WIN_servent servent_port;
-
- struct WIN_hostent WSAhostent_addr;
- struct WIN_hostent WSAhostent_name;
- struct WIN_protoent WSAprotoent_name;
- struct WIN_protoent WSAprotoent_number;
- struct WIN_servent WSAservent_name;
- struct WIN_servent WSAservent_port;
- /* 8K scratch buffer for aliases and friends are hopefully enough */
- char scratch[8192];
-};
-static struct WinSockHeap *Heap;
-static HGLOBAL16 HeapHandle;
-#ifndef WINELIB32
-static int ScratchPtr;
-#endif
-
-#ifndef WINELIB
-#define GET_SEG_PTR(x) MAKELONG((int)((char*)(x)-(char*)Heap), \
- GlobalHandleToSel(HeapHandle))
-#else
-#define GET_SEG_PTR(x) ((SEGPTR)x)
-#endif
-
-#ifndef WINELIB
-#pragma pack(4)
-#endif
-
-#define dump_sockaddr(a) \
- fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
- ((struct sockaddr_in *)a)->sin_family, \
- inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
- ntohs(((struct sockaddr_in *)a)->sin_port))
-
-#ifndef WINELIB32
-static void ResetScratch()
-{
- ScratchPtr=0;
-}
-
-static void *scratch_alloc(int size)
-{
- char *ret;
- if(ScratchPtr+size > sizeof(Heap->scratch))
- return 0;
- ret = Heap->scratch + ScratchPtr;
- ScratchPtr += size;
- return ret;
-}
-
-static SEGPTR scratch_strdup(char * s)
-{
- char *ret=scratch_alloc(strlen(s)+1);
- strcpy(ret,s);
- return GET_SEG_PTR(ret);
-}
-#endif
-
-static WORD wsaerrno(void)
-{
-#ifdef DEBUG_WINSOCK
-#ifndef sun
-#if defined(__FreeBSD__)
- fprintf(stderr, "winsock: errno %d, (%s).\n",
- errno, sys_errlist[errno]);
-#else
- fprintf(stderr, "winsock: errno %d\n", errno);
-#endif
-#else
- fprintf(stderr, "winsock: errno %d\n", errno);
-#endif
-#endif
-
- switch(errno)
- {
- case EINTR: return WSAEINTR;
- case EBADF: return WSAEBADF;
- case EACCES: return WSAEACCES;
- case EFAULT: return WSAEFAULT;
- case EINVAL: return WSAEINVAL;
- case EMFILE: return WSAEMFILE;
- case EWOULDBLOCK: return WSAEWOULDBLOCK;
- case EINPROGRESS: return WSAEINPROGRESS;
- case EALREADY: return WSAEALREADY;
- case ENOTSOCK: return WSAENOTSOCK;
- case EDESTADDRREQ: return WSAEDESTADDRREQ;
- case EMSGSIZE: return WSAEMSGSIZE;
- case EPROTOTYPE: return WSAEPROTOTYPE;
- case ENOPROTOOPT: return WSAENOPROTOOPT;
- case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
- case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
- case EOPNOTSUPP: return WSAEOPNOTSUPP;
- case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
- case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
- case EADDRINUSE: return WSAEADDRINUSE;
- case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
- case ENETDOWN: return WSAENETDOWN;
- case ENETUNREACH: return WSAENETUNREACH;
- case ENETRESET: return WSAENETRESET;
- case ECONNABORTED: return WSAECONNABORTED;
- case ECONNRESET: return WSAECONNRESET;
- case ENOBUFS: return WSAENOBUFS;
- case EISCONN: return WSAEISCONN;
- case ENOTCONN: return WSAENOTCONN;
- case ESHUTDOWN: return WSAESHUTDOWN;
- case ETOOMANYREFS: return WSAETOOMANYREFS;
- case ETIMEDOUT: return WSAETIMEDOUT;
- case ECONNREFUSED: return WSAECONNREFUSED;
- case ELOOP: return WSAELOOP;
- case ENAMETOOLONG: return WSAENAMETOOLONG;
- case EHOSTDOWN: return WSAEHOSTDOWN;
- case EHOSTUNREACH: return WSAEHOSTUNREACH;
- case ENOTEMPTY: return WSAENOTEMPTY;
-#ifdef EPROCLIM
- case EPROCLIM: return WSAEPROCLIM;
-#endif
-#ifdef EUSERS
- case EUSERS: return WSAEUSERS;
-#endif
-#ifdef EDQUOT
- case EDQUOT: return WSAEDQUOT;
-#endif
- case ESTALE: return WSAESTALE;
- case EREMOTE: return WSAEREMOTE;
-/* just in case we ever get here and there are no problems */
- case 0: return 0;
-
- default:
- fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
- return WSAEOPNOTSUPP;
- }
-}
-
-static void errno_to_wsaerrno(void)
-{
- wsa_errno = wsaerrno();
-}
-
-
-static WORD wsaherrno(void)
-{
-#if DEBUG_WINSOCK
-#ifndef sun
-#if defined(__FreeBSD__)
- fprintf(stderr, "winsock: h_errno %d, (%s).\n",
- h_errno, sys_errlist[h_errno]);
-#else
- fprintf(stderr, "winsock: h_errno %d.\n", h_errno);
- herror("wine: winsock: wsaherrno");
-#endif
-#else
- fprintf(stderr, "winsock: h_errno %d\n", h_errno);
-#endif
-#endif
-
- switch(h_errno)
- {
- case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
- case TRY_AGAIN: return WSATRY_AGAIN;
- case NO_RECOVERY: return WSANO_RECOVERY;
- case NO_DATA: return WSANO_DATA;
-/* just in case we ever get here and there are no problems */
- case 0: return 0;
-
-
- default:
- fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno);
- return WSAEOPNOTSUPP;
- }
-}
-
-
-static void herrno_to_wsaerrno(void)
-{
- wsa_errno = wsaherrno();
-}
-
-
-static void convert_sockopt(INT *level, INT *optname)
-{
-/* $%#%!#! why couldn't they use the same values for both winsock and unix ? */
-
- switch (*level) {
- case -1:
- *level = SOL_SOCKET;
- switch (*optname) {
- case 0x01: *optname = SO_DEBUG;
- break;
- case 0x04: *optname = SO_REUSEADDR;
- break;
- case 0x08: *optname = SO_KEEPALIVE;
- break;
- case 0x10: *optname = SO_DONTROUTE;
- break;
- case 0x20: *optname = SO_BROADCAST;
- break;
- case 0x80: *optname = SO_LINGER;
- break;
- case 0x100: *optname = SO_OOBINLINE;
- break;
- case 0x1001: *optname = SO_SNDBUF;
- break;
- case 0x1002: *optname = SO_RCVBUF;
- break;
- case 0x1007: *optname = SO_ERROR;
- break;
- case 0x1008: *optname = SO_TYPE;
- break;
- default:
- fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
- break;
- }
- break;
- case 6: *optname = IPPROTO_TCP;
- }
-}
-
-#ifndef WINELIB
-static SEGPTR copy_stringlist(char **list)
-{
- SEGPTR *s_list;
- int i;
- for(i=0;list[i];i++)
- ;
- s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
- for(i=0;list[i];i++)
- {
- void *copy = scratch_alloc(strlen(list[i])+1);
- strcpy(copy,list[i]);
- s_list[i]=GET_SEG_PTR(copy);
- }
- s_list[i]=0;
- return GET_SEG_PTR(s_list);
-}
-
-
-static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
-{
- SEGPTR *addr_list;
- int i;
- ResetScratch();
- strcpy(heapent->hostname,host->h_name);
- heapent->h_name = GET_SEG_PTR(heapent->hostname);
- /* Convert aliases. Have to create array with FAR pointers */
- if(!host->h_aliases)
- heapent->h_aliases = 0;
- else
- heapent->h_aliases = copy_stringlist(host->h_aliases);
-
- heapent->h_addrtype = host->h_addrtype;
- heapent->h_length = host->h_length;
- for(i=0;host->h_addr_list[i];i++)
- ;
- addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
- heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list);
- for(i=0;host->h_addr_list[i];i++)
- {
- void *addr=scratch_alloc(host->h_length);
- memcpy(addr,host->h_addr_list[i],host->h_length);
- addr_list[i]=GET_SEG_PTR(addr);
- }
- addr_list[i]=0;
-}
-
-static void CONVERT_PROTOENT(struct WIN_protoent *heapent,
- struct protoent *proto)
-{
- ResetScratch();
- heapent->p_name= scratch_strdup(proto->p_name);
- heapent->p_aliases=proto->p_aliases ?
- copy_stringlist(proto->p_aliases) : 0;
- heapent->p_proto = proto->p_proto;
-}
-
-static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
-{
- ResetScratch();
- heapent->s_name = scratch_strdup(serv->s_name);
- heapent->s_aliases = serv->s_aliases ?
- copy_stringlist(serv->s_aliases) : 0;
- heapent->s_port = serv->s_port;
- heapent->s_proto = scratch_strdup(serv->s_proto);
-}
-#else
-#define CONVERT_HOSTENT(a,b) memcpy(a, &b, sizeof(a))
-#define CONVERT_PROTOENT(a,b) memcpy(a, &b, sizeof(a))
-#define CONVERT_SERVENT(a,b) memcpy(a, &b, sizeof(a))
-#endif
-
-SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
-{
- int sock;
-
- dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return INVALID_SOCKET;
- }
-
- if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
- errno_to_wsaerrno();
- return INVALID_SOCKET;
- }
- return sock;
-}
-
-INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
-{
-
- dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
- dump_sockaddr(name);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (namelen < sizeof(*name)) {
- WSASetLastError(WSAEFAULT);
- return SOCKET_ERROR;
- }
-
- /* check the socket family */
- if ( ((struct sockaddr_in *)name)->sin_family != AF_INET ) {
- WSASetLastError(WSAEAFNOSUPPORT);
- return SOCKET_ERROR;
- }
-
- if (bind(s, name, namelen) < 0) {
- switch(errno) {
- case EBADF:
- WSASetLastError(WSAENOTSOCK);
- break;
- case EADDRNOTAVAIL:
- WSASetLastError(WSAEINVAL);
- break;
- default:
- errno_to_wsaerrno();
- break;
- }
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT WINSOCK_closesocket(SOCKET s)
-{
- dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- FD_CLR(s, &fd_in_use);
-
- if (close(s) < 0) {
- if (errno == EBADF)
- WSASetLastError(WSAENOTSOCK);
- else
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
-{
- dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
- dump_sockaddr(name);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (connect(s, name, namelen) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
-{
- dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
- dump_sockaddr(name);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (getpeername(s, name, (int *) namelen) < 0) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
-{
- dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (getsockname(s, name, (int *) namelen) < 0) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT
-WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
-{
- dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- convert_sockopt(&level, &optname);
-
- if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
- if (errno == EBADF)
- WSASetLastError(WSAENOTSOCK);
- else
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-u_long WINSOCK_htonl(u_long hostlong)
-{
- return( htonl(hostlong) );
-}
-
-u_short WINSOCK_htons(u_short hostshort)
-{
- return( htons(hostshort) );
-}
-
-u_long WINSOCK_inet_addr(char *cp)
-{
- return( inet_addr(cp) );
-}
-
-char *WINSOCK_inet_ntoa(struct in_addr in)
-{
- char *s;
-
-/* dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
-
- if ((s = inet_ntoa(in)) == NULL) {
- errno_to_wsaerrno();
- return NULL;
- }
-
- strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
-
- return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
-}
-
-INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
-{
- long newcmd;
- u_long *newargp;
- char *ctlname;
- dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- /* Why can't they all use the same ioctl numbers */
- newcmd=cmd;
- newargp=argp;
- ctlname=0;
- if(cmd == _IOR('f',127,u_long))
- {
- ctlname="FIONREAD";
- newcmd=FIONREAD;
- }else
- if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
- {
- ctlname="FIONBIO";
- newcmd=FIONBIO;
- }else
- if(cmd == _IOW('f',125,u_long))
- {
- ctlname="FIOASYNC";
- newcmd=FIOASYNC;
- }
-
- if(!ctlname)
- fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
- else
- dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
-
-
- if (ioctl(s, newcmd, newargp) < 0) {
- if (errno == EBADF)
- WSASetLastError(WSAENOTSOCK);
- else
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT WINSOCK_listen(SOCKET s, INT backlog)
-{
- dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (listen(s, backlog) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-u_long WINSOCK_ntohl(u_long netlong)
-{
- return( ntohl(netlong) );
-}
-
-u_short WINSOCK_ntohs(u_short netshort)
-{
- return( ntohs(netshort) );
-}
-
-INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
-{
- int length;
-
- dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if ((length = recv(s, buf, len, flags)) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return length;
-}
-
-INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
- struct sockaddr *from, int *fromlen)
-{
- int length;
-
- dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return length;
-}
-
-INT WINSOCK_select(INT nfds, WinSock_fd_set *ws_readfds,
- WinSock_fd_set *ws_writefds, WinSock_fd_set *ws_exceptfds,
- struct timeval *timeout)
-{
- int ret;
- int i;
- int count;
- int highfd;
- fd_set readfds,writefds,exceptfds;
- FD_ZERO(&readfds);
- FD_ZERO(&writefds);
- FD_ZERO(&exceptfds);
-
- dprintf_winsock(stddeb, "WSA_select called: nfds %d (ignored), ptr %8lx, ptr %8lx, ptr %8lx\n", nfds, (unsigned long) ws_readfds, (unsigned long) ws_writefds, (unsigned long) ws_exceptfds);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- dprintf_winsock(stddeb, "WSA_select: returning error WSANOTINITIALISED\n");
- return SOCKET_ERROR;
- }
-
-/* In some sort of attempt to be BSD-compatible, MS-Winsock accepts and
- discards the nfds parameter. However, the format of windoze's fd_sets
- is totally different from the BSD standard. So much for compatibility.
- Hence, we must convert the winsock array-of-ints fd_set to the UNIX
- bitmapped format. */
-
- if(ws_readfds!=NULL) {
- dprintf_winsock(stddeb, "readfds: (%d) ",ws_readfds->fd_count);
- for(i=0;i<(ws_readfds->fd_count);i++) {
- dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_readfds)[2]) )[i]);
- /*FD_SET(((SOCKET *)&(((char *)ws_readfds)[2]))[i], &readfds);*/
- FD_SET(ws_readfds->fd_array[i], &readfds);
- }
- dprintf_winsock(stddeb, "\n");
- } else {
- dprintf_winsock(stddeb, "readfds: (null)\n");
- }
- if(ws_writefds!=NULL) {
- dprintf_winsock(stddeb, "writefds: (%d) ",ws_writefds->fd_count);
- for(i=0;i<(ws_writefds->fd_count);i++) {
- dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_writefds)[2]) )[i]);
- /*FD_SET(((SOCKET *)&(((char *)ws_writefds)[2]))[i], &writefds);*/
- FD_SET(ws_writefds->fd_array[i], &writefds);
- }
- dprintf_winsock(stddeb, "\n");
- } else {
- dprintf_winsock(stddeb, "writefds: (null)\n");
- }
- if(ws_exceptfds!=NULL) {
- dprintf_winsock(stddeb, "exceptfds: (%d) ",ws_exceptfds->fd_count);
- for(i=0;i<(ws_exceptfds->fd_count);i++) {
- dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_exceptfds)[2]) )[i]);
- /*FD_SET(((SOCKET *)&(((char *)ws_exceptfds)[2]))[i], &exceptfds);*/
- FD_SET(ws_exceptfds->fd_array[i], &exceptfds);
- }
- dprintf_winsock(stddeb, "\n");
- } else {
- dprintf_winsock(stddeb, "exceptfds: (null)\n");
- }
-
- /* Make the select() call */
- dprintf_winsock(stddeb, "WSA_select: calling select()\n");
- highfd=256; /* We should count them, but this works */
- ret=select(highfd, &readfds, &writefds, &exceptfds, timeout);
- dprintf_winsock(stddeb, "WSA_select: select() returned %d\n",ret);
- if(ret<0) {
- errno_to_wsaerrno();
- dprintf_winsock(stddeb, "WSA_select returning: Error %d\n",SOCKET_ERROR);
- return SOCKET_ERROR;
- }
-
- /* update the winsock fd sets */
- if(ws_readfds!=NULL) {
- dprintf_winsock(stddeb, "readfds: ");
- count=0;
- for(i=0;i<highfd;i++) {
- if(FD_ISSET(i,&readfds)) {
- dprintf_winsock(stddeb, " %d",i);
- ws_readfds->fd_array[count++]=i;
- }
- }
- dprintf_winsock(stddeb, " (%d)\n",count);
- ws_readfds->fd_count=count;
- } else {
- dprintf_winsock(stddeb, "readfds: (null)\n");
- }
- if(ws_writefds!=NULL) {
- dprintf_winsock(stddeb, "writefds: ");
- count=0;
- for(i=0;i<highfd;i++) {
- if(FD_ISSET(i,&writefds)) {
- dprintf_winsock(stddeb, " %d",i);
- ws_writefds->fd_array[count++]=i;
- }
- }
- dprintf_winsock(stddeb, " (%d)\n",count);
- ws_writefds->fd_count=count;
- } else {
- dprintf_winsock(stddeb, "writefds: (null)\n");
- }
- if(ws_exceptfds!=NULL) {
- dprintf_winsock(stddeb, "exceptfds: ");
- count=0;
- for(i=0;i<highfd;i++) {
- if(FD_ISSET(i,&exceptfds)) {
- dprintf_winsock(stddeb, " %d",i);
- ws_exceptfds->fd_array[count++]=i;
- }
- }
- dprintf_winsock(stddeb, " (%d)\n",count);
- ws_exceptfds->fd_count=count;
- } else {
- dprintf_winsock(stddeb, "exceptfds: (null)\n");
- }
-
- dprintf_winsock(stddeb, "WSA_select returning: %d\n",ret);
- return(ret);
-}
-
-INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
-{
- int length;
-
- dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if ((length = send(s, buf, len, flags)) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return length;
-}
-
-INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
- struct sockaddr *to, INT tolen)
-{
- int length;
-
- dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return length;
-}
-
-INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval,
- INT optlen)
-{
- dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
- convert_sockopt(&level, &optname);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (setsockopt(s, level, optname, optval, optlen) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-INT WINSOCK_shutdown(SOCKET s, INT how)
-{
- dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (shutdown(s, how) < 0) {
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
-{
- int sock;
-
- dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return INVALID_SOCKET;
- }
-
- /* check the socket family */
- switch(af) {
- case AF_INET:
- case AF_UNSPEC:
- break;
- default:
- WSASetLastError(WSAEAFNOSUPPORT);
- return INVALID_SOCKET;
- break;
- }
-
- /* check the socket type */
- switch(type) {
- case SOCK_STREAM:
- case SOCK_DGRAM:
- case SOCK_RAW:
- break;
- default:
- WSASetLastError(WSAESOCKTNOSUPPORT);
- return INVALID_SOCKET;
- break;
- }
-
- /* check the protocol type */
- if ( protocol < 0 ) { /* don't support negative values */
- WSASetLastError(WSAEPROTONOSUPPORT);
- return INVALID_SOCKET;
- }
-
- if ( af == AF_UNSPEC) { /* did they not specify the address family? */
- switch(protocol) {
- case IPPROTO_TCP:
- if (type == SOCK_STREAM) {
- af = AF_INET;
- break;
- }
- case IPPROTO_UDP:
- if (type == SOCK_DGRAM) {
- af = AF_INET;
- break;
- }
- default:
- WSASetLastError(WSAEPROTOTYPE);
- return INVALID_SOCKET;
- break;
- }
- }
-
- if ((sock = socket(af, type, protocol)) < 0) {
- if (errno == EPERM) {
- /* non super-user wants a raw socket */
- fprintf(stderr, "WSA_socket: not enough privileges\n");
- WSASetLastError(WSAESOCKTNOSUPPORT);
- } else
- errno_to_wsaerrno();
- dprintf_winsock(stddeb, "WSA_socket: failed !\n");
- return INVALID_SOCKET;
- }
-
- if (sock > WINSOCK_MAX_SOCKETS) {
- /* we only support socket numbers up to WINSOCK_MAX_SOCKETS.
- * The return value indicates no more descriptors are available
- */
- WSASetLastError(WSAEMFILE);
- return INVALID_SOCKET;
- }
-
- FD_SET(sock, &fd_in_use);
-
- dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
- return sock;
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
-{
- struct hostent *host;
-
- dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- if ((host = gethostbyaddr(addr, len, type)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return NULL;
- }
- CONVERT_HOSTENT(&Heap->hostent_addr, host);
-
- return GET_SEG_PTR(&Heap->hostent_addr);
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyname(const char *name)
-{
- struct hostent *host;
-
- dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- if ((host = gethostbyname(name)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return NULL;
- }
- CONVERT_HOSTENT(&Heap->hostent_name, host);
-
- return GET_SEG_PTR(&Heap->hostent_name);
-}
-
-INT WINSOCK_gethostname(char *name, INT namelen)
-{
- dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- if (gethostname(name, namelen) < 0) {
- if (errno == EINVAL)
- WSASetLastError(WSAEFAULT);
- else
- errno_to_wsaerrno();
- return SOCKET_ERROR;
- }
- return 0;
-}
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobyname(char *name)
-{
- struct protoent *proto;
-
- dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- if ((proto = getprotobyname(name)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return NULL;
- }
- CONVERT_PROTOENT(&Heap->protoent_name, proto);
-
- return GET_SEG_PTR(&Heap->protoent_name);
-}
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobynumber(INT number)
-{
- struct protoent *proto;
-
- dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- if ((proto = getprotobynumber(number)) == NULL) {
-#if 0
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
-#endif
- WSASetLastError(WSANO_DATA);
- return NULL;
- }
- CONVERT_PROTOENT(&Heap->protoent_number, proto);
-
- return GET_SEG_PTR(&Heap->protoent_number);
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
-{
- struct servent *service;
-
- if (proto == NULL)
- proto = "tcp";
-
- dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- if ((service = getservbyname(name, proto)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return NULL;
- }
- CONVERT_SERVENT(&Heap->servent_name, service);
-
- return GET_SEG_PTR(&Heap->servent_name);
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
-{
- struct servent *service;
-
- dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- if ((service = getservbyport(port, proto)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- return NULL;
- }
- CONVERT_SERVENT(&Heap->servent_port, service);
-
- return GET_SEG_PTR(&Heap->servent_port);
-}
-
-/******************** winsock specific functions ************************
- *
- */
-static HANDLE16 new_handle = 1;
-
-static HANDLE16 AllocWSAHandle(void)
-{
- return new_handle++;
-}
-
-static void recv_message(int sig)
-{
- static struct ipc_packet message;
- int message_is_valid = 0;
- BOOL result;
-
- message.mtype = MTYPE;
-
- signal(SIGUSR1, recv_message);
- while (1) {
-
- if (!message_is_valid) {
- if (msgrcv(wine_key, (struct msgbuf*)&(message),
- IPC_PACKET_SIZE, 0 /*MTYPE*/, IPC_NOWAIT) == -1) {
- perror("wine: winsock: msgrcv");
- break;
- }
- }
-
- result = PostMessage(message.hWnd, message.wMsg,
- (WPARAM16)message.handle, message.lParam);
- if (result != FALSE) {
- message_is_valid = 1;
- break;
- }
- else
- message_is_valid = 0;
-
- }
-
- if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
- perror("wine: winsock: msgget");
-}
-
-
-static void send_message( HWND hWnd, u_int wMsg, HANDLE16 handle, long lParam)
-{
- struct ipc_packet message;
-
- message.mtype = MTYPE;
- message.handle = handle;
- message.hWnd = hWnd;
- message.wMsg = wMsg;
- message.lParam = lParam;
-
- if (msgsnd(wine_key, (struct msgbuf*)&(message),
- IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1)
- perror("wine: winsock: msgsnd");
-
- kill(getppid(), SIGUSR1);
-}
-
-
-HANDLE16 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr,
- INT len, INT type, LPSTR buf, INT buflen)
-{
- HANDLE16 handle;
- struct hostent *host;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return 0;
- }
-
- handle = AllocWSAHandle();
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return handle;
- } else {
- if ((host = gethostbyaddr(addr, len, type)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- send_message(hWnd, wMsg, handle, wsaerrno() << 16);
- exit(0);
- }
- memcpy(buf, host, buflen);
- send_message(hWnd, wMsg, handle, 0);
- exit(0);
- }
-}
-
-
-HANDLE16 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, LPCSTR name,
- LPSTR buf, INT buflen)
-{
- HANDLE16 handle;
- struct hostent *host;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return 0;
- }
-
- handle = AllocWSAHandle();
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return handle;
- } else {
- if ((host = gethostbyname(name)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- send_message(hWnd, wMsg, handle, wsaerrno() << 16);
- exit(0);
- }
- memcpy(buf, host, buflen);
- send_message(hWnd, wMsg, handle, 0);
- exit(0);
- }
-}
-
-
-HANDLE16 WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, LPCSTR name,
- LPSTR buf, INT buflen)
-{
- HANDLE16 handle;
- struct protoent *proto;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return 0;
- }
-
- handle = AllocWSAHandle();
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return handle;
- } else {
- if ((proto = getprotobyname(name)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- send_message(hWnd, wMsg, handle, wsaerrno() << 16);
- exit(0);
- }
- memcpy(buf, proto, buflen);
- send_message(hWnd, wMsg, handle, 0);
- exit(0);
- }
-}
-
-
-HANDLE16 WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number,
- LPSTR buf, INT buflen)
-{
- HANDLE16 handle;
- struct protoent *proto;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return 0;
- }
-
- handle = AllocWSAHandle();
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return handle;
- } else {
- if ((proto = getprotobynumber(number)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- send_message(hWnd, wMsg, handle, wsaerrno() << 16);
- exit(0);
- }
- memcpy(buf, proto, buflen);
- send_message(hWnd, wMsg, handle, 0);
- exit(0);
- }
-}
-
-
-HANDLE16 WSAAsyncGetServByName(HWND hWnd, u_int wMsg, LPCSTR name,
- LPCSTR proto, LPSTR buf, INT buflen)
-{
- HANDLE16 handle;
- struct servent *service;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return 0;
- }
-
- handle = AllocWSAHandle();
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return handle;
- } else {
- if ((service = getservbyname(name, proto)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- send_message(hWnd, wMsg, handle, wsaerrno() << 16);
- exit(0);
- }
- memcpy(buf, service, buflen);
- send_message(hWnd, wMsg, handle, 0);
- exit(0);
- }
-}
-
-
-HANDLE16 WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, LPCSTR proto,
- LPSTR buf, INT buflen)
-{
- HANDLE16 handle;
- struct servent *service;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return 0;
- }
-
- handle = AllocWSAHandle();
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return handle;
- } else {
- if ((service = getservbyport(port, proto)) == NULL) {
- if (h_errno < 0) {
- errno_to_wsaerrno();
- } else {
- herrno_to_wsaerrno();
- }
- send_message(hWnd, wMsg, handle, wsaerrno() << 16);
- exit(0);
- }
- memcpy(buf, service, buflen);
- send_message(hWnd, wMsg, handle, 0);
- exit(0);
- }
-}
-
-INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
-{
- long event;
- fd_set read_fds, write_fds, except_fds;
- int errors = 0;
- int newpid;
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %04x, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
-
- /* remove outstanding asyncselect() processes */
- /* kill */
-
- if (wMsg == 0 && lEvent == 0)
- return 0;
-
- newpid = fork();
- if (newpid) {
- dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
- return 0;
- } else {
- while (1) {
- FD_ZERO(&read_fds);
- FD_ZERO(&write_fds);
- FD_ZERO(&except_fds);
-
- if (lEvent & FD_READ)
- FD_SET(s, &read_fds);
- if (lEvent & FD_WRITE)
- FD_SET(s, &write_fds);
-
- fcntl(s, F_SETFL, O_NONBLOCK);
- if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) {
- errors = wsaerrno();
- }
-
- event = 0;
- if (FD_ISSET(s, &read_fds))
- event |= FD_READ;
- if (FD_ISSET(s, &write_fds))
- event |= FD_WRITE;
- send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors));
- }
- }
-}
-
-INT WSAFDIsSet(SOCKET fd, WinSock_fd_set *set)
-{
- int i = set->fd_count;
-
- dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
-
- while (i--)
- {
- if (set->fd_array[i] == fd)
- {
- dprintf_winsock(stddeb, "__WSAFDIsSet returning 1\n");
- return 1;
- }
- }
- dprintf_winsock(stddeb, "__WSAFDIsSet returning 0\n");
- return 0;
-}
-
-INT WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
-{
- dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %04x\n", hAsyncTaskHandle);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- return 0;
-}
-
-INT WSACancelBlockingCall(void)
-{
- dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- return 0;
-}
-
-INT WSAGetLastError(void)
-{
- dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
-
- return wsa_errno;
-}
-
-void WSASetLastError(INT iError)
-{
- dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
-
- /* technically, we should make sure that WINESockets
- * has been started up correctly. But since this function
- * is also used internally, it makes no sense.
- *
- *if (!wsa_initted) {
- * WSASetLastError(WSANOTINITIALISED);
- * return SOCKET_ERROR;
- *}
- */
-
- wsa_errno = iError;
-}
-
-BOOL WSAIsBlocking(void)
-{
- dprintf_winsock(stddeb, "WSA_IsBlocking\n");
-
- return 0;
-}
-
-FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
-{
- dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- BlockFunction = lpBlockFunc;
-
- return (FARPROC16) lpBlockFunc;
-}
-
-INT WSAUnhookBlockingHook(void)
-{
- dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return NULL;
- }
-
- BlockFunction = NULL;
-
- return 0;
-}
-
-#ifdef 0
-WSADATA WINSOCK_data = {
- 0x0101,
- 0x0101,
- "WINE Sockets",
-#ifdef linux
- "LINUX/i386",
-#elif defined(__NetBSD__)
- "NetBSD/i386",
-#elif defined(sunos)
- "SunOS",
-#elif defined(__FreeBSD__)
- "FreeBSD",
-#else
- "Unknown",
-#endif
- WINSOCK_MAX_SOCKETS,
- WINSOCK_MAX_UDPDG,
- NULL
-};
-#endif
-
-INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
-{
-
- WSADATA WINSOCK_data = {
- 0x0101,
- 0x0101,
- "WINE Sockets",
- #ifdef linux
- "Linux/i386",
- #elif defined(__NetBSD__)
- "NetBSD/i386",
- #elif defined(sunos)
- "SunOS",
- #elif defined(__FreeBSD__)
- "FreeBSD",
- #else
- "Unknown",
- #endif
- WINSOCK_MAX_SOCKETS,
- WINSOCK_MAX_UDPDG,
- NULL
- };
-
- dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
-
- if (LOBYTE(wVersionRequested) < 1 ||
- (LOBYTE(wVersionRequested) == 1 &&
- HIBYTE(wVersionRequested) < 1))
- return WSAVERNOTSUPPORTED;
-
- if (!lpWSAData)
- return WSAEINVAL;
-
- /* alloc winsock heap */
-
- if ((HeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
- return WSASYSNOTREADY;
-
- Heap = (struct WinSockHeap *) GlobalLock16(HeapHandle);
-
- /* return winsock information */
- memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
-
- /* ipc stuff */
-
- if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
- perror("wine: winsock: msgget");
-
- signal(SIGUSR1, recv_message);
-
- /* clear */
-
- FD_ZERO(&fd_in_use);
-
- /* increment our usage count */
- wsa_initted++;
- dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
- return(0);
-}
-
-INT WSACleanup(void)
-{
- int fd;
-
- dprintf_winsock(stddeb, "WSACleanup (%d)\n",getpid());
-
- if (!wsa_initted) {
- WSASetLastError(WSANOTINITIALISED);
- return SOCKET_ERROR;
- }
-
- /* decrement usage count */
- wsa_initted--;
-
- if (wsa_initted == 0) {
- if (wine_key)
- if (msgctl(wine_key, IPC_RMID, NULL) == -1)
- perror("wine: winsock: msgctl");
-
- for (fd = 0; fd != FD_SETSIZE; fd++)
- if (FD_ISSET(fd, &fd_in_use))
- close(fd);
-
- }
- return 0;
-}
-
-VOID
-WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) {
- fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
- x1,x2,x3,x4,x5,x6
- );
- fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
- x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
- );
- return;
-}