diff --git a/source/lib/sysdep/win/waio.cpp b/source/lib/sysdep/win/waio.cpp index c93d0530d7..49ceeceee6 100755 --- a/source/lib/sysdep/win/waio.cpp +++ b/source/lib/sysdep/win/waio.cpp @@ -79,7 +79,6 @@ static void aio_h_cleanup() static bool is_valid_file_handle(const HANDLE h) { - SetLastError(0); bool valid = (GetFileSize(h, 0) != INVALID_FILE_SIZE); assert(valid); return valid; @@ -380,7 +379,9 @@ int aio_reopen(int fd, const char* fn, int oflag, ...) // open file DWORD flags = FILE_FLAG_OVERLAPPED|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN; + WIN_SAVE_LAST_ERROR; // CreateFile HANDLE h = CreateFile(fn, access, share, 0, create, flags, 0); + WIN_RESTORE_LAST_ERROR; if(h == INVALID_HANDLE_VALUE) { fail: @@ -411,7 +412,6 @@ int aio_close(int fd) return -1; } - SetLastError(0); if(!CloseHandle(h)) assert(0); aio_h_set(fd, INVALID_HANDLE_VALUE); @@ -437,6 +437,8 @@ static int aio_rw(struct aiocb* cb) debug_out("aio_rw cb=%p\n", cb); #endif + WIN_SAVE_LAST_ERROR; + const bool is_write = cb->aio_lio_opcode == LIO_WRITE; if(!cb) @@ -481,9 +483,7 @@ debug_out("aio_rw cb=%p\n", cb); unsigned long opt = 0; socklen_t optlen = sizeof(opt); int sock = (int)(intptr_t)h; - DWORD last_err = GetLastError(); bool is_sock = getsockopt(sock, SOL_SOCKET, SO_TYPE, &opt, &optlen) != -1; - SetLastError(last_err); // socket: no alignment calculation necessary if(is_sock) @@ -537,23 +537,26 @@ debug_out("aio_rw cb=%p\n", cb); // this assumes little endian, but we're windows-specific here anyway. *(size_t*)&r->ovl.Offset = ofs; - -assert(cb->aio_buf != 0); - - SetLastError(0); - + assert(cb->aio_buf != 0); DWORD size32 = (DWORD)(size & 0xffffffff); -ResetEvent(r->ovl.hEvent); - BOOL ok = (cb->aio_lio_opcode == LIO_READ)? - ReadFile(h, buf, size32, 0, &r->ovl) : WriteFile(h, buf, size32, 0, &r->ovl); + ResetEvent(r->ovl.hEvent); + + BOOL ok; + if(cb->aio_lio_opcode == LIO_READ) + ok = ReadFile(h, buf, size32, 0, &r->ovl); + else + ok = WriteFile(h, buf, size32, 0, &r->ovl); + + // "pending" isn't an error if(GetLastError() == ERROR_IO_PENDING) { - // clear annoying error SetLastError(0); ok = true; } + WIN_RESTORE_LAST_ERROR; + return ok? 0 : -1; } diff --git a/source/lib/sysdep/win/wcpu.cpp b/source/lib/sysdep/win/wcpu.cpp index f48e6000d3..c13836860b 100755 --- a/source/lib/sysdep/win/wcpu.cpp +++ b/source/lib/sysdep/win/wcpu.cpp @@ -50,6 +50,8 @@ int on_each_cpu(void(*cb)()) static void check_speedstep() { + WIN_SAVE_LAST_ERROR; + // CallNtPowerInformation // (manual import because it's not supported on Win95) NTSTATUS (WINAPI *pCNPI)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG) = 0; @@ -108,6 +110,8 @@ static void check_speedstep() // ia32 code will get a second crack at it. cpu_speedstep = (is_laptop)? 1 : 0; } + + WIN_RESTORE_LAST_ERROR; } diff --git a/source/lib/sysdep/win/wdetect.cpp b/source/lib/sysdep/win/wdetect.cpp index 2921f81026..9648784db8 100755 --- a/source/lib/sysdep/win/wdetect.cpp +++ b/source/lib/sysdep/win/wdetect.cpp @@ -176,6 +176,8 @@ int win_get_gfx_drv_ver() CHECK_ERR(get_ogl_drv_name(ogl_drv_name, sizeof(ogl_drv_name))); + WIN_SAVE_LAST_ERROR; // GetFileVersion*, Ver* + // don't want to return 0 on success - we'd need to duplicate free(buf). // instead, set this variable and return that. int ret = -1; @@ -208,6 +210,8 @@ int win_get_gfx_drv_ver() } free(buf); + WIN_RESTORE_LAST_ERROR; + return ret; } diff --git a/source/lib/sysdep/win/wfam.cpp b/source/lib/sysdep/win/wfam.cpp index bbc95936d1..6ff79420c2 100755 --- a/source/lib/sysdep/win/wfam.cpp +++ b/source/lib/sysdep/win/wfam.cpp @@ -262,6 +262,10 @@ static int get_packet(FAMConnection* fc); int FAMMonitorDirectory(FAMConnection* const fc, const char* const _dir, FAMRequest* const fr, void* const user_data) { + int err = -1; + WIN_SAVE_LAST_ERROR; // Create* + + { const std::string dir(_dir); GET_APP_STATE(fc, state); @@ -272,14 +276,14 @@ int FAMMonitorDirectory(FAMConnection* const fc, const char* const _dir, FAMRequ // make sure dir is not already being watched for(WatchIt it = watches.begin(); it != watches.end(); ++it) if(dir == it->second->dir_name) - return -1; + goto fail; // open handle to directory const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED; const HANDLE hDir = CreateFile(_dir, FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0); if(hDir == INVALID_HANDLE_VALUE) - return -1; + goto fail; // assign a new (unique) request number. don't do this earlier - prevents // DOS via wasting reqnums due to invalid directory parameters. @@ -287,7 +291,8 @@ int FAMMonitorDirectory(FAMConnection* const fc, const char* const _dir, FAMRequ if(last_reqnum == INT_MAX) { debug_warn("FAMMonitorDirectory: request numbers are no longer unique"); - return -1; + CloseHandle(hDir); + goto fail; } const int reqnum = ++last_reqnum; fr->reqnum = reqnum; @@ -300,9 +305,8 @@ int FAMMonitorDirectory(FAMConnection* const fc, const char* const _dir, FAMRequ hIOCP = CreateIoCompletionPort(hDir, hIOCP, key, 0); if(hIOCP == 0 || hIOCP == INVALID_HANDLE_VALUE) { -fail: CloseHandle(hDir); - return -1; + goto fail; } // create Watch and associate with FAM structs @@ -324,8 +328,13 @@ fail: // instead of only at the next call to FAMPending. PostQueuedCompletionStatus(hIOCP, 0, key, 0); get_packet(fc); + } - return 0; + err = 0; + +fail: + WIN_RESTORE_LAST_ERROR; + return err; } diff --git a/source/lib/sysdep/win/win.cpp b/source/lib/sysdep/win/win.cpp index b9363d1bda..37c156b174 100755 --- a/source/lib/sysdep/win/win.cpp +++ b/source/lib/sysdep/win/win.cpp @@ -28,6 +28,12 @@ #include +void sle(int x) +{ + SetLastError((DWORD)x); +} + + // // these override the portable stdio versions in sysdep.cpp // (they're more convenient) diff --git a/source/lib/sysdep/win/win_internal.h b/source/lib/sysdep/win/win_internal.h index 34fac415f5..96a785f5cf 100755 --- a/source/lib/sysdep/win/win_internal.h +++ b/source/lib/sysdep/win/win_internal.h @@ -316,4 +316,8 @@ extern void win_unlock(uint idx); #define WIN_REGISTER_FUNC(func) static int func(); static int(*p##func)(void) = func +#define WIN_SAVE_LAST_ERROR DWORD last_err__ = GetLastError(); +#define WIN_RESTORE_LAST_ERROR STMT(if(last_err__ != 0 && GetLastError() == 0) SetLastError(last_err__);); + + #endif // #ifndef WIN_INTERNAL_H diff --git a/source/lib/sysdep/win/wposix.cpp b/source/lib/sysdep/win/wposix.cpp index 9d1964cd48..2dc72c20af 100755 --- a/source/lib/sysdep/win/wposix.cpp +++ b/source/lib/sysdep/win/wposix.cpp @@ -66,8 +66,13 @@ int open(const char* fn, int oflag, ...) va_end(args); } + WIN_SAVE_LAST_ERROR; + int fd = _open(fn, oflag, mode); + WIN_RESTORE_LAST_ERROR; + + // open it for async I/O as well (_open defaults to deny_none sharing) if(fd > 2) { @@ -200,9 +205,18 @@ struct dirent* readdir(DIR* dir) { _DIR* d = (_DIR*)dir; + DWORD last_err = GetLastError(); + if(d->not_first) if(!FindNextFile(d->handle, &d->fd)) + { + // don't pass on the "error" + if(GetLastError() == ERROR_NO_MORE_FILES) + SetLastError(last_err); + else + debug_warn("FindNextFile failed"); return 0; + } d->not_first = true; d->ent.d_ino = 0; @@ -396,6 +410,8 @@ int pthread_mutex_destroy(pthread_mutex_t* m) void* mmap(void* start, size_t len, int prot, int flags, int fd, off_t offset) { + WIN_SAVE_LAST_ERROR; + if(!(flags & MAP_FIXED)) start = 0; @@ -434,13 +450,16 @@ void* mmap(void* start, size_t len, int prot, int flags, int fd, off_t offset) if(!ptr || (flags & MAP_FIXED && ptr != start)) return MAP_FAILED; + WIN_RESTORE_LAST_ERROR; + return ptr; } int munmap(void* start, size_t /* len */) { - return UnmapViewOfFile(start) - 1; /* 0: success; -1: fail */ + BOOL ok = UnmapViewOfFile(start); + return ok? 0 : -1; } @@ -494,7 +513,13 @@ int uname(struct utsname* un) // node name DWORD buf_size = sizeof(un->nodename); - GetComputerName(un->nodename, &buf_size); + DWORD last_err = GetLastError(); + BOOL ok = GetComputerName(un->nodename, &buf_size); + // GetComputerName sets last error even on success - suppress. + if(ok) + SetLastError(last_err); + else + debug_warn("GetComputerName failed"); // hardware type static SYSTEM_INFO si; diff --git a/source/lib/sysdep/win/wsdl.cpp b/source/lib/sysdep/win/wsdl.cpp index 23bfef14c7..d0a957e264 100755 --- a/source/lib/sysdep/win/wsdl.cpp +++ b/source/lib/sysdep/win/wsdl.cpp @@ -542,6 +542,9 @@ void SDL_Quit() */ int SDL_SetVideoMode(int w, int h, int bpp, unsigned long flags) { + int ret = 0; // assume failure + WIN_SAVE_LAST_ERROR; // OpenGL and GDI + fullscreen = (flags & SDL_FULLSCREEN) != 0; /* get current mode settings */ @@ -610,16 +613,20 @@ int SDL_SetVideoMode(int w, int h, int bpp, unsigned long flags) int pf = ChoosePixelFormat(hDC, &pfd); if(!SetPixelFormat(hDC, pf, &pfd)) - return 0; + goto fail; hGLRC = wglCreateContext(hDC); if(!hGLRC) - return 0; + goto fail; if(!wglMakeCurrent(hDC, hGLRC)) - return 0; + goto fail; - return 1; + ret = 1; + +fail: + WIN_RESTORE_LAST_ERROR; + return ret; } @@ -760,9 +767,9 @@ SDL_VideoInfo* SDL_GetVideoInfo() #ifdef DDRAW - static bool init; - if(!init) - { + WIN_SAVE_LAST_ERROR; // DirectDraw + + ONCE({ IDirectDraw* dd = 0; HRESULT hr = DirectDrawCreate(0, &dd, 0); if(SUCCEEDED(hr) && dd != 0) @@ -774,9 +781,9 @@ SDL_VideoInfo* SDL_GetVideoInfo() video_info.video_mem = caps.dwVidMemTotal; dd->Release(); } + }); - init = true; - } + WIN_RESTORE_LAST_ERROR; #endif