Browse Source

Port Tor to work on Windows CE

Most of the changes here are switches to use APIs available on Windows
CE.  The most pervasive change is that Windows CE only provides the
wide-character ("FooW") variants of most of the windows function, and
doesn't support the older ASCII verions at all.

This patch will require use of the wcecompat library to get working
versions of the posix-style fd-based file IO functions.

[commit message by nickm]
valerino 15 years ago
parent
commit
8d31141ccb
7 changed files with 135 additions and 37 deletions
  1. 33 13
      src/common/compat.c
  2. 2 2
      src/common/compat.h
  3. 13 8
      src/common/util.c
  4. 9 2
      src/or/config.c
  5. 20 12
      src/or/eventdns.c
  6. 56 0
      src/or/main.c
  7. 2 0
      src/or/or.h

+ 33 - 13
src/common/compat.c

@@ -22,8 +22,10 @@
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
 #include <process.h>
 #include <process.h>
 #include <windows.h>
 #include <windows.h>
+#if !defined (WINCE)
 #include <sys/locking.h>
 #include <sys/locking.h>
 #endif
 #endif
+#endif
 
 
 #ifdef HAVE_UNAME
 #ifdef HAVE_UNAME
 #include <sys/utsname.h>
 #include <sys/utsname.h>
@@ -169,12 +171,13 @@ tor_munmap_file(tor_mmap_t *handle)
 tor_mmap_t *
 tor_mmap_t *
 tor_mmap_file(const char *filename)
 tor_mmap_file(const char *filename)
 {
 {
+  WCHAR wfilename[MAX_PATH]= {0};
   tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
   tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
   int empty = 0;
   int empty = 0;
   res->file_handle = INVALID_HANDLE_VALUE;
   res->file_handle = INVALID_HANDLE_VALUE;
   res->mmap_handle = NULL;
   res->mmap_handle = NULL;
-
-  res->file_handle = CreateFile(filename,
+  mbstowcs(wfilename,filename,MAX_PATH);
+  res->file_handle = CreateFileW(wfilename,
                                 GENERIC_READ, FILE_SHARE_READ,
                                 GENERIC_READ, FILE_SHARE_READ,
                                 NULL,
                                 NULL,
                                 OPEN_EXISTING,
                                 OPEN_EXISTING,
@@ -1697,10 +1700,15 @@ get_uname(void)
 #endif
 #endif
       {
       {
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
-        OSVERSIONINFOEX info;
+#if defined (WINCE)
+        OSVERSIONINFO info;
+#else
+        OSVERSIONINFOEXW info;
+#endif
         int i;
         int i;
         const char *plat = NULL;
         const char *plat = NULL;
         const char *extra = NULL;
         const char *extra = NULL;
+        char acsd[MAX_PATH] = {0};
         static struct {
         static struct {
           unsigned major; unsigned minor; const char *version;
           unsigned major; unsigned minor; const char *version;
         } win_version_table[] = {
         } win_version_table[] = {
@@ -1718,20 +1726,21 @@ get_uname(void)
         };
         };
         memset(&info, 0, sizeof(info));
         memset(&info, 0, sizeof(info));
         info.dwOSVersionInfoSize = sizeof(info);
         info.dwOSVersionInfoSize = sizeof(info);
-        if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
+        if (! GetVersionExW((LPOSVERSIONINFO)&info)) {
           strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
           strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
                   " doesn't work.", sizeof(uname_result));
                   " doesn't work.", sizeof(uname_result));
           uname_result_is_set = 1;
           uname_result_is_set = 1;
           return uname_result;
           return uname_result;
         }
         }
+        wcstombs(acsd, info.szCSDVersion, MAX_PATH);
         if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
         if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
           if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
           if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
             plat = "Windows NT 4.0";
             plat = "Windows NT 4.0";
           else
           else
             plat = "Windows 95";
             plat = "Windows 95";
-          if (info.szCSDVersion[1] == 'B')
+          if (acsd[1] == 'B')
             extra = "OSR2 (B)";
             extra = "OSR2 (B)";
-          else if (info.szCSDVersion[1] == 'C')
+          else if (acsd[1] == 'C')
             extra = "OSR2 (C)";
             extra = "OSR2 (C)";
         } else {
         } else {
           for (i=0; win_version_table[i].major>0; ++i) {
           for (i=0; win_version_table[i].major>0; ++i) {
@@ -1743,14 +1752,14 @@ get_uname(void)
           }
           }
         }
         }
         if (plat && !strcmp(plat, "Windows 98")) {
         if (plat && !strcmp(plat, "Windows 98")) {
-          if (info.szCSDVersion[1] == 'A')
+          if (acsd[1] == 'A')
             extra = "SE (A)";
             extra = "SE (A)";
-          else if (info.szCSDVersion[1] == 'B')
+          else if (acsd[1] == 'B')
             extra = "SE (B)";
             extra = "SE (B)";
         }
         }
         if (plat) {
         if (plat) {
           if (!extra)
           if (!extra)
-            extra = info.szCSDVersion;
+            extra = acsd;
           tor_snprintf(uname_result, sizeof(uname_result), "%s %s",
           tor_snprintf(uname_result, sizeof(uname_result), "%s %s",
                        plat, extra);
                        plat, extra);
         } else {
         } else {
@@ -1759,13 +1768,14 @@ get_uname(void)
             tor_snprintf(uname_result, sizeof(uname_result),
             tor_snprintf(uname_result, sizeof(uname_result),
                       "Very recent version of Windows [major=%d,minor=%d] %s",
                       "Very recent version of Windows [major=%d,minor=%d] %s",
                       (int)info.dwMajorVersion,(int)info.dwMinorVersion,
                       (int)info.dwMajorVersion,(int)info.dwMinorVersion,
-                      info.szCSDVersion);
+                      acsd);
           else
           else
             tor_snprintf(uname_result, sizeof(uname_result),
             tor_snprintf(uname_result, sizeof(uname_result),
                       "Unrecognized version of Windows [major=%d,minor=%d] %s",
                       "Unrecognized version of Windows [major=%d,minor=%d] %s",
                       (int)info.dwMajorVersion,(int)info.dwMinorVersion,
                       (int)info.dwMajorVersion,(int)info.dwMinorVersion,
-                      info.szCSDVersion);
+                      acsd);
         }
         }
+#if !defined (WINCE)
 #ifdef VER_SUITE_BACKOFFICE
 #ifdef VER_SUITE_BACKOFFICE
         if (info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
         if (info.wProductType == VER_NT_DOMAIN_CONTROLLER) {
           strlcat(uname_result, " [domain controller]", sizeof(uname_result));
           strlcat(uname_result, " [domain controller]", sizeof(uname_result));
@@ -1775,6 +1785,7 @@ get_uname(void)
           strlcat(uname_result, " [workstation]", sizeof(uname_result));
           strlcat(uname_result, " [workstation]", sizeof(uname_result));
         }
         }
 #endif
 #endif
+#endif
 #else
 #else
         strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
         strlcpy(uname_result, "Unknown platform", sizeof(uname_result));
 #endif
 #endif
@@ -1902,8 +1913,15 @@ tor_gettimeofday(struct timeval *timeval)
     uint64_t ft_64;
     uint64_t ft_64;
     FILETIME ft_ft;
     FILETIME ft_ft;
   } ft;
   } ft;
+#if defined (WINCE)
+  /* wince do not have GetSystemTimeAsFileTime */
+  SYSTEMTIME stime;
+  GetSystemTime(&stime);
+  SystemTimeToFileTime(&stime,&ft.ft_ft);
+#else
   /* number of 100-nsec units since Jan 1, 1601 */
   /* number of 100-nsec units since Jan 1, 1601 */
   GetSystemTimeAsFileTime(&ft.ft_ft);
   GetSystemTimeAsFileTime(&ft.ft_ft);
+#endif
   if (ft.ft_64 < EPOCH_BIAS) {
   if (ft.ft_64 < EPOCH_BIAS) {
     log_err(LD_GENERAL,"System time is before 1970; failing.");
     log_err(LD_GENERAL,"System time is before 1970; failing.");
     exit(1);
     exit(1);
@@ -2515,10 +2533,11 @@ char *
 format_win32_error(DWORD err)
 format_win32_error(DWORD err)
 {
 {
   LPVOID str = NULL;
   LPVOID str = NULL;
+  char abuf[1024] = {0};
   char *result;
   char *result;
 
 
   /* Somebody once decided that this interface was better than strerror(). */
   /* Somebody once decided that this interface was better than strerror(). */
-  FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL, err,
                  NULL, err,
@@ -2527,7 +2546,8 @@ format_win32_error(DWORD err)
                  0, NULL);
                  0, NULL);
 
 
   if (str) {
   if (str) {
-    result = tor_strdup((char*)str);
+    wcstombs(abuf,str,1024);
+    result = tor_strdup((char*)abuf);
     LocalFree(str); /* LocalFree != free() */
     LocalFree(str); /* LocalFree != free() */
   } else {
   } else {
     result = tor_strdup("<unformattable error>");
     result = tor_strdup("<unformattable error>");

+ 2 - 2
src/common/compat.h

@@ -177,8 +177,8 @@ extern INLINE double U64_TO_DBL(uint64_t x) {
 /* ===== String compatibility */
 /* ===== String compatibility */
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
 /* Windows names string functions differently from most other platforms. */
 /* Windows names string functions differently from most other platforms. */
-#define strncasecmp strnicmp
-#define strcasecmp stricmp
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
 #endif
 #endif
 #ifndef HAVE_STRLCAT
 #ifndef HAVE_STRLCAT
 size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));
 size_t strlcat(char *dst, const char *src, size_t siz) ATTR_NONNULL((1,2));

+ 13 - 8
src/common/util.c

@@ -1707,7 +1707,7 @@ check_private_dir(const char *dirname, cpd_check_t check)
       return -1;
       return -1;
     } else if (check == CPD_CREATE) {
     } else if (check == CPD_CREATE) {
       log_info(LD_GENERAL, "Creating directory %s", dirname);
       log_info(LD_GENERAL, "Creating directory %s", dirname);
-#ifdef MS_WINDOWS
+#if defined (MS_WINDOWS) && !defined (WINCE)
       r = mkdir(dirname);
       r = mkdir(dirname);
 #else
 #else
       r = mkdir(dirname, 0700);
       r = mkdir(dirname, 0700);
@@ -1843,7 +1843,8 @@ start_writing_to_file(const char *fname, int open_flags, int mode,
   if (open_flags & O_BINARY)
   if (open_flags & O_BINARY)
     new_file->binary = 1;
     new_file->binary = 1;
 
 
-  if ((new_file->fd = open(open_name, open_flags, mode)) < 0) {
+  new_file->fd = open(open_name, open_flags, mode);
+  if (new_file->fd < 0) {
     log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
     log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
         open_name, fname, strerror(errno));
         open_name, fname, strerror(errno));
     goto err;
     goto err;
@@ -2526,22 +2527,26 @@ tor_listdir(const char *dirname)
   smartlist_t *result;
   smartlist_t *result;
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
   char *pattern;
   char *pattern;
+  WCHAR wpattern[MAX_PATH] = {0};
+  char name[MAX_PATH] = {0};
   HANDLE handle;
   HANDLE handle;
-  WIN32_FIND_DATA findData;
+  WIN32_FIND_DATAW findData;
   size_t pattern_len = strlen(dirname)+16;
   size_t pattern_len = strlen(dirname)+16;
   pattern = tor_malloc(pattern_len);
   pattern = tor_malloc(pattern_len);
   tor_snprintf(pattern, pattern_len, "%s\\*", dirname);
   tor_snprintf(pattern, pattern_len, "%s\\*", dirname);
-  if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(pattern, &findData))) {
+  mbstowcs(wpattern,pattern,MAX_PATH);
+  if (INVALID_HANDLE_VALUE == (handle = FindFirstFileW(wpattern, &findData))) {
     tor_free(pattern);
     tor_free(pattern);
     return NULL;
     return NULL;
   }
   }
+  wcstombs(name,findData.cFileName,MAX_PATH);
   result = smartlist_create();
   result = smartlist_create();
   while (1) {
   while (1) {
-    if (strcmp(findData.cFileName, ".") &&
-        strcmp(findData.cFileName, "..")) {
-      smartlist_add(result, tor_strdup(findData.cFileName));
+    if (strcmp(name, ".") &&
+        strcmp(name, "..")) {
+      smartlist_add(result, tor_strdup(name));
     }
     }
-    if (!FindNextFile(handle, &findData)) {
+    if (!FindNextFileW(handle, &findData)) {
       DWORD err;
       DWORD err;
       if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
       if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
         char *errstr = format_win32_error(err);
         char *errstr = format_win32_error(err);

+ 9 - 2
src/or/config.c

@@ -217,8 +217,12 @@ static config_var_t _option_vars[] = {
   V(ExitPortStatistics,          BOOL,     "0"),
   V(ExitPortStatistics,          BOOL,     "0"),
   V(ExtraInfoStatistics,         BOOL,     "0"),
   V(ExtraInfoStatistics,         BOOL,     "0"),
 
 
+#if defined (WINCE)
+  V(FallbackNetworkstatusFile,   FILENAME, "fallback-consensus"),
+#else
   V(FallbackNetworkstatusFile,   FILENAME,
   V(FallbackNetworkstatusFile,   FILENAME,
     SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"),
     SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"),
+#endif
   V(FascistFirewall,             BOOL,     "0"),
   V(FascistFirewall,             BOOL,     "0"),
   V(FirewallPorts,               CSV,      ""),
   V(FirewallPorts,               CSV,      ""),
   V(FastFirstHopPK,              BOOL,     "1"),
   V(FastFirstHopPK,              BOOL,     "1"),
@@ -3697,6 +3701,7 @@ get_windows_conf_root(void)
 {
 {
   static int is_set = 0;
   static int is_set = 0;
   static char path[MAX_PATH+1];
   static char path[MAX_PATH+1];
+  WCHAR wpath[MAX_PATH] = {0};
 
 
   LPITEMIDLIST idl;
   LPITEMIDLIST idl;
   IMalloc *m;
   IMalloc *m;
@@ -3714,7 +3719,7 @@ get_windows_conf_root(void)
 #define APPDATA_PATH CSIDL_APPDATA
 #define APPDATA_PATH CSIDL_APPDATA
 #endif
 #endif
   if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) {
   if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) {
-    GetCurrentDirectory(MAX_PATH, path);
+    getcwd(path,MAX_PATH);
     is_set = 1;
     is_set = 1;
     log_warn(LD_CONFIG,
     log_warn(LD_CONFIG,
              "I couldn't find your application data folder: are you "
              "I couldn't find your application data folder: are you "
@@ -3723,7 +3728,9 @@ get_windows_conf_root(void)
     return path;
     return path;
   }
   }
   /* Convert the path from an "ID List" (whatever that is!) to a path. */
   /* Convert the path from an "ID List" (whatever that is!) to a path. */
-  result = SHGetPathFromIDList(idl, path);
+  result = SHGetPathFromIDListW(idl, wpath);
+  wcstombs(path,wpath,MAX_PATH);
+
   /* Now we need to free the */
   /* Now we need to free the */
   SHGetMalloc(&m);
   SHGetMalloc(&m);
   if (m) {
   if (m) {

+ 20 - 12
src/or/eventdns.c

@@ -3132,13 +3132,13 @@ load_nameservers_with_getnetworkparams(void)
 	GetNetworkParams_fn_t fn;
 	GetNetworkParams_fn_t fn;
 
 
 	/* XXXX Possibly, we should hardcode the location of this DLL. */
 	/* XXXX Possibly, we should hardcode the location of this DLL. */
-	if (!(handle = LoadLibrary("iphlpapi.dll"))) {
+	if (!(handle = LoadLibraryW(L"iphlpapi.dll"))) {
 		log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll");
 		log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll");
 		/* right now status = 0, doesn't that mean "good" - mikec */
 		/* right now status = 0, doesn't that mean "good" - mikec */
 		status = -1;
 		status = -1;
 		goto done;
 		goto done;
 	}
 	}
-	if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, "GetNetworkParams"))) {
+	if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, TEXT("GetNetworkParams")))) {
 		log(EVDNS_LOG_WARN, "Could not get address of function.");
 		log(EVDNS_LOG_WARN, "Could not get address of function.");
 		/* same as above */
 		/* same as above */
 		status = -1;
 		status = -1;
@@ -3205,32 +3205,40 @@ config_nameserver_from_reg_key(HKEY key, const char *subkey)
 {
 {
 	char *buf;
 	char *buf;
 	DWORD bufsz = 0, type = 0;
 	DWORD bufsz = 0, type = 0;
+	WCHAR wsubkey[MAX_PATH] = {0};
+	char ansibuf[MAX_PATH] = {0};
 	int status = 0;
 	int status = 0;
 
 
-	if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz)
+	mbstowcs(wsubkey,subkey,MAX_PATH);
+	if (RegQueryValueExW(key, wsubkey, 0, &type, NULL, &bufsz)
 		!= ERROR_MORE_DATA)
 		!= ERROR_MORE_DATA)
 		return -1;
 		return -1;
 	if (!(buf = mm_malloc(bufsz)))
 	if (!(buf = mm_malloc(bufsz)))
 		return -1;
 		return -1;
 
 
-	if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz)
+	if (RegQueryValueExW(key, wsubkey, 0, &type, (LPBYTE)buf, &bufsz)
 		== ERROR_SUCCESS && bufsz > 1) {
 		== ERROR_SUCCESS && bufsz > 1) {
-		status = evdns_nameserver_ip_add_line(buf);
+		wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);
+		status = evdns_nameserver_ip_add_line(ansibuf);
 	}
 	}
 
 
 	mm_free(buf);
 	mm_free(buf);
 	return status;
 	return status;
 }
 }
 
 
-#define SERVICES_KEY "System\\CurrentControlSet\\Services\\"
-#define WIN_NS_9X_KEY  SERVICES_KEY "VxD\\MSTCP"
-#define WIN_NS_NT_KEY  SERVICES_KEY "Tcpip\\Parameters"
+#define SERVICES_KEY L"System\\CurrentControlSet\\Services\\"
+#define WIN_NS_9X_KEY  SERVICES_KEY L"VxD\\MSTCP"
+#define WIN_NS_NT_KEY  SERVICES_KEY L"Tcpip\\Parameters"
 
 
 static int
 static int
 load_nameservers_from_registry(void)
 load_nameservers_from_registry(void)
 {
 {
 	int found = 0;
 	int found = 0;
 	int r;
 	int r;
+	OSVERSIONINFO info = {0};
+	info.dwOSVersionInfoSize = sizeof (info);
+	GetVersionExW((LPOSVERSIONINFO)&info);
+
 #define TRY(k, name)													\
 #define TRY(k, name)													\
 	if (!found && config_nameserver_from_reg_key(k,name) == 0) {		\
 	if (!found && config_nameserver_from_reg_key(k,name) == 0) {		\
 		log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name);		\
 		log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name);		\
@@ -3240,15 +3248,15 @@ load_nameservers_from_registry(void)
 			#k,#name);													\
 			#k,#name);													\
 	}
 	}
 
 
-	if (((int)GetVersion()) > 0) { /* NT */
+	if (info.dwMajorVersion >= 5) { /* NT */
 		HKEY nt_key = 0, interfaces_key = 0;
 		HKEY nt_key = 0, interfaces_key = 0;
 
 
-		if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
+		if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
 						 KEY_READ, &nt_key) != ERROR_SUCCESS) {
 						 KEY_READ, &nt_key) != ERROR_SUCCESS) {
 			log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError());
 			log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError());
 			return -1;
 			return -1;
 		}
 		}
-		r = RegOpenKeyEx(nt_key, "Interfaces", 0,
+		r = RegOpenKeyExW(nt_key, L"Interfaces", 0,
 						 KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
 						 KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
 						 &interfaces_key);
 						 &interfaces_key);
 		if (r != ERROR_SUCCESS) {
 		if (r != ERROR_SUCCESS) {
@@ -3263,7 +3271,7 @@ load_nameservers_from_registry(void)
 		RegCloseKey(nt_key);
 		RegCloseKey(nt_key);
 	} else {
 	} else {
 		HKEY win_key = 0;
 		HKEY win_key = 0;
-		if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
+		if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
 						 KEY_READ, &win_key) != ERROR_SUCCESS) {
 						 KEY_READ, &win_key) != ERROR_SUCCESS) {
 			log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError());
 			log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError());
 			return -1;
 			return -1;

+ 56 - 0
src/or/main.c

@@ -24,6 +24,10 @@
 #include <event.h>
 #include <event.h>
 #endif
 #endif
 
 
+#if defined (WINCE)
+#include <projects.h>
+#endif
+
 void evdns_shutdown(int);
 void evdns_shutdown(int);
 
 
 /********* PROTOTYPES **********/
 /********* PROTOTYPES **********/
@@ -2104,6 +2108,31 @@ do_hash_password(void)
   printf("16:%s\n",output);
   printf("16:%s\n",output);
 }
 }
 
 
+#if defined (WINCE)
+int
+find_flashcard_path(PWCHAR path, size_t size)
+{
+  WIN32_FIND_DATA d = {0};
+  HANDLE h = NULL;
+
+  if (!path)
+    return -1;
+
+  h = FindFirstFlashCard(&d);
+  if (h == INVALID_HANDLE_VALUE)
+    return -1;
+
+  if (wcslen(d.cFileName) == 0) {
+    FindClose(h);
+    return -1;
+  }
+
+  wcsncpy(path,d.cFileName,size);
+  FindClose(h);
+  return 0;
+}
+#endif
+
 /** Main entry point for the Tor process.  Called from main(). */
 /** Main entry point for the Tor process.  Called from main(). */
 /* This function is distinct from main() only so we can link main.c into
 /* This function is distinct from main() only so we can link main.c into
  * the unittest binary without conflicting with the unittests' main. */
  * the unittest binary without conflicting with the unittests' main. */
@@ -2111,6 +2140,33 @@ int
 tor_main(int argc, char *argv[])
 tor_main(int argc, char *argv[])
 {
 {
   int result = 0;
   int result = 0;
+#if defined (WINCE)
+  WCHAR path [MAX_PATH] = {0};
+  WCHAR fullpath [MAX_PATH] = {0};
+  PWCHAR p = NULL;
+  FILE* redir = NULL;
+  FILE* redirdbg = NULL;
+
+  // this is to facilitate debugging by opening
+  // a file on a folder shared by the wm emulator.
+  // if no flashcard (real or emulated) is present,
+  // log files will be written in the root folder
+  if (find_flashcard_path(path,MAX_PATH) == -1)
+  {
+    redir = _wfreopen( L"\\stdout.log", L"w", stdout );
+    redirdbg = _wfreopen( L"\\stderr.log", L"w", stderr );
+  } else {
+    swprintf(fullpath,L"\\%s\\tor",path);
+    CreateDirectory(fullpath,NULL);
+
+    swprintf(fullpath,L"\\%s\\tor\\stdout.log",path);
+    redir = _wfreopen( fullpath, L"w", stdout );
+
+    swprintf(fullpath,L"\\%s\\tor\\stderr.log",path);
+    redirdbg = _wfreopen( fullpath, L"w", stderr );
+  }
+#endif
+
   update_approx_time(time(NULL));
   update_approx_time(time(NULL));
   tor_threads_init();
   tor_threads_init();
   init_logging();
   init_logging();

+ 2 - 0
src/or/or.h

@@ -4377,8 +4377,10 @@ void networkstatus_free_all(void);
 
 
 /********************************* ntmain.c ***************************/
 /********************************* ntmain.c ***************************/
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
+#if !defined (WINCE)
 #define NT_SERVICE
 #define NT_SERVICE
 #endif
 #endif
+#endif
 
 
 #ifdef NT_SERVICE
 #ifdef NT_SERVICE
 int nt_service_parse_options(int argc, char **argv, int *should_exit);
 int nt_service_parse_options(int argc, char **argv, int *should_exit);