summaryrefslogtreecommitdiff
path: root/pr/src/md/windows
diff options
context:
space:
mode:
Diffstat (limited to 'pr/src/md/windows')
-rw-r--r--pr/src/md/windows/Makefile.in10
-rw-r--r--pr/src/md/windows/ntinrval.c47
-rw-r--r--pr/src/md/windows/ntio.c35
-rw-r--r--pr/src/md/windows/ntmisc.c24
-rw-r--r--pr/src/md/windows/ntthread.c43
-rw-r--r--pr/src/md/windows/w32poll.c40
-rw-r--r--pr/src/md/windows/w95io.c420
-rw-r--r--pr/src/md/windows/w95sock.c26
-rw-r--r--pr/src/md/windows/w95thred.c23
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)