Merge remote branch 'public/win_unicode_fixes'

This commit is contained in:
Nick Mathewson 2010-09-06 10:06:07 -04:00
commit edc9256e95
7 changed files with 125 additions and 103 deletions

11
changes/win32_unicode Normal file
View File

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

View File

@ -169,13 +169,17 @@ 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}; TCHAR tfilename[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;
mbstowcs(wfilename,filename,MAX_PATH); #ifdef UNICODE
res->file_handle = CreateFileW(wfilename, mbstowcs(tfilename,filename,MAX_PATH);
#else
strlcpy(tfilename,filename,MAX_PATH);
#endif
res->file_handle = CreateFile(tfilename,
GENERIC_READ, FILE_SHARE_READ, GENERIC_READ, FILE_SHARE_READ,
NULL, NULL,
OPEN_EXISTING, OPEN_EXISTING,
@ -1698,11 +1702,7 @@ get_uname(void)
#endif #endif
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
#if defined (WINCE) OSVERSIONINFOEX info;
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;
@ -1724,13 +1724,17 @@ get_uname(void)
}; };
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
info.dwOSVersionInfoSize = sizeof(info); info.dwOSVersionInfoSize = sizeof(info);
if (! GetVersionExW((LPOSVERSIONINFOW)&info)) { if (! GetVersionEx((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;
} }
#ifdef UNICODE
wcstombs(acsd, info.szCSDVersion, MAX_PATH); wcstombs(acsd, info.szCSDVersion, MAX_PATH);
#else
strlcpy(acsd, info.szCSDVersion, sizeof(acsd));
#endif
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";
@ -2517,22 +2521,26 @@ network_init(void)
char * char *
format_win32_error(DWORD err) format_win32_error(DWORD err)
{ {
LPVOID str = NULL; TCHAR *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(). */
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err, NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &str, (LPVOID)&str,
0, NULL); 0, NULL);
if (str) { if (str) {
#ifdef UNICODE
char abuf[1024] = {0};
wcstombs(abuf,str,1024); wcstombs(abuf,str,1024);
result = tor_strdup((char*)abuf); result = tor_strdup(abuf);
#else
result = tor_strdup(str);
#endif
LocalFree(str); /* LocalFree != free() */ LocalFree(str); /* LocalFree != free() */
} else { } else {
result = tor_strdup("<unformattable error>"); result = tor_strdup("<unformattable error>");

View File

@ -2569,26 +2569,34 @@ 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}; TCHAR tpattern[MAX_PATH] = {0};
char name[MAX_PATH] = {0}; char name[MAX_PATH] = {0};
HANDLE handle; HANDLE handle;
WIN32_FIND_DATAW findData; WIN32_FIND_DATA 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);
mbstowcs(wpattern,pattern,MAX_PATH); #ifdef UNICODE
if (INVALID_HANDLE_VALUE == (handle = FindFirstFileW(wpattern, &findData))) { mbstowcs(tpattern,pattern,MAX_PATH);
#else
strlcpy(tpattern, pattern, MAX_PATH);
#endif
if (INVALID_HANDLE_VALUE == (handle = FindFirstFile(tpattern, &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) {
#ifdef UNICODE
wcstombs(name,findData.cFileName,MAX_PATH);
#else
strlcpy(name,findData.cFileName,sizeof(name));
#endif
if (strcmp(name, ".") && if (strcmp(name, ".") &&
strcmp(name, "..")) { strcmp(name, "..")) {
smartlist_add(result, tor_strdup(name)); smartlist_add(result, tor_strdup(name));
} }
if (!FindNextFileW(handle, &findData)) { if (!FindNextFile(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);

View File

@ -3832,7 +3832,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}; TCHAR tpath[MAX_PATH] = {0};
LPITEMIDLIST idl; LPITEMIDLIST idl;
IMalloc *m; IMalloc *m;
@ -3859,8 +3859,12 @@ 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 = SHGetPathFromIDListW(idl, wpath); result = SHGetPathFromIDList(idl, tpath);
wcstombs(path,wpath,MAX_PATH); #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 /* 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. */ * typical Windows fashion, we can't just call 'free()' on it. */

View File

@ -3132,7 +3132,7 @@ 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 = LoadLibraryW(L"iphlpapi.dll"))) { if (!(handle = LoadLibrary(TEXT("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;
@ -3201,46 +3201,44 @@ load_nameservers_with_getnetworkparams(void)
} }
static int static int
config_nameserver_from_reg_key(HKEY key, const char *subkey) config_nameserver_from_reg_key(HKEY key, const TCHAR *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;
mbstowcs(wsubkey,subkey,MAX_PATH); if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz)
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 (RegQueryValueExW(key, wsubkey, 0, &type, (LPBYTE)buf, &bufsz) if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz)
== ERROR_SUCCESS && bufsz > 1) { == ERROR_SUCCESS && bufsz > 1) {
wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH); wcstombs(ansibuf,(wchar_t*)buf,MAX_PATH);/*XXXX UNICODE */
status = evdns_nameserver_ip_add_line(ansibuf); status = evdns_nameserver_ip_add_line(buf);
} }
mm_free(buf); mm_free(buf);
return status; return status;
} }
#define SERVICES_KEY L"System\\CurrentControlSet\\Services\\" #define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\")
#define WIN_NS_9X_KEY SERVICES_KEY L"VxD\\MSTCP" #define WIN_NS_9X_KEY SERVICES_KEY TEXT("VxD\\MSTCP")
#define WIN_NS_NT_KEY SERVICES_KEY L"Tcpip\\Parameters" #define WIN_NS_NT_KEY SERVICES_KEY TEXT("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}; OSVERSIONINFO info;
memset(&info, 0, sizeof(info));
info.dwOSVersionInfoSize = sizeof (info); info.dwOSVersionInfoSize = sizeof (info);
GetVersionExW((LPOSVERSIONINFO)&info); GetVersionEx(&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,TEXT(name)) == 0) { \
log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \
found = 1; \ found = 1; \
} else if (!found) { \ } else if (!found) { \
@ -3251,12 +3249,12 @@ load_nameservers_from_registry(void)
if (info.dwMajorVersion >= 5) { /* NT */ if (info.dwMajorVersion >= 5) { /* NT */
HKEY nt_key = 0, interfaces_key = 0; 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) { 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 = RegOpenKeyExW(nt_key, L"Interfaces", 0, r = RegOpenKeyEx(nt_key, Text("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) {
@ -3271,7 +3269,7 @@ load_nameservers_from_registry(void)
RegCloseKey(nt_key); RegCloseKey(nt_key);
} else { } else {
HKEY win_key = 0; 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) { 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;

View File

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

View File

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