Skip to content

Commit 86564d3

Browse files
committed
fix #179: support for unicode file names
1 parent a1a8c26 commit 86564d3

File tree

5 files changed

+40
-114
lines changed

5 files changed

+40
-114
lines changed

Diff for: src/iisnode/cmoduleconfiguration.cpp

+6-55
Original file line numberDiff line numberDiff line change
@@ -690,39 +690,11 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context,
690690
}
691691
else if (0 == strcmpi(keyStart, "nodeProcessCommandLine"))
692692
{
693-
if (config->nodeProcessCommandLine)
694-
{
695-
delete [] config->nodeProcessCommandLine;
696-
config->nodeProcessCommandLine = NULL;
697-
}
698-
699-
ErrorIf(NULL == (config->nodeProcessCommandLine = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY);
700-
if (valueStart)
701-
{
702-
strcpy(config->nodeProcessCommandLine, valueStart);
703-
}
704-
else
705-
{
706-
strcpy(config->nodeProcessCommandLine, "");
707-
}
693+
CheckError(GetString(valueStart, &config->nodeProcessCommandLine));
708694
}
709695
else if (0 == strcmpi(keyStart, "interceptor"))
710696
{
711-
if (config->interceptor)
712-
{
713-
delete [] config->interceptor;
714-
config->interceptor = NULL;
715-
}
716-
717-
ErrorIf(NULL == (config->interceptor = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY);
718-
if (valueStart)
719-
{
720-
strcpy(config->interceptor, valueStart);
721-
}
722-
else
723-
{
724-
strcpy(config->interceptor, "");
725-
}
697+
CheckError(GetString(valueStart, &config->interceptor));
726698
}
727699

728700
return S_OK;
@@ -1036,7 +1008,6 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
10361008
HRESULT hr;
10371009
CModuleConfiguration* c = NULL;
10381010
IAppHostElement* section = NULL;
1039-
LPWSTR commandLine = NULL;
10401011
size_t i;
10411012
CheckNull(config);
10421013

@@ -1074,28 +1045,14 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
10741045
CheckError(GetBOOL(section, L"enableXFF", &c->enableXFF));
10751046
CheckError(GetString(section, L"promoteServerVars", &c->promoteServerVarsRaw));
10761047
CheckError(GetString(section, L"configOverrides", &c->configOverrides));
1048+
CheckError(GetString(section, L"nodeProcessCommandLine", &c->nodeProcessCommandLine));
1049+
CheckError(GetString(section, L"interceptor", &c->interceptor));
10771050

10781051
// debuggerPathSegment
10791052

10801053
CheckError(GetString(section, L"debuggerPathSegment", &c->debuggerPathSegment));
10811054
c->debuggerPathSegmentLength = wcslen(c->debuggerPathSegment);
10821055

1083-
// nodeProcessCommandLine
1084-
1085-
CheckError(GetString(section, L"nodeProcessCommandLine", &commandLine));
1086-
ErrorIf(NULL == (c->nodeProcessCommandLine = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY);
1087-
ErrorIf(0 != wcstombs_s(&i, c->nodeProcessCommandLine, (size_t)MAX_PATH, commandLine, _TRUNCATE), ERROR_INVALID_PARAMETER);
1088-
delete [] commandLine;
1089-
commandLine = NULL;
1090-
1091-
// interceptor
1092-
1093-
CheckError(GetString(section, L"interceptor", &commandLine));
1094-
ErrorIf(NULL == (c->interceptor = new char[MAX_PATH]), ERROR_NOT_ENOUGH_MEMORY);
1095-
ErrorIf(0 != wcstombs_s(&i, c->interceptor, (size_t)MAX_PATH, commandLine, _TRUNCATE), ERROR_INVALID_PARAMETER);
1096-
delete [] commandLine;
1097-
commandLine = NULL;
1098-
10991056
// apply config setting overrides from the optional YAML configuration file
11001057

11011058
CheckError(CModuleConfiguration::ApplyYamlConfigOverrides(context, c));
@@ -1129,12 +1086,6 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
11291086
section = NULL;
11301087
}
11311088

1132-
if (NULL != commandLine)
1133-
{
1134-
delete [] commandLine;
1135-
commandLine = NULL;
1136-
}
1137-
11381089
if (NULL != c)
11391090
{
11401091
delete c;
@@ -1164,12 +1115,12 @@ DWORD CModuleConfiguration::GetNodeProcessCountPerApplication(IHttpContext* ctx)
11641115
GETCONFIG(nodeProcessCountPerApplication)
11651116
}
11661117

1167-
LPCTSTR CModuleConfiguration::GetNodeProcessCommandLine(IHttpContext* ctx)
1118+
LPWSTR CModuleConfiguration::GetNodeProcessCommandLine(IHttpContext* ctx)
11681119
{
11691120
GETCONFIG(nodeProcessCommandLine)
11701121
}
11711122

1172-
LPCTSTR CModuleConfiguration::GetInterceptor(IHttpContext* ctx)
1123+
LPWSTR CModuleConfiguration::GetInterceptor(IHttpContext* ctx)
11731124
{
11741125
GETCONFIG(interceptor)
11751126
}

Diff for: src/iisnode/cmoduleconfiguration.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ class CModuleConfiguration : public IHttpStoredContext
99

1010
DWORD asyncCompletionThreadCount;
1111
DWORD nodeProcessCountPerApplication;
12-
LPTSTR nodeProcessCommandLine;
13-
LPTSTR interceptor;
12+
LPWSTR nodeProcessCommandLine;
13+
LPWSTR interceptor;
1414
DWORD maxConcurrentRequestsPerProcess;
1515
DWORD maxNamedPipeConnectionRetry;
1616
DWORD namedPipeConnectionRetryDelay;
@@ -70,8 +70,8 @@ class CModuleConfiguration : public IHttpStoredContext
7070

7171
static DWORD GetAsyncCompletionThreadCount(IHttpContext* ctx);
7272
static DWORD GetNodeProcessCountPerApplication(IHttpContext* ctx);
73-
static LPCTSTR GetNodeProcessCommandLine(IHttpContext* ctx);
74-
static LPCTSTR GetInterceptor(IHttpContext* ctx);
73+
static LPWSTR GetNodeProcessCommandLine(IHttpContext* ctx);
74+
static LPWSTR GetInterceptor(IHttpContext* ctx);
7575
static DWORD GetMaxConcurrentRequestsPerProcess(IHttpContext* ctx);
7676
static DWORD GetMaxNamedPipeConnectionRetry(IHttpContext* ctx);
7777
static DWORD GetNamedPipeConnectionRetryDelay(IHttpContext* ctx);

Diff for: src/iisnode/cnodeprocess.cpp

+28-40
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,18 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
4545
HRESULT hr;
4646
UUID uuid;
4747
RPC_CSTR suuid = NULL;
48-
LPTSTR fullCommandLine = NULL;
49-
LPCTSTR coreCommandLine;
50-
LPCTSTR interceptor;
48+
LPWSTR fullCommandLine = NULL;
49+
LPCWSTR coreCommandLine;
50+
LPCWSTR interceptor;
5151
PCWSTR scriptName;
52-
size_t coreCommandLineLength, scriptNameLength, scriptNameLengthW, interceptorLength;
5352
PROCESS_INFORMATION processInformation;
5453
DWORD exitCode = S_OK;
5554
LPCH newEnvironment = NULL;
5655
DWORD flags;
5756
HANDLE job;
5857
PWSTR currentDirectory = NULL;
59-
PSTR currentDirectoryA = NULL;
58+
PWSTR scriptTranslated = NULL;
6059
DWORD currentDirectorySize = 0;
61-
DWORD currentDirectorySizeA = 0;
6260
CNodeApplication* app = this->GetProcessManager()->GetApplication();
6361

6462
RtlZeroMemory(&processInformation, sizeof processInformation);
@@ -80,53 +78,44 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
8078
// build the full command line for the node.js process
8179

8280
interceptor = CModuleConfiguration::GetInterceptor(context);
83-
interceptorLength = strlen(interceptor);
8481
coreCommandLine = CModuleConfiguration::GetNodeProcessCommandLine(context);
8582
scriptName = this->GetProcessManager()->GetApplication()->GetScriptName();
86-
coreCommandLineLength = _tcslen(coreCommandLine);
87-
scriptNameLengthW = wcslen(scriptName) + 1;
88-
ErrorIf(0 != wcstombs_s(&scriptNameLength, NULL, 0, scriptName, _TRUNCATE), ERROR_CAN_NOT_COMPLETE);
8983
// allocate memory for command line to allow for debugging options plus interceptor plus spaces and enclosing the script name in quotes
90-
ErrorIf(NULL == (fullCommandLine = new TCHAR[coreCommandLineLength + interceptorLength + scriptNameLength + 256]), ERROR_NOT_ENOUGH_MEMORY);
91-
_tcscpy(fullCommandLine, coreCommandLine);
92-
DWORD offset = 0;
84+
ErrorIf(NULL == (fullCommandLine = new WCHAR[wcslen(coreCommandLine) + wcslen(interceptor) + wcslen(scriptName) + 256]), ERROR_NOT_ENOUGH_MEMORY);
85+
wcscpy(fullCommandLine, coreCommandLine);
9386

9487
// add debug options
9588
if (app->IsDebuggee())
9689
{
97-
char buffer[64];
90+
WCHAR buffer[64];
9891

9992
if (ND_DEBUG_BRK == app->GetDebugCommand())
10093
{
101-
sprintf(buffer, " --debug-brk=%d ", app->GetDebugPort());
94+
swprintf(buffer, L" --debug-brk=%d ", app->GetDebugPort());
10295
}
10396
else if (ND_DEBUG == app->GetDebugCommand())
10497
{
105-
sprintf(buffer, " --debug=%d ", app->GetDebugPort());
98+
swprintf(buffer, L" --debug=%d ", app->GetDebugPort());
10699
}
107100
else
108101
{
109102
CheckError(ERROR_INVALID_PARAMETER);
110103
}
111104

112-
_tcscat(fullCommandLine, buffer);
113-
offset += strlen(buffer);
105+
wcscat(fullCommandLine, buffer);
114106
}
115107

116108
if (!app->IsDebugger())
117109
{
118110
// add interceptor
119-
_tcscat(fullCommandLine, _T(" "));
120-
offset += 1;
121-
_tcscat(fullCommandLine, interceptor);
122-
offset += interceptorLength;
111+
wcscat(fullCommandLine, L" ");
112+
wcscat(fullCommandLine, interceptor);
123113
}
124114

125115
// add application entry point
126-
_tcscat(fullCommandLine, _T(" \""));
127-
offset += 2;
128-
ErrorIf(0 != wcstombs_s(&scriptNameLength, fullCommandLine + coreCommandLineLength + offset, scriptNameLength, scriptName, _TRUNCATE), ERROR_CAN_NOT_COMPLETE);
129-
_tcscat(fullCommandLine, _T("\""));
116+
wcscat(fullCommandLine, L" \"");
117+
wcscat(fullCommandLine, scriptName);
118+
wcscat(fullCommandLine, L"\"");
130119

131120
// create the environment block for the node.js process
132121

@@ -139,18 +128,17 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
139128
// establish the current directory for node.exe process to be the same as the location of the application *.js file
140129
// (in case of the debugger process, it is still the debuggee application file)
141130

142-
currentDirectory = (PWSTR)context->GetScriptTranslated(&currentDirectorySize);
143-
while (currentDirectorySize && currentDirectory[currentDirectorySize] != L'\\' && currentDirectory[currentDirectorySize] != L'/')
131+
scriptTranslated = (PWSTR)context->GetScriptTranslated(&currentDirectorySize);
132+
while (currentDirectorySize && scriptTranslated[currentDirectorySize] != L'\\' && scriptTranslated[currentDirectorySize] != L'/')
144133
currentDirectorySize--;
145-
ErrorIf(0 == (currentDirectorySizeA = WideCharToMultiByte(CP_ACP, 0, currentDirectory, currentDirectorySize, NULL, 0, NULL, NULL)), E_FAIL);
146-
ErrorIf(NULL == (currentDirectoryA = new char[currentDirectorySize + 1]), ERROR_NOT_ENOUGH_MEMORY);
147-
ErrorIf(currentDirectorySizeA != WideCharToMultiByte(CP_ACP, 0, currentDirectory, currentDirectorySize, currentDirectoryA, currentDirectorySizeA, NULL, NULL), E_FAIL);
148-
currentDirectoryA[currentDirectorySizeA] = '\0';
134+
ErrorIf(NULL == (currentDirectory = new WCHAR[wcslen(scriptTranslated) + 1]), ERROR_NOT_ENOUGH_MEMORY);
135+
wcscpy(currentDirectory, scriptTranslated);
136+
currentDirectory[currentDirectorySize] = L'\0';
149137

150138
// create startup info for the node.js process
151139

152140
RtlZeroMemory(&this->startupInfo, sizeof this->startupInfo);
153-
GetStartupInfo(&startupInfo);
141+
GetStartupInfoW(&startupInfo);
154142
CheckError(this->CreateStdHandles(context));
155143

156144
// create process watcher thread in a suspended state
@@ -172,15 +160,15 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
172160
flags |= CREATE_BREAKAWAY_FROM_JOB;
173161
}
174162

175-
if(!CreateProcess(
163+
if(!CreateProcessW(
176164
NULL,
177165
fullCommandLine,
178166
NULL,
179167
NULL,
180168
TRUE,
181169
flags,
182170
newEnvironment,
183-
currentDirectoryA,
171+
currentDirectory,
184172
&this->startupInfo,
185173
&processInformation))
186174
{
@@ -211,8 +199,8 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
211199

212200
// clean up
213201

214-
delete [] currentDirectoryA;
215-
currentDirectoryA = NULL;
202+
delete [] currentDirectory;
203+
currentDirectory = NULL;
216204
delete [] newEnvironment;
217205
newEnvironment = NULL;
218206
delete [] fullCommandLine;
@@ -245,10 +233,10 @@ HRESULT CNodeProcess::Initialize(IHttpContext* context)
245233
L"iisnode failed to initialize a new node.exe process", WINEVENT_LEVEL_ERROR);
246234
}
247235

248-
if (currentDirectoryA)
236+
if (currentDirectory)
249237
{
250-
delete [] currentDirectoryA;
251-
currentDirectoryA = NULL;
238+
delete [] currentDirectory;
239+
currentDirectory = NULL;
252240
}
253241

254242
if (suuid != NULL)

Diff for: src/iisnode/cnodeprocess.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class CNodeProcess
1616
HANDLE processWatcher;
1717
DWORD maxConcurrentRequestsPerProcess;
1818
BOOL isClosing;
19-
STARTUPINFO startupInfo;
19+
STARTUPINFOW startupInfo;
2020
BOOL hasProcessExited;
2121
OVERLAPPED overlapped;
2222
CConnectionPool connectionPool;

Diff for: src/iisnode/cprotocolbridge.cpp

+1-14
Original file line numberDiff line numberDiff line change
@@ -160,25 +160,12 @@ BOOL CProtocolBridge::SendIisnodeError(IHttpContext* httpCtx, HRESULT hr)
160160
break;
161161

162162
case IISNODE_ERROR_UNABLE_TO_START_NODE_EXE:
163-
LPCTSTR commandLine = CModuleConfiguration::GetNodeProcessCommandLine(httpCtx);
164-
char* errorMessage;
165-
if (NULL == (errorMessage = (char*)httpCtx->AllocateRequestMemory(strlen(commandLine) + 512)))
166-
{
167-
errorMessage =
163+
char* errorMessage =
168164
"The iisnode module is unable to start the node.exe process. Make sure the node.exe executable is available "
169165
"at the location specified in the <a href=""https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config"">"
170166
"system.webServer/iisnode/@nodeProcessCommandLine</a> element of web.config. "
171167
"By default node.exe is expected to be installed in %ProgramFiles%\\nodejs folder on x86 systems and "
172168
"%ProgramFiles(x86)%\\nodejs folder on x64 systems.";
173-
}
174-
else
175-
{
176-
sprintf(errorMessage,
177-
"The iisnode module is unable to start the node.exe process. Make sure the node.exe executable is available "
178-
"at the location specified in the <a href=""https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config"">"
179-
"system.webServer/iisnode/@nodeProcessCommandLine</a> element of web.config. "
180-
"The command line iisnode attempted to run was:<br><br>%s", commandLine);
181-
}
182169

183170
CProtocolBridge::SendSyncResponse(
184171
httpCtx,

0 commit comments

Comments
 (0)