mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-07 20:42:09 -05:00
launcher, launchctl: StartWithSecret
This commit is contained in:
parent
c0344f53b0
commit
518cd0e8c0
@ -110,6 +110,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -128,6 +129,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -149,6 +151,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -170,6 +173,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
#include <launcher/launcher.h>
|
#include <launcher/launcher.h>
|
||||||
#include <npapi.h>
|
#include <npapi.h>
|
||||||
|
#include <wincred.h>
|
||||||
|
|
||||||
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
||||||
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
||||||
@ -403,7 +404,7 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
|
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
|
||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
WCHAR UserName[256], Password[256];
|
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH], Password[CREDUI_MAX_PASSWORD_LENGTH];
|
||||||
|
|
||||||
/* CONNECT_PROMPT is only valid if CONNECT_INTERACTIVE is also set */
|
/* CONNECT_PROMPT is only valid if CONNECT_INTERACTIVE is also set */
|
||||||
if (CONNECT_PROMPT == (dwFlags & (CONNECT_INTERACTIVE | CONNECT_PROMPT)))
|
if (CONNECT_PROMPT == (dwFlags & (CONNECT_INTERACTIVE | CONNECT_PROMPT)))
|
||||||
|
@ -115,7 +115,8 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||||
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv)
|
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv,
|
||||||
|
BOOLEAN HasSecret)
|
||||||
{
|
{
|
||||||
PWSTR P;
|
PWSTR P;
|
||||||
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
||||||
@ -130,7 +131,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
|||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
P = PipeBuf;
|
P = PipeBuf;
|
||||||
*P++ = LauncherSvcInstanceStart;
|
*P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||||
@ -230,7 +231,17 @@ int wmain(int argc, wchar_t **argv)
|
|||||||
if (3 > argc || argc > 12)
|
if (3 > argc || argc > 12)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3);
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"startWithSecret", argv[0]))
|
||||||
|
{
|
||||||
|
if (3 > argc || argc > 12)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||||
|
TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (0 == lstrcmpW(L"stop", argv[0]))
|
if (0 == lstrcmpW(L"stop", argv[0]))
|
||||||
|
@ -21,6 +21,53 @@
|
|||||||
#define PROGNAME "WinFsp.Launcher"
|
#define PROGNAME "WinFsp.Launcher"
|
||||||
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
||||||
|
|
||||||
|
BOOL CreateOverlappedPipe(
|
||||||
|
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
||||||
|
DWORD ReadMode, DWORD WriteMode)
|
||||||
|
{
|
||||||
|
RPC_STATUS RpcStatus;
|
||||||
|
UUID Uuid;
|
||||||
|
WCHAR PipeNameBuf[MAX_PATH];
|
||||||
|
HANDLE ReadPipe, WritePipe;
|
||||||
|
DWORD LastError;
|
||||||
|
|
||||||
|
RpcStatus = UuidCreate(&Uuid);
|
||||||
|
if (S_OK != RpcStatus && RPC_S_UUID_LOCAL_ONLY != RpcStatus)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INTERNAL_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsprintfW(PipeNameBuf, L"\\\\.\\pipe\\"
|
||||||
|
"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||||
|
Uuid.Data1, Uuid.Data2, Uuid.Data3,
|
||||||
|
Uuid.Data4[0], Uuid.Data4[1], Uuid.Data4[2], Uuid.Data4[3],
|
||||||
|
Uuid.Data4[4], Uuid.Data4[5], Uuid.Data4[6], Uuid.Data4[7]);
|
||||||
|
|
||||||
|
ReadPipe = CreateNamedPipeW(PipeNameBuf,
|
||||||
|
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | ReadMode,
|
||||||
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||||
|
1, Size, Size, 120 * 1000, SecurityAttributes);
|
||||||
|
if (INVALID_HANDLE_VALUE == ReadPipe)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
WritePipe = CreateFileW(PipeNameBuf,
|
||||||
|
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
SecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == WritePipe)
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
CloseHandle(ReadPipe);
|
||||||
|
SetLastError(LastError);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PReadPipe = ReadPipe;
|
||||||
|
*PWritePipe = WritePipe;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE Process;
|
HANDLE Process;
|
||||||
@ -80,6 +127,7 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
LONG RefCount;
|
||||||
PWSTR ClassName;
|
PWSTR ClassName;
|
||||||
PWSTR InstanceName;
|
PWSTR InstanceName;
|
||||||
PWSTR CommandLine;
|
PWSTR CommandLine;
|
||||||
@ -87,6 +135,7 @@ typedef struct
|
|||||||
DWORD ProcessId;
|
DWORD ProcessId;
|
||||||
HANDLE Process;
|
HANDLE Process;
|
||||||
HANDLE ProcessWait;
|
HANDLE ProcessWait;
|
||||||
|
HANDLE StdioHandles[2];
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
WCHAR Buffer[];
|
WCHAR Buffer[];
|
||||||
} SVC_INSTANCE;
|
} SVC_INSTANCE;
|
||||||
@ -231,8 +280,129 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||||
|
HANDLE StdioHandles[2],
|
||||||
|
PPROCESS_INFORMATION ProcessInfo)
|
||||||
|
{
|
||||||
|
STARTUPINFOEXW StartupInfoEx;
|
||||||
|
HANDLE ChildHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
||||||
|
HANDLE ParentHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
||||||
|
SECURITY_ATTRIBUTES PipeAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
|
||||||
|
PPROC_THREAD_ATTRIBUTE_LIST AttrList = 0;
|
||||||
|
SIZE_T Size;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
memset(&StartupInfoEx, 0, sizeof StartupInfoEx);
|
||||||
|
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||||
|
|
||||||
|
if (0 != StdioHandles)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Create child process and redirect stdin/stdout. Do *not* inherit other handles.
|
||||||
|
*
|
||||||
|
* For explanation see:
|
||||||
|
* https://blogs.msdn.microsoft.com/oldnewthing/20111216-00/?p=8873/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* create stdin read/write ends; make them inheritable */
|
||||||
|
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0], &PipeAttributes, 0,
|
||||||
|
0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create stdout read/write ends; make them inheritable */
|
||||||
|
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1], &PipeAttributes, 0,
|
||||||
|
FILE_FLAG_OVERLAPPED, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = 0;
|
||||||
|
if (!InitializeProcThreadAttributeList(0, 1, 0, &Size) &&
|
||||||
|
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
AttrList = MemAlloc(Size);
|
||||||
|
if (0 == AttrList)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InitializeProcThreadAttributeList(AttrList, 1, 0, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only the child ends of stdin/stdout are actually inherited */
|
||||||
|
if (!UpdateProcThreadAttribute(AttrList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||||
|
ChildHandles, sizeof ChildHandles, 0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartupInfoEx.lpAttributeList = AttrList;
|
||||||
|
StartupInfoEx.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||||
|
StartupInfoEx.StartupInfo.hStdInput = ChildHandles[0];
|
||||||
|
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
|
||||||
|
StartupInfoEx.StartupInfo.hStdError = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0,
|
||||||
|
(PVOID)&StartupInfoEx, ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!CreateProcessW(Executable, CommandLine, 0, 0, FALSE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0,
|
||||||
|
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandles[0])
|
||||||
|
CloseHandle(ParentHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandles[0])
|
||||||
|
CloseHandle(ParentHandles[0]);
|
||||||
|
}
|
||||||
|
else if (0 != StdioHandles)
|
||||||
|
{
|
||||||
|
StdioHandles[0] = ParentHandles[0];
|
||||||
|
StdioHandles[1] = ParentHandles[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != ChildHandles[0])
|
||||||
|
CloseHandle(ChildHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != ChildHandles[1])
|
||||||
|
CloseHandle(ChildHandles[1]);
|
||||||
|
|
||||||
|
MemFree(AttrList);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
||||||
|
BOOLEAN RedirectStdio,
|
||||||
SVC_INSTANCE **PSvcInstance)
|
SVC_INSTANCE **PSvcInstance)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = 0;
|
SVC_INSTANCE *SvcInstance = 0;
|
||||||
@ -244,7 +414,6 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
DWORD JobControl;
|
DWORD JobControl;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
PWSTR Argv[10];
|
PWSTR Argv[10];
|
||||||
STARTUPINFOW StartupInfo;
|
|
||||||
PROCESS_INFORMATION ProcessInfo;
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
@ -259,7 +428,6 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
Argv[0] = 0;
|
Argv[0] = 0;
|
||||||
Argc++;
|
Argc++;
|
||||||
|
|
||||||
memset(&StartupInfo, 0, sizeof StartupInfo);
|
|
||||||
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
||||||
|
|
||||||
EnterCriticalSection(&SvcInstanceLock);
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
@ -353,23 +521,23 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(SvcInstance, 0, sizeof *SvcInstance);
|
memset(SvcInstance, 0, sizeof *SvcInstance);
|
||||||
|
SvcInstance->RefCount = 2;
|
||||||
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
||||||
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
||||||
SvcInstance->ClassName = SvcInstance->Buffer;
|
SvcInstance->ClassName = SvcInstance->Buffer;
|
||||||
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
||||||
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
StartupInfo.cb = sizeof StartupInfo;
|
Result = SvcInstanceCreateProcess(Executable, CommandLine,
|
||||||
if (!CreateProcessW(Executable, SvcInstance->CommandLine, 0, 0, FALSE,
|
RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
|
||||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfo, &ProcessInfo))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
|
||||||
|
|
||||||
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
||||||
SvcInstance->Process = ProcessInfo.hProcess;
|
SvcInstance->Process = ProcessInfo.hProcess;
|
||||||
@ -413,6 +581,11 @@ exit:
|
|||||||
|
|
||||||
if (0 != SvcInstance)
|
if (0 != SvcInstance)
|
||||||
{
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
|
||||||
if (0 != SvcInstance->ProcessWait)
|
if (0 != SvcInstance->ProcessWait)
|
||||||
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
|
|
||||||
@ -435,13 +608,21 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID SvcInstanceDelete(SVC_INSTANCE *SvcInstance)
|
static VOID SvcInstanceRelease(SVC_INSTANCE *SvcInstance)
|
||||||
{
|
{
|
||||||
|
if (0 != InterlockedDecrement(&SvcInstance->RefCount))
|
||||||
|
return;
|
||||||
|
|
||||||
EnterCriticalSection(&SvcInstanceLock);
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
if (RemoveEntryList(&SvcInstance->ListEntry))
|
if (RemoveEntryList(&SvcInstance->ListEntry))
|
||||||
SetEvent(SvcInstanceEvent);
|
SetEvent(SvcInstanceEvent);
|
||||||
LeaveCriticalSection(&SvcInstanceLock);
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
|
||||||
if (0 != SvcInstance->ProcessWait)
|
if (0 != SvcInstance->ProcessWait)
|
||||||
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
if (0 != SvcInstance->Process)
|
if (0 != SvcInstance->Process)
|
||||||
@ -457,15 +638,79 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout)
|
|||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = Context;
|
SVC_INSTANCE *SvcInstance = Context;
|
||||||
|
|
||||||
SvcInstanceDelete(SvcInstance);
|
SvcInstanceRelease(SvcInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job)
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job,
|
||||||
|
BOOLEAN HasSecret)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance;
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
return SvcInstanceCreate(ClientToken, ClassName, InstanceName, Argc, Argv, Job, &SvcInstance);
|
HasSecret = HasSecret && 0 < Argc && L'\0' != Argv[Argc - 1][0];
|
||||||
|
|
||||||
|
Result = SvcInstanceCreate(ClientToken, ClassName, InstanceName,
|
||||||
|
Argc - HasSecret, Argv, Job, HasSecret,
|
||||||
|
&SvcInstance);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
if (!HasSecret)
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PWSTR Secret = Argv[Argc - 1];
|
||||||
|
UINT8 RspBuf[2];
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
OVERLAPPED Overlapped;
|
||||||
|
|
||||||
|
if (!WriteFile(SvcInstance->StdioHandles[0], Secret, lstrlenW(Secret), &BytesTransferred, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&Overlapped, 0, sizeof Overlapped);
|
||||||
|
if (!ReadFile(SvcInstance->StdioHandles[1], RspBuf, sizeof RspBuf, 0, &Overlapped) &&
|
||||||
|
ERROR_IO_PENDING != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetOverlappedResultEx(SvcInstance->StdioHandles[1], &Overlapped, &BytesTransferred,
|
||||||
|
LAUNCHER_START_WITH_SECRET_TIMEOUT, FALSE))
|
||||||
|
{
|
||||||
|
if (WAIT_TIMEOUT == GetLastError())
|
||||||
|
Result = STATUS_TIMEOUT;
|
||||||
|
else
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
CancelIoEx(SvcInstance->StdioHandles[1], &Overlapped);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeof RspBuf <= BytesTransferred && 'O' == RspBuf[0] && 'K' == RspBuf[1])
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
{
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
{
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcInstanceRelease(SvcInstance);
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
||||||
@ -909,12 +1154,16 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
|||||||
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
||||||
PWSTR ClassName, InstanceName;
|
PWSTR ClassName, InstanceName;
|
||||||
ULONG Argc; PWSTR Argv[9];
|
ULONG Argc; PWSTR Argv[9];
|
||||||
|
BOOLEAN HasSecret = FALSE;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
*PSize = 0;
|
*PSize = 0;
|
||||||
|
|
||||||
switch (*P++)
|
switch (*P++)
|
||||||
{
|
{
|
||||||
|
case LauncherSvcInstanceStartWithSecret:
|
||||||
|
HasSecret = TRUE;
|
||||||
|
/* fall through! */
|
||||||
case LauncherSvcInstanceStart:
|
case LauncherSvcInstanceStart:
|
||||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
@ -924,7 +1173,8 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
|||||||
|
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
if (0 != ClassName && 0 != InstanceName)
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob);
|
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob,
|
||||||
|
HasSecret);
|
||||||
|
|
||||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
break;
|
break;
|
||||||
|
@ -28,7 +28,9 @@
|
|||||||
#define LAUNCHER_PIPE_BUFFER_SIZE 2048
|
#define LAUNCHER_PIPE_BUFFER_SIZE 2048
|
||||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
||||||
|
|
||||||
/*
|
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 30000
|
||||||
|
|
||||||
|
/*
|
||||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||||
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||||
@ -53,6 +55,7 @@
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||||
|
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||||
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||||
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||||
LauncherSvcInstanceList = 'L', /* requires: none*/
|
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user