Skip to content

Commit

Permalink
Allow compiling as a Unicode application.
Browse files Browse the repository at this point in the history
Overhaul the entire codebase so that it compiles and runs as either a
Unicode or ANSI application.
  • Loading branch information
Iain Patterson committed Nov 26, 2013
1 parent cba3331 commit 5b9e64a
Show file tree
Hide file tree
Showing 17 changed files with 310 additions and 296 deletions.
46 changes: 23 additions & 23 deletions event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
unsigned long tls_index;

/* Convert error code to error string - must call LocalFree() on return value */
char *error_string(unsigned long error) {
TCHAR *error_string(unsigned long error) {
/* Thread-safe buffer */
char *error_message = (char *) TlsGetValue(tls_index);
TCHAR *error_message = (TCHAR *) TlsGetValue(tls_index);
if (! error_message) {
error_message = (char *) LocalAlloc(LPTR, NSSM_ERROR_BUFSIZE);
if (! error_message) return "<out of memory for error message>";
error_message = (TCHAR *) LocalAlloc(LPTR, NSSM_ERROR_BUFSIZE);
if (! error_message) return _T("<out of memory for error message>");
TlsSetValue(tls_index, (void *) error_message);
}

if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) error_message, NSSM_ERROR_BUFSIZE, 0)) {
if (_snprintf_s(error_message, NSSM_ERROR_BUFSIZE, _TRUNCATE, "system error %lu", error) < 0) return 0;
if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (TCHAR *) error_message, NSSM_ERROR_BUFSIZE, 0)) {
if (_sntprintf_s(error_message, NSSM_ERROR_BUFSIZE, _TRUNCATE, _T("system error %lu"), error) < 0) return 0;
}
return error_message;
}

/* Convert message code to format string */
char *message_string(unsigned long error) {
char *ret;
if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &ret, NSSM_ERROR_BUFSIZE, 0)) {
ret = (char *) HeapAlloc(GetProcessHeap(), 0, 32);
if (_snprintf_s(ret, NSSM_ERROR_BUFSIZE, _TRUNCATE, "system error %lu", error) < 0) return 0;
TCHAR *message_string(unsigned long error) {
TCHAR *ret;
if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &ret, NSSM_ERROR_BUFSIZE, 0)) {
ret = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, 32 * sizeof(TCHAR));
if (_sntprintf_s(ret, NSSM_ERROR_BUFSIZE, _TRUNCATE, _T("system error %lu"), error) < 0) return 0;
}
return ret;
}
Expand All @@ -34,20 +34,20 @@ char *message_string(unsigned long error) {
void log_event(unsigned short type, unsigned long id, ...) {
va_list arg;
int count;
char *s;
char *strings[NSSM_NUM_EVENT_STRINGS];
TCHAR *s;
TCHAR *strings[NSSM_NUM_EVENT_STRINGS];

/* Open event log */
HANDLE handle = RegisterEventSource(0, TEXT(NSSM));
HANDLE handle = RegisterEventSource(0, NSSM);
if (! handle) return;

/* Log it */
count = 0;
va_start(arg, id);
while ((s = va_arg(arg, char *)) && count < NSSM_NUM_EVENT_STRINGS - 1) strings[count++] = s;
while ((s = va_arg(arg, TCHAR *)) && count < NSSM_NUM_EVENT_STRINGS - 1) strings[count++] = s;
strings[count] = 0;
va_end(arg);
ReportEvent(handle, type, 0, id, 0, count, 0, (const char **) strings, 0);
ReportEvent(handle, type, 0, id, 0, count, 0, (const TCHAR **) strings, 0);

/* Close event log */
DeregisterEventSource(handle);
Expand All @@ -57,11 +57,11 @@ void log_event(unsigned short type, unsigned long id, ...) {
void print_message(FILE *file, unsigned long id, ...) {
va_list arg;

char *format = message_string(id);
TCHAR *format = message_string(id);
if (! format) return;

va_start(arg, id);
vfprintf(file, format, arg);
_vftprintf(file, format, arg);
va_end(arg);

LocalFree(format);
Expand All @@ -71,17 +71,17 @@ void print_message(FILE *file, unsigned long id, ...) {
int popup_message(unsigned int type, unsigned long id, ...) {
va_list arg;

char *format = message_string(id);
TCHAR *format = message_string(id);
if (! format) {
return MessageBox(0, "Message %lu was supposed to go here!", NSSM, MB_OK | MB_ICONEXCLAMATION);
return MessageBox(0, _T("Message %lu was supposed to go here!"), NSSM, MB_OK | MB_ICONEXCLAMATION);
}

char blurb[256];
TCHAR blurb[256];
va_start(arg, id);
if (vsnprintf_s(blurb, sizeof(blurb), _TRUNCATE, format, arg) < 0) {
if (_vsntprintf_s(blurb, sizeof(blurb), _TRUNCATE, format, arg) < 0) {
va_end(arg);
LocalFree(format);
return MessageBox(0, "Message %lu was supposed to go here!", NSSM, MB_OK | MB_ICONEXCLAMATION);
return MessageBox(0, _T("Message %lu was supposed to go here!"), NSSM, MB_OK | MB_ICONEXCLAMATION);
}
va_end(arg);

Expand Down
4 changes: 2 additions & 2 deletions event.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#ifndef EVENT_H
#define EVENT_H

char *error_string(unsigned long);
char *message_string(unsigned long);
TCHAR *error_string(unsigned long);
TCHAR *message_string(unsigned long);
void log_event(unsigned short, unsigned long, ...);
void print_message(FILE *, unsigned long, ...);
int popup_message(unsigned int, unsigned long, ...);
Expand Down
82 changes: 43 additions & 39 deletions gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_I
static HWND tablist[NSSM_NUM_TABS];
static int selected_tab;

int nssm_gui(int resource, char *name) {
int nssm_gui(int resource, TCHAR *name) {
/* Create window */
HWND dlg = CreateDialog(0, MAKEINTRESOURCE(resource), 0, install_dlg);
if (! dlg) {
Expand Down Expand Up @@ -74,7 +74,7 @@ static inline void check_method_timeout(HWND tab, unsigned long control, unsigne
if (translated) *timeout = configured;
}

static inline void check_io(char *name, char *buffer, size_t bufsize, unsigned long control) {
static inline void check_io(TCHAR *name, TCHAR *buffer, size_t bufsize, unsigned long control) {
if (! SendMessage(GetDlgItem(tablist[NSSM_TAB_IO], control), WM_GETTEXTLENGTH, 0, 0)) return;
if (GetDlgItemText(tablist[NSSM_TAB_IO], control, buffer, (int) bufsize)) return;
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, name);
Expand Down Expand Up @@ -104,7 +104,7 @@ int install(HWND window) {

/* Get startup directory. */
if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir, sizeof(service->dir))) {
memmove(service->dir, service->exe, sizeof(service->dir));
_sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe);
strip_basename(service->dir);
}

Expand Down Expand Up @@ -132,9 +132,9 @@ int install(HWND window) {
if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;

/* Get I/O stuff. */
check_io("stdin", service->stdin_path, sizeof(service->stdin_path), IDC_STDIN);
check_io("stdout", service->stdout_path, sizeof(service->stdout_path), IDC_STDOUT);
check_io("stderr", service->stderr_path, sizeof(service->stderr_path), IDC_STDERR);
check_io(_T("stdin"), service->stdin_path, sizeof(service->stdin_path), IDC_STDIN);
check_io(_T("stdout"), service->stdout_path, sizeof(service->stdout_path), IDC_STDOUT);
check_io(_T("stderr"), service->stderr_path, sizeof(service->stderr_path), IDC_STDERR);
/* Override stdout and/or stderr. */
if (SendDlgItemMessage(tablist[NSSM_TAB_IO], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
Expand All @@ -144,9 +144,9 @@ int install(HWND window) {
/* Get environment. */
unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
if (envlen) {
char *env = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, envlen + 2);
TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
if (! env) {
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "environment", "install()");
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
cleanup_nssm_service(service);
return 5;
}
Expand All @@ -161,21 +161,21 @@ int install(HWND window) {
/* Strip CR and replace LF with NULL. */
unsigned long newlen = 0;
unsigned long i, j;
for (i = 0; i < envlen; i++) if (env[i] != '\r') newlen++;
for (i = 0; i < envlen; i++) if (env[i] != _T('\r')) newlen++;
/* Must end with two NULLs. */
newlen += 2;

char *newenv = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newlen);
TCHAR *newenv = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newlen * sizeof(TCHAR));
if (! newenv) {
HeapFree(GetProcessHeap(), 0, env);
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "environment", "install()");
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
cleanup_nssm_service(service);
return 5;
}

for (i = 0, j = 0; i < envlen; i++) {
if (env[i] == '\r') continue;
if (env[i] == '\n') newenv[j] = '\0';
if (env[i] == _T('\r')) continue;
if (env[i] == _T('\n')) newenv[j] = _T('\0');
else newenv[j] = env[i];
j++;
}
Expand All @@ -185,15 +185,19 @@ int install(HWND window) {
envlen = newlen;

/* Test the environment is valid. */
char path[MAX_PATH];
GetModuleFileName(0, path, sizeof(path));
TCHAR path[MAX_PATH];
GetModuleFileName(0, path, _countof(path));
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
unsigned long flags = CREATE_SUSPENDED;
#ifdef UNICODE
flags |= CREATE_UNICODE_ENVIRONMENT;
#endif

if (! CreateProcess(0, path, 0, 0, 0, CREATE_SUSPENDED, env, 0, &si, &pi)) {
if (! CreateProcess(0, path, 0, 0, 0, flags, env, 0, &si, &pi)) {
unsigned long error = GetLastError();
if (error == ERROR_INVALID_PARAMETER) {
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
Expand All @@ -219,7 +223,7 @@ int install(HWND window) {
/* See if it works. */
switch (install_service(service)) {
case 1:
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "service", "install()");
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
cleanup_nssm_service(service);
return 1;

Expand Down Expand Up @@ -277,7 +281,7 @@ int remove(HWND window) {

switch (remove_service(service)) {
case 1:
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "service", "remove()");
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
cleanup_nssm_service(service);
return 1;

Expand All @@ -302,12 +306,12 @@ int remove(HWND window) {
return 0;
}

static char *browse_filter(int message) {
static TCHAR *browse_filter(int message) {
switch (message) {
case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return "*.exe;*.bat;*.cmd";
case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return ".";
case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
default: return "*.*";
default: return _T("*.*");
}
}

Expand All @@ -321,7 +325,7 @@ UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
}

/* Browse for application */
void browse(HWND window, char *current, unsigned long flags, ...) {
void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
if (! window) return;

va_list arg;
Expand All @@ -332,31 +336,31 @@ void browse(HWND window, char *current, unsigned long flags, ...) {
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFilter = (char *) HeapAlloc(GetProcessHeap(), 0, bufsize);
ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
/* XXX: Escaping nulls with FormatMessage is tricky */
if (ofn.lpstrFilter) {
ZeroMemory((void *) ofn.lpstrFilter, bufsize);
len = 0;
/* "Applications" + NULL + "*.exe" + NULL */
va_start(arg, flags);
while (i = va_arg(arg, int)) {
char *localised = message_string(i);
_snprintf_s((char *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
len += strlen(localised) + 1;
TCHAR *localised = message_string(i);
_sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
len += _tcslen(localised) + 1;
LocalFree(localised);
char *filter = browse_filter(i);
_snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, "%s", filter);
len += strlen(filter) + 1;
TCHAR *filter = browse_filter(i);
_sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
len += _tcslen(filter) + 1;
}
va_end(arg);
/* Remainder of the buffer is already zeroed */
}
ofn.lpstrFile = new char[MAX_PATH];
ofn.lpstrFile = new TCHAR[MAX_PATH];
if (flags & OFN_NOVALIDATE) {
/* Directory hack. */
_snprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, ":%s:", message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
_sntprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
}
else _snprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, "%s", current);
else _sntprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, _T("%s"), current);
ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
Expand All @@ -379,7 +383,7 @@ INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
/* Button was pressed or control was controlled. */
case WM_COMMAND:
HWND dlg;
char buffer[MAX_PATH];
TCHAR buffer[MAX_PATH];

switch (LOWORD(w)) {
/* Browse for application. */
Expand Down Expand Up @@ -455,14 +459,14 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {

/* Application tab. */
tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
tab.cchTextMax = (int) strlen(tab.pszText);
tab.cchTextMax = (int) _tcslen(tab.pszText);
SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
tablist[NSSM_TAB_APPLICATION] = CreateDialog(0, MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);

/* Shutdown tab. */
tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
tab.cchTextMax = (int) strlen(tab.pszText);
tab.cchTextMax = (int) _tcslen(tab.pszText);
SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
tablist[NSSM_TAB_SHUTDOWN] = CreateDialog(0, MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
Expand All @@ -478,7 +482,7 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {

/* Restart tab. */
tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
tab.cchTextMax = (int) strlen(tab.pszText);
tab.cchTextMax = (int) _tcslen(tab.pszText);
SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
tablist[NSSM_TAB_EXIT] = CreateDialog(0, MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
Expand All @@ -494,14 +498,14 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {

/* I/O tab. */
tab.pszText = message_string(NSSM_GUI_TAB_IO);
tab.cchTextMax = (int) strlen(tab.pszText) + 1;
tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
tablist[NSSM_TAB_IO] = CreateDialog(0, MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);

/* Environment tab. */
tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
tab.cchTextMax = (int) strlen(tab.pszText) + 1;
tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
tablist[NSSM_TAB_ENVIRONMENT] = CreateDialog(0, MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
Expand Down
2 changes: 1 addition & 1 deletion gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <commctrl.h>
#include "resource.h"

int nssm_gui(int, char *);
int nssm_gui(int, TCHAR *);
void centre_window(HWND);
int install(HWND);
int remove(HWND);
Expand Down
4 changes: 2 additions & 2 deletions imports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ imports_t imports;
absolutely need. If we later add some indispensible imports we can
return non-zero here to force an application exit.
*/
HMODULE get_dll(const char *dll, unsigned long *error) {
HMODULE get_dll(const TCHAR *dll, unsigned long *error) {
*error = 0;

HMODULE ret = LoadLibrary(dll);
Expand Down Expand Up @@ -38,7 +38,7 @@ int get_imports() {

ZeroMemory(&imports, sizeof(imports));

imports.kernel32 = get_dll("kernel32.dll", &error);
imports.kernel32 = get_dll(_T("kernel32.dll"), &error);
if (imports.kernel32) {
imports.AttachConsole = (AttachConsole_ptr) get_import(imports.kernel32, "AttachConsole", &error);
if (! imports.AttachConsole) {
Expand Down
2 changes: 1 addition & 1 deletion imports.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ typedef struct {
WakeConditionVariable_ptr WakeConditionVariable;
} imports_t;

HMODULE get_dll(const char *, unsigned long *);
HMODULE get_dll(const TCHAR *, unsigned long *);
FARPROC get_import(HMODULE, const char *, unsigned long *);
int get_imports();
void free_imports();
Expand Down
Loading

0 comments on commit 5b9e64a

Please sign in to comment.