- // Retrieve the system error message for the last-error code
-
- LPSTR lpMsgBuf;
- DWORD dw = GetLastError();
-
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- dw,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0, NULL );
-
- log_err("%s - %s", lpszFunction, lpMsgBuf);
- LocalFree(lpMsgBuf);
+ int rc = 0;
+ DWORD flags = FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_OVERLAPPED;
+ DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ DWORD openmode = OPEN_ALWAYS;
+ DWORD access;
+
+ dprint(FD_FILE, "fd open %s\n", f->file_name);
+
+ if (f->filetype == FIO_TYPE_PIPE) {
+ log_err("windowsaio: pipes are not supported\n");
+ return 1;
+ }
+
+ if (!strcmp(f->file_name, "-")) {
+ log_err("windowsaio: can't read/write to stdin/out\n");
+ return 1;
+ }
+
+ if (td->o.odirect)
+ flags |= FILE_FLAG_NO_BUFFERING;
+ if (td->o.sync_io)
+ flags |= FILE_FLAG_WRITE_THROUGH;
+
+ /*
+ * Inform Windows whether we're going to be doing sequential or
+ * random io so it can tune the Cache Manager
+ */
+ if (td->o.td_ddir == TD_DDIR_READ ||
+ td->o.td_ddir == TD_DDIR_WRITE)
+ flags |= FILE_FLAG_SEQUENTIAL_SCAN;
+ else
+ flags |= FILE_FLAG_RANDOM_ACCESS;
+
+ if (!td_write(td) || read_only)
+ access = GENERIC_READ;
+ else
+ access = (GENERIC_READ | GENERIC_WRITE);
+
+ if (td->o.create_on_open)
+ openmode = OPEN_ALWAYS;
+ else
+ openmode = OPEN_EXISTING;
+
+ f->hFile = CreateFile(f->file_name, access, sharemode,
+ NULL, openmode, flags, NULL);
+
+ if (f->hFile == INVALID_HANDLE_VALUE) {
+ log_err("windowsaio: failed to open file \"%s\"\n", f->file_name);
+ rc = 1;
+ }
+
+ /* Only set up the completion port and thread if we're not just
+ * querying the device size */
+ if (!rc && td->io_ops->data != NULL) {
+ struct windowsaio_data *wd;
+
+ wd = td->io_ops->data;
+
+ if (CreateIoCompletionPort(f->hFile, wd->iocp, 0, 0) == NULL) {
+ log_err("windowsaio: failed to create io completion port\n");
+ rc = 1;
+ }
+ }
+
+ return rc;