mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-20 18:22:09 +01:00
Merge remote branch 'public/win_unicode_fixes'
This commit is contained in:
commit
edc9256e95
11
changes/win32_unicode
Normal file
11
changes/win32_unicode
Normal 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.
|
@ -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>");
|
||||||
|
@ -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);
|
||||||
|
@ -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. */
|
||||||
|
@ -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;
|
||||||
|
113
src/or/ntmain.c
113
src/or/ntmain.c
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user