OSDN Git Service

2012-01-06 Chris Sutcliffe <ir0nh34d@users.sf.net>
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / autoload.cc
1 /* autoload.cc: all dynamic load stuff.
2
3    Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4    2009, 2010, 2011 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include "miscfuncs.h"
14 #include "fenv.h"
15 #define USE_SYS_TYPES_FD_SET
16 #include <winsock2.h>
17
18 bool NO_COPY wsock_started;
19
20 /* Macro for defining "auto-load" functions.
21  * Note that this is self-modifying code *gasp*.
22  * The first invocation of a routine will trigger the loading of
23  * the DLL.  This will then be followed by the discovery of
24  * the procedure's entry point, which is placed into the location
25  * pointed to by the stack pointer.  This code then changes
26  * the "call" operand which invoked it to a "jmp" which will
27  * transfer directly to the DLL function on the next invocation.
28  *
29  * Subsequent calls to routines whose transfer address has not been
30  * determined will skip the "load the dll" step, starting at the
31  * "discovery of the entry point" step.
32  *
33  * So, immediately following the the call to one of the above routines
34  * we have:
35  *  DLL info (4 bytes)   Pointer to a block of information concerning
36  *                       the DLL (see below).
37  *  DLL args (4 bytes)   The number of arguments pushed on the stack by
38  *                       the call.  If this is an odd value then this
39  *                       is a flag that non-existence of this function
40  *                       is not a fatal error
41  *  func name (n bytes)  asciz string containing the name of the function
42  *                       to be loaded.
43  *
44  * The DLL info block consists of the following
45  *  load_state (4 bytes) Pointer to a word containing the routine used
46  *                       to eventually invoke the function.  Initially
47  *                       points to an init function which loads the
48  *                       DLL, gets the process's load address,
49  *                       changes the contents here to point to the
50  *                       function address, and changes the call *(%eax)
51  *                       to a jmp func.  If the initialization has been
52  *                       done, only the load part is done.
53  *  DLL handle (4 bytes) The handle to use when loading the DLL.
54  *  DLL locker (4 bytes) Word to use to avoid multi-thread access during
55  *                       initialization.
56  *  extra init (4 bytes) Extra initialization function.
57  *  DLL name (n bytes)   asciz string containing the name of the DLL.
58  */
59
60 /* LoadDLLprime is used to prime the DLL info information, providing an
61    additional initialization routine to call prior to calling the first
62    function.  */
63 #define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ (" \n\
64 .ifndef " #dllname "_primed                             \n\
65   .section      .data_cygwin_nocopy,\"w\"               \n\
66   .align        4                                       \n\
67 ."#dllname "_info:                                      \n\
68   .long         _std_dll_init                           \n\
69   .long         " #no_resolve_on_fork "                 \n\
70   .long         -1                                      \n\
71   .long         " #init_also "                          \n\
72   .string16     \"" #dllname ".dll\"                    \n\
73   .text                                                 \n\
74   .set          " #dllname "_primed, 1                  \n\
75 .endif                                                  \n\
76 ");
77
78 /* Create a "decorated" name */
79 #define mangle(name, n) #name "@" #n
80
81 /* Standard DLL load macro.  May invoke a fatal error if the function isn't
82    found. */
83 #define LoadDLLfunc(name, n, dllname) \
84   LoadDLLfuncEx (name, n, dllname, 0)
85 #define LoadDLLfuncEx(name, n, dllname, notimp) \
86   LoadDLLfuncEx2(name, n, dllname, notimp, 0)
87 #define LoadDLLfuncEx2(name, n, dllname, notimp, err) \
88   LoadDLLfuncEx3(name, n, dllname, notimp, err, 0)
89
90 /* Main DLL setup stuff. */
91 #define LoadDLLfuncEx3(name, n, dllname, notimp, err, no_resolve_on_fork) \
92   LoadDLLprime (dllname, dll_func_load, no_resolve_on_fork) \
93   __asm__ ("                                            \n\
94   .section      ." #dllname "_autoload_text,\"wx\"      \n\
95   .global       _" mangle (name, n) "                   \n\
96   .global       _win32_" mangle (name, n) "             \n\
97   .align        8                                       \n\
98 _" mangle (name, n) ":                                  \n\
99 _win32_" mangle (name, n) ":                            \n\
100   .byte         0xe9                                    \n\
101   .long         -4 + 1f - .                             \n\
102 1:movl          (2f),%eax                               \n\
103    call         *(%eax)                                 \n\
104 2:.long         ." #dllname "_info                      \n\
105   .long         (" #n "+" #notimp ") | (((" #err ") & 0xff) <<16) \n\
106   .asciz        \"" #name "\"                           \n\
107   .text                                                 \n\
108 ");
109
110 /* DLL loader helper functions used during initialization. */
111
112 /* The function which finds the address, given the name and overwrites
113    the call so that future invocations go straight to the function in
114    the DLL. */
115 extern "C" void dll_func_load () __asm__ ("dll_func_load");
116
117 /* Called by the primary initialization function "init_std_dll" to
118    setup the stack and eliminate future calls to init_std_dll for other
119    functions from this DLL.  */
120 extern "C" void dll_chain () __asm__ ("dll_chain");
121
122 extern "C" {
123
124 __asm__ ("                                                              \n\
125          .text                                                          \n\
126 msg1:                                                                   \n\
127         .ascii  \"couldn't dynamically determine load address for '%s' (handle %p), %E\\0\"\n\
128                                                                         \n\
129         .align  32                                                      \n\
130 noload:                                                                 \n\
131         popl    %edx            # Get the address of the information block\n\
132         movl    4(%edx),%eax    # Should we 'ignore' the lack           \n\
133         test    $1,%eax         #  of this function?                    \n\
134         jz      1f              # Nope.                                 \n\
135         decl    %eax            # Yes.  This is the # of bytes + 1      \n\
136         popl    %edx            # Caller's caller                       \n\
137         addl    %eax,%esp       # Pop off bytes                         \n\
138         andl    $0xffff0000,%eax# upper word                            \n\
139         subl    %eax,%esp       # adjust for possible return value      \n\
140         pushl   %eax            # Save for later                        \n\
141         movl    $127,%eax       # ERROR_PROC_NOT_FOUND                  \n\
142         pushl   %eax            # First argument                        \n\
143         call    _SetLastError@4 # Set it                                \n\
144         popl    %eax            # Get back argument                     \n\
145         sarl    $16,%eax        # return value in high order word       \n\
146         jmp     *%edx           # Return                                \n\
147 1:                                                                      \n\
148         movl    (%edx),%eax     # Handle value                          \n\
149         pushl   4(%eax)                                                 \n\
150         leal    8(%edx),%eax    # Location of name of function          \n\
151         pushl   %eax                                                    \n\
152         pushl   $msg1           # The message                           \n\
153         call    _api_fatal      # Print message. Never returns          \n\
154                                                                         \n\
155         .globl  dll_func_load                                           \n\
156 dll_func_load:                                                          \n\
157         movl    (%esp),%eax     # 'Return address' contains load info   \n\
158         addl    $8,%eax         # Address of name of function to load   \n\
159         pushl   %eax            # Second argument                       \n\
160         movl    -8(%eax),%eax   # Where handle lives                    \n\
161         movl    4(%eax),%eax    # Address of Handle to DLL              \n\
162         pushl   %eax            # Handle to DLL                         \n\
163         call    _GetProcAddress@8# Load it                              \n\
164         test    %eax,%eax       # Success?                              \n\
165         jne     gotit           # Yes                                   \n\
166         jmp     noload          # Issue an error or return              \n\
167 gotit:                                                                  \n\
168         popl    %edx            # Pointer to 'return address'           \n\
169         subl    %edx,%eax       # Make it relative                      \n\
170         addl    $7,%eax         # Tweak                                 \n\
171         subl    $12,%edx        # Point to jmp                          \n\
172         movl    %eax,1(%edx)    # Move relative address after jump      \n\
173         jmp     *%edx           # Jump to actual function               \n\
174                                                                         \n\
175         .global dll_chain                                               \n\
176 dll_chain:                                                              \n\
177         pushl   %eax            # Restore 'return address'              \n\
178         jmp     *%edx           # Jump to next init function            \n\
179 ");
180
181 /* C representations of the two info blocks described above.
182    FIXME: These structures confuse gdb for some reason.  GDB can print
183    the whole structure but has problems with the name field? */
184 struct dll_info
185 {
186   DWORD load_state;
187   HANDLE handle;
188   LONG here;
189   void (*init) ();
190   WCHAR name[];
191 };
192
193 struct func_info
194 {
195   struct dll_info *dll;
196   LONG decoration;
197   char name[];
198 };
199
200 /* Mechanism for setting up info for passing to dll_chain routines. */
201 union retchain
202 {
203   struct {long high; long low;};
204   long long ll;
205 };
206
207
208 /* This function is a workaround for the problem reported here:
209   http://cygwin.com/ml/cygwin/2011-02/msg00552.html
210   and discussed here:
211   http://cygwin.com/ml/cygwin-developers/2011-02/threads.html#00007
212
213   To wit: winmm.dll calls FreeLibrary in its DllMain and that can result
214   in LoadLibraryExW returning an ERROR_INVALID_ADDRESS.  */
215 static __inline bool
216 dll_load (HANDLE& handle, WCHAR *name)
217 {
218   HANDLE h = LoadLibraryW (name);
219   if (!h && handle && wincap.use_dont_resolve_hack ()
220       && GetLastError () == ERROR_INVALID_ADDRESS)
221     h = LoadLibraryExW (name, NULL, DONT_RESOLVE_DLL_REFERENCES);
222   if (!h)
223     return false;
224   handle = h;
225   return true;
226 }
227
228 #define RETRY_COUNT 10
229
230 /* The standard DLL initialization routine. */
231 __attribute__ ((used, noinline)) static long long
232 std_dll_init ()
233 {
234   struct func_info *func = (struct func_info *) __builtin_return_address (0);
235   struct dll_info *dll = func->dll;
236   retchain ret;
237
238   if (InterlockedIncrement (&dll->here))
239     do
240       {
241         InterlockedDecrement (&dll->here);
242         yield ();
243       }
244     while (InterlockedIncrement (&dll->here));
245   else if ((uintptr_t) dll->handle <= 1)
246     {
247       fenv_t fpuenv;
248       fegetenv (&fpuenv);
249       WCHAR dll_path[MAX_PATH];
250       DWORD err = ERROR_SUCCESS;
251       int i;
252       /* http://www.microsoft.com/technet/security/advisory/2269637.mspx */
253       wcpcpy (wcpcpy (dll_path, windows_system_directory), dll->name);
254       /* MSDN seems to imply that LoadLibrary can fail mysteriously, so,
255          since there have been reports of this in the mailing list, retry
256          several times before giving up. */
257       for (i = 1; i <= RETRY_COUNT; i++)
258         {
259           /* If loading the library succeeds, just leave the loop. */
260           if (!dll_load (dll->handle, dll_path))
261             break;
262           /* Otherwise check error code returned by LoadLibrary.  If the
263              error code is neither NOACCESS nor DLL_INIT_FAILED, break out
264              of the loop. */
265           err = GetLastError ();
266           if (err != ERROR_NOACCESS && err != ERROR_DLL_INIT_FAILED)
267             break;
268           if (i < RETRY_COUNT)
269             yield ();
270         }
271       if ((uintptr_t) dll->handle <= 1)
272         {
273           /* If LoadLibrary with full path returns one of the weird errors
274              reported on the Cygwin mailing list, retry with only the DLL
275              name.  Only do this when the above retry loop has been exhausted. */
276           if (i > RETRY_COUNT && dll_load (dll->handle, dll->name))
277             /* got it with the fallback */;
278           else if ((func->decoration & 1))
279             dll->handle = INVALID_HANDLE_VALUE;
280           else
281             api_fatal ("unable to load %W, %E", dll_path);
282         }
283       fesetenv (&fpuenv);
284     }
285
286   /* Set "arguments" for dll_chain. */
287   ret.low = (long) dll->init;
288   ret.high = (long) func;
289
290   InterlockedDecrement (&dll->here);
291
292   /* Kludge alert.  Redirects the return address to dll_chain. */
293   __asm__ __volatile__ ("               \n\
294         movl    $dll_chain,4(%ebp)      \n\
295   ");
296
297   return ret.ll;
298 }
299
300 /* Initialization function for winsock stuff. */
301 WSADATA NO_COPY wsadata;
302 __attribute__ ((used, noinline, regparm(1))) static long long
303 wsock_init ()
304 {
305   static LONG NO_COPY here = -1L;
306   struct func_info *func = (struct func_info *) __builtin_return_address (0);
307   struct dll_info *dll = func->dll;
308
309   while (InterlockedIncrement (&here))
310     {
311       InterlockedDecrement (&here);
312       yield ();
313     }
314
315   if (!wsock_started)
316     {
317       int __stdcall (*wsastartup) (int, WSADATA *);
318
319       /* Don't use autoload to load WSAStartup to eliminate recursion. */
320       wsastartup = (int __stdcall (*)(int, WSADATA *))
321                    GetProcAddress ((HMODULE) (dll->handle), "WSAStartup");
322       if (wsastartup)
323         {
324           int res = wsastartup ((2<<8) | 2, &wsadata);
325
326           debug_printf ("res %d", res);
327           debug_printf ("wVersion %d", wsadata.wVersion);
328           debug_printf ("wHighVersion %d", wsadata.wHighVersion);
329           debug_printf ("szDescription %s", wsadata.szDescription);
330           debug_printf ("szSystemStatus %s", wsadata.szSystemStatus);
331           debug_printf ("iMaxSockets %d", wsadata.iMaxSockets);
332           debug_printf ("iMaxUdpDg %d", wsadata.iMaxUdpDg);
333           debug_printf ("lpVendorInfo %d", wsadata.lpVendorInfo);
334
335           wsock_started = 1;
336         }
337     }
338
339   /* Kludge alert.  Redirects the return address to dll_chain. */
340   __asm__ __volatile__ ("               \n\
341         movl    $dll_chain,4(%ebp)      \n\
342   ");
343
344   InterlockedDecrement (&here);
345
346   volatile retchain ret;
347   /* Set "arguments for dll_chain. */
348   ret.low = (long) dll_func_load;
349   ret.high = (long) func;
350   return ret.ll;
351 }
352
353 LoadDLLprime (ws2_32, _wsock_init, 0)
354
355 LoadDLLfunc (CreateProcessAsUserW, 44, advapi32)
356 LoadDLLfunc (CryptAcquireContextW, 20, advapi32)
357 LoadDLLfunc (CryptGenRandom, 12, advapi32)
358 LoadDLLfunc (CryptReleaseContext, 8, advapi32)
359 LoadDLLfunc (DeregisterEventSource, 4, advapi32)
360 LoadDLLfunc (LogonUserW, 24, advapi32)
361 LoadDLLfunc (LookupAccountNameW, 28, advapi32)
362 LoadDLLfunc (LookupAccountSidW, 28, advapi32)
363 LoadDLLfunc (LsaClose, 4, advapi32)
364 LoadDLLfunc (LsaEnumerateAccountRights, 16, advapi32)
365 LoadDLLfunc (LsaFreeMemory, 4, advapi32)
366 LoadDLLfunc (LsaOpenPolicy, 16, advapi32)
367 LoadDLLfunc (LsaQueryInformationPolicy, 12, advapi32)
368 LoadDLLfunc (LsaRetrievePrivateData, 12, advapi32)
369 LoadDLLfunc (LsaStorePrivateData, 12, advapi32)
370 LoadDLLfunc (RegCloseKey, 4, advapi32)
371 LoadDLLfunc (RegCreateKeyExW, 36, advapi32)
372 LoadDLLfunc (RegEnumKeyExW, 32, advapi32)
373 LoadDLLfunc (RegEnumValueW, 32, advapi32)
374 LoadDLLfunc (RegGetKeySecurity, 16, advapi32)
375 LoadDLLfunc (RegOpenKeyExW, 20, advapi32)
376 LoadDLLfunc (RegQueryInfoKeyW, 48, advapi32)
377 LoadDLLfunc (RegQueryValueExW, 24, advapi32)
378 LoadDLLfunc (RegisterEventSourceW, 8, advapi32)
379 LoadDLLfunc (ReportEventW, 36, advapi32)
380
381 LoadDLLfunc (DnsQuery_A, 24, dnsapi)
382 LoadDLLfunc (DnsRecordListFree, 8, dnsapi)
383
384 // 50 = ERROR_NOT_SUPPORTED.  Returned if OS doesn't support iphlpapi funcs
385 LoadDLLfuncEx2 (GetAdaptersAddresses, 20, iphlpapi, 1, 50)
386 LoadDLLfunc (GetIfEntry, 4, iphlpapi)
387 LoadDLLfunc (GetIpAddrTable, 12, iphlpapi)
388 LoadDLLfunc (GetIpForwardTable, 12, iphlpapi)
389 LoadDLLfunc (GetNetworkParams, 8, iphlpapi)
390 LoadDLLfunc (GetUdpTable, 12, iphlpapi)
391
392 LoadDLLfuncEx (AttachConsole, 4, kernel32, 1)
393 LoadDLLfuncEx (GetModuleHandleExW, 12, kernel32, 1)
394 LoadDLLfuncEx (GetNamedPipeClientProcessId, 8, kernel32, 1)
395 LoadDLLfuncEx (GetSystemWow64DirectoryW, 8, kernel32, 1)
396 LoadDLLfuncEx (GetVolumePathNamesForVolumeNameW, 16, kernel32, 1)
397 LoadDLLfunc (LocaleNameToLCID, 8, kernel32)
398
399 LoadDLLfunc (WNetCloseEnum, 4, mpr)
400 LoadDLLfunc (WNetEnumResourceA, 16, mpr)
401 LoadDLLfunc (WNetGetProviderNameA, 12, mpr)
402 LoadDLLfunc (WNetGetResourceInformationA, 16, mpr)
403 LoadDLLfunc (WNetOpenEnumA, 20, mpr)
404
405 LoadDLLfunc (DsGetDcNameW, 24, netapi32)
406 LoadDLLfunc (NetApiBufferFree, 4, netapi32)
407 LoadDLLfunc (NetUserGetGroups, 28, netapi32)
408 LoadDLLfunc (NetUserGetInfo, 16, netapi32)
409 LoadDLLfunc (NetUserGetLocalGroups, 32, netapi32)
410
411 LoadDLLfunc (NtCommitTransaction, 8, ntdll)
412 LoadDLLfunc (NtCreateTransaction, 40, ntdll)
413 LoadDLLfunc (NtRollbackTransaction, 8, ntdll)
414 LoadDLLfunc (RtlGetCurrentTransaction, 0, ntdll)
415 LoadDLLfunc (RtlSetCurrentTransaction, 4, ntdll)
416
417 LoadDLLfunc (CoTaskMemFree, 4, ole32)
418
419 LoadDLLfunc (LsaDeregisterLogonProcess, 4, secur32)
420 LoadDLLfunc (LsaFreeReturnBuffer, 4, secur32)
421 LoadDLLfunc (LsaLogonUser, 56, secur32)
422 LoadDLLfunc (LsaLookupAuthenticationPackage, 12, secur32)
423 LoadDLLfunc (LsaRegisterLogonProcess, 12, secur32)
424
425 LoadDLLfunc (SHGetDesktopFolder, 4, shell32)
426
427 LoadDLLfunc (CloseClipboard, 0, user32)
428 LoadDLLfunc (CloseDesktop, 4, user32)
429 LoadDLLfunc (CloseWindowStation, 4, user32)
430 LoadDLLfunc (CreateDesktopW, 24, user32)
431 LoadDLLfunc (CreateWindowExW, 48, user32)
432 LoadDLLfunc (CreateWindowStationW, 16, user32)
433 LoadDLLfunc (DefWindowProcW, 16, user32)
434 LoadDLLfunc (DispatchMessageW, 4, user32)
435 LoadDLLfunc (EmptyClipboard, 0, user32)
436 LoadDLLfunc (EnumWindows, 8, user32)
437 LoadDLLfunc (GetClipboardData, 4, user32)
438 LoadDLLfunc (GetForegroundWindow, 0, user32)
439 LoadDLLfunc (GetKeyboardLayout, 4, user32)
440 LoadDLLfunc (GetMessageW, 16, user32)
441 LoadDLLfunc (GetPriorityClipboardFormat, 8, user32)
442 LoadDLLfunc (GetProcessWindowStation, 0, user32)
443 LoadDLLfunc (GetThreadDesktop, 4, user32)
444 LoadDLLfunc (GetUserObjectInformationW, 20, user32)
445 LoadDLLfunc (GetWindowThreadProcessId, 8, user32)
446 LoadDLLfunc (MessageBeep, 4, user32)
447 LoadDLLfunc (MessageBoxW, 16, user32)
448 LoadDLLfunc (MsgWaitForMultipleObjectsEx, 20, user32)
449 LoadDLLfunc (OpenClipboard, 4, user32)
450 LoadDLLfunc (PeekMessageW, 20, user32)
451 LoadDLLfunc (PostMessageW, 16, user32)
452 LoadDLLfunc (PostQuitMessage, 4, user32)
453 LoadDLLfunc (RegisterClassW, 4, user32)
454 LoadDLLfunc (RegisterClipboardFormatW, 4, user32)
455 LoadDLLfunc (SendNotifyMessageW, 16, user32)
456 LoadDLLfunc (SetClipboardData, 8, user32)
457 LoadDLLfunc (SetParent, 8, user32)
458 LoadDLLfunc (SetProcessWindowStation, 4, user32)
459 LoadDLLfunc (SetThreadDesktop, 4, user32)
460
461 LoadDLLfuncEx3 (waveInAddBuffer, 12, winmm, 1, 0, 1)
462 LoadDLLfuncEx3 (waveInClose, 4, winmm, 1, 0, 1)
463 LoadDLLfuncEx3 (waveInGetNumDevs, 0, winmm, 1, 0, 1)
464 LoadDLLfuncEx3 (waveInOpen, 24, winmm, 1, 0, 1)
465 LoadDLLfuncEx3 (waveInPrepareHeader, 12, winmm, 1, 0, 1)
466 LoadDLLfuncEx3 (waveInReset, 4, winmm, 1, 0, 1)
467 LoadDLLfuncEx3 (waveInStart, 4, winmm, 1, 0, 1)
468 LoadDLLfuncEx3 (waveInUnprepareHeader, 12, winmm, 1, 0, 1)
469 LoadDLLfuncEx3 (waveOutClose, 4, winmm, 1, 0, 1)
470 LoadDLLfuncEx3 (waveOutGetNumDevs, 0, winmm, 1, 0, 1)
471 LoadDLLfuncEx3 (waveOutGetVolume, 8, winmm, 1, 0, 1)
472 LoadDLLfuncEx3 (waveOutOpen, 24, winmm, 1, 0, 1)
473 LoadDLLfuncEx3 (waveOutPrepareHeader, 12, winmm, 1, 0, 1)
474 LoadDLLfuncEx3 (waveOutReset, 4, winmm, 1, 0, 1)
475 LoadDLLfuncEx3 (waveOutSetVolume, 8, winmm, 1, 0, 1)
476 LoadDLLfuncEx3 (waveOutUnprepareHeader, 12, winmm, 1, 0, 1)
477 LoadDLLfuncEx3 (waveOutWrite, 12, winmm, 1, 0, 1)
478
479 LoadDLLfunc (accept, 12, ws2_32)
480 LoadDLLfunc (bind, 12, ws2_32)
481 LoadDLLfunc (closesocket, 4, ws2_32)
482 LoadDLLfunc (connect, 12, ws2_32)
483 LoadDLLfunc (gethostbyaddr, 12, ws2_32)
484 LoadDLLfunc (gethostbyname, 4, ws2_32)
485 LoadDLLfunc (gethostname, 8, ws2_32)
486 LoadDLLfunc (getpeername, 12, ws2_32)
487 LoadDLLfunc (getprotobyname, 4, ws2_32)
488 LoadDLLfunc (getprotobynumber, 4, ws2_32)
489 LoadDLLfunc (getservbyname, 8, ws2_32)
490 LoadDLLfunc (getservbyport, 8, ws2_32)
491 LoadDLLfunc (getsockname, 12, ws2_32)
492 LoadDLLfunc (getsockopt, 20, ws2_32)
493 LoadDLLfunc (ioctlsocket, 12, ws2_32)
494 LoadDLLfunc (listen, 8, ws2_32)
495 LoadDLLfunc (setsockopt, 20, ws2_32)
496 LoadDLLfunc (shutdown, 8, ws2_32)
497 LoadDLLfunc (socket, 12, ws2_32)
498 LoadDLLfunc (WSAAsyncSelect, 16, ws2_32)
499 LoadDLLfunc (WSADuplicateSocketW, 12, ws2_32)
500 LoadDLLfunc (WSAEnumNetworkEvents, 12, ws2_32)
501 LoadDLLfunc (WSAEventSelect, 12, ws2_32)
502 LoadDLLfunc (WSAGetLastError, 0, ws2_32)
503 LoadDLLfunc (WSAIoctl, 36, ws2_32)
504 LoadDLLfunc (WSARecv, 28, ws2_32)
505 LoadDLLfunc (WSARecvFrom, 36, ws2_32)
506 LoadDLLfunc (WSASendMsg, 24, ws2_32)
507 LoadDLLfunc (WSASendTo, 36, ws2_32)
508 LoadDLLfunc (WSASetLastError, 4, ws2_32)
509 LoadDLLfunc (WSASocketW, 24, ws2_32)
510 // LoadDLLfunc (WSAStartup, 8, ws2_32)
511 LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32)
512 }