diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj
index 784bfe71..54553b37 100644
--- a/build/VStudio/winfsp_dll.vcxproj
+++ b/build/VStudio/winfsp_dll.vcxproj
@@ -39,6 +39,7 @@
+
diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters
index b93ce5e2..00f55d7f 100644
--- a/build/VStudio/winfsp_dll.vcxproj.filters
+++ b/build/VStudio/winfsp_dll.vcxproj.filters
@@ -115,6 +115,9 @@
Source
+
+ Source
+
diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h
index 6892acc9..d74b50aa 100644
--- a/inc/winfsp/winfsp.h
+++ b/inc/winfsp/winfsp.h
@@ -1703,6 +1703,133 @@ FSP_API NTSTATUS FspServiceContextCheck(HANDLE Token, PBOOLEAN PIsLocalSystem);
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...);
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
*/
diff --git a/src/dll/fs.c b/src/dll/fs.c
index 4da26737..66a277b9 100644
--- a/src/dll/fs.c
+++ b/src/dll/fs.c
@@ -16,7 +16,6 @@
*/
#include
-#include
enum
{
@@ -191,64 +190,25 @@ FSP_API VOID FspFileSystemDelete(FSP_FILE_SYSTEM *FileSystem)
static NTSTATUS FspFileSystemLauncherDefineDosDevice(
WCHAR Sign, PWSTR MountPoint, PWSTR VolumeName)
{
- NTSTATUS Result;
- ULONG MountPointLen, VolumeNameLen;
- PWSTR PipeBuf = 0, P;
- DWORD BytesTransferred;
-
- MountPointLen = lstrlenW(MountPoint);
- VolumeNameLen = lstrlenW(VolumeName);
-
- if (2 != MountPointLen ||
- FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= VolumeNameLen)
+ if (2 != lstrlenW(MountPoint) ||
+ FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR) <= lstrlenW(VolumeName))
return STATUS_INVALID_PARAMETER;
- PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
- if (0 == PipeBuf)
- {
- Result = STATUS_INSUFFICIENT_RESOURCES;
- goto exit;
- }
+ WCHAR Argv0[4];
+ PWSTR Argv[2];
+ NTSTATUS Result;
+ ULONG ErrorCode;
- P = PipeBuf;
- *P++ = LauncherDefineDosDevice;
- *P++ = Sign;
- memcpy(P, MountPoint, MountPointLen * sizeof(WCHAR)); P += MountPointLen; *P++ = L'\0';
- memcpy(P, VolumeName, VolumeNameLen * sizeof(WCHAR)); P += VolumeNameLen; *P++ = L'\0';
+ Argv0[0] = Sign;
+ Argv0[1] = MountPoint[0];
+ Argv0[2] = MountPoint[1];
+ Argv0[3] = 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;
+ Argv[0] = Argv0;
+ Argv[1] = VolumeName;
- if (sizeof(WCHAR) > BytesTransferred)
- Result = RPC_NT_PROTOCOL_ERROR;
- 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;
+ Result = FspLaunchCallLauncherPipe('D', 2, Argv, 0, 0, 0, &ErrorCode);
+ return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
}
static NTSTATUS FspFileSystemSetMountPoint_Drive(PWSTR MountPoint, PWSTR VolumeName,
diff --git a/src/dll/launch.c b/src/dll/launch.c
new file mode 100644
index 00000000..03042f4c
--- /dev/null
+++ b/src/dll/launch.c
@@ -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
+#include
+
+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);
+}
diff --git a/src/dll/np.c b/src/dll/np.c
index ff9955f6..e0f95cb1 100644
--- a/src/dll/np.c
+++ b/src/dll/np.c
@@ -168,39 +168,17 @@ static inline BOOLEAN FspNpParseRemoteUserName(PWSTR RemoteName,
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;
- DWORD BytesTransferred;
+ ULONG ErrorCode;
- Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
- &BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
-
- if (!NT_SUCCESS(Result))
- 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;
+ Result = FspLaunchCallLauncherPipe(Command, Argc, Argv, Argl, Buffer, PSize, &ErrorCode);
+ return !NT_SUCCESS(Result) ?
+ WN_NO_NETWORK :
+ (ERROR_BROKEN_PIPE == ErrorCode ? WN_NO_NETWORK : ErrorCode);
}
static NTSTATUS FspNpGetVolumeList(
@@ -490,7 +468,9 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
PWSTR ClassName, InstanceName, RemoteName, P;
ULONG ClassNameLen, InstanceNameLen;
DWORD CredentialsKind;
- PWSTR PipeBuf = 0;
+ ULONG Argc;
+ PWSTR Argv[6];
+ ULONG Argl[6];
#if defined(FSP_NP_CREDENTIAL_MANAGER)
PCREDENTIALW Credential = 0;
#endif
@@ -556,32 +536,24 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
}
}
- PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
- if (0 == PipeBuf)
- {
- NpResult = WN_OUT_OF_MEMORY;
- goto exit;
- }
-
- /* 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;
+ Argc = 0;
+ Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
+ Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
+ Argv[Argc] = RemoteName; Argl[Argc] = -1; Argc++;
+ Argv[Argc] = LocalNameBuf; Argl[Argc] = -1; Argc++;
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)
{
- lstrcpyW(P, lpPassword); P += lstrlenW(lpPassword) + 1;
+ Argv[Argc] = lpPassword; Argl[Argc] = -1; Argc++;
}
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)
{
case WN_SUCCESS:
@@ -627,13 +599,13 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
break;
}
- P = PipeBuf;
- *P++ = LauncherSvcInstanceInfo;
- memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
- memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
+ Argc = 0;
+ Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
+ Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
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! */
NpResult = WN_NO_NETWORK;
@@ -677,8 +649,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
}
exit:
- MemFree(PipeBuf);
-
#if defined(FSP_NP_CREDENTIAL_MANAGER)
if (0 != Credential)
CredFree(Credential);
@@ -767,9 +737,11 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
DWORD NpResult;
WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
DWORD RemoteNameSize;
- PWSTR ClassName, InstanceName, RemoteName, P;
+ PWSTR ClassName, InstanceName, RemoteName;
ULONG ClassNameLen, InstanceNameLen;
- PWSTR PipeBuf = 0;
+ ULONG Argc;
+ PWSTR Argv[2];
+ ULONG Argl[2];
if (FspNpCheckLocalName(lpName))
{
@@ -789,17 +761,13 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
return WN_BAD_NETNAME;
- PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
- if (0 == PipeBuf)
- return WN_OUT_OF_MEMORY;
-
- 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';
+ Argc = 0;
+ Argv[Argc] = ClassName; Argl[Argc] = ClassNameLen; Argc++;
+ Argv[Argc] = InstanceName; Argl[Argc] = InstanceNameLen; Argc++;
NpResult = FspNpCallLauncherPipe(
- PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
+ LauncherSvcInstanceStop,
+ Argc, Argv, Argl, 0, 0);
switch (NpResult)
{
case WN_SUCCESS:
@@ -812,8 +780,6 @@ DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
break;
}
- MemFree(PipeBuf);
-
return NpResult;
}