Commit c0c78682 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Make the windows build succeed with or without -DUNICODE enabled.

This should keep WinCE working (unicode always-on) and get Win98
working again (unicode never-on).

There are two places where we explicitly use ASCII-only APIs, still:
in ntmain.c and in the unit tests.

This patch also fixes a bug in windoes tor_listdir that would cause
the first file to be listed an arbitrary number of times that was
also introduced with WinCE support.

Should fix bug 1797.
parent 34551cda
Loading
Loading
Loading
Loading

changes/win32_unicode

0 → 100644
+11 −0
Original line number Diff line number Diff line
  o Minor bugfixes
    - On Windows, build correctly either with or without Unicode support.
      This is necessary so that Tor can support fringe platforms like
      Windows 98 (which has no Unicode), or Windows CE (which has no
      non-Unicode). Bugfix on 0.2.2.14-alpha. Fixes bug 1797.
    - Fix the Windows directory-listing code.  A bug introduced in
      0.2.2.14-alpha could make Windows directory servers forget to
      load some of their cached v2 networkstatus files.

  o Testing
    - Add a unit test for cross-platform directory-listing code.
+22 −14
Original line number Diff line number Diff line
@@ -169,13 +169,17 @@ tor_munmap_file(tor_mmap_t *handle)
tor_mmap_t *
tor_mmap_file(const char *filename)
{
  WCHAR wfilename[MAX_PATH]= {0};
  TCHAR tfilename[MAX_PATH]= {0};
  tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t));
  int empty = 0;
  res->file_handle = INVALID_HANDLE_VALUE;
  res->mmap_handle = NULL;
  mbstowcs(wfilename,filename,MAX_PATH);
  res->file_handle = CreateFileW(wfilename,
#ifdef UNICODE
  mbstowcs(tfilename,filename,MAX_PATH);
#else
  strlcpy(tfilename,filename,MAX_PATH);
#endif
  res->file_handle = CreateFile(tfilename,
                                GENERIC_READ, FILE_SHARE_READ,
                                NULL,
                                OPEN_EXISTING,
@@ -1698,11 +1702,7 @@ get_uname(void)
#endif
      {
#ifdef MS_WINDOWS
#if defined (WINCE)
        OSVERSIONINFO info;
#else
        OSVERSIONINFOEXW info;
#endif
        OSVERSIONINFOEX info;
        int i;
        const char *plat = NULL;
        const char *extra = NULL;
@@ -1724,13 +1724,17 @@ get_uname(void)
        };
        memset(&info, 0, sizeof(info));
        info.dwOSVersionInfoSize = sizeof(info);
        if (! GetVersionExW((LPOSVERSIONINFOW)&info)) {
        if (! GetVersionEx((LPOSVERSIONINFO)&info)) {
          strlcpy(uname_result, "Bizarre version of Windows where GetVersionEx"
                  " doesn't work.", sizeof(uname_result));
          uname_result_is_set = 1;
          return uname_result;
        }
#ifdef UNICODE
        wcstombs(acsd, info.szCSDVersion, MAX_PATH);
#else
        strlcpy(acsd, info.szCSDVersion, sizeof(acsd));
#endif
        if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) {
          if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
            plat = "Windows NT 4.0";
@@ -2517,22 +2521,26 @@ network_init(void)
char *
format_win32_error(DWORD err)
{
  LPVOID str = NULL;
  char abuf[1024] = {0};
  TCHAR *str = NULL;
  char *result;

  /* Somebody once decided that this interface was better than strerror(). */
  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                 FORMAT_MESSAGE_FROM_SYSTEM |
                 FORMAT_MESSAGE_IGNORE_INSERTS,
                 NULL, err,
                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                 (LPWSTR) &str,
                (LPVOID)&str,
                 0, NULL);

  if (str) {
#ifdef UNICODE
    char abuf[1024] = {0};
    wcstombs(abuf,str,1024);
    result = tor_strdup((char*)abuf);
    result = tor_strdup(abuf);
#else
    result = tor_strdup(str);
#endif
    LocalFree(str); /* LocalFree != free() */
  } else {
    result = tor_strdup("<unformattable error>");
+14 −6
Original line number Diff line number Diff line
@@ -2526,26 +2526,34 @@ tor_listdir(const char *dirname)
  smartlist_t *result;
#ifdef MS_WINDOWS
  char *pattern;
  WCHAR wpattern[MAX_PATH] = {0};
  TCHAR tpattern[MAX_PATH] = {0};
  char name[MAX_PATH] = {0};
  HANDLE handle;
  WIN32_FIND_DATAW findData;
  WIN32_FIND_DATA findData;
  size_t pattern_len = strlen(dirname)+16;
  pattern = tor_malloc(pattern_len);
  tor_snprintf(pattern, pattern_len, "%s\\*", dirname);
  mbstowcs(wpattern,pattern,MAX_PATH);
  if (INVALID_HANDLE_VALUE == (handle = FindFirstFileW(wpattern, &findData))) {
#ifdef UNICODE
  mbstowcs(tpattern,pattern,MAX_PATH);
#else
  strlcpy(tpattern, pattern, MAX_PATH);
#endif
  if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &findData))) {
    tor_free(pattern);
    return NULL;
  }
  wcstombs(name,findData.cFileName,MAX_PATH);
  result = smartlist_create();
  while (1) {
#ifdef UNICODE
    wcstombs(name,findData.cFileName,MAX_PATH);
#else
    strlcpy(name,findData.cFileName,sizeof(name));
#endif
    if (strcmp(name, ".") &&
        strcmp(name, "..")) {
      smartlist_add(result, tor_strdup(name));
    }
    if (!FindNextFileW(handle, &findData)) {
    if (!FindNextFile(handle, &findData)) {
      DWORD err;
      if ((err = GetLastError()) != ERROR_NO_MORE_FILES) {
        char *errstr = format_win32_error(err);
+7 −3
Original line number Diff line number Diff line
@@ -3832,7 +3832,7 @@ get_windows_conf_root(void)
{
  static int is_set = 0;
  static char path[MAX_PATH+1];
  WCHAR wpath[MAX_PATH] = {0};
  TCHAR tpath[MAX_PATH] = {0};

  LPITEMIDLIST idl;
  IMalloc *m;
@@ -3859,8 +3859,12 @@ get_windows_conf_root(void)
    return path;
  }
  /* Convert the path from an "ID List" (whatever that is!) to a path. */
  result = SHGetPathFromIDListW(idl, wpath);
  wcstombs(path,wpath,MAX_PATH);
  result = SHGetPathFromIDList(idl, tpath);
#ifdef UNICODE
  wcstombs(path,tpath,MAX_PATH);
#else
  strlcpy(path,tpath,sizeof(path));
#endif

  /* Now we need to free the memory that the path-idl was stored in.  In
   * typical Windows fashion, we can't just call 'free()' on it. */
+16 −18
Original line number Diff line number Diff line
@@ -3132,7 +3132,7 @@ load_nameservers_with_getnetworkparams(void)
	GetNetworkParams_fn_t fn;

	/* XXXX Possibly, we should hardcode the location of this DLL. */
	if (!(handle = LoadLibraryW(L"iphlpapi.dll"))) {
	if (!(handle = LoadLibrary(TEXT("iphlpapi.dll"))) {
		log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll");
		/* right now status = 0, doesn't that mean "good" - mikec */
		status = -1;
@@ -3201,46 +3201,44 @@ load_nameservers_with_getnetworkparams(void)
}

static int
config_nameserver_from_reg_key(HKEY key, const char *subkey)
config_nameserver_from_reg_key(HKEY key, const TCHAR *subkey)
{
	char *buf;
	DWORD bufsz = 0, type = 0;
	WCHAR wsubkey[MAX_PATH] = {0};
	char ansibuf[MAX_PATH] = {0};
	int status = 0;

	mbstowcs(wsubkey,subkey,MAX_PATH);
	if (RegQueryValueExW(key, wsubkey, 0, &type, NULL, &bufsz)
	if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz)
		!= ERROR_MORE_DATA)
		return -1;
	if (!(buf = mm_malloc(bufsz)))
		return -1;

	if (RegQueryValueExW(key, wsubkey, 0, &type, (LPBYTE)buf, &bufsz)
	if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz)
		== ERROR_SUCCESS && bufsz > 1) {
		wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);
		status = evdns_nameserver_ip_add_line(ansibuf);
		wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);/*XXXX UNICODE */
		status = evdns_nameserver_ip_add_line(buf);
	}

	mm_free(buf);
	return status;
}

#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"
#define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\")
#define WIN_NS_9X_KEY  SERVICES_KEY TEXT("VxD\\MSTCP")
#define WIN_NS_NT_KEY  SERVICES_KEY TEXT("Tcpip\\Parameters")

static int
load_nameservers_from_registry(void)
{
	int found = 0;
	int r;
	OSVERSIONINFO info = {0};
	OSVERSIONINFO info;
	memset(&info, 0, sizeof(info));
	info.dwOSVersionInfoSize = sizeof (info);
	GetVersionExW((LPOSVERSIONINFO)&info);
	GetVersionEx(&info);

#define TRY(k, name)													\
	if (!found && config_nameserver_from_reg_key(k,name) == 0) {		\
	if (!found && config_nameserver_from_reg_key(k,TEXT(name)) == 0) {	\
		log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name);		\
		found = 1;														\
	} else if (!found) {												\
@@ -3251,12 +3249,12 @@ load_nameservers_from_registry(void)
	if (info.dwMajorVersion >= 5) { /* NT */
		HKEY nt_key = 0, interfaces_key = 0;

		if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
		if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0,
						 KEY_READ, &nt_key) != ERROR_SUCCESS) {
			log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError());
			return -1;
		}
		r = RegOpenKeyExW(nt_key, L"Interfaces", 0,
		r = RegOpenKeyEx(nt_key, Text("Interfaces"), 0,
						 KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS,
						 &interfaces_key);
		if (r != ERROR_SUCCESS) {
@@ -3271,7 +3269,7 @@ load_nameservers_from_registry(void)
		RegCloseKey(nt_key);
	} else {
		HKEY win_key = 0;
		if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
		if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0,
						 KEY_READ, &win_key) != ERROR_SUCCESS) {
			log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError());
			return -1;
Loading