2005-11-09 02:50:54 +00:00
|
|
|
/*
|
2000-05-13 13:51:08 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
2005-11-09 02:50:54 +00:00
|
|
|
* PROJECT: ReactOS Win32 Kernel Library
|
2015-11-14 14:57:11 +00:00
|
|
|
* FILE: dll/win32/kernel32/client/file/npipe.c
|
2005-11-09 02:50:54 +00:00
|
|
|
* PURPOSE: Named Pipe Functions
|
|
|
|
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
|
|
|
* Ariadne ( ariadne@xs4all.nl)
|
2000-05-13 13:51:08 +00:00
|
|
|
*/
|
|
|
|
|
2011-11-07 00:18:13 +00:00
|
|
|
/* INCLUDES *******************************************************************/
|
2000-05-13 13:51:08 +00:00
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
[KERNEL32]: While working on the CMAKE branch, Amine and myself discovered a rather serious issue in kernel32 (and perhaps other libraries as well). Unlike rbuild, CMake does not allow you to export non-existant DLL functions (try it: add "poopyhead" in kernel32's exports under RBuild, and will it export "poopyhead", God knowing what that will actually link to).
As an additional feature on top of the "allow non-existing functions to be exported" "feature", because rbuild generates and links STDCALL function names without the proper decoration (vs. enforcing decoration at linking, but only removing it at export-time), this allows the definition (as an export) of a STDCALL function that is completely different from the actual function itself.
For example, the 5-parameter Foo function is normally Foo@20, while the 3-parameter Foo function woudl be Foo@12. Linking one against the other would fail (say, 2 parameters were added to Foo in a newer version). However, under RBUILD, both of these would appear as "Foo", and the linker/compiler would happilly connect the caller of Foo@3 (that has pushed 3 parameters) to the receiving side of Foo@5 (that is about to pop 5 parameters).
Even -if- decorations WERE to be applied, Foo@12 would STILL succeed, because of the first feature, which would enable the export of Foo@12 even though no such function exist.
In a further, bizare, twist of fate, the behavior of this RBUILD "feature", when the target function is not found, is to link the exported DLL TO ITSELF.
Therefore, one can see how, previously to this patch, kernel32.dll would import a dozen functions from itself (all the non-existing functions).
To really seal the deal, the behavior of exported functions used by kernel32, but that are actually forwarded to another DLL deserves a special mention.
GetLastError, for example, merely forwards to RtlGetLastWin32Error, so it is normal behavior to use a #define in the C code so that all internal calls to the function are routed correctly.
This did not happen, so instead, kernel32 tried importing/linking/exporting GetLastError, but this symbol is not found in the binary, because it is only a forwarder.
This caused kernel32 to import from itself (the behavior when an exported symbol is not found). When importing from itself, the loader would now find the _forwarded_ for GetLastError, and correctly link with ntdll.
What should be a one-liner of assembly (inline TEB access) thus became a triple-call indirection (GetLastError@0->StubLastError@0->__impGetLastError@0->__impRtlGetLastWin32Error->RtlGetLastWin32Error.
While analyzing these issues, we also realized a strange macro SetLastErrorByStatus that manually tried to perform what there already exists a function for: RtlSetLastNtStatusFromWin32Error.
And, in an exciting coda, we also realized that our Server 2003 Kernel32 exports more than a dozen Windows 95 APIs, through an auto-stub generation mechanism within winebuild, that gets linked as an object behind the scenes.
[KERNEL32]: Removed all Win95 exports, cleaned up exports.
[KERNEL32]: Fixed up set/get error macros by making them inline and/or calling the correct ntdll function.
[KERNEL32]: Removed bizare calls to Wine-internal/specific APIs from our core Win32 DLL.
[KERNEL32]: Wrote stubs for all functions which should be exported, and set the correct number of parameters for them.
[KERNEL32]: Kernel32 is smaller, loads faster, does not export Windows 95 functions, does not export non-existing functions, and does not import from itself anymore.
Note: This is one of the many failings of RBUILD the CMAKE system has helped us discover. I believe these issues are serious enough to warrant an immediate sync with trunk, but rest assured, there are many more completely broken, infinitely-regressing things that we discovered while switching to CMAKE.
svn path=/trunk/; revision=48475
2010-08-07 05:02:58 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
2010-09-21 17:14:22 +00:00
|
|
|
DEBUG_CHANNEL(kernel32file);
|
2000-05-13 13:51:08 +00:00
|
|
|
|
2011-11-07 00:18:13 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
LONG ProcessPipeId;
|
|
|
|
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
2017-10-23 15:08:50 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2017-10-23 12:36:18 +00:00
|
|
|
static
|
|
|
|
BOOL
|
|
|
|
NpGetUserNamep(HANDLE hNamedPipe,
|
|
|
|
LPWSTR lpUserName,
|
|
|
|
DWORD nMaxUserNameSize)
|
|
|
|
{
|
2017-10-23 15:08:50 +00:00
|
|
|
BOOL Ret;
|
|
|
|
HANDLE hToken;
|
|
|
|
HMODULE hAdvapi;
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOL (WINAPI *pRevertToSelf)(void);
|
|
|
|
BOOL (WINAPI *pGetUserNameW)(LPWSTR lpBuffer, LPDWORD lpnSize);
|
|
|
|
BOOL (WINAPI *pImpersonateNamedPipeClient)(HANDLE hNamedPipe);
|
|
|
|
|
|
|
|
/* Open advapi, we'll funcs from it */
|
|
|
|
hAdvapi = LoadLibraryW(L"advapi32.dll");
|
|
|
|
if (hAdvapi == NULL)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Import the three required functions */
|
2017-10-23 15:25:19 +00:00
|
|
|
pRevertToSelf = (BOOL (WINAPI *)(void))GetProcAddress(hAdvapi, "RevertToSelf");
|
|
|
|
pGetUserNameW = (BOOL (WINAPI *)(LPWSTR, LPDWORD))GetProcAddress(hAdvapi, "GetUserNameW");
|
|
|
|
pImpersonateNamedPipeClient = (BOOL (WINAPI *)(HANDLE))GetProcAddress(hAdvapi, "ImpersonateNamedPipeClient");
|
2017-10-23 15:08:50 +00:00
|
|
|
/* If any couldn't be found, fail */
|
|
|
|
if (pRevertToSelf == NULL || pGetUserNameW == NULL || pImpersonateNamedPipeClient == NULL)
|
|
|
|
{
|
|
|
|
FreeLibrary(hAdvapi);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now, open the thread token for impersonation */
|
|
|
|
Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hToken);
|
|
|
|
/* Try to impersonate the pipe client */
|
|
|
|
if (pImpersonateNamedPipeClient(hNamedPipe))
|
|
|
|
{
|
|
|
|
DWORD lpnSize;
|
|
|
|
|
|
|
|
/* It worked, get the user name */
|
|
|
|
lpnSize = nMaxUserNameSize;
|
|
|
|
Ret = pGetUserNameW(lpUserName, &lpnSize);
|
|
|
|
/* Failed to get the thread token? Revert to self */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
pRevertToSelf();
|
|
|
|
|
|
|
|
FreeLibrary(hAdvapi);
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Restore the thread token */
|
|
|
|
Status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken,
|
|
|
|
&hToken, sizeof(HANDLE));
|
|
|
|
/* We cannot fail closing the thread token! */
|
|
|
|
if (!CloseHandle(hToken))
|
|
|
|
{
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set last error if it failed */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If opening the thread token succeed, close it */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We cannot fail closing it! */
|
|
|
|
if (!CloseHandle(hToken))
|
|
|
|
{
|
|
|
|
ASSERT(FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeLibrary(hAdvapi);
|
|
|
|
return Ret;
|
2017-10-23 12:36:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-07 00:18:13 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
CreatePipe(PHANDLE hReadPipe,
|
|
|
|
PHANDLE hWritePipe,
|
|
|
|
LPSECURITY_ATTRIBUTES lpPipeAttributes,
|
|
|
|
DWORD nSize)
|
|
|
|
{
|
|
|
|
WCHAR Buffer[64];
|
|
|
|
UNICODE_STRING PipeName;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
IO_STATUS_BLOCK StatusBlock;
|
|
|
|
LARGE_INTEGER DefaultTimeout;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE ReadPipeHandle;
|
|
|
|
HANDLE WritePipeHandle;
|
|
|
|
LONG PipeId;
|
|
|
|
ULONG Attributes;
|
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
|
|
|
|
|
|
/* Set the timeout to 120 seconds */
|
|
|
|
DefaultTimeout.QuadPart = -1200000000;
|
|
|
|
|
|
|
|
/* Use default buffer size if desired */
|
|
|
|
if (!nSize) nSize = 0x1000;
|
|
|
|
|
|
|
|
/* Increase the Pipe ID */
|
|
|
|
PipeId = InterlockedIncrement(&ProcessPipeId);
|
|
|
|
|
|
|
|
/* Create the pipe name */
|
|
|
|
swprintf(Buffer,
|
2018-02-15 21:34:48 +00:00
|
|
|
L"\\Device\\NamedPipe\\Win32Pipes.%p.%08x",
|
2011-11-07 00:18:13 +00:00
|
|
|
NtCurrentTeb()->ClientId.UniqueProcess,
|
|
|
|
PipeId);
|
|
|
|
RtlInitUnicodeString(&PipeName, Buffer);
|
|
|
|
|
|
|
|
/* Always use case insensitive */
|
|
|
|
Attributes = OBJ_CASE_INSENSITIVE;
|
|
|
|
|
|
|
|
/* Check if we got attributes */
|
|
|
|
if (lpPipeAttributes)
|
|
|
|
{
|
|
|
|
/* Use the attributes' SD instead */
|
|
|
|
SecurityDescriptor = lpPipeAttributes->lpSecurityDescriptor;
|
|
|
|
|
|
|
|
/* Set OBJ_INHERIT if requested */
|
|
|
|
if (lpPipeAttributes->bInheritHandle) Attributes |= OBJ_INHERIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize the attributes */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&PipeName,
|
|
|
|
Attributes,
|
|
|
|
NULL,
|
|
|
|
SecurityDescriptor);
|
|
|
|
|
|
|
|
/* Create the named pipe */
|
|
|
|
Status = NtCreateNamedPipeFile(&ReadPipeHandle,
|
|
|
|
GENERIC_READ |FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&StatusBlock,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
FILE_CREATE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
|
|
FILE_PIPE_BYTE_STREAM_TYPE,
|
|
|
|
FILE_PIPE_BYTE_STREAM_MODE,
|
|
|
|
FILE_PIPE_QUEUE_OPERATION,
|
|
|
|
1,
|
|
|
|
nSize,
|
|
|
|
nSize,
|
|
|
|
&DefaultTimeout);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Convert error and fail */
|
|
|
|
WARN("Status: %lx\n", Status);
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now try opening it for write access */
|
|
|
|
Status = NtOpenFile(&WritePipeHandle,
|
2013-07-19 15:05:28 +00:00
|
|
|
FILE_GENERIC_WRITE,
|
2011-11-07 00:18:13 +00:00
|
|
|
&ObjectAttributes,
|
|
|
|
&StatusBlock,
|
|
|
|
FILE_SHARE_READ,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Convert error and fail */
|
|
|
|
WARN("Status: %lx\n", Status);
|
|
|
|
NtClose(ReadPipeHandle);
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return both handles */
|
|
|
|
*hReadPipe = ReadPipeHandle;
|
|
|
|
*hWritePipe = WritePipeHandle;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2000-05-13 13:51:08 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-09 02:50:54 +00:00
|
|
|
HANDLE
|
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
CreateNamedPipeA(LPCSTR lpName,
|
2005-11-09 02:50:54 +00:00
|
|
|
DWORD dwOpenMode,
|
|
|
|
DWORD dwPipeMode,
|
|
|
|
DWORD nMaxInstances,
|
|
|
|
DWORD nOutBufferSize,
|
|
|
|
DWORD nInBufferSize,
|
|
|
|
DWORD nDefaultTimeOut,
|
|
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
2011-07-22 09:50:33 +00:00
|
|
|
/* Call the W(ide) function */
|
|
|
|
ConvertWin32AnsiChangeApiToUnicodeApi(CreateNamedPipe,
|
|
|
|
lpName,
|
|
|
|
dwOpenMode,
|
|
|
|
dwPipeMode,
|
|
|
|
nMaxInstances,
|
|
|
|
nOutBufferSize,
|
|
|
|
nInBufferSize,
|
|
|
|
nDefaultTimeOut,
|
|
|
|
lpSecurityAttributes);
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-09 00:44:37 +00:00
|
|
|
HANDLE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
CreateNamedPipeW(LPCWSTR lpName,
|
2005-11-09 00:44:37 +00:00
|
|
|
DWORD dwOpenMode,
|
|
|
|
DWORD dwPipeMode,
|
|
|
|
DWORD nMaxInstances,
|
|
|
|
DWORD nOutBufferSize,
|
|
|
|
DWORD nInBufferSize,
|
|
|
|
DWORD nDefaultTimeOut,
|
|
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
2005-11-09 00:44:37 +00:00
|
|
|
UNICODE_STRING NamedPipeName;
|
|
|
|
BOOL Result;
|
|
|
|
NTSTATUS Status;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
HANDLE PipeHandle;
|
|
|
|
ACCESS_MASK DesiredAccess;
|
|
|
|
ULONG CreateOptions = 0;
|
|
|
|
ULONG WriteModeMessage;
|
|
|
|
ULONG ReadModeMessage;
|
|
|
|
ULONG NonBlocking;
|
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
ULONG ShareAccess = 0, Attributes;
|
|
|
|
LARGE_INTEGER DefaultTimeOut;
|
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
|
|
|
|
|
|
/* Check for valid instances */
|
|
|
|
if (nMaxInstances == 0 || nMaxInstances > PIPE_UNLIMITED_INSTANCES)
|
|
|
|
{
|
|
|
|
/* Fail */
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert to NT syntax */
|
2007-07-08 20:09:22 +00:00
|
|
|
if (nMaxInstances == PIPE_UNLIMITED_INSTANCES)
|
|
|
|
nMaxInstances = -1;
|
2005-11-09 00:44:37 +00:00
|
|
|
|
|
|
|
/* Convert the name */
|
2005-12-17 15:45:59 +00:00
|
|
|
Result = RtlDosPathNameToNtPathName_U(lpName,
|
2005-11-09 00:44:37 +00:00
|
|
|
&NamedPipeName,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
if (!Result)
|
|
|
|
{
|
|
|
|
/* Conversion failed */
|
2007-07-08 20:09:22 +00:00
|
|
|
SetLastError(ERROR_PATH_NOT_FOUND);
|
|
|
|
return INVALID_HANDLE_VALUE;
|
2005-11-09 00:44:37 +00:00
|
|
|
}
|
|
|
|
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("Pipe name: %wZ\n", &NamedPipeName);
|
|
|
|
TRACE("Pipe name: %S\n", NamedPipeName.Buffer);
|
2005-11-09 00:44:37 +00:00
|
|
|
|
|
|
|
/* Always case insensitive, check if we got extra attributes */
|
|
|
|
Attributes = OBJ_CASE_INSENSITIVE;
|
|
|
|
if(lpSecurityAttributes)
|
|
|
|
{
|
|
|
|
/* We did; get the security descriptor */
|
|
|
|
SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
|
|
|
|
|
|
|
|
/* And check if this is pipe's handle will beinheritable */
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpSecurityAttributes->bInheritHandle)
|
|
|
|
Attributes |= OBJ_INHERIT;
|
2005-11-09 00:44:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now we can initialize the object attributes */
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&NamedPipeName,
|
|
|
|
Attributes,
|
|
|
|
NULL,
|
|
|
|
SecurityDescriptor);
|
|
|
|
|
|
|
|
/* Setup the default Desired Access */
|
|
|
|
DesiredAccess = SYNCHRONIZE | (dwOpenMode & (WRITE_DAC |
|
|
|
|
WRITE_OWNER |
|
|
|
|
ACCESS_SYSTEM_SECURITY));
|
|
|
|
|
|
|
|
/* Convert to NT Create Flags */
|
|
|
|
if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
|
|
|
|
{
|
|
|
|
CreateOptions |= FILE_WRITE_THROUGH;
|
|
|
|
}
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2005-11-09 00:44:37 +00:00
|
|
|
if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
|
|
|
|
{
|
|
|
|
CreateOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
|
|
|
|
}
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
/* Handle all open modes */
|
2005-11-09 00:44:37 +00:00
|
|
|
if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
|
|
|
|
{
|
|
|
|
ShareAccess |= FILE_SHARE_READ;
|
|
|
|
DesiredAccess |= GENERIC_WRITE;
|
|
|
|
}
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2005-11-09 00:44:37 +00:00
|
|
|
if (dwOpenMode & PIPE_ACCESS_INBOUND)
|
|
|
|
{
|
|
|
|
ShareAccess |= FILE_SHARE_WRITE;
|
|
|
|
DesiredAccess |= GENERIC_READ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the type flags */
|
|
|
|
if (dwPipeMode & PIPE_TYPE_MESSAGE)
|
|
|
|
{
|
|
|
|
WriteModeMessage = FILE_PIPE_MESSAGE_TYPE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WriteModeMessage = FILE_PIPE_BYTE_STREAM_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the mode flags */
|
|
|
|
if (dwPipeMode & PIPE_READMODE_MESSAGE)
|
|
|
|
{
|
|
|
|
ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the blocking mode */
|
|
|
|
if (dwPipeMode & PIPE_NOWAIT)
|
|
|
|
{
|
|
|
|
NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NonBlocking = FILE_PIPE_QUEUE_OPERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if we have a timeout */
|
|
|
|
if (nDefaultTimeOut)
|
|
|
|
{
|
|
|
|
/* Convert the time to NT format */
|
2014-09-01 11:58:42 +00:00
|
|
|
DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000LL;
|
2005-11-09 00:44:37 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use default timeout of 50 ms */
|
|
|
|
DefaultTimeOut.QuadPart = -500000;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now create the pipe */
|
|
|
|
Status = NtCreateNamedPipeFile(&PipeHandle,
|
|
|
|
DesiredAccess,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&Iosb,
|
|
|
|
ShareAccess,
|
|
|
|
FILE_OPEN_IF,
|
|
|
|
CreateOptions,
|
|
|
|
WriteModeMessage,
|
|
|
|
ReadModeMessage,
|
|
|
|
NonBlocking,
|
|
|
|
nMaxInstances,
|
|
|
|
nInBufferSize,
|
|
|
|
nOutBufferSize,
|
|
|
|
&DefaultTimeOut);
|
|
|
|
|
2005-11-09 04:53:32 +00:00
|
|
|
/* Normalize special error codes */
|
|
|
|
if ((Status == STATUS_INVALID_DEVICE_REQUEST) ||
|
|
|
|
(Status == STATUS_NOT_SUPPORTED))
|
|
|
|
{
|
|
|
|
Status = STATUS_OBJECT_NAME_INVALID;
|
|
|
|
}
|
|
|
|
|
2005-11-09 00:44:37 +00:00
|
|
|
/* Free the name */
|
2006-01-22 13:41:39 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(),
|
|
|
|
0,
|
|
|
|
NamedPipeName.Buffer);
|
2005-11-09 00:44:37 +00:00
|
|
|
|
|
|
|
/* Check status */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Failed to create it */
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN("NtCreateNamedPipe failed (Status %x)!\n", Status);
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError (Status);
|
2005-11-09 00:44:37 +00:00
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the handle */
|
|
|
|
return PipeHandle;
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-09 02:50:54 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
WaitNamedPipeA(LPCSTR lpNamedPipeName,
|
2005-11-09 02:50:54 +00:00
|
|
|
DWORD nTimeOut)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
2017-10-23 11:39:44 +00:00
|
|
|
BOOL r = FALSE;
|
2005-11-09 02:50:54 +00:00
|
|
|
UNICODE_STRING NameU;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-11-09 02:50:54 +00:00
|
|
|
/* Convert the name to Unicode */
|
2017-10-23 11:39:44 +00:00
|
|
|
if (Basep8BitStringToDynamicUnicodeString(&NameU, lpNamedPipeName))
|
|
|
|
{
|
|
|
|
/* Call the Unicode API */
|
|
|
|
r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2017-10-23 11:39:44 +00:00
|
|
|
/* Free the Unicode string */
|
|
|
|
RtlFreeUnicodeString(&NameU);
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-11-09 02:50:54 +00:00
|
|
|
/* Return result */
|
|
|
|
return r;
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
WaitNamedPipeW(LPCWSTR lpNamedPipeName,
|
|
|
|
DWORD nTimeOut)
|
|
|
|
{
|
|
|
|
UNICODE_STRING NamedPipeName, NewName, DevicePath, PipePrefix;
|
|
|
|
ULONG NameLength;
|
|
|
|
ULONG i;
|
|
|
|
PWCHAR p;
|
|
|
|
ULONG Type;
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
NTSTATUS Status;
|
|
|
|
HANDLE FileHandle;
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
ULONG WaitPipeInfoSize;
|
2017-10-29 19:34:49 +00:00
|
|
|
PVOID DevicePathBuffer;
|
2005-11-08 21:07:11 +00:00
|
|
|
PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo;
|
|
|
|
|
|
|
|
/* Start by making a unicode string of the name */
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("Sent path: %S\n", lpNamedPipeName);
|
2013-09-13 22:27:41 +00:00
|
|
|
if (!RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-11-08 21:07:11 +00:00
|
|
|
NameLength = NamedPipeName.Length / sizeof(WCHAR);
|
|
|
|
|
|
|
|
/* All slashes must become backslashes */
|
|
|
|
for (i = 0; i < NameLength; i++)
|
|
|
|
{
|
|
|
|
/* Check and convert */
|
|
|
|
if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\';
|
|
|
|
}
|
|
|
|
|
2017-10-29 19:34:49 +00:00
|
|
|
DevicePathBuffer = NULL;
|
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
/* Find the path type of the name we were given */
|
|
|
|
NewName = NamedPipeName;
|
|
|
|
Type = RtlDetermineDosPathNameType_U(lpNamedPipeName);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
/* Check if this was a device path, ie : "\\.\pipe\name" */
|
2007-03-04 21:14:58 +00:00
|
|
|
if (Type == RtlPathTypeLocalDevice)
|
2005-11-08 21:07:11 +00:00
|
|
|
{
|
|
|
|
/* Make sure it's a valid prefix */
|
|
|
|
RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\");
|
2013-09-13 22:27:41 +00:00
|
|
|
if (!RtlPrefixUnicodeString(&PipePrefix, &NewName, TRUE))
|
|
|
|
{
|
|
|
|
/* The name is invalid */
|
|
|
|
WARN("Invalid name!\n");
|
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
|
|
|
BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-11-08 21:07:11 +00:00
|
|
|
|
|
|
|
/* Move past it */
|
2013-09-14 09:12:12 +00:00
|
|
|
NewName.Buffer += PipePrefix.Length / sizeof(WCHAR);
|
|
|
|
NewName.Length -= PipePrefix.Length;
|
|
|
|
NewName.MaximumLength -= PipePrefix.Length;
|
2005-11-08 21:07:11 +00:00
|
|
|
|
|
|
|
/* Initialize the Dos Devices name */
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("NewName: %wZ\n", &NewName);
|
2005-11-08 21:07:11 +00:00
|
|
|
RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\");
|
|
|
|
}
|
2013-09-13 22:27:41 +00:00
|
|
|
else if (Type == RtlPathTypeUncAbsolute)
|
2005-11-08 21:07:11 +00:00
|
|
|
{
|
2017-10-29 19:34:49 +00:00
|
|
|
PWSTR PipeName;
|
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
/* The path is \\server\\pipe\name; find the pipename itself */
|
|
|
|
p = &NewName.Buffer[2];
|
|
|
|
|
|
|
|
/* First loop to get past the server name */
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* Check if this is a backslash */
|
|
|
|
if (*p == L'\\') break;
|
|
|
|
|
|
|
|
/* Check next */
|
|
|
|
p++;
|
|
|
|
} while (*p);
|
|
|
|
|
|
|
|
/* Now make sure the full name contains "pipe\" */
|
2013-09-14 09:12:12 +00:00
|
|
|
if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\") - sizeof(ANSI_NULL))))
|
2005-11-08 21:07:11 +00:00
|
|
|
{
|
|
|
|
/* Get to the pipe name itself now */
|
2013-09-14 09:12:12 +00:00
|
|
|
p += sizeof("pipe\\") - sizeof(ANSI_NULL);
|
2005-11-08 21:07:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The name is invalid */
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN("Invalid name!\n");
|
2013-09-13 22:27:41 +00:00
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
2005-11-08 21:07:11 +00:00
|
|
|
}
|
|
|
|
|
2017-10-29 19:34:49 +00:00
|
|
|
/* Skip first backslash */
|
|
|
|
NewName.Buffer++;
|
|
|
|
/* And skip pipe for copying name */
|
|
|
|
PipeName = p + ((sizeof(L"pipe\\") - sizeof(UNICODE_NULL)) / sizeof(WCHAR));
|
|
|
|
/* Update the string */
|
|
|
|
NewName.Length = (USHORT)((ULONG_PTR)PipeName - (ULONG_PTR)NewName.Buffer);
|
|
|
|
NewName.MaximumLength = (USHORT)((ULONG_PTR)PipeName - (ULONG_PTR)NewName.Buffer);
|
|
|
|
|
|
|
|
/* DevicePath will contain the pipename + the DosDevice prefix */
|
|
|
|
DevicePath.MaximumLength = (USHORT)((ULONG_PTR)PipeName - (ULONG_PTR)NewName.Buffer) + sizeof(L"\\DosDevices\\UNC\\");
|
|
|
|
|
|
|
|
/* Allocate the buffer for DevicePath */
|
|
|
|
DevicePathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DevicePath.MaximumLength);
|
|
|
|
if (DevicePathBuffer == NULL)
|
|
|
|
{
|
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the prefix first */
|
|
|
|
DevicePath.Buffer = DevicePathBuffer;
|
|
|
|
RtlCopyMemory(DevicePathBuffer, L"\\DosDevices\\UNC\\", sizeof(L"\\DosDevices\\UNC\\") - sizeof(UNICODE_NULL));
|
|
|
|
DevicePath.Length = sizeof(L"\\DosDevices\\UNC\\") - sizeof(UNICODE_NULL);
|
|
|
|
/* And append the rest */
|
|
|
|
RtlAppendUnicodeStringToString(&DevicePath, &NewName);
|
|
|
|
/* And fix pipe name without its prefix */
|
|
|
|
RtlInitUnicodeString(&NewName, PipeName + 1);
|
2005-11-08 21:07:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN("Invalid path type\n");
|
2013-09-13 22:27:41 +00:00
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD);
|
2005-11-08 21:07:11 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-12-11 20:04:38 +00:00
|
|
|
/* Now calculate the total length of the structure and allocate it */
|
|
|
|
WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) +
|
|
|
|
NewName.Length;
|
|
|
|
WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize);
|
|
|
|
if (WaitPipeInfo == NULL)
|
|
|
|
{
|
2017-10-29 19:34:49 +00:00
|
|
|
if (DevicePathBuffer != NULL)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DevicePathBuffer);
|
|
|
|
}
|
|
|
|
|
2013-09-13 22:27:41 +00:00
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
2005-12-11 20:04:38 +00:00
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
/* Initialize the object attributes */
|
2008-05-12 12:01:51 +00:00
|
|
|
TRACE("Opening: %wZ\n", &DevicePath);
|
2005-11-08 21:07:11 +00:00
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
|
|
&DevicePath,
|
|
|
|
OBJ_CASE_INSENSITIVE,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Open the path */
|
|
|
|
Status = NtOpenFile(&FileHandle,
|
|
|
|
FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
|
|
|
&ObjectAttributes,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
2017-10-29 19:34:49 +00:00
|
|
|
|
|
|
|
if (DevicePathBuffer != NULL)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DevicePathBuffer);
|
|
|
|
}
|
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Fail; couldn't open */
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN("Status: %lx\n", Status);
|
2005-12-11 20:04:38 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
|
2013-09-13 22:27:41 +00:00
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
2005-11-08 21:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check what timeout we got */
|
|
|
|
if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
|
|
|
|
{
|
|
|
|
/* Don't use a timeout */
|
|
|
|
WaitPipeInfo->TimeoutSpecified = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Check if we should wait forever */
|
|
|
|
if (nTimeOut == NMPWAIT_WAIT_FOREVER)
|
|
|
|
{
|
|
|
|
/* Set the max */
|
|
|
|
WaitPipeInfo->Timeout.LowPart = 0;
|
|
|
|
WaitPipeInfo->Timeout.HighPart = 0x80000000;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Convert to NT format */
|
2014-09-01 11:58:42 +00:00
|
|
|
WaitPipeInfo->Timeout.QuadPart = nTimeOut * -10000LL;
|
2005-11-08 21:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* In both cases, we do have a timeout */
|
2008-01-09 22:03:42 +00:00
|
|
|
WaitPipeInfo->TimeoutSpecified = TRUE;
|
2005-11-08 21:07:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the length and copy the name */
|
|
|
|
WaitPipeInfo->NameLength = NewName.Length;
|
|
|
|
RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length);
|
|
|
|
|
|
|
|
/* Get rid of the full name */
|
|
|
|
RtlFreeUnicodeString(&NamedPipeName);
|
|
|
|
|
|
|
|
/* Let NPFS know of our request */
|
|
|
|
Status = NtFsControlFile(FileHandle,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&IoStatusBlock,
|
|
|
|
FSCTL_PIPE_WAIT,
|
|
|
|
WaitPipeInfo,
|
|
|
|
WaitPipeInfoSize,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
|
|
|
|
/* Free our pipe info data and close the handle */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
|
|
|
|
NtClose(FileHandle);
|
|
|
|
|
|
|
|
/* Check the status */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Failure to wait on the pipe */
|
2008-05-12 12:01:51 +00:00
|
|
|
WARN("Status: %lx\n", Status);
|
2013-09-13 22:27:41 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2005-11-08 21:07:11 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2001-08-07 14:13:45 +00:00
|
|
|
|
2005-11-08 21:07:11 +00:00
|
|
|
/* Success */
|
|
|
|
return TRUE;
|
|
|
|
}
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2007-07-08 20:09:22 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2005-05-06 16:07:51 +00:00
|
|
|
ConnectNamedPipe(IN HANDLE hNamedPipe,
|
|
|
|
IN LPOVERLAPPED lpOverlapped)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
NTSTATUS Status;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpOverlapped != NULL)
|
|
|
|
{
|
2005-05-06 16:07:51 +00:00
|
|
|
PVOID ApcContext;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-05-06 16:07:51 +00:00
|
|
|
lpOverlapped->Internal = STATUS_PENDING;
|
|
|
|
ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-05-06 16:07:51 +00:00
|
|
|
Status = NtFsControlFile(hNamedPipe,
|
|
|
|
lpOverlapped->hEvent,
|
|
|
|
NULL,
|
|
|
|
ApcContext,
|
|
|
|
(PIO_STATUS_BLOCK)lpOverlapped,
|
|
|
|
FSCTL_PIPE_LISTEN,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
|
|
|
|
/* return FALSE in case of failure and pending operations! */
|
2005-05-21 17:02:38 +00:00
|
|
|
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-05-06 16:07:51 +00:00
|
|
|
IO_STATUS_BLOCK Iosb;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-05-06 16:07:51 +00:00
|
|
|
Status = NtFsControlFile(hNamedPipe,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
FSCTL_PIPE_LISTEN,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
|
|
|
|
/* wait in case operation is pending */
|
|
|
|
if (Status == STATUS_PENDING)
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
2005-05-06 16:07:51 +00:00
|
|
|
Status = NtWaitForSingleObject(hNamedPipe,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
|
|
|
Status = Iosb.Status;
|
|
|
|
}
|
|
|
|
}
|
2005-05-06 16:07:51 +00:00
|
|
|
|
2005-05-21 17:02:38 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2005-05-06 16:07:51 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
return TRUE;
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-05 16:11:31 +00:00
|
|
|
BOOL
|
2007-07-08 20:09:22 +00:00
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
SetNamedPipeHandleState(HANDLE hNamedPipe,
|
2005-06-20 01:52:47 +00:00
|
|
|
LPDWORD lpMode,
|
|
|
|
LPDWORD lpMaxCollectionCount,
|
|
|
|
LPDWORD lpCollectDataTimeout)
|
2000-05-13 13:51:08 +00:00
|
|
|
{
|
2005-06-20 01:52:47 +00:00
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
/* Check if the Mode is being changed */
|
|
|
|
if (lpMode)
|
|
|
|
{
|
|
|
|
FILE_PIPE_INFORMATION Settings;
|
|
|
|
|
|
|
|
/* Set the Completion Mode */
|
|
|
|
Settings.CompletionMode = (*lpMode & PIPE_NOWAIT) ?
|
|
|
|
FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
|
|
|
|
|
|
|
|
/* Set the Read Mode */
|
|
|
|
Settings.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE) ?
|
|
|
|
FILE_PIPE_MESSAGE_MODE: FILE_PIPE_BYTE_STREAM_MODE;
|
|
|
|
|
2005-11-05 16:11:31 +00:00
|
|
|
/* Send the changes to the Driver */
|
2005-06-20 01:52:47 +00:00
|
|
|
Status = NtSetInformationFile(hNamedPipe,
|
|
|
|
&Iosb,
|
|
|
|
&Settings,
|
|
|
|
sizeof(FILE_PIPE_INFORMATION),
|
|
|
|
FilePipeInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
2005-06-20 01:52:47 +00:00
|
|
|
}
|
|
|
|
}
|
2005-11-05 16:11:31 +00:00
|
|
|
|
2005-06-20 01:52:47 +00:00
|
|
|
/* Check if the Collection count or Timeout are being changed */
|
|
|
|
if (lpMaxCollectionCount || lpCollectDataTimeout)
|
|
|
|
{
|
|
|
|
FILE_PIPE_REMOTE_INFORMATION RemoteSettings;
|
|
|
|
|
|
|
|
/* Setting one without the other would delete it, so we read old one */
|
|
|
|
if (!lpMaxCollectionCount || !lpCollectDataTimeout)
|
|
|
|
{
|
|
|
|
Status = NtQueryInformationFile(hNamedPipe,
|
|
|
|
&Iosb,
|
|
|
|
&RemoteSettings,
|
|
|
|
sizeof(FILE_PIPE_REMOTE_INFORMATION),
|
|
|
|
FilePipeRemoteInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
2005-06-20 01:52:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-05 16:11:31 +00:00
|
|
|
/* Now set the new settings */
|
|
|
|
RemoteSettings.MaximumCollectionCount = (lpMaxCollectionCount) ?
|
|
|
|
*lpMaxCollectionCount :
|
2005-06-20 01:52:47 +00:00
|
|
|
RemoteSettings.MaximumCollectionCount;
|
|
|
|
if (lpCollectDataTimeout)
|
|
|
|
{
|
|
|
|
/* Convert it to Quad */
|
2014-09-01 11:58:42 +00:00
|
|
|
RemoteSettings.CollectDataTime.QuadPart = *lpCollectDataTimeout * -10000LL;
|
2005-06-20 01:52:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Tell the driver to change them */
|
|
|
|
Status = NtSetInformationFile(hNamedPipe,
|
|
|
|
&Iosb,
|
|
|
|
&RemoteSettings,
|
|
|
|
sizeof(FILE_PIPE_REMOTE_INFORMATION),
|
|
|
|
FilePipeRemoteInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
2005-06-20 01:52:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2000-05-13 13:51:08 +00:00
|
|
|
}
|
2000-05-14 09:31:05 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-09 02:53:58 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-08-07 14:13:45 +00:00
|
|
|
CallNamedPipeA(LPCSTR lpNamedPipeName,
|
2005-11-09 02:53:58 +00:00
|
|
|
LPVOID lpInBuffer,
|
|
|
|
DWORD nInBufferSize,
|
|
|
|
LPVOID lpOutBuffer,
|
|
|
|
DWORD nOutBufferSize,
|
|
|
|
LPDWORD lpBytesRead,
|
|
|
|
DWORD nTimeOut)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2005-11-09 03:02:33 +00:00
|
|
|
PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
|
2005-11-09 02:53:58 +00:00
|
|
|
ANSI_STRING AnsiPipe;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-11-09 02:53:58 +00:00
|
|
|
/* Initialize the string as ANSI_STRING and convert to Unicode */
|
2005-11-09 03:02:33 +00:00
|
|
|
RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName);
|
|
|
|
RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-11-09 02:53:58 +00:00
|
|
|
/* Call the Unicode function */
|
|
|
|
return CallNamedPipeW(PipeName->Buffer,
|
|
|
|
lpInBuffer,
|
|
|
|
nInBufferSize,
|
|
|
|
lpOutBuffer,
|
|
|
|
nOutBufferSize,
|
|
|
|
lpBytesRead,
|
|
|
|
nTimeOut);
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-09 03:02:33 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-08-07 14:13:45 +00:00
|
|
|
CallNamedPipeW(LPCWSTR lpNamedPipeName,
|
2005-11-09 03:02:33 +00:00
|
|
|
LPVOID lpInBuffer,
|
|
|
|
DWORD nInBufferSize,
|
|
|
|
LPVOID lpOutBuffer,
|
|
|
|
DWORD nOutBufferSize,
|
|
|
|
LPDWORD lpBytesRead,
|
|
|
|
DWORD nTimeOut)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2005-11-09 03:02:33 +00:00
|
|
|
HANDLE hPipe;
|
|
|
|
BOOL bRetry = TRUE;
|
|
|
|
BOOL bError;
|
|
|
|
DWORD dwPipeMode;
|
2002-06-25 18:49:38 +00:00
|
|
|
|
2005-11-09 03:02:33 +00:00
|
|
|
while (TRUE)
|
2002-06-25 18:49:38 +00:00
|
|
|
{
|
2005-11-09 03:02:33 +00:00
|
|
|
/* Try creating it */
|
|
|
|
hPipe = CreateFileW(lpNamedPipeName,
|
|
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
NULL,
|
|
|
|
OPEN_EXISTING,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* Success, break out */
|
2007-07-08 20:09:22 +00:00
|
|
|
if (hPipe != INVALID_HANDLE_VALUE)
|
|
|
|
break;
|
2005-11-09 03:02:33 +00:00
|
|
|
|
|
|
|
/* Already tried twice, give up */
|
2007-07-08 20:09:22 +00:00
|
|
|
if (bRetry == FALSE)
|
|
|
|
return FALSE;
|
2005-11-09 03:02:33 +00:00
|
|
|
|
|
|
|
/* Wait on it */
|
|
|
|
WaitNamedPipeW(lpNamedPipeName, nTimeOut);
|
|
|
|
|
|
|
|
/* Get ready to try again */
|
|
|
|
bRetry = FALSE;
|
2002-06-25 18:49:38 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 03:02:33 +00:00
|
|
|
/* Set the pipe mode */
|
|
|
|
dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
|
|
|
|
bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL);
|
|
|
|
if (!bError)
|
2002-06-25 18:49:38 +00:00
|
|
|
{
|
2005-11-09 03:02:33 +00:00
|
|
|
/* Couldn't change state, fail */
|
|
|
|
CloseHandle(hPipe);
|
|
|
|
return FALSE;
|
2002-06-25 18:49:38 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 03:02:33 +00:00
|
|
|
/* Do the transact */
|
|
|
|
bError = TransactNamedPipe(hPipe,
|
|
|
|
lpInBuffer,
|
|
|
|
nInBufferSize,
|
|
|
|
lpOutBuffer,
|
|
|
|
nOutBufferSize,
|
|
|
|
lpBytesRead,
|
|
|
|
NULL);
|
2007-07-08 20:09:22 +00:00
|
|
|
|
|
|
|
/* Close the handle */
|
2005-11-09 03:02:33 +00:00
|
|
|
CloseHandle(hPipe);
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2005-11-09 03:02:33 +00:00
|
|
|
return bError;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2007-07-08 20:09:22 +00:00
|
|
|
BOOL
|
2005-11-09 04:32:44 +00:00
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
DisconnectNamedPipe(HANDLE hNamedPipe)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
NTSTATUS Status;
|
2001-05-10 23:38:31 +00:00
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Send the FSCTL to the driver */
|
|
|
|
Status = NtFsControlFile(hNamedPipe,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
FSCTL_PIPE_DISCONNECT,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
if (Status == STATUS_PENDING)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Wait on NPFS to finish and get updated status */
|
|
|
|
Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
|
2007-07-08 20:09:22 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
Status = Iosb.Status;
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
2001-05-10 23:38:31 +00:00
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Check for error */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Fail */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2005-11-09 04:32:44 +00:00
|
|
|
return FALSE;
|
2007-07-08 20:09:22 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
return TRUE;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
2007-07-08 20:09:22 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-08-07 14:13:45 +00:00
|
|
|
GetNamedPipeHandleStateW(HANDLE hNamedPipe,
|
2007-07-08 20:09:22 +00:00
|
|
|
LPDWORD lpState,
|
|
|
|
LPDWORD lpCurInstances,
|
|
|
|
LPDWORD lpMaxCollectionCount,
|
|
|
|
LPDWORD lpCollectDataTimeout,
|
|
|
|
LPWSTR lpUserName,
|
|
|
|
DWORD nMaxUserNameSize)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
IO_STATUS_BLOCK StatusBlock;
|
|
|
|
NTSTATUS Status;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpState != NULL)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
FILE_PIPE_INFORMATION PipeInfo;
|
2004-10-08 21:25:18 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
Status = NtQueryInformationFile(hNamedPipe,
|
|
|
|
&StatusBlock,
|
|
|
|
&PipeInfo,
|
|
|
|
sizeof(FILE_PIPE_INFORMATION),
|
|
|
|
FilePipeInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
*lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
|
|
|
|
*lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if(lpCurInstances != NULL)
|
|
|
|
{
|
|
|
|
FILE_PIPE_LOCAL_INFORMATION LocalInfo;
|
2004-10-08 21:25:18 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
Status = NtQueryInformationFile(hNamedPipe,
|
|
|
|
&StatusBlock,
|
|
|
|
&LocalInfo,
|
|
|
|
sizeof(FILE_PIPE_LOCAL_INFORMATION),
|
|
|
|
FilePipeLocalInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
*lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
|
2004-10-08 21:25:18 +00:00
|
|
|
}
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
|
2004-10-08 21:25:18 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
FILE_PIPE_REMOTE_INFORMATION RemoteInfo;
|
|
|
|
|
|
|
|
Status = NtQueryInformationFile(hNamedPipe,
|
|
|
|
&StatusBlock,
|
|
|
|
&RemoteInfo,
|
|
|
|
sizeof(FILE_PIPE_REMOTE_INFORMATION),
|
|
|
|
FilePipeRemoteInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpMaxCollectionCount != NULL)
|
|
|
|
{
|
|
|
|
*lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
|
|
|
|
}
|
|
|
|
|
2017-10-23 12:36:18 +00:00
|
|
|
if (lpCollectDataTimeout != NULL)
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
2017-10-23 12:36:18 +00:00
|
|
|
LARGE_INTEGER CollectDataTime;
|
|
|
|
|
|
|
|
/* Convert time and return it */
|
|
|
|
RemoteInfo.CollectDataTime.QuadPart *= -1;
|
|
|
|
CollectDataTime = RtlExtendedLargeIntegerDivide(RemoteInfo.CollectDataTime, 10000, NULL);
|
|
|
|
/* In case of overflow, just return MAX - 1 */
|
|
|
|
if (CollectDataTime.HighPart != 0)
|
|
|
|
{
|
|
|
|
*lpCollectDataTimeout = -2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*lpCollectDataTimeout = CollectDataTime.LowPart;
|
|
|
|
}
|
2007-07-08 20:09:22 +00:00
|
|
|
}
|
2004-10-08 21:25:18 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpUserName != NULL)
|
2004-10-08 21:25:18 +00:00
|
|
|
{
|
2017-10-23 12:36:18 +00:00
|
|
|
return NpGetUserNamep(hNamedPipe, lpUserName, nMaxUserNameSize);
|
2004-10-08 21:25:18 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
return TRUE;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
2004-10-08 21:25:18 +00:00
|
|
|
* @implemented
|
2003-07-10 18:50:51 +00:00
|
|
|
*/
|
2007-07-08 20:09:22 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-08-07 14:13:45 +00:00
|
|
|
GetNamedPipeHandleStateA(HANDLE hNamedPipe,
|
2007-07-08 20:09:22 +00:00
|
|
|
LPDWORD lpState,
|
|
|
|
LPDWORD lpCurInstances,
|
|
|
|
LPDWORD lpMaxCollectionCount,
|
|
|
|
LPDWORD lpCollectDataTimeout,
|
|
|
|
LPSTR lpUserName,
|
|
|
|
DWORD nMaxUserNameSize)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2008-12-03 17:33:13 +00:00
|
|
|
UNICODE_STRING UserNameW = { 0, 0, NULL };
|
2007-07-08 20:09:22 +00:00
|
|
|
ANSI_STRING UserNameA;
|
|
|
|
BOOL Ret;
|
|
|
|
|
|
|
|
if(lpUserName != NULL)
|
2005-12-11 19:36:43 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
UserNameW.MaximumLength = (USHORT)nMaxUserNameSize * sizeof(WCHAR);
|
|
|
|
UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
|
|
|
|
if (UserNameW.Buffer == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
UserNameA.Buffer = lpUserName;
|
|
|
|
UserNameA.Length = 0;
|
|
|
|
UserNameA.MaximumLength = (USHORT)nMaxUserNameSize;
|
|
|
|
}
|
2005-12-11 19:36:43 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
Ret = GetNamedPipeHandleStateW(hNamedPipe,
|
|
|
|
lpState,
|
|
|
|
lpCurInstances,
|
|
|
|
lpMaxCollectionCount,
|
|
|
|
lpCollectDataTimeout,
|
|
|
|
UserNameW.Buffer,
|
|
|
|
nMaxUserNameSize);
|
|
|
|
if (Ret && lpUserName != NULL)
|
2004-10-08 21:25:18 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
|
|
|
|
Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
Ret = FALSE;
|
|
|
|
}
|
2004-10-08 21:25:18 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (UserNameW.Buffer != NULL)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
return Ret;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2007-07-08 20:09:22 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
GetNamedPipeInfo(HANDLE hNamedPipe,
|
2007-07-08 20:09:22 +00:00
|
|
|
LPDWORD lpFlags,
|
|
|
|
LPDWORD lpOutBufferSize,
|
|
|
|
LPDWORD lpInBufferSize,
|
|
|
|
LPDWORD lpMaxInstances)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
|
|
|
|
IO_STATUS_BLOCK StatusBlock;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = NtQueryInformationFile(hNamedPipe,
|
|
|
|
&StatusBlock,
|
|
|
|
&PipeLocalInformation,
|
|
|
|
sizeof(FILE_PIPE_LOCAL_INFORMATION),
|
|
|
|
FilePipeLocalInformation);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-08-07 14:13:45 +00:00
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
2001-08-07 14:13:45 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpFlags != NULL)
|
2001-08-07 14:13:45 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
*lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
|
|
|
|
*lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
|
2001-08-07 14:13:45 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpOutBufferSize != NULL)
|
|
|
|
*lpOutBufferSize = PipeLocalInformation.OutboundQuota;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpInBufferSize != NULL)
|
|
|
|
*lpInBufferSize = PipeLocalInformation.InboundQuota;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpMaxInstances != NULL)
|
2001-08-07 14:13:45 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
if (PipeLocalInformation.MaximumInstances >= 255)
|
|
|
|
*lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
|
|
|
|
else
|
|
|
|
*lpMaxInstances = PipeLocalInformation.MaximumInstances;
|
2001-08-07 14:13:45 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
return TRUE;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2005-11-09 04:32:44 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2001-05-10 23:38:31 +00:00
|
|
|
PeekNamedPipe(HANDLE hNamedPipe,
|
2005-11-09 04:32:44 +00:00
|
|
|
LPVOID lpBuffer,
|
|
|
|
DWORD nBufferSize,
|
|
|
|
LPDWORD lpBytesRead,
|
|
|
|
LPDWORD lpTotalBytesAvail,
|
|
|
|
LPDWORD lpBytesLeftThisMessage)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
PFILE_PIPE_PEEK_BUFFER Buffer;
|
|
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
ULONG BufferSize;
|
2007-07-08 20:09:22 +00:00
|
|
|
ULONG BytesRead;
|
2005-11-09 04:32:44 +00:00
|
|
|
NTSTATUS Status;
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Calculate the buffer space that we'll need and allocate it */
|
2012-09-22 09:18:34 +00:00
|
|
|
BufferSize = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[nBufferSize]);
|
2005-11-09 04:32:44 +00:00
|
|
|
Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
|
2005-12-11 20:04:38 +00:00
|
|
|
if (Buffer == NULL)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Tell the driver to seek */
|
|
|
|
Status = NtFsControlFile(hNamedPipe,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
FSCTL_PIPE_PEEK,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
Buffer,
|
|
|
|
BufferSize);
|
|
|
|
if (Status == STATUS_PENDING)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Wait for npfs to be done, and update the status */
|
|
|
|
Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
|
2007-07-08 20:09:22 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
Status = Iosb.Status;
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Overflow is success for us */
|
2007-07-08 20:09:22 +00:00
|
|
|
if (Status == STATUS_BUFFER_OVERFLOW)
|
|
|
|
Status = STATUS_SUCCESS;
|
2001-11-20 20:35:10 +00:00
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* If we failed */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Free the buffer and return failure */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2005-11-09 04:32:44 +00:00
|
|
|
return FALSE;
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Check if caller requested bytes available */
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpTotalBytesAvail)
|
2012-09-22 09:18:34 +00:00
|
|
|
{
|
|
|
|
/* Return bytes available */
|
2007-07-08 20:09:22 +00:00
|
|
|
*lpTotalBytesAvail = Buffer->ReadDataAvailable;
|
2012-09-22 09:18:34 +00:00
|
|
|
}
|
2007-07-08 20:09:22 +00:00
|
|
|
|
|
|
|
/* Calculate the bytes returned, minus our structure overhead */
|
|
|
|
BytesRead = (ULONG)(Iosb.Information -
|
2007-07-08 20:39:27 +00:00
|
|
|
FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
|
2012-09-22 09:18:34 +00:00
|
|
|
ASSERT(BytesRead <= nBufferSize);
|
2005-11-09 04:32:44 +00:00
|
|
|
|
|
|
|
/* Check if caller requested bytes read */
|
|
|
|
if (lpBytesRead)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
/* Return the bytes read */
|
|
|
|
*lpBytesRead = BytesRead;
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Check if caller requested bytes left */
|
|
|
|
if (lpBytesLeftThisMessage)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Calculate total minus what we returned and our structure overhead */
|
2007-07-08 20:09:22 +00:00
|
|
|
*lpBytesLeftThisMessage = Buffer->MessageLength - BytesRead;
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Check if the caller wanted to see the actual data */
|
|
|
|
if (lpBuffer)
|
2001-11-20 20:35:10 +00:00
|
|
|
{
|
2005-11-09 04:32:44 +00:00
|
|
|
/* Give him what he wants */
|
|
|
|
RtlCopyMemory(lpBuffer,
|
|
|
|
Buffer->Data,
|
2007-07-08 20:09:22 +00:00
|
|
|
BytesRead);
|
2001-11-20 20:35:10 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
/* Free the buffer */
|
2005-11-09 04:32:44 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2005-11-09 04:32:44 +00:00
|
|
|
return TRUE;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2007-07-08 20:09:22 +00:00
|
|
|
BOOL
|
|
|
|
WINAPI
|
2005-05-06 16:47:09 +00:00
|
|
|
TransactNamedPipe(IN HANDLE hNamedPipe,
|
|
|
|
IN LPVOID lpInBuffer,
|
|
|
|
IN DWORD nInBufferSize,
|
|
|
|
OUT LPVOID lpOutBuffer,
|
|
|
|
IN DWORD nOutBufferSize,
|
|
|
|
OUT LPDWORD lpBytesRead OPTIONAL,
|
|
|
|
IN LPOVERLAPPED lpOverlapped OPTIONAL)
|
2001-03-31 01:17:30 +00:00
|
|
|
{
|
2007-07-08 20:09:22 +00:00
|
|
|
NTSTATUS Status;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpBytesRead != NULL)
|
|
|
|
{
|
2005-05-06 16:47:09 +00:00
|
|
|
*lpBytesRead = 0;
|
2007-07-08 20:09:22 +00:00
|
|
|
}
|
2002-06-25 18:49:38 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
if (lpOverlapped != NULL)
|
|
|
|
{
|
2005-05-06 16:47:09 +00:00
|
|
|
PVOID ApcContext;
|
2002-06-25 18:49:38 +00:00
|
|
|
|
2005-05-06 16:47:09 +00:00
|
|
|
ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
|
|
|
|
lpOverlapped->Internal = STATUS_PENDING;
|
2002-06-25 18:49:38 +00:00
|
|
|
|
2005-05-06 16:47:09 +00:00
|
|
|
Status = NtFsControlFile(hNamedPipe,
|
|
|
|
lpOverlapped->hEvent,
|
|
|
|
NULL,
|
|
|
|
ApcContext,
|
|
|
|
(PIO_STATUS_BLOCK)lpOverlapped,
|
|
|
|
FSCTL_PIPE_TRANSCEIVE,
|
|
|
|
lpInBuffer,
|
|
|
|
nInBufferSize,
|
|
|
|
lpOutBuffer,
|
|
|
|
nOutBufferSize);
|
|
|
|
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2005-05-06 16:47:09 +00:00
|
|
|
|
|
|
|
if (lpBytesRead != NULL)
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
|
|
|
*lpBytesRead = lpOverlapped->InternalHigh;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-05-06 16:47:09 +00:00
|
|
|
IO_STATUS_BLOCK Iosb;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2005-05-06 16:47:09 +00:00
|
|
|
Status = NtFsControlFile(hNamedPipe,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
&Iosb,
|
|
|
|
FSCTL_PIPE_TRANSCEIVE,
|
|
|
|
lpInBuffer,
|
|
|
|
nInBufferSize,
|
|
|
|
lpOutBuffer,
|
|
|
|
nOutBufferSize);
|
|
|
|
if (Status == STATUS_PENDING)
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
|
|
|
Status = NtWaitForSingleObject(hNamedPipe,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
Status = Iosb.Status;
|
|
|
|
}
|
2005-05-06 16:47:09 +00:00
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
|
|
|
/* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
|
|
|
|
check that case either and crashes (only after the operation
|
|
|
|
completed) */
|
|
|
|
*lpBytesRead = Iosb.Information;
|
|
|
|
}
|
2005-05-06 16:47:09 +00:00
|
|
|
else
|
2007-07-08 20:09:22 +00:00
|
|
|
{
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2007-07-08 20:09:22 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2005-05-06 16:47:09 +00:00
|
|
|
|
2007-07-08 20:09:22 +00:00
|
|
|
return TRUE;
|
2001-03-31 01:17:30 +00:00
|
|
|
}
|
|
|
|
|
2000-05-14 09:31:05 +00:00
|
|
|
/* EOF */
|