        s lpBuffers dwBufferCount lpNumberOfBytesRecvd
        lpFlags lpFrom lpFromLen lpOverlapped lpCompletionRoutine ;
 
-: make-receive-buffer ( n buf -- WSABUF )
+:: make-receive-buffer ( n buf -- buf' WSABUF )
+    buf >c-ptr pinned-alien?
+    [ buf ] [ n malloc [ buf n memcpy ] keep ] if :> buf'
+    buf'
     WSABUF malloc-struct &free
         n >>len
-        buf >>buf ; inline
-
-:: <WSARecvFrom-args> ( n buf datagram -- WSARecvFrom )
+        buf' >>buf ; inline
+
+:: <WSARecvFrom-args> ( n buf datagram -- buf buf' WSARecvFrom )
+    n buf make-receive-buffer :> ( buf' wsaBuf )
+    buf buf'
     WSARecvFrom-args new
         datagram >>port
         datagram handle>> handle>> >>s
         datagram addr>> sockaddr-size
             [ malloc &free >>lpFrom ]
             [ malloc-int &free >>lpFromLen ] bi
-        n buf make-receive-buffer >>lpBuffers
+        wsaBuf >>lpBuffers
         1 >>dwBufferCount
         0 malloc-int &free >>lpFlags
         0 malloc-int &free >>lpNumberOfBytesRecvd

    s name namelen lpSendBuffer dwSendDataLength
    lpdwBytesSent lpOverlapped ptr ;

: wait-for-socket ( args -- n )
    [ lpOverlapped>> ] [ port>> ] bi twiddle-thumbs ; inline

: <ConnectEx-args> ( sockaddr size -- ConnectEx )

        [ lpCompletionRoutine>> ]
    } cleave WSARecvFrom socket-error* ; inline

:: finalize-buf ( buf buf' count -- )
    buf buf' eq? [ buf buf' count memcpy ] unless ; inline

:: parse-WSARecvFrom ( buf buf' count wsaRecvFrom -- count sockaddr )
    buf buf' count finalize-buf
    wsaRecvFrom
    [ port>> addr>> empty-sockaddr dup ]
    [ lpFrom>> ]
    [ lpFromLen>> int deref ]
    tri memcpy ; inline

M: windows (receive) ( n buf datagram -- count addrspec )
    [
        <WSARecvFrom-args>
        [ call-WSARecvFrom ]
