diff --git a/src/iisnode/cmoduleconfiguration.cpp b/src/iisnode/cmoduleconfiguration.cpp index a01ea031..826fe633 100644 --- a/src/iisnode/cmoduleconfiguration.cpp +++ b/src/iisnode/cmoduleconfiguration.cpp @@ -690,39 +690,11 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context, } else if (0 == strcmpi(keyStart, "nodeProcessCommandLine")) { - if (config->nodeProcessCommandLine) - { - delete [] config->nodeProcessCommandLine; - config->nodeProcessCommandLine = NULL; - } - - ErrorIf(NULL == (config->nodeProcessCommandLine = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY); - if (valueStart) - { - strcpy(config->nodeProcessCommandLine, valueStart); - } - else - { - strcpy(config->nodeProcessCommandLine, ""); - } + CheckError(GetString(valueStart, &config->nodeProcessCommandLine)); } else if (0 == strcmpi(keyStart, "interceptor")) { - if (config->interceptor) - { - delete [] config->interceptor; - config->interceptor = NULL; - } - - ErrorIf(NULL == (config->interceptor = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY); - if (valueStart) - { - strcpy(config->interceptor, valueStart); - } - else - { - strcpy(config->interceptor, ""); - } + CheckError(GetString(valueStart, &config->interceptor)); } return S_OK; @@ -1036,7 +1008,6 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat HRESULT hr; CModuleConfiguration* c = NULL; IAppHostElement* section = NULL; - LPWSTR commandLine = NULL; size_t i; CheckNull(config); @@ -1074,28 +1045,14 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat CheckError(GetBOOL(section, L"enableXFF", &c->enableXFF)); CheckError(GetString(section, L"promoteServerVars", &c->promoteServerVarsRaw)); CheckError(GetString(section, L"configOverrides", &c->configOverrides)); + CheckError(GetString(section, L"nodeProcessCommandLine", &c->nodeProcessCommandLine)); + CheckError(GetString(section, L"interceptor", &c->interceptor)); // debuggerPathSegment CheckError(GetString(section, L"debuggerPathSegment", &c->debuggerPathSegment)); c->debuggerPathSegmentLength = wcslen(c->debuggerPathSegment); - // nodeProcessCommandLine - - CheckError(GetString(section, L"nodeProcessCommandLine", &commandLine)); - ErrorIf(NULL == (c->nodeProcessCommandLine = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY); - ErrorIf(0 != wcstombs_s(&i, c->nodeProcessCommandLine, (size_t)MAX_PATH, commandLine, _TRUNCATE), ERROR_INVALID_PARAMETER); - delete [] commandLine; - commandLine = NULL; - - // interceptor - - CheckError(GetString(section, L"interceptor", &commandLine)); - ErrorIf(NULL == (c->interceptor = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY); - ErrorIf(0 != wcstombs_s(&i, c->interceptor, (size_t)MAX_PATH, commandLine, _TRUNCATE), ERROR_INVALID_PARAMETER); - delete [] commandLine; - commandLine = NULL; - // apply config setting overrides from the optional YAML configuration file CheckError(CModuleConfiguration::ApplyYamlConfigOverrides(context, c)); @@ -1129,12 +1086,6 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat section = NULL; } - if (NULL != commandLine) - { - delete [] commandLine; - commandLine = NULL; - } - if (NULL != c) { delete c; @@ -1164,12 +1115,12 @@ DWORD CModuleConfiguration::GetNodeProcessCountPerApplication(IHttpContext* ctx) GETCONFIG(nodeProcessCountPerApplication) } -LPCTSTR CModuleConfiguration::GetNodeProcessCommandLine(IHttpContext* ctx) +LPWSTR CModuleConfiguration::GetNodeProcessCommandLine(IHttpContext* ctx) { GETCONFIG(nodeProcessCommandLine) } -LPCTSTR CModuleConfiguration::GetInterceptor(IHttpContext* ctx) +LPWSTR CModuleConfiguration::GetInterceptor(IHttpContext* ctx) { GETCONFIG(interceptor) } diff --git a/src/iisnode/cmoduleconfiguration.h b/src/iisnode/cmoduleconfiguration.h index d5ca2459..a7f75626 100644 --- a/src/iisnode/cmoduleconfiguration.h +++ b/src/iisnode/cmoduleconfiguration.h @@ -9,8 +9,8 @@ class CModuleConfiguration : public IHttpStoredContext DWORD asyncCompletionThreadCount; DWORD nodeProcessCountPerApplication; - LPTSTR nodeProcessCommandLine; - LPTSTR interceptor; + LPWSTR nodeProcessCommandLine; + LPWSTR interceptor; DWORD maxConcurrentRequestsPerProcess; DWORD maxNamedPipeConnectionRetry; DWORD namedPipeConnectionRetryDelay; @@ -70,8 +70,8 @@ class CModuleConfiguration : public IHttpStoredContext static DWORD GetAsyncCompletionThreadCount(IHttpContext* ctx); static DWORD GetNodeProcessCountPerApplication(IHttpContext* ctx); - static LPCTSTR GetNodeProcessCommandLine(IHttpContext* ctx); - static LPCTSTR GetInterceptor(IHttpContext* ctx); + static LPWSTR GetNodeProcessCommandLine(IHttpContext* ctx); + static LPWSTR GetInterceptor(IHttpContext* ctx); static DWORD GetMaxConcurrentRequestsPerProcess(IHttpContext* ctx); static DWORD GetMaxNamedPipeConnectionRetry(IHttpContext* ctx); static DWORD GetNamedPipeConnectionRetryDelay(IHttpContext* ctx); diff --git a/src/iisnode/cnodeprocess.cpp b/src/iisnode/cnodeprocess.cpp index f4d06965..7be1637b 100644 --- a/src/iisnode/cnodeprocess.cpp +++ b/src/iisnode/cnodeprocess.cpp @@ -45,20 +45,18 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) HRESULT hr; UUID uuid; RPC_CSTR suuid = NULL; - LPTSTR fullCommandLine = NULL; - LPCTSTR coreCommandLine; - LPCTSTR interceptor; + LPWSTR fullCommandLine = NULL; + LPCWSTR coreCommandLine; + LPCWSTR interceptor; PCWSTR scriptName; - size_t coreCommandLineLength, scriptNameLength, scriptNameLengthW, interceptorLength; PROCESS_INFORMATION processInformation; DWORD exitCode = S_OK; LPCH newEnvironment = NULL; DWORD flags; HANDLE job; PWSTR currentDirectory = NULL; - PSTR currentDirectoryA = NULL; + PWSTR scriptTranslated = NULL; DWORD currentDirectorySize = 0; - DWORD currentDirectorySizeA = 0; CNodeApplication* app = this->GetProcessManager()->GetApplication(); RtlZeroMemory(&processInformation, sizeof processInformation); @@ -80,53 +78,44 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) // build the full command line for the node.js process interceptor = CModuleConfiguration::GetInterceptor(context); - interceptorLength = strlen(interceptor); coreCommandLine = CModuleConfiguration::GetNodeProcessCommandLine(context); scriptName = this->GetProcessManager()->GetApplication()->GetScriptName(); - coreCommandLineLength = _tcslen(coreCommandLine); - scriptNameLengthW = wcslen(scriptName) + 1; - ErrorIf(0 != wcstombs_s(&scriptNameLength, NULL, 0, scriptName, _TRUNCATE), ERROR_CAN_NOT_COMPLETE); // allocate memory for command line to allow for debugging options plus interceptor plus spaces and enclosing the script name in quotes - ErrorIf(NULL == (fullCommandLine = new TCHAR[coreCommandLineLength + interceptorLength + scriptNameLength + 256]), ERROR_NOT_ENOUGH_MEMORY); - _tcscpy(fullCommandLine, coreCommandLine); - DWORD offset = 0; + ErrorIf(NULL == (fullCommandLine = new WCHAR[wcslen(coreCommandLine) + wcslen(interceptor) + wcslen(scriptName) + 256]), ERROR_NOT_ENOUGH_MEMORY); + wcscpy(fullCommandLine, coreCommandLine); // add debug options if (app->IsDebuggee()) { - char buffer[64]; + WCHAR buffer[64]; if (ND_DEBUG_BRK == app->GetDebugCommand()) { - sprintf(buffer, " --debug-brk=%d ", app->GetDebugPort()); + swprintf(buffer, L" --debug-brk=%d ", app->GetDebugPort()); } else if (ND_DEBUG == app->GetDebugCommand()) { - sprintf(buffer, " --debug=%d ", app->GetDebugPort()); + swprintf(buffer, L" --debug=%d ", app->GetDebugPort()); } else { CheckError(ERROR_INVALID_PARAMETER); } - _tcscat(fullCommandLine, buffer); - offset += strlen(buffer); + wcscat(fullCommandLine, buffer); } if (!app->IsDebugger()) { // add interceptor - _tcscat(fullCommandLine, _T(" ")); - offset += 1; - _tcscat(fullCommandLine, interceptor); - offset += interceptorLength; + wcscat(fullCommandLine, L" "); + wcscat(fullCommandLine, interceptor); } // add application entry point - _tcscat(fullCommandLine, _T(" \"")); - offset += 2; - ErrorIf(0 != wcstombs_s(&scriptNameLength, fullCommandLine + coreCommandLineLength + offset, scriptNameLength, scriptName, _TRUNCATE), ERROR_CAN_NOT_COMPLETE); - _tcscat(fullCommandLine, _T("\"")); + wcscat(fullCommandLine, L" \""); + wcscat(fullCommandLine, scriptName); + wcscat(fullCommandLine, L"\""); // create the environment block for the node.js process @@ -139,18 +128,17 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) // establish the current directory for node.exe process to be the same as the location of the application *.js file // (in case of the debugger process, it is still the debuggee application file) - currentDirectory = (PWSTR)context->GetScriptTranslated(¤tDirectorySize); - while (currentDirectorySize && currentDirectory[currentDirectorySize] != L'\\' && currentDirectory[currentDirectorySize] != L'/') + scriptTranslated = (PWSTR)context->GetScriptTranslated(¤tDirectorySize); + while (currentDirectorySize && scriptTranslated[currentDirectorySize] != L'\\' && scriptTranslated[currentDirectorySize] != L'/') currentDirectorySize--; - ErrorIf(0 == (currentDirectorySizeA = WideCharToMultiByte(CP_ACP, 0, currentDirectory, currentDirectorySize, NULL, 0, NULL, NULL)), E_FAIL); - ErrorIf(NULL == (currentDirectoryA = new char[currentDirectorySize + 1]), ERROR_NOT_ENOUGH_MEMORY); - ErrorIf(currentDirectorySizeA != WideCharToMultiByte(CP_ACP, 0, currentDirectory, currentDirectorySize, currentDirectoryA, currentDirectorySizeA, NULL, NULL), E_FAIL); - currentDirectoryA[currentDirectorySizeA] = '\0'; + ErrorIf(NULL == (currentDirectory = new WCHAR[wcslen(scriptTranslated) + 1]), ERROR_NOT_ENOUGH_MEMORY); + wcscpy(currentDirectory, scriptTranslated); + currentDirectory[currentDirectorySize] = L'\0'; // create startup info for the node.js process RtlZeroMemory(&this->startupInfo, sizeof this->startupInfo); - GetStartupInfo(&startupInfo); + GetStartupInfoW(&startupInfo); CheckError(this->CreateStdHandles(context)); // create process watcher thread in a suspended state @@ -172,7 +160,7 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) flags |= CREATE_BREAKAWAY_FROM_JOB; } - if(!CreateProcess( + if(!CreateProcessW( NULL, fullCommandLine, NULL, @@ -180,7 +168,7 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) TRUE, flags, newEnvironment, - currentDirectoryA, + currentDirectory, &this->startupInfo, &processInformation)) { @@ -211,8 +199,8 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) // clean up - delete [] currentDirectoryA; - currentDirectoryA = NULL; + delete [] currentDirectory; + currentDirectory = NULL; delete [] newEnvironment; newEnvironment = NULL; delete [] fullCommandLine; @@ -245,10 +233,10 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context) L"iisnode failed to initialize a new node.exe process", WINEVENT_LEVEL_ERROR); } - if (currentDirectoryA) + if (currentDirectory) { - delete [] currentDirectoryA; - currentDirectoryA = NULL; + delete [] currentDirectory; + currentDirectory = NULL; } if (suuid != NULL) diff --git a/src/iisnode/cnodeprocess.h b/src/iisnode/cnodeprocess.h index 14ec87b3..95eb7f63 100644 --- a/src/iisnode/cnodeprocess.h +++ b/src/iisnode/cnodeprocess.h @@ -16,7 +16,7 @@ class CNodeProcess HANDLE processWatcher; DWORD maxConcurrentRequestsPerProcess; BOOL isClosing; - STARTUPINFO startupInfo; + STARTUPINFOW startupInfo; BOOL hasProcessExited; OVERLAPPED overlapped; CConnectionPool connectionPool; diff --git a/src/iisnode/cprotocolbridge.cpp b/src/iisnode/cprotocolbridge.cpp index b2cf4b9e..ba535c29 100644 --- a/src/iisnode/cprotocolbridge.cpp +++ b/src/iisnode/cprotocolbridge.cpp @@ -160,25 +160,12 @@ BOOL CProtocolBridge::SendIisnodeError(IHttpContext* httpCtx, HRESULT hr) break; case IISNODE_ERROR_UNABLE_TO_START_NODE_EXE: - LPCTSTR commandLine = CModuleConfiguration::GetNodeProcessCommandLine(httpCtx); - char* errorMessage; - if (NULL == (errorMessage = (char*)httpCtx->AllocateRequestMemory(strlen(commandLine) + 512))) - { - errorMessage = + char* errorMessage = "The iisnode module is unable to start the node.exe process. Make sure the node.exe executable is available " "at the location specified in the " "system.webServer/iisnode/@nodeProcessCommandLine element of web.config. " "By default node.exe is expected to be installed in %ProgramFiles%\\nodejs folder on x86 systems and " "%ProgramFiles(x86)%\\nodejs folder on x64 systems."; - } - else - { - sprintf(errorMessage, - "The iisnode module is unable to start the node.exe process. Make sure the node.exe executable is available " - "at the location specified in the " - "system.webServer/iisnode/@nodeProcessCommandLine element of web.config. " - "The command line iisnode attempted to run was:

%s", commandLine); - } CProtocolBridge::SendSyncResponse( httpCtx,