From ec1796636dc90361b1c87546ab54cf11182b1266 Mon Sep 17 00:00:00 2001 From: Mayank Agrawal Date: Mon, 1 Jun 2026 14:47:17 +0530 Subject: [PATCH 1/4] Add comments for assembly --- winsup/cygwin/autoload.cc | 160 +++++++++++++++++--------------------- 1 file changed, 73 insertions(+), 87 deletions(-) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 8f6204b09..17860c3f5 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -64,44 +64,34 @@ bool NO_COPY wsock_started; * DLL name (n bytes) asciz string containing the name of the DLL. */ -/* LoadDLLprime is used to prime the DLL info information, providing an - additional initialization routine to call prior to calling the first - function. */ #if defined(__x86_64__) -#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ (" \n\ -.ifndef " #dllname "_primed \n\ - .section .data_cygwin_nocopy,\"w\" \n\ - .align 8 \n\ -."#dllname "_info: \n\ - .quad _std_dll_init \n\ - .quad " #no_resolve_on_fork " \n\ - .long -1 \n\ - .align 8 \n\ - .quad " #init_also " \n\ - .string16 \"" #dllname ".dll\" \n\ - .text \n\ - .set " #dllname "_primed, 1 \n\ -.endif \n\ -"); +# define WORD64 ".quad" #elif defined(__aarch64__) -#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ ( "\n\ +# define WORD64 ".xword" +#else +# error unimplemented for this target +#endif + +/* LoadDLLprime is used to prime the DLL info information, providing an + additional initialization routine to call prior to calling the first + function. WORD64 stands in for .quad/.xword, and .balign (which means + "align to N bytes" on both targets - "x64" and "arm64) is used for + alignment. */ +#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ ("\n\ .ifndef " #dllname "_primed \n\ .section .data_cygwin_nocopy,\"w\" \n\ - .balign 8 \n\ -." #dllname "_info: \n\ - .xword _std_dll_init \n\ - .xword " #no_resolve_on_fork " \n\ - .long -1 \n\ - .balign 8 \n\ - .xword " #init_also " \n\ + .balign 8 \n\ +." #dllname "_info: \n\ + " WORD64 " _std_dll_init \n\ + " WORD64 " " #no_resolve_on_fork " \n\ + .long -1 \n\ + .balign 8 \n\ + " WORD64 " " #init_also " \n\ .string16 \"" #dllname ".dll\" \n\ - .text \n\ + .text \n\ .set " #dllname "_primed, 1 \n\ -.endif \n\ +.endif \n\ "); -#else -#error unimplemented for this target -#endif /* Standard DLL load macro. May invoke a fatal error if the function isn't found. */ @@ -149,28 +139,28 @@ _win32_" #name ": \n\ .p2align 4 \n\ " #name ": \n\ _win32_" #name ": \n\ - adr x16, 3f \n\ - ldr x16, [x16] \n\ - br x16 \n\ + adr x16, 3f // x16 = &func_addr slot (label 3 == func_info+12)\n\ + ldr x16, [x16] // x16 = *(&func_addr) = 1b first time, real addr later\n\ + br x16 // fast-path branch into the resolved DLL func\n\ 1: \n\ - sub sp, sp, #80 \n\ + sub sp, sp, #80 // reserve 80B frame for caller's arg regs + LR\n\ stp x0, x1, [sp, #0] \n\ stp x2, x3, [sp, #16] \n\ stp x4, x5, [sp, #32] \n\ stp x6, x7, [sp, #48] \n\ - stp x8, x30, [sp, #64] \n\ - adr x16, 2f \n\ - ldur x17, [x16] \n\ - ldr x17, [x17] \n\ - blr x17 \n\ + stp x8, x30, [sp, #64] // x30 here == label 2 == &func_info\n\ + adr x16, 2f // x16 = &func_info\n\ + ldr x17, [x16] // x17 = func_info->dll (= dll_info*)\n\ + ldr x17, [x17] // x17 = dll_info->load_state (e.g. _std_dll_init)\n\ + blr x17 // call thunk; LR = label 2 = arg to std_dll_init\n\ 2: \n\ - .xword ." #dllname "_info \n\ - .hword " #notimp " \n\ - .hword ((" #err ") & 0xffff) \n\ -3: \n\ - .xword 1b \n\ - .asciz \"" #name "\" \n\ - .text \n\ + .xword ." #dllname "_info // +0 func_info.dll\n\ + .hword " #notimp " // +8 func_info.decoration[lo]\n\ + .hword ((" #err ") & 0xffff) // +10 func_info.decoration[hi]\n\ +3: \n\ + .xword 1b // +12 func_info.func_addr (patched by dll_func_load)\n\ + .asciz \"" #name "\" // +20 func_info.name (asciz)\n\ + .text \n\ "); #else #error unimplemented for this target @@ -261,55 +251,51 @@ msg1: \n\ \n\ .text \n\ .p2align 2 \n\ -noload: \n\ - ldr x2, [sp] // func_info* \n\ - ldr w3, [x2, #8] // decoration \n\ - tbz w3, #0, 1f \n\ - \n\ - asr w4, w3, #16 \n\ - str w4, [sp, #8] \n\ - mov w0, #127 // ERROR_PROC_NOT_FOUND \n\ + noload: \n\ + ldr x2, [sp] // x2 = func_info* (pushed by dll_chain)\n\ + ldr w3, [x2, #8] // w3 = func_info.decoration\n\ + tbz w3, #0, 1f // notimp bit clear -> fatal\n\ + asr w4, w3, #16 // w4 = err (sign-extend high half)\n\ + str w4, [sp, #8] // spill into dll_chain's xzr slot\n\ + mov w0, #127 // ERROR_PROC_NOT_FOUND\n\ bl SetLastError \n\ - ldr w0, [sp, #8] \n\ - ldr x30, [sp, #88] \n\ - add sp, sp, #96 \n\ - ret \n\ -1: \n\ - add x1, x2, #20 \n\ - ldur x3, [x2] \n\ - ldr x2, [x3, #8] \n\ - adrp x0, msg1 \n\ - add x0, x0, #:lo12:msg1 \n\ - bl api_fatal \n\ + ldr w0, [sp, #8] // reload err as return value\n\ + ldr x30, [sp, #88] // restore caller LR (16 + 72)\n\ + add sp, sp, #96 // drop dll_chain (16) + trampoline (80) frames\n\ + ret \n\ +1: \n\ + add x1, x2, #20 // x1 = &func_info.name\n\ + ldr x3, [x2] // x3 = dll_info*\n\ + ldr x2, [x3, #8] // x2 = dll_info->handle\n\ + adrp x0, msg1 \n\ + add x0, x0, #:lo12:msg1\n\ + bl api_fatal // never returns \n\ \n\ .globl dll_func_load \n\ -dll_func_load: \n\ - ldr x2, [sp] \n\ - ldur x3, [x2] \n\ - ldr x0, [x3, #8] \n\ - add x1, x2, #20 \n\ +dll_func_load: \n\ + ldr x2, [sp] // x2 = func_info* (pushed by dll_chain)\n\ + ldr x3, [x2] // x3 = dll_info*\n\ + ldr x0, [x3, #8] // x0 = dll handle (arg1 to GetProcAddress)\n\ + add x1, x2, #20 // x1 = &func_info.name (arg2)\n\ bl GetProcAddress \n\ - cbz x0, noload \n\ - \n\ - ldr x2, [sp] \n\ - add x3, x2, #12 \n\ - str x0, [x3] \n\ - \n\ - sub x16, x2, #52 \n\ - \n\ - add sp, sp, #16 \n\ - ldp x0, x1, [sp, #0] \n\ + cbz x0, noload // 0 -> not found, jump to error path\n\ + ldr x2, [sp] // reload func_info*\n\ + str x0, [x2, #12] // patch func_addr slot (label 3)\n\ + sub x16, x2, #52 // x16 = trampoline entry; '#52' = 12B prologue\n\ + // + 40B slow path; sync with LoadDLLfuncEx3\n\ + add sp, sp, #16 // drop dll_chain frame\n\ + ldp x0, x1, [sp, #0] // restore caller's arg regs\n\ ldp x2, x3, [sp, #16] \n\ ldp x4, x5, [sp, #32] \n\ ldp x6, x7, [sp, #48] \n\ - ldp x8, x30, [sp, #64] \n\ - add sp, sp, #80 \n\ - br x16 \n\ + ldp x8, x30, [sp, #64]\n\ + add sp, sp, #80 // drop trampoline frame\n\ + br x16 // re-enter trampoline; fast path now hits real func\n\ \n\ .global dll_chain \n\ dll_chain: \n\ - stp x0, xzr, [sp, #-16]! \n\ - br x1 \n\ + stp x0, xzr, [sp, #-16]! // x0 = func_info* (= ret.high); push for dll_func_load\n\ + br x1 // x1 = dll->init (= ret.low); tail-call resolver\n\ "); #else #error unimplemented for this target @@ -781,4 +767,4 @@ LoadDLLfunc (PdhAddEnglishCounterW, pdh) LoadDLLfunc (PdhCollectQueryData, pdh) LoadDLLfunc (PdhGetFormattedCounterValue, pdh) LoadDLLfunc (PdhOpenQueryW, pdh) -} +} \ No newline at end of file From 7d593faf6ee1bfbbf9cdf9049e234f4f7e6ef659 Mon Sep 17 00:00:00 2001 From: Mayank Agrawal Date: Wed, 24 Jun 2026 12:05:03 +0530 Subject: [PATCH 2/4] Cygwin: autoload: Fix ws2_32 init (WSAStartup never called) on AArch64 On AArch64, the autoload INIT_WRAPPER passes its func_info* argument in x30 (mov x0, x30), which is only valid when the wrapper is reached via the trampoline'\''s blr to the FIRST init function (std_dll_init). A second, chained INIT_WRAPPER'\''d init -- wsock_init, used only by ws2_32 -- is reached from dll_chain via a tail "br x1", which does not set x30. So wsock_init received a garbage func_info, read dll->handle as 0, and GetProcAddress((HMODULE)0, "WSAStartup") returned NULL: WSAStartup was never called and Winsock was never initialized. Every ws2_32 function (GetAddrInfoW, socket, gethostbyname) then ran against uninitialized Winsock -> EFAULT / hang / WSANOTINITIALISED (10093). This affected only ws2_32 (the sole DLL with a secondary INIT_WRAPPER init); all other DLLs chain straight to dll_func_load, which reads func_info from the stack and is unaffected. x86_64 was unaffected because its INIT_WRAPPER reads the argument from the stack in both positions. Fix: have dll_chain also place func_info in x30 before the tail-branch, so a chained INIT_WRAPPER init gets the correct argument. dll_func_load is unaffected (it reads func_info from [sp]); std_dll_init is unaffected (reached via blr, not dll_chain). --- winsup/cygwin/autoload.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 17860c3f5..9a6a34d45 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -295,6 +295,10 @@ dll_func_load: \n\ .global dll_chain \n\ dll_chain: \n\ stp x0, xzr, [sp, #-16]! // x0 = func_info* (= ret.high); push for dll_func_load\n\ + mov x30, x0 // also pass func_info in x30: a chained INIT_WRAPPER\n\ + // (e.g. _wsock_init) reads its arg from x30, but is\n\ + // reached here via 'br' which would otherwise leave\n\ + // x30 stale. dll_func_load ignores x30 (reads [sp]).\n\ br x1 // x1 = dll->init (= ret.low); tail-call resolver\n\ "); #else From 2496bd00fc7dd9035029f38161dbf773df961993 Mon Sep 17 00:00:00 2001 From: Mayank Agrawal Date: Wed, 24 Jun 2026 15:42:59 +0530 Subject: [PATCH 3/4] Cygwin: autoload: Fix first ws2_32 call faulting on AArch64 (stranded dll_chain frame) Second half of the AArch64 ws2_32 chained-init fix. After the x30 fix let wsock_init run WSAStartup, the FIRST ws2_32 call in a process still faulted (later fast-path calls worked). Cause: ws2_32 is the only DLL with a chained second init stage, so dll_chain runs twice (-> wsock_init, -> dll_func_load), each pushing a 16-byte func_info frame. wsock_init takes its arg from x30, not the stack, so the frame dll_chain pushed before wsock_init is never consumed and strands on the stack. dll_func_load assumes exactly one dll_chain frame above the trampoline register-save frame, so it then restores the caller arg registers from a 16-byte-shifted offset, corrupting the first real call. Fix: give aarch64 wsock_init a dedicated INIT_WRAPPER that drops the stranded dll_chain frame (extra add sp,#16) before chaining to dll_func_load. x86_64 keeps the shared INIT_WRAPPER (its dll_chain push/0x28(%rsp) mechanism is not affected). std_dll_init keeps the plain wrapper (reached via blr; no stranded frame). --- winsup/cygwin/autoload.cc | 41 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 9a6a34d45..70fb705e9 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -479,9 +479,48 @@ std_dll_init (struct func_info *func) /* Initialization function for winsock stuff. */ -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) /* See above comment preceeding std_dll_init. */ INIT_WRAPPER (wsock_init) +#elif defined(__aarch64__) +/* ws2_32 is the only DLL with a SECOND, chained init stage (wsock_init): + trampoline -> std_dll_init -> dll_chain -> wsock_init -> dll_chain -> + dll_func_load. Every dll_chain hand-off pushes a 16-byte frame carrying + func_info for the next stage. dll_func_load consumes the frame pushed for + IT (it reads func_info from [sp] and drops 16 bytes), and it assumes that + directly below sits the trampoline's register-save frame. But wsock_init + takes its argument from x30 (set by dll_chain), NOT from the stack, so the + dll_chain frame pushed *before wsock_init* is never consumed -- it strands + on the stack between dll_func_load's frame and the trampoline frame. + dll_func_load then restores the caller's argument registers from a + 16-byte-shifted offset, corrupting the very first ws2_32 call (later calls + take the patched fast path and bypass this). Fix: this dedicated wrapper + drops that stranded dll_chain frame (the extra "add sp, sp, #16") before + chaining onward. std_dll_init keeps the plain INIT_WRAPPER: it is reached + via blr with no preceding dll_chain frame to clean up. */ +__asm__ ( "\n\ + .text \n\ + .p2align 2 \n\ + .seh_proc _wsock_init \n\ +_wsock_init: \n\ + // Reached from dll_chain via 'br' (NOT 'blr'): dll_chain has put func_info\n\ + // in x30 for us and left its own 16-byte hand-off frame on the stack just\n\ + // above the trampoline's register-save frame. We consume our arg from x30\n\ + // and must drop that stranded frame before chaining onward (see note above).\n\ + stp x29, x30, [sp, #-16]! // save fp/lr, open our 16-byte frame\n\ + .seh_save_fplr_x 16 \n\ + .seh_endprologue \n\ + mov x0, x30 // x0 = func_info (the wsock_init() argument)\n\ + bl wsock_init // run WSAStartup; returns x0=func_info, x1=dll_func_load\n\ + ldp x29, xzr, [sp], #16 // restore fp, discard saved lr, close our frame\n\ + add sp, sp, #16 // drop the stranded dll_chain frame so the\n\ + // downstream dll_func_load sees exactly one\n\ + // dll_chain frame above the trampoline frame\n\ + adrp x30, dll_chain // x30 = &dll_chain ...\n\ + add x30, x30, #:lo12:dll_chain // ... so the 'ret' below tail-chains there\n\ + ret // -> dll_chain, which tail-calls x1 (dll_func_load)\n\ + .seh_endproc \n\ +"); #else #error unimplemented for this target #endif From 17f4bce92de78b7852f549ef58db42dc7561ca0b Mon Sep 17 00:00:00 2001 From: Mayank Agrawal Date: Thu, 25 Jun 2026 10:47:41 +0530 Subject: [PATCH 4/4] remove dead code no_resolve_on_fork --- winsup/cygwin/autoload.cc | 91 ++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 55 deletions(-) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 70fb705e9..433815b5f 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -77,13 +77,13 @@ bool NO_COPY wsock_started; function. WORD64 stands in for .quad/.xword, and .balign (which means "align to N bytes" on both targets - "x64" and "arm64) is used for alignment. */ -#define LoadDLLprime(dllname, init_also, no_resolve_on_fork) __asm__ ("\n\ +#define LoadDLLprime(dllname, init_also) __asm__ ("\n\ .ifndef " #dllname "_primed \n\ .section .data_cygwin_nocopy,\"w\" \n\ .balign 8 \n\ ." #dllname "_info: \n\ " WORD64 " _std_dll_init \n\ - " WORD64 " " #no_resolve_on_fork " \n\ + " WORD64 " 0 \n\ .long -1 \n\ .balign 8 \n\ " WORD64 " " #init_also " \n\ @@ -100,12 +100,12 @@ bool NO_COPY wsock_started; #define LoadDLLfuncEx(name, dllname, notimp) \ LoadDLLfuncEx2(name, dllname, notimp, 0) #define LoadDLLfuncEx2(name, dllname, notimp, err) \ - LoadDLLfuncEx3(name, dllname, notimp, err, 0) + LoadDLLfuncEx3(name, dllname, notimp, err) /* Main DLL setup stuff. */ #if defined(__x86_64__) -#define LoadDLLfuncEx3(name, dllname, notimp, err, no_resolve_on_fork) \ - LoadDLLprime (dllname, dll_func_load, no_resolve_on_fork) \ +#define LoadDLLfuncEx3(name, dllname, notimp, err) \ + LoadDLLprime (dllname, dll_func_load) \ __asm__ (" \n\ .section ." #dllname "_autoload_text,\"wx\" \n\ .global " #name " \n\ @@ -130,8 +130,8 @@ _win32_" #name ": \n\ .text \n\ "); #elif defined(__aarch64__) -#define LoadDLLfuncEx3(name, dllname, notimp, err, no_resolve_on_fork) \ - LoadDLLprime (dllname, dll_func_load, no_resolve_on_fork) \ +#define LoadDLLfuncEx3(name, dllname, notimp, err) \ + LoadDLLprime (dllname, dll_func_load) \ __asm__ ( "\n\ .section ." #dllname "_autoload_text,\"wx\" \n\ .global " #name " \n\ @@ -436,7 +436,7 @@ std_dll_init (struct func_info *func) yield (); } while (InterlockedIncrement (&dll->here)); - else if ((uintptr_t) dll->handle <= 1) + else if (!dll->handle) { fenv_t fpuenv; fegetenv (&fpuenv); @@ -459,7 +459,7 @@ std_dll_init (struct func_info *func) if (i < RETRY_COUNT) yield (); } - if ((uintptr_t) dll->handle <= 1) + if (!dll->handle) { if ((func->decoration & 1)) dll->handle = INVALID_HANDLE_VALUE; @@ -483,42 +483,23 @@ std_dll_init (struct func_info *func) /* See above comment preceeding std_dll_init. */ INIT_WRAPPER (wsock_init) #elif defined(__aarch64__) -/* ws2_32 is the only DLL with a SECOND, chained init stage (wsock_init): - trampoline -> std_dll_init -> dll_chain -> wsock_init -> dll_chain -> - dll_func_load. Every dll_chain hand-off pushes a 16-byte frame carrying - func_info for the next stage. dll_func_load consumes the frame pushed for - IT (it reads func_info from [sp] and drops 16 bytes), and it assumes that - directly below sits the trampoline's register-save frame. But wsock_init - takes its argument from x30 (set by dll_chain), NOT from the stack, so the - dll_chain frame pushed *before wsock_init* is never consumed -- it strands - on the stack between dll_func_load's frame and the trampoline frame. - dll_func_load then restores the caller's argument registers from a - 16-byte-shifted offset, corrupting the very first ws2_32 call (later calls - take the patched fast path and bypass this). Fix: this dedicated wrapper - drops that stranded dll_chain frame (the extra "add sp, sp, #16") before - chaining onward. std_dll_init keeps the plain INIT_WRAPPER: it is reached - via blr with no preceding dll_chain frame to clean up. */ __asm__ ( "\n\ .text \n\ .p2align 2 \n\ .seh_proc _wsock_init \n\ _wsock_init: \n\ - // Reached from dll_chain via 'br' (NOT 'blr'): dll_chain has put func_info\n\ - // in x30 for us and left its own 16-byte hand-off frame on the stack just\n\ - // above the trampoline's register-save frame. We consume our arg from x30\n\ - // and must drop that stranded frame before chaining onward (see note above).\n\ - stp x29, x30, [sp, #-16]! // save fp/lr, open our 16-byte frame\n\ - .seh_save_fplr_x 16 \n\ - .seh_endprologue \n\ + stp x29, x30, [sp, #-16]! // save fp/lr, open 16-byte frame\n\ + .seh_save_fplr_x 16 \n\ + .seh_endprologue \n\ mov x0, x30 // x0 = func_info (the wsock_init() argument)\n\ bl wsock_init // run WSAStartup; returns x0=func_info, x1=dll_func_load\n\ - ldp x29, xzr, [sp], #16 // restore fp, discard saved lr, close our frame\n\ + ldp x29, xzr, [sp], #16 // restore fp, discard saved lr, close frame\n\ add sp, sp, #16 // drop the stranded dll_chain frame so the\n\ // downstream dll_func_load sees exactly one\n\ // dll_chain frame above the trampoline frame\n\ - adrp x30, dll_chain // x30 = &dll_chain ...\n\ - add x30, x30, #:lo12:dll_chain // ... so the 'ret' below tail-chains there\n\ - ret // -> dll_chain, which tail-calls x1 (dll_func_load)\n\ + adrp x30, dll_chain // x30 = &dll_chain so the 'ret' below tail-chains there\n\ + add x30, x30, #:lo12:dll_chain // -> dll_chain, which tail-calls x1 (dll_func_load)\n\ + ret \n\ .seh_endproc \n\ "); #else @@ -571,7 +552,7 @@ wsock_init (struct func_info *func) return ret.ll; } -LoadDLLprime (ws2_32, _wsock_init, 0) +LoadDLLprime (ws2_32, _wsock_init) LoadDLLfunc (CheckTokenMembership, advapi32) LoadDLLfunc (CreateProcessAsUserW, advapi32) @@ -748,25 +729,25 @@ LoadDLLfuncEx2 (CreateProfile, userenv, 1, 1) LoadDLLfunc (DestroyEnvironmentBlock, userenv) LoadDLLfunc (LoadUserProfileW, userenv) -LoadDLLfuncEx3 (waveInAddBuffer, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInClose, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInGetNumDevs, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInOpen, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInPrepareHeader, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInReset, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInStart, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveInUnprepareHeader, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutClose, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutGetNumDevs, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutGetVolume, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutOpen, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutPrepareHeader, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutReset, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutSetVolume, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutUnprepareHeader, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutWrite, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutMessage, winmm, 1, 0, 1) -LoadDLLfuncEx3 (waveOutGetDevCapsA, winmm, 1, 0, 1) +LoadDLLfuncEx3 (waveInAddBuffer, winmm, 1, 0) +LoadDLLfuncEx3 (waveInClose, winmm, 1, 0) +LoadDLLfuncEx3 (waveInGetNumDevs, winmm, 1, 0) +LoadDLLfuncEx3 (waveInOpen, winmm, 1, 0) +LoadDLLfuncEx3 (waveInPrepareHeader, winmm, 1, 0) +LoadDLLfuncEx3 (waveInReset, winmm, 1, 0) +LoadDLLfuncEx3 (waveInStart, winmm, 1, 0) +LoadDLLfuncEx3 (waveInUnprepareHeader, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutClose, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutGetNumDevs, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutGetVolume, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutOpen, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutPrepareHeader, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutReset, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutSetVolume, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutUnprepareHeader, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutWrite, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutMessage, winmm, 1, 0) +LoadDLLfuncEx3 (waveOutGetDevCapsA, winmm, 1, 0) LoadDLLfunc (accept, ws2_32) LoadDLLfunc (bind, ws2_32)