diff --git a/build/VStudio/launcher/launcher.vcxproj b/build/VStudio/launcher/launcher.vcxproj
index 42d22f38..028f1539 100644
--- a/build/VStudio/launcher/launcher.vcxproj
+++ b/build/VStudio/launcher/launcher.vcxproj
@@ -176,6 +176,7 @@
+
diff --git a/build/VStudio/launcher/launcher.vcxproj.filters b/build/VStudio/launcher/launcher.vcxproj.filters
index 7e2d9316..bd46cd0e 100644
--- a/build/VStudio/launcher/launcher.vcxproj.filters
+++ b/build/VStudio/launcher/launcher.vcxproj.filters
@@ -21,5 +21,8 @@
Include\shared
+
+ Source
+
\ No newline at end of file
diff --git a/src/launcher/launcher.c b/src/launcher/launcher.c
index 8fca5f01..2ac08ca8 100644
--- a/src/launcher/launcher.c
+++ b/src/launcher/launcher.c
@@ -15,9 +15,7 @@
* software.
*/
-#include
-#include
-#include
+#include
#define PROGNAME "WinFsp-Launcher"
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
@@ -282,18 +280,171 @@ VOID SvcInstanceStop(PWSTR InstanceName)
LeaveCriticalSection(&SvcInstanceLock);
}
+static HANDLE SvcThread, SvcEvent;
+static HANDLE SvcPipe = INVALID_HANDLE_VALUE;
+static OVERLAPPED SvcOverlapped;
+
+static DWORD WINAPI SvcPipeServer(PVOID Context);
+
static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
{
InitializeCriticalSection(&SvcInstanceLock);
+
+ SvcEvent = CreateEventW(0, TRUE, FALSE, 0);
+ if (0 == SvcEvent)
+ goto fail;
+
+ SvcOverlapped.hEvent = CreateEventW(0, TRUE, FALSE, 0);
+ if (0 == SvcOverlapped.hEvent)
+ goto fail;
+
+ SvcPipe = CreateNamedPipeW(L"" PIPE_NAME,
+ PIPE_ACCESS_DUPLEX |
+ FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
+ 1, PIPE_SRVBUF_SIZE, PIPE_CLIBUF_SIZE, 0, 0);
+ if (INVALID_HANDLE_VALUE == SvcPipe)
+ goto fail;
+
+ SvcThread = CreateThread(0, 0, SvcPipeServer, Service, 0, 0);
+ if (0 == SvcThread)
+ goto fail;
+
return STATUS_SUCCESS;
+
+fail:
+ DWORD LastError = GetLastError();
+
+ if (0 != SvcThread)
+ CloseHandle(SvcThread);
+
+ if (INVALID_HANDLE_VALUE != SvcPipe)
+ CloseHandle(SvcPipe);
+
+ if (0 != SvcOverlapped.hEvent)
+ CloseHandle(SvcOverlapped.hEvent);
+
+ if (0 != SvcEvent)
+ CloseHandle(SvcEvent);
+
+ DeleteCriticalSection(&SvcInstanceLock);
+
+ return FspNtStatusFromWin32(LastError);
}
static NTSTATUS SvcStop(FSP_SERVICE *Service)
{
+ SetEvent(SvcEvent);
+ FspServiceRequestTime(Service, 4500); /* just under 5 sec */
+ WaitForSingleObject(SvcThread, 4500);
+
+ if (0 != SvcThread)
+ CloseHandle(SvcThread);
+
+ if (INVALID_HANDLE_VALUE != SvcPipe)
+ CloseHandle(SvcPipe);
+
+ if (0 != SvcOverlapped.hEvent)
+ CloseHandle(SvcOverlapped.hEvent);
+
+ if (0 != SvcEvent)
+ CloseHandle(SvcEvent);
+
DeleteCriticalSection(&SvcInstanceLock);
+
return STATUS_SUCCESS;
}
+static inline DWORD SvcPipeWaitResult(BOOL Success, HANDLE StopEvent,
+ HANDLE Handle, OVERLAPPED *Overlapped, PDWORD PBytesTransferred)
+{
+ HANDLE WaitObjects[2];
+ DWORD WaitResult;
+
+ if (!Success && ERROR_IO_PENDING != GetLastError())
+ return GetLastError();
+
+ WaitObjects[0] = StopEvent;
+ WaitObjects[1] = Overlapped->hEvent;
+ WaitResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
+ if (WAIT_OBJECT_0 == WaitResult)
+ return -1; /* special: stop thread */
+ else if (WAIT_OBJECT_0 + 1 == WaitResult)
+ {
+ if (!GetOverlappedResult(Handle, Overlapped, PBytesTransferred, TRUE))
+ return GetLastError();
+ return 0;
+ }
+ else
+ return GetLastError();
+}
+
+static DWORD WINAPI SvcPipeServer(PVOID Context)
+{
+ FSP_SERVICE *Service = Context;
+ PWSTR PipeBuf = 0;
+ DWORD LastError, BytesTransferred;
+
+ PipeBuf = MemAlloc(PIPE_SRVBUF_SIZE);
+ if (0 == PipeBuf)
+ {
+ FspServiceSetExitCode(Service, ERROR_NO_SYSTEM_RESOURCES);
+ goto exit;
+ }
+
+ for (;;)
+ {
+ LastError = SvcPipeWaitResult(
+ ConnectNamedPipe(SvcPipe, &SvcOverlapped),
+ SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
+ if (-1 == LastError)
+ break;
+ else if (ERROR_PIPE_CONNECTED != LastError && ERROR_NO_DATA != LastError)
+ {
+ FspServiceLog(EVENTLOG_WARNING_TYPE,
+ L"Error in service main loop (ConnectNamedPipe = %ld). Continuing...", LastError);
+ continue;
+ }
+
+ LastError = SvcPipeWaitResult(
+ ReadFile(SvcPipe, PipeBuf, PIPE_SRVBUF_SIZE, &BytesTransferred, &SvcOverlapped),
+ SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
+ if (-1 == LastError)
+ break;
+ else if (0 != LastError)
+ {
+ DisconnectNamedPipe(SvcPipe);
+ FspServiceLog(EVENTLOG_WARNING_TYPE,
+ L"Error in service main loop (ReadFile = %ld). Continuing...", LastError);
+ continue;
+ }
+
+ /* handle PipeBuf */
+
+ LastError = SvcPipeWaitResult(
+ WriteFile(SvcPipe, PipeBuf, PIPE_SRVBUF_SIZE, &BytesTransferred, &SvcOverlapped),
+ SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
+ if (-1 == LastError)
+ break;
+ else if (0 != LastError)
+ {
+ DisconnectNamedPipe(SvcPipe);
+ FspServiceLog(EVENTLOG_WARNING_TYPE,
+ L"Error in service main loop (WriteFile = %ld). Continuing...", LastError);
+ continue;
+ }
+
+ DisconnectNamedPipe(SvcPipe);
+ }
+
+exit:
+ MemFree(PipeBuf);
+
+ FspServiceStop(Service);
+
+ return 0;
+}
+
int wmain(int argc, wchar_t **argv)
{
ProcessHeap = GetProcessHeap();
diff --git a/src/launcher/launcher.h b/src/launcher/launcher.h
new file mode 100644
index 00000000..c126293d
--- /dev/null
+++ b/src/launcher/launcher.h
@@ -0,0 +1,29 @@
+/**
+ * @file launcher/launcher.h
+ *
+ * @copyright 2015-2016 Bill Zissimopoulos
+ */
+/*
+ * This file is part of WinFsp.
+ *
+ * You can redistribute it and/or modify it under the terms of the
+ * GNU Affero General Public License version 3 as published by the
+ * Free Software Foundation.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * software.
+ */
+
+#ifndef WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
+#define WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
+
+#include
+#include
+
+#define PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
+#define PIPE_SRVBUF_SIZE 1024
+#define PIPE_CLIBUF_SIZE 1024
+
+
+#endif