/* * The WINSOCK routine gethostbyname has a bug in both FTP and NetManage * implementations which causes the blocking hook, if any, not to be * called. This routine attempts to work around the problem by using * the async routines to emulate the functionality of the synchronous * routines */ struct hostent *PASCAL krb_gethostbyname( const char *name) { HWND hwnd; char buf[MAXGETHOSTSTRUCT]; BOOL FARPROC blockinghook; WNDCLASS wc; static BOOL isregistered; blockinghook = WSASetBlockingHook(NULL); WSASetBlockingHook(blockinghook); if (blockinghook == NULL) return gethostbyname(name); if (RegisterWndClass() == NULL) return gethostbyname(name); if (!isregistered) { wc.style = 0; wc.lpfnWndProc = gethostbyname_wnd_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hlibinstance; wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = GETHOSTBYNAME_CLASS; if (!RegisterClass(&wc)) return gethostbyname(name); isregistered = TRUE; } hwnd = CreateWindow(GETHOSTBYNAME_CLASS, "", WS_OVERLAPPED, -100, -100, 0, 0, HWND_DESKTOP, NULL, hlibinstance, NULL); if (hwnd == NULL) return gethostbyname(name); htaskasync = WSAAsyncGetHostByName(hwnd, WM_ASYNC_COMPLETED, name, buf, sizeof(buf)); b = blockinghook(NULL); }
/* * Function: Set up a blocking hook function. * * Parameters: * timeout - # of seconds to block for before cancelling. */ void start_blocking_hook(int timeout) { FARPROC proc; if (isblocking) return; isblocking = TRUE; blocking_end_time = GetTickCount() + (1000 * timeout); #ifdef _WIN32 proc = WSASetBlockingHook(blocking_hook_proc); #else hook_instance = MakeProcInstance(blocking_hook_proc, hinstance); proc = WSASetBlockingHook(hook_instance); #endif assert(proc != NULL); }
void WINS_GetLocalAddress() { struct hostent *local = NULL; char buff[MAXHOSTNAMELEN]; unsigned long addr; if (myAddr != INADDR_ANY) { return; } if (pgethostname(buff, MAXHOSTNAMELEN) == SOCKET_ERROR) { return; } blocktime = Sys_FloatTime(); WSASetBlockingHook(BlockingHook); local = pgethostbyname(buff); WSAUnhookBlockingHook(); if (local == NULL) { return; } myAddr = *(int *)local->h_addr_list[0]; addr = ntohl(myAddr); sprintf(my_tcpip_address, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); }
/* * css_windows_shutdown() - * return: */ void css_windows_shutdown (void) { int err; #if 0 if (old_hook != NULL) { (void) WSASetBlockingHook (old_hook); } #endif if (wsa_Init_count > 0) { err = WSACleanup (); wsa_Init_count--; } }
/* * css_windows_startup() - * return: */ int css_windows_startup (void) { WORD wVersionRequested; WSADATA wsaData; int err; old_hook = NULL; css_Wsa_error = CSS_ER_WINSOCK_NOERROR; wVersionRequested = 0x101; err = WSAStartup (wVersionRequested, &wsaData); if (err != 0) { /* don't use WSAGetLastError since it has not been initialized. */ css_Wsa_error = CSS_ER_WINSOCK_STARTUP; er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CSS_WINSOCK_STARTUP, 1, err); return -1; } max_socket_fds = wsaData.iMaxSockets; #if 0 /* * Establish a blocking "hook" function to prevent Windows messages * from being dispatched when we block on reads. */ old_hook = WSASetBlockingHook ((FARPROC) css_windows_blocking_hook); if (old_hook == NULL) { /* couldn't set up our hook */ css_Wsa_error = CSS_ER_WINSOCK_BLOCKING_HOOK; er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_CSS_WINSOCK_STARTUP, 1, WSAGetLastError ()); (void) WSACleanup (); return -1; } #endif wsa_Init_count++; return 1; }
PGPError PGPSetSocketsIdleEventHandler( PGPEventHandlerProcPtr inCallback, PGPUserValue inUserData) { PGPRMWOLockStartWriting(&sIdleEventHandlerLock); if (!PGPThreadSetSpecific(sIdleEventHandlerIndex, inCallback)) { if (!PGPThreadSetSpecific(sIdleEventHandlerDataIndex, inUserData)) { if (inCallback != NULL) { WSASetBlockingHook(SocketsBlockingHook); } else { WSAUnhookBlockingHook(); } } else { (void) PGPThreadSetSpecific(sIdleEventHandlerIndex, NULL); } } PGPRMWOLockStopWriting(&sIdleEventHandlerLock); return kPGPError_NoErr; }
int WINS_Init(void) { int i; int err; char buff[MAXHOSTNAMELEN]; char *colon; struct hostent *local; struct qsockaddr addr; if (COM_CheckParm("-noudp")) return -1; if (!winsock_initialized) { err = WSAStartup(MAKEWORD(1,1), &winsockdata); if (err) { Con_SafePrintf("Winsock initialization failed.\n"); return -1; } } winsock_initialized++; /* determine my name & address */ myAddr.s_addr = htonl(INADDR_LOOPBACK); err = gethostname(buff, MAXHOSTNAMELEN); if (err) { Con_Printf("%s: WARNING: gethostname failed.\n", __func__); } else { buff[MAXHOSTNAMELEN - 1] = 0; blocktime = Sys_DoubleTime(); WSASetBlockingHook(BlockingHook); local = gethostbyname(buff); WSAUnhookBlockingHook(); if (!local) { Con_Printf("%s: WARNING: gethostbyname timed out.\n", __func__); } else if (local->h_addrtype != AF_INET) { Con_Printf("%s: address from gethostbyname not IPv4\n", __func__); } else { myAddr = *(struct in_addr *)local->h_addr_list[0]; } } Con_Printf ("UDP, Local address: %s\n", inet_ntoa(myAddr)); i = COM_CheckParm("-ip"); if (i && i < com_argc - 1) { bindAddr.s_addr = inet_addr(com_argv[i + 1]); if (bindAddr.s_addr == INADDR_NONE) Sys_Error("%s: %s is not a valid IP address", __func__, com_argv[i + 1]); Con_Printf("Binding to IP Interface Address of %s\n", com_argv[i + 1]); } else { bindAddr.s_addr = INADDR_NONE; } i = COM_CheckParm("-localip"); if (i && i < com_argc - 1) { localAddr.s_addr = inet_addr(com_argv[i + 1]); if (localAddr.s_addr == INADDR_NONE) Sys_Error("%s: %s is not a valid IP address", __func__, com_argv[i + 1]); Con_Printf("Advertising %s as the local IP in response packets\n", com_argv[i + 1]); } else { localAddr.s_addr = INADDR_NONE; } net_controlsocket = WINS_OpenSocket(0); if (net_controlsocket == -1) { Con_Printf("%s: Unable to open control socket\n", __func__); if (--winsock_initialized == 0) WSACleanup(); return -1; } broadcastaddr.sin_family = AF_INET; broadcastaddr.sin_addr.s_addr = INADDR_BROADCAST; broadcastaddr.sin_port = htons((unsigned short)net_hostport); WINS_GetSocketAddr(net_controlsocket, &addr); strcpy(my_tcpip_address, WINS_AddrToString(&addr)); colon = strrchr(my_tcpip_address, ':'); if (colon) *colon = 0; Con_Printf("Winsock TCP/IP Initialized (%s)\n", my_tcpip_address); tcpipAvailable = true; return net_controlsocket; }
/*********************************************************************** * WSASetBlockingHook (WINSOCK.109) */ FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc) { /* FIXME: should deal with 16-bit proc */ return (FARPROC16)WSASetBlockingHook( (FARPROC)lpBlockFunc ); }
DWORD WINAPI WsAsyncThread(IN PWSASYNCCONTEXT Context) { PWSASYNCBLOCK AsyncBlock; PLIST_ENTRY Entry; HANDLE AsyncEvent = Context->AsyncEvent; PLIST_ENTRY ListHead = &Context->AsyncQueue; /* Set the blocking hook */ WSASetBlockingHook((FARPROC)WsAsyncThreadBlockingHook); /* Loop */ while (TRUE) { /* Wait for the event */ WaitForSingleObject(AsyncEvent, INFINITE); /* Get the lock */ WsAsyncLock(); /* Process the queue */ while (ListHead->Flink != ListHead) { /* Remove this entry and get the async block */ Entry = RemoveHeadList(ListHead); AsyncBlock = CONTAINING_RECORD(Entry, WSASYNCBLOCK, AsyncQueue); /* Save the current task handle */ WsAsyncCurrentTaskHandle = AsyncBlock->TaskHandle; /* Release the lock */ WsAsyncUnlock(); /* Check which operation to do */ switch (AsyncBlock->Operation) { /* Get Host by Y */ case WsAsyncGetHostByAddr: case WsAsyncGetHostByName: /* Call the handler */ WsAsyncGetHost(AsyncBlock->TaskHandle, AsyncBlock->Operation, AsyncBlock->GetHost.hWnd, AsyncBlock->GetHost.wMsg, AsyncBlock->GetHost.ByWhat, AsyncBlock->GetHost.Length, AsyncBlock->GetHost.Type, AsyncBlock->GetHost.Buffer, AsyncBlock->GetHost.BufferLength); break; /* Get Proto by Y */ case WsAsyncGetProtoByNumber: case WsAsyncGetProtoByName: /* Call the handler */ WsAsyncGetProto(AsyncBlock->TaskHandle, AsyncBlock->Operation, AsyncBlock->GetProto.hWnd, AsyncBlock->GetProto.wMsg, AsyncBlock->GetHost.ByWhat, AsyncBlock->GetProto.Buffer, AsyncBlock->GetProto.BufferLength); break; /* Get Serv by Y */ case WsAsyncGetServByPort: case WsAsyncGetServByName: /* Call the handler */ WsAsyncGetServ(AsyncBlock->TaskHandle, AsyncBlock->Operation, AsyncBlock->GetServ.hWnd, AsyncBlock->GetServ.wMsg, AsyncBlock->GetServ.ByWhat, AsyncBlock->GetServ.Protocol, AsyncBlock->GetServ.Buffer, AsyncBlock->GetServ.BufferLength); break; /* Termination */ case WsAsyncTerminate: /* Clean up the extra reference */ WSACleanup(); /* Free the context block */ WsAsyncFreeBlock(AsyncBlock); /* Acquire the lock */ WsAsyncLock(); /* Loop the queue and flush it */ while (!IsListEmpty(ListHead)) { Entry = RemoveHeadList(ListHead); AsyncBlock = CONTAINING_RECORD(Entry, WSASYNCBLOCK, AsyncQueue); WsAsyncFreeBlock(AsyncBlock); } /* Release lock */ WsAsyncUnlock(); /* Close the event, free the Context */ CloseHandle(AsyncEvent); HeapFree(WsSockHeap, 0, Context); /* Remove the extra DLL reference and kill us */ FreeLibraryAndExitThread(WsAsyncDllHandle, 0); default: break; } /* Done processing */ WsAsyncCurrentTaskHandle = NULL; /* Free this block, get lock and reloop */ WsAsyncFreeBlock(AsyncBlock); WsAsyncLock(); } /* Release the lock */ WsAsyncUnlock(); } }
int WINS_Init (void) { int i; struct hostent *local = NULL; char buff[MAXHOSTNAMELEN]; struct qsockaddr addr; char *p; int r; WORD wVersionRequested; // initialize the Winsock function vectors (we do this instead of statically linking // so we can run on Win 3.1, where there isn't necessarily Winsock) hInst = LoadLibrary("wsock32.dll"); if (hInst == NULL) { Con_SafePrintf ("Failed to load winsock.dll\n"); winsock_lib_initialized = false; return -1; } winsock_lib_initialized = true; pWSAStartup = (void *)GetProcAddress(hInst, "WSAStartup"); pWSACleanup = (void *)GetProcAddress(hInst, "WSACleanup"); pWSAGetLastError = (void *)GetProcAddress(hInst, "WSAGetLastError"); psocket = (void *)GetProcAddress(hInst, "socket"); pioctlsocket = (void *)GetProcAddress(hInst, "ioctlsocket"); psetsockopt = (void *)GetProcAddress(hInst, "setsockopt"); precvfrom = (void *)GetProcAddress(hInst, "recvfrom"); psendto = (void *)GetProcAddress(hInst, "sendto"); pclosesocket = (void *)GetProcAddress(hInst, "closesocket"); pgethostname = (void *)GetProcAddress(hInst, "gethostname"); pgethostbyname = (void *)GetProcAddress(hInst, "gethostbyname"); pgethostbyaddr = (void *)GetProcAddress(hInst, "gethostbyaddr"); pgetsockname = (void *)GetProcAddress(hInst, "getsockname"); if (!pWSAStartup || !pWSACleanup || !pWSAGetLastError || !psocket || !pioctlsocket || !psetsockopt || !precvfrom || !psendto || !pclosesocket || !pgethostname || !pgethostbyname || !pgethostbyaddr || !pgetsockname) { Con_SafePrintf ("Couldn't GetProcAddress from winsock.dll\n"); return -1; } if (COM_CheckParm ("-noudp")) return -1; if (winsock_initialized == 0) { wVersionRequested = MAKEWORD(1, 1); r = pWSAStartup (MAKEWORD(1, 1), &winsockdata); if (r) { Con_SafePrintf ("Winsock initialization failed.\n"); return -1; } } winsock_initialized++; // determine my name & address if (pgethostname(buff, MAXHOSTNAMELEN) == 0) { blocktime = Sys_FloatTime(); WSASetBlockingHook(BlockingHook); local = pgethostbyname(buff); WSAUnhookBlockingHook(); if (local == NULL) { Con_DPrintf ("Winsock TCP/IP Initialization timed out.\n"); if (--winsock_initialized == 0) pWSACleanup (); return -1; } } if (local) { myAddr = *(int *)local->h_addr_list[0]; // if the quake hostname isn't set, set it to the machine name if (strcmp(hostname.string, "UNNAMED") == 0) { // see if it's a text IP address (well, close enough) for (p = buff; *p; p++) if ((*p < '0' || *p > '9') && *p != '.') break; // if it is a real name, strip off the domain; we only want the host if (*p) { for (i = 0; i < 15; i++) if (buff[i] == '.') break; buff[i] = 0; } Cvar_Set ("hostname", buff); } } if ((net_controlsocket = WINS_OpenSocket (0)) == -1) { Con_Printf("WINS_Init: Unable to open control socket\n"); if (--winsock_initialized == 0) pWSACleanup (); return -1; } ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET; ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST; ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((unsigned short)net_hostport); WINS_GetSocketAddr (net_controlsocket, &addr); strcpy(my_tcpip_address, WINS_AddrToString (&addr)); p = strrchr (my_tcpip_address, ':'); if (p) *p = 0; Con_Printf("Winsock TCP/IP Initialized\n"); tcpipAvailable = true; return net_controlsocket; }