mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	launchctl: implementation
This commit is contained in:
		| @@ -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 | ||||||
| { | { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user