Browse Source

Adjust buffer sizes.

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.
Iain Patterson 8 years ago
parent
commit
2994e17c24
6 changed files with 56 additions and 22 deletions
  1. 8 5
      gui.cpp
  2. 5 5
      io.cpp
  3. 31 0
      nssm.h
  4. 1 1
      process.cpp
  5. 2 2
      registry.cpp
  6. 9 9
      service.h

+ 8 - 5
gui.cpp

@@ -746,14 +746,17 @@ void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
     va_end(arg);
     /* Remainder of the buffer is already zeroed */
   }
-  ofn.lpstrFile = new TCHAR[MAX_PATH];
+  ofn.lpstrFile = new TCHAR[PATH_LENGTH];
   if (flags & OFN_NOVALIDATE) {
     /* Directory hack. */
-    _sntprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
+    _sntprintf_s(ofn.lpstrFile, _countof(ofn.lpstrFile), _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
+    ofn.nMaxFile = DIR_LENGTH;
   }
-  else _sntprintf_s(ofn.lpstrFile, MAX_PATH, _TRUNCATE, _T("%s"), current);
+  else {
+    _sntprintf_s(ofn.lpstrFile, _countof(ofn.lpstrFile), _TRUNCATE, _T("%s"), current);
+    ofn.nMaxFile = PATH_LENGTH;
+  }
   ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
-  ofn.nMaxFile = MAX_PATH;
   ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
 
   if (GetOpenFileName(&ofn)) {
@@ -774,7 +777,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;
-      TCHAR buffer[MAX_PATH];
+      TCHAR buffer[PATH_LENGTH];
       unsigned char enabled;
 
       switch (LOWORD(w)) {

+ 5 - 5
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);
     return 1;
   }
-  switch (expand_parameter(key, value, path, MAX_PATH, true, false)) {
+  switch (expand_parameter(key, value, path, PATH_LENGTH, true, false)) {
     case 0: if (! path[0]) return 0; break; /* OK. */
     default: return 2; /* Error. */
   }
@@ -165,10 +165,10 @@ static void rotated_filename(TCHAR *path, TCHAR *rotated, unsigned long rotated_
     GetSystemTime(st);
   }
 
-  TCHAR buffer[MAX_PATH];
+  TCHAR buffer[PATH_LENGTH];
   memmove(buffer, path, sizeof(buffer));
   TCHAR *ext = PathFindExtension(buffer);
-  TCHAR extension[MAX_PATH];
+  TCHAR extension[PATH_LENGTH];
   _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);
   *ext = _T('\0');
   _sntprintf_s(rotated, rotated_len, _TRUNCATE, _T("%s%s"), buffer, extension);
@@ -227,7 +227,7 @@ void rotate_file(TCHAR *service_name, TCHAR *path, unsigned long seconds, unsign
   /* Get new filename. */
   FileTimeToSystemTime(&info.ftLastWriteTime, &st);
 
-  TCHAR rotated[MAX_PATH];
+  TCHAR rotated[PATH_LENGTH];
   rotated_filename(path, rotated, _countof(rotated), &st);
 
   /* Rotate. */
@@ -507,7 +507,7 @@ unsigned long WINAPI log_and_rotate(void *arg) {
 
           /* Rotate. */
           *logger->rotate_online = NSSM_ROTATE_ONLINE;
-          TCHAR rotated[MAX_PATH];
+          TCHAR rotated[PATH_LENGTH];
           rotated_filename(logger->path, rotated, _countof(rotated), 0);
 
           /*

+ 31 - 0
nssm.h

@@ -1,6 +1,37 @@
 #ifndef NSSM_H
 #define NSSM_H
 
+/*
+  MSDN says, basically, that the maximum length of a path is 260 characters,
+  which is represented by the constant MAX_PATH.  Except when it isn't.
+
+  The maximum length of a directory path is MAX_PATH - 12 because it must be
+  possible to create a file in 8.3 format under any valid directory.
+
+  Unicode versions of filesystem API functions accept paths up to 32767
+  characters if the first four (wide) characters are L"\\?\" and each component
+  of the path, separated by L"\", does not exceed the value of
+  lpMaximumComponentLength returned by GetVolumeInformation(), which is
+  probably 255.  But might not be.
+
+  Relative paths are always limited to MAX_PATH because the L"\\?\" prefix
+  is not valid for a relative path.
+
+  Note that we don't care about the last two paragraphs because we're only
+  concerned with allocating buffers big enough to store valid paths.  If the
+  user tries to store invalid paths they will fit in the buffers but the
+  application will fail.  The reason for the failure will end up in the
+  event log and the user will realise the mistake.
+
+  So that's that cleared up, then.
+*/
+#ifdef UNICODE
+#define PATH_LENGTH 32767
+#else
+#define PATH_LENGTH MAX_PATH
+#endif
+#define DIR_LENGTH PATH_LENGTH - 12
+
 #define _WIN32_WINNT 0x0500
 #include <fcntl.h>
 #include <io.h>

+ 1 - 1
process.cpp

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

+ 2 - 2
registry.cpp

@@ -17,7 +17,7 @@ int create_messages() {
   }
 
   /* Get path of this program */
-  TCHAR path[MAX_PATH];
+  TCHAR path[PATH_LENGTH];
   GetModuleFileName(0, path, _countof(path));
 
   /* Try to register the module but don't worry so much on failure */
@@ -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;
 
   /* Change to startup directory in case stdout/stderr are relative paths. */
-  TCHAR cwd[MAX_PATH];
+  TCHAR cwd[PATH_LENGTH];
   GetCurrentDirectory(_countof(cwd), cwd);
   SetCurrentDirectory(service->dir);
 

+ 9 - 9
service.h

@@ -6,16 +6,16 @@
 /*
   MSDN says the commandline in CreateProcess() is limited to 32768 characters
   and the application name to MAX_PATH.
+  A service name and service display name are limited to 256 characters.
   A registry key is limited to 255 characters.
   A registry value is limited to 16383 characters.
   Therefore we limit the service name to accommodate the path under HKLM.
 */
-#define EXE_LENGTH MAX_PATH
+#define EXE_LENGTH PATH_LENGTH
 #define CMD_LENGTH 32768
 #define KEY_LENGTH 255
 #define VALUE_LENGTH 16383
-#define SERVICE_NAME_LENGTH KEY_LENGTH - 55
-#define SERVICE_DISPLAYNAME_LENGTH 256
+#define SERVICE_NAME_LENGTH 256
 
 #define ACTION_LEN 16
 
@@ -35,7 +35,7 @@
 typedef struct {
   bool native;
   TCHAR name[SERVICE_NAME_LENGTH];
-  TCHAR displayname[SERVICE_DISPLAYNAME_LENGTH];
+  TCHAR displayname[SERVICE_NAME_LENGTH];
   TCHAR description[VALUE_LENGTH];
   unsigned long startup;
   TCHAR *username;
@@ -43,28 +43,28 @@ typedef struct {
   TCHAR *password;
   size_t passwordlen;
   unsigned long type;
-  TCHAR image[MAX_PATH];
+  TCHAR image[PATH_LENGTH];
   TCHAR exe[EXE_LENGTH];
   TCHAR flags[VALUE_LENGTH];
-  TCHAR dir[MAX_PATH];
+  TCHAR dir[DIR_LENGTH];
   TCHAR *env;
   __int64 affinity;
   unsigned long envlen;
   TCHAR *env_extra;
   unsigned long env_extralen;
   unsigned long priority;
-  TCHAR stdin_path[MAX_PATH];
+  TCHAR stdin_path[PATH_LENGTH];
   unsigned long stdin_sharing;
   unsigned long stdin_disposition;
   unsigned long stdin_flags;
-  TCHAR stdout_path[MAX_PATH];
+  TCHAR stdout_path[PATH_LENGTH];
   unsigned long stdout_sharing;
   unsigned long stdout_disposition;
   unsigned long stdout_flags;
   HANDLE stdout_pipe;
   HANDLE stdout_thread;
   unsigned long stdout_tid;
-  TCHAR stderr_path[MAX_PATH];
+  TCHAR stderr_path[PATH_LENGTH];
   unsigned long stderr_sharing;
   unsigned long stderr_disposition;
   unsigned long stderr_flags;