Adjust buffer sizes.
authorIain Patterson <me@iain.cx>
Wed, 15 Jan 2014 21:27:32 +0000 (21:27 +0000)
committerIain Patterson <me@iain.cx>
Wed, 15 Jan 2014 21:27:32 +0000 (21:27 +0000)
Unicode applications can under certain circumstances access paths longer
than MAX_PATH characters.  Service names are limited to 256 characters.

Adjust our buffers to suit.

gui.cpp
io.cpp
nssm.h
process.cpp
registry.cpp
service.h

diff --git a/gui.cpp b/gui.cpp
index 64382f4..3f34943 100644 (file)
--- a/gui.cpp
+++ b/gui.cpp
@@ -746,14 +746,17 @@ void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
     va_end(arg);\r
     /* Remainder of the buffer is already zeroed */\r
   }\r
-  ofn.lpstrFile = new TCHAR[MAX_PATH];\r
+  ofn.lpstrFile = new TCHAR[PATH_LENGTH];\r
   if (flags & OFN_NOVALIDATE) {\r
     /* Directory hack. */\r
-    _sntprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));\r
+    _sntprintf_s(ofn.lpstrFile, _countof(ofn.lpstrFile), _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));\r
+    ofn.nMaxFile = DIR_LENGTH;\r
   }\r
-  else _sntprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, _T("%s"), current);\r
+  else {
+    _sntprintf_s(ofn.lpstrFile, _countof(ofn.lpstrFile), _TRUNCATE, _T("%s"), current);\r
+    ofn.nMaxFile = PATH_LENGTH;\r
+  }
   ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);\r
-  ofn.nMaxFile = MAX_PATH;\r
   ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;\r
 \r
   if (GetOpenFileName(&ofn)) {\r
@@ -774,7 +777,7 @@ INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
     /* Button was pressed or control was controlled. */\r
     case WM_COMMAND:\r
       HWND dlg;\r
-      TCHAR buffer[MAX_PATH];\r
+      TCHAR buffer[PATH_LENGTH];\r
       unsigned char enabled;\r
 \r
       switch (LOWORD(w)) {\r
diff --git a/io.cpp b/io.cpp
index 2578800..3f80810 100644 (file)
--- a/io.cpp
+++ b/io.cpp
@@ -71,7 +71,7 @@ int get_createfile_parameters(HKEY key, TCHAR *prefix, TCHAR *path, unsigned lon
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, prefix, _T("get_createfile_parameters()"), 0);\r
     return 1;\r
   }\r
-  switch (expand_parameter(key, value, path, MAX_PATH, true, false)) {\r
+  switch (expand_parameter(key, value, path, PATH_LENGTH, true, false)) {\r
     case 0: if (! path[0]) return 0; break; /* OK. */\r
     default: return 2; /* Error. */\r
   }\r
@@ -165,10 +165,10 @@ static void rotated_filename(TCHAR *path, TCHAR *rotated, unsigned long rotated_
     GetSystemTime(st);\r
   }\r
 \r
-  TCHAR buffer[MAX_PATH];\r
+  TCHAR buffer[PATH_LENGTH];\r
   memmove(buffer, path, sizeof(buffer));\r
   TCHAR *ext = PathFindExtension(buffer);\r
-  TCHAR extension[MAX_PATH];\r
+  TCHAR extension[PATH_LENGTH];\r
   _sntprintf_s(extension, _countof(extension), _TRUNCATE, _T("-%04u%02u%02uT%02u%02u%02u.%03u%s"), st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds, ext);\r
   *ext = _T('\0');\r
   _sntprintf_s(rotated, rotated_len, _TRUNCATE, _T("%s%s"), buffer, extension);\r
@@ -227,7 +227,7 @@ void rotate_file(TCHAR *service_name, TCHAR *path, unsigned long seconds, unsign
   /* Get new filename. */\r
   FileTimeToSystemTime(&info.ftLastWriteTime, &st);\r
 \r
-  TCHAR rotated[MAX_PATH];\r
+  TCHAR rotated[PATH_LENGTH];\r
   rotated_filename(path, rotated, _countof(rotated), &st);\r
 \r
   /* Rotate. */\r
@@ -507,7 +507,7 @@ unsigned long WINAPI log_and_rotate(void *arg) {
 \r
           /* Rotate. */\r
           *logger->rotate_online = NSSM_ROTATE_ONLINE;\r
-          TCHAR rotated[MAX_PATH];\r
+          TCHAR rotated[PATH_LENGTH];\r
           rotated_filename(logger->path, rotated, _countof(rotated), 0);\r
 \r
           /*\r
diff --git a/nssm.h b/nssm.h
index 8e82d59..1ad2b94 100644 (file)
--- a/nssm.h
+++ b/nssm.h
@@ -1,6 +1,37 @@
 #ifndef NSSM_H\r
 #define NSSM_H\r
 \r
+/*\r
+  MSDN says, basically, that the maximum length of a path is 260 characters,\r
+  which is represented by the constant MAX_PATH.  Except when it isn't.\r
+\r
+  The maximum length of a directory path is MAX_PATH - 12 because it must be\r
+  possible to create a file in 8.3 format under any valid directory.\r
+\r
+  Unicode versions of filesystem API functions accept paths up to 32767\r
+  characters if the first four (wide) characters are L"\\?\" and each component\r
+  of the path, separated by L"\", does not exceed the value of\r
+  lpMaximumComponentLength returned by GetVolumeInformation(), which is\r
+  probably 255.  But might not be.\r
+\r
+  Relative paths are always limited to MAX_PATH because the L"\\?\" prefix\r
+  is not valid for a relative path.\r
+\r
+  Note that we don't care about the last two paragraphs because we're only\r
+  concerned with allocating buffers big enough to store valid paths.  If the\r
+  user tries to store invalid paths they will fit in the buffers but the\r
+  application will fail.  The reason for the failure will end up in the\r
+  event log and the user will realise the mistake.\r
+\r
+  So that's that cleared up, then.\r
+*/\r
+#ifdef UNICODE\r
+#define PATH_LENGTH 32767\r
+#else\r
+#define PATH_LENGTH MAX_PATH\r
+#endif\r
+#define DIR_LENGTH PATH_LENGTH - 12\r
+\r
 #define _WIN32_WINNT 0x0500\r
 #include <fcntl.h>\r
 #include <io.h>\r
index 69aea03..19b893a 100644 (file)
@@ -314,7 +314,7 @@ void kill_process_tree(nssm_service_t *service, unsigned long pid, unsigned long
            -1 on error.
 */
 int test_environment(TCHAR *env) {
-  TCHAR path[MAX_PATH];
+  TCHAR path[PATH_LENGTH];
   GetModuleFileName(0, path, _countof(path));
   STARTUPINFO si;
   ZeroMemory(&si, sizeof(si));
index 0cb552f..158158d 100644 (file)
@@ -17,7 +17,7 @@ int create_messages() {
   }\r
 \r
   /* Get path of this program */\r
-  TCHAR path[MAX_PATH];\r
+  TCHAR path[PATH_LENGTH];\r
   GetModuleFileName(0, path, _countof(path));\r
 \r
   /* Try to register the module but don't worry so much on failure */\r
@@ -609,7 +609,7 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) {
   if (get_number(key, NSSM_REG_ROTATE_BYTES_HIGH, &service->rotate_bytes_high, false) != 1) service->rotate_bytes_high = 0;\r
 \r
   /* Change to startup directory in case stdout/stderr are relative paths. */\r
-  TCHAR cwd[MAX_PATH];\r
+  TCHAR cwd[PATH_LENGTH];\r
   GetCurrentDirectory(_countof(cwd), cwd);\r
   SetCurrentDirectory(service->dir);\r
 \r
index 0d37757..6da55f3 100644 (file)
--- a/service.h
+++ b/service.h
@@ -6,16 +6,16 @@
 /*\r
   MSDN says the commandline in CreateProcess() is limited to 32768 characters\r
   and the application name to MAX_PATH.\r
+  A service name and service display name are limited to 256 characters.\r
   A registry key is limited to 255 characters.\r
   A registry value is limited to 16383 characters.\r
   Therefore we limit the service name to accommodate the path under HKLM.\r
 */\r
-#define EXE_LENGTH MAX_PATH\r
+#define EXE_LENGTH PATH_LENGTH\r
 #define CMD_LENGTH 32768\r
 #define KEY_LENGTH 255\r
 #define VALUE_LENGTH 16383\r
-#define SERVICE_NAME_LENGTH KEY_LENGTH - 55\r
-#define SERVICE_DISPLAYNAME_LENGTH 256\r
+#define SERVICE_NAME_LENGTH 256\r
 \r
 #define ACTION_LEN 16\r
 \r
@@ -35,7 +35,7 @@
 typedef struct {\r
   bool native;\r
   TCHAR name[SERVICE_NAME_LENGTH];\r
-  TCHAR displayname[SERVICE_DISPLAYNAME_LENGTH];\r
+  TCHAR displayname[SERVICE_NAME_LENGTH];\r
   TCHAR description[VALUE_LENGTH];\r
   unsigned long startup;\r
   TCHAR *username;\r
@@ -43,28 +43,28 @@ typedef struct {
   TCHAR *password;\r
   size_t passwordlen;\r
   unsigned long type;\r
-  TCHAR image[MAX_PATH];\r
+  TCHAR image[PATH_LENGTH];\r
   TCHAR exe[EXE_LENGTH];\r
   TCHAR flags[VALUE_LENGTH];\r
-  TCHAR dir[MAX_PATH];\r
+  TCHAR dir[DIR_LENGTH];\r
   TCHAR *env;\r
   __int64 affinity;\r
   unsigned long envlen;\r
   TCHAR *env_extra;\r
   unsigned long env_extralen;\r
   unsigned long priority;\r
-  TCHAR stdin_path[MAX_PATH];\r
+  TCHAR stdin_path[PATH_LENGTH];\r
   unsigned long stdin_sharing;\r
   unsigned long stdin_disposition;\r
   unsigned long stdin_flags;\r
-  TCHAR stdout_path[MAX_PATH];\r
+  TCHAR stdout_path[PATH_LENGTH];\r
   unsigned long stdout_sharing;\r
   unsigned long stdout_disposition;\r
   unsigned long stdout_flags;\r
   HANDLE stdout_pipe;\r
   HANDLE stdout_thread;\r
   unsigned long stdout_tid;\r
-  TCHAR stderr_path[MAX_PATH];\r
+  TCHAR stderr_path[PATH_LENGTH];\r
   unsigned long stderr_sharing;\r
   unsigned long stderr_disposition;\r
   unsigned long stderr_flags;\r