mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 08:23:05 -05:00
launchctl: implementation
This commit is contained in:
parent
9ae28a5529
commit
ec21e830f1
@ -19,12 +19,268 @@
|
||||
|
||||
#define PROGNAME "launchctl"
|
||||
|
||||
#define fatal(ExitCode, format, ...) (warn(format, __VA_ARGS__), ExitProcess(ExitCode))
|
||||
|
||||
static void vwarn(const char *format, va_list ap)
|
||||
{
|
||||
char buf[1024];
|
||||
/* wvsprintf is only safe with a 1024 byte buffer */
|
||||
size_t len;
|
||||
DWORD BytesTransferred;
|
||||
|
||||
wvsprintfA(buf, format, ap);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
|
||||
len = lstrlenA(buf);
|
||||
buf[len++] = '\n';
|
||||
|
||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
|
||||
buf, (DWORD)len, &BytesTransferred, 0);
|
||||
}
|
||||
|
||||
static void warn(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vwarn(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fatal(ERROR_INVALID_PARAMETER,
|
||||
"usage: %s COMMAND ARGS\n"
|
||||
"\n"
|
||||
"commands:\n"
|
||||
" start ClassName InstanceName Args...\n"
|
||||
" stop InstanceName\n"
|
||||
" list\n"
|
||||
" info\n",
|
||||
PROGNAME);
|
||||
}
|
||||
|
||||
static void report(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
{
|
||||
if (0 == PipeBufSize)
|
||||
warn("KO received empty buffer from launcher");
|
||||
else if (L'$' == PipeBuf[0])
|
||||
{
|
||||
if (1 == PipeBufSize)
|
||||
warn("OK");
|
||||
else
|
||||
{
|
||||
for (PWSTR P = PipeBuf, PipeBufEnd = P + PipeBufSize / sizeof(WCHAR); PipeBufEnd > P; P++)
|
||||
if (L'\0' == *P)
|
||||
*P = L'\n';
|
||||
|
||||
if (PipeBufSize < PIPE_BUFFER_SIZE)
|
||||
PipeBuf[PipeBufSize / sizeof(WCHAR)] = L'\0';
|
||||
else
|
||||
PipeBuf[PIPE_BUFFER_SIZE / sizeof(WCHAR) - 1] = L'\0';
|
||||
|
||||
warn("OK\n%S", PipeBuf + 1);
|
||||
}
|
||||
}
|
||||
else if (L'!' == PipeBuf[0])
|
||||
{
|
||||
if (PipeBufSize < PIPE_BUFFER_SIZE)
|
||||
PipeBuf[PipeBufSize / sizeof(WCHAR)] = L'\0';
|
||||
else
|
||||
PipeBuf[PIPE_BUFFER_SIZE / sizeof(WCHAR) - 1] = L'\0';
|
||||
|
||||
warn("KO %S", PipeBuf + 1);
|
||||
}
|
||||
else
|
||||
warn("KO received corrupted buffer from launcher", 0);
|
||||
}
|
||||
|
||||
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv)
|
||||
{
|
||||
PWSTR P;
|
||||
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
ClassNameSize = lstrlenW(ClassName) + 1;
|
||||
InstanceNameSize = lstrlenW(InstanceName) + 1;
|
||||
ArgvSize = 0;
|
||||
for (DWORD Argi = Argc; Argc > Argi; Argi++)
|
||||
ArgvSize += lstrlenW(Argv[Argi]);
|
||||
|
||||
if (PipeBufSize < (1 + ClassNameSize + InstanceNameSize + ArgvSize) * sizeof(WCHAR))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceStart;
|
||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||
for (DWORD Argi = Argc; Argc > Argi; Argi++)
|
||||
{
|
||||
ArgvSize = lstrlenW(Argv[Argi]);
|
||||
memcpy(P, Argv[Argi], ArgvSize * sizeof(WCHAR)); P += ArgvSize;
|
||||
}
|
||||
|
||||
if (CallNamedPipeW(L"" PIPE_NAME,
|
||||
PipeBuf, (DWORD)((P - PipeBuf) * sizeof(WCHAR)), PipeBuf, PipeBufSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT))
|
||||
{
|
||||
LastError = 0;
|
||||
report(PipeBuf, BytesTransferred);
|
||||
}
|
||||
else
|
||||
LastError = GetLastError();
|
||||
|
||||
return LastError;
|
||||
}
|
||||
|
||||
int stop(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
PWSTR InstanceName)
|
||||
{
|
||||
PWSTR P;
|
||||
DWORD InstanceNameSize;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
InstanceNameSize = lstrlenW(InstanceName) + 1;
|
||||
|
||||
if (PipeBufSize < (1 + InstanceNameSize) * sizeof(WCHAR))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceStop;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR));
|
||||
|
||||
if (CallNamedPipeW(L"" PIPE_NAME,
|
||||
PipeBuf, (DWORD)((P - PipeBuf) * sizeof(WCHAR)), PipeBuf, PipeBufSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT))
|
||||
{
|
||||
LastError = 0;
|
||||
report(PipeBuf, BytesTransferred);
|
||||
}
|
||||
else
|
||||
LastError = GetLastError();
|
||||
|
||||
return LastError;
|
||||
}
|
||||
|
||||
int list(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||
{
|
||||
PWSTR P;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
if (PipeBufSize < 1 * sizeof(WCHAR))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceList;
|
||||
|
||||
if (CallNamedPipeW(L"" PIPE_NAME,
|
||||
PipeBuf, (DWORD)((P - PipeBuf) * sizeof(WCHAR)), PipeBuf, PipeBufSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT))
|
||||
{
|
||||
LastError = 0;
|
||||
report(PipeBuf, BytesTransferred);
|
||||
}
|
||||
else
|
||||
LastError = GetLastError();
|
||||
|
||||
return LastError;
|
||||
}
|
||||
|
||||
int info(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||
PWSTR InstanceName)
|
||||
{
|
||||
PWSTR P;
|
||||
DWORD InstanceNameSize;
|
||||
DWORD LastError, BytesTransferred;
|
||||
|
||||
InstanceNameSize = lstrlenW(InstanceName) + 1;
|
||||
|
||||
if (PipeBufSize < (1 + InstanceNameSize) * sizeof(WCHAR))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
P = PipeBuf;
|
||||
*P++ = LauncherSvcInstanceInfo;
|
||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR));
|
||||
|
||||
if (CallNamedPipeW(L"" PIPE_NAME,
|
||||
PipeBuf, (DWORD)((P - PipeBuf) * sizeof(WCHAR)), PipeBuf, PipeBufSize,
|
||||
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT))
|
||||
{
|
||||
LastError = 0;
|
||||
report(PipeBuf, BytesTransferred);
|
||||
}
|
||||
else
|
||||
LastError = GetLastError();
|
||||
|
||||
return LastError;
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t **argv)
|
||||
{
|
||||
PWSTR PipeBuf = 0;
|
||||
|
||||
/* allocate our PipeBuf early on; freed on process exit by the system */
|
||||
PipeBuf = MemAlloc(PIPE_BUFFER_SIZE);
|
||||
if (0 == PipeBuf)
|
||||
return ERROR_NO_SYSTEM_RESOURCES;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (0 == argc)
|
||||
usage();
|
||||
|
||||
if (0 == lstrcmp(L"start", argv[0]))
|
||||
{
|
||||
if (3 > argc || argc > 12)
|
||||
usage();
|
||||
|
||||
return start(PipeBuf, PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3);
|
||||
}
|
||||
else
|
||||
if (0 == lstrcmp(L"stop", argv[0]))
|
||||
{
|
||||
if (2 != argc)
|
||||
usage();
|
||||
|
||||
return stop(PipeBuf, PIPE_BUFFER_SIZE, argv[1]);
|
||||
}
|
||||
if (0 == lstrcmp(L"list", argv[0]))
|
||||
{
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
return list(PipeBuf, PIPE_BUFFER_SIZE);
|
||||
}
|
||||
if (0 == lstrcmp(L"info", argv[0]))
|
||||
{
|
||||
if (2 != argc)
|
||||
usage();
|
||||
|
||||
return info(PipeBuf, PIPE_BUFFER_SIZE, argv[1]);
|
||||
}
|
||||
else
|
||||
usage();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wmainCRTStartup(void)
|
||||
void wmainCRTStartup(void)
|
||||
{
|
||||
return wmain(0, 0);
|
||||
DWORD Argc;
|
||||
PWSTR *Argv;
|
||||
|
||||
extern HANDLE ProcessHeap;
|
||||
ProcessHeap = GetProcessHeap();
|
||||
if (0 == ProcessHeap)
|
||||
ExitProcess(GetLastError());
|
||||
|
||||
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||
if (0 == Argv)
|
||||
ExitProcess(GetLastError());
|
||||
|
||||
ExitProcess(wmain(Argc, Argv));
|
||||
}
|
||||
|
||||
HANDLE ProcessHeap;
|
||||
|
@ -20,8 +20,6 @@
|
||||
#define PROGNAME "WinFsp-Launcher"
|
||||
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
||||
|
||||
HANDLE ProcessHeap;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PWSTR ClassName;
|
||||
@ -367,7 +365,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
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_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, 0);
|
||||
1, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, PIPE_DEFAULT_TIMEOUT, 0);
|
||||
if (INVALID_HANDLE_VALUE == SvcPipe)
|
||||
goto fail;
|
||||
|
||||
@ -630,13 +628,17 @@ static VOID SvcPipeTransact(PWSTR PipeBuf, PULONG PSize)
|
||||
|
||||
int wmain(int argc, wchar_t **argv)
|
||||
{
|
||||
ProcessHeap = GetProcessHeap();
|
||||
if (0 == ProcessHeap)
|
||||
return GetLastError();
|
||||
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
||||
}
|
||||
|
||||
int wmainCRTStartup(void)
|
||||
void wmainCRTStartup(void)
|
||||
{
|
||||
return wmain(0, 0);
|
||||
extern HANDLE ProcessHeap;
|
||||
ProcessHeap = GetProcessHeap();
|
||||
if (0 == ProcessHeap)
|
||||
ExitProcess(GetLastError());
|
||||
|
||||
ExitProcess(wmain(0, 0));
|
||||
}
|
||||
|
||||
HANDLE ProcessHeap;
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#define PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||
#define PIPE_BUFFER_SIZE 2048
|
||||
#define PIPE_DEFAULT_TIMEOUT 3000
|
||||
|
||||
enum
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user