Move Windows port to MinGW

- Add calls to WSAStartup in the network code as required by
  Winsock.
- Add Windows-specific init_random_state function which uses the
  Crypto API.
- Move Windows port to MinGW and update build system to create a
  64-bit binary by default.
- Install text files as .rtf so they won't open in Notepad by default
  (Wordpad understands Unix line endings; Notepad doesn't).
- Simplify WiX installer code.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/os/os-windows.h b/os/os-windows.h
index 8812cfa..06fe433 100644
--- a/os/os-windows.h
+++ b/os/os-windows.h
@@ -1,220 +1,252 @@
-#ifndef FIO_OS_WINDOWS_H

-#define FIO_OS_WINDOWS_H

-

-#define FIO_OS	os_windows

-

-#include <sys/types.h>

-#include <errno.h>

-#include <windows.h>

-#include <psapi.h>

-#include <stdlib.h>

-

-#include "../smalloc.h"

-#include "../file.h"

-#include "../log.h"

-

-#define FIO_HAVE_ODIRECT

-#define FIO_HAVE_CPU_AFFINITY

-#define FIO_HAVE_CHARDEV_SIZE

-#define FIO_HAVE_FALLOCATE

-#define FIO_HAVE_FDATASYNC

-#define FIO_HAVE_WINDOWSAIO

-#define FIO_HAVE_GETTID

-

-#define FIO_OS_HAVE_SOCKLEN_T

-typedef int fio_socklen_t;

-

-#define FIO_USE_GENERIC_RAND

-

-#define OS_MAP_ANON		MAP_ANON

-

-#define OS_CLOCK CLOCK_REALTIME

-

-#define FIO_PREFERRED_ENGINE	"windowsaio"

-

-#define FIO_LITTLE_ENDIAN

-#define fio_swap16(x)	_byteswap_ushort(x)

-#define fio_swap32(x)	_byteswap_ulong(x)

-#define fio_swap64(x)	_byteswap_uint64(x)

-

-typedef off_t off64_t;

-

-typedef struct {

-  LARGE_INTEGER Length;

-} GET_LENGTH_INFORMATION;

-

-#define IOCTL_DISK_GET_LENGTH_INFO 0x7405C

-

-pid_t cygwin_winpid_to_pid(int winpid);

-

-static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)

-{

-	int rc = 0;

-	HANDLE hFile;

-

-	if (f->hFile == NULL) {

-		hFile = CreateFile(f->file_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,

-				NULL, OPEN_EXISTING, 0, NULL);

-	} else {

-		hFile = f->hFile;

-	}

-

-	GET_LENGTH_INFORMATION info;

-	DWORD outBytes;

-	LARGE_INTEGER size;

-	size.QuadPart = 0;

-	if (DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &outBytes, NULL))

-		*bytes = info.Length.QuadPart;

-	else

-		rc = EIO;

-

-	/* If we were passed a POSIX fd,

-	 * close the HANDLE we created via CreateFile */

-	if (hFile != INVALID_HANDLE_VALUE && f->hFile == NULL)

-		CloseHandle(hFile);

-

-	return rc;

-}

-

-static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)

-{

-	return blockdev_size(f, bytes);

-}

-

-static inline int blockdev_invalidate_cache(struct fio_file *f)

-{

-	/* There's no way to invalidate the cache in Windows

-	 * so just pretend to succeed */

-	return 0;

-}

-

-static inline unsigned long long os_phys_mem(void)

-{

-	SYSTEM_INFO sysInfo;

-	unsigned long addr;

-	GetSystemInfo(&sysInfo);

-	addr = (unsigned long)sysInfo.lpMaximumApplicationAddress;

-	return addr;

-}

-

-static inline void os_get_tmpdir(char *path, int len)

-{

-	GetTempPath(len, path);

-}

-

-typedef DWORD_PTR os_cpu_mask_t;

-

-static inline int gettid(void)

-{

-	return GetCurrentThreadId();

-}

-

-static inline int pid_to_winpid(int pid)

-{

-	int winpid = 0;

-	DWORD outbytes = 0;

-	DWORD *ids = NULL;

-	size_t allocsize;

-	

-	allocsize = sizeof(DWORD) * 1024;

-	

-	do {

-		if (allocsize == outbytes)

-			allocsize *= 2;

-

-		ids = realloc(ids, allocsize);

-		EnumProcesses(ids, allocsize, &outbytes);

-	} while (allocsize == outbytes);

-	

-	for (int i = 0; i < (outbytes/sizeof(DWORD)); i++) {

-		if (cygwin_winpid_to_pid(ids[i]) == pid) {

-			winpid = ids[i];

-			break;

-		}

-	}

-	

-	free(ids);

-	return winpid;

-}

-

-HANDLE WINAPI OpenThread(

-    DWORD dwDesiredAccess,

-    BOOL bInheritHandle,

-    DWORD dwThreadId);

-    

-DWORD WINAPI GetProcessIdOfThread(HANDLE Thread);

-

-static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask)

-{

-	HANDLE h;

-	BOOL bSuccess;

-	int winpid;

-	

-	h = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION, TRUE, pid);

-	if (h != NULL) {

-		bSuccess = SetThreadAffinityMask(h, cpumask);

-	} else {

-		// then we might have a process id instead of a thread id

-		winpid = pid_to_winpid(pid);

-		h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, TRUE, winpid);

-		if (h == NULL)

-			return -1;

-

-		bSuccess = SetProcessAffinityMask(h, cpumask);

-	}

-

-	CloseHandle(h);

-

-	return (bSuccess)? 0 : -1;

-}

-

-static inline void fio_getaffinity(int pid, os_cpu_mask_t *mask)

-{

-	os_cpu_mask_t systemMask;

-	int winpid;

-	

-	HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, TRUE, pid);

-	if (h != NULL)

-		winpid = GetProcessIdOfThread(h);

-	else

-		winpid = pid_to_winpid(pid);

-	

-	h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, winpid);

-

-	if (h != NULL) {

-		GetProcessAffinityMask(h, mask, &systemMask);

-		CloseHandle(h);

-	} else {

-		fprintf(stderr, "fio_getaffinity failed: failed to get handle for pid %d\n", pid);

-	}

-	

-}

-

-static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)

-{

-	*mask ^= 1 << (cpu-1);

-}

-

-static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)

-{

-	*mask |= 1 << (cpu-1);

-}

-

-static inline int fio_cpuset_init(os_cpu_mask_t *mask)

-{

-	*mask = 0;

-	return 0;

-}

-

-static inline int fio_cpuset_exit(os_cpu_mask_t *mask)

-{

-	return 0;

-}

-

-#define FIO_MAX_CPUS			MAXIMUM_PROCESSORS

-

-#ifdef MADV_FREE

-#define FIO_MADV_FREE	MADV_FREE

-#endif

-

-#endif /* FIO_OS_WINDOWS_H */

+#ifndef FIO_OS_WINDOWS_H
+#define FIO_OS_WINDOWS_H
+
+#define FIO_OS	os_windows
+
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <windows.h>
+#include <psapi.h>
+#include <stdlib.h>
+
+#include "../smalloc.h"
+#include "../file.h"
+#include "../log.h"
+
+#define FIO_HAVE_ODIRECT
+#define FIO_HAVE_CPU_AFFINITY
+#define FIO_HAVE_CHARDEV_SIZE
+#define FIO_HAVE_FDATASYNC
+#define FIO_HAVE_WINDOWSAIO
+#define FIO_HAVE_GETTID
+#define FIO_HAVE_CLOCK_MONOTONIC
+#define FIO_USE_GENERIC_RAND
+
+#define FIO_PREFERRED_ENGINE		"windowsaio"
+#define FIO_PREFERRED_CLOCK_SOURCE	CS_CGETTIME
+#define FIO_OS_PATH_SEPARATOR		"\\"
+
+#define FIO_MAX_CPUS	MAXIMUM_PROCESSORS
+
+#define FIO_OS_HAVE_SOCKLEN_T
+typedef int fio_socklen_t;
+
+#define OS_MAP_ANON		MAP_ANON
+
+#define FIO_LITTLE_ENDIAN
+#define fio_swap16(x)	_byteswap_ushort(x)
+#define fio_swap32(x)	_byteswap_ulong(x)
+#define fio_swap64(x)	_byteswap_uint64(x)
+
+typedef off_t off64_t;
+typedef int clockid_t;
+
+typedef DWORD_PTR os_cpu_mask_t;
+
+#define CLOCK_REALTIME	1
+#define CLOCK_MONOTONIC	2
+
+#define _SC_PAGESIZE			0x1
+#define _SC_NPROCESSORS_ONLN	0x2
+#define _SC_PHYS_PAGES			0x4
+
+#define SA_RESTART	0
+#define SIGPIPE		0
+
+/*
+ * Windows doesn't have O_DIRECT or O_SYNC, so define them
+ * here so we can reject them at runtime when using the _open
+ * interface (windowsaio uses CreateFile)
+ */
+#define O_DIRECT	0x1000000
+#define O_SYNC		0x2000000
+
+/* Windows doesn't support madvise, so any values will work */
+#define POSIX_MADV_DONTNEED		0
+#define POSIX_MADV_SEQUENTIAL	0
+#define POSIX_MADV_RANDOM		0
+
+#define F_SETFL			0x1
+#define F_GETFL			0x2
+#define O_NONBLOCK		FIONBIO
+
+/* Winsock doesn't support MSG_WAIT */
+#define OS_MSG_DONTWAIT	0
+
+#define POLLOUT	1
+#define POLLIN	2
+#define POLLERR	0
+#define POLLHUP	1
+
+#define SIGCONT	0
+
+typedef int sigset_t;
+typedef int siginfo_t;
+
+struct sigaction
+{
+	void (*sa_handler)(int);
+	sigset_t sa_mask;
+	int sa_flags;
+	void* (*sa_sigaction)(int, siginfo_t *, void*);
+};
+
+char *strsep(char **stringp, const char *delim);
+long sysconf(int name);
+
+int kill(pid_t pid, int sig);
+pid_t setsid(void);
+int setgid(gid_t gid);
+int setuid(uid_t uid);
+int nice(int incr);
+int sigaction(int sig, const struct sigaction *act,
+		struct sigaction *oact);
+int fsync(int fildes);
+int fork(void);
+int fcntl(int fildes, int cmd, ...);
+int fdatasync(int fildes);
+int lstat(const char * path, struct stat * buf);
+uid_t geteuid(void);
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
+ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
+		off_t offset);
+extern void td_fill_rand_seeds(struct thread_data *);
+
+static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
+{
+	int rc = 0;
+	HANDLE hFile;
+
+	if (f->hFile == NULL) {
+		hFile = CreateFile(f->file_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+				NULL, OPEN_EXISTING, 0, NULL);
+	} else {
+		hFile = f->hFile;
+	}
+
+	GET_LENGTH_INFORMATION info;
+	DWORD outBytes;
+	LARGE_INTEGER size;
+	size.QuadPart = 0;
+	if (DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &outBytes, NULL))
+		*bytes = info.Length.QuadPart;
+	else
+		rc = EIO;
+
+	/* If we were passed a POSIX fd,
+	 * close the HANDLE we created via CreateFile */
+	if (hFile != INVALID_HANDLE_VALUE && f->hFile == NULL)
+		CloseHandle(hFile);
+
+	return rc;
+}
+
+static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)
+{
+	return blockdev_size(f, bytes);
+}
+
+static inline int blockdev_invalidate_cache(struct fio_file *f)
+{
+	/* There's no way to invalidate the cache in Windows
+	 * so just pretend to succeed */
+	return 0;
+}
+
+static inline unsigned long long os_phys_mem(void)
+{
+	SYSTEM_INFO sysInfo;
+	uintptr_t addr;
+
+	GetSystemInfo(&sysInfo);
+	addr = (uintptr_t)sysInfo.lpMaximumApplicationAddress;
+	return (unsigned long long)addr;
+}
+
+static inline void os_get_tmpdir(char *path, int len)
+{
+	GetTempPath(len, path);
+}
+
+static inline int gettid(void)
+{
+	return GetCurrentThreadId();
+}
+
+static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask)
+{
+	HANDLE h;
+	BOOL bSuccess = FALSE;
+
+	h = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION, TRUE, pid);
+	if (h != NULL) {
+		bSuccess = SetThreadAffinityMask(h, cpumask);
+		CloseHandle(h);
+	}
+
+	return (bSuccess)? 0 : -1;
+}
+
+static inline void fio_getaffinity(int pid, os_cpu_mask_t *mask)
+{
+	os_cpu_mask_t systemMask;
+
+	HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
+
+	if (h != NULL) {
+		GetProcessAffinityMask(h, mask, &systemMask);
+		CloseHandle(h);
+	} else {
+		log_err("fio_getaffinity failed: failed to get handle for pid %d\n", pid);
+	}
+}
+
+static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)
+{
+	*mask ^= 1 << (cpu-1);
+}
+
+static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)
+{
+	*mask |= 1 << (cpu-1);
+}
+
+static inline int fio_cpuset_init(os_cpu_mask_t *mask)
+{
+	*mask = 0;
+	return 0;
+}
+
+static inline int fio_cpuset_exit(os_cpu_mask_t *mask)
+{
+	return 0;
+}
+
+static inline int init_random_state(struct thread_data *td, unsigned long *rand_seeds, int size)
+{
+	HCRYPTPROV hCryptProv;
+
+	if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+	{
+		errno = GetLastError();
+		log_err("CryptAcquireContext() failed: error %d\n", errno);
+		return 1;
+	}
+
+	if (!CryptGenRandom(hCryptProv, size, (BYTE*)rand_seeds)) {
+		errno = GetLastError();
+		log_err("CryptGenRandom() failed, error %d\n", errno);
+		CryptReleaseContext(hCryptProv, 0);
+		return 1;
+	}
+
+	CryptReleaseContext(hCryptProv, 0);
+	td_fill_rand_seeds(td);
+	return 0;
+}
+
+
+#endif /* FIO_OS_WINDOWS_H */