dll: FspLaunch API

This commit is contained in:
Bill Zissimopoulos 2018-01-04 11:08:23 -08:00
parent 9bd9cf4fbd
commit e111451475
No known key found for this signature in database
GPG Key ID: 3D4F95D52C7B3EA3
6 changed files with 332 additions and 123 deletions

View File

@ -39,6 +39,7 @@
<ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" /> <ClCompile Include="..\..\src\dll\fuse\fuse_intf.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse_main.c" /> <ClCompile Include="..\..\src\dll\fuse\fuse_main.c" />
<ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" /> <ClCompile Include="..\..\src\dll\fuse\fuse_opt.c" />
<ClCompile Include="..\..\src\dll\launch.c" />
<ClCompile Include="..\..\src\dll\np.c" /> <ClCompile Include="..\..\src\dll\np.c" />
<ClCompile Include="..\..\src\dll\posix.c" /> <ClCompile Include="..\..\src\dll\posix.c" />
<ClCompile Include="..\..\src\dll\security.c" /> <ClCompile Include="..\..\src\dll\security.c" />

View File

@ -115,6 +115,9 @@
<ClCompile Include="..\..\src\dll\wksid.c"> <ClCompile Include="..\..\src\dll\wksid.c">
<Filter>Source</Filter> <Filter>Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\dll\launch.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\src\dll\library.def"> <None Include="..\..\src\dll\library.def">

View File

@ -1703,6 +1703,133 @@ FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem);
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...); FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...);
FSP_API VOID FspServiceLogV(ULONG Type, PWSTR Format, va_list ap); FSP_API VOID FspServiceLogV(ULONG Type, PWSTR Format, va_list ap);
/**
* @group Launch Control
*/
/**
* Call launcher pipe.
*
* This function is used to send a command to the launcher and receive a response.
*
* @param Command
* Launcher command to send. For example, the 'L' launcher command instructs
* the launcher to list all running service instances.
* @param Argc
* Command argument count. May be 0.
* @param Argv
* Command argument array. May be NULL.
* @param Argl
* Command argument length array. May be NULL. If this is NULL all command arguments
* are assumed to be NULL-terminated strings. It is also possible for specific arguments
* to be NULL-terminated; in this case pass -1 in the corresponding Argl position.
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
PWSTR Buffer, PULONG PSize, PULONG PLauncherError);
/**
* Start a service instance.
*
* @param ClassName
* Class name of the service instance to start.
* @param InstanceName
* Instance name of the service instance to start.
* @param Argc
* Service instance argument count. May be 0.
* @param Argv
* Service instance argument array. May be NULL.
* @param HasSecret
* Whether the last argument in Argv is assumed to be a secret (e.g. password) or not.
* Secrets are passed to service instances through standard input rather than the command
* line.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchStart(
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
BOOLEAN HasSecret,
PULONG PLauncherError);
/**
* Stop a service instance.
*
* @param ClassName
* Class name of the service instance to stop.
* @param InstanceName
* Instance name of the service instance to stop.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchStop(
PWSTR ClassName, PWSTR InstanceName,
PULONG PLauncherError);
/**
* Get information about a service instance.
*
* The information is a list of NULL-terminated strings: the class name of the service instance,
* the instance name of the service instance and the full command line used to start the service
* instance.
*
* @param ClassName
* Class name of the service instance to stop.
* @param InstanceName
* Instance name of the service instance to stop.
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchGetInfo(
PWSTR ClassName, PWSTR InstanceName,
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError);
/**
* List service instances.
*
* The information is a list of pairs of NULL-terminated strings. Each pair contains the class
* name and instance name of a service instance. All currently running service instances are
* listed.
*
* @param Buffer
* Buffer that receives the command response. May be NULL.
* @param PSize
* Pointer to a ULONG. On input it contains the size of the Buffer. On output it
* contains the number of bytes transferred. May be NULL.
* @param PLauncherError
* Receives the launcher error if any. This is always a Win32 error code. May not be NULL.
* @return
* STATUS_SUCCESS if the command is sent successfully to the launcher, even if the launcher
* returns an error. Other status codes indicate a communication error. Launcher errors are
* reported through PLauncherError.
*/
FSP_API NTSTATUS FspLaunchGetNameList(
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError);
/* /*
* Utility * Utility
*/ */

View File

@ -16,7 +16,6 @@
*/ */
#include <dll/library.h> #include <dll/library.h>
#include <launcher/launcher.h>
enum enum
{ {
@ -191,64 +190,25 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
static NTSTATUS FspFileSystemLauncherDefineDosDevice( static NTSTATUS FspFileSystemLauncherDefineDosDevice(
WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName) WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName)
{ {
NTSTATUS Result; if (2 != lstrlenW(MountPoint) ||
ULONG MountPointLen, VolumeNameLen; FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= lstrlenW(VolumeName))
PWSTR PipeBuf = 0, P;
DWORD BytesTransferred;
MountPointLen = lstrlenW(MountPoint);
VolumeNameLen = lstrlenW(VolumeName);
if (2 != MountPointLen ||
FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= VolumeNameLen)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE); WCHAR Argv0[4];
if (0 == PipeBuf) PWSTR Argv[2];
{ NTSTATUS Result;
Result = STATUS_INSUFFICIENT_RESOURCES; ULONG ErrorCode;
goto exit;
}
P = PipeBuf; Argv0[0] = Sign;
*P++ = LauncherDefineDosDevice; Argv0[1] = MountPoint[0];
*P++ = Sign; Argv0[2] = MountPoint[1];
memcpy(P, MountPoint, MountPointLen * sizeof(WCHAR)); P += MountPointLen; *P++ = L'\0'; Argv0[3] = L'\0';
memcpy(P, VolumeName, VolumeNameLen * sizeof(WCHAR)); P += VolumeNameLen; *P++ = L'\0';
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, Argv[0] = Argv0;
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, Argv[1] = VolumeName;
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
if (!NT_SUCCESS(Result))
goto exit;
if (sizeof(WCHAR) > BytesTransferred) Result = FspLaunchCallLauncherPipe('D', 2, Argv, 0, 0, 0, &ErrorCode);
Result = RPC_NT_PROTOCOL_ERROR; return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
else if (LauncherSuccess == PipeBuf[0])
Result = STATUS_SUCCESS;
else if (LauncherFailure == PipeBuf[0])
{
DWORD ErrorCode = 0;
for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++)
{
if (L'0' > *P || *P > L'9')
break;
ErrorCode = 10 * ErrorCode + (*P - L'0');
}
Result = FspNtStatusFromWin32(ErrorCode);
if (0 == Result)
Result = RPC_NT_PROTOCOL_ERROR;
}
else
Result = RPC_NT_PROTOCOL_ERROR;
exit:
MemFree(PipeBuf);
return Result;
} }
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName, static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,

152
src/dll/launch.c Normal file
View File

@ -0,0 +1,152 @@
/**
* @file dll/launch.c
*
* @copyright 2015-2018 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* 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.
*/
#include <dll/library.h>
#include <launcher/launcher.h>
FSP_API NTSTATUS FspLaunchCallLauncherPipe(
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
PWSTR Buffer, PULONG PSize, PULONG PLauncherError)
{
PWSTR PipeBuf = 0, P;
ULONG Length, BytesTransferred;
NTSTATUS Result;
ULONG ErrorCode;
if (0 != PSize)
*PSize = 0;
*PLauncherError = 0;
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
if (0 == PipeBuf)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
P = PipeBuf;
*P++ = Command;
for (ULONG I = 0; Argc > I; I++)
if (0 != Argv[I])
{
Length = 0 == Argl || -1 == Argl[I] ? lstrlenW(Argv[I]) : Argl[I];
if (LAUNCHER_PIPE_BUFFER_SIZE < ((ULONG)(P - PipeBuf) + Length + 1) * sizeof(WCHAR))
{
Result = STATUS_INVALID_PARAMETER;
goto exit;
}
memcpy(P, Argv[I], Length * sizeof(WCHAR)); P += Length; *P++ = L'\0';
}
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME,
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE,
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
if (!NT_SUCCESS(Result))
goto exit;
Result = STATUS_SUCCESS;
ErrorCode = ERROR_BROKEN_PIPE; /* protocol error! */
if (sizeof(WCHAR) <= BytesTransferred)
{
if (LauncherSuccess == PipeBuf[0])
{
ErrorCode = 0;
if (0 != PSize)
{
BytesTransferred -= sizeof(WCHAR);
memcpy(Buffer, PipeBuf, *PSize < BytesTransferred ? *PSize : BytesTransferred);
*PSize = BytesTransferred;
}
}
else if (LauncherFailure == PipeBuf[0])
{
ErrorCode = 0;
for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++)
{
if (L'0' > *P || *P > L'9')
break;
ErrorCode = 10 * ErrorCode + (*P - L'0');
}
if (0 == ErrorCode)
ErrorCode = ERROR_BROKEN_PIPE; /* protocol error! */
}
}
*PLauncherError = ErrorCode;
exit:
MemFree(PipeBuf);
return Result;
}
FSP_API NTSTATUS FspLaunchStart(
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0,
BOOLEAN HasSecret,
PULONG PLauncherError)
{
PWSTR Argv[9 + 2];
if (9 < Argc)
return STATUS_INVALID_PARAMETER;
Argv[0] = ClassName;
Argv[1] = InstanceName;
memcpy(Argv + 2, Argv, Argc * sizeof(PWSTR));
return FspLaunchCallLauncherPipe(
HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart,
Argc + 2, Argv, 0, 0, 0, PLauncherError);
}
FSP_API NTSTATUS FspLaunchStop(
PWSTR ClassName, PWSTR InstanceName,
PULONG PLauncherError)
{
PWSTR Argv[2];
Argv[0] = ClassName;
Argv[1] = InstanceName;
return FspLaunchCallLauncherPipe(LauncherSvcInstanceStop,
2, Argv, 0, 0, 0, PLauncherError);
}
FSP_API NTSTATUS FspLaunchGetInfo(
PWSTR ClassName, PWSTR InstanceName,
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError)
{
PWSTR Argv[2];
Argv[0] = ClassName;
Argv[1] = InstanceName;
return FspLaunchCallLauncherPipe(LauncherSvcInstanceInfo,
2, Argv, 0, Buffer, PSize, PLauncherError);
}
FSP_API NTSTATUS FspLaunchGetNameList(
PWSTR Buffer, PULONG PSize,
PULONG PLauncherError)
{
return FspLaunchCallLauncherPipe(LauncherSvcInstanceList,
0, 0, 0, Buffer, PSize, PLauncherError);
}

View File

@ -168,39 +168,17 @@ static inline BOOLEAN FspNpParseRemoteUserName(PWSTR RemoteName,
return FALSE; return FALSE;
} }
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize) static inline DWORD FspNpCallLauncherPipe(
WCHAR Command, ULONG Argc, PWSTR *Argv, ULONG *Argl,
PWSTR Buffer, PULONG PSize)
{ {
DWORD NpResult;
NTSTATUS Result; NTSTATUS Result;
DWORD BytesTransferred; ULONG ErrorCode;
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize, Result = FspLaunchCallLauncherPipe(Command, Argc, Argv, Argl, Buffer, PSize, &ErrorCode);
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER); return !NT_SUCCESS(Result) ?
WN_NO_NETWORK :
if (!NT_SUCCESS(Result)) (ERROR_BROKEN_PIPE == ErrorCode ? WN_NO_NETWORK : ErrorCode);
NpResult = WN_NO_NETWORK;
else if (sizeof(WCHAR) > BytesTransferred)
NpResult = WN_NO_NETWORK;
else if (LauncherSuccess == PipeBuf[0])
NpResult = WN_SUCCESS;
else if (LauncherFailure == PipeBuf[0])
{
NpResult = 0;
for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++)
{
if (L'0' > *P || *P > L'9')
break;
NpResult = 10 * NpResult + (*P - L'0');
}
if (0 == NpResult)
NpResult = WN_NO_NETWORK;
}
else
NpResult = WN_NO_NETWORK;
return NpResult;
} }
static NTSTATUS FspNpGetVolumeList( static NTSTATUS FspNpGetVolumeList(
@ -490,7 +468,9 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
PWSTR ClassName, InstanceName, RemoteName, P; PWSTR ClassName, InstanceName, RemoteName, P;
ULONG ClassNameLen, InstanceNameLen; ULONG ClassNameLen, InstanceNameLen;
DWORD CredentialsKind; DWORD CredentialsKind;
PWSTR PipeBuf = 0; ULONG Argc;
PWSTR Argv[6];
ULONG Argl[6];
#if defined(FSP_NP_CREDENTIAL_MANAGER) #if defined(FSP_NP_CREDENTIAL_MANAGER)
PCREDENTIALW Credential = 0; PCREDENTIALW Credential = 0;
#endif #endif
@ -556,32 +536,24 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
} }
} }
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE); Argc = 0;
if (0 == PipeBuf) Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
{ Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
NpResult = WN_OUT_OF_MEMORY; Argv[Argc] = RemoteName; Argl[Argc] = -1; Argc++;
goto exit; Argv[Argc] = LocalNameBuf; Argl[Argc] = -1; Argc++;
}
/* we do not explicitly check, but assumption is it all fits in LAUNCHER_PIPE_BUFFER_SIZE */
P = PipeBuf;
*P++ = FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind) if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
{ {
lstrcpyW(P, lpUserName); P += lstrlenW(lpUserName) + 1; Argv[Argc] = lpUserName; Argl[Argc] = -1; Argc++;
} }
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind) if (FSP_NP_CREDENTIALS_NONE != CredentialsKind)
{ {
lstrcpyW(P, lpPassword); P += lstrlenW(lpPassword) + 1; Argv[Argc] = lpPassword; Argl[Argc] = -1; Argc++;
} }
NpResult = FspNpCallLauncherPipe( NpResult = FspNpCallLauncherPipe(
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE); FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart,
Argc, Argv, Argl, 0, 0);
switch (NpResult) switch (NpResult)
{ {
case WN_SUCCESS: case WN_SUCCESS:
@ -627,13 +599,13 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
break; break;
} }
P = PipeBuf; Argc = 0;
*P++ = LauncherSvcInstanceInfo; Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0'; Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
if (WN_SUCCESS != FspNpCallLauncherPipe( if (WN_SUCCESS != FspNpCallLauncherPipe(
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE)) LauncherSvcInstanceInfo,
Argc, Argv, Argl, 0, 0))
{ {
/* looks like the file system is gone! */ /* looks like the file system is gone! */
NpResult = WN_NO_NETWORK; NpResult = WN_NO_NETWORK;
@ -677,8 +649,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
} }
exit: exit:
MemFree(PipeBuf);
#if defined(FSP_NP_CREDENTIAL_MANAGER) #if defined(FSP_NP_CREDENTIAL_MANAGER)
if (0 != Credential) if (0 != Credential)
CredFree(Credential); CredFree(Credential);
@ -767,9 +737,11 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
DWORD NpResult; DWORD NpResult;
WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)]; WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
DWORD RemoteNameSize; DWORD RemoteNameSize;
PWSTR ClassName, InstanceName, RemoteName, P; PWSTR ClassName, InstanceName, RemoteName;
ULONG ClassNameLen, InstanceNameLen; ULONG ClassNameLen, InstanceNameLen;
PWSTR PipeBuf = 0; ULONG Argc;
PWSTR Argv[2];
ULONG Argl[2];
if (FspNpCheckLocalName(lpName)) if (FspNpCheckLocalName(lpName))
{ {
@ -789,17 +761,13 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen)) &ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
return WN_BAD_NETNAME; return WN_BAD_NETNAME;
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE); Argc = 0;
if (0 == PipeBuf) Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
return WN_OUT_OF_MEMORY; Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
P = PipeBuf;
*P++ = LauncherSvcInstanceStop;
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
NpResult = FspNpCallLauncherPipe( NpResult = FspNpCallLauncherPipe(
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE); LauncherSvcInstanceStop,
Argc, Argv, Argl, 0, 0);
switch (NpResult) switch (NpResult)
{ {
case WN_SUCCESS: case WN_SUCCESS:
@ -812,8 +780,6 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
break; break;
} }
MemFree(PipeBuf);
return NpResult; return NpResult;
} }