Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

840 lines
20 KiB

  1. #include <rrcm.h>
  2. #include <queue.h>
  3. // Forward declarations
  4. DWORD WINAPI WS1MsgThread (LPVOID );
  5. LRESULT CALLBACK WS1WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  6. BOOL StartWS1MsgThread();
  7. BOOL StopWS1MsgThread();
  8. void __stdcall SendRecvCompleteAPC(ULONG_PTR dw);
  9. class CWS2EmulSock;
  10. #define WM_WSA_READWRITE (WM_USER + 100)
  11. // structure used to store WSASendTo/WSARecvFrom parameters
  12. struct WSAIOREQUEST {
  13. WSAOVERLAPPED *pOverlapped;
  14. WSABUF wsabuf[2];
  15. DWORD dwBufCount;
  16. union {
  17. struct {
  18. struct sockaddr *pRecvFromAddr;
  19. LPINT pRecvFromLen;
  20. };
  21. struct sockaddr SendToAddr;
  22. };
  23. };
  24. // global Winsock emulation state
  25. struct WS2Emul {
  26. #define MAX_EMUL_SOCKETS 10
  27. CWS2EmulSock *m_pEmulSocks[MAX_EMUL_SOCKETS];
  28. int numSockets;
  29. HWND hWnd;
  30. HANDLE hMsgThread;
  31. HANDLE hAckEvent;
  32. // external crit sect serializes the WS2EmulXX apis
  33. // to make them multi-thread safe
  34. CRITICAL_SECTION extcs;
  35. // internal crit sect serializes access between
  36. // MsgThread and WS2EmulXX apis
  37. // Never claim extcs while holding intcs.
  38. // (Is there a more elegant way to do this?)
  39. CRITICAL_SECTION intcs;
  40. } g_WS2Emul;
  41. /*
  42. CWS2EmulSock -
  43. WS2 socket emulation class
  44. Manages queues of overlapped i/o requests
  45. */
  46. class CWS2EmulSock
  47. {
  48. public:
  49. CWS2EmulSock(int myIndex) : m_myIndex(myIndex), m_RecvThreadId(0),m_SendThreadId(0),
  50. m_hRecvThread(NULL), m_hSendThread(NULL), m_sock(INVALID_SOCKET)
  51. { ZeroMemory(&m_SendOverlapped, sizeof(m_SendOverlapped));}
  52. ;
  53. BOOL NewSock(int af, int type, int protocol);
  54. int Close();
  55. int RecvFrom(
  56. LPWSABUF lpBuffers,DWORD dwBufferCount, LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,
  57. struct sockaddr FAR * lpFrom, LPINT lpFromlen,
  58. LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
  59. int SendTo(
  60. LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent,DWORD dwFlags,
  61. const struct sockaddr FAR * lpTo, int iTolen,
  62. LPWSAOVERLAPPED lpOverlapped,LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
  63. LRESULT HandleMessage(WPARAM wParam, LPARAM lParam); // WS1 window msg handler
  64. SOCKET GetSocket() { return m_sock;}
  65. WSAOVERLAPPED *GetSendOverlapped() {return &m_SendOverlapped;}
  66. private:
  67. SOCKET m_sock; // real socket handle
  68. int m_myIndex; // fake socket handle
  69. QueueOf<WSAIOREQUEST> m_RecvQ; // queue of overlapped recv requests
  70. QueueOf<WSAIOREQUEST> m_SendQ; // queue of overlapped send requests
  71. WSAOVERLAPPED m_SendOverlapped; // used only for synchronous send calls
  72. // the following fields are used to issue Send/Recv APCs
  73. DWORD m_RecvThreadId;
  74. DWORD m_SendThreadId;
  75. HANDLE m_hRecvThread; // thread issuing receive requests
  76. HANDLE m_hSendThread; // thread issuing send requests
  77. };
  78. void WS2EmulInit()
  79. {
  80. InitializeCriticalSection(&g_WS2Emul.extcs);
  81. InitializeCriticalSection(&g_WS2Emul.intcs);
  82. }
  83. void WS2EmulTerminate()
  84. {
  85. DeleteCriticalSection(&g_WS2Emul.extcs);
  86. DeleteCriticalSection(&g_WS2Emul.intcs);
  87. }
  88. BOOL
  89. CWS2EmulSock::NewSock(int af,int type, int protocol)
  90. {
  91. m_sock = socket(af,type,protocol);
  92. if (m_sock != INVALID_SOCKET)
  93. {
  94. WSAAsyncSelect(m_sock, g_WS2Emul.hWnd, WM_WSA_READWRITE+m_myIndex, FD_READ|FD_WRITE);
  95. }
  96. return m_sock != INVALID_SOCKET;
  97. }
  98. int
  99. CWS2EmulSock::RecvFrom(
  100. LPWSABUF lpBuffers,
  101. DWORD dwBufferCount,
  102. LPDWORD lpNumberOfBytesRecvd,
  103. LPDWORD lpFlags,
  104. struct sockaddr FAR * lpFrom,
  105. LPINT lpFromlen,
  106. LPWSAOVERLAPPED lpOverlapped,
  107. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
  108. {
  109. WSAIOREQUEST ioreq;
  110. int error = 0;
  111. if (lpCompletionRoutine) {
  112. DWORD thid = GetCurrentThreadId();
  113. HANDLE hCurProcess;
  114. if (thid != m_RecvThreadId) {
  115. // need to create a thread handle for QueueUserAPC
  116. // typically this will only happen once
  117. if (!m_RecvQ.IsEmpty())
  118. {
  119. // dont allow simultaneous recv access by more than one thread
  120. error = WSAEINVAL;
  121. }
  122. else
  123. {
  124. if (m_hRecvThread)
  125. CloseHandle(m_hRecvThread);
  126. m_hRecvThread = NULL;
  127. hCurProcess = GetCurrentProcess();
  128. m_RecvThreadId = thid;
  129. if (!DuplicateHandle(
  130. hCurProcess, // handle to process with handle to duplicate
  131. GetCurrentThread(), // handle to duplicate
  132. hCurProcess, // handle to process to duplicate to
  133. &m_hRecvThread, // pointer to duplicate handle
  134. 0, // access for duplicate handle
  135. FALSE, // handle inheritance flag
  136. DUPLICATE_SAME_ACCESS // optional actions
  137. ))
  138. {
  139. error = WSAEINVAL;
  140. m_RecvThreadId = 0;
  141. }
  142. }
  143. }
  144. }
  145. if (error || dwBufferCount != 1 || !lpOverlapped)
  146. {
  147. WSASetLastError(WSAENOBUFS);
  148. return SOCKET_ERROR;
  149. }
  150. ioreq.pOverlapped = lpOverlapped;
  151. if (lpOverlapped) // cache away ptr to completion routine
  152. lpOverlapped->Pointer = lpCompletionRoutine;
  153. ioreq.pRecvFromAddr = lpFrom;
  154. ioreq.pRecvFromLen = lpFromlen;
  155. ioreq.wsabuf[0] = lpBuffers[0];
  156. ioreq.dwBufCount = dwBufferCount;
  157. m_RecvQ.Put(ioreq);
  158. //LOG((LOGMSG_RECVFROM1,(UINT)lpOverlapped));
  159. // signal WS1 send/recv thread
  160. PostMessage(g_WS2Emul.hWnd, WM_WSA_READWRITE+m_myIndex, m_sock, FD_READ);
  161. WSASetLastError(ERROR_IO_PENDING);
  162. return SOCKET_ERROR;
  163. }
  164. int CWS2EmulSock::SendTo(
  165. LPWSABUF lpBuffers,
  166. DWORD dwBufferCount,
  167. LPDWORD lpNumberOfBytesSent,
  168. DWORD dwFlags,
  169. const struct sockaddr FAR * lpTo,
  170. int iTolen,
  171. LPWSAOVERLAPPED lpOverlapped,
  172. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
  173. {
  174. WSAIOREQUEST ioreq;
  175. int error = 0;
  176. if (lpCompletionRoutine) {
  177. DWORD thid = GetCurrentThreadId();
  178. HANDLE hCurProcess;
  179. if (thid != m_SendThreadId) {
  180. // need to create a thread handle for QueueUserAPC
  181. if (!m_SendQ.IsEmpty())
  182. {
  183. // dont allow simultaneous send access by more than one thread
  184. error = WSAEINVAL;
  185. }
  186. else
  187. {
  188. if (m_hSendThread)
  189. CloseHandle(m_hSendThread);
  190. m_hSendThread = NULL;
  191. hCurProcess = GetCurrentProcess();
  192. m_SendThreadId = thid;
  193. if (!DuplicateHandle(
  194. hCurProcess, // handle to process with handle to duplicate
  195. GetCurrentThread(), // handle to duplicate
  196. hCurProcess, // handle to process to duplicate to
  197. &m_hSendThread, // pointer to duplicate handle
  198. 0, // access for duplicate handle
  199. FALSE, // handle inheritance flag
  200. DUPLICATE_SAME_ACCESS // optional actions
  201. ))
  202. {
  203. error = WSAEINVAL;
  204. m_SendThreadId = 0;
  205. }
  206. }
  207. }
  208. }
  209. if (error || dwBufferCount != 1 || iTolen != sizeof(struct sockaddr) || !lpOverlapped)
  210. {
  211. WSASetLastError(WSAEINVAL);
  212. return SOCKET_ERROR;
  213. }
  214. ioreq.pOverlapped = lpOverlapped;
  215. if (lpOverlapped) // cache away ptr to completion routine
  216. lpOverlapped->Pointer = lpCompletionRoutine;
  217. ioreq.SendToAddr = *lpTo;
  218. ioreq.wsabuf[0] = lpBuffers[0];
  219. ioreq.dwBufCount = dwBufferCount;
  220. m_SendQ.Put(ioreq);
  221. // signal WS1 send/recv thread
  222. PostMessage(g_WS2Emul.hWnd, WM_WSA_READWRITE+m_myIndex, m_sock, FD_WRITE);
  223. WSASetLastError(ERROR_IO_PENDING);
  224. return SOCKET_ERROR;
  225. }
  226. /*
  227. Close - close the socket and cancel pending i/o
  228. */
  229. int
  230. CWS2EmulSock::Close()
  231. {
  232. WSAIOREQUEST ioreq;
  233. int status;
  234. status = closesocket(m_sock);
  235. m_sock = NULL;
  236. while (m_SendQ.Get(&ioreq))
  237. {
  238. // complete the request
  239. ioreq.pOverlapped->Internal = WSA_OPERATION_ABORTED;
  240. // if there is a callback routine, its address is cached in pOverlapped->Offset
  241. if (ioreq.pOverlapped->Pointer)
  242. {
  243. QueueUserAPC(SendRecvCompleteAPC,m_hSendThread,(DWORD_PTR)ioreq.pOverlapped);
  244. }
  245. else
  246. {
  247. SetEvent((HANDLE)ioreq.pOverlapped->hEvent);
  248. }
  249. }
  250. while (m_RecvQ.Get(&ioreq))
  251. {
  252. // complete the request
  253. ioreq.pOverlapped->Internal = WSA_OPERATION_ABORTED;
  254. if (ioreq.pOverlapped->Pointer)
  255. {
  256. QueueUserAPC(SendRecvCompleteAPC,m_hRecvThread,(DWORD_PTR)ioreq.pOverlapped);
  257. }
  258. else
  259. {
  260. SetEvent((HANDLE)ioreq.pOverlapped->hEvent);
  261. }
  262. }
  263. if (m_hSendThread)
  264. {
  265. CloseHandle(m_hSendThread);
  266. m_hSendThread = NULL;
  267. }
  268. if (m_hRecvThread)
  269. {
  270. CloseHandle(m_hRecvThread);
  271. m_hRecvThread = NULL;
  272. }
  273. return 0;
  274. }
  275. LRESULT
  276. CWS2EmulSock::HandleMessage(WPARAM sock, LPARAM lParam)
  277. {
  278. WORD wEvent= (WSAGETSELECTEVENT(lParam));
  279. WORD wError= (WSAGETSELECTERROR(lParam));
  280. int iRet;
  281. int status;
  282. WSAIOREQUEST ioreq;
  283. HANDLE hThread;
  284. // make sure the message is intended for this socket
  285. if ((SOCKET) sock != m_sock)
  286. return 0;
  287. // get the first RecvFrom or SendTo request, but leave it on the queue
  288. // in case the request blocks
  289. //if (wEvent == FD_READ)
  290. // LOG((LOGMSG_ONREAD1, (UINT)sock));
  291. if (wEvent == FD_READ && m_RecvQ.Peek(&ioreq))
  292. {
  293. //LOG((LOGMSG_ONREAD2, (UINT)ioreq.pOverlapped));
  294. iRet = recvfrom(m_sock, ioreq.wsabuf[0].buf, ioreq.wsabuf[0].len, 0, ioreq.pRecvFromAddr, ioreq.pRecvFromLen);
  295. }
  296. else if (wEvent == FD_WRITE && m_SendQ.Peek(&ioreq))
  297. {
  298. iRet = sendto(m_sock, ioreq.wsabuf[0].buf, ioreq.wsabuf[0].len, 0, &ioreq.SendToAddr, sizeof(ioreq.SendToAddr));
  299. }
  300. else // some other event or no queued request
  301. return 1;
  302. // complete send and recv
  303. if(iRet >=0)
  304. {
  305. status = 0;
  306. ioreq.pOverlapped->InternalHigh = iRet; // numBytesReceived
  307. } else {
  308. // error (or "would block") case falls out here
  309. ASSERT(iRet == SOCKET_ERROR);
  310. status = WSAGetLastError();
  311. ioreq.pOverlapped->InternalHigh = 0;
  312. }
  313. // check the error - it could be blocking
  314. if (status != WSAEWOULDBLOCK)
  315. {
  316. ioreq.pOverlapped->Internal = status;
  317. // pull request off the queue
  318. if (wEvent == FD_READ)
  319. {
  320. m_RecvQ.Get(NULL);
  321. hThread = m_hRecvThread;
  322. //LOG((LOGMSG_ONREADDONE1, (UINT)ioreq.pOverlapped));
  323. }
  324. else // wEvent == FD_WRITE
  325. {
  326. m_SendQ.Get(NULL);
  327. hThread = m_hSendThread;
  328. }
  329. // complete the request
  330. if (ioreq.pOverlapped->Pointer)
  331. {
  332. // if there is a callback routine, its address is cached in pOverlapped->Offset
  333. QueueUserAPC(SendRecvCompleteAPC,hThread, (DWORD_PTR)ioreq.pOverlapped);
  334. }
  335. else
  336. {
  337. SetEvent((HANDLE)ioreq.pOverlapped->hEvent);
  338. }
  339. }
  340. return 1;
  341. }
  342. void __stdcall
  343. SendRecvCompleteAPC(ULONG_PTR dw)
  344. {
  345. WSAOVERLAPPED *pOverlapped = (WSAOVERLAPPED *)dw;
  346. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  347. = (LPWSAOVERLAPPED_COMPLETION_ROUTINE) pOverlapped->Pointer;
  348. //LOG((LOGMSG_RECVFROM2,(UINT)pOverlapped));
  349. lpCompletionRoutine((DWORD)pOverlapped->Internal, (DWORD)pOverlapped->InternalHigh, pOverlapped, 0);
  350. }
  351. inline
  352. CWS2EmulSock *
  353. EmulSockFromSocket(SOCKET s)
  354. {
  355. return ( ((UINT) s < MAX_EMUL_SOCKETS) ? g_WS2Emul.m_pEmulSocks[s] : NULL);
  356. }
  357. inline SOCKET MapSocket(SOCKET s)
  358. {
  359. return (((UINT) s < MAX_EMUL_SOCKETS) && g_WS2Emul.m_pEmulSocks[s] ? g_WS2Emul.m_pEmulSocks[s]->GetSocket() : INVALID_SOCKET);
  360. }
  361. SOCKET
  362. PASCAL
  363. WS2EmulSocket(
  364. int af,
  365. int type,
  366. int protocol,
  367. LPWSAPROTOCOL_INFO lpProtocolInfo,
  368. GROUP,
  369. DWORD)
  370. {
  371. SOCKET s = INVALID_SOCKET;
  372. int i;
  373. CWS2EmulSock *pESock;
  374. if (g_WS2Emul.numSockets == MAX_EMUL_SOCKETS)
  375. return s;
  376. EnterCriticalSection(&g_WS2Emul.extcs);
  377. if (af == FROM_PROTOCOL_INFO)
  378. af = lpProtocolInfo->iAddressFamily;
  379. if (type == FROM_PROTOCOL_INFO)
  380. type = lpProtocolInfo->iSocketType;
  381. if (protocol == FROM_PROTOCOL_INFO)
  382. protocol = lpProtocolInfo->iProtocol;
  383. for (i=0;i<MAX_EMUL_SOCKETS;i++)
  384. {
  385. if (g_WS2Emul.m_pEmulSocks[i] == NULL)
  386. {
  387. pESock = new CWS2EmulSock(i);
  388. if (pESock) {
  389. if (++g_WS2Emul.numSockets == 1)
  390. {
  391. StartWS1MsgThread();
  392. }
  393. if (pESock->NewSock(af,type,protocol))
  394. {
  395. g_WS2Emul.m_pEmulSocks[i] = pESock;
  396. s = (SOCKET)i;
  397. } else {
  398. delete pESock;
  399. if (--g_WS2Emul.numSockets == 0)
  400. {
  401. StopWS1MsgThread();
  402. }
  403. }
  404. }
  405. break;
  406. }
  407. }
  408. LeaveCriticalSection(&g_WS2Emul.extcs);
  409. return s;
  410. }
  411. int
  412. PASCAL
  413. WS2EmulRecvFrom(
  414. SOCKET s,
  415. LPWSABUF lpBuffers,
  416. DWORD dwBufferCount,
  417. LPDWORD lpNumberOfBytesRecvd,
  418. LPDWORD lpFlags,
  419. struct sockaddr FAR * lpFrom,
  420. LPINT lpFromlen,
  421. LPWSAOVERLAPPED lpOverlapped,
  422. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  423. )
  424. {
  425. CWS2EmulSock *pESock;
  426. int iret;
  427. EnterCriticalSection(&g_WS2Emul.extcs);
  428. if (pESock = EmulSockFromSocket(s))
  429. {
  430. EnterCriticalSection(&g_WS2Emul.intcs);
  431. iret = pESock->RecvFrom(lpBuffers, dwBufferCount, lpNumberOfBytesRecvd,
  432. lpFlags,
  433. lpFrom, lpFromlen,
  434. lpOverlapped, lpCompletionRoutine);
  435. LeaveCriticalSection(&g_WS2Emul.intcs);
  436. }
  437. else
  438. {
  439. WSASetLastError(WSAENOTSOCK);
  440. iret = SOCKET_ERROR;
  441. }
  442. LeaveCriticalSection(&g_WS2Emul.extcs);
  443. return iret;
  444. }
  445. /*----------------------------------------------------------------------------
  446. * Function: WS2EmulSendCB
  447. * Description: private Winsock callback
  448. * This is only called if WS2EmulSendTo is called in synchronous mode
  449. * (i.e.) lpOverlapped == NULL. In that case, the sync call is converted to async
  450. * using a private Overlapped struct, and the WS2EmulSendTo api blocks until
  451. * this routine sets the hEvent field to TRUE;
  452. * Input:
  453. *
  454. * Return: None
  455. *--------------------------------------------------------------------------*/
  456. void CALLBACK WS2EmulSendCB (DWORD dwError,
  457. DWORD cbTransferred,
  458. LPWSAOVERLAPPED lpOverlapped,
  459. DWORD dwFlags)
  460. {
  461. lpOverlapped->Internal = dwError;
  462. lpOverlapped->InternalHigh = cbTransferred;
  463. lpOverlapped->hEvent = (WSAEVENT) TRUE;
  464. }
  465. int
  466. PASCAL
  467. WS2EmulSendTo(
  468. SOCKET s,
  469. LPWSABUF lpBuffers,
  470. DWORD dwBufferCount,
  471. LPDWORD lpNumberOfBytesSent,
  472. DWORD dwFlags,
  473. const struct sockaddr FAR * lpTo,
  474. int iTolen,
  475. LPWSAOVERLAPPED lpOverlapped,
  476. LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  477. )
  478. {
  479. CWS2EmulSock *pESock;
  480. int iret;
  481. BOOL fSync = FALSE;
  482. EnterCriticalSection(&g_WS2Emul.extcs);
  483. if (pESock = EmulSockFromSocket(s))
  484. {
  485. if (!lpOverlapped)
  486. {
  487. // synchronous call - we use our own overlapped struct to issue the
  488. // send request.
  489. lpOverlapped = pESock->GetSendOverlapped();
  490. lpOverlapped->hEvent = (WSAEVENT) FALSE; // will be set to TRUE in Callback
  491. lpCompletionRoutine = &WS2EmulSendCB;
  492. fSync = TRUE;
  493. }
  494. EnterCriticalSection(&g_WS2Emul.intcs);
  495. iret = pESock->SendTo(lpBuffers, dwBufferCount, lpNumberOfBytesSent,
  496. dwFlags,
  497. lpTo, iTolen,
  498. lpOverlapped, lpCompletionRoutine);
  499. LeaveCriticalSection(&g_WS2Emul.intcs);
  500. if (fSync) {
  501. DWORD dwError;
  502. if (iret == SOCKET_ERROR)
  503. {
  504. dwError = WSAGetLastError();
  505. if (dwError != WSA_IO_PENDING) {
  506. // there was an error so there will not be a callback
  507. lpOverlapped->hEvent = (WSAEVENT) TRUE;
  508. lpOverlapped->Internal = dwError;
  509. }
  510. }
  511. // wait for the call to complete
  512. // WS2EmulSendCB sets the hEvent field to TRUE and sets the Internal field to
  513. // the completion status
  514. while (!lpOverlapped->hEvent)
  515. {
  516. dwError =SleepEx(5000,TRUE); // WARNING: sleeping inside a Critical Section
  517. ASSERT(dwError == WAIT_IO_COMPLETION);
  518. }
  519. WSASetLastError((int)lpOverlapped->Internal);
  520. if (lpNumberOfBytesSent)
  521. *lpNumberOfBytesSent = (DWORD)lpOverlapped->InternalHigh;
  522. iret = lpOverlapped->Internal ? SOCKET_ERROR : 0;
  523. }
  524. }
  525. else
  526. {
  527. WSASetLastError(WSAENOTSOCK);
  528. iret = SOCKET_ERROR;
  529. }
  530. LeaveCriticalSection(&g_WS2Emul.extcs);
  531. return iret;
  532. }
  533. int
  534. PASCAL
  535. WS2EmulCloseSocket(SOCKET s)
  536. {
  537. CWS2EmulSock *pESock;
  538. int iret;
  539. EnterCriticalSection(&g_WS2Emul.extcs);
  540. if (pESock = EmulSockFromSocket(s))
  541. {
  542. // shut out access to this socket
  543. // by the MsgThread
  544. EnterCriticalSection(&g_WS2Emul.intcs);
  545. g_WS2Emul.m_pEmulSocks[s] = NULL;
  546. pESock->Close();
  547. delete pESock;
  548. LeaveCriticalSection(&g_WS2Emul.intcs);
  549. if (--g_WS2Emul.numSockets == 0)
  550. {
  551. // cant stop the thread with while holding intcs
  552. StopWS1MsgThread();
  553. }
  554. iret = 0;
  555. }
  556. else
  557. {
  558. WSASetLastError(WSAENOTSOCK);
  559. iret = SOCKET_ERROR;
  560. }
  561. LeaveCriticalSection(&g_WS2Emul.extcs);
  562. return iret;
  563. }
  564. int
  565. PASCAL
  566. WS2EmulSetSockOpt(
  567. SOCKET s, int level,int optname,const char FAR * optval,int optlen)
  568. {
  569. return setsockopt(MapSocket(s), level, optname, optval, optlen);
  570. }
  571. int
  572. PASCAL
  573. WS2EmulBind( SOCKET s, const struct sockaddr FAR * name, int namelen)
  574. {
  575. return bind(MapSocket(s), name, namelen);
  576. }
  577. int
  578. PASCAL
  579. WS2EmulGetSockName( SOCKET s,
  580. struct sockaddr * name,
  581. int * namelen )
  582. {
  583. return getsockname(MapSocket(s), name, namelen);
  584. }
  585. int
  586. PASCAL
  587. WS2EmulHtonl(
  588. SOCKET s,
  589. u_long hostlong,
  590. u_long FAR * lpnetlong
  591. )
  592. {
  593. *lpnetlong = htonl(hostlong);
  594. return 0;
  595. }
  596. int
  597. PASCAL
  598. WS2EmulHtons(
  599. SOCKET s,
  600. u_short hostshort,
  601. u_short FAR * lpnetshort
  602. )
  603. {
  604. *lpnetshort = htons(hostshort);
  605. return 0;
  606. }
  607. int
  608. PASCAL
  609. WS2EmulNtohl(
  610. SOCKET s,
  611. u_long netlong,
  612. u_long FAR * lphostlong
  613. )
  614. {
  615. *lphostlong = ntohl(netlong);
  616. return 0;
  617. }
  618. int
  619. PASCAL
  620. WS2EmulNtohs(
  621. SOCKET s,
  622. u_short netshort,
  623. u_short FAR * lphostshort
  624. )
  625. {
  626. *lphostshort = ntohs(netshort);
  627. return 0;
  628. }
  629. int
  630. PASCAL
  631. WS2EmulGetHostName(char *name, int namelen)
  632. {
  633. return gethostname(name, namelen);
  634. }
  635. struct hostent FAR *
  636. PASCAL
  637. WS2EmulGetHostByName(const char * name)
  638. {
  639. return gethostbyname(name);
  640. }
  641. SOCKET
  642. PASCAL
  643. WS2EmulJoinLeaf(
  644. SOCKET s,
  645. const struct sockaddr FAR * name,
  646. int namelen,
  647. LPWSABUF lpCallerData,
  648. LPWSABUF lpCalleeData,
  649. LPQOS lpSQOS,
  650. LPQOS lpGQOS,
  651. DWORD dwFlags
  652. )
  653. {
  654. ASSERT(0);
  655. return (-1);
  656. }
  657. int
  658. PASCAL
  659. WS2EmulIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer,
  660. DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
  661. LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE
  662. )
  663. {
  664. ASSERT(0);
  665. return -1;
  666. }
  667. BOOL StartWS1MsgThread()
  668. {
  669. DWORD threadId;
  670. DWORD dwStatus;
  671. ASSERT(g_WS2Emul.hMsgThread == 0);
  672. g_WS2Emul.hAckEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  673. g_WS2Emul.hMsgThread = CreateThread(NULL,0, WS1MsgThread, 0, 0, &threadId);
  674. dwStatus = WaitForSingleObject(g_WS2Emul.hAckEvent,INFINITE);
  675. return dwStatus == WAIT_OBJECT_0;
  676. }
  677. BOOL StopWS1MsgThread()
  678. {
  679. if (g_WS2Emul.hMsgThread && g_WS2Emul.hWnd)
  680. {
  681. PostMessage(g_WS2Emul.hWnd, WM_CLOSE, 0, 0);
  682. WaitForSingleObject(g_WS2Emul.hMsgThread,INFINITE);
  683. CloseHandle(g_WS2Emul.hMsgThread);
  684. CloseHandle(g_WS2Emul.hAckEvent);
  685. g_WS2Emul.hMsgThread = NULL;
  686. g_WS2Emul.hAckEvent = NULL;
  687. }
  688. return TRUE;
  689. }
  690. LRESULT CALLBACK WS1WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  691. {
  692. int i;
  693. CWS2EmulSock *pESock;
  694. EnterCriticalSection(&g_WS2Emul.intcs);
  695. if (pESock = EmulSockFromSocket(msg - WM_WSA_READWRITE))
  696. {
  697. LRESULT l = pESock->HandleMessage(wParam, lParam);
  698. LeaveCriticalSection(&g_WS2Emul.intcs);
  699. return l;
  700. }
  701. LeaveCriticalSection(&g_WS2Emul.intcs);
  702. if (msg == WM_DESTROY)
  703. PostQuitMessage(0);
  704. return (DefWindowProc(hWnd, msg, wParam, lParam));
  705. }
  706. DWORD WINAPI WS1MsgThread (LPVOID )
  707. {
  708. HRESULT hr;
  709. BOOL fChange = FALSE;
  710. MSG msg;
  711. // Register hidden window class:
  712. WNDCLASS wcHidden =
  713. {
  714. 0L,
  715. WS1WindowProc,
  716. 0,
  717. 0,
  718. GetModuleHandle(NULL),
  719. NULL,
  720. NULL,
  721. NULL,
  722. NULL,
  723. "WS1EmulWindowClass"
  724. };
  725. if (RegisterClass(&wcHidden)) {
  726. // Create hidden window
  727. // Create a hidden window for event processing:
  728. g_WS2Emul.hWnd = ::CreateWindow( "WS1EmulWindowClass",
  729. "",
  730. WS_POPUP, // not visible!
  731. 0, 0, 0, 0,
  732. NULL,
  733. NULL,
  734. GetModuleHandle(NULL),
  735. NULL);
  736. }
  737. if(!g_WS2Emul.hWnd)
  738. {
  739. hr = GetLastError();
  740. goto CLEANUPEXIT;
  741. }
  742. //SetThreadPriority(m_hRecvThread, THREAD_PRIORITY_ABOVE_NORMAL);
  743. // This function is guaranteed to create a queue on this thread
  744. PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  745. // notify thread creator that we're ready to recv messages
  746. SetEvent(g_WS2Emul.hAckEvent);
  747. // Wait for control messages or Winsock messages directed to
  748. // our hidden window
  749. while (GetMessage(&msg, NULL, 0, 0)) {
  750. TranslateMessage(&msg);
  751. DispatchMessage(&msg);
  752. }
  753. g_WS2Emul.hWnd = NULL;
  754. hr = S_OK;
  755. CLEANUPEXIT:
  756. UnregisterClass("WS1EmulWindowClass",GetModuleHandle(NULL));
  757. SetEvent(g_WS2Emul.hAckEvent);
  758. return hr;
  759. }
  760.