diff --git a/core/libc/libc-tests.factor b/core/libc/libc-tests.factor
new file mode 100755
index 0000000000..249399bdd0
--- /dev/null
+++ b/core/libc/libc-tests.factor
@@ -0,0 +1,11 @@
+IN: libc.tests
+USING: libc libc.private tools.test namespaces assocs
+destructors kernel ;
+
+100 malloc "block" set
+
+[ t ] [ "block" get mallocs get key? ] unit-test
+
+[ ] [ [ "block" get &free drop ] with-destructors ] unit-test
+
+[ f ] [ "block" get mallocs get key? ] unit-test
diff --git a/core/libc/libc.factor b/core/libc/libc.factor
index cba0b9253f..dff6e9e0f1 100755
--- a/core/libc/libc.factor
+++ b/core/libc/libc.factor
@@ -81,14 +81,14 @@ PRIVATE>
 <PRIVATE
 
 ! Memory allocations
-TUPLE: memory-destructor alien ;
+TUPLE: memory-destructor alien disposed ;
 
 M: memory-destructor dispose* alien>> free ;
 
 PRIVATE>
 
 : &free ( alien -- alien )
-    dup memory-destructor boa &dispose drop ; inline
+    dup f memory-destructor boa &dispose drop ; inline
 
 : |free ( alien -- alien )
-    dup memory-destructor boa |dispose drop ; inline
+    dup f memory-destructor boa |dispose drop ; inline
diff --git a/extra/io/mmap/mmap-docs.factor b/extra/io/mmap/mmap-docs.factor
index 0c8148d6b0..4ac85232b8 100755
--- a/extra/io/mmap/mmap-docs.factor
+++ b/extra/io/mmap/mmap-docs.factor
@@ -16,6 +16,11 @@ HELP: <mapped-file>
 { $notes "You must call " { $link close-mapped-file } " when you are finished working with the returned object, to reclaim resources. The " { $link with-mapped-file } " provides an abstraction which can close the mapped file for you." }
 { $errors "Throws an error if a memory mapping could not be established." } ;
 
+HELP: with-mapped-file
+{ $values { "path" "a pathname string" } { "length" integer } { "quot" "a quotation with stack effect " { $snippet "( mmap -- )" } } }
+{ $contract "Opens a file and maps its contents into memory, passing the " { $link mapped-file } " instance to the quotation. The mapped file is disposed of when the quotation returns, or if an error is thrown." }
+{ $errors "Throws an error if a memory mapping could not be established." } ;
+
 HELP: close-mapped-file
 { $values { "mmap" mapped-file } }
 { $contract "Releases system resources associated with the mapped file. This word should not be called by user code; use " { $link dispose } " instead." }
diff --git a/extra/io/mmap/mmap-tests.factor b/extra/io/mmap/mmap-tests.factor
index da3ed38688..d25097e2b0 100755
--- a/extra/io/mmap/mmap-tests.factor
+++ b/extra/io/mmap/mmap-tests.factor
@@ -2,11 +2,14 @@ USING: io io.mmap io.files kernel tools.test continuations
 sequences io.encodings.ascii accessors ;
 IN: io.mmap.tests
 
-[ "resource:mmap-test-file.txt" delete-file ] ignore-errors
-[ ] [ "12345" "resource:mmap-test-file.txt" ascii set-file-contents ] unit-test
-[ ] [ "resource:mmap-test-file.txt" dup file-info size>> [ CHAR: 2 0 pick set-nth drop ] with-mapped-file ] unit-test
-[ 5 ] [ "resource:mmap-test-file.txt" dup file-info size>> [ length ] with-mapped-file ] unit-test
-[ "22345" ] [ "resource:mmap-test-file.txt" ascii file-contents ] unit-test
-[ "resource:mmap-test-file.txt" delete-file ] ignore-errors
-
+[ "mmap-test-file.txt" temp-file delete-file ] ignore-errors
+[ ] [ "12345" "mmap-test-file.txt" temp-file ascii set-file-contents ] unit-test
+[ ] [ "mmap-test-file.txt" temp-file dup file-info size>> [ CHAR: 2 0 pick set-nth drop ] with-mapped-file ] unit-test
+[ 5 ] [ "mmap-test-file.txt" temp-file dup file-info size>> [ length ] with-mapped-file ] unit-test
+[ "22345" ] [ "mmap-test-file.txt" temp-file ascii file-contents ] unit-test
+[ "mmap-test-file.txt" temp-file delete-file ] ignore-errors
 
+[ ] [ "a" "mmap-grow-test.txt" temp-file ascii set-file-contents ] unit-test
+[ 1 ] [ "mmap-grow-test.txt" temp-file file-info size>> ] unit-test
+[ ] [ "mmap-grow-test.txt" temp-file 100 [ drop ] with-mapped-file ] unit-test
+[ 100 ] [ "mmap-grow-test.txt" temp-file file-info size>> ] unit-test
diff --git a/extra/io/sockets/sockets.factor b/extra/io/sockets/sockets.factor
index 40f6c22b82..36a0559bdb 100755
--- a/extra/io/sockets/sockets.factor
+++ b/extra/io/sockets/sockets.factor
@@ -27,10 +27,10 @@ GENERIC: inet-ntop ( data addrspec -- str )
 GENERIC: inet-pton ( str addrspec -- data )
 
 : make-sockaddr/size ( addrspec -- sockaddr size )
-    dup make-sockaddr swap sockaddr-type heap-size ;
+    [ make-sockaddr ] [ sockaddr-type heap-size ] bi ;
 
-: empty-sockaddr/size ( addrspec -- sockaddr len )
-    sockaddr-type [ <c-object> ] [ heap-size <int> ] bi ;
+: empty-sockaddr/size ( addrspec -- sockaddr size )
+    sockaddr-type [ <c-object> ] [ heap-size ] bi ;
 
 GENERIC: parse-sockaddr ( sockaddr addrspec -- newaddrspec )
 
diff --git a/extra/io/unix/mmap/mmap.factor b/extra/io/unix/mmap/mmap.factor
index 14ad49a89a..c31e23849e 100755
--- a/extra/io/unix/mmap/mmap.factor
+++ b/extra/io/unix/mmap/mmap.factor
@@ -6,7 +6,7 @@ IN: io.unix.mmap
 
 : open-r/w ( path -- fd ) O_RDWR file-mode open-file ;
 
-:: mmap-open ( length prot flags path -- alien fd )
+:: mmap-open ( path length prot flags -- alien fd )
     [
         f length prot flags
         path open-r/w |dispose
@@ -14,10 +14,9 @@ IN: io.unix.mmap
     ] with-destructors ;
 
 M: unix (mapped-file)
-    swap >r
     { PROT_READ PROT_WRITE } flags
     { MAP_FILE MAP_SHARED } flags
-    r> mmap-open ;
+    mmap-open ;
 
 M: unix close-mapped-file ( mmap -- )
     [ [ address>> ] [ length>> ] bi munmap io-error ]
diff --git a/extra/io/unix/sockets/sockets.factor b/extra/io/unix/sockets/sockets.factor
old mode 100644
new mode 100755
index 910f87a163..0bb0e3405a
--- a/extra/io/unix/sockets/sockets.factor
+++ b/extra/io/unix/sockets/sockets.factor
@@ -23,7 +23,7 @@ M: unix addrinfo-error ( n -- )
 
 ! Client sockets - TCP and Unix domain
 M: object (get-local-address) ( handle remote -- sockaddr )
-    >r handle-fd r> empty-sockaddr/size
+    >r handle-fd r> empty-sockaddr/size <int>
     [ getsockname io-error ] 2keep drop ;
 
 : init-client-socket ( fd -- )
@@ -67,7 +67,7 @@ M: object (server) ( addrspec -- handle )
     ] with-destructors ;
 
 : do-accept ( server addrspec -- fd )
-    [ handle>> handle-fd ] [ empty-sockaddr/size ] bi* accept ; inline
+    [ handle>> handle-fd ] [ empty-sockaddr/size <int> ] bi* accept ; inline
 
 M: object (accept) ( server addrspec -- fd )
     2dup do-accept
@@ -100,7 +100,7 @@ packet-size <byte-array> receive-buffer set-global
         packet-size ! nbytes
         0 ! flags
         sockaddr ! from
-        len ! fromlen
+        len <int> ! fromlen
         recvfrom dup 0 >= [
             receive-buffer get-global swap head sockaddr
         ] [
diff --git a/extra/io/windows/ce/privileges/privileges.factor b/extra/io/windows/ce/privileges/privileges.factor
new file mode 100755
index 0000000000..e0aa186b3d
--- /dev/null
+++ b/extra/io/windows/ce/privileges/privileges.factor
@@ -0,0 +1,4 @@
+IN: io.windows.ce.privileges
+USING: io.windows.privileges system ;
+
+M: wince set-privilege 2drop ;
diff --git a/extra/io/windows/files/files.factor b/extra/io/windows/files/files.factor
index ed6ca0bc54..ef3db0dcd1 100755
--- a/extra/io/windows/files/files.factor
+++ b/extra/io/windows/files/files.factor
@@ -1,11 +1,121 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien.c-types io.backend io.files io.windows kernel math
+USING: alien.c-types io.binary io.backend io.files io.buffers
+io.windows kernel math splitting
 windows windows.kernel32 windows.time calendar combinators
 math.functions sequences namespaces words symbols system
-combinators.lib io.ports destructors math.bitfields.lib ;
+combinators.lib io.ports destructors accessors
+math.bitfields math.bitfields.lib ;
 IN: io.windows.files
 
+: open-file ( path access-mode create-mode flags -- handle )
+    [
+        >r >r share-mode security-attributes-inherit r> r>
+        CreateFile-flags f CreateFile opened-file
+    ] with-destructors ;
+
+: open-pipe-r/w ( path -- win32-file )
+    { GENERIC_READ GENERIC_WRITE } flags
+    OPEN_EXISTING 0 open-file ;
+
+: open-read ( path -- win32-file )
+    GENERIC_READ OPEN_EXISTING 0 open-file 0 >>ptr ;
+
+: open-write ( path -- win32-file )
+    GENERIC_WRITE CREATE_ALWAYS 0 open-file 0 >>ptr ;
+
+: (open-append) ( path -- win32-file )
+    GENERIC_WRITE OPEN_ALWAYS 0 open-file ;
+
+: open-existing ( path -- win32-file )
+    { GENERIC_READ GENERIC_WRITE } flags
+    share-mode
+    f
+    OPEN_EXISTING
+    FILE_FLAG_BACKUP_SEMANTICS
+    f CreateFileW dup win32-error=0/f <win32-file> ;
+
+: maybe-create-file ( path -- win32-file ? )
+    #! return true if file was just created
+    { GENERIC_READ GENERIC_WRITE } flags
+    share-mode
+    f
+    OPEN_ALWAYS
+    0 CreateFile-flags
+    f CreateFileW dup win32-error=0/f <win32-file>
+    GetLastError ERROR_ALREADY_EXISTS = not ;
+
+: set-file-pointer ( handle length method -- )
+    >r dupd d>w/w <uint> r> SetFilePointer
+    INVALID_SET_FILE_POINTER = [
+        CloseHandle "SetFilePointer failed" throw
+    ] when drop ;
+
+HOOK: open-append os ( path -- win32-file )
+
+TUPLE: FileArgs
+    hFile lpBuffer nNumberOfBytesToRead
+    lpNumberOfBytesRet lpOverlapped ;
+
+C: <FileArgs> FileArgs
+
+: make-FileArgs ( port -- <FileArgs> )
+    {
+        [ handle>> handle>> ]
+        [ buffer>> ]
+        [ buffer>> buffer-length ]
+        [ drop "DWORD" <c-object> ]
+        [ FileArgs-overlapped ]
+    } cleave <FileArgs> ;
+
+: setup-read ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRead lpOverlapped )
+    {
+        [ hFile>> ]
+        [ lpBuffer>> buffer-end ]
+        [ lpBuffer>> buffer-capacity ]
+        [ lpNumberOfBytesRet>> ]
+        [ lpOverlapped>> ]
+    } cleave ;
+
+: setup-write ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToWrite lpNumberOfBytesWritten lpOverlapped )
+    {
+        [ hFile>> ]
+        [ lpBuffer>> buffer@ ]
+        [ lpBuffer>> buffer-length ]
+        [ lpNumberOfBytesRet>> ]
+        [ lpOverlapped>> ]
+    } cleave ;
+
+M: windows (file-reader) ( path -- stream )
+    open-read <input-port> ;
+
+M: windows (file-writer) ( path -- stream )
+    open-write <output-port> ;
+
+M: windows (file-appender) ( path -- stream )
+    open-append <output-port> ;
+
+M: windows move-file ( from to -- )
+    [ normalize-path ] bi@ MoveFile win32-error=0/f ;
+
+M: windows delete-file ( path -- )
+    normalize-path DeleteFile win32-error=0/f ;
+
+M: windows copy-file ( from to -- )
+    dup parent-directory make-directories
+    [ normalize-path ] bi@ 0 CopyFile win32-error=0/f ;
+
+M: windows make-directory ( path -- )
+    normalize-path
+    f CreateDirectory win32-error=0/f ;
+
+M: windows delete-directory ( path -- )
+    normalize-path
+    RemoveDirectory win32-error=0/f ;
+
+M: windows normalize-directory ( string -- string )
+    normalize-path "\\" ?tail drop "\\*" append ;
+
 SYMBOLS: +read-only+ +hidden+ +system+
 +archive+ +device+ +normal+ +temporary+
 +sparse-file+ +reparse-point+ +compressed+ +offline+
@@ -101,7 +211,7 @@ M: winnt link-info ( path -- info )
 
 : file-times ( path -- timestamp timestamp timestamp )
     [
-        normalize-path open-existing dup close-always
+        normalize-path open-existing &dispose handle>>
         "FILETIME" <c-object>
         "FILETIME" <c-object>
         "FILETIME" <c-object>
@@ -117,7 +227,7 @@ M: winnt link-info ( path -- info )
     #! timestamp order: creation access write
     [
         >r >r >r
-            normalize-path open-existing dup close-always
+            normalize-path open-existing &dispose handle>>
         r> r> r> (set-file-times)
     ] with-destructors ;
 
@@ -133,6 +243,6 @@ M: winnt link-info ( path -- info )
 M: winnt touch-file ( path -- )
     [
         normalize-path
-        maybe-create-file over close-always
-        [ drop ] [ f now dup (set-file-times) ] if
+        maybe-create-file >r &dispose r>
+        [ drop ] [ handle>> f now dup (set-file-times) ] if
     ] with-destructors ;
diff --git a/extra/io/windows/files/unique/unique.factor b/extra/io/windows/files/unique/unique.factor
old mode 100644
new mode 100755
index 2c166373e7..dcb713df7f
--- a/extra/io/windows/files/unique/unique.factor
+++ b/extra/io/windows/files/unique/unique.factor
@@ -1,10 +1,10 @@
 USING: kernel system io.files.unique.backend
-windows.kernel32 io.windows io.ports windows ;
+windows.kernel32 io.windows io.windows.files io.ports windows
+destructors ;
 IN: io.windows.files.unique
 
 M: windows (make-unique-file) ( path -- )
-    GENERIC_WRITE CREATE_NEW 0 open-file
-    CloseHandle win32-error=0/f ;
+    GENERIC_WRITE CREATE_NEW 0 open-file dispose ;
 
 M: windows temporary-path ( -- path )
     "TEMP" os-env ;
diff --git a/extra/io/windows/launcher/launcher.factor b/extra/io/windows/launcher/launcher.factor
index 28e7e241e5..1cfb91d716 100755
--- a/extra/io/windows/launcher/launcher.factor
+++ b/extra/io/windows/launcher/launcher.factor
@@ -6,7 +6,7 @@ windows.types math windows.kernel32
 namespaces io.launcher kernel sequences windows.errors
 splitting system threads init strings combinators
 io.backend accessors concurrency.flags io.files assocs
-io.files.private windows destructors ;
+io.files.private windows destructors classes.tuple.lib ;
 IN: io.windows.launcher
 
 TUPLE: CreateProcess-args
@@ -19,8 +19,7 @@ TUPLE: CreateProcess-args
        lpEnvironment
        lpCurrentDirectory
        lpStartupInfo
-       lpProcessInformation
-       stdout-pipe stdin-pipe ;
+       lpProcessInformation ;
 
 : default-CreateProcess-args ( -- obj )
     CreateProcess-args new
@@ -31,18 +30,7 @@ TUPLE: CreateProcess-args
     0 >>dwCreateFlags ;
 
 : call-CreateProcess ( CreateProcess-args -- )
-    {
-        lpApplicationName>>
-        lpCommandLine>>
-        lpProcessAttributes>>
-        lpThreadAttributes>>
-        bInheritHandles>>
-        dwCreateFlags>>
-        lpEnvironment>>
-        lpCurrentDirectory>>
-        lpStartupInfo>>
-        lpProcessInformation>>
-    } get-slots CreateProcess win32-error=0/f ;
+    CreateProcess-args >tuple< CreateProcess win32-error=0/f ;
 
 : count-trailing-backslashes ( str n -- str n )
     >r "\\" ?tail [
diff --git a/extra/io/windows/mmap/mmap.factor b/extra/io/windows/mmap/mmap.factor
index b401ed5556..72dfca9df3 100755
--- a/extra/io/windows/mmap/mmap.factor
+++ b/extra/io/windows/mmap/mmap.factor
@@ -1,88 +1,44 @@
-USING: alien alien.c-types alien.syntax arrays continuations
-destructors generic io.mmap io.ports io.windows
-kernel libc math namespaces quotations sequences windows
-windows.advapi32 windows.kernel32 io.backend system ;
+USING: alien alien.c-types arrays destructors generic io.mmap
+io.ports io.windows io.windows.files io.windows.privileges
+kernel libc math math.bitfields namespaces quotations sequences
+windows windows.advapi32 windows.kernel32 io.backend system
+accessors locals ;
 IN: io.windows.mmap
 
-TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES
+: create-file-mapping
+    CreateFileMapping [ win32-error=0/f ] keep <win32-handle> ;
 
-! Security tokens
-!  http://msdn.microsoft.com/msdnmag/issues/05/03/TokenPrivileges/
+: map-view-of-file
+    MapViewOfFile [ win32-error=0/f ] keep ;
 
-: (open-process-token) ( handle -- handle )
-    TOKEN_ADJUST_PRIVILEGES TOKEN_QUERY bitor "PHANDLE" <c-object>
-    [ OpenProcessToken win32-error=0/f ] keep *void* ;
+:: mmap-open ( path length access-mode create-mode protect access -- handle handle address )
+    [let | lo [ length HEX: ffffffff bitand ]
+           hi [ length -32 shift HEX: ffffffff bitand ] |
+        { "SeCreateGlobalPrivilege" "SeLockMemoryPrivilege" } [
+            path access-mode create-mode 0 open-file |dispose
+            dup handle>> f protect hi lo f create-file-mapping |dispose
+            dup handle>> access 0 0 0 map-view-of-file
+        ] with-privileges
+    ] ;
 
-: open-process-token ( -- handle )
-    #! remember to handle-close this
-    GetCurrentProcess (open-process-token) ;
+TUPLE: win32-mapped-file file mapping ;
 
-: with-process-token ( quot -- )
-    #! quot: ( token-handle -- token-handle )
-    >r open-process-token r>
-    [ keep ] curry
-    [ CloseHandle drop ] [ ] cleanup ; inline
+M: win32-mapped-file dispose
+    [ file>> dispose ] [ mapping>> dispose ] bi ;
 
-: lookup-privilege ( string -- luid )
-    >r f r> "LUID" <c-object>
-    [ LookupPrivilegeValue win32-error=0/f ] keep ;
+C: <win32-mapped-file> win32-mapped-file
 
-: make-token-privileges ( name ? -- obj )
-    "TOKEN_PRIVILEGES" <c-object>
-    1 [ over set-TOKEN_PRIVILEGES-PrivilegeCount ] keep
-    "LUID_AND_ATTRIBUTES" malloc-array
-    dup free-always over set-TOKEN_PRIVILEGES-Privileges
-
-    swap [
-        SE_PRIVILEGE_ENABLED over TOKEN_PRIVILEGES-Privileges
-        set-LUID_AND_ATTRIBUTES-Attributes
-    ] when
-
-    >r lookup-privilege r>
+M: windows (mapped-file)
     [
-        TOKEN_PRIVILEGES-Privileges
-        >r 0 r> LUID_AND_ATTRIBUTES-nth
-        set-LUID_AND_ATTRIBUTES-Luid
-    ] keep ;
-
-: set-privilege ( name ? -- )
-    [
-        -rot 0 -rot make-token-privileges
-        dup length f f AdjustTokenPrivileges win32-error=0/f
-    ] with-process-token ;
-
-HOOK: with-privileges io-backend ( seq quot -- ) inline
-
-M: winnt with-privileges
-    over [ [ t set-privilege ] each ] curry compose
-    swap [ [ f set-privilege ] each ] curry [ ] cleanup ;
-
-M: wince with-privileges
-    nip call ;
-
-: mmap-open ( path access-mode create-mode flProtect access -- handle handle address )
-    { "SeCreateGlobalPrivilege" "SeLockMemoryPrivilege" } [
-        >r >r 0 open-file dup f r> 0 0 f
-        CreateFileMapping [ win32-error=0/f ] keep
-        dup close-later
-        dup
-        r> 0 0 0 MapViewOfFile [ win32-error=0/f ] keep
-        dup close-later
-    ] with-privileges ;
-    
-M: windows (mapped-file) ( path length -- mmap )
-    [
-        swap
-        GENERIC_WRITE GENERIC_READ bitor
+        { GENERIC_WRITE GENERIC_READ } flags
         OPEN_ALWAYS
-        PAGE_READWRITE SEC_COMMIT bitor
+        { PAGE_READWRITE SEC_COMMIT } flags
         FILE_MAP_ALL_ACCESS mmap-open
-        -rot 2array
-        f \ mapped-file boa
+        -rot <win32-mapped-file>
     ] with-destructors ;
 
 M: windows close-mapped-file ( mapped-file -- )
     [
-        dup mapped-file-handle [ close-always ] each
-        mapped-file-address UnmapViewOfFile win32-error=0/f
+        [ handle>> &dispose drop ]
+        [ address>> UnmapViewOfFile win32-error=0/f ] bi
     ] with-destructors ;
diff --git a/extra/io/windows/nt/backend/backend.factor b/extra/io/windows/nt/backend/backend.factor
index 99364f832d..134a0c024a 100755
--- a/extra/io/windows/nt/backend/backend.factor
+++ b/extra/io/windows/nt/backend/backend.factor
@@ -1,9 +1,10 @@
 USING: alien alien.c-types arrays assocs combinators
-continuations destructors io io.backend io.ports
-io.windows libc kernel math namespaces sequences
-threads classes.tuple.lib windows windows.errors
-windows.kernel32 strings splitting io.files qualified ascii
-combinators.lib system accessors ;
+continuations destructors io io.backend io.ports io.timeouts
+io.windows io.windows.files libc kernel math namespaces
+sequences threads classes.tuple.lib windows windows.errors
+windows.kernel32 strings splitting io.files
+io.buffers qualified ascii combinators.lib system
+accessors locals ;
 QUALIFIED: windows.winsock
 IN: io.windows.nt.backend
 
@@ -14,11 +15,11 @@ TUPLE: io-callback port thread ;
 C: <io-callback> io-callback
 
 : (make-overlapped) ( -- overlapped-ext )
-    "OVERLAPPED" malloc-object dup free-always ;
+    "OVERLAPPED" malloc-object &free ;
 
 : make-overlapped ( port -- overlapped-ext )
-    >r (make-overlapped) r> port-handle win32-file-ptr
-    [ over set-OVERLAPPED-offset ] when* ;
+    >r (make-overlapped)
+    r> handle>> ptr>> [ over set-OVERLAPPED-offset ] when* ;
 
 : <completion-port> ( handle existing -- handle )
      f 1 CreateIoCompletionPort dup win32-error=0/f ;
@@ -28,8 +29,8 @@ SYMBOL: master-completion-port
 : <master-completion-port> ( -- handle )
     INVALID_HANDLE_VALUE f <completion-port> ;
 
-M: winnt add-completion ( handle -- )
-    master-completion-port get-global <completion-port> drop ;
+M: winnt add-completion ( win32-handle -- )
+    handle>> master-completion-port get-global <completion-port> drop ;
 
 : eof? ( error -- ? )
     dup ERROR_HANDLE_EOF = swap ERROR_BROKEN_PIPE = or ;
@@ -56,13 +57,21 @@ M: winnt add-completion ( handle -- )
         io-hash get-global set-at
     ] "I/O" suspend 3drop ;
 
-: wait-for-overlapped ( ms -- overlapped ? )
-    >r master-completion-port get-global
-    r> INFINITE or ! timeout
+: twiddle-thumbs ( overlapped port -- bytes-transferred )
+    [ save-callback ]
+    [ get-overlapped-result ]
+    [ nip pending-error ]
+    2tri ;
+
+:: wait-for-overlapped ( ms -- overlapped ? )
+    master-completion-port get-global
     0 <int> ! bytes
     f <void*> ! key
     f <void*> ! overlapped
-    [ roll GetQueuedCompletionStatus ] keep *void* swap zero? ;
+    [
+        ms INFINITE or ! timeout
+        GetQueuedCompletionStatus
+    ] keep *void* swap zero? ;
 
 : lookup-callback ( overlapped -- callback )
     io-hash get-global delete-at* drop
@@ -70,32 +79,64 @@ M: winnt add-completion ( handle -- )
 
 : handle-overlapped ( timeout -- ? )
     wait-for-overlapped [
-        GetLastError dup expected-io-error? [
-            2drop t
-        ] [
-            dup eof? [
-                drop lookup-callback
-                dup port>> t >>eof drop
-            ] [
-                (win32-error-string) swap lookup-callback
-                [ port>> set-port-error ] keep
-            ] if thread>> resume f
+        GetLastError dup expected-io-error? [ 2drop f ] [
+            >r lookup-callback [ thread>> ] [ port>> ] bi r>
+            dup eof?
+            [ drop t >>eof ]
+            [ (win32-error-string) >>error ] if drop
+            resume t
         ] if
     ] [
         lookup-callback
-        io-callback-thread resume f
+        thread>> resume t
     ] if ;
 
-: drain-overlapped ( timeout -- )
-    handle-overlapped [ 0 drain-overlapped ] unless ;
-
 M: winnt cancel-io
     handle>> handle>> CancelIo drop ;
 
 M: winnt io-multiplex ( ms -- )
-    drain-overlapped ;
+    handle-overlapped [ 0 io-multiplex ] when ;
 
 M: winnt init-io ( -- )
     <master-completion-port> master-completion-port set-global
     H{ } clone io-hash set-global
     windows.winsock:init-winsock ;
+
+: update-file-ptr ( n port -- )
+    handle>> dup ptr>> [ rot + >>ptr drop ] [ 2drop ] if* ;
+
+: finish-flush ( n port -- )
+    [ update-file-ptr ] [ buffer>> buffer-consume ] 2bi ;
+
+: ((wait-to-write)) ( port -- )
+    dup make-FileArgs
+    tuck setup-write WriteFile
+    dupd overlapped-error? [
+        >r lpOverlapped>> r>
+        [ twiddle-thumbs ] keep
+        [ finish-flush ] keep
+        dup buffer>> buffer-empty? [ drop ] [ ((wait-to-write)) ] if
+    ] [
+        2drop
+    ] if ;
+
+M: winnt (wait-to-write)
+    [ [ ((wait-to-write)) ] with-timeout ] with-destructors ;
+
+: finish-read ( n port -- )
+    over zero? [
+        t >>eof 2drop
+    ] [
+        [ buffer>> n>buffer ] [ update-file-ptr ] 2bi
+    ] if ;
+
+: ((wait-to-read)) ( port -- )
+    dup make-FileArgs
+    tuck setup-read ReadFile
+    dupd overlapped-error? [
+        >r lpOverlapped>> r>
+        [ twiddle-thumbs ] [ finish-read ] bi
+    ] [ 2drop ] if ;
+
+M: winnt (wait-to-read) ( port -- )
+    [ [ ((wait-to-read)) ] with-timeout ] with-destructors ;
diff --git a/extra/io/windows/nt/files/files.factor b/extra/io/windows/nt/files/files.factor
index 2b3021a3f1..67161716a3 100755
--- a/extra/io/windows/nt/files/files.factor
+++ b/extra/io/windows/nt/files/files.factor
@@ -1,6 +1,7 @@
 USING: continuations destructors io.buffers io.files io.backend
-io.timeouts io.ports io.windows io.windows.nt.backend
-kernel libc math threads windows windows.kernel32 system
+io.timeouts io.ports io.windows io.windows.files
+io.windows.nt.backend windows windows.kernel32
+kernel libc math threads system
 alien.c-types alien.arrays alien.strings sequences combinators
 combinators.lib sequences.lib ascii splitting alien strings
 assocs namespaces io.files.private accessors ;
@@ -29,6 +30,7 @@ M: winnt root-directory? ( path -- ? )
     } cond nip ;
 
 ERROR: not-absolute-path ;
+
 : root-directory ( string -- string' )
     {
         [ dup length 2 >= ]
@@ -54,57 +56,4 @@ M: winnt FileArgs-overlapped ( port -- overlapped )
 
 M: winnt open-append
     [ dup file-info size>> ] [ drop 0 ] recover
-    >r (open-append) r> ;
-
-: update-file-ptr ( n port -- )
-    port-handle
-    dup win32-file-ptr [
-        rot + swap set-win32-file-ptr
-    ] [
-        2drop
-    ] if* ;
-
-: finish-flush ( overlapped port -- )
-    dup pending-error
-    tuck get-overlapped-result
-    dup pick update-file-ptr
-    swap buffer>> buffer-consume ;
-
-: (flush-output) ( port -- )
-    dup make-FileArgs
-    tuck setup-write WriteFile
-    dupd overlapped-error? [
-        >r FileArgs-lpOverlapped r>
-        [ save-callback ] 2keep
-        [ finish-flush ] keep
-        dup buffer>> buffer-empty? [ drop ] [ (flush-output) ] if
-    ] [
-        2drop
-    ] if ;
-
-: flush-output ( port -- )
-    [ [ (flush-output) ] with-timeout ] with-destructors ;
-
-M: winnt flush-port
-    dup buffer>> buffer-empty? [ dup flush-output ] unless drop ;
-
-: finish-read ( overlapped port -- )
-    dup pending-error
-    tuck get-overlapped-result dup zero? [
-        drop t >>eof drop
-    ] [
-        dup pick buffer>> n>buffer
-        swap update-file-ptr
-    ] if ;
-
-: ((wait-to-read)) ( port -- )
-    dup make-FileArgs
-    tuck setup-read ReadFile
-    dupd overlapped-error? [
-        >r FileArgs-lpOverlapped r>
-        [ save-callback ] 2keep
-        finish-read
-    ] [ 2drop ] if ;
-
-M: winnt (wait-to-read) ( port -- )
-    [ [ ((wait-to-read)) ] with-timeout ] with-destructors ;
+    >r (open-append) r> >>ptr ;
diff --git a/extra/io/windows/nt/launcher/launcher.factor b/extra/io/windows/nt/launcher/launcher.factor
index c18523e68d..6c86b53049 100755
--- a/extra/io/windows/nt/launcher/launcher.factor
+++ b/extra/io/windows/nt/launcher/launcher.factor
@@ -4,8 +4,9 @@ USING: alien alien.c-types arrays continuations destructors io
 io.windows libc io.ports io.pipes windows.types
 math windows.kernel32 windows namespaces io.launcher kernel
 sequences windows.errors assocs splitting system strings
-io.windows.launcher io.windows.nt.pipes io.backend io.files
-io.files.private combinators shuffle accessors locals ;
+io.windows.launcher io.windows.files
+io.backend io.files io.files.private combinators shuffle
+accessors locals ;
 IN: io.windows.nt.launcher
 
 : duplicate-handle ( handle -- handle' )
@@ -21,10 +22,10 @@ IN: io.windows.nt.launcher
 
 ! /dev/null simulation
 : null-input ( -- pipe )
-    (pipe) [ in>> handle>> ] [ out>> close-handle ] bi ;
+    (pipe) [ in>> handle>> ] [ out>> dispose ] bi ;
 
 : null-output ( -- pipe )
-    (pipe) [ in>> close-handle ] [ out>> handle>> ] bi ;
+    (pipe) [ in>> dispose ] [ out>> handle>> ] bi ;
 
 : null-pipe ( mode -- pipe )
     {
@@ -35,13 +36,13 @@ IN: io.windows.nt.launcher
 ! The below code is based on the example given in
 ! http://msdn2.microsoft.com/en-us/library/ms682499.aspx
 
-: redirect-default ( default obj access-mode create-mode -- handle )
-    3drop ;
+: redirect-default ( obj access-mode create-mode -- handle )
+    3drop f ;
 
-: redirect-closed ( default obj access-mode create-mode -- handle )
-    drop 2nip null-pipe ;
+: redirect-closed ( obj access-mode create-mode -- handle )
+    drop nip null-pipe ;
 
-:: redirect-file ( default path access-mode create-mode -- handle )
+:: redirect-file ( path access-mode create-mode -- handle )
     path normalize-path
     access-mode
     share-mode
@@ -49,9 +50,9 @@ IN: io.windows.nt.launcher
     create-mode
     FILE_ATTRIBUTE_NORMAL ! flags and attributes
     f ! template file
-    CreateFile dup invalid-handle? dup close-always ;
+    CreateFile dup invalid-handle? <win32-file> &dispose handle>> ;
 
-: redirect-append ( default path access-mode create-mode -- handle )
+: redirect-append ( path access-mode create-mode -- handle )
     >r >r path>> r> r>
     drop OPEN_ALWAYS
     redirect-file
@@ -60,14 +61,13 @@ IN: io.windows.nt.launcher
 : set-inherit ( handle ? -- )
     >r HANDLE_FLAG_INHERIT r> >BOOLEAN SetHandleInformation win32-error=0/f ;
 
-: redirect-handle ( default handle access-mode create-mode -- handle )
-    2drop nip
-    handle>> duplicate-handle dup t set-inherit ;
+: redirect-handle ( handle access-mode create-mode -- handle )
+    2drop handle>> duplicate-handle dup t set-inherit ;
 
-: redirect-stream ( default stream access-mode create-mode -- handle )
-    >r >r underlying-handle r> r> redirect-handle ;
+: redirect-stream ( stream access-mode create-mode -- handle )
+    >r >r underlying-handle handle>> r> r> redirect-handle ;
 
-: redirect ( default obj access-mode create-mode -- handle )
+: redirect ( obj access-mode create-mode -- handle )
     {
         { [ pick not ] [ redirect-default ] }
         { [ pick +closed+ eq? ] [ redirect-closed ] }
@@ -77,12 +77,9 @@ IN: io.windows.nt.launcher
         [ redirect-stream ]
     } cond ;
 
-: default-stdout ( args -- handle )
-    stdout-pipe>> dup [ out>> ] when ;
-
 : redirect-stdout ( process args -- handle )
-    default-stdout
-    swap stdout>>
+    drop
+    stdout>>
     GENERIC_WRITE
     CREATE_ALWAYS
     redirect
@@ -90,25 +87,20 @@ IN: io.windows.nt.launcher
 
 : redirect-stderr ( process args -- handle )
     over stderr>> +stdout+ eq? [
-        lpStartupInfo>>
-        STARTUPINFO-hStdOutput
         nip
+        lpStartupInfo>> STARTUPINFO-hStdOutput
     ] [
         drop
-        f
-        swap stderr>>
+        stderr>>
         GENERIC_WRITE
         CREATE_ALWAYS
         redirect
         STD_ERROR_HANDLE GetStdHandle or
     ] if ;
 
-: default-stdin ( args -- handle )
-    stdin-pipe>> dup [ in>> ] when ;
-
 : redirect-stdin ( process args -- handle )
-    default-stdin
-    swap stdin>>
+    drop
+    stdin>>
     GENERIC_READ
     OPEN_EXISTING
     redirect
diff --git a/extra/io/windows/nt/monitors/monitors.factor b/extra/io/windows/nt/monitors/monitors.factor
index ee8c6c60e1..a509d1d5e7 100755
--- a/extra/io/windows/nt/monitors/monitors.factor
+++ b/extra/io/windows/nt/monitors/monitors.factor
@@ -17,11 +17,7 @@ IN: io.windows.nt.monitors
     OPEN_EXISTING
     { FILE_FLAG_BACKUP_SEMANTICS FILE_FLAG_OVERLAPPED } flags
     f
-    CreateFile
-    dup invalid-handle?
-    dup close-later
-    dup add-completion
-    f <win32-file> ;
+    CreateFile opened-file ;
 
 TUPLE: win32-monitor-port < input-port recursive ;
 
@@ -41,11 +37,7 @@ TUPLE: win32-monitor < monitor port ;
 
 : read-changes ( port -- bytes )
     [
-        dup begin-reading-changes
-        swap [ save-callback ] 2keep
-        check-closed ! we may have closed it...
-        dup eof>> [ "EOF??" throw ] when
-        get-overlapped-result
+        [ begin-reading-changes ] [ twiddle-thumbs ] bi
     ] with-destructors ;
 
 : parse-action ( action -- changed )
@@ -87,7 +79,7 @@ TUPLE: win32-monitor < monitor port ;
     ] each ;
 
 : fill-queue ( monitor -- )
-    dup port>> check-closed
+    dup port>> dup check-disposed
     [ buffer>> ptr>> ] [ read-changes zero? ] bi
     [ 2dup parse-notify-records ] unless
     2drop ;
@@ -97,7 +89,7 @@ TUPLE: win32-monitor < monitor port ;
 
 : fill-queue-thread ( monitor -- )
     [ dup fill-queue (fill-queue-thread) ]
-    [ dup port-closed-error? [ 2drop ] [ rethrow ] if ] recover ;
+    [ dup already-disposed? [ 2drop ] [ rethrow ] if ] recover ;
 
 M:: winnt (monitor) ( path recursive? mailbox -- monitor )
     [
diff --git a/extra/io/windows/nt/nt.factor b/extra/io/windows/nt/nt.factor
index 33bb3a88b9..8e59a4d555 100755
--- a/extra/io/windows/nt/nt.factor
+++ b/extra/io/windows/nt/nt.factor
@@ -7,6 +7,7 @@ USE: io.windows.nt.backend
 USE: io.windows.nt.files
 USE: io.windows.nt.launcher
 USE: io.windows.nt.monitors
+USE: io.windows.nt.privileges
 USE: io.windows.nt.sockets
 USE: io.windows.mmap
 USE: io.windows.files
diff --git a/extra/io/windows/nt/pipes/pipes.factor b/extra/io/windows/nt/pipes/pipes.factor
index 8a0fa05b74..97c2e49627 100755
--- a/extra/io/windows/nt/pipes/pipes.factor
+++ b/extra/io/windows/nt/pipes/pipes.factor
@@ -17,10 +17,7 @@ IN: io.windows.nt.pipes
     4096
     0
     security-attributes-inherit
-    CreateNamedPipe
-    dup win32-error=0/f
-    dup add-completion
-    f <win32-file> ;
+    CreateNamedPipe opened-file ;
 
 : open-other-end ( name -- handle )
     GENERIC_WRITE
@@ -29,10 +26,7 @@ IN: io.windows.nt.pipes
     OPEN_EXISTING
     FILE_FLAG_OVERLAPPED
     f
-    CreateFile
-    dup win32-error=0/f
-    dup add-completion
-    f <win32-file> ;
+    CreateFile opened-file ;
 
 : unique-pipe-name ( -- string )
     [
@@ -47,7 +41,6 @@ IN: io.windows.nt.pipes
 M: winnt (pipe) ( -- pipe )
     [
         unique-pipe-name
-        [ create-named-pipe dup close-later ]
-        [ open-other-end dup close-later ]
-        bi pipe boa
+        [ create-named-pipe ] [ open-other-end ] bi
+        pipe boa
     ] with-destructors ;
diff --git a/extra/io/windows/nt/privileges/privileges.factor b/extra/io/windows/nt/privileges/privileges.factor
new file mode 100755
index 0000000000..007d05f9af
--- /dev/null
+++ b/extra/io/windows/nt/privileges/privileges.factor
@@ -0,0 +1,53 @@
+USING: alien alien.c-types alien.syntax arrays continuations
+destructors generic io.mmap io.ports io.windows io.windows.files
+kernel libc math math.bitfields namespaces quotations sequences windows
+windows.advapi32 windows.kernel32 io.backend system accessors
+io.windows.privileges ;
+IN: io.windows.nt.privileges
+
+TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES
+
+! Security tokens
+!  http://msdn.microsoft.com/msdnmag/issues/05/03/TokenPrivileges/
+
+: (open-process-token) ( handle -- handle )
+    { TOKEN_ADJUST_PRIVILEGES TOKEN_QUERY } flags "PHANDLE" <c-object>
+    [ OpenProcessToken win32-error=0/f ] keep *void* ;
+
+: open-process-token ( -- handle )
+    #! remember to CloseHandle
+    GetCurrentProcess (open-process-token) ;
+
+: with-process-token ( quot -- )
+    #! quot: ( token-handle -- token-handle )
+    >r open-process-token r>
+    [ keep ] curry
+    [ CloseHandle drop ] [ ] cleanup ; inline
+
+: lookup-privilege ( string -- luid )
+    >r f r> "LUID" <c-object>
+    [ LookupPrivilegeValue win32-error=0/f ] keep ;
+
+: make-token-privileges ( name ? -- obj )
+    "TOKEN_PRIVILEGES" <c-object>
+    1 [ over set-TOKEN_PRIVILEGES-PrivilegeCount ] keep
+    "LUID_AND_ATTRIBUTES" malloc-array &free
+    over set-TOKEN_PRIVILEGES-Privileges
+
+    swap [
+        SE_PRIVILEGE_ENABLED over TOKEN_PRIVILEGES-Privileges
+        set-LUID_AND_ATTRIBUTES-Attributes
+    ] when
+
+    >r lookup-privilege r>
+    [
+        TOKEN_PRIVILEGES-Privileges
+        >r 0 r> LUID_AND_ATTRIBUTES-nth
+        set-LUID_AND_ATTRIBUTES-Luid
+    ] keep ;
+
+M: winnt set-privilege ( name ? -- )
+    [
+        -rot 0 -rot make-token-privileges
+        dup length f f AdjustTokenPrivileges win32-error=0/f
+    ] with-process-token ;
diff --git a/extra/io/windows/nt/sockets/sockets.factor b/extra/io/windows/nt/sockets/sockets.factor
index 5baa0a31e5..75a08a02c4 100755
--- a/extra/io/windows/nt/sockets/sockets.factor
+++ b/extra/io/windows/nt/sockets/sockets.factor
@@ -1,8 +1,9 @@
 USING: alien alien.accessors alien.c-types byte-arrays
 continuations destructors io.ports io.timeouts io.sockets
 io.sockets io namespaces io.streams.duplex io.windows
+io.windows.sockets
 io.windows.nt.backend windows.winsock kernel libc math sequences
-threads classes.tuple.lib system accessors ;
+threads classes.tuple.lib system combinators accessors ;
 IN: io.windows.nt.sockets
 
 : malloc-int ( object -- object )
@@ -30,121 +31,68 @@ TUPLE: ConnectEx-args port
     s* name* namelen* lpSendBuffer* dwSendDataLength*
     lpdwBytesSent* lpOverlapped* ptr* ;
 
-: init-connect ( sockaddr size ConnectEx -- )
-    [ set-ConnectEx-args-namelen* ] keep
-    [ set-ConnectEx-args-name* ] keep
-    f over set-ConnectEx-args-lpSendBuffer*
-    0 over set-ConnectEx-args-dwSendDataLength*
-    f over set-ConnectEx-args-lpdwBytesSent*
-    (make-overlapped) swap set-ConnectEx-args-lpOverlapped* ;
+: wait-for-socket ( args -- n )
+    [ lpOverlapped*>> ] [ port>> ] bi twiddle-thumbs ;
 
-: (ConnectEx) ( ConnectEx -- )
-    \ ConnectEx-args >tuple*<
+: <ConnectEx-args> ( sockaddr size -- ConnectEx )
+    ConnectEx-args new
+        swap >>namelen*
+        swap >>name*
+        f >>lpSendBuffer*
+        0 >>dwSendDataLength*
+        f >>lpdwBytesSent*
+        (make-overlapped) >>lpOverlapped* ;
+
+: call-ConnectEx ( ConnectEx -- )
+    ConnectEx-args >tuple*<
     "int"
     { "SOCKET" "sockaddr_in*" "int" "PVOID" "DWORD" "LPDWORD" "void*" }
     "stdcall" alien-indirect drop
     winsock-error-string [ throw ] when* ;
 
-: connect-continuation ( overlapped port -- )
-    2dup save-callback
-    get-overlapped-result drop ;
-
-M: win32-socket wait-to-connect ( client-out handle -- )
-    [ overlapped>> swap connect-continuation ]
-    [ drop pending-error ]
-    2bi ;
-
-M: object ((client)) ( addrspec -- handle )
-    [
-        \ ConnectEx-args new
-        over make-sockaddr/size pick init-connect
-        over tcp-socket over set-ConnectEx-args-s*
-        dup ConnectEx-args-s* add-completion
-        dup ConnectEx-args-s* get-ConnectEx-ptr over set-ConnectEx-args-ptr*
-        dup ConnectEx-args-s* INADDR_ANY roll bind-socket
-        dup (ConnectEx)
-
-        dup [ ConnectEx-args-s* ] [ ConnectEx-args-lpOverlapped* ] bi <win32-socket>
-    ] with-destructors ;
+M: object establish-connection ( client-out remote -- )
+    make-sockaddr/size <ConnectEx-args>
+        swap >>port
+        dup port>> handle>> handle>> >>s*
+        dup s*>> get-ConnectEx-ptr >>ptr*
+        dup call-ConnectEx
+        wait-for-socket drop ;
 
 TUPLE: AcceptEx-args port
     sListenSocket* sAcceptSocket* lpOutputBuffer* dwReceiveDataLength*
     dwLocalAddressLength* dwRemoteAddressLength* lpdwBytesReceived* lpOverlapped* ;
 
-: init-accept-buffer ( server-port AcceptEx -- )
-    >r server-port-addr sockaddr-type heap-size 16 +
-    dup dup 2 * malloc dup free-always r>
-    [ set-AcceptEx-args-lpOutputBuffer* ] keep
-    [ set-AcceptEx-args-dwLocalAddressLength* ] keep
-    set-AcceptEx-args-dwRemoteAddressLength* ;
+: init-accept-buffer ( addr AcceptEx -- )
+    swap sockaddr-type heap-size 16 +
+        [ >>dwLocalAddressLength* ] [ >>dwRemoteAddressLength* ] bi
+        dup dwLocalAddressLength*>> 2 * malloc &free >>lpOutputBuffer*
+        drop ;
 
-: init-accept ( server-port AcceptEx -- )
-    [ init-accept-buffer ] 2keep
-    [ set-AcceptEx-args-port ] 2keep
-    >r port-handle win32-file-handle r> [ set-AcceptEx-args-sListenSocket* ] keep
-    dup AcceptEx-args-port server-port-addr tcp-socket
-    over set-AcceptEx-args-sAcceptSocket*
-    0 over set-AcceptEx-args-dwReceiveDataLength*
-    f over set-AcceptEx-args-lpdwBytesReceived*
-    (make-overlapped) swap set-AcceptEx-args-lpOverlapped* ;
+: <AcceptEx-args> ( server addr -- AcceptEx )
+    AcceptEx-args new
+        2dup init-accept-buffer
+        swap SOCK_STREAM open-socket |dispose handle>> >>sAcceptSocket*
+        over handle>> handle>> >>sListenSocket*
+        swap >>port
+        0 >>dwReceiveDataLength*
+        f >>lpdwBytesReceived*
+        (make-overlapped) >>lpOverlapped* ;
 
-: ((accept)) ( AcceptEx -- )
-    \ AcceptEx-args >tuple*<
-    AcceptEx drop
+: call-AcceptEx ( AcceptEx -- )
+    AcceptEx-args >tuple*< AcceptEx drop
     winsock-error-string [ throw ] when* ;
 
-: make-accept-continuation ( AcceptEx -- )
-    dup AcceptEx-args-lpOverlapped*
-    swap AcceptEx-args-port save-callback ;
-
-: check-accept-error ( AcceptEx -- )
-    dup AcceptEx-args-lpOverlapped*
-    swap AcceptEx-args-port get-overlapped-result drop ;
-
-: extract-remote-host ( AcceptEx -- addrspec )
-    [
-        [ AcceptEx-args-lpOutputBuffer* ] keep
-        [ AcceptEx-args-dwReceiveDataLength* ] keep
-        [ AcceptEx-args-dwLocalAddressLength* ] keep
-        AcceptEx-args-dwRemoteAddressLength*
-        f <void*>
-        0 <int>
-        f <void*> [
-            0 <int> GetAcceptExSockaddrs
-        ] keep *void*
-    ] keep AcceptEx-args-port server-port-addr parse-sockaddr ;
-
-: accept-continuation ( AcceptEx -- addrspec client )
-    [ make-accept-continuation ] keep
-    [ check-accept-error ] keep
-    [ extract-remote-host ] keep
-    ! addrspec AcceptEx
-    [ AcceptEx-args-sAcceptSocket* add-completion ] keep
-    [ AcceptEx-args-sAcceptSocket* ] [ AcceptEx-args-lpOverlapped* ] bi <win32-socket> ;
-
-M: winnt (accept) ( server -- addrspec handle )
+M: object (accept) ( server addr -- handle )
     [
         [
-            \ AcceptEx-args new
-            [ init-accept ] keep
-            [ ((accept)) ] keep
-            [ accept-continuation ] keep
-            AcceptEx-args-port pending-error
-        ] with-timeout
-    ] with-destructors ;
-
-M: winnt (server) ( addrspec -- handle )
-    [
-        SOCK_STREAM server-fd dup listen-on-socket
-        dup add-completion
-        f <win32-socket>
-    ] with-destructors ;
-
-M: winnt (datagram) ( addrspec -- handle )
-    [
-        SOCK_DGRAM server-fd
-        dup add-completion
-        f <win32-socket>
+            <AcceptEx-args>
+            {
+                [ call-AcceptEx ]
+                [ wait-for-socket drop ]
+                [ sAcceptSocket*>> opened-socket ]
+                [ port>> pending-error ]
+            } cleave
+        ] curry with-timeout
     ] with-destructors ;
 
 TUPLE: WSARecvFrom-args port
@@ -152,53 +100,38 @@ TUPLE: WSARecvFrom-args port
        lpFlags* lpFrom* lpFromLen* lpOverlapped* lpCompletionRoutine* ;
 
 : make-receive-buffer ( -- WSABUF )
-    "WSABUF" malloc-object dup free-always
+    "WSABUF" malloc-object &free
     default-buffer-size get over set-WSABUF-len
-    default-buffer-size get malloc dup free-always over set-WSABUF-buf ;
+    default-buffer-size get malloc &free over set-WSABUF-buf ;
 
-: init-WSARecvFrom ( datagram WSARecvFrom -- )
-    [ set-WSARecvFrom-args-port ] 2keep
-    [
-        >r handle>> handle>> r>
-        set-WSARecvFrom-args-s*
-    ] 2keep [
-        >r datagram-port-addr sockaddr-type heap-size r>
-        2dup >r malloc dup free-always r> set-WSARecvFrom-args-lpFrom*
-        >r malloc-int dup free-always r> set-WSARecvFrom-args-lpFromLen*
-    ] keep
-    make-receive-buffer over set-WSARecvFrom-args-lpBuffers*
-    1 over set-WSARecvFrom-args-dwBufferCount*
-    0 malloc-int dup free-always over set-WSARecvFrom-args-lpFlags*
-    0 malloc-int dup free-always over set-WSARecvFrom-args-lpNumberOfBytesRecvd*
-    (make-overlapped) swap set-WSARecvFrom-args-lpOverlapped* ;
-
-: WSARecvFrom-continuation ( WSARecvFrom -- n )
-    dup WSARecvFrom-args-lpOverlapped*
-    swap WSARecvFrom-args-port [ save-callback ] 2keep
-    get-overlapped-result ;
+: <WSARecvFrom-args> ( datagram -- WSARecvFrom )
+    WSARecvFrom-args new
+        swap >>port
+        dup port>> handle>> handle>> >>s*
+        dup port>> addr>> sockaddr-type heap-size
+            [ malloc &free >>lpFrom* ]
+            [ malloc-int &free >>lpFromLen* ] bi
+        make-receive-buffer >>lpBuffers*
+        1 >>dwBufferCount*
+        0 malloc-int &free >>lpFlags*
+        0 malloc-int &free >>lpNumberOfBytesRecvd*
+        (make-overlapped) >>lpOverlapped* ;
 
 : call-WSARecvFrom ( WSARecvFrom -- )
-    \ WSARecvFrom-args >tuple*<
-    WSARecvFrom
-    socket-error* ;
+    WSARecvFrom-args >tuple*< WSARecvFrom socket-error* ;
 
-: parse-WSARecvFrom ( n WSARecvFrom -- packet addrspec )
-    [
-        WSARecvFrom-args-lpBuffers* WSABUF-buf
-        swap memory>byte-array
-    ] keep
-    [ WSARecvFrom-args-lpFrom* ] keep
-    WSARecvFrom-args-port datagram-port-addr parse-sockaddr ;
+: parse-WSARecvFrom ( n WSARecvFrom -- packet sockaddr )
+    [ lpBuffers*>> WSABUF-buf swap memory>byte-array ] [ lpFrom*>> ] bi ;
 
-M: winnt receive ( datagram -- packet addrspec )
+M: winnt (receive) ( datagram -- packet addrspec )
     [
-        check-datagram-port
-        \ WSARecvFrom-args new
-        [ init-WSARecvFrom ] keep
-        [ call-WSARecvFrom ] keep
-        [ WSARecvFrom-continuation ] keep
-        [ WSARecvFrom-args-port pending-error ] keep
-        parse-WSARecvFrom
+        <WSARecvFrom-args>
+        {
+            [ call-WSARecvFrom ]
+            [ wait-for-socket ]
+            [ port>> pending-error ]
+            [ parse-WSARecvFrom ]
+        } cleave
     ] with-destructors ;
 
 TUPLE: WSASendTo-args port
@@ -206,49 +139,33 @@ TUPLE: WSASendTo-args port
        dwFlags* lpTo* iToLen* lpOverlapped* lpCompletionRoutine* ;
 
 : make-send-buffer ( packet -- WSABUF )
-    "WSABUF" malloc-object dup free-always
-    over malloc-byte-array dup free-always over set-WSABUF-buf
-    swap length over set-WSABUF-len ;
+    "WSABUF" malloc-object &free
+    [ >r malloc-byte-array &free r> set-WSABUF-buf ]
+    [ >r length r> set-WSABUF-len ]
+    [ nip ]
+    2tri ;
 
-: init-WSASendTo ( packet addrspec datagram WSASendTo -- )
-    [ set-WSASendTo-args-port ] 2keep
-    [
-        >r port-handle win32-file-handle r> set-WSASendTo-args-s*
-    ] keep
-    [
-        >r make-sockaddr/size >r
-        malloc-byte-array dup free-always
-        r> r>
-        [ set-WSASendTo-args-iToLen* ] keep
-        set-WSASendTo-args-lpTo*
-    ] keep
-    [
-        >r make-send-buffer r> set-WSASendTo-args-lpBuffers*
-    ] keep
-    1 over set-WSASendTo-args-dwBufferCount*
-    0 over set-WSASendTo-args-dwFlags*
-    0 <uint> over set-WSASendTo-args-lpNumberOfBytesSent*
-    (make-overlapped) swap set-WSASendTo-args-lpOverlapped* ;
-
-: WSASendTo-continuation ( WSASendTo -- )
-    dup WSASendTo-args-lpOverlapped*
-    swap WSASendTo-args-port
-    [ save-callback ] 2keep
-    get-overlapped-result drop ;
+: <WSASendTo-args> ( packet addrspec datagram -- WSASendTo )
+    WSASendTo-args new
+        swap >>port
+        dup port>> handle>> handle>> >>s*
+        swap make-sockaddr/size
+            >r malloc-byte-array &free
+            r> [ >>lpTo* ] [ >>iToLen* ] bi*
+        swap make-send-buffer >>lpBuffers*
+        1 >>dwBufferCount*
+        0 >>dwFlags*
+        0 <uint> >>lpNumberOfBytesSent*
+        (make-overlapped) >>lpOverlapped* ;
 
 : call-WSASendTo ( WSASendTo -- )
-    \ WSASendTo-args >tuple*<
-    WSASendTo socket-error* ;
+    WSASendTo-args >tuple*< WSASendTo socket-error* ;
 
-USE: io.sockets
-
-M: winnt send ( packet addrspec datagram -- )
+M: winnt (send) ( packet addrspec datagram -- )
     [
-        check-datagram-send
-        \ WSASendTo-args new
-        [ init-WSASendTo ] keep
-        [ call-WSASendTo ] keep
-        [ WSASendTo-continuation ] keep
-        WSASendTo-args-port pending-error
+        <WSASendTo-args>
+        [ call-WSASendTo ]
+        [ wait-for-socket drop ]
+        [ port>> pending-error ]
+        tri
     ] with-destructors ;
-
diff --git a/extra/io/windows/privileges/privileges.factor b/extra/io/windows/privileges/privileges.factor
new file mode 100755
index 0000000000..144c799912
--- /dev/null
+++ b/extra/io/windows/privileges/privileges.factor
@@ -0,0 +1,8 @@
+USING: io.backend kernel continuations sequences ;
+IN: io.windows.privileges
+
+HOOK: set-privilege io-backend ( name ? -- ) inline
+
+: with-privileges ( seq quot -- )
+    over [ [ t set-privilege ] each ] curry compose
+    swap [ [ f set-privilege ] each ] curry [ ] cleanup ; inline
diff --git a/extra/io/windows/sockets/sockets.factor b/extra/io/windows/sockets/sockets.factor
new file mode 100755
index 0000000000..67d827aa95
--- /dev/null
+++ b/extra/io/windows/sockets/sockets.factor
@@ -0,0 +1,58 @@
+USING: kernel accessors io.sockets io.windows io.backend
+windows.winsock system destructors alien.c-types ;
+IN: io.windows.sockets
+
+HOOK: WSASocket-flags io-backend ( -- DWORD )
+
+TUPLE: win32-socket < win32-file ;
+
+: <win32-socket> ( handle -- win32-socket )
+    win32-socket new
+        swap >>handle ;
+
+M: win32-socket dispose ( stream -- )
+    handle>> closesocket drop ;
+
+: unspecific-sockaddr/size ( addrspec -- sockaddr len )
+    [ empty-sockaddr/size ] [ protocol-family ] bi
+    pick set-sockaddr-in-family ;
+
+: opened-socket ( handle -- win32-socket )
+    <win32-socket> |dispose dup add-completion ;
+
+: open-socket ( addrspec type -- win32-socket )
+    >r protocol-family r>
+    0 f 0 WSASocket-flags WSASocket
+    dup socket-error
+    opened-socket ;
+
+M: object (get-local-address) ( socket addrspec -- sockaddr )
+    >r handle>> r> empty-sockaddr/size <int>
+    [ getsockname socket-error ] 2keep drop ;
+
+: bind-socket ( win32-socket sockaddr len -- )
+    >r >r handle>> r> r> bind socket-error ;
+
+M: object ((client)) ( addrspec -- handle )
+    [ SOCK_STREAM open-socket ] keep
+    [ unspecific-sockaddr/size bind-socket ] [ drop ] 2bi ;
+
+: server-socket ( addrspec type -- fd )
+    [ open-socket ] [ drop ] 2bi
+    [ make-sockaddr/size bind-socket ] [ drop ] 2bi ;
+
+! http://support.microsoft.com/kb/127144
+! NOTE: Possibly tweak this because of SYN flood attacks
+: listen-backlog ( -- n ) HEX: 7fffffff ; inline
+
+M: object (server) ( addrspec -- handle )
+    [
+        SOCK_STREAM server-socket
+        dup handle>> listen-backlog listen winsock-return-check
+    ] with-destructors ;
+
+M: windows (datagram) ( addrspec -- handle )
+    [ SOCK_DGRAM server-socket ] with-destructors ;
+
+M: windows addrinfo-error ( n -- )
+    winsock-return-check ;
diff --git a/extra/io/windows/windows.factor b/extra/io/windows/windows.factor
index 4f34153b31..6b6b54ab92 100755
--- a/extra/io/windows/windows.factor
+++ b/extra/io/windows/windows.factor
@@ -8,18 +8,33 @@ windows.shell32 windows.types windows.winsock splitting
 continuations math.bitfields system accessors ;
 IN: io.windows
 
-M: windows destruct-socket closesocket drop ;
+TUPLE: win32-handle handle disposed ;
 
-TUPLE: win32-file handle ptr ;
+: new-win32-handle ( handle class -- win32-handle )
+    new swap >>handle ;
 
-C: <win32-file> win32-file
+: <win32-handle> ( handle -- win32-handle )
+    win32-handle new-win32-handle ;
+
+M: win32-handle dispose* ( handle -- )
+    handle>> CloseHandle drop ;
+
+TUPLE: win32-file < win32-handle ptr ;
+
+: <win32-file> ( handle -- win32-file )
+    win32-file new-win32-handle ;
+
+M: win32-file init-handle ( handle -- )
+    drop ;
 
 HOOK: CreateFile-flags io-backend ( DWORD -- DWORD )
 HOOK: FileArgs-overlapped io-backend ( port -- overlapped/f )
 HOOK: add-completion io-backend ( port -- )
 
-M: windows normalize-directory ( string -- string )
-    normalize-path "\\" ?tail drop "\\*" append ;
+: opened-file ( handle -- win32-file )
+    dup invalid-handle?
+    <win32-file> |dispose
+    dup add-completion ;
 
 : share-mode ( -- fixnum )
     {
@@ -36,176 +51,3 @@ M: windows normalize-directory ( string -- string )
 : security-attributes-inherit ( -- obj )
     default-security-attributes
     TRUE over set-SECURITY_ATTRIBUTES-bInheritHandle ; foldable
-
-M: win32-file init-handle ( handle -- )
-    drop ;
-
-M: win32-file close-handle ( handle -- )
-    win32-file-handle close-handle ;
-
-M: alien close-handle ( handle -- )
-    CloseHandle drop ;
-
-! Clean up resources (open handle) if add-completion fails
-: open-file ( path access-mode create-mode flags -- handle )
-    [
-        >r >r share-mode security-attributes-inherit r> r>
-        CreateFile-flags f CreateFile
-        dup invalid-handle? dup close-later
-        dup add-completion
-    ] with-destructors ;
-
-: open-pipe-r/w ( path -- handle )
-    { GENERIC_READ GENERIC_WRITE } flags
-    OPEN_EXISTING 0 open-file ;
-
-: open-read ( path -- handle length )
-    GENERIC_READ OPEN_EXISTING 0 open-file 0 ;
-
-: open-write ( path -- handle length )
-    GENERIC_WRITE CREATE_ALWAYS 0 open-file 0 ;
-
-: (open-append) ( path -- handle )
-    GENERIC_WRITE OPEN_ALWAYS 0 open-file ;
-
-: open-existing ( path -- handle )
-    { GENERIC_READ GENERIC_WRITE } flags
-    share-mode
-    f
-    OPEN_EXISTING
-    FILE_FLAG_BACKUP_SEMANTICS
-    f CreateFileW dup win32-error=0/f ;
-
-: maybe-create-file ( path -- handle ? )
-    #! return true if file was just created
-    { GENERIC_READ GENERIC_WRITE } flags
-    share-mode
-    f
-    OPEN_ALWAYS
-    0 CreateFile-flags
-    f CreateFileW dup win32-error=0/f
-    GetLastError ERROR_ALREADY_EXISTS = not ;
-
-: set-file-pointer ( handle length method -- )
-    >r dupd d>w/w <uint> r> SetFilePointer
-    INVALID_SET_FILE_POINTER = [
-        CloseHandle "SetFilePointer failed" throw
-    ] when drop ;
-
-HOOK: open-append os ( path -- handle length )
-
-TUPLE: FileArgs
-    hFile lpBuffer nNumberOfBytesToRead
-    lpNumberOfBytesRet lpOverlapped ;
-
-C: <FileArgs> FileArgs
-
-: make-FileArgs ( port -- <FileArgs> )
-    [ port-handle win32-file-handle ] keep
-    [ buffer>> ] keep
-    [
-        buffer>> buffer-length
-        "DWORD" <c-object>
-    ] keep FileArgs-overlapped <FileArgs> ;
-
-: setup-read ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRead lpOverlapped )
-    [ FileArgs-hFile ] keep
-    [ FileArgs-lpBuffer buffer-end ] keep
-    [ FileArgs-lpBuffer buffer-capacity ] keep
-    [ FileArgs-lpNumberOfBytesRet ] keep
-    FileArgs-lpOverlapped ;
-
-: setup-write ( <FileArgs> -- hFile lpBuffer nNumberOfBytesToWrite lpNumberOfBytesWritten lpOverlapped )
-    [ FileArgs-hFile ] keep
-    [ FileArgs-lpBuffer buffer@ ] keep
-    [ FileArgs-lpBuffer buffer-length ] keep
-    [ FileArgs-lpNumberOfBytesRet ] keep
-    FileArgs-lpOverlapped ;
-
-M: windows (file-reader) ( path -- stream )
-    open-read <win32-file> <input-port> ;
-
-M: windows (file-writer) ( path -- stream )
-    open-write <win32-file> <output-port> ;
-
-M: windows (file-appender) ( path -- stream )
-    open-append <win32-file> <output-port> ;
-
-M: windows move-file ( from to -- )
-    [ normalize-path ] bi@ MoveFile win32-error=0/f ;
-
-M: windows delete-file ( path -- )
-    normalize-path DeleteFile win32-error=0/f ;
-
-M: windows copy-file ( from to -- )
-    dup parent-directory make-directories
-    [ normalize-path ] bi@ 0 CopyFile win32-error=0/f ;
-
-M: windows make-directory ( path -- )
-    normalize-path
-    f CreateDirectory win32-error=0/f ;
-
-M: windows delete-directory ( path -- )
-    normalize-path
-    RemoveDirectory win32-error=0/f ;
-
-HOOK: WSASocket-flags io-backend ( -- DWORD )
-
-TUPLE: win32-socket < win32-file overlapped ;
-
-: <win32-socket> ( handle overlapped -- win32-socket )
-    win32-socket new
-        swap >>overlapped
-        swap >>handle ;
-
-: open-socket ( family type -- socket )
-    0 f 0 WSASocket-flags WSASocket dup socket-error ;
-
-USE: windows.winsock
-: init-sockaddr ( port# addrspec -- sockaddr )
-    dup sockaddr-type <c-object>
-    [ swap protocol-family swap set-sockaddr-in-family ] keep
-    [ >r htons r> set-sockaddr-in-port ] keep ;
-
-: server-sockaddr ( port# addrspec -- sockaddr )
-    init-sockaddr
-    [ INADDR_ANY swap set-sockaddr-in-addr ] keep ;
-
-: bind-socket ( socket sockaddr addrspec -- )
-    [ server-sockaddr ] keep
-    sockaddr-type heap-size bind socket-error ;
-
-TUPLE: socket-destructor alien ;
-
-C: <socket-destructor> socket-destructor
-
-HOOK: destruct-socket io-backend ( obj -- )
-
-M: socket-destructor dispose ( obj -- )
-    alien>> destruct-socket ;
-
-: close-socket-later ( handle -- )
-    <socket-destructor> <only-once> |dispose drop ;
-
-: server-fd ( addrspec type -- fd )
-    >r dup protocol-family r> open-socket
-        dup close-socket-later
-    dup rot make-sockaddr/size bind socket-error ;
-
-USE: namespaces
-
-! http://support.microsoft.com/kb/127144
-! NOTE: Possibly tweak this because of SYN flood attacks
-: listen-backlog ( -- n ) HEX: 7fffffff ; inline
-
-: listen-on-socket ( socket -- )
-    listen-backlog listen winsock-return-check ;
-
-M: win32-socket dispose ( stream -- )
-    win32-file-handle closesocket drop ;
-
-M: windows addrinfo-error ( n -- )
-    winsock-return-check ;
-
-: tcp-socket ( addrspec -- socket )
-    protocol-family SOCK_STREAM open-socket ;
diff --git a/extra/windows/winsock/winsock.factor b/extra/windows/winsock/winsock.factor
old mode 100644
new mode 100755
index 39d11b562b..0699afc682
--- a/extra/windows/winsock/winsock.factor
+++ b/extra/windows/winsock/winsock.factor
@@ -167,6 +167,8 @@ FUNCTION: int shutdown ( SOCKET s, int how ) ;
 FUNCTION: int send ( SOCKET s, char* buf, int len, int flags ) ;
 FUNCTION: int recv ( SOCKET s, char* buf, int len, int flags ) ;
 
+FUNCTION: int getsockname ( SOCKET s, sockaddr_in* address, int* addrlen ) ;
+
 TYPEDEF: uint SERVICETYPE
 TYPEDEF: OVERLAPPED WSAOVERLAPPED
 TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED