diff options
Diffstat (limited to 'pr/src/md/windows')
-rw-r--r-- | pr/src/md/windows/Makefile.in | 10 | ||||
-rw-r--r-- | pr/src/md/windows/ntinrval.c | 47 | ||||
-rw-r--r-- | pr/src/md/windows/ntio.c | 35 | ||||
-rw-r--r-- | pr/src/md/windows/ntmisc.c | 24 | ||||
-rw-r--r-- | pr/src/md/windows/ntthread.c | 43 | ||||
-rw-r--r-- | pr/src/md/windows/w32poll.c | 40 | ||||
-rw-r--r-- | pr/src/md/windows/w95io.c | 420 | ||||
-rw-r--r-- | pr/src/md/windows/w95sock.c | 26 | ||||
-rw-r--r-- | pr/src/md/windows/w95thred.c | 23 |
9 files changed, 606 insertions, 62 deletions
diff --git a/pr/src/md/windows/Makefile.in b/pr/src/md/windows/Makefile.in index 283fa4a4..dd5a613b 100644 --- a/pr/src/md/windows/Makefile.in +++ b/pr/src/md/windows/Makefile.in @@ -105,3 +105,13 @@ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) +# Bug 122433 workaround: disable global optimization (-Og-) on ntio.c. +ifdef BUILD_OPT +ifeq ($(OS_TARGET), WINNT) +ifndef NS_USE_GCC +$(OBJDIR)/ntio.$(OBJ_SUFFIX): ntio.c + @$(MAKE_OBJDIR) + $(CC) -Fo$@ -c $(CFLAGS) -Og- $< +endif +endif +endif diff --git a/pr/src/md/windows/ntinrval.c b/pr/src/md/windows/ntinrval.c index d6a3fe6f..857ada6a 100644 --- a/pr/src/md/windows/ntinrval.c +++ b/pr/src/md/windows/ntinrval.c @@ -45,9 +45,8 @@ #define QueryPerformanceCounter(x) FALSE #endif -PRIntn _nt_bitShift = 0; -PRInt32 _nt_highMask = 0; -PRInt32 _nt_ticksPerSec = -1; +static PRIntn _nt_bitShift = 0; +static PRInt32 _nt_ticksPerSec = -1; void _PR_MD_INTERVAL_INIT() @@ -55,16 +54,33 @@ _PR_MD_INTERVAL_INIT() LARGE_INTEGER count; if (QueryPerformanceFrequency(&count)) { + /* + * HighPart is signed (LONG). Assert that its sign bit is 0 + * because we will be right shifting it. LowPart is unsigned + * (DWORD). + */ + PR_ASSERT(count.HighPart >= 0); + while(count.HighPart) { + count.LowPart = (count.HighPart << 31) + (count.LowPart >> 1); + count.HighPart >>= 1; + _nt_bitShift++; + } while(count.LowPart > PR_INTERVAL_MAX) { count.LowPart >>= 1; _nt_bitShift++; - _nt_highMask = (_nt_highMask << 1)+1; } - _nt_ticksPerSec = count.LowPart; - PR_ASSERT(_nt_ticksPerSec > PR_INTERVAL_MIN); - } else - _nt_ticksPerSec = -1; + /* + * We can't use the performance counter if after + * normalization we are left with fewer than 32 bits. + */ + if (_nt_bitShift <= 32) { + _nt_ticksPerSec = count.LowPart; + PR_ASSERT(_nt_ticksPerSec > PR_INTERVAL_MIN); + return; + } + } + _nt_ticksPerSec = -1; } PRIntervalTime @@ -76,12 +92,15 @@ _PR_MD_GET_INTERVAL() * to only 100000 ticks per second; QueryPerformanceCounter is too high * resolution... */ - if (QueryPerformanceCounter(&count)) { - PRInt32 top = count.HighPart & _nt_highMask; - top = top << (32 - _nt_bitShift); - count.LowPart = count.LowPart >> _nt_bitShift; - count.LowPart = count.LowPart + top; - return (PRUint32)count.LowPart; + if (_nt_ticksPerSec != -1) { + (void)QueryPerformanceCounter(&count); + PR_ASSERT(_nt_bitShift <= 32); + if (_nt_bitShift == 32) { + return (PRUint32)count.HighPart; + } else { + return (PRUint32)((count.HighPart << (32 - _nt_bitShift)) + + (count.LowPart >> _nt_bitShift)); + } } else #if defined(__MINGW32__) return time(); diff --git a/pr/src/md/windows/ntio.c b/pr/src/md/windows/ntio.c index 299033cc..345e253a 100644 --- a/pr/src/md/windows/ntio.c +++ b/pr/src/md/windows/ntio.c @@ -99,7 +99,11 @@ static DWORD dirAccessTable[] = { * We store the value in a PRTime variable for convenience. * This constant is used by _PR_FileTimeToPRTime(). */ +#ifdef __GNUC__ +static const PRTime _pr_filetime_offset = 116444736000000000LL; +#else static const PRTime _pr_filetime_offset = 116444736000000000i64; +#endif #define _NEED_351_FILE_LOCKING_HACK #ifdef _NEED_351_FILE_LOCKING_HACK @@ -1328,6 +1332,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); + closesocket(accept_sock); return -1; } me->io_pending = PR_TRUE; @@ -1346,6 +1351,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) { /* Argh! The IO failed */ + closesocket(accept_sock); _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; @@ -1365,12 +1371,14 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); + closesocket(accept_sock); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { + closesocket(accept_sock); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); @@ -1381,6 +1389,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, } if (me->md.blocked_io_status == 0) { + closesocket(accept_sock); _PR_MD_MAP_ACCEPTEX_ERROR(me->md.blocked_io_error); return -1; } @@ -1446,6 +1455,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); + closesocket(*newSock); return -1; } me->io_pending = PR_TRUE; @@ -1463,6 +1473,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, &(me->md.overlapped.overlapped)); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) { + closesocket(*newSock); _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; @@ -1482,6 +1493,7 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); + closesocket(*newSock); return -1; } @@ -1511,8 +1523,10 @@ retry: callback(callbackArg); madeCallback = PR_TRUE; me->state = _PR_IO_WAIT; - if (_NT_ResumeIO(me, timeout) == PR_FAILURE) + if (_NT_ResumeIO(me, timeout) == PR_FAILURE) { + closesocket(*newSock); return -1; + } goto retry; } @@ -1520,8 +1534,10 @@ retry: /* Socket is connected but time not elapsed, RESUME IO */ timeout -= elapsed; me->state = _PR_IO_WAIT; - if (_NT_ResumeIO(me, timeout) == PR_FAILURE) + if (_NT_ResumeIO(me, timeout) == PR_FAILURE) { + closesocket(*newSock); return -1; + } goto retry; } } else { @@ -1548,6 +1564,7 @@ retry: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } me->state = _PR_RUNNING; + closesocket(*newSock); return -1; } @@ -2322,7 +2339,7 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) } PRInt32 -_PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len) +_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) { PRInt32 f = fd->secret->md.osfd; PRInt32 bytes; @@ -2488,7 +2505,7 @@ _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) } PROffset32 -_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, int whence) +_PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence) { DWORD moveMethod; PROffset32 rv; @@ -2521,7 +2538,7 @@ _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, int whence) } PROffset64 -_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, int whence) +_PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence) { DWORD moveMethod; LARGE_INTEGER li; @@ -2815,12 +2832,16 @@ _PR_MD_DELETE(const char *name) } } -static void +void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) { PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); CopyMemory(prtm, filetime, sizeof(PRTime)); +#ifdef __GNUC__ + *prtm = (*prtm - _pr_filetime_offset) / 10LL; +#else *prtm = (*prtm - _pr_filetime_offset) / 10i64; +#endif #ifdef DEBUG /* Doublecheck our calculation. */ @@ -3168,7 +3189,7 @@ _PR_MD_RENAME(const char *from, const char *to) } PRInt32 -_PR_MD_ACCESS(const char *name, PRIntn how) +_PR_MD_ACCESS(const char *name, PRAccessHow how) { PRInt32 rv; diff --git a/pr/src/md/windows/ntmisc.c b/pr/src/md/windows/ntmisc.c index c4bb8511..32a199ce 100644 --- a/pr/src/md/windows/ntmisc.c +++ b/pr/src/md/windows/ntmisc.c @@ -84,18 +84,12 @@ PRIntn _PR_MD_PUT_ENV(const char *name) PR_IMPLEMENT(PRTime) PR_Now(void) { - PRInt64 s, ms, ms2us, s2us; - struct timeb b; - - ftime(&b); - LL_I2L(ms2us, PR_USEC_PER_MSEC); - LL_I2L(s2us, PR_USEC_PER_SEC); - LL_I2L(s, b.time); - LL_I2L(ms, b.millitm); - LL_MUL(ms, ms, ms2us); - LL_MUL(s, s, s2us); - LL_ADD(s, s, ms); - return s; + PRTime prt; + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + _PR_FileTimeToPRTime(&ft, &prt); + return prt; } /* @@ -792,7 +786,7 @@ PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) PRInt32 result; asm volatile ("lock ; xadd %0, %1" : "=r"(result), "=m"(*val) - : "0"(1), "m"(*val)); + : "0"(-1), "m"(*val)); //asm volatile("lock ; xadd %0, %1" : "=m" (val), "=a" (result) : "-1" (1)); return result - 1; #else @@ -814,8 +808,8 @@ PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val) PRInt32 result; //asm volatile("lock ; xadd %1, %0" : "=m" (intp), "=a" (result) : "1" (val)); asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(intp) - : "0"(val), "m"(intp)); + : "=r"(result), "=m"(*intp) + : "0"(val), "m"(*intp)); return result + val; #else __asm diff --git a/pr/src/md/windows/ntthread.c b/pr/src/md/windows/ntthread.c index 9c3e2baf..0e7ef6e0 100644 --- a/pr/src/md/windows/ntthread.c +++ b/pr/src/md/windows/ntthread.c @@ -191,6 +191,14 @@ _PR_MD_INIT_THREAD(PRThread *thread) return PR_SUCCESS; } +static unsigned __stdcall +pr_root(void *arg) +{ + PRThread *thread = (PRThread *)arg; + thread->md.start(thread); + return 0; +} + PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), @@ -200,23 +208,14 @@ _PR_MD_CREATE_THREAD(PRThread *thread, PRUint32 stackSize) { -#if 0 - thread->md.handle = CreateThread( - NULL, /* security attrib */ - thread->stack->stackSize, /* stack size */ - (LPTHREAD_START_ROUTINE)start, /* startup routine */ - (void *)thread, /* thread param */ - CREATE_SUSPENDED, /* create flags */ - &(thread->id) ); /* thread id */ -#else + thread->md.start = start; thread->md.handle = (HANDLE) _beginthreadex( NULL, thread->stack->stackSize, - (unsigned (__stdcall *)(void *))start, + pr_root, (void *)thread, CREATE_SUSPENDED, &(thread->id)); -#endif if(!thread->md.handle) { PRErrorCode prerror; thread->md.fiber_last_error = GetLastError(); @@ -238,6 +237,13 @@ _PR_MD_CREATE_THREAD(PRThread *thread, } thread->md.id = thread->id; + /* + * On windows, a thread is created with a thread priority of + * THREAD_PRIORITY_NORMAL. + */ + if (priority != PR_PRIORITY_NORMAL) { + _PR_MD_SET_PRIORITY(&(thread->md), priority); + } /* Activate the thread */ if ( ResumeThread( thread->md.handle ) != -1) @@ -247,6 +253,21 @@ _PR_MD_CREATE_THREAD(PRThread *thread, return PR_FAILURE; } +void +_PR_MD_JOIN_THREAD(_MDThread *md) +{ + DWORD rv; + + rv = WaitForSingleObject(md->handle, INFINITE); + PR_ASSERT(WAIT_OBJECT_0 == rv); +} + +void +_PR_MD_END_THREAD(void) +{ + _endthreadex(0); +} + void _PR_MD_YIELD(void) { diff --git a/pr/src/md/windows/w32poll.c b/pr/src/md/windows/w32poll.c index 2747a040..403aa004 100644 --- a/pr/src/md/windows/w32poll.c +++ b/pr/src/md/windows/w32poll.c @@ -36,6 +36,9 @@ * This file implements _PR_MD_PR_POLL for Win32. */ +/* The default value of FD_SETSIZE is 64. */ +#define FD_SETSIZE 1024 + #include "primpl.h" #if !defined(_PR_GLOBAL_THREADS_ONLY) @@ -105,6 +108,8 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { int ready, err; fd_set rd, wt, ex; + fd_set *rdp, *wtp, *exp; + int nrd, nwt, nex; PRFileDesc *bottom; PRPollDesc *pd, *epd; PRThread *me = _PR_MD_CURRENT_THREAD(); @@ -127,6 +132,7 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) return 0; } + nrd = nwt = nex = 0; FD_ZERO(&rd); FD_ZERO(&wt); FD_ZERO(&ex); @@ -189,23 +195,30 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { pd->out_flags |= _PR_POLL_READ_SYS_READ; FD_SET(osfd, &rd); + nrd++; } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; FD_SET(osfd, &wt); + nwt++; } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; FD_SET(osfd, &rd); + nrd++; } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; FD_SET(osfd, &wt); + nwt++; + } + if (pd->in_flags & PR_POLL_EXCEPT) { + FD_SET(osfd, &ex); + nex++; } - if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); } } else @@ -223,23 +236,40 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) } } } + else + { + pd->out_flags = 0; + } } if (0 != ready) return ready; /* no need to block */ + if ((nrd > FD_SETSIZE) || (nwt > FD_SETSIZE) || (nex > FD_SETSIZE)) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + + rdp = (0 == nrd) ? NULL : &rd; + wtp = (0 == nwt) ? NULL : &wt; + exp = (0 == nex) ? NULL : &ex; + + if ((NULL == rdp) && (NULL == wtp) && (NULL == exp)) { + PR_Sleep(timeout); + return 0; + } + if (timeout != PR_INTERVAL_NO_TIMEOUT) { PRInt32 ticksPerSecond = PR_TicksPerSecond(); tv.tv_sec = timeout / ticksPerSecond; - tv.tv_usec = timeout - (ticksPerSecond * tv.tv_sec); - tv.tv_usec = (PR_USEC_PER_SEC * tv.tv_usec) / ticksPerSecond; + tv.tv_usec = PR_IntervalToMicroseconds( timeout % ticksPerSecond ); tvp = &tv; } #if defined(_PR_GLOBAL_THREADS_ONLY) - ready = _MD_SELECT(0, &rd, &wt, &ex, tvp); + ready = _MD_SELECT(0, rdp, wtp, exp, tvp); #else - ready = _PR_NTFiberSafeSelect(0, &rd, &wt, &ex, tvp); + ready = _PR_NTFiberSafeSelect(0, rdp, wtp, exp, tvp); #endif /* diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index 89669e6e..6ccdf410 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -41,6 +41,9 @@ #include "primpl.h" #include <direct.h> #include <mbstring.h> +#ifdef MOZ_UNICODE +#include <wchar.h> +#endif /* MOZ_UNICODE */ struct _MDLock _pr_ioq_lock; @@ -74,6 +77,10 @@ static const PRTime _pr_filetime_offset = 116444736000000000LL; static const PRTime _pr_filetime_offset = 116444736000000000i64; #endif +#ifdef MOZ_UNICODE +static void InitUnicodeSupport(void); +#endif + void _PR_MD_INIT_IO() { @@ -110,6 +117,10 @@ _PR_MD_INIT_IO() #endif /* DEBUG */ _PR_NT_InitSids(); + +#ifdef MOZ_UNICODE + InitUnicodeSupport(); +#endif } PRStatus @@ -568,7 +579,7 @@ _PR_MD_DELETE(const char *name) } } -static void +void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) { PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); @@ -1088,3 +1099,410 @@ _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } + +#ifdef MOZ_UNICODE + +typedef HANDLE (WINAPI *CreateFileWFn) (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); +static CreateFileWFn createFileW = NULL; +typedef HANDLE (WINAPI *FindFirstFileWFn) (LPCWSTR, LPWIN32_FIND_DATAW); +static FindFirstFileWFn findFirstFileW = NULL; +typedef BOOL (WINAPI *FindNextFileWFn) (HANDLE, LPWIN32_FIND_DATAW); +static FindNextFileWFn findNextFileW = NULL; +typedef DWORD (WINAPI *GetFullPathNameWFn) (LPCWSTR, DWORD, LPWSTR, LPWSTR *); +static GetFullPathNameWFn getFullPathNameW = NULL; +typedef UINT (WINAPI *GetDriveTypeWFn) (LPCWSTR); +static GetDriveTypeWFn getDriveTypeW = NULL; + +static void InitUnicodeSupport(void) +{ + HMODULE module; + + /* + * The W functions do not exist on Win9x. NSPR won't run on Win9x + * if we call the W functions directly. Use GetProcAddress() to + * look up their addresses at run time. + */ + + module = GetModuleHandle("Kernel32.dll"); + if (!module) { + return; + } + + createFileW = (CreateFileWFn)GetProcAddress(module, "CreateFileW"); + findFirstFileW = (FindFirstFileWFn)GetProcAddress(module, "FindFirstFileW"); + findNextFileW = (FindNextFileWFn)GetProcAddress(module, "FindNextFileW"); + getDriveTypeW = (GetDriveTypeWFn)GetProcAddress(module, "GetDriveTypeW"); + getFullPathNameW = (GetFullPathNameWFn)GetProcAddress(module, "GetFullPathNameW"); +} + +/* ================ UTF16 Interfaces ================================ */ +void FlipSlashesW(PRUnichar *cp, int len) +{ + while (--len >= 0) { + if (cp[0] == L'/') { + cp[0] = L'\\'; + } + cp++; + } +} /* end FlipSlashesW() */ + +PRInt32 +_PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, int mode) +{ + HANDLE file; + PRInt32 access = 0; + PRInt32 flags = 0; + PRInt32 flag6 = 0; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + + if (!createFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; + } + + if (osflags & PR_CREATE_FILE) { + if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } + } + + if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; + + if (osflags & PR_RDONLY || osflags & PR_RDWR) + access |= GENERIC_READ; + if (osflags & PR_WRONLY || osflags & PR_RDWR) + access |= GENERIC_WRITE; + + if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) + flags = CREATE_NEW; + else if (osflags & PR_CREATE_FILE) { + if (osflags & PR_TRUNCATE) + flags = CREATE_ALWAYS; + else + flags = OPEN_ALWAYS; + } else { + if (osflags & PR_TRUNCATE) + flags = TRUNCATE_EXISTING; + else + flags = OPEN_EXISTING; + } + + file = createFileW(name, + access, + FILE_SHARE_READ|FILE_SHARE_WRITE, + lpSA, + flags, + flag6, + NULL); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } + if (file == INVALID_HANDLE_VALUE) { + _PR_MD_MAP_OPEN_ERROR(GetLastError()); + return -1; + } + + return (PRInt32)file; +} + +PRStatus +_PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *d, const PRUnichar *name) +{ + PRUnichar filename[ MAX_PATH ]; + int len; + + if (!findFirstFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; + } + + len = wcslen(name); + /* Need 5 bytes for \*.* and the trailing null byte. */ + if (len + 5 > MAX_PATH) { + PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); + return PR_FAILURE; + } + wcscpy(filename, name); + + /* + * If 'name' ends in a slash or backslash, do not append + * another backslash. + */ + if (filename[len - 1] == L'/' || filename[len - 1] == L'\\') { + len--; + } + wcscpy(&filename[len], L"\\*.*"); + FlipSlashesW( filename, wcslen(filename) ); + + d->d_hdl = findFirstFileW( filename, &(d->d_entry) ); + if ( d->d_hdl == INVALID_HANDLE_VALUE ) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return PR_FAILURE; + } + d->firstEntry = PR_TRUE; + d->magic = _MD_MAGIC_DIR; + return PR_SUCCESS; +} + +PRUnichar * +_PR_MD_READ_DIR_UTF16(_MDDirUTF16 *d, PRIntn flags) +{ + PRInt32 err; + BOOL rv; + PRUnichar *fileName; + + if (!findNextFileW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return NULL; + } + + if ( d ) { + while (1) { + if (d->firstEntry) { + d->firstEntry = PR_FALSE; + rv = 1; + } else { + rv = findNextFileW(d->d_hdl, &(d->d_entry)); + } + if (rv == 0) { + break; + } + fileName = GetFileFromDIR(d); + if ( (flags & PR_SKIP_DOT) && + (fileName[0] == L'.') && (fileName[1] == L'\0')) + continue; + if ( (flags & PR_SKIP_DOT_DOT) && + (fileName[0] == L'.') && (fileName[1] == L'.') && + (fileName[2] == L'\0')) + continue; + if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) + continue; + return fileName; + } + err = GetLastError(); + PR_ASSERT(NO_ERROR != err); + _PR_MD_MAP_READDIR_ERROR(err); + return NULL; + } + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return NULL; +} + +PRStatus +_PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *d) +{ + if ( d ) { + if (FindClose(d->d_hdl)) { + d->magic = (PRUint32)-1; + return PR_SUCCESS; + } else { + _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError()); + return PR_FAILURE; + } + } + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return PR_FAILURE; +} + +#define _PR_IS_W_SLASH(ch) ((ch) == L'/' || (ch) == L'\\') + +/* + * IsRootDirectoryW -- + * + * Return PR_TRUE if the pathname 'fn' is a valid root directory, + * else return PR_FALSE. The PRUnichar buffer pointed to by 'fn' must + * be writable. During the execution of this function, the contents + * of the buffer pointed to by 'fn' may be modified, but on return + * the original contents will be restored. 'buflen' is the size of + * the buffer pointed to by 'fn', in PRUnichars. + * + * Root directories come in three formats: + * 1. / or \, meaning the root directory of the current drive. + * 2. C:/ or C:\, where C is a drive letter. + * 3. \\<server name>\<share point name>\ or + * \\<server name>\<share point name>, meaning the root directory + * of a UNC (Universal Naming Convention) name. + */ + +static PRBool +IsRootDirectoryW(PRUnichar *fn, size_t buflen) +{ + PRUnichar *p; + PRBool slashAdded = PR_FALSE; + PRBool rv = PR_FALSE; + + if (_PR_IS_W_SLASH(fn[0]) && fn[1] == L'\0') { + return PR_TRUE; + } + + if (iswalpha(fn[0]) && fn[1] == L':' && _PR_IS_W_SLASH(fn[2]) + && fn[3] == L'\0') { + rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; + return rv; + } + + /* The UNC root directory */ + + if (_PR_IS_W_SLASH(fn[0]) && _PR_IS_W_SLASH(fn[1])) { + /* The 'server' part should have at least one character. */ + p = &fn[2]; + if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the next slash */ + do { + p++; + } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); + if (*p == L'\0') { + return PR_FALSE; + } + + /* The 'share' part should have at least one character. */ + p++; + if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { + return PR_FALSE; + } + + /* look for the final slash */ + do { + p++; + } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); + if (_PR_IS_W_SLASH(*p) && p[1] != L'\0') { + return PR_FALSE; + } + if (*p == L'\0') { + /* + * GetDriveType() doesn't work correctly if the + * path is of the form \\server\share, so we add + * a final slash temporarily. + */ + if ((p + 1) < (fn + buflen)) { + *p++ = L'\\'; + *p = L'\0'; + slashAdded = PR_TRUE; + } else { + return PR_FALSE; /* name too long */ + } + } + rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; + /* restore the 'fn' buffer */ + if (slashAdded) { + *--p = L'\0'; + } + } + return rv; +} + +PRInt32 +_PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info) +{ + HANDLE hFindFile; + WIN32_FIND_DATAW findFileData; + PRUnichar pathbuf[MAX_PATH + 1]; + + if (!findFirstFileW || !getFullPathNameW || !getDriveTypeW) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return -1; + } + + if (NULL == fn || L'\0' == *fn) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return -1; + } + + /* + * FindFirstFile() expands wildcard characters. So + * we make sure the pathname contains no wildcard. + */ + if (NULL != wcspbrk(fn, L"?*")) { + PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); + return -1; + } + + hFindFile = findFirstFileW(fn, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + DWORD len; + PRUnichar *filePart; + + /* + * FindFirstFile() does not work correctly on root directories. + * It also doesn't work correctly on a pathname that ends in a + * slash. So we first check to see if the pathname specifies a + * root directory. If not, and if the pathname ends in a slash, + * we remove the final slash and try again. + */ + + /* + * If the pathname does not contain ., \, and /, it cannot be + * a root directory or a pathname that ends in a slash. + */ + if (NULL == wcspbrk(fn, L".\\/")) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + len = getFullPathNameW(fn, sizeof(pathbuf)/sizeof(pathbuf[0]), pathbuf, + &filePart); + if (0 == len) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + if (len > sizeof(pathbuf)/sizeof(pathbuf[0])) { + PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); + return -1; + } + if (IsRootDirectoryW(pathbuf, sizeof(pathbuf)/sizeof(pathbuf[0]))) { + info->type = PR_FILE_DIRECTORY; + info->size = 0; + /* + * These timestamps don't make sense for root directories. + */ + info->modifyTime = 0; + info->creationTime = 0; + return 0; + } + if (!_PR_IS_W_SLASH(pathbuf[len - 1])) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } else { + pathbuf[len - 1] = L'\0'; + hFindFile = findFirstFileW(pathbuf, &findFileData); + if (INVALID_HANDLE_VALUE == hFindFile) { + _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); + return -1; + } + } + } + + FindClose(hFindFile); + + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + info->type = PR_FILE_DIRECTORY; + } else { + info->type = PR_FILE_FILE; + } + + info->size = findFileData.nFileSizeHigh; + info->size = (info->size << 32) + findFileData.nFileSizeLow; + + _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime); + + if (0 == findFileData.ftCreationTime.dwLowDateTime && + 0 == findFileData.ftCreationTime.dwHighDateTime) { + info->creationTime = info->modifyTime; + } else { + _PR_FileTimeToPRTime(&findFileData.ftCreationTime, + &info->creationTime); + } + + return 0; +} +/* ================ end of UTF16 Interfaces ================================ */ +#endif /* MOZ_UNICODE */ diff --git a/pr/src/md/windows/w95sock.c b/pr/src/md/windows/w95sock.c index d36ffdcd..58944703 100644 --- a/pr/src/md/windows/w95sock.c +++ b/pr/src/md/windows/w95sock.c @@ -168,7 +168,6 @@ PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv; - int one = 1; rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen); @@ -180,6 +179,20 @@ _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) return 0; } +PRInt32 +_PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) +{ + PRInt32 rv; + + rv = listen(fd->secret->md.osfd, backlog); + + if (rv == SOCKET_ERROR) { + _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError()); + return -1; + } + + return 0; +} PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, @@ -461,6 +474,7 @@ static PRInt32 socket_io_wait( struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime elapsed, remaining; + PRBool wait_for_remaining; fd_set rd_wr, ex; int err, len; @@ -547,8 +561,10 @@ static PRInt32 socket_io_wait( * so that there is an upper limit on the delay * before the interrupt bit is checked. */ + wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { + wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { @@ -618,8 +634,12 @@ static PRInt32 socket_io_wait( */ if (rv == 0 ) { - elapsed = PR_SecondsToInterval(tv.tv_sec) - + PR_MicrosecondsToInterval(tv.tv_usec); + if (wait_for_remaining) { + elapsed = remaining; + } else { + elapsed = PR_SecondsToInterval(tv.tv_sec) + + PR_MicrosecondsToInterval(tv.tv_usec); + } if (elapsed >= remaining) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c index a70f1620..f2519f42 100644 --- a/pr/src/md/windows/w95thred.c +++ b/pr/src/md/windows/w95thred.c @@ -106,6 +106,14 @@ _PR_MD_INIT_THREAD(PRThread *thread) return PR_SUCCESS; } +static unsigned __stdcall +pr_root(void *arg) +{ + PRThread *thread = (PRThread *)arg; + thread->md.start(thread); + return 0; +} + PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), @@ -115,14 +123,11 @@ _PR_MD_CREATE_THREAD(PRThread *thread, PRUint32 stackSize) { + thread->md.start = start; thread->md.handle = (HANDLE) _beginthreadex( NULL, thread->stack->stackSize, -#if defined(__MINGW32__) - (void *)start, -#else - (unsigned (__stdcall *)(void *))start, -#endif + pr_root, (void *)thread, CREATE_SUSPENDED, &(thread->id)); @@ -131,7 +136,13 @@ _PR_MD_CREATE_THREAD(PRThread *thread, } thread->md.id = thread->id; - _PR_MD_SET_PRIORITY(&(thread->md), priority); + /* + * On windows, a thread is created with a thread priority of + * THREAD_PRIORITY_NORMAL. + */ + if (priority != PR_PRIORITY_NORMAL) { + _PR_MD_SET_PRIORITY(&(thread->md), priority); + } /* Activate the thread */ if ( ResumeThread( thread->md.handle ) != -1) |