Subject: [PATCH] Revert "os: remove 5ms sleep on Windows in (*Process).Wait"
Fix os.RemoveAll not working on Windows7
Revert "runtime: always use LoadLibraryEx to load system libraries"
Revert "syscall: remove Windows 7 console handle workaround"
Revert "net: remove sysSocket fallback for Windows 7"
Revert "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
---
Index: src/crypto/internal/sysrand/rand_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/crypto/internal/sysrand/rand_windows.go b/src/crypto/internal/sysrand/rand_windows.go
--- a/src/crypto/internal/sysrand/rand_windows.go	(revision e87b10ea2a2c6c65b80c4374af42b9c02ac9fb20)
+++ b/src/crypto/internal/sysrand/rand_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
@@ -7,5 +7,26 @@
 import "internal/syscall/windows"
 
 func read(b []byte) error {
-	return windows.ProcessPrng(b)
+	// RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at
+	// most 1<<31-1 bytes at a time so that  this works the same on 32-bit
+	// and 64-bit systems.
+	return batched(windows.RtlGenRandom, 1<<31-1)(b)
+}
+
+// batched returns a function that calls f to populate a []byte by chunking it
+// into subslices of, at most, readMax bytes.
+func batched(f func([]byte) error, readMax int) func([]byte) error {
+	return func(out []byte) error {
+		for len(out) > 0 {
+			read := len(out)
+			if read > readMax {
+				read = readMax
+			}
+			if err := f(out[:read]); err != nil {
+				return err
+			}
+			out = out[read:]
+		}
+		return nil
+	}
 }
Index: src/crypto/rand/rand.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go
--- a/src/crypto/rand/rand.go	(revision e87b10ea2a2c6c65b80c4374af42b9c02ac9fb20)
+++ b/src/crypto/rand/rand.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
@@ -25,7 +25,7 @@
 //   - On legacy Linux (< 3.17), Reader opens /dev/urandom on first use.
 //   - On macOS, iOS, and OpenBSD Reader, uses arc4random_buf(3).
 //   - On NetBSD, Reader uses the kern.arandom sysctl.
-//   - On Windows, Reader uses the ProcessPrng API.
+//   - On Windows systems, Reader uses the RtlGenRandom API.
 //   - On js/wasm, Reader uses the Web Crypto API.
 //   - On wasip1/wasm, Reader uses random_get.
 //
Index: src/internal/syscall/windows/syscall_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
--- a/src/internal/syscall/windows/syscall_windows.go	(revision e87b10ea2a2c6c65b80c4374af42b9c02ac9fb20)
+++ b/src/internal/syscall/windows/syscall_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
@@ -421,7 +421,7 @@
 //sys	DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
 //sys	CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW
 
-//sys	ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng
+//sys	RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036
 
 type FILE_ID_BOTH_DIR_INFO struct {
 	NextEntryOffset uint32
Index: src/internal/syscall/windows/zsyscall_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
--- a/src/internal/syscall/windows/zsyscall_windows.go	(revision e87b10ea2a2c6c65b80c4374af42b9c02ac9fb20)
+++ b/src/internal/syscall/windows/zsyscall_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
@@ -38,7 +38,6 @@
 
 var (
 	modadvapi32         = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
-	modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll"))
 	modiphlpapi         = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
 	modkernel32         = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
 	modnetapi32         = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
@@ -65,7 +64,7 @@
 	procSetEntriesInAclW                  = modadvapi32.NewProc("SetEntriesInAclW")
 	procSetNamedSecurityInfoW             = modadvapi32.NewProc("SetNamedSecurityInfoW")
 	procSetTokenInformation               = modadvapi32.NewProc("SetTokenInformation")
-	procProcessPrng                       = modbcryptprimitives.NewProc("ProcessPrng")
+	procSystemFunction036                 = modadvapi32.NewProc("SystemFunction036")
 	procGetAdaptersAddresses              = modiphlpapi.NewProc("GetAdaptersAddresses")
 	procCreateEventW                      = modkernel32.NewProc("CreateEventW")
 	procCreateIoCompletionPort            = modkernel32.NewProc("CreateIoCompletionPort")
@@ -271,12 +270,12 @@
 	return
 }
 
-func ProcessPrng(buf []byte) (err error) {
+func RtlGenRandom(buf []byte) (err error) {
 	var _p0 *byte
 	if len(buf) > 0 {
 		_p0 = &buf[0]
 	}
-	r1, _, e1 := syscall.SyscallN(procProcessPrng.Addr(), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)))
+	r1, _, e1 := syscall.SyscallN(procSystemFunction036.Addr(), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)))
 	if r1 == 0 {
 		err = errnoErr(e1)
 	}
Index: src/runtime/os_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
--- a/src/runtime/os_windows.go	(revision e87b10ea2a2c6c65b80c4374af42b9c02ac9fb20)
+++ b/src/runtime/os_windows.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
@@ -40,7 +40,8 @@
 //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll"
 //go:cgo_import_dynamic runtime._SetThreadContext SetThreadContext%2 "kernel32.dll"
-//go:cgo_import_dynamic runtime._LoadLibraryExW LoadLibraryExW%3 "kernel32.dll"
+//go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll"
+//go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll"
 //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll"
 //go:cgo_import_dynamic runtime._QueryPerformanceCounter QueryPerformanceCounter%1 "kernel32.dll"
 //go:cgo_import_dynamic runtime._QueryPerformanceFrequency QueryPerformanceFrequency%1 "kernel32.dll"
@@ -74,7 +75,6 @@
 	// Following syscalls are available on every Windows PC.
 	// All these variables are set by the Windows executable
 	// loader before the Go program starts.
-	_AddVectoredContinueHandler,
 	_AddVectoredExceptionHandler,
 	_CloseHandle,
 	_CreateEventA,
@@ -97,7 +97,8 @@
 	_GetSystemInfo,
 	_GetThreadContext,
 	_SetThreadContext,
-	_LoadLibraryExW,
+	_LoadLibraryW,
+	_LoadLibraryA,
 	_PostQueuedCompletionStatus,
 	_QueryPerformanceCounter,
 	_QueryPerformanceFrequency,
@@ -126,8 +127,23 @@
 	_WriteFile,
 	_ stdFunction
 
-	// Use ProcessPrng to generate cryptographically random data.
-	_ProcessPrng stdFunction
+	// Following syscalls are only available on some Windows PCs.
+	// We will load syscalls, if available, before using them.
+	_AddDllDirectory,
+	_AddVectoredContinueHandler,
+	_LoadLibraryExA,
+	_LoadLibraryExW,
+	_ stdFunction
+
+	// Use RtlGenRandom to generate cryptographically random data.
+	// This approach has been recommended by Microsoft (see issue
+	// 15589 for details).
+	// The RtlGenRandom is not listed in advapi32.dll, instead
+	// RtlGenRandom function can be found by searching for SystemFunction036.
+	// Also some versions of Mingw cannot link to SystemFunction036
+	// when building executable as Cgo. So load SystemFunction036
+	// manually during runtime startup.
+	_RtlGenRandom stdFunction
 
 	// Load ntdll.dll manually during startup, otherwise Mingw
 	// links wrong printf function to cgo executable (see issue
@@ -144,13 +160,6 @@
 	_ stdFunction
 )
 
-var (
-	bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0}
-	ntdlldll            = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0}
-	powrprofdll         = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0}
-	winmmdll            = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0}
-)
-
 // Function to be called by windows CreateThread
 // to start new os thread.
 func tstart_stdcall(newm *m)
@@ -242,9 +251,40 @@
 	return unsafe.String(&sysDirectory[0], sysDirectoryLen)
 }
 
-func windowsLoadSystemLib(name []uint16) uintptr {
-	const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
-	return stdcall(_LoadLibraryExW, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
+//go:linkname syscall_getSystemDirectory syscall.getSystemDirectory
+func syscall_getSystemDirectory() string {
+	return unsafe.String(&sysDirectory[0], sysDirectoryLen)
+}
+
+func windowsLoadSystemLib(name []byte) uintptr {
+	if useLoadLibraryEx {
+		return stdcall(_LoadLibraryExA, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
+	} else {
+		absName := append(sysDirectory[:sysDirectoryLen], name...)
+		return stdcall(_LoadLibraryA, uintptr(unsafe.Pointer(&absName[0])))
+	}
+}
+
+const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
+
+// When available, this function will use LoadLibraryEx with the filename
+// parameter and the important SEARCH_SYSTEM32 argument. But on systems that
+// do not have that option, absoluteFilepath should contain a fallback
+// to the full path inside of system32 for use with vanilla LoadLibrary.
+//
+//go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary
+func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) {
+	if useLoadLibraryEx {
+		handle, _, err = syscall_syscalln(uintptr(unsafe.Pointer(_LoadLibraryExW)), 3, uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
+	} else {
+		handle, _, err = syscall_syscalln(uintptr(unsafe.Pointer(_LoadLibraryW)), 1, uintptr(unsafe.Pointer(absoluteFilepath)))
+	}
+	KeepAlive(filename)
+	KeepAlive(absoluteFilepath)
+	if handle != 0 {
+		err = 0
+	}
+	return
 }
 
 //go:linkname windows_QueryPerformanceCounter internal/syscall/windows.QueryPerformanceCounter
@@ -262,13 +302,28 @@
 }
 
 func loadOptionalSyscalls() {
-	bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:])
-	if bcryptPrimitives == 0 {
-		throw("bcryptprimitives.dll not found")
+	var kernel32dll = []byte("kernel32.dll\000")
+	k32 := stdcall(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
+	if k32 == 0 {
+		throw("kernel32.dll not found")
 	}
-	_ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000"))
+	_AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000"))
+	_AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000"))
+	_LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000"))
+	_LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000"))
+	useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil)
+
+	initSysDirectory()
 
-	n32 := windowsLoadSystemLib(ntdlldll[:])
+	var advapi32dll = []byte("advapi32.dll\000")
+	a32 := windowsLoadSystemLib(advapi32dll)
+	if a32 == 0 {
+		throw("advapi32.dll not found")
+	}
+	_RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
+
+	var ntdll = []byte("ntdll.dll\000")
+	n32 := windowsLoadSystemLib(ntdll)
 	if n32 == 0 {
 		throw("ntdll.dll not found")
 	}
@@ -297,7 +352,7 @@
 		context  uintptr
 	}
 
-	powrprof := windowsLoadSystemLib(powrprofdll[:])
+	powrprof := windowsLoadSystemLib([]byte("powrprof.dll\000"))
 	if powrprof == 0 {
 		return // Running on Windows 7, where we don't need it anyway.
 	}
@@ -351,6 +406,22 @@
 // in sys_windows_386.s and sys_windows_amd64.s:
 func getlasterror() uint32
 
+// When loading DLLs, we prefer to use LoadLibraryEx with
+// LOAD_LIBRARY_SEARCH_* flags, if available. LoadLibraryEx is not
+// available on old Windows, though, and the LOAD_LIBRARY_SEARCH_*
+// flags are not available on some versions of Windows without a
+// security patch.
+//
+// https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says:
+// "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows
+// Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on
+// systems that have KB2533623 installed. To determine whether the
+// flags are available, use GetProcAddress to get the address of the
+// AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories
+// function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_*
+// flags can be used with LoadLibraryEx."
+var useLoadLibraryEx bool
+
 var timeBeginPeriodRetValue uint32
 
 // osRelaxMinNS indicates that sysmon shouldn't osRelax if the next
@@ -417,7 +488,8 @@
 		// Only load winmm.dll if we need it.
 		// This avoids a dependency on winmm.dll for Go programs
 		// that run on new Windows versions.
-		m32 := windowsLoadSystemLib(winmmdll[:])
+		var winmmdll = []byte("winmm.dll\000")
+		m32 := windowsLoadSystemLib(winmmdll)
 		if m32 == 0 {
 			print("runtime: LoadLibraryExW failed; errno=", getlasterror(), "\n")
 			throw("winmm.dll not found")
@@ -458,6 +530,28 @@
 	canUseLongPaths = true
 }
 
+var osVersionInfo struct {
+	majorVersion uint32
+	minorVersion uint32
+	buildNumber  uint32
+}
+
+func initOsVersionInfo() {
+	info := windows.OSVERSIONINFOW{}
+	info.OSVersionInfoSize = uint32(unsafe.Sizeof(info))
+	stdcall(_RtlGetVersion, uintptr(unsafe.Pointer(&info)))
+	osVersionInfo.majorVersion = info.MajorVersion
+	osVersionInfo.minorVersion = info.MinorVersion
+	osVersionInfo.buildNumber = info.BuildNumber
+}
+
+//go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers
+func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) {
+	*majorVersion = osVersionInfo.majorVersion
+	*minorVersion = osVersionInfo.minorVersion
+	*buildNumber = osVersionInfo.buildNumber
+}
+
 func osinit() {
 	asmstdcallAddr = unsafe.Pointer(windows.AsmStdCallAddr())
 
@@ -470,8 +564,8 @@
 	initHighResTimer()
 	timeBeginPeriodRetValue = osRelax(false)
 
-	initSysDirectory()
 	initLongPathSupport()
+	initOsVersionInfo()
 
 	numCPUStartup = getCPUCount()
 
@@ -487,7 +581,7 @@
 //go:nosplit
 func readRandom(r []byte) int {
 	n := 0
-	if stdcall(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
+	if stdcall(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 {
 		n = len(r)
 	}
 	return n
Index: src/net/hook_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/net/hook_windows.go b/src/net/hook_windows.go
--- a/src/net/hook_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
+++ b/src/net/hook_windows.go	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
@@ -13,6 +13,7 @@
 	hostsFilePath = windows.GetSystemDirectory() + "/Drivers/etc/hosts"
 
 	// Placeholders for socket system calls.
+	socketFunc    func(int, int, int) (syscall.Handle, error)                                                 = syscall.Socket
 	wsaSocketFunc func(int32, int32, int32, *syscall.WSAProtocolInfo, uint32, uint32) (syscall.Handle, error) = windows.WSASocket
 	connectFunc   func(syscall.Handle, syscall.Sockaddr) error                                                = syscall.Connect
 	listenFunc    func(syscall.Handle, int) error                                                             = syscall.Listen
Index: src/net/internal/socktest/main_test.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/net/internal/socktest/main_test.go b/src/net/internal/socktest/main_test.go
--- a/src/net/internal/socktest/main_test.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
+++ b/src/net/internal/socktest/main_test.go	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !js && !plan9 && !wasip1 && !windows
+//go:build !js && !plan9 && !wasip1
 
 package socktest_test
 
Index: src/net/internal/socktest/main_windows_test.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/net/internal/socktest/main_windows_test.go b/src/net/internal/socktest/main_windows_test.go
new file mode 100644
--- /dev/null	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
+++ b/src/net/internal/socktest/main_windows_test.go	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package socktest_test
+
+import "syscall"
+
+var (
+	socketFunc func(int, int, int) (syscall.Handle, error)
+	closeFunc  func(syscall.Handle) error
+)
+
+func installTestHooks() {
+	socketFunc = sw.Socket
+	closeFunc = sw.Closesocket
+}
+
+func uninstallTestHooks() {
+	socketFunc = syscall.Socket
+	closeFunc = syscall.Closesocket
+}
Index: src/net/internal/socktest/sys_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/net/internal/socktest/sys_windows.go b/src/net/internal/socktest/sys_windows.go
--- a/src/net/internal/socktest/sys_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
+++ b/src/net/internal/socktest/sys_windows.go	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
@@ -9,6 +9,38 @@
 	"syscall"
 )
 
+// Socket wraps [syscall.Socket].
+func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) {
+	sw.once.Do(sw.init)
+
+	so := &Status{Cookie: cookie(family, sotype, proto)}
+	sw.fmu.RLock()
+	f, _ := sw.fltab[FilterSocket]
+	sw.fmu.RUnlock()
+
+	af, err := f.apply(so)
+	if err != nil {
+		return syscall.InvalidHandle, err
+	}
+	s, so.Err = syscall.Socket(family, sotype, proto)
+	if err = af.apply(so); err != nil {
+		if so.Err == nil {
+			syscall.Closesocket(s)
+		}
+		return syscall.InvalidHandle, err
+	}
+
+	sw.smu.Lock()
+	defer sw.smu.Unlock()
+	if so.Err != nil {
+		sw.stats.getLocked(so.Cookie).OpenFailed++
+		return syscall.InvalidHandle, so.Err
+	}
+	nso := sw.addLocked(s, family, sotype, proto)
+	sw.stats.getLocked(nso.Cookie).Opened++
+	return s, nil
+}
+
 // WSASocket wraps [syscall.WSASocket].
 func (sw *Switch) WSASocket(family, sotype, proto int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (s syscall.Handle, err error) {
 	sw.once.Do(sw.init)
Index: src/net/main_windows_test.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/net/main_windows_test.go b/src/net/main_windows_test.go
--- a/src/net/main_windows_test.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
+++ b/src/net/main_windows_test.go	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
@@ -12,6 +12,7 @@
 
 var (
 	// Placeholders for saving original socket system calls.
+	origSocket      = socketFunc
 	origWSASocket   = wsaSocketFunc
 	origClosesocket = poll.CloseFunc
 	origConnect     = connectFunc
@@ -21,6 +22,7 @@
 )
 
 func installTestHooks() {
+	socketFunc = sw.Socket
 	wsaSocketFunc = sw.WSASocket
 	poll.CloseFunc = sw.Closesocket
 	connectFunc = sw.Connect
@@ -30,6 +32,7 @@
 }
 
 func uninstallTestHooks() {
+	socketFunc = origSocket
 	wsaSocketFunc = origWSASocket
 	poll.CloseFunc = origClosesocket
 	connectFunc = origConnect
Index: src/net/sock_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/net/sock_windows.go b/src/net/sock_windows.go
--- a/src/net/sock_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
+++ b/src/net/sock_windows.go	(revision 2263b05b2fa6ce228fde1899587baf109f1e2e0a)
@@ -20,6 +20,21 @@
 func sysSocket(family, sotype, proto int) (syscall.Handle, error) {
 	s, err := wsaSocketFunc(int32(family), int32(sotype), int32(proto),
 		nil, 0, windows.WSA_FLAG_OVERLAPPED|windows.WSA_FLAG_NO_HANDLE_INHERIT)
+	if err == nil {
+		return s, nil
+	}
+	// WSA_FLAG_NO_HANDLE_INHERIT flag is not supported on some
+	// old versions of Windows, see
+	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
+	// for details. Just use syscall.Socket, if windows.WSASocket failed.
+
+	// See ../syscall/exec_unix.go for description of ForkLock.
+	syscall.ForkLock.RLock()
+	s, err = socketFunc(family, sotype, proto)
+	if err == nil {
+		syscall.CloseOnExec(s)
+	}
+	syscall.ForkLock.RUnlock()
 	if err != nil {
 		return syscall.InvalidHandle, os.NewSyscallError("socket", err)
 	}
Index: src/syscall/exec_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
--- a/src/syscall/exec_windows.go	(revision 4b29590aa510e05686ea53de16e1e571d22203d8)
+++ b/src/syscall/exec_windows.go	(revision ae41f7abdd5d7b8b51db2c03bf819ac66b8e1eb1)
@@ -15,7 +15,6 @@
 	"unsafe"
 )
 
-// ForkLock is not used on Windows.
 var ForkLock sync.RWMutex
 
 // EscapeArg rewrites command line argument s as prescribed
@@ -304,6 +303,9 @@
 var zeroProcAttr ProcAttr
 var zeroSysProcAttr SysProcAttr
 
+//go:linkname rtlGetNtVersionNumbers
+func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32)
+
 func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) {
 	if len(argv0) == 0 {
 		return 0, 0, EWINDOWS
@@ -367,6 +369,17 @@
 		}
 	}
 
+	var maj, min, build uint32
+	rtlGetNtVersionNumbers(&maj, &min, &build)
+	isWin7 := maj < 6 || (maj == 6 && min <= 1)
+	// NT kernel handles are divisible by 4, with the bottom 3 bits left as
+	// a tag. The fully set tag correlates with the types of handles we're
+	// concerned about here.  Except, the kernel will interpret some
+	// special handle values, like -1, -2, and so forth, so kernelbase.dll
+	// checks to see that those bottom three bits are checked, but that top
+	// bit is not checked.
+	isLegacyWin7ConsoleHandle := func(handle Handle) bool { return isWin7 && handle&0x10000003 == 3 }
+
 	p, _ := GetCurrentProcess()
 	parentProcess := p
 	if sys.ParentProcess != 0 {
@@ -375,7 +388,15 @@
 	fd := make([]Handle, len(attr.Files))
 	for i := range attr.Files {
 		if attr.Files[i] > 0 {
-			err := DuplicateHandle(p, Handle(attr.Files[i]), parentProcess, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
+			destinationProcessHandle := parentProcess
+
+			// On Windows 7, console handles aren't real handles, and can only be duplicated
+			// into the current process, not a parent one, which amounts to the same thing.
+			if parentProcess != p && isLegacyWin7ConsoleHandle(Handle(attr.Files[i])) {
+				destinationProcessHandle = p
+			}
+
+			err := DuplicateHandle(p, Handle(attr.Files[i]), destinationProcessHandle, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
 			if err != nil {
 				return 0, 0, err
 			}
@@ -406,6 +427,14 @@
 
 	fd = append(fd, sys.AdditionalInheritedHandles...)
 
+	// On Windows 7, console handles aren't real handles, so don't pass them
+	// through to PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
+	for i := range fd {
+		if isLegacyWin7ConsoleHandle(fd[i]) {
+			fd[i] = 0
+		}
+	}
+
 	// The presence of a NULL handle in the list is enough to cause PROC_THREAD_ATTRIBUTE_HANDLE_LIST
 	// to treat the entire list as empty, so remove NULL handles.
 	j := 0
Index: src/syscall/dll_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go
--- a/src/syscall/dll_windows.go	(revision ae41f7abdd5d7b8b51db2c03bf819ac66b8e1eb1)
+++ b/src/syscall/dll_windows.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
@@ -119,14 +119,7 @@
 }
 
 //go:linkname loadsystemlibrary
-func loadsystemlibrary(filename *uint16) (uintptr, Errno) {
-	const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
-	handle, _, err := SyscallN(uintptr(__LoadLibraryExW), uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
-	if handle != 0 {
-		err = 0
-	}
-	return handle, err
-}
+func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno)
 
 //go:linkname getprocaddress
 func getprocaddress(handle uintptr, procname *uint8) (uintptr, Errno) {
@@ -143,6 +136,9 @@
 	Handle Handle
 }
 
+//go:linkname getSystemDirectory
+func getSystemDirectory() string // Implemented in runtime package.
+
 // LoadDLL loads the named DLL file into memory.
 //
 // If name is not an absolute path and is not a known system DLL used by
@@ -159,7 +155,11 @@
 	var h uintptr
 	var e Errno
 	if sysdll.IsSystemDLL[name] {
-		h, e = loadsystemlibrary(namep)
+		absoluteFilepathp, err := UTF16PtrFromString(getSystemDirectory() + name)
+		if err != nil {
+			return nil, err
+		}
+		h, e = loadsystemlibrary(namep, absoluteFilepathp)
 	} else {
 		h, e = loadlibrary(namep)
 	}
Index: src/os/removeall_at.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go
--- a/src/os/removeall_at.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
+++ b/src/os/removeall_at.go	(revision 4ea1045cf3124221f055dbd2f3d2c9822934f661)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build unix || wasip1 || windows
+//go:build unix || wasip1
 
 package os
 
@@ -175,3 +175,25 @@
 	}
 	return newDirFile(fd, name)
 }
+
+func rootRemoveAll(r *Root, name string) error {
+	// Consistency with os.RemoveAll: Strip trailing /s from the name,
+	// so RemoveAll("not_a_directory/") succeeds.
+	for len(name) > 0 && IsPathSeparator(name[len(name)-1]) {
+		name = name[:len(name)-1]
+	}
+	if endsWithDot(name) {
+		// Consistency with os.RemoveAll: Return EINVAL when trying to remove .
+		return &PathError{Op: "RemoveAll", Path: name, Err: syscall.EINVAL}
+	}
+	_, err := doInRoot(r, name, nil, func(parent sysfdType, name string) (struct{}, error) {
+		return struct{}{}, removeAllFrom(parent, name)
+	})
+	if IsNotExist(err) {
+		return nil
+	}
+	if err != nil {
+		return &PathError{Op: "RemoveAll", Path: name, Err: underlyingError(err)}
+	}
+	return err
+}
Index: src/os/removeall_noat.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/os/removeall_noat.go b/src/os/removeall_noat.go
--- a/src/os/removeall_noat.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
+++ b/src/os/removeall_noat.go	(revision 4ea1045cf3124221f055dbd2f3d2c9822934f661)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build (js && wasm) || plan9
+//go:build (js && wasm) || plan9 || windows
 
 package os
 
@@ -140,3 +140,22 @@
 	}
 	return err
 }
+
+func rootRemoveAll(r *Root, name string) error {
+	if endsWithDot(name) {
+		// Consistency with os.RemoveAll: Return EINVAL when trying to remove .
+		return &PathError{Op: "RemoveAll", Path: name, Err: syscall.EINVAL}
+	}
+	if err := checkPathEscapesLstat(r, name); err != nil {
+		if err == syscall.ENOTDIR {
+			// Some intermediate path component is not a directory.
+			// RemoveAll treats this as success (since the target doesn't exist).
+			return nil
+		}
+		return &PathError{Op: "RemoveAll", Path: name, Err: err}
+	}
+	if err := RemoveAll(joinPath(r.root.name, name)); err != nil {
+		return &PathError{Op: "RemoveAll", Path: name, Err: underlyingError(err)}
+	}
+	return nil
+}
Index: src/os/root_noopenat.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/os/root_noopenat.go b/src/os/root_noopenat.go
--- a/src/os/root_noopenat.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
+++ b/src/os/root_noopenat.go	(revision 4ea1045cf3124221f055dbd2f3d2c9822934f661)
@@ -11,7 +11,6 @@
 	"internal/filepathlite"
 	"internal/stringslite"
 	"sync/atomic"
-	"syscall"
 	"time"
 )
 
@@ -185,25 +184,6 @@
 	}
 	return nil
 }
-
-func rootRemoveAll(r *Root, name string) error {
-	if endsWithDot(name) {
-		// Consistency with os.RemoveAll: Return EINVAL when trying to remove .
-		return &PathError{Op: "RemoveAll", Path: name, Err: syscall.EINVAL}
-	}
-	if err := checkPathEscapesLstat(r, name); err != nil {
-		if err == syscall.ENOTDIR {
-			// Some intermediate path component is not a directory.
-			// RemoveAll treats this as success (since the target doesn't exist).
-			return nil
-		}
-		return &PathError{Op: "RemoveAll", Path: name, Err: err}
-	}
-	if err := RemoveAll(joinPath(r.root.name, name)); err != nil {
-		return &PathError{Op: "RemoveAll", Path: name, Err: underlyingError(err)}
-	}
-	return nil
-}
 
 func rootReadlink(r *Root, name string) (string, error) {
 	if err := checkPathEscapesLstat(r, name); err != nil {
Index: src/os/root_openat.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/os/root_openat.go b/src/os/root_openat.go
--- a/src/os/root_openat.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
+++ b/src/os/root_openat.go	(revision 4ea1045cf3124221f055dbd2f3d2c9822934f661)
@@ -196,28 +196,6 @@
 	return nil
 }
 
-func rootRemoveAll(r *Root, name string) error {
-	// Consistency with os.RemoveAll: Strip trailing /s from the name,
-	// so RemoveAll("not_a_directory/") succeeds.
-	for len(name) > 0 && IsPathSeparator(name[len(name)-1]) {
-		name = name[:len(name)-1]
-	}
-	if endsWithDot(name) {
-		// Consistency with os.RemoveAll: Return EINVAL when trying to remove .
-		return &PathError{Op: "RemoveAll", Path: name, Err: syscall.EINVAL}
-	}
-	_, err := doInRoot(r, name, nil, func(parent sysfdType, name string) (struct{}, error) {
-		return struct{}{}, removeAllFrom(parent, name)
-	})
-	if IsNotExist(err) {
-		return nil
-	}
-	if err != nil {
-		return &PathError{Op: "RemoveAll", Path: name, Err: underlyingError(err)}
-	}
-	return err
-}
-
 func rootRename(r *Root, oldname, newname string) error {
 	_, err := doInRoot(r, oldname, nil, func(oldparent sysfdType, oldname string) (struct{}, error) {
 		_, err := doInRoot(r, newname, nil, func(newparent sysfdType, newname string) (struct{}, error) {
Index: src/os/root_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/os/root_windows.go b/src/os/root_windows.go
--- a/src/os/root_windows.go	(revision ce2e1a3d2c3c0d7277b4102841db1697147d2923)
+++ b/src/os/root_windows.go	(revision 4ea1045cf3124221f055dbd2f3d2c9822934f661)
@@ -402,3 +402,14 @@
 	}
 	return fi.Mode(), nil
 }
+
+func checkPathEscapes(r *Root, name string) error {
+	if !filepathlite.IsLocal(name) {
+		return errPathEscapes
+	}
+	return nil
+}
+
+func checkPathEscapesLstat(r *Root, name string) error {
+	return checkPathEscapes(r, name)
+}
Index: src/os/exec_windows.go
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/os/exec_windows.go b/src/os/exec_windows.go
--- a/src/os/exec_windows.go	(revision 4ea1045cf3124221f055dbd2f3d2c9822934f661)
+++ b/src/os/exec_windows.go	(revision 8149d992682ce76c6af804b507878e19fc966f7b)
@@ -10,6 +10,7 @@
 	"runtime"
 	"syscall"
 	"time"
+	_ "unsafe"
 )
 
 // Note that Process.handle is never nil because Windows always requires
@@ -49,9 +50,23 @@
 	// than statusDone.
 	p.doRelease(statusReleased)
 
+	var maj, min, build uint32
+	rtlGetNtVersionNumbers(&maj, &min, &build)
+	if maj < 10 {
+		// NOTE(brainman): It seems that sometimes process is not dead
+		// when WaitForSingleObject returns. But we do not know any
+		// other way to wait for it. Sleeping for a while seems to do
+		// the trick sometimes.
+		// See https://golang.org/issue/25965 for details.
+		time.Sleep(5 * time.Millisecond)
+	}
+
 	return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
 }
 
+//go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers
+func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32)
+
 func (p *Process) signal(sig Signal) error {
 	handle, status := p.handleTransientAcquire()
 	switch status {
