Source code of Windows XP (NT5)
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.

1869 lines
45 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Wsraw.h
  5. Abstract:
  6. Support for database winsock calls for WOW.
  7. Author:
  8. David Treadwell (davidtr) 02-Oct-1992
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "wsdynmc.h"
  14. #define FIND_16_OFFSET_FROM_32(base16, base32, actual32) \
  15. ( (DWORD)base16 + ( (DWORD)actual32 - (DWORD)base32 ) )
  16. DWORD
  17. BytesInHostent32 (
  18. PHOSTENT Hostent32
  19. );
  20. DWORD
  21. CopyHostent32To16 (
  22. PHOSTENT16 Hostent16,
  23. VPHOSTENT16 VHostent16,
  24. int BufferLength,
  25. PHOSTENT Hostent32
  26. );
  27. DWORD
  28. BytesInProtoent32 (
  29. PPROTOENT Protoent32
  30. );
  31. DWORD
  32. CopyProtoent32To16 (
  33. PPROTOENT16 Protoent16,
  34. VPPROTOENT16 VProtoent16,
  35. int BufferLength,
  36. PPROTOENT Protoent32
  37. );
  38. DWORD
  39. BytesInServent32 (
  40. PSERVENT Servent32
  41. );
  42. DWORD
  43. CopyServent32To16 (
  44. PSERVENT16 Servent16,
  45. VPSERVENT16 VServent16,
  46. int BufferLength,
  47. PSERVENT Servent32
  48. );
  49. /*++
  50. GENERIC FUNCTION PROTOTYPE:
  51. ==========================
  52. ULONG FASTCALL WWS32<function name>(PVDMFRAME pFrame)
  53. {
  54. ULONG ul;
  55. register P<function name>16 parg16;
  56. GETARGPTR(pFrame, sizeof(<function name>16), parg16);
  57. <get any other required pointers into 16 bit space>
  58. ALLOCVDMPTR
  59. GETVDMPTR
  60. GETMISCPTR
  61. et cetera
  62. <copy any complex structures from 16 bit -> 32 bit space>
  63. <ALWAYS use the FETCHxxx macros>
  64. ul = GET<return type>16(<function name>(parg16->f1,
  65. :
  66. :
  67. parg16->f<n>);
  68. <copy any complex structures from 32 -> 16 bit space>
  69. <ALWAYS use the STORExxx macros>
  70. <free any pointers to 16 bit space you previously got>
  71. <flush any areas of 16 bit memory if they were written to>
  72. FLUSHVDMPTR
  73. FREEARGPTR(parg16);
  74. RETURN(ul);
  75. }
  76. NOTE:
  77. The VDM frame is automatically set up, with all the function parameters
  78. available via parg16->f<number>.
  79. Handles must ALWAYS be mapped for 16 -> 32 -> 16 space via the mapping tables
  80. laid out in WALIAS.C.
  81. Any storage you allocate must be freed (eventually...).
  82. Further to that - if a thunk which allocates memory fails in the 32 bit call
  83. then it must free that memory.
  84. Also, never update structures in 16 bit land if the 32 bit call fails.
  85. Be aware that the GETxxxPTR macros return the CURRENT selector-to-flat_memory
  86. mapping. Calls to some 32-bit functions may indirectly cause callbacks into
  87. 16-bit code. These may cause 16-bit memory to move due to allocations
  88. made in 16-bit land. If the 16-bit memory does move, the corresponding 32-bit
  89. ptr in WOW32 needs to be refreshed to reflect the NEW selector-to-flat_memory
  90. mapping.
  91. --*/
  92. ULONG FASTCALL WWS32gethostbyaddr(PVDMFRAME pFrame)
  93. {
  94. ULONG ul;
  95. register PGETHOSTBYADDR16 parg16;
  96. PDWORD paddr16;
  97. PHOSTENT hostent32;
  98. PHOSTENT16 hostent16;
  99. DWORD bytesRequired;
  100. DWORD addr32; // address must be in PF_INET format (length == 4 bytes)
  101. if ( !WWS32IsThreadInitialized ) {
  102. SetLastError( WSANOTINITIALISED );
  103. RETURN((ULONG)NULL);
  104. }
  105. GETARGPTR( pFrame, sizeof(GETHOSTBYADDR16), parg16 );
  106. GETVDMPTR( parg16->Address, sizeof(DWORD), paddr16 );
  107. addr32 = *paddr16; // copy the 4-byte address
  108. hostent32 = (PHOSTENT) (*wsockapis[WOW_GETHOSTBYADDR].lpfn)((CHAR *)&addr32,
  109. parg16->Length,
  110. parg16->Type);
  111. // Note: 16-bit callbacks resulting from above function
  112. // call may have caused 16-bit memory movement
  113. FREEVDMPTR(paddr16);
  114. FREEARGPTR(parg16);
  115. if ( hostent32 != NULL ) {
  116. GETVDMPTR( WWS32vHostent, MAXGETHOSTSTRUCT, hostent16 );
  117. bytesRequired = CopyHostent32To16(
  118. hostent16,
  119. WWS32vHostent,
  120. MAXGETHOSTSTRUCT,
  121. hostent32
  122. );
  123. ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
  124. FLUSHVDMPTR( WWS32vHostent, (USHORT) bytesRequired, hostent16 );
  125. FREEVDMPTR( hostent16 );
  126. ul = WWS32vHostent;
  127. } else {
  128. ul = 0;
  129. }
  130. FREEVDMPTR( paddr16 );
  131. FREEARGPTR(parg16);
  132. RETURN(ul);
  133. } // WWS32gethostbyaddr
  134. ULONG FASTCALL WWS32gethostbyname(PVDMFRAME pFrame)
  135. {
  136. ULONG ul;
  137. register PGETHOSTBYNAME16 parg16;
  138. PHOSTENT hostent32 = NULL;
  139. PHOSTENT16 hostent16;
  140. PSZ name32 = NULL;
  141. PSZ name16;
  142. DWORD bytesRequired;
  143. if ( !WWS32IsThreadInitialized ) {
  144. SetLastError( WSANOTINITIALISED );
  145. RETURN((ULONG)NULL);
  146. }
  147. GETARGPTR( pFrame, sizeof(GETHOSTBYNAME16), parg16 );
  148. GETVDMPTR( parg16->Name, 32, name16 );
  149. if(name16) {
  150. name32 = malloc_w(strlen(name16)+1);
  151. if ( name32 ) {
  152. strcpy(name32, name16);
  153. hostent32 = (PHOSTENT) (*wsockapis[WOW_GETHOSTBYNAME].lpfn)( name32 );
  154. free_w(name32);
  155. }
  156. }
  157. // Note: 16-bit callbacks resulting from above function
  158. // call may have caused 16-bit memory movement
  159. FREEVDMPTR(name16);
  160. FREEARGPTR(parg16);
  161. if ( hostent32 != NULL ) {
  162. GETVDMPTR( WWS32vHostent, MAXGETHOSTSTRUCT, hostent16 );
  163. bytesRequired = CopyHostent32To16(
  164. hostent16,
  165. WWS32vHostent,
  166. MAXGETHOSTSTRUCT,
  167. hostent32
  168. );
  169. ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
  170. FLUSHVDMPTR( WWS32vHostent, (USHORT) bytesRequired, hostent16 );
  171. FREEVDMPTR( hostent16 );
  172. ul = WWS32vHostent;
  173. } else {
  174. ul = 0;
  175. }
  176. RETURN(ul);
  177. } // WWS32gethostbyname
  178. ULONG FASTCALL WWS32gethostname(PVDMFRAME pFrame)
  179. {
  180. ULONG ul;
  181. register PGETHOSTNAME16 parg16;
  182. PCHAR name32 = NULL;
  183. PCHAR name16;
  184. INT NameLength;
  185. VPSZ vpszName;
  186. if ( !WWS32IsThreadInitialized ) {
  187. SetLastError( WSANOTINITIALISED );
  188. RETURN((ULONG)NULL);
  189. }
  190. GETARGPTR( pFrame, sizeof(GETHOSTNAME16), parg16 );
  191. vpszName = FETCHDWORD(parg16->Name);
  192. NameLength = INT32(parg16->NameLength);
  193. if(vpszName) {
  194. name32 = malloc_w(NameLength);
  195. }
  196. ul = GETWORD16( (*wsockapis[WOW_GETHOSTNAME].lpfn)( name32, NameLength ) );
  197. // Note: 16-bit callbacks resulting from above function
  198. // call may have caused 16-bit memory movement
  199. FREEVDMPTR(name16);
  200. FREEARGPTR(parg16);
  201. GETVDMPTR( vpszName, NameLength, name16 );
  202. if(name16 && name32) {
  203. strcpy(name16, name32);
  204. }
  205. FLUSHVDMPTR( vpszName, NameLength, name16 );
  206. FREEVDMPTR( name16 );
  207. FREEARGPTR(parg16);
  208. RETURN(ul);
  209. } // WWS32gethostname
  210. ULONG FASTCALL WWS32WSAAsyncGetHostByAddr(PVDMFRAME pFrame)
  211. {
  212. ULONG ul;
  213. register PWSAASYNCGETHOSTBYADDR16 parg16;
  214. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  215. PVOID buffer32;
  216. PDWORD paddr16;
  217. if ( !WWS32IsThreadInitialized ) {
  218. SetLastError( WSANOTINITIALISED );
  219. RETURN(0);
  220. }
  221. GETARGPTR( pFrame, sizeof(WSAASYNCGETHOSTBYADDR16), parg16 );
  222. GETVDMPTR( parg16->Address, sizeof(DWORD), paddr16 );
  223. //
  224. // Set up locals so we know how to clean up on exit.
  225. //
  226. context = NULL;
  227. buffer32 = NULL;
  228. ul = 0;
  229. //
  230. // Allocate a context block and 32-bit buffer to use for the request.
  231. //
  232. context = malloc_w( sizeof(*context) );
  233. if ( context == NULL ) {
  234. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  235. goto exit;
  236. }
  237. buffer32 = malloc_w( MAXGETHOSTSTRUCT );
  238. if ( context == NULL ) {
  239. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  240. goto exit;
  241. }
  242. //
  243. // Fill in entries in the context buffer.
  244. //
  245. context->Buffer32 = buffer32;
  246. context->vBuffer16 = parg16->Buffer;
  247. context->Buffer16Length = parg16->BufferLength;
  248. //
  249. // Enter a critical section to synchronize access to the context block
  250. // and their global list.
  251. //
  252. RtlEnterCriticalSection( &WWS32CriticalSection );
  253. context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETHOSTBYADDR].lpfn)(
  254. (HWND)HWND32(parg16->hWnd),
  255. (parg16->wMsg << 16) |
  256. WWS32_MESSAGE_ASYNC_GETHOST,
  257. (char *)paddr16,
  258. parg16->Length,
  259. parg16->Type,
  260. buffer32,
  261. MAXGETHOSTSTRUCT);
  262. if ( context->AsyncTaskHandle32 != 0 ) {
  263. //
  264. // The call succeeded so get a 16-bit task handle for this
  265. // request and place the context block on the global list. The
  266. // resources will be freed by WWS32PostAsyncGetHost.
  267. //
  268. ul = WWS32GetAsyncTaskHandle16( );
  269. context->AsyncTaskHandle16 = (HAND16)ul;
  270. InsertTailList(
  271. &WWS32AsyncContextBlockListHead,
  272. &context->ContextBlockListEntry
  273. );
  274. }
  275. RtlLeaveCriticalSection( &WWS32CriticalSection );
  276. exit:
  277. if ( ul == 0 ) {
  278. if ( context != NULL ) {
  279. free_w( (PVOID)context );
  280. }
  281. if ( buffer32 != NULL ) {
  282. free_w( buffer32 );
  283. }
  284. }
  285. FREEVDMPTR( paddr16 );
  286. FREEARGPTR( parg16 );
  287. RETURN(ul);
  288. } // WWS32WSAAsyncGetHostByAddr
  289. ULONG FASTCALL WWS32WSAAsyncGetHostByName(PVDMFRAME pFrame)
  290. {
  291. ULONG ul;
  292. register PWSAASYNCGETHOSTBYNAME16 parg16;
  293. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  294. PVOID buffer32;
  295. PCHAR name32;
  296. if ( !WWS32IsThreadInitialized ) {
  297. SetLastError( WSANOTINITIALISED );
  298. RETURN(0);
  299. }
  300. GETARGPTR( pFrame, sizeof(WSAASYNCGETHOSTBYNAME16), parg16 );
  301. GETVDMPTR( parg16->Name, 32, name32 );
  302. //
  303. // Set up locals so we know how to clean up on exit.
  304. //
  305. context = NULL;
  306. buffer32 = NULL;
  307. ul = 0;
  308. //
  309. // Allocate a context block and 32-bit buffer to use for the request.
  310. //
  311. context = malloc_w( sizeof(*context) );
  312. if ( context == NULL ) {
  313. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  314. goto exit;
  315. }
  316. buffer32 = malloc_w( MAXGETHOSTSTRUCT );
  317. if ( context == NULL ) {
  318. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  319. goto exit;
  320. }
  321. //
  322. // Fill in entries in the context buffer.
  323. //
  324. context->Buffer32 = buffer32;
  325. context->vBuffer16 = parg16->Buffer;
  326. context->Buffer16Length = parg16->BufferLength;
  327. //
  328. // Enter a critical section to synchronize access to the context block
  329. // and their global list.
  330. //
  331. RtlEnterCriticalSection( &WWS32CriticalSection );
  332. context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETHOSTBYNAME].lpfn)(
  333. (HWND)HWND32(parg16->hWnd),
  334. (parg16->wMsg << 16) |
  335. WWS32_MESSAGE_ASYNC_GETHOST,
  336. name32,
  337. buffer32,
  338. MAXGETHOSTSTRUCT
  339. );
  340. if ( context->AsyncTaskHandle32 != 0 ) {
  341. //
  342. // The call succeeded so get a 16-bit task handle for this
  343. // request and place the context block on the global list. The
  344. // resources will be freed by WWS32PostAsyncGetHost.
  345. //
  346. ul = WWS32GetAsyncTaskHandle16( );
  347. context->AsyncTaskHandle16 = (HAND16)ul;
  348. InsertTailList(
  349. &WWS32AsyncContextBlockListHead,
  350. &context->ContextBlockListEntry
  351. );
  352. }
  353. RtlLeaveCriticalSection( &WWS32CriticalSection );
  354. exit:
  355. if ( ul == 0 ) {
  356. if ( context != NULL ) {
  357. free_w( (PVOID)context );
  358. }
  359. if ( buffer32 != NULL ) {
  360. free_w( buffer32 );
  361. }
  362. }
  363. FREEVDMPTR( name32 );
  364. FREEARGPTR( parg16 );
  365. RETURN(ul);
  366. } // WWS32WSAAsyncGetHostByName
  367. BOOL
  368. WWS32PostAsyncGetHost (
  369. HWND hWnd,
  370. UINT Msg,
  371. WPARAM wParam,
  372. LPARAM lParam
  373. )
  374. {
  375. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  376. BOOL ret;
  377. PVOID buffer16;
  378. DWORD bytesRequired;
  379. context = WWS32FindAndRemoveAsyncContext( (HANDLE)wParam );
  380. ASSERT( context != NULL );
  381. //
  382. // If the call was successful, copy the 32-bit buffer to the
  383. // 16-bit buffer specified by the application.
  384. //
  385. if ( WSAGETASYNCERROR( lParam ) == 0 ) {
  386. //
  387. // Copy the 32-bit structure to 16-bit buffer.
  388. //
  389. GETVDMPTR( context->vBuffer16, context->Buffer16Length, buffer16 );
  390. bytesRequired = CopyHostent32To16(
  391. buffer16,
  392. context->vBuffer16,
  393. context->Buffer16Length,
  394. context->Buffer32
  395. );
  396. //
  397. // If the application's buffer was too small, return an error
  398. // and information aqbout the buffer size required.
  399. //
  400. if ( bytesRequired > context->Buffer16Length ) {
  401. lParam = WSAMAKEASYNCREPLY( (WORD)bytesRequired, WSAENOBUFS );
  402. }
  403. }
  404. //
  405. // Post the completion message to the 16-bit application.
  406. //
  407. ret = PostMessage(
  408. hWnd,
  409. Msg >> 16,
  410. context->AsyncTaskHandle16,
  411. lParam
  412. );
  413. //
  414. // Free resources and return.
  415. //
  416. free_w( context->Buffer32 );
  417. free_w( (PVOID)context );
  418. return ret;
  419. } // WWS32PostAsyncGetHost
  420. DWORD
  421. CopyHostent32To16 (
  422. PHOSTENT16 Hostent16,
  423. VPHOSTENT16 VHostent16,
  424. int BufferLength,
  425. PHOSTENT Hostent32
  426. )
  427. {
  428. DWORD requiredBufferLength;
  429. DWORD bytesFilled;
  430. PCHAR currentLocation = (PCHAR)Hostent16;
  431. DWORD aliasCount;
  432. DWORD addressCount;
  433. DWORD i;
  434. VPBYTE *addrList16;
  435. VPSZ *aliases16;
  436. //
  437. // Determine how many bytes are needed to fully copy the structure.
  438. //
  439. requiredBufferLength = BytesInHostent32( Hostent32 );
  440. //
  441. // Copy over the hostent structure if it fits.
  442. //
  443. bytesFilled = sizeof(*Hostent32);
  444. if ( bytesFilled > (DWORD)BufferLength ) {
  445. return requiredBufferLength;
  446. }
  447. STOREWORD( Hostent16->h_addrtype, Hostent32->h_addrtype );
  448. STOREWORD( Hostent16->h_length, Hostent32->h_length );
  449. currentLocation = (PCHAR)Hostent16 + bytesFilled;
  450. //
  451. // Count the host's aliases and set up an array to hold pointers to
  452. // them.
  453. //
  454. for ( aliasCount = 0;
  455. Hostent32->h_aliases[aliasCount] != NULL;
  456. aliasCount++ );
  457. bytesFilled += (aliasCount+1) * sizeof(char FAR *);
  458. if ( bytesFilled > (DWORD)BufferLength ) {
  459. Hostent32->h_aliases = NULL;
  460. return requiredBufferLength;
  461. }
  462. Hostent16->h_aliases =
  463. FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation );
  464. aliases16 = (VPSZ *)currentLocation;
  465. currentLocation = (PCHAR)Hostent16 + bytesFilled;
  466. //
  467. // Count the host's addresses and set up an array to hold pointers to
  468. // them.
  469. //
  470. for ( addressCount = 0;
  471. Hostent32->h_addr_list[addressCount] != NULL;
  472. addressCount++ );
  473. bytesFilled += (addressCount+1) * sizeof(void FAR *);
  474. if ( bytesFilled > (DWORD)BufferLength ) {
  475. Hostent32->h_addr_list = NULL;
  476. return requiredBufferLength;
  477. }
  478. Hostent16->h_addr_list =
  479. FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation );
  480. addrList16 = (VPBYTE *)currentLocation;
  481. currentLocation = (PCHAR)Hostent16 + bytesFilled;
  482. //
  483. // Start filling in addresses. Do addresses before filling in the
  484. // host name and aliases in order to avoid alignment problems.
  485. //
  486. for ( i = 0; i < addressCount; i++ ) {
  487. bytesFilled += Hostent32->h_length;
  488. if ( bytesFilled > (DWORD)BufferLength ) {
  489. STOREDWORD( addrList16[i], 0 );
  490. return requiredBufferLength;
  491. }
  492. STOREDWORD(
  493. addrList16[i],
  494. FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation )
  495. );
  496. RtlMoveMemory(
  497. currentLocation,
  498. Hostent32->h_addr_list[i],
  499. Hostent32->h_length
  500. );
  501. currentLocation = (PCHAR)Hostent16 + bytesFilled;
  502. }
  503. STOREDWORD( addrList16[i], 0 );
  504. //
  505. // Copy the host name if it fits.
  506. //
  507. bytesFilled += strlen( Hostent32->h_name ) + 1;
  508. if ( bytesFilled > (DWORD)BufferLength ) {
  509. return requiredBufferLength;
  510. }
  511. Hostent16->h_name =
  512. FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation );
  513. RtlMoveMemory( currentLocation, Hostent32->h_name, strlen( Hostent32->h_name ) + 1 );
  514. currentLocation = (PCHAR)Hostent16 + bytesFilled;
  515. //
  516. // Start filling in aliases.
  517. //
  518. for ( i = 0; i < aliasCount; i++ ) {
  519. bytesFilled += strlen( Hostent32->h_aliases[i] ) + 1;
  520. if ( bytesFilled > (DWORD)BufferLength ) {
  521. STOREDWORD( aliases16[i], 0 );
  522. return requiredBufferLength;
  523. }
  524. STOREDWORD(
  525. aliases16[i],
  526. FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation )
  527. );
  528. RtlMoveMemory(
  529. currentLocation,
  530. Hostent32->h_aliases[i],
  531. strlen( Hostent32->h_aliases[i] ) + 1
  532. );
  533. currentLocation = (PCHAR)Hostent16 + bytesFilled;
  534. }
  535. STOREDWORD( aliases16[i], 0 );
  536. return requiredBufferLength;
  537. } // CopyHostentToBuffer
  538. DWORD
  539. BytesInHostent32 (
  540. PHOSTENT Hostent32
  541. )
  542. {
  543. DWORD total;
  544. int i;
  545. total = sizeof(HOSTENT);
  546. total += strlen( Hostent32->h_name ) + 1;
  547. total += sizeof(char *) + sizeof(char *);
  548. for ( i = 0; Hostent32->h_aliases[i] != NULL; i++ ) {
  549. total += strlen( Hostent32->h_aliases[i] ) + 1 + sizeof(char *);
  550. }
  551. for ( i = 0; Hostent32->h_addr_list[i] != NULL; i++ ) {
  552. total += Hostent32->h_length + sizeof(char *);
  553. }
  554. return total;
  555. } // BytesInHostent
  556. ULONG FASTCALL WWS32getprotobyname(PVDMFRAME pFrame)
  557. {
  558. ULONG ul;
  559. register PGETPROTOBYNAME16 parg16;
  560. PPROTOENT protoent32 = NULL;
  561. PPROTOENT16 protoent16;
  562. PSZ name32 = NULL;
  563. PBYTE name16;
  564. DWORD bytesRequired;
  565. if ( !WWS32IsThreadInitialized ) {
  566. SetLastError( WSANOTINITIALISED );
  567. RETURN((ULONG)NULL);
  568. }
  569. GETARGPTR( pFrame, sizeof(GETPROTOBYNAME16), parg16 );
  570. GETVDMPTR( parg16->Name, 32, name16 );
  571. if(name16) {
  572. name32 = malloc_w(strlen(name16)+1);
  573. if ( name32 ) {
  574. strcpy(name32, name16);
  575. protoent32 = (PPROTOENT) (*wsockapis[WOW_GETPROTOBYNAME].lpfn)( name32 );
  576. free_w( name32 );
  577. }
  578. }
  579. // Note: 16-bit callbacks resulting from above function
  580. // call may have caused 16-bit memory movement
  581. FREEVDMPTR(name16);
  582. FREEARGPTR(parg16);
  583. if ( protoent32 != NULL ) {
  584. GETVDMPTR( WWS32vProtoent, MAXGETHOSTSTRUCT, protoent16 );
  585. bytesRequired = CopyProtoent32To16(
  586. protoent16,
  587. WWS32vProtoent,
  588. MAXGETHOSTSTRUCT,
  589. protoent32
  590. );
  591. ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
  592. FLUSHVDMPTR( WWS32vProtoent, (USHORT) bytesRequired, protoent16 );
  593. FREEVDMPTR( protoent16 );
  594. ul = WWS32vProtoent;
  595. } else {
  596. ul = 0;
  597. }
  598. RETURN(ul);
  599. } // WWS32getprotobyname
  600. ULONG FASTCALL WWS32getprotobynumber(PVDMFRAME pFrame)
  601. {
  602. ULONG ul;
  603. register PGETPROTOBYNUMBER16 parg16;
  604. PPROTOENT protoent32;
  605. PPROTOENT16 protoent16;
  606. DWORD bytesRequired;
  607. if ( !WWS32IsThreadInitialized ) {
  608. SetLastError( WSANOTINITIALISED );
  609. RETURN((ULONG)NULL);
  610. }
  611. GETARGPTR( pFrame, sizeof(GETPROTOBYNUMBER16), parg16 );
  612. protoent32 = (PPROTOENT) (*wsockapis[WOW_GETPROTOBYNUMBER].lpfn)( parg16->Protocol );
  613. if ( protoent32 != NULL ) {
  614. GETVDMPTR( WWS32vProtoent, MAXGETHOSTSTRUCT, protoent16 );
  615. bytesRequired = CopyProtoent32To16(
  616. protoent16,
  617. WWS32vProtoent,
  618. MAXGETHOSTSTRUCT,
  619. protoent32
  620. );
  621. ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
  622. FLUSHVDMPTR( WWS32vProtoent, (USHORT) bytesRequired, protoent16 );
  623. FREEVDMPTR( protoent16 );
  624. ul = WWS32vProtoent;
  625. } else {
  626. ul = 0;
  627. }
  628. FREEARGPTR(parg16);
  629. RETURN(ul);
  630. } // WWS32getprotobynumber
  631. ULONG FASTCALL WWS32WSAAsyncGetProtoByName(PVDMFRAME pFrame)
  632. {
  633. ULONG ul;
  634. register PWSAASYNCGETPROTOBYNAME16 parg16;
  635. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  636. PVOID buffer32;
  637. PSZ name32;
  638. if ( !WWS32IsThreadInitialized ) {
  639. SetLastError( WSANOTINITIALISED );
  640. RETURN(0);
  641. }
  642. GETARGPTR( pFrame, sizeof(WSAASYNCGETPROTOBYNAME16), parg16 );
  643. GETVDMPTR( parg16->Name, 32, name32 );
  644. //
  645. // Set up locals so we know how to clean up on exit.
  646. //
  647. context = NULL;
  648. buffer32 = NULL;
  649. ul = 0;
  650. //
  651. // Allocate a context block and 32-bit buffer to use for the request.
  652. //
  653. context = malloc_w( sizeof(*context) );
  654. if ( context == NULL ) {
  655. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  656. goto exit;
  657. }
  658. buffer32 = malloc_w( MAXGETHOSTSTRUCT );
  659. if ( context == NULL ) {
  660. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  661. goto exit;
  662. }
  663. //
  664. // Fill in entries in the context buffer.
  665. //
  666. context->Buffer32 = buffer32;
  667. context->vBuffer16 = parg16->Buffer;
  668. context->Buffer16Length = parg16->BufferLength;
  669. //
  670. // Enter a critical section to synchronize access to the context block
  671. // and their global list.
  672. //
  673. RtlEnterCriticalSection( &WWS32CriticalSection );
  674. context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETPROTOBYNAME].lpfn)(
  675. (HWND)HWND32(parg16->hWnd),
  676. (parg16->wMsg << 16) |
  677. WWS32_MESSAGE_ASYNC_GETPROTO,
  678. name32,
  679. buffer32,
  680. MAXGETHOSTSTRUCT
  681. );
  682. if ( context->AsyncTaskHandle32 != 0 ) {
  683. //
  684. // The call succeeded so get a 16-bit task handle for this
  685. // request and place the context block on the global list. The
  686. // resources will be freed by WWS32PostAsyncGetProto.
  687. //
  688. ul = WWS32GetAsyncTaskHandle16( );
  689. context->AsyncTaskHandle16 = (HAND16)ul;
  690. InsertTailList(
  691. &WWS32AsyncContextBlockListHead,
  692. &context->ContextBlockListEntry
  693. );
  694. }
  695. RtlLeaveCriticalSection( &WWS32CriticalSection );
  696. exit:
  697. if ( ul == 0 ) {
  698. if ( context != NULL ) {
  699. free_w( (PVOID)context );
  700. }
  701. if ( buffer32 != NULL ) {
  702. free_w( buffer32 );
  703. }
  704. }
  705. FREEARGPTR( name32 );
  706. FREEARGPTR( parg16 );
  707. RETURN(ul);
  708. } // WWS32WSAAsyncGetProtoByName
  709. ULONG FASTCALL WWS32WSAAsyncGetProtoByNumber(PVDMFRAME pFrame)
  710. {
  711. ULONG ul;
  712. register PWSAASYNCGETPROTOBYNUMBER16 parg16;
  713. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  714. PVOID buffer32;
  715. if ( !WWS32IsThreadInitialized ) {
  716. SetLastError( WSANOTINITIALISED );
  717. RETURN(0);
  718. }
  719. GETARGPTR( pFrame, sizeof(WSAASYNCGETPROTOBYNUMBER16), parg16 );
  720. //
  721. // Set up locals so we know how to clean up on exit.
  722. //
  723. context = NULL;
  724. buffer32 = NULL;
  725. ul = 0;
  726. //
  727. // Allocate a context block and 32-bit buffer to use for the request.
  728. //
  729. context = malloc_w( sizeof(*context) );
  730. if ( context == NULL ) {
  731. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  732. goto exit;
  733. }
  734. buffer32 = malloc_w( MAXGETHOSTSTRUCT );
  735. if ( context == NULL ) {
  736. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  737. goto exit;
  738. }
  739. //
  740. // Fill in entries in the context buffer.
  741. //
  742. context->Buffer32 = buffer32;
  743. context->vBuffer16 = parg16->Buffer;
  744. context->Buffer16Length = parg16->BufferLength;
  745. //
  746. // Enter a critical section to synchronize access to the context block
  747. // and their global list.
  748. //
  749. RtlEnterCriticalSection( &WWS32CriticalSection );
  750. context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETPROTOBYNUMBER].lpfn)(
  751. (HWND)HWND32(parg16->hWnd),
  752. (parg16->wMsg << 16) |
  753. WWS32_MESSAGE_ASYNC_GETPROTO,
  754. parg16->Number,
  755. buffer32,
  756. MAXGETHOSTSTRUCT
  757. );
  758. if ( context->AsyncTaskHandle32 != 0 ) {
  759. //
  760. // The call succeeded so get a 16-bit task handle for this
  761. // request and place the context block on the global list. The
  762. // resources will be freed by WWS32PostAsyncGetProto.
  763. //
  764. ul = WWS32GetAsyncTaskHandle16( );
  765. context->AsyncTaskHandle16 = (HAND16)ul;
  766. InsertTailList(
  767. &WWS32AsyncContextBlockListHead,
  768. &context->ContextBlockListEntry
  769. );
  770. }
  771. RtlLeaveCriticalSection( &WWS32CriticalSection );
  772. exit:
  773. if ( ul == 0 ) {
  774. if ( context != NULL ) {
  775. free_w( (PVOID)context );
  776. }
  777. if ( buffer32 != NULL ) {
  778. free_w( buffer32 );
  779. }
  780. }
  781. FREEARGPTR( parg16 );
  782. RETURN(ul);
  783. } // WWS32WSAAsyncGetProtoByNumber
  784. BOOL
  785. WWS32PostAsyncGetProto (
  786. HWND hWnd,
  787. UINT Msg,
  788. WPARAM wParam,
  789. LPARAM lParam
  790. )
  791. {
  792. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  793. BOOL ret;
  794. PVOID buffer16;
  795. DWORD bytesRequired;
  796. context = WWS32FindAndRemoveAsyncContext( (HANDLE)wParam );
  797. ASSERT( context != NULL );
  798. //
  799. // If the call was successful, copy the 32-bit buffer to the
  800. // 16-bit buffer specified by the application.
  801. //
  802. if ( WSAGETASYNCERROR( lParam ) == 0 ) {
  803. //
  804. // Copy the 32-bit structure to 16-bit buffer.
  805. //
  806. GETVDMPTR( context->vBuffer16, context->Buffer16Length, buffer16 );
  807. bytesRequired = CopyProtoent32To16(
  808. buffer16,
  809. context->vBuffer16,
  810. context->Buffer16Length,
  811. context->Buffer32
  812. );
  813. //
  814. // If the application's buffer was too small, return an error
  815. // and information aqbout the buffer size required.
  816. //
  817. if ( bytesRequired > context->Buffer16Length ) {
  818. lParam = WSAMAKEASYNCREPLY( (WORD)bytesRequired, WSAENOBUFS );
  819. }
  820. }
  821. //
  822. // Post the completion message to the 16-bit application.
  823. //
  824. ret = PostMessage(
  825. hWnd,
  826. Msg >> 16,
  827. context->AsyncTaskHandle16,
  828. lParam
  829. );
  830. //
  831. // Free resources and return.
  832. //
  833. free_w( context->Buffer32 );
  834. free_w( (PVOID)context );
  835. return ret;
  836. } // WWS32PostAsyncGetProto
  837. DWORD
  838. CopyProtoent32To16 (
  839. PPROTOENT16 Protoent16,
  840. VPPROTOENT16 VProtoent16,
  841. int BufferLength,
  842. PPROTOENT Protoent32
  843. )
  844. {
  845. DWORD requiredBufferLength;
  846. DWORD bytesFilled;
  847. PCHAR currentLocation = (PCHAR)Protoent16;
  848. DWORD aliasCount;
  849. DWORD i;
  850. VPBYTE *aliases16;
  851. //
  852. // Determine how many bytes are needed to fully copy the structure.
  853. //
  854. requiredBufferLength = BytesInProtoent32( Protoent32 );
  855. //
  856. // Copy over the protoent structure if it fits.
  857. //
  858. bytesFilled = sizeof(*Protoent16);
  859. if ( bytesFilled > (DWORD)BufferLength ) {
  860. return requiredBufferLength;
  861. }
  862. STOREWORD( Protoent16->p_proto, Protoent32->p_proto );
  863. currentLocation = (PCHAR)Protoent16 + bytesFilled;
  864. //
  865. // Count the protocol's aliases and set up an array to hold pointers to
  866. // them.
  867. //
  868. for ( aliasCount = 0;
  869. Protoent32->p_aliases[aliasCount] != NULL;
  870. aliasCount++ );
  871. bytesFilled += (aliasCount+1) * sizeof(char FAR *);
  872. if ( bytesFilled > (DWORD)BufferLength ) {
  873. Protoent16->p_aliases = 0;
  874. return requiredBufferLength;
  875. }
  876. Protoent16->p_aliases =
  877. FIND_16_OFFSET_FROM_32( VProtoent16, Protoent16, currentLocation );
  878. aliases16 = (VPBYTE *)currentLocation;
  879. currentLocation = (PCHAR)Protoent16 + bytesFilled;
  880. //
  881. // Copy the protocol name if it fits.
  882. //
  883. bytesFilled += strlen( Protoent32->p_name ) + 1;
  884. if ( bytesFilled > (DWORD)BufferLength ) {
  885. return requiredBufferLength;
  886. }
  887. Protoent16->p_name =
  888. FIND_16_OFFSET_FROM_32( VProtoent16, Protoent16, currentLocation );
  889. RtlMoveMemory( currentLocation, Protoent32->p_name, strlen( Protoent32->p_name ) + 1 );
  890. currentLocation = (PCHAR)Protoent16 + bytesFilled;
  891. //
  892. // Start filling in aliases.
  893. //
  894. for ( i = 0; i < aliasCount; i++ ) {
  895. bytesFilled += strlen( Protoent32->p_aliases[i] ) + 1;
  896. if ( bytesFilled > (DWORD)BufferLength ) {
  897. STOREDWORD( aliases16[i], 0 );
  898. return requiredBufferLength;
  899. }
  900. STOREDWORD(
  901. aliases16[i],
  902. FIND_16_OFFSET_FROM_32( VProtoent16, Protoent16, currentLocation )
  903. );
  904. RtlMoveMemory(
  905. currentLocation,
  906. Protoent32->p_aliases[i],
  907. strlen( Protoent32->p_aliases[i] ) + 1
  908. );
  909. currentLocation = (PCHAR)Protoent16 + bytesFilled;
  910. }
  911. STOREDWORD( aliases16[i], 0 );
  912. return requiredBufferLength;
  913. } // CopyProtoent32To16
  914. DWORD
  915. BytesInProtoent32 (
  916. PPROTOENT Protoent32
  917. )
  918. {
  919. DWORD total;
  920. int i;
  921. total = sizeof(PROTOENT);
  922. total += strlen( Protoent32->p_name ) + 1;
  923. total += sizeof(char *);
  924. for ( i = 0; Protoent32->p_aliases[i] != NULL; i++ ) {
  925. total += strlen( Protoent32->p_aliases[i] ) + 1 + sizeof(char *);
  926. }
  927. return total;
  928. } // BytesInProtoent32
  929. ULONG FASTCALL WWS32getservbyname(PVDMFRAME pFrame)
  930. {
  931. ULONG ul;
  932. register PGETSERVBYNAME16 parg16;
  933. PSERVENT servent32;
  934. PSERVENT16 servent16;
  935. PSZ name32;
  936. PSZ protocol32;
  937. DWORD bytesRequired;
  938. if ( !WWS32IsThreadInitialized ) {
  939. SetLastError( WSANOTINITIALISED );
  940. RETURN((ULONG)NULL);
  941. }
  942. GETARGPTR( pFrame, sizeof(GETSERVBYNAME16), parg16 );
  943. GETVDMPTR( parg16->Name, 32, name32 );
  944. GETVDMPTR( parg16->Protocol, 32, protocol32 );
  945. servent32 = (PSERVENT) (*wsockapis[WOW_GETSERVBYNAME].lpfn)( name32, protocol32 );
  946. if ( servent32 != NULL ) {
  947. GETVDMPTR( WWS32vServent, MAXGETHOSTSTRUCT, servent16 );
  948. bytesRequired = CopyServent32To16(
  949. servent16,
  950. WWS32vServent,
  951. MAXGETHOSTSTRUCT,
  952. servent32
  953. );
  954. ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
  955. FLUSHVDMPTR( WWS32vServent, (USHORT) bytesRequired, servent16 );
  956. FREEVDMPTR( servent16 );
  957. ul = WWS32vServent;
  958. } else {
  959. ul = 0;
  960. }
  961. FREEVDMPTR( name32 );
  962. FREEVDMPTR( protocol32 );
  963. FREEARGPTR(parg16);
  964. RETURN(ul);
  965. } // WWS32getservbyname
  966. ULONG FASTCALL WWS32getservbyport(PVDMFRAME pFrame)
  967. {
  968. ULONG ul;
  969. register PGETSERVBYPORT16 parg16;
  970. PSERVENT servent32;
  971. PSERVENT16 servent16;
  972. PSZ protocol32;
  973. DWORD bytesRequired;
  974. if ( !WWS32IsThreadInitialized ) {
  975. SetLastError( WSANOTINITIALISED );
  976. RETURN((ULONG)NULL);
  977. }
  978. GETARGPTR( pFrame, sizeof(GETSERVBYPORT16), parg16 );
  979. GETVDMPTR( parg16->Protocol, 32, protocol32 );
  980. servent32 = (PSERVENT) (*wsockapis[WOW_GETSERVBYPORT].lpfn)( parg16->Port, protocol32 );
  981. if ( servent32 != NULL ) {
  982. GETVDMPTR( WWS32vServent, MAXGETHOSTSTRUCT, servent16 );
  983. bytesRequired = CopyServent32To16(
  984. servent16,
  985. WWS32vServent,
  986. MAXGETHOSTSTRUCT,
  987. servent32
  988. );
  989. ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
  990. FLUSHVDMPTR( WWS32vServent, (USHORT) bytesRequired, servent16 );
  991. FREEVDMPTR( servent16 );
  992. ul = WWS32vServent;
  993. } else {
  994. ul = 0;
  995. }
  996. FREEVDMPTR( protocol32 );
  997. FREEARGPTR(parg16);
  998. RETURN(ul);
  999. } // WWS32getservbyport
  1000. ULONG FASTCALL WWS32WSAAsyncGetServByPort(PVDMFRAME pFrame)
  1001. {
  1002. ULONG ul;
  1003. register PWSAASYNCGETSERVBYPORT16 parg16;
  1004. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  1005. PVOID buffer32;
  1006. PSZ proto32;
  1007. if ( !WWS32IsThreadInitialized ) {
  1008. SetLastError( WSANOTINITIALISED );
  1009. RETURN((ULONG)0);
  1010. }
  1011. GETARGPTR( pFrame, sizeof(WSAASYNCGETSERVBYPORT16), parg16 );
  1012. GETVDMPTR( parg16->Protocol, 32, proto32 );
  1013. //
  1014. // Set up locals so we know how to clean up on exit.
  1015. //
  1016. context = NULL;
  1017. buffer32 = NULL;
  1018. ul = 0;
  1019. //
  1020. // Allocate a context block and 32-bit buffer to use for the request.
  1021. //
  1022. context = malloc_w( sizeof(*context) );
  1023. if ( context == NULL ) {
  1024. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  1025. goto exit;
  1026. }
  1027. buffer32 = malloc_w( MAXGETHOSTSTRUCT );
  1028. if ( context == NULL ) {
  1029. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  1030. goto exit;
  1031. }
  1032. //
  1033. // Fill in entries in the context buffer.
  1034. //
  1035. context->Buffer32 = buffer32;
  1036. context->vBuffer16 = parg16->Buffer;
  1037. context->Buffer16Length = parg16->BufferLength;
  1038. //
  1039. // Enter a critical section to synchronize access to the context block
  1040. // and their global list.
  1041. //
  1042. RtlEnterCriticalSection( &WWS32CriticalSection );
  1043. context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETSERVBYPORT].lpfn)(
  1044. (HWND)HWND32(parg16->hWnd),
  1045. (parg16->wMsg << 16) |
  1046. WWS32_MESSAGE_ASYNC_GETSERV,
  1047. parg16->Port,
  1048. proto32,
  1049. buffer32,
  1050. MAXGETHOSTSTRUCT
  1051. );
  1052. if ( context->AsyncTaskHandle32 != 0 ) {
  1053. //
  1054. // The call succeeded so get a 16-bit task handle for this
  1055. // request and place the context block on the global list. The
  1056. // resources will be freed by WWS32PostAsyncGetServ.
  1057. //
  1058. ul = WWS32GetAsyncTaskHandle16( );
  1059. context->AsyncTaskHandle16 = (HAND16)ul;
  1060. InsertTailList(
  1061. &WWS32AsyncContextBlockListHead,
  1062. &context->ContextBlockListEntry
  1063. );
  1064. }
  1065. RtlLeaveCriticalSection( &WWS32CriticalSection );
  1066. exit:
  1067. if ( ul == 0 ) {
  1068. if ( context != NULL ) {
  1069. free_w( (PVOID)context );
  1070. }
  1071. if ( buffer32 != NULL ) {
  1072. free_w( buffer32 );
  1073. }
  1074. }
  1075. FREEARGPTR( proto32 );
  1076. FREEARGPTR( parg16 );
  1077. RETURN(ul);
  1078. } // WWS32WSAAsyncGetServByPort
  1079. ULONG FASTCALL WWS32WSAAsyncGetServByName(PVDMFRAME pFrame)
  1080. {
  1081. ULONG ul;
  1082. register PWSAASYNCGETSERVBYNAME16 parg16;
  1083. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  1084. PVOID buffer32;
  1085. PSZ name32;
  1086. PSZ proto32;
  1087. if ( !WWS32IsThreadInitialized ) {
  1088. SetLastError( WSANOTINITIALISED );
  1089. RETURN((ULONG)0);
  1090. }
  1091. GETARGPTR( pFrame, sizeof(WSAASYNCGETSERVBYNAME16), parg16 );
  1092. GETVDMPTR( parg16->Name, 32, name32 );
  1093. GETVDMPTR( parg16->Protocol, 32, proto32 );
  1094. //
  1095. // Set up locals so we know how to clean up on exit.
  1096. //
  1097. context = NULL;
  1098. buffer32 = NULL;
  1099. ul = 0;
  1100. //
  1101. // Allocate a context block and 32-bit buffer to use for the request.
  1102. //
  1103. context = malloc_w( sizeof(*context) );
  1104. if ( context == NULL ) {
  1105. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  1106. goto exit;
  1107. }
  1108. buffer32 = malloc_w( MAXGETHOSTSTRUCT );
  1109. if ( context == NULL ) {
  1110. (*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
  1111. goto exit;
  1112. }
  1113. //
  1114. // Fill in entries in the context buffer.
  1115. //
  1116. context->Buffer32 = buffer32;
  1117. context->vBuffer16 = parg16->Buffer;
  1118. context->Buffer16Length = parg16->BufferLength;
  1119. //
  1120. // Enter a critical section to synchronize access to the context block
  1121. // and their global list.
  1122. //
  1123. RtlEnterCriticalSection( &WWS32CriticalSection );
  1124. context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETSERVBYNAME].lpfn)(
  1125. (HWND)HWND32(parg16->hWnd),
  1126. (parg16->wMsg << 16) |
  1127. WWS32_MESSAGE_ASYNC_GETSERV,
  1128. name32,
  1129. proto32,
  1130. buffer32,
  1131. MAXGETHOSTSTRUCT
  1132. );
  1133. if ( context->AsyncTaskHandle32 != 0 ) {
  1134. //
  1135. // The call succeeded so get a 16-bit task handle for this
  1136. // request and place the context block on the global list. The
  1137. // resources will be freed by WWS32PostAsyncGetServ.
  1138. //
  1139. ul = WWS32GetAsyncTaskHandle16( );
  1140. context->AsyncTaskHandle16 = (HAND16)ul;
  1141. InsertTailList(
  1142. &WWS32AsyncContextBlockListHead,
  1143. &context->ContextBlockListEntry
  1144. );
  1145. }
  1146. RtlLeaveCriticalSection( &WWS32CriticalSection );
  1147. exit:
  1148. if ( ul == 0 ) {
  1149. if ( context != NULL ) {
  1150. free_w( (PVOID)context );
  1151. }
  1152. if ( buffer32 != NULL ) {
  1153. free_w( buffer32 );
  1154. }
  1155. }
  1156. FREEARGPTR( proto32 );
  1157. FREEARGPTR( name32 );
  1158. FREEARGPTR( parg16 );
  1159. RETURN(ul);
  1160. } // WWS32WSAAsyncGetServByName
  1161. BOOL
  1162. WWS32PostAsyncGetServ (
  1163. HWND hWnd,
  1164. UINT Msg,
  1165. WPARAM wParam,
  1166. LPARAM lParam
  1167. )
  1168. {
  1169. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  1170. BOOL ret;
  1171. PVOID buffer16;
  1172. DWORD bytesRequired;
  1173. context = WWS32FindAndRemoveAsyncContext( (HANDLE)wParam );
  1174. ASSERT( context != NULL );
  1175. //
  1176. // If the call was successful, copy the 32-bit buffer to the
  1177. // 16-bit buffer specified by the application.
  1178. //
  1179. if ( WSAGETASYNCERROR( lParam ) == 0 ) {
  1180. //
  1181. // Copy the 32-bit structure to 16-bit buffer.
  1182. //
  1183. GETVDMPTR( context->vBuffer16, context->Buffer16Length, buffer16 );
  1184. bytesRequired = CopyServent32To16(
  1185. buffer16,
  1186. context->vBuffer16,
  1187. context->Buffer16Length,
  1188. context->Buffer32
  1189. );
  1190. //
  1191. // If the application's buffer was too small, return an error
  1192. // and information aqbout the buffer size required.
  1193. //
  1194. if ( bytesRequired > context->Buffer16Length ) {
  1195. lParam = WSAMAKEASYNCREPLY( (WORD)bytesRequired, WSAENOBUFS );
  1196. }
  1197. }
  1198. //
  1199. // Post the completion message to the 16-bit application.
  1200. //
  1201. ret = PostMessage(
  1202. hWnd,
  1203. Msg >> 16,
  1204. context->AsyncTaskHandle16,
  1205. lParam
  1206. );
  1207. //
  1208. // Free resources and return.
  1209. //
  1210. free_w( context->Buffer32 );
  1211. free_w( (PVOID)context );
  1212. return ret;
  1213. } // WWS32PostAsyncGetServ
  1214. DWORD
  1215. CopyServent32To16 (
  1216. PSERVENT16 Servent16,
  1217. VPSERVENT16 VServent16,
  1218. int BufferLength,
  1219. PSERVENT Servent32
  1220. )
  1221. {
  1222. DWORD requiredBufferLength;
  1223. DWORD bytesFilled;
  1224. PCHAR currentLocation = (PCHAR)Servent16;
  1225. DWORD aliasCount;
  1226. DWORD i;
  1227. VPBYTE *aliases16;
  1228. //
  1229. // Determine how many bytes are needed to fully copy the structure.
  1230. //
  1231. requiredBufferLength = BytesInServent32( Servent32 );
  1232. //
  1233. // Copy over the servent structure if it fits.
  1234. //
  1235. bytesFilled = sizeof(*Servent16);
  1236. if ( bytesFilled > (DWORD)BufferLength ) {
  1237. return requiredBufferLength;
  1238. }
  1239. STOREWORD( Servent16->s_port, Servent32->s_port );
  1240. currentLocation = (PCHAR)Servent16 + bytesFilled;
  1241. //
  1242. // Count the service's aliases and set up an array to hold pointers to
  1243. // them.
  1244. //
  1245. for ( aliasCount = 0;
  1246. Servent32->s_aliases[aliasCount] != NULL;
  1247. aliasCount++ );
  1248. bytesFilled += (aliasCount+1) * sizeof(char FAR *);
  1249. if ( bytesFilled > (DWORD)BufferLength ) {
  1250. STOREDWORD( Servent32->s_aliases, 0 );
  1251. return requiredBufferLength;
  1252. }
  1253. Servent16->s_aliases =
  1254. FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation );
  1255. aliases16 = (VPBYTE *)currentLocation;
  1256. currentLocation = (PCHAR)Servent16 + bytesFilled;
  1257. //
  1258. // Copy the service name if it fits.
  1259. //
  1260. bytesFilled += strlen( Servent32->s_name ) + 1;
  1261. if ( bytesFilled > (DWORD)BufferLength ) {
  1262. return requiredBufferLength;
  1263. }
  1264. Servent16->s_name =
  1265. FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation );
  1266. RtlMoveMemory( currentLocation, Servent32->s_name, strlen( Servent32->s_name ) + 1 );
  1267. currentLocation = (PCHAR)Servent16 + bytesFilled;
  1268. //
  1269. // Copy the protocol name if it fits.
  1270. //
  1271. bytesFilled += strlen( Servent32->s_proto ) + 1;
  1272. if ( bytesFilled > (DWORD)BufferLength ) {
  1273. return requiredBufferLength;
  1274. }
  1275. Servent16->s_proto =
  1276. FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation );
  1277. RtlMoveMemory( currentLocation, Servent32->s_proto, strlen( Servent32->s_proto ) + 1 );
  1278. currentLocation = (PCHAR)Servent16 + bytesFilled;
  1279. //
  1280. // Start filling in aliases.
  1281. //
  1282. for ( i = 0; i < aliasCount; i++ ) {
  1283. bytesFilled += strlen( Servent32->s_aliases[i] ) + 1;
  1284. if ( bytesFilled > (DWORD)BufferLength ) {
  1285. STOREDWORD( aliases16[i], NULL );
  1286. return requiredBufferLength;
  1287. }
  1288. STOREDWORD(
  1289. aliases16[i],
  1290. FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation )
  1291. );
  1292. RtlMoveMemory(
  1293. currentLocation,
  1294. Servent32->s_aliases[i],
  1295. strlen( Servent32->s_aliases[i] ) + 1
  1296. );
  1297. currentLocation = (PCHAR)Servent16 + bytesFilled;
  1298. }
  1299. STOREDWORD( aliases16[i], NULL );
  1300. return requiredBufferLength;
  1301. } // CopyServent32To16
  1302. DWORD
  1303. BytesInServent32 (
  1304. IN PSERVENT Servent32
  1305. )
  1306. {
  1307. DWORD total;
  1308. int i;
  1309. total = sizeof(SERVENT);
  1310. total += strlen( Servent32->s_name ) + 1;
  1311. total += strlen( Servent32->s_proto ) + 1;
  1312. total += sizeof(char *);
  1313. for ( i = 0; Servent32->s_aliases[i] != NULL; i++ ) {
  1314. total += strlen( Servent32->s_aliases[i] ) + 1 + sizeof(char *);
  1315. }
  1316. return total;
  1317. } // BytesInServent32
  1318. ULONG FASTCALL WWS32WSACancelAsyncRequest(PVDMFRAME pFrame)
  1319. {
  1320. ULONG ul;
  1321. register PWSACANCELASYNCREQUEST16 parg16;
  1322. if ( !WWS32IsThreadInitialized ) {
  1323. SetLastError( WSANOTINITIALISED );
  1324. RETURN((ULONG)SOCKET_ERROR);
  1325. }
  1326. GETARGPTR(pFrame, sizeof(WSACANCELASYNCREQUEST16), parg16);
  1327. //ul = GETWORD16((*wsockapis[WOW_WSACANCELASYNCREQUEST].lpfn)(
  1328. // ));
  1329. FREEARGPTR(parg16);
  1330. ul = (ULONG) SOCKET_ERROR;
  1331. SetLastError( WSAEINVAL );
  1332. RETURN(ul);
  1333. } // WWS32WSACancelAsyncRequest
  1334. PWINSOCK_ASYNC_CONTEXT_BLOCK
  1335. WWS32FindAndRemoveAsyncContext (
  1336. IN HANDLE AsyncTaskHandle32
  1337. )
  1338. {
  1339. PWINSOCK_ASYNC_CONTEXT_BLOCK context;
  1340. PLIST_ENTRY listEntry;
  1341. RtlEnterCriticalSection( &WWS32CriticalSection );
  1342. //
  1343. // Walk the global list of async context blocks, looking for
  1344. // one that matches the specified task handle.
  1345. //
  1346. for ( listEntry = WWS32AsyncContextBlockListHead.Flink;
  1347. listEntry != &WWS32AsyncContextBlockListHead;
  1348. listEntry = listEntry->Flink ) {
  1349. context = CONTAINING_RECORD(
  1350. listEntry,
  1351. WINSOCK_ASYNC_CONTEXT_BLOCK,
  1352. ContextBlockListEntry
  1353. );
  1354. if ( context->AsyncTaskHandle32 == AsyncTaskHandle32 ) {
  1355. //
  1356. // Found a match. Remove it from the global list, leave
  1357. // the critical section, and return the context block.
  1358. //
  1359. RemoveEntryList( &context->ContextBlockListEntry );
  1360. RtlLeaveCriticalSection( &WWS32CriticalSection );
  1361. return context;
  1362. }
  1363. }
  1364. //
  1365. // A matching context block was not found on the list.
  1366. //
  1367. RtlLeaveCriticalSection( &WWS32CriticalSection );
  1368. return NULL;
  1369. } // WWS32FindAndRemoveAsyncContext
  1370. HAND16
  1371. WWS32GetAsyncTaskHandle16 (
  1372. VOID
  1373. )
  1374. {
  1375. HAND16 asyncTaskHandle16;
  1376. // *** this routine *must* be called from within the WWS32 critical
  1377. // section!
  1378. ASSERT( WWS32AsyncTaskHandleCounter != 0 );
  1379. asyncTaskHandle16 = (HAND16)WWS32AsyncTaskHandleCounter;
  1380. WWS32AsyncTaskHandleCounter++;
  1381. //
  1382. // 0 is an invalid task handle value; if the counter has wrapped to
  1383. // zero, set it to 1.
  1384. //
  1385. if ( WWS32AsyncTaskHandleCounter == 0 ) {
  1386. WWS32AsyncTaskHandleCounter = 1;
  1387. }
  1388. return WWS32AsyncTaskHandleCounter;
  1389. } // WWS32GetAsyncTaskHandle16