diff --git a/src/iisnode/cfilewatcher.cpp b/src/iisnode/cfilewatcher.cpp
index befc222..0cda805 100644
--- a/src/iisnode/cfilewatcher.cpp
+++ b/src/iisnode/cfilewatcher.cpp
@@ -26,7 +26,11 @@ CFileWatcher::~CFileWatcher()
while (NULL != this->directories)
{
WatchedDirectory* currentDirectory = this->directories;
- CloseHandle(currentDirectory->watchHandle);
+ if(currentDirectory->watchHandle != NULL)
+ {
+ CloseHandle(currentDirectory->watchHandle);
+ currentDirectory->watchHandle = NULL;
+ }
delete [] currentDirectory->directoryName;
while (NULL != currentDirectory->files)
{
@@ -385,6 +389,7 @@ Error:
if (NULL != newDirectory->watchHandle)
{
CloseHandle(newDirectory->watchHandle);
+ newDirectory->watchHandle = NULL;
}
delete newDirectory;
@@ -437,7 +442,11 @@ HRESULT CFileWatcher::RemoveWatch(CNodeApplication* application)
if (!directory->files)
{
delete [] directory->directoryName;
- CloseHandle(directory->watchHandle);
+ if(directory->watchHandle != NULL)
+ {
+ CloseHandle(directory->watchHandle);
+ directory->watchHandle = NULL;
+ }
if (previousDirectory)
{
@@ -507,7 +516,7 @@ unsigned int CFileWatcher::Worker(void* arg)
while (current && current != directory)
current = current->next;
- if (current)
+ if (current && current->watchHandle != NULL)
{
watcher->ScanDirectory(current, FALSE);
@@ -541,8 +550,46 @@ unsigned int CFileWatcher::Worker(void* arg)
WatchedDirectory* current = watcher->directories;
while (current)
{
- if (watcher->ScanDirectory(current, TRUE))
- break;
+ //
+ // watched directory exists, check if handle is valid, if not, create one.
+ // watchHandle will be NULL if the watched directory was deleted before.
+ //
+ if(watcher->DirectoryExists(current->directoryName))
+ {
+ if(current->watchHandle == NULL)
+ {
+ current->watchHandle = CreateFileW(
+ current->directoryName,
+ FILE_LIST_DIRECTORY,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+ NULL);
+ }
+
+ //
+ // scan the directory for file changes
+ //
+ if (watcher->ScanDirectory(current, TRUE))
+ {
+ //
+ // found a change that will recycle the application.
+ //
+ break;
+ }
+ }
+ else
+ {
+ //
+ // directory being watched was deleted, close the handle.
+ //
+ if(current->watchHandle != NULL)
+ {
+ CloseHandle(current->watchHandle);
+ current->watchHandle = NULL;
+ }
+ }
current = current->next;
}
@@ -553,6 +600,16 @@ unsigned int CFileWatcher::Worker(void* arg)
return 0;
}
+BOOL CFileWatcher::DirectoryExists(LPCWSTR directoryPath)
+{
+ DWORD dwFileAttributes;
+
+ dwFileAttributes = GetFileAttributesW(directoryPath);
+
+ return ((dwFileAttributes != INVALID_FILE_ATTRIBUTES) &&
+ (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
+}
+
BOOL CFileWatcher::ScanDirectory(WatchedDirectory* directory, BOOL unc)
{
WatchedFile* file = directory->files;
diff --git a/src/iisnode/cfilewatcher.h b/src/iisnode/cfilewatcher.h
index 92801c8..cdf9659 100644
--- a/src/iisnode/cfilewatcher.h
+++ b/src/iisnode/cfilewatcher.h
@@ -42,6 +42,7 @@ private:
static unsigned int WINAPI Worker(void* arg);
BOOL ScanDirectory(WatchedDirectory* directory, BOOL unc);
HRESULT WatchFile(PCWSTR directoryName, DWORD directoryNameLength, BOOL unc, PCWSTR startSubdirectoryName, PCWSTR startFileName, PCWSTR endFileName, BOOL wildcard);
+ BOOL DirectoryExists(LPCWSTR directoryPath);
static HRESULT GetWatchedFileTimestamp(WatchedFile* file, FILETIME* timestamp);
public:
diff --git a/src/iisnode/cmoduleconfiguration.cpp b/src/iisnode/cmoduleconfiguration.cpp
index 43fb091..31f9bf4 100644
--- a/src/iisnode/cmoduleconfiguration.cpp
+++ b/src/iisnode/cmoduleconfiguration.cpp
@@ -629,10 +629,11 @@ HRESULT CModuleConfiguration::GetBOOL(char* str, BOOL* value)
return S_OK;
}
-HRESULT CModuleConfiguration::GetString(char* str, LPWSTR* value)
+HRESULT CModuleConfiguration::GetString(char* str, LPWSTR* value, BOOL expandEnvironmentStrings)
{
HRESULT hr;
int wcharSize, bytesConverted;
+ LPWSTR pszStr = NULL;
if (*value)
{
@@ -645,12 +646,31 @@ HRESULT CModuleConfiguration::GetString(char* str, LPWSTR* value)
str = "";
}
- ErrorIf(0 == (wcharSize = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0)), GetLastError());
- ErrorIf(NULL == (*value = new WCHAR[wcharSize]), ERROR_NOT_ENOUGH_MEMORY);
- ErrorIf(wcharSize != MultiByteToWideChar(CP_ACP, 0, str, -1, *value, wcharSize), GetLastError());
+ if(expandEnvironmentStrings == FALSE)
+ {
+ ErrorIf(0 == (wcharSize = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0)), GetLastError());
+ ErrorIf(NULL == (*value = new WCHAR[wcharSize]), ERROR_NOT_ENOUGH_MEMORY);
+ ErrorIf(wcharSize != MultiByteToWideChar(CP_ACP, 0, str, -1, *value, wcharSize), GetLastError());
+ }
+ else
+ {
+ ErrorIf(0 == (wcharSize = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0)), GetLastError());
+ ErrorIf(NULL == (pszStr = new WCHAR[wcharSize]), ERROR_NOT_ENOUGH_MEMORY);
+ ErrorIf(wcharSize != MultiByteToWideChar(CP_ACP, 0, str, -1, pszStr, wcharSize), GetLastError());
+ ErrorIf(0 == (wcharSize = ExpandEnvironmentStringsW(pszStr, NULL, 0)), GetLastError());
+ ErrorIf(NULL == (*value = new WCHAR[wcharSize]), ERROR_NOT_ENOUGH_MEMORY);
+ ErrorIf(wcharSize != ExpandEnvironmentStringsW(pszStr, *value, wcharSize), GetLastError());
+ }
+
+ hr = S_OK; // fall through to clean up section.
- return S_OK;
Error:
+
+ if(pszStr != NULL)
+ {
+ delete[] pszStr;
+ }
+
return hr;
}
@@ -774,7 +794,7 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context,
}
else if (0 == strcmpi(keyStart, "nodeProcessCommandLine"))
{
- CheckError(GetString(valueStart, &config->nodeProcessCommandLine));
+ CheckError(GetString(valueStart, &config->nodeProcessCommandLine, TRUE));
}
else if (0 == strcmpi(keyStart, "interceptor"))
{
diff --git a/src/iisnode/cmoduleconfiguration.h b/src/iisnode/cmoduleconfiguration.h
index af62e02..3774250 100644
--- a/src/iisnode/cmoduleconfiguration.h
+++ b/src/iisnode/cmoduleconfiguration.h
@@ -52,7 +52,7 @@ private:
static HRESULT GetBOOL(IAppHostElement* section, LPCWSTR propertyName, BOOL* value, BOOL defaultValue);
static HRESULT GetDWORD(char* str, DWORD* value);
static HRESULT GetBOOL(char* str, BOOL* value);
- static HRESULT GetString(char* str, LPWSTR* value);
+ static HRESULT GetString(char* str, LPWSTR* value, BOOL expandEnvironmentStrings = FALSE);
static HRESULT GetDWORD(IAppHostElement* section, LPCWSTR propertyName, DWORD* value);
static HRESULT ApplyConfigOverrideKeyValue(IHttpContext* context, CModuleConfiguration* config, char* keyStart, char* keyEnd, char* valueStart, char* valueEnd);
static HRESULT ApplyYamlConfigOverrides(IHttpContext* context, CModuleConfiguration* config);
diff --git a/src/iisnode/cprotocolbridge.cpp b/src/iisnode/cprotocolbridge.cpp
index efb59bb..6c9b9a4 100644
--- a/src/iisnode/cprotocolbridge.cpp
+++ b/src/iisnode/cprotocolbridge.cpp
@@ -491,7 +491,17 @@ HRESULT CProtocolBridge::InitiateRequest(CNodeHttpStoredContext* context)
if (NULL == (url = request->GetHeader("X-Original-URL", &urlLength)))
{
HTTP_REQUEST* raw = request->GetRawHttpRequest();
- context->SetTargetUrl(raw->pRawUrl, raw->RawUrlLength);
+
+ // Fix for https://github.com/tjanczuk/iisnode/issues/296
+ PSTR path = NULL;
+ int pathSizeA = 0;
+ int cchAbsPathLength = (raw->CookedUrl.AbsPathLength + raw->CookedUrl.QueryStringLength) >> 1;
+ ErrorIf(0 == (pathSizeA = WideCharToMultiByte(CP_ACP, 0, raw->CookedUrl.pAbsPath, cchAbsPathLength, NULL, 0, NULL, NULL)), E_FAIL);
+ ErrorIf(NULL == (path = (TCHAR*)context->GetHttpContext()->AllocateRequestMemory(pathSizeA + 1)), ERROR_NOT_ENOUGH_MEMORY);
+ ErrorIf(pathSizeA != WideCharToMultiByte(CP_ACP, 0, raw->CookedUrl.pAbsPath, cchAbsPathLength, path, pathSizeA, NULL, NULL), E_FAIL);
+ path[pathSizeA] = 0;
+
+ context->SetTargetUrl(path, pathSizeA);
}
else
{
diff --git a/test/functional/www/103_urlrewrite/web.config b/test/functional/www/103_urlrewrite/web.config
index 59ce739..148ac55 100644
--- a/test/functional/www/103_urlrewrite/web.config
+++ b/test/functional/www/103_urlrewrite/web.config
@@ -1,15 +1,15 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+