Browse Source

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.
Nick Mathewson 13 years ago
parent
commit
c0c7868250
7 changed files with 125 additions and 103 deletions
  1. 11 0
      changes/win32_unicode
  2. 22 14
      src/common/compat.c
  3. 14 6
      src/common/util.c
  4. 7 3
      src/or/config.c
  5. 16 18
      src/or/eventdns.c
  6. 53 60
      src/or/ntmain.c
  7. 2 2
      src/test/tinytest.c

+ 11 - 0
changes/win32_unicode

@@ -0,0 +1,11 @@
+  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
src/common/compat.c

@@ -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
src/common/util.c

@@ -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
src/or/config.c

@@ -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
src/or/eventdns.c

@@ -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;

+ 53 - 60
src/or/ntmain.c

@@ -15,12 +15,12 @@
 #include <event.h>
 #endif
 
-#include <tchar.h>
-#define GENSRV_SERVICENAME  TEXT("tor")
-#define GENSRV_DISPLAYNAME  TEXT("Tor Win32 Service")
+#include <windows.h>
+#define GENSRV_SERVICENAME  "tor"
+#define GENSRV_DISPLAYNAME  "Tor Win32 Service"
 #define GENSRV_DESCRIPTION  \
-  TEXT("Provides an anonymous Internet communication system")
-#define GENSRV_USERACCT TEXT("NT AUTHORITY\\LocalService")
+  "Provides an anonymous Internet communication system"
+#define GENSRV_USERACCT "NT AUTHORITY\\LocalService"
 
 // Cheating: using the pre-defined error codes, tricks Windows into displaying
 //           a semi-related human-readable error message if startup fails as
@@ -36,7 +36,6 @@ static SERVICE_STATUS_HANDLE hStatus;
  * to the NT service functions. */
 static char **backup_argv;
 static int backup_argc;
-static char* nt_strerror(uint32_t errnum);
 
 static void nt_service_control(DWORD request);
 static void nt_service_body(int argc, char **argv);
@@ -70,30 +69,30 @@ struct service_fns {
 
   SC_HANDLE (WINAPI *CreateServiceA_fn)(
                              SC_HANDLE hSCManager,
-                             LPCTSTR lpServiceName,
-                             LPCTSTR lpDisplayName,
+                             LPCSTR lpServiceName,
+                             LPCSTR lpDisplayName,
                              DWORD dwDesiredAccess,
                              DWORD dwServiceType,
                              DWORD dwStartType,
                              DWORD dwErrorControl,
-                             LPCTSTR lpBinaryPathName,
-                             LPCTSTR lpLoadOrderGroup,
+                             LPCSTR lpBinaryPathName,
+                             LPCSTR lpLoadOrderGroup,
                              LPDWORD lpdwTagId,
-                             LPCTSTR lpDependencies,
-                             LPCTSTR lpServiceStartName,
-                             LPCTSTR lpPassword);
+                             LPCSTR lpDependencies,
+                             LPCSTR lpServiceStartName,
+                             LPCSTR lpPassword);
 
   BOOL (WINAPI *DeleteService_fn)(
                              SC_HANDLE hService);
 
   SC_HANDLE (WINAPI *OpenSCManagerA_fn)(
-                             LPCTSTR lpMachineName,
-                             LPCTSTR lpDatabaseName,
+                             LPCSTR lpMachineName,
+                             LPCSTR lpDatabaseName,
                              DWORD dwDesiredAccess);
 
   SC_HANDLE (WINAPI *OpenServiceA_fn)(
                              SC_HANDLE hSCManager,
-                             LPCTSTR lpServiceName,
+                             LPCSTR lpServiceName,
                              DWORD dwDesiredAccess);
 
   BOOL (WINAPI *QueryServiceStatus_fn)(
@@ -101,23 +100,23 @@ struct service_fns {
                              LPSERVICE_STATUS lpServiceStatus);
 
   SERVICE_STATUS_HANDLE (WINAPI *RegisterServiceCtrlHandlerA_fn)(
-                             LPCTSTR lpServiceName,
+                             LPCSTR lpServiceName,
                              LPHANDLER_FUNCTION lpHandlerProc);
 
   BOOL (WINAPI *SetServiceStatus_fn)(SERVICE_STATUS_HANDLE,
                              LPSERVICE_STATUS);
 
   BOOL (WINAPI *StartServiceCtrlDispatcherA_fn)(
-                             const SERVICE_TABLE_ENTRY* lpServiceTable);
+                             const SERVICE_TABLE_ENTRYA* lpServiceTable);
 
   BOOL (WINAPI *StartServiceA_fn)(
                              SC_HANDLE hService,
                              DWORD dwNumServiceArgs,
-                             LPCTSTR* lpServiceArgVectors);
+                             LPCSTR* lpServiceArgVectors);
 
   BOOL (WINAPI *LookupAccountNameA_fn)(
-                             LPCTSTR lpSystemName,
-                             LPCTSTR lpAccountName,
+                             LPCSTR lpSystemName,
+                             LPCSTR lpAccountName,
                              PSID Sid,
                              LPDWORD cbSid,
                              LPTSTR ReferencedDomainName,
@@ -140,7 +139,7 @@ nt_service_loadlibrary(void)
     return;
 
   /* XXXX Possibly, we should hardcode the location of this DLL. */
-  if (!(library = LoadLibrary("advapi32.dll"))) {
+  if (!(library = LoadLibrary(TEXT("advapi32.dll")))) {
     log_err(LD_GENERAL, "Couldn't open advapi32.dll.  Are you trying to use "
             "NT services on Windows 98? That doesn't work.");
     goto err;
@@ -284,20 +283,20 @@ nt_service_body(int argc, char **argv)
 static void
 nt_service_main(void)
 {
-  SERVICE_TABLE_ENTRY table[2];
+  SERVICE_TABLE_ENTRYA table[2];
   DWORD result = 0;
   char *errmsg;
   nt_service_loadlibrary();
   table[0].lpServiceName = (char*)GENSRV_SERVICENAME;
-  table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body;
+  table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)nt_service_body;
   table[1].lpServiceName = NULL;
   table[1].lpServiceProc = NULL;
 
   if (!service_fns.StartServiceCtrlDispatcherA_fn(table)) {
     result = GetLastError();
-    errmsg = nt_strerror(result);
+    errmsg = format_win32_error(result);
     printf("Service error %d : %s\n", (int) result, errmsg);
-    LocalFree(errmsg);
+    tor_free(errmsg);
     if (result == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
       if (tor_init(backup_argc, backup_argv) < 0)
         return;
@@ -332,9 +331,9 @@ nt_service_open_scm(void)
   nt_service_loadlibrary();
   if ((hSCManager = service_fns.OpenSCManagerA_fn(
                             NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) {
-    errmsg = nt_strerror(GetLastError());
+    errmsg = format_win32_error(GetLastError());
     printf("OpenSCManager() failed : %s\n", errmsg);
-    LocalFree(errmsg);
+    tor_free(errmsg);
   }
   return hSCManager;
 }
@@ -349,9 +348,9 @@ nt_service_open(SC_HANDLE hSCManager)
   nt_service_loadlibrary();
   if ((hService = service_fns.OpenServiceA_fn(hSCManager, GENSRV_SERVICENAME,
                               SERVICE_ALL_ACCESS)) == NULL) {
-    errmsg = nt_strerror(GetLastError());
+    errmsg = format_win32_error(GetLastError());
     printf("OpenService() failed : %s\n", errmsg);
-    LocalFree(errmsg);
+    tor_free(errmsg);
   }
   return hService;
 }
@@ -383,14 +382,14 @@ nt_service_start(SC_HANDLE hService)
       printf("Service started successfully\n");
       return 0;
     } else {
-      errmsg = nt_strerror(service_status.dwWin32ExitCode);
+      errmsg = format_win32_error(service_status.dwWin32ExitCode);
       printf("Service failed to start : %s\n", errmsg);
-      LocalFree(errmsg);
+      tor_free(errmsg);
     }
   } else {
-    errmsg = nt_strerror(GetLastError());
+    errmsg = format_win32_error(GetLastError());
     printf("StartService() failed : %s\n", errmsg);
-    LocalFree(errmsg);
+    tor_free(errmsg);
   }
   return -1;
 }
@@ -427,14 +426,14 @@ nt_service_stop(SC_HANDLE hService)
     } else if (wait_time == MAX_SERVICE_WAIT_TIME) {
       printf("Service did not stop within %d seconds.\n", wait_time);
     } else {
-      errmsg = nt_strerror(GetLastError());
+      errmsg = format_win32_error(GetLastError());
       printf("QueryServiceStatus() failed : %s\n",errmsg);
-      LocalFree(errmsg);
+      tor_free(errmsg);
     }
   } else {
-    errmsg = nt_strerror(GetLastError());
+    errmsg = format_win32_error(GetLastError());
     printf("ControlService() failed : %s\n", errmsg);
-    LocalFree(errmsg);
+    tor_free(errmsg);
   }
   return -1;
 }
@@ -448,6 +447,7 @@ static char *
 nt_service_command_line(int *using_default_torrc)
 {
   TCHAR tor_exe[MAX_PATH+1];
+  char tor_exe_ascii[MAX_PATH+1];
   char *command, *options=NULL;
   smartlist_t *sl;
   int i, cmdlen;
@@ -473,18 +473,25 @@ nt_service_command_line(int *using_default_torrc)
     options = smartlist_join_strings(sl,"\" \"",0,NULL);
   smartlist_free(sl);
 
+#ifdef UNICODE
+  wcstombs(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii));
+#else
+  strlcpy(tor_exe_ascii, tor_exe, sizeof(tor_exe_ascii));
+#endif
+
   /* Allocate a string for the NT service command line */
-  cmdlen = strlen(tor_exe) + (options?strlen(options):0) + 32;
+  cmdlen = strlen(tor_exe_ascii) + (options?strlen(options):0) + 32;
   command = tor_malloc(cmdlen);
 
   /* Format the service command */
   if (options) {
     if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service \"%s\"",
-                     tor_exe, options)<0) {
+                     tor_exe_ascii, options)<0) {
       tor_free(command); /* sets command to NULL. */
     }
   } else { /* ! options */
-    if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service", tor_exe)<0) {
+    if (tor_snprintf(command, cmdlen, "\"%s\" --nt-service",
+                     tor_exe_ascii)<0) {
       tor_free(command); /* sets command to NULL. */
     }
   }
@@ -509,7 +516,7 @@ nt_service_install(int argc, char **argv)
 
   SC_HANDLE hSCManager = NULL;
   SC_HANDLE hService = NULL;
-  SERVICE_DESCRIPTION sdBuff;
+  SERVICE_DESCRIPTIONA sdBuff;
   char *command;
   char *errmsg;
   const char *user_acct = GENSRV_USERACCT;
@@ -599,10 +606,10 @@ nt_service_install(int argc, char **argv)
                                 SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
                                 command, NULL, NULL, NULL,
                                 user_acct, password)) == NULL) {
-    errmsg = nt_strerror(GetLastError());
+    errmsg = format_win32_error(GetLastError());
     printf("CreateService() failed : %s\n", errmsg);
     service_fns.CloseServiceHandle_fn(hSCManager);
-    LocalFree(errmsg);
+    tor_free(errmsg);
     tor_free(command);
     return -1;
   }
@@ -643,9 +650,9 @@ nt_service_remove(void)
 
   nt_service_stop(hService);
   if (service_fns.DeleteService_fn(hService) == FALSE) {
-    errmsg = nt_strerror(GetLastError());
+    errmsg = format_win32_error(GetLastError());
     printf("DeleteService() failed : %s\n", errmsg);
-    LocalFree(errmsg);
+    tor_free(errmsg);
     service_fns.CloseServiceHandle_fn(hService);
     service_fns.CloseServiceHandle_fn(hSCManager);
     return -1;
@@ -702,20 +709,6 @@ nt_service_cmd_stop(void)
   return stop;
 }
 
-/** Given a Win32 error code, this attempts to make Windows
- * return a human-readable error message. The char* returned
- * is allocated by Windows, but should be freed with LocalFree()
- * when finished with it. */
-static char*
-nt_strerror(uint32_t errnum)
-{
-   char *msgbuf;
-   FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-                 NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                 (LPSTR)&msgbuf, 0, NULL);
-   return msgbuf;
-}
-
 int
 nt_service_parse_options(int argc, char **argv, int *should_exit)
 {

+ 2 - 2
src/test/tinytest.c

@@ -111,7 +111,7 @@ _testcase_run_forked(const struct testgroup_t *group,
 	 */
 	int ok;
 	char buffer[LONGEST_TEST_NAME+256];
-	STARTUPINFO si;
+	STARTUPINFOA si;
 	PROCESS_INFORMATION info;
 	DWORD exitcode;
 
@@ -130,7 +130,7 @@ _testcase_run_forked(const struct testgroup_t *group,
 	memset(&info, 0, sizeof(info));
 	si.cb = sizeof(si);
 
-	ok = CreateProcess(commandname, buffer, NULL, NULL, 0,
+	ok = CreateProcessA(commandname, buffer, NULL, NULL, 0,
 			   0, NULL, NULL, &si, &info);
 	if (!ok) {
 		printf("CreateProcess failed!\n");