Le mercredi 09 septembre 2009 à 21:41 -0700, Pavel Pergamenshchik a écrit : > On Wed, Sep 9, 2009 at 8:28 AM, Cedric Delfosse <cdelfo...@mandriva.com> > wrote: > > Hello, > > > > Twisted Python 8.2.0 on Windows 2000 gives me this TB when I try to use > > the IOCP reactor. Is it supported on this platform ? (Works very well on > > Windows XP) > > > > The instance's SvcRun() method failed > > File "win32serviceutil.pyc", line 805, in SvcRun > > File "server-win32.pyc", line 81, in SvcDoRun > > File "twisted\internet\iocpreactor\__init__.pyc", line 8, in <module> > > File "twisted\internet\iocpreactor\reactor.pyc", line 19, in <module> > > File "twisted\internet\iocpreactor\iocpsupport.pyc", line 12, in <module> > > File "twisted\internet\iocpreactor\iocpsupport.pyc", line 10, in __load > > File "iocpsupport.pyx", line 242, in iocpsupport > > <type 'exceptions.ValueError'>: Failed to initialize Winsock function > > vectors > > iocpreactor is not supported on Windows 2000. iocpreactor relies on > ConnectEx() API. It was introduced in Windows XP. It is, > theoretically, possible to work around it, but nobody has done so.
Hello, thanks a lot. Unfortunately I'm not used at all to Windows programming. I tried to use a library thats wrap missing API for Windows 2000, but with no luck (gpt some obscure DLL issues): http://win2kgaming.site90.com/phpBB2/viewtopic.php?t=7 Maybe the ConnectEx() API replacement used by this library could be a solution ? (see code attached to this mail) Regards, -- Cedric Delfosse Mandriva / Linbox 152, rue de Grigy - Technopole Metz 57070 METZ - FRANCE tel: +33 (0)3 87 50 87 90 http://mandriva.com
/* Windows 2000 XP API Wrapper Pack Copyright (C) 2008 OldCigarette This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _WIN32_WINNT 0x0500 #include <Winsock2.h> #include <WS2tcpip.h> #include <WSPiApi.h> #include <MSWSock.h> #include <windows.h> #include "../common/win2k_xp_debug.h" /*Debugging*/ int debugLevel; DbgPrintf_t DbgPrintf; GUID ConnectExGUID = WSAID_CONNECTEX; GUID DisconnectExGUID = WSAID_DISCONNECTEX; GUID TransmitFileGUID = WSAID_TRANSMITFILE; HANDLE hHeap = NULL; #define MALLOC(x) HeapAlloc(hHeap, 0, x) #define FREE(x) HeapFree(hHeap, 0, x) typedef struct _CONNECTEX_CONNECT_DATA { SOCKET s; PVOID lpSendBuffer; DWORD dwSendDataLength; LPOVERLAPPED lpOverlapped; WSAEVENT event; HANDLE WaitObject; } CONNECTEX_CONNECT_DATA; void FreeConnectData(CONNECTEX_CONNECT_DATA *data) { if(data->lpSendBuffer) FREE(data->lpSendBuffer); if(data->WaitObject) if(data->event != WSA_INVALID_EVENT) WSACloseEvent(data->event); FREE(data); } BOOL CALLBACK ConnectEx_CONNECT (PVOID lpParameter, BOOLEAN TimerOrWaitFired) { fd_set fdset; WSABUF wsabuf; DWORD sent, dwTemp; int r; BOOL ret = FALSE; CONNECTEX_CONNECT_DATA *data = (CONNECTEX_CONNECT_DATA *)lpParameter; if(data->WaitObject) UnregisterWait(data->WaitObject); //Do we have a connection? fdset.fd_count = 1; fdset.fd_array[0] = data->s; if(select(0, NULL, &fdset, NULL, NULL) == 1) { if(!data->lpSendBuffer) { ret = TRUE; goto cleanup; } //We are ready to send data wsabuf.len = data->dwSendDataLength; wsabuf.buf = data->lpSendBuffer; sent = 0; if(data->event == WSA_INVALID_EVENT) { //Blocking - will send everything r = WSASend(data->s, &wsabuf, 1, &sent, 0, NULL, NULL); if(r == SOCKET_ERROR && debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: ConnectEx_CONNECT blocking send failed 0x%08X\n", WSAGetLastError()); } else { r = WSAEventSelect(data->s, data->event, FD_WRITE); if(r == SOCKET_ERROR) { if(debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: Could not connect event to FD_WRITE 0x%08X\n", WSAGetLastError()); goto cleanup; } while(r != SOCKET_ERROR) { r = WSASend(data->s, &wsabuf, 1, &dwTemp, 0, NULL, NULL); if(r == SOCKET_ERROR && debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: ConnectEx_CONNECT blocking send failed 0x%08X\n", WSAGetLastError()); sent += dwTemp; if(sent >= data->dwSendDataLength) { ret = TRUE; goto cleanup; } wsabuf.buf += dwTemp; wsabuf.len -= dwTemp; WaitForSingleObject(data->event, INFINITE); } } } else { if(debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: ConnectEx_CONNECT socket is not ready\n"); } cleanup: if(data->lpOverlapped) WSASetEvent(data->lpOverlapped->hEvent); FreeConnectData(data); return ret; } CONNECTEX_CONNECT_DATA *CreateConnectData (SOCKET s, PVOID lpSendBuffer, DWORD dwSendDataLength, LPOVERLAPPED lpOverlapped, WSAEVENT event) { CONNECTEX_CONNECT_DATA *data; data = (CONNECTEX_CONNECT_DATA *)MALLOC(sizeof(CONNECTEX_CONNECT_DATA)); //Store the socket to send on data->s = s; //Copy the send buffer if(lpSendBuffer) { data->lpSendBuffer = (PVOID)MALLOC(dwSendDataLength); RtlCopyMemory(data->lpSendBuffer, lpSendBuffer, dwSendDataLength); data->dwSendDataLength = dwSendDataLength; } else { data->lpSendBuffer = NULL; data->dwSendDataLength = 0; } //Store the event we must close data->event = event; data->lpOverlapped = lpOverlapped; data->WaitObject = NULL; return data; } BOOL PASCAL XP_ConnectEx(SOCKET s, const struct sockaddr *name, int namelen, PVOID lpSendBuffer, DWORD dwSendDataLength, LPDWORD lpdwBytesSent, LPOVERLAPPED lpOverlapped) { int r; HANDLE h; BOOL ret; CONNECTEX_CONNECT_DATA *data; DWORD len = 0; WSAEVENT event = WSA_INVALID_EVENT; r = connect(s, name, namelen); if(r == SOCKET_ERROR) { if(WSAGetLastError() != WSAEWOULDBLOCK) return FALSE; //It's going to take us a bit to connect event = WSACreateEvent(); if(event == WSA_INVALID_EVENT) { if(debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: Could not create an event for ConnectEx 0x%08X\n", WSAGetLastError()); return FALSE; } data = CreateConnectData(s, lpSendBuffer, dwSendDataLength, lpOverlapped, event); if(!RegisterWaitForSingleObject(&data->WaitObject, event, ConnectEx_CONNECT, data, INFINITE, WT_EXECUTEINIOTHREAD|WT_EXECUTEONLYONCE)) { if(debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: Could not register event for ConnectEx 0x%08X\n", GetLastError()); WSACloseEvent(event); FreeConnectData(data); return FALSE; } r = WSAEventSelect(s, event, FD_CONNECT); if(r == SOCKET_ERROR) { if(debugLevel) DbgPrintf(DBG_WARN, S_YELLOW "ws2_32: Could not connect event to FD_CONNECT 0x%08X\n", WSAGetLastError()); WSACloseEvent(event); FreeConnectData(data); return FALSE; } WSASetLastError(ERROR_IO_PENDING); return FALSE; } data = CreateConnectData(s, lpSendBuffer, dwSendDataLength, lpOverlapped, WSA_INVALID_EVENT); ret = ConnectEx_CONNECT(data, FALSE); if(lpdwBytesSent) *lpdwBytesSent = dwSendDataLength; return ret; } /*http://www.microsoft.com/mspress/books/sampchap/5726.aspx However, for Windows 2000 or Windows NT 4.0 it is possible to call TransmitFile with a null filehandle and buffers but specify the disconnect and re-use flags, which will achieve the same results.*/ BOOL PASCAL XP_DisconnectEx(SOCKET s, LPOVERLAPPED lpOverlapped, DWORD dwFlags, DWORD dwReserved) { LPFN_TRANSMITFILE _TransmitFile; int r; DWORD bytes, flags; r = WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &TransmitFileGUID, sizeof(GUID), &_TransmitFile, sizeof(LPFN_TRANSMITFILE), &bytes, NULL, NULL); if(r == SOCKET_ERROR) return FALSE; flags = TF_DISCONNECT; if(dwFlags & TF_REUSE_SOCKET) flags |= TF_REUSE_SOCKET; return _TransmitFile(s, NULL, 0, 0, lpOverlapped, NULL, flags); } int WSAAPI XP_WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { int r; r = WSAIoctl(s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine); if(dwIoControlCode == SIO_GET_EXTENSION_FUNCTION_POINTER && lpvInBuffer && r == SOCKET_ERROR) { if(debugLevel) DbgPrintf(DBG_INFO, "WSAIoctl SIO_GET_EXTENSION_FUNCTION_POINTER GUID=0x%08X\n", *(DWORD *)lpvInBuffer); if(memcmp(lpvInBuffer, &ConnectExGUID, sizeof(GUID)) == 0) { SetLastError(ERROR_SUCCESS); if(cbOutBuffer >= 4 && lpvOutBuffer) *(LPFN_CONNECTEX *)lpvOutBuffer = XP_ConnectEx; if(lpcbBytesReturned) *lpcbBytesReturned = 4; r = 0; } else if(memcmp(lpvInBuffer, &DisconnectExGUID, sizeof(GUID)) == 0) { SetLastError(ERROR_SUCCESS); if(cbOutBuffer >= 4 && lpvOutBuffer) *(LPFN_DISCONNECTEX *)lpvOutBuffer = XP_DisconnectEx; if(lpcbBytesReturned) *lpcbBytesReturned = 4; r = 0; } else if(debugLevel) { DbgPrintf(DBG_ERROR, S_RED "WSAIoctl SIO_GET_EXTENSION_FUNCTION_POINTER GUID=0x%08X failed, WSALastError=0x%08X\n", *(DWORD *)lpvInBuffer, WSAGetLastError()); } } return r; } //Cheers to Microsoft for doing the hard work!!!! int WINAPI XP_getaddrinfo(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res) { return WspiapiLegacyGetAddrInfo(nodename, servname, hints, res); } void WINAPI XP_freeaddrinfo(struct addrinfo* ai) { WspiapiLegacyFreeAddrInfo(ai); } int WINAPI XP_getnameinfo(const struct sockaddr FAR* sa, socklen_t salen, char FAR* host, DWORD hostlen, char FAR* serv, DWORD servlen, int flags) { return WspiapiLegacyGetNameInfo(sa, salen, host, hostlen, serv, servlen, flags); } void WINAPI XP_FreeAddrInfoW(PADDRINFOW pAddrInfo) { //well you can't get anything yet } BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { DebugLevel_t DebugLevel; switch(fdwReason) { case DLL_PROCESS_ATTACH: if(!hHeap) hHeap = GetProcessHeap(); //Init debug data DbgPrintf = GetDbgPrintf(); DebugLevel = GetDebugLevel(); if(DebugLevel) debugLevel = DebugLevel(); else debugLevel = 0; if(DbgPrintf) DbgPrintf(DBG_ALWAYS, "ws2_32: WS2_32.DLL Wrapper Init\n"); break; } return TRUE; }
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python