mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 08:53:01 -05:00
launchctl: implementation
This commit is contained in:
parent
9ae28a5529
commit
ec21e830f1
@ -19,12 +19,268 @@
|
|||||||
|
|
||||||
#define PROGNAME "launchctl"
|
#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)
|
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;
|
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 PROGNAME "WinFsp-Launcher"
|
||||||
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
||||||
|
|
||||||
HANDLE ProcessHeap;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
PWSTR ClassName;
|
PWSTR ClassName;
|
||||||
@ -367,7 +365,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
PIPE_ACCESS_DUPLEX |
|
PIPE_ACCESS_DUPLEX |
|
||||||
FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
|
FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
|
||||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
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)
|
if (INVALID_HANDLE_VALUE == SvcPipe)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -630,13 +628,17 @@ static VOID SvcPipeTransact(PWSTR PipeBuf, PULONG PSize)
|
|||||||
|
|
||||||
int wmain(int argc, wchar_t **argv)
|
int wmain(int argc, wchar_t **argv)
|
||||||
{
|
{
|
||||||
ProcessHeap = GetProcessHeap();
|
|
||||||
if (0 == ProcessHeap)
|
|
||||||
return GetLastError();
|
|
||||||
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
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_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||||
#define PIPE_BUFFER_SIZE 2048
|
#define PIPE_BUFFER_SIZE 2048
|
||||||
|
#define PIPE_DEFAULT_TIMEOUT 3000
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user