William A. Rowe, Jr. wrote:
> Ioan Popescu wrote:
>> Why is "WINNT" defined in the project file? What does it "mean"? It 
>> wasn't explicitly defined before, why is it now?
>> 
>> Just checking whether I need this for CE...
> 
> I don't think you do; we look at each.
> 
> WINNT triggers some shorthands to melt away Win9x code from the build 
> when it's contained within the various ELSE_WIN_OS_IS_ANSI blocks, and 
> eliminating the conditional evaluation behind IF_WIN_OS_IS_UNICODE, but I
> believe those macros are already triggered by _WINCE.

You're right. I don't need to worry about WINNT.

I've checked the libapriconv and libaprutil patches and both apply cleanly
to trunk. Not all patches to libapr are clean, but the ones that are, I've
reattached. I've also found a couple errors in my own previous patches to
libapr and updated the use of _WIN32_WCE. APIs existing before or including
CE 3 default to checking whether it's defined. APIs existing afterwards are
used only if they exist (depends on _WIN32_WCE version).

Still working on the files that won't merge because they're too different. I
have to do them by hand. Probably won't have anything until next week.
Index: dso/win32/dso.c
===================================================================
--- dso/win32/dso.c     (revision 584220)
+++ dso/win32/dso.c     (working copy)
@@ -141,7 +141,7 @@
     apr_wchar_t wsymname[256];
     apr_status_t rv;
 
-    rv = apr_conv_utf8_to_ucs2(wsymname, &wsymlen, symname, &symlen);
+    rv = apr_conv_utf8_to_ucs2(symname, &symlen, wsymname, &wsymlen);
     if (rv != APR_SUCCESS) {
         return rv;
     }
Index: file_io/unix/tempdir.c
===================================================================
--- file_io/unix/tempdir.c      (revision 584220)
+++ file_io/unix/tempdir.c      (working copy)
@@ -17,8 +17,8 @@
 #include "apr_file_io.h"
 #include "apr_strings.h"
 #include "apr_env.h"
+#include "apr_arch_file_io.h"
 
-
 /* Try to open a temporary file in the temporary dir, write to it,
    and then close it. */
 static int test_tempdir(const char *temp_dir, apr_pool_t *p)
@@ -41,6 +41,7 @@
                                            apr_pool_t *p)
 {
     apr_status_t apr_err;
+#ifndef _WIN32_WCE
     const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" };
     const char *try_envs[] = { "TMP", "TEMP", "TMPDIR" };
     const char *dir;
@@ -126,5 +127,22 @@
 
 end:
     *temp_dir = apr_pstrdup(p, dir);
+#else
+    char *dir;
+    apr_wchar_t wdir[APR_PATH_MAX] = {0};
+    DWORD len;
+
+    len = GetTempPathW(APR_PATH_MAX, wdir);
+    if (!len)
+        return APR_EGENERAL;
+    /* Need to remove the trailing back-slash. */
+    wdir[len-1] = 0;
+    dir = apr_pcalloc(p, APR_PATH_MAX);
+    apr_err = unicode_to_utf8_path(dir, APR_PATH_MAX, wdir);
+    if (apr_err != APR_SUCCESS)
+        return apr_err;
+    if (test_tempdir(dir, p))
+        *temp_dir = dir;
+#endif
     return APR_SUCCESS;
 }
Index: file_io/win32/dir.c
===================================================================
--- file_io/win32/dir.c (revision 584220)
+++ file_io/win32/dir.c (working copy)
@@ -95,7 +95,17 @@
                         apr_pool_cleanup_null);
 
     rv = apr_dir_read(NULL, 0, *new);
+#ifndef _WIN32_WCE
     if (rv != APR_SUCCESS) {
+#else
+    /* CE fails apr_dir_read() on an *empty* directory
+     * (no "." nor ".." files).
+     */
+    if (rv == APR_FROM_OS_ERROR(ERROR_NO_MORE_FILES)) {
+        rv = APR_SUCCESS;
+    }
+    else if (rv != APR_SUCCESS) {
+#endif
         dir_cleanup(*new);
         *new = NULL;
     }
@@ -266,8 +276,17 @@
      */
     rv = dir_cleanup(dir);
 
-    if (rv == APR_SUCCESS)
+    if (rv == APR_SUCCESS) {
         rv = apr_dir_read(NULL, 0, dir);
+#ifdef _WIN32_WCE
+        /* CE fails apr_dir_read() on an *empty* directory
+         * (no "." nor ".." files).
+         */
+        if (rv == APR_FROM_OS_ERROR(ERROR_NO_MORE_FILES)) {
+            rv = APR_SUCCESS;
+        }
+#endif
+    }
 
     return rv;
 }
Index: file_io/win32/filepath.c
===================================================================
--- file_io/win32/filepath.c    (revision 584220)
+++ file_io/win32/filepath.c    (working copy)
@@ -265,7 +265,8 @@
             return APR_EINCOMPLETE;
         }
 
-        /* Left with a path of '/', what drive are we asking about? 
+#ifndef _WIN32_WCE
+        /* Left with a path of '/', what drive are we asking about?
          */
         *inpath = testpath + 1;
         newpath = apr_palloc(p, 2);
@@ -276,8 +277,37 @@
         newpath[1] = '\0';
         *rootpath = newpath;
         return APR_EINCOMPLETE;
+#else
+        /* Evaluate path of '/' (root on CE). */
+        do {
+            apr_status_t rv;
+            /* Validate that '/' drive exists, test must be rooted
+             */
+            newpath = apr_palloc(p, 2);
+            newpath[0] = seperator[0];
+            newpath[1] = '\0';
+            if (flags & APR_FILEPATH_TRUENAME) {
+                rv = filepath_root_test(newpath, p);
+                if (rv)
+                    return rv;
+            }
+
+            /* strip off remaining slashes that designate the root,
+             * give the caller back their original choice of slash
+             * unless this is NATIVED'ed
+             */
+            *inpath = testpath + 1;
+            while (**inpath == '/' || **inpath == '\\')
+                ++*inpath;
+            if (!(flags & APR_FILEPATH_NATIVE))
+                newpath[0] = testpath[0];
+            *rootpath = newpath;
+            return APR_SUCCESS;
+        } while(0);
+#endif
     }
 
+#ifndef _WIN32_WCE
     /* Evaluate path of 'd:[/]' */
     if (IS_FNCHAR(*testpath) && testpath[1] == ':') 
     {
@@ -320,6 +350,7 @@
         *rootpath = newpath;
         return APR_SUCCESS;
     }
+#endif
 
     /* Nothing interesting */
     return APR_ERELATIVE;
Index: file_io/win32/filestat.c
===================================================================
--- file_io/win32/filestat.c    (revision 584220)
+++ file_io/win32/filestat.c    (working copy)
@@ -15,15 +15,19 @@
  */
 
 #include "apr.h"
+#include "apr_private.h"
+#if HAVE_ACLAPI
 #include <aclapi.h>
-#include "apr_private.h"
+#endif
 #include "apr_arch_file_io.h"
 #include "apr_file_io.h"
 #include "apr_general.h"
 #include "apr_strings.h"
 #include "apr_errno.h"
 #include "apr_time.h"
+#ifndef _WIN32_WCE
 #include <sys/stat.h>
+#endif
 #include "apr_arch_atime.h"
 #include "apr_arch_misc.h"
 
@@ -50,6 +54,7 @@
     return APR_SUCCESS;
 }
 
+#ifndef _WIN32_WCE
 static apr_status_t free_localheap(void *heap) {
     LocalFree(heap);
     return APR_SUCCESS;
@@ -64,6 +69,7 @@
         worldid = NULL;
     }
 }
+#endif
 
 /* Left bit shifts from World scope to given scope */
 typedef enum prot_scope_e {
@@ -88,6 +94,7 @@
     return (prot << scope);
 }
 
+#ifndef _WIN32_WCE
 static void resolve_prot(apr_finfo_t *finfo, apr_int32_t wanted, PACL dacl)
 {
     TRUSTEE_W ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID};
@@ -138,6 +145,7 @@
         }
     }
 }
+#endif
 
 static apr_status_t resolve_ident(apr_finfo_t *finfo, const char *fname,
                                   apr_int32_t wanted, apr_pool_t *pool)
@@ -210,12 +218,15 @@
 apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, 
                         apr_int32_t wanted, int whatfile)
 {
+#ifndef _WIN32_WCE
     PSID user = NULL, grp = NULL;
     PACL dacl = NULL;
     apr_status_t rv;
+#endif
 
     if (apr_os_level < APR_WIN_NT)
         guess_protection_bits(finfo);
+#ifndef _WIN32_WCE
     else if (wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
     {
         /* On NT this request is incredibly expensive, but accurate.
@@ -288,6 +299,7 @@
         else if (wanted & APR_FINFO_PROT)
             guess_protection_bits(finfo);
     }
+#endif
 
     return ((wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS);
 }
@@ -389,6 +401,7 @@
 
     if (finfo->filetype == APR_REG)
     {
+#ifndef _WIN32_WCE
         /* Go the extra mile to be -certain- that we have a real, regular
          * file, since the attribute bits aren't a certain thing.  Even
          * though fillin should have hinted if we *must* do this, we
@@ -405,6 +418,7 @@
             /* Otherwise leave the original conclusion alone 
              */
         }
+#endif
     }
 
     finfo->pool = thefile->pool;
@@ -579,6 +593,7 @@
         if (fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) &FileInfo, 
                             0, wanted))
         {
+#ifndef _WIN32_WCE
             /* Go the extra mile to assure we have a file.  WinNT/2000 seems
              * to reliably translate char devices to the path '\\.\device'
              * so go ask for the full path.
@@ -634,6 +649,9 @@
             else {
                 finfo->valid &= ~APR_FINFO_TYPE;
             }
+#else
+            finfo->valid &= ~APR_FINFO_TYPE;
+#endif
         }
         finfo->pool = pool;
     }
@@ -646,7 +664,7 @@
     if (wanted &= ~finfo->valid) {
         /* Caller wants more than APR_FINFO_MIN | APR_FINFO_NAME */
 #if APR_HAS_UNICODE_FS
-        if (apr_os_level >= APR_WIN_NT)
+        if (apr_os_level > APR_WIN_UNICODE)
             return more_finfo(finfo, wfname, wanted, MORE_OF_WFSPEC);
 #endif
         return more_finfo(finfo, fname, wanted, MORE_OF_FSPEC);
Index: file_io/win32/filesys.c
===================================================================
--- file_io/win32/filesys.c     (revision 584220)
+++ file_io/win32/filesys.c     (working copy)
@@ -66,6 +66,7 @@
 apr_status_t filepath_root_test(char *path, apr_pool_t *p)
 {
     apr_status_t rv;
+#ifndef _WIN32_WCE
 #if APR_HAS_UNICODE_FS
     if (apr_os_level >= APR_WIN_NT)
     {
@@ -81,6 +82,19 @@
 
     if (rv == DRIVE_UNKNOWN || rv == DRIVE_NO_ROOT_DIR)
         return APR_EBADPATH;
+#else
+    apr_wchar_t wpath[APR_PATH_MAX];
+    if (rv = utf8_to_unicode_path(wpath, sizeof(wpath)
+        / sizeof(apr_wchar_t), path))
+        return rv;
+    if (!CeGetCanonicalPathNameW(wpath, wpath, sizeof(wpath) / 
sizeof(apr_wchar_t), 0))
+        return apr_get_os_error();
+    /* CE doesn't have "drives"; instead, it uses unix-style paths with a 
root. Check
+     * for the root at the beginning of a canonical path.
+     */
+    if (wpath[0] != L'\\' && wpath[0] != L'/')
+        return APR_EBADPATH;
+#endif
     return APR_SUCCESS;
 }
 
@@ -92,10 +106,11 @@
 #if APR_HAS_UNICODE_FS
     IF_WIN_OS_IS_UNICODE
     {
+        apr_wchar_t wpath[APR_PATH_MAX];
+        apr_status_t rv;
+#ifndef _WIN32_WCE
         apr_wchar_t *ignored;
         apr_wchar_t wdrive[8];
-        apr_wchar_t wpath[APR_PATH_MAX];
-        apr_status_t rv;
         /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:" 
          * as if that is useful for anything.
          */
@@ -103,6 +118,13 @@
         wdrive[0] = (apr_wchar_t)(unsigned char)drive;
         if (!GetFullPathNameW(wdrive, sizeof(wpath) / sizeof(apr_wchar_t), 
wpath, &ignored))
             return apr_get_os_error();
+#else
+        apr_wchar_t wpath2[APR_PATH_MAX];
+        if ((rv = utf8_to_unicode_path(wpath2, sizeof(wpath2) / 
sizeof(apr_wchar_t), *rootpath)))
+            return rv;
+        if (!CeGetCanonicalPathNameW(wpath2, wpath, sizeof(wpath2) / 
sizeof(apr_wchar_t), 0))
+            return apr_get_os_error();
+#endif
         if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath)))
             return rv;
     }
@@ -136,7 +158,9 @@
 #if APR_HAS_UNICODE_FS
     IF_WIN_OS_IS_UNICODE
     {
+#ifndef _WIN32_WCE
         apr_wchar_t *ignored;
+#endif
         apr_wchar_t wpath[APR_PATH_MAX];
         apr_status_t rv;
         apr_wchar_t wroot[APR_PATH_MAX];
@@ -146,8 +170,13 @@
         if (rv = utf8_to_unicode_path(wroot, sizeof(wroot) 
                                            / sizeof(apr_wchar_t), root))
             return rv;
+#ifndef _WIN32_WCE
         if (!GetFullPathNameW(wroot, sizeof(wpath) / sizeof(apr_wchar_t), 
wpath, &ignored))
             return apr_get_os_error();
+#else
+        if (!CeGetCanonicalPathNameW(wroot, wpath, sizeof(wpath) / 
sizeof(apr_wchar_t), 0))
+            return apr_get_os_error();
+#endif
 
         /* Borrow wroot as a char buffer (twice as big as necessary) 
          */
@@ -173,6 +202,9 @@
 APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags,
                                            apr_pool_t *p)
 {
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
     char path[APR_PATH_MAX];
 #if APR_HAS_UNICODE_FS
     IF_WIN_OS_IS_UNICODE
@@ -200,12 +232,16 @@
     }
     *rootpath = apr_pstrdup(p, path);
     return APR_SUCCESS;
+#endif
 }
 
 
 APR_DECLARE(apr_status_t) apr_filepath_set(const char *rootpath,
                                            apr_pool_t *p)
 {
+#ifdef _WIN32_WCE
+    return APR_ENOTIMPL;
+#else
 #if APR_HAS_UNICODE_FS
     IF_WIN_OS_IS_UNICODE
     {
@@ -226,4 +262,5 @@
     }
 #endif
     return APR_SUCCESS;
+#endif
 }
Index: file_io/win32/flock.c
===================================================================
--- file_io/win32/flock.c       (revision 584220)
+++ file_io/win32/flock.c       (working copy)
@@ -18,23 +18,20 @@
 
 APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
 {
-#ifdef _WIN32_WCE
-    /* The File locking is unsuported on WCE */
-    return APR_ENOTIMPL;
-#else
     const DWORD len = 0xffffffff;
     DWORD flags; 
 
     flags = ((type & APR_FLOCK_NONBLOCK) ? LOCKFILE_FAIL_IMMEDIATELY : 0)
           + (((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED) 
                                        ? 0 : LOCKFILE_EXCLUSIVE_LOCK);
-    if (apr_os_level >= APR_WIN_NT) {
+    if (apr_os_level >= APR_WIN_CE_5) {
         /* Syntax is correct, len is passed for LengthLow and LengthHigh*/
         OVERLAPPED offset;
         memset (&offset, 0, sizeof(offset));
         if (!LockFileEx(thefile->filehand, flags, 0, len, len, &offset))
             return apr_get_os_error();
     }
+#ifndef _WIN32_WCE
     else {
         /* On Win9x, LockFile() never blocks.  Hack in a crufty poll.
          *
@@ -57,30 +54,36 @@
             return APR_FROM_OS_ERROR(err);
         }
     }
+#else
+    else {
+        return APR_ENOTIMPL;
+    }
+#endif
 
     return APR_SUCCESS;
-#endif /* !defined(_WIN32_WCE) */
 }
 
 APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
 {
-#ifdef _WIN32_WCE
-    return APR_ENOTIMPL;
-#else
     DWORD len = 0xffffffff;
 
-    if (apr_os_level >= APR_WIN_NT) {
+    if (apr_os_level >= APR_WIN_CE_5) {
         /* Syntax is correct, len is passed for LengthLow and LengthHigh*/
         OVERLAPPED offset;
         memset (&offset, 0, sizeof(offset));
         if (!UnlockFileEx(thefile->filehand, 0, len, len, &offset))
             return apr_get_os_error();
     }
+#ifndef _WIN32_WCE
     else {
         if (!UnlockFile(thefile->filehand, 0, 0, len, 0))
             return apr_get_os_error();
     }
+#else
+    else {
+        return APR_ENOTIMPL;
+    }
+#endif
 
     return APR_SUCCESS;
-#endif /* !defined(_WIN32_WCE) */
 }
Index: include/apr_general.h
===================================================================
--- include/apr_general.h       (revision 584220)
+++ include/apr_general.h       (working copy)
@@ -115,13 +115,21 @@
  * have it
  */
 #if (!APR_HAVE_STRCASECMP) && (APR_HAVE_STRICMP) 
+#ifdef _WIN32_WCE
+#define strcasecmp(s1, s2) _stricmp(s1, s2)
+#else
 #define strcasecmp(s1, s2) stricmp(s1, s2)
+#endif
 #elif (!APR_HAVE_STRCASECMP)
 int strcasecmp(const char *a, const char *b);
 #endif
 
 #if (!APR_HAVE_STRNCASECMP) && (APR_HAVE_STRNICMP)
+#ifdef _WIN32_WCE
+#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
+#else
 #define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
+#endif
 #elif (!APR_HAVE_STRNCASECMP)
 int strncasecmp(const char *a, const char *b, size_t n);
 #endif
Index: include/arch/win32/apr_arch_networkio.h
===================================================================
--- include/arch/win32/apr_arch_networkio.h     (revision 584220)
+++ include/arch/win32/apr_arch_networkio.h     (working copy)
@@ -50,13 +50,17 @@
      */
     OVERLAPPED         *overlapped;
 #endif
+#if _WIN32_WCE >= 0x400
+    /* Needed in CE to implement blocking sockets that timeout. */
+    WSAOVERLAPPED      *wsaoverlapped;
+#endif
     sock_userdata_t    *userdata;
 
     /* if there is a timeout set, then this pollset is used */
     apr_pollset_t *pollset;
 };
 
-#ifdef _WIN32_WCE
+#if _WIN32_WCE < 0x500
 #ifndef WSABUF
 typedef struct _WSABUF {
     u_long      len;     /* the length of the buffer */
Index: include/arch/win32/apr_private.h
===================================================================
--- include/arch/win32/apr_private.h    (revision 584220)
+++ include/arch/win32/apr_private.h    (working copy)
@@ -134,7 +134,9 @@
 
 #if !APR_HAVE_ERRNO_H
 APR_DECLARE_DATA int errno;
-#define ENOSPC 1
+#define ENOSPC 28
+#define EINVAL 22
+#define ERANGE 34
 #endif
 
 #if APR_HAVE_IPV6
@@ -161,6 +163,10 @@
 #endif
 #endif
 
+#ifndef BUFSIZ
+#define BUFSIZ 512
+#endif
+
 /* used to check for DWORD overflow in 64bit compiles */
 #define APR_DWORD_MAX 0xFFFFFFFFUL
 
Index: misc/win32/rand.c
===================================================================
--- misc/win32/rand.c   (revision 584220)
+++ misc/win32/rand.c   (working copy)
@@ -20,8 +20,10 @@
 #include "apr_general.h"
 #include "apr_portable.h"
 #include "apr_arch_misc.h"
+#ifdef _WIN32_WCE
+#include <objbase.h>
+#endif
 
-
 APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf,
                                                     apr_size_t length)
 {
@@ -32,7 +34,12 @@
      * and will only work for Win2K and later.
      */
     DWORD flags = CRYPT_VERIFYCONTEXT
+#ifndef _WIN32_WCE
                 | ((apr_os_level >= APR_WIN_2000) ? 0x40 : 0);
+#else
+    /* CRYPT_SILENT works on CE from the beginning of CryptAcquireContext(). */
+                | CRYPT_SILENT;
+#endif
 
     if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, flags)) {
        return apr_get_os_error();
@@ -61,7 +68,11 @@
      * Note that Win2000, XP and later no longer suffer from this problem,
      * a scrambling fix is only needed for (apr_os_level < APR_WIN_2000)
      */
+#ifndef _WIN32_WCE
     if (FAILED(UuidCreate((UUID *)uuid_data))) {
+#else
+    if (FAILED(CoCreateGuid((UUID *)uuid_data))) {
+#endif
         return APR_EGENERAL;
     }
     return APR_SUCCESS;
Index: mmap/win32/mmap.c
===================================================================
--- mmap/win32/mmap.c   (revision 584220)
+++ mmap/win32/mmap.c   (working copy)
@@ -75,6 +75,12 @@
     DWORD mvaccess = 0;
     DWORD offlo;
     DWORD offhi;
+#ifdef _WIN32_WCE
+    apr_wchar_t wfname[APR_PATH_MAX];
+    apr_status_t rv;
+    DWORD oflags = 0;
+    HANDLE fhandle;
+#endif
 
     if (size == 0)
         return APR_EINVAL;
@@ -104,13 +110,40 @@
     (*new)->pstart = (offset / memblock) * memblock;
     (*new)->poffset = offset - (*new)->pstart;
     (*new)->psize = (apr_size_t)((*new)->poffset) + size;
+#ifndef _WIN32_WCE
     /* The size of the CreateFileMapping object is the current size
      * of the size of the mmap object (e.g. file size), not the size 
      * of the mapped region!
      */
-
     (*new)->mhandle = CreateFileMapping(file->filehand, NULL, fmaccess,
                                         0, 0, NULL);
+#else
+    rv = utf8_to_unicode_path(wfname, APR_PATH_MAX, file->fname);
+    if (rv != APR_SUCCESS) {
+        *new = NULL;
+        return rv;
+    }
+    /* Need to use CreateFileForMapping() on CE to ensure MMap files work.
+     * CE ignores the sharemode parameter. Instead, it grants the same
+     * share mode as the desired access (open) flags.
+     */
+    if (flag & APR_MMAP_WRITE)
+        oflags = GENERIC_READ | GENERIC_WRITE;
+    else if (flag & APR_MMAP_READ)
+        oflags |= GENERIC_READ;
+    fhandle = CreateFileForMappingW(wfname, oflags, 0, NULL,
+                                    OPEN_EXISTING, 0, NULL);
+    if (!fhandle || fhandle == INVALID_HANDLE_VALUE) {
+        *new = NULL;
+        return apr_get_os_error();
+    }
+    /* The size of the CreateFileMapping object is the current size
+     * of the size of the mmap object (e.g. file size), not the size 
+     * of the mapped region!
+     */
+    (*new)->mhandle = CreateFileMapping(fhandle, NULL, fmaccess,
+                                        0, 0, NULL);
+#endif
     if (!(*new)->mhandle || (*new)->mhandle == INVALID_HANDLE_VALUE)
     {
         *new = NULL;
Index: network_io/win32/sendrecv.c
===================================================================
--- network_io/win32/sendrecv.c (revision 584220)
+++ network_io/win32/sendrecv.c (working copy)
@@ -41,22 +41,54 @@
 {
     apr_ssize_t rv;
     WSABUF wsaData;
-    int lasterror;
     DWORD dwBytes = 0;
+#if _WIN32_WCE >= 0x400
+    apr_status_t wsarv;
+#endif
 
     wsaData.len = (u_long)*len;
     wsaData.buf = (char*) buf;
 
 #ifndef _WIN32_WCE
     rv = WSASend(sock->socketdes, &wsaData, 1, &dwBytes, 0, NULL, NULL);
+#elif _WIN32_WCE >= 0x400
+    rv = WSASend(sock->socketdes, &wsaData, 1, &dwBytes, 0,
+                 sock->wsaoverlapped, NULL);
+    if (rv == SOCKET_ERROR) {
+        wsarv = apr_get_netos_error();
+        if (wsarv == APR_FROM_OS_ERROR(WSA_IO_PENDING)) {
+            rv = WSAWaitForMultipleEvents(1, &sock->wsaoverlapped->hEvent,
+                                          FALSE, sock->timeout_ms >= 0
+                                                 ? sock->timeout_ms
+                                                 : WSA_INFINITE, FALSE);
+            if (rv == WSA_WAIT_EVENT_0) {
+                if (WSAResetEvent(sock->wsaoverlapped->hEvent)) {
+                    DWORD flags = 0;
+                    if (!WSAGetOverlappedResult(sock->socketdes,
+                        sock->wsaoverlapped, &dwBytes, FALSE, &flags)) {
+                        rv = SOCKET_ERROR;
+                    }
+                }
+                else {
+                    rv = SOCKET_ERROR;
+                }
+            }
+            else {
+                apr_set_netos_error(rv);
+                rv = SOCKET_ERROR;
+            }
+        }
+        else {
+            apr_set_netos_error(wsarv);
+        }
+    }
 #else
     rv = send(sock->socketdes, wsaData.buf, wsaData.len, 0);
     dwBytes = rv;
 #endif
     if (rv == SOCKET_ERROR) {
-        lasterror = apr_get_netos_error();
         *len = 0;
-        return lasterror;
+        return apr_get_netos_error();
     }
 
     *len = dwBytes;
@@ -70,23 +102,55 @@
 {
     apr_ssize_t rv;
     WSABUF wsaData;
-    int lasterror;
     DWORD dwBytes = 0;
     DWORD flags = 0;
+#if _WIN32_WCE >= 0x400
+    apr_status_t wsarv;
+#endif
 
     wsaData.len = (u_long)*len;
     wsaData.buf = (char*) buf;
 
 #ifndef _WIN32_WCE
     rv = WSARecv(sock->socketdes, &wsaData, 1, &dwBytes, &flags, NULL, NULL);
+#elif _WIN32_WCE >= 0x400
+    rv = WSARecv(sock->socketdes, &wsaData, 1, &dwBytes, &flags,
+                 sock->wsaoverlapped, NULL);
+    if (rv == SOCKET_ERROR) {
+        wsarv = apr_get_netos_error();
+        if (wsarv == APR_FROM_OS_ERROR(WSA_IO_PENDING)) {
+            rv = WSAWaitForMultipleEvents(1, &sock->wsaoverlapped->hEvent,
+                                          FALSE, sock->timeout_ms >= 0
+                                                 ? sock->timeout_ms
+                                                 : WSA_INFINITE, FALSE);
+            if (rv == WSA_WAIT_EVENT_0) {
+                if (WSAResetEvent(sock->wsaoverlapped->hEvent)) {
+                    flags = 0;
+                    if (!WSAGetOverlappedResult(sock->socketdes,
+                        sock->wsaoverlapped, &dwBytes, FALSE, &flags)) {
+                        rv = SOCKET_ERROR;
+                    }
+                }
+                else {
+                    rv = SOCKET_ERROR;
+                }
+            }
+            else {
+                apr_set_netos_error(rv);
+                rv = SOCKET_ERROR;
+            }
+        }
+        else {
+            apr_set_netos_error(wsarv);
+        }
+    }
 #else
     rv = recv(sock->socketdes, wsaData.buf, wsaData.len, 0);
     dwBytes = rv;
 #endif
     if (rv == SOCKET_ERROR) {
-        lasterror = apr_get_netos_error();
         *len = 0;
-        return lasterror;
+        return apr_get_netos_error();
     }
 
     *len = dwBytes;
@@ -145,6 +209,34 @@
     if (rv == SOCKET_ERROR) {
         rc = apr_get_netos_error();
     }
+#elif _WIN32_WCE >= 0x400
+    rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0,
+                 sock->wsaoverlapped, NULL);
+    rc = rv;
+    if (rv == SOCKET_ERROR) {
+        rc = apr_get_netos_error();
+        if (rc == APR_FROM_OS_ERROR(WSA_IO_PENDING)) {
+            rv = WSAWaitForMultipleEvents(1, &sock->wsaoverlapped->hEvent,
+                                          FALSE, sock->timeout_ms >= 0
+                                                 ? sock->timeout_ms
+                                                 : WSA_INFINITE, FALSE);
+            if (rv == WSA_WAIT_EVENT_0) {
+                if (WSAResetEvent(sock->wsaoverlapped->hEvent)) {
+                    DWORD flags = 0;
+                    if (!WSAGetOverlappedResult(sock->socketdes,
+                        sock->wsaoverlapped, &dwBytes, FALSE, &flags)) {
+                        rc = apr_get_netos_error();
+                    }
+                }
+                else {
+                    rc = apr_get_netos_error();
+                }
+            }
+            else {
+                rc = rv;
+            }
+        }
+    }
 #else
     for (i = 0; i < nvec; i++) {
         rv = send(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, 0);
@@ -169,10 +261,52 @@
                                             apr_size_t *len)
 {
     apr_ssize_t rv;
+#if _WIN32_WCE >= 0x400
+    apr_status_t wsarv;
+    WSABUF wsaData;
+    DWORD dwBytes = 0;
 
+    wsaData.len = (u_long)*len;
+    wsaData.buf = (char*) buf;
+
+    rv = WSASendTo(sock->socketdes, &wsaData, 1, &dwBytes, flags,
+                   (const struct sockaddr*)&where->sa, where->salen,
+                   sock->wsaoverlapped, NULL);
+    if (rv == SOCKET_ERROR) {
+        wsarv = apr_get_netos_error();
+        if (wsarv == APR_FROM_OS_ERROR(WSA_IO_PENDING)) {
+            rv = WSAWaitForMultipleEvents(1, &sock->wsaoverlapped->hEvent,
+                                          FALSE, sock->timeout_ms >= 0
+                                                 ? sock->timeout_ms
+                                                 : WSA_INFINITE, FALSE);
+            if (rv == WSA_WAIT_EVENT_0) {
+                if (WSAResetEvent(sock->wsaoverlapped->hEvent)) {
+                    if (WSAGetOverlappedResult(sock->socketdes,
+                        sock->wsaoverlapped, &dwBytes, FALSE, &flags)) {
+                        rv = dwBytes;
+                    }
+                    else {
+                        rv = SOCKET_ERROR;
+                    }
+                }
+                else {
+                    rv = SOCKET_ERROR;
+                }
+            }
+            else {
+                apr_set_netos_error(rv);
+                rv = SOCKET_ERROR;
+            }
+        }
+        else {
+            apr_set_netos_error(wsarv);
+        }
+    }
+#else
     rv = sendto(sock->socketdes, buf, (int)*len, flags, 
                 (const struct sockaddr*)&where->sa, 
                 where->salen);
+#endif
     if (rv == SOCKET_ERROR) {
         *len = 0;
         return apr_get_netos_error();
@@ -189,9 +323,54 @@
                                               char *buf, apr_size_t *len)
 {
     apr_ssize_t rv;
+#if _WIN32_WCE >= 0x400
+    apr_status_t wsarv;
+    WSABUF wsaData;
+    DWORD dwBytes = 0;
 
+    wsaData.len = (u_long)*len;
+    wsaData.buf = (char*) buf;
+
+    rv = WSARecvFrom(sock->socketdes, &wsaData, 1, &dwBytes, &flags,
+                     (struct sockaddr*)&from->sa, &from->salen,
+                     sock->wsaoverlapped, NULL);
+    if (rv == SOCKET_ERROR) {
+        wsarv = apr_get_netos_error();
+        if (wsarv == APR_FROM_OS_ERROR(WSA_IO_PENDING)) {
+            rv = WSAWaitForMultipleEvents(1, &sock->wsaoverlapped->hEvent,
+                                          FALSE, sock->timeout_ms >= 0
+                                                 ? sock->timeout_ms
+                                                 : WSA_INFINITE, FALSE);
+            if (rv == WSA_WAIT_EVENT_0) {
+                if (WSAResetEvent(sock->wsaoverlapped->hEvent)) {
+                    if (WSAGetOverlappedResult(sock->socketdes,
+                        sock->wsaoverlapped, &dwBytes, FALSE, &flags)) {
+                        rv = dwBytes;
+                    }
+                    else {
+                        rv = SOCKET_ERROR;
+                    }
+                }
+                else {
+                    rv = SOCKET_ERROR;
+                }
+            }
+            else {
+                apr_set_netos_error(rv);
+                rv = SOCKET_ERROR;
+            }
+        }
+        else {
+            apr_set_netos_error(wsarv);
+        }
+    }
+    else {
+        rv = dwBytes;
+    }
+#else
     rv = recvfrom(sock->socketdes, buf, (int)*len, flags, 
                   (struct sockaddr*)&from->sa, &from->salen);
+#endif
     if (rv == SOCKET_ERROR) {
         (*len) = 0;
         return apr_get_netos_error();
Index: network_io/win32/sockopt.c
===================================================================
--- network_io/win32/sockopt.c  (revision 584220)
+++ network_io/win32/sockopt.c  (working copy)
@@ -24,7 +24,12 @@
 {
     u_long zero = 0;
 
+#if _WIN32_WCE >= 0x400
+    if (WSAIoctl(sd, FIONBIO, &zero, sizeof(zero),
+                 NULL, 0, NULL, NULL, NULL) == SOCKET_ERROR) {
+#else
     if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
+#endif
         return apr_get_netos_error();
     }
     return APR_SUCCESS;
@@ -34,7 +39,12 @@
 {
     u_long one = 1;
 
+#if _WIN32_WCE >= 0x400
+    if (WSAIoctl(sd, FIONBIO, &one, sizeof(one),
+                 NULL, 0, NULL, NULL, NULL) == SOCKET_ERROR) {
+#else
     if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
+#endif
         return apr_get_netos_error();
     }
     return APR_SUCCESS;
@@ -63,12 +73,14 @@
         {
             /* Win32 timeouts are in msec, represented as int */
             sock->timeout_ms = (int)apr_time_as_msec(t);
+#ifndef _WIN32_WCE
             setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
                        (char *) &sock->timeout_ms, 
                        sizeof(sock->timeout_ms));
             setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
                        (char *) &sock->timeout_ms, 
                        sizeof(sock->timeout_ms));
+#endif
         }
     }
     else if (t < 0) {
@@ -76,10 +88,12 @@
         /* Set the socket to blocking with infinite timeouts */
         if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
             return stat;
+#ifndef _WIN32_WCE
         setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
                    (char *) &zero, sizeof(zero));
         setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
                    (char *) &zero, sizeof(zero));
+#endif
     }
     sock->timeout = t;
     return APR_SUCCESS;
Index: shmem/win32/shm.c
===================================================================
--- shmem/win32/shm.c   (revision 584220)
+++ shmem/win32/shm.c   (working copy)
@@ -86,12 +86,11 @@
 
     if (!file) {
         /* Do Anonymous, which must be passed as a duplicated handle */
-#ifndef _WIN32_WCE
         hFile = INVALID_HANDLE_VALUE;
-#endif
         mapkey = NULL;
     }
     else {
+#ifndef _WIN32_WCE
         /* Do file backed, which is not an inherited handle 
          * While we could open APR_EXCL, it doesn't seem that Unix
          * ever did.  Ignore that error here, but fail later when
@@ -105,7 +104,24 @@
             return rv;
         }
         rv = apr_file_trunc(f, size);
+#else
+        apr_wchar_t wfname[APR_PATH_MAX];
 
+        rv = utf8_to_unicode_path(wfname, APR_PATH_MAX, file);
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+        /* Need to use CreateFileForMapping() on CE to ensure MMap files
+         * work. CE ignores the sharemode parameter. Instead, it grants
+         * the same share mode as the desired access (open) flags.
+         */
+        hFile = CreateFileForMappingW(wfname, GENERIC_READ
+            | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
+        if (!hFile || hFile == INVALID_HANDLE_VALUE) {
+            return apr_get_os_error();
+        }
+#endif
+
         /* res_name_from_filename turns file into a pseudo-name
          * without slashes or backslashes, and prepends the \global
          * prefix on Win2K and later
@@ -129,9 +145,11 @@
 #endif
     err = apr_get_os_error();
 
+#ifndef _WIN32_WCE
     if (file) {
         apr_file_close(f);
     }
+#endif
 
     if (hMap && APR_STATUS_IS_EEXIST(err)) {
         CloseHandle(hMap);
Index: strings/apr_strings.c
===================================================================
--- strings/apr_strings.c       (revision 584220)
+++ strings/apr_strings.c       (working copy)
@@ -239,7 +239,13 @@
 {
     errno = 0;
     *offset = APR_OFF_T_STRFN(nptr, endptr, base);
+#ifndef _WIN32_WCE
     return APR_FROM_OS_ERROR(errno);
+#else
+    if (*offset == LONG_MAX || *offset == LONG_MIN)
+        return APR_FROM_OS_ERROR(ERROR_ARITHMETIC_OVERFLOW);
+    return APR_SUCCESS;
+#endif
 }
 
 APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int 
base)
@@ -464,3 +470,4 @@
     } while (1);
 }
 
+
Index: threadproc/win32/thread.c
===================================================================
--- threadproc/win32/thread.c   (revision 584220)
+++ threadproc/win32/thread.c   (working copy)
@@ -117,7 +117,9 @@
    if ((handle = CreateThread(NULL,
                         attr && attr->stacksize > 0 ? attr->stacksize : 0,
                         (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker,
-                        (*new), 0, &temp)) == 0) {
+                        (*new), attr && attr->stacksize > 0
+                        ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0,
+                        &temp)) == 0) {
         return apr_get_os_error();
     }
 #endif
Index: time/win32/time.c
===================================================================
--- time/win32/time.c   (revision 584220)
+++ time/win32/time.c   (working copy)
@@ -91,9 +91,7 @@
 #ifndef _WIN32_WCE
     GetSystemTimeAsFileTime(&time);
 #else
-    SYSTEMTIME st;
-    GetSystemTime(&st);
-    SystemTimeToFileTime(&st, &time);
+    GetCurrentFT(&time);
 #endif
     FileTimeToAprTime(&aprtime, &time);
     return aprtime; 

Reply via email to