#include <k32.h>
#define NDEBUG
-#define USING_PROPER_NPFS_WAIT_SEMANTICS
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
#include "../include/debug.h"
/* FUNCTIONS ****************************************************************/
nOutBufferSize,
&DefaultTimeOut);
+ /* Normalize special error codes */
+ if ((Status == STATUS_INVALID_DEVICE_REQUEST) ||
+ (Status == STATUS_NOT_SUPPORTED))
+ {
+ Status = STATUS_OBJECT_NAME_INVALID;
+ }
+
/* Free the name */
RtlFreeUnicodeString(&NamedPipeName);
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+WINAPI
CallNamedPipeA(LPCSTR lpNamedPipeName,
- LPVOID lpInBuffer,
- DWORD nInBufferSize,
- LPVOID lpOutBuffer,
- DWORD nOutBufferSize,
- LPDWORD lpBytesRead,
- DWORD nTimeOut)
+ LPVOID lpInBuffer,
+ DWORD nInBufferSize,
+ LPVOID lpOutBuffer,
+ DWORD nOutBufferSize,
+ LPDWORD lpBytesRead,
+ DWORD nTimeOut)
{
- UNICODE_STRING PipeName;
- BOOL Result;
-
- RtlCreateUnicodeStringFromAsciiz(&PipeName,
- (LPSTR)lpNamedPipeName);
-
- Result = CallNamedPipeW(PipeName.Buffer,
- lpInBuffer,
- nInBufferSize,
- lpOutBuffer,
- nOutBufferSize,
- lpBytesRead,
- nTimeOut);
+ PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
+ ANSI_STRING AnsiPipe;
- RtlFreeUnicodeString(&PipeName);
-
- return(Result);
+ /* Initialize the string as ANSI_STRING and convert to Unicode */
+ RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName);
+ RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE);
+
+ /* Call the Unicode function */
+ return CallNamedPipeW(PipeName->Buffer,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize,
+ lpBytesRead,
+ nTimeOut);
}
-
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+WINAPI
CallNamedPipeW(LPCWSTR lpNamedPipeName,
- LPVOID lpInBuffer,
- DWORD nInBufferSize,
- LPVOID lpOutBuffer,
- DWORD nOutBufferSize,
- LPDWORD lpBytesRead,
- DWORD nTimeOut)
+ LPVOID lpInBuffer,
+ DWORD nInBufferSize,
+ LPVOID lpOutBuffer,
+ DWORD nOutBufferSize,
+ LPDWORD lpBytesRead,
+ DWORD nTimeOut)
{
- HANDLE hPipe = INVALID_HANDLE_VALUE;
- BOOL bRetry = TRUE;
- BOOL bError = FALSE;
- DWORD dwPipeMode;
+ HANDLE hPipe;
+ BOOL bRetry = TRUE;
+ BOOL bError;
+ DWORD dwPipeMode;
- while (TRUE)
+ while (TRUE)
{
- hPipe = CreateFileW(lpNamedPipeName,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if (hPipe != INVALID_HANDLE_VALUE)
- break;
-
- if (bRetry == FALSE)
- return(FALSE);
-
- WaitNamedPipeW(lpNamedPipeName,
- nTimeOut);
-
- bRetry = FALSE;
+ /* 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 */
+ if (hPipe != INVALID_HANDLE_VALUE) break;
+
+ /* Already tried twice, give up */
+ if (bRetry == FALSE) return FALSE;
+
+ /* Wait on it */
+ WaitNamedPipeW(lpNamedPipeName, nTimeOut);
+
+ /* Get ready to try again */
+ bRetry = FALSE;
}
- dwPipeMode = PIPE_READMODE_MESSAGE;
- bError = SetNamedPipeHandleState(hPipe,
- &dwPipeMode,
- NULL,
- NULL);
- if (!bError)
+ /* Set the pipe mode */
+ dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+ bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL);
+ if (!bError)
{
- CloseHandle(hPipe);
- return(FALSE);
+ /* Couldn't change state, fail */
+ CloseHandle(hPipe);
+ return FALSE;
}
- bError = TransactNamedPipe(hPipe,
- lpInBuffer,
- nInBufferSize,
- lpOutBuffer,
- nOutBufferSize,
- lpBytesRead,
- NULL);
- CloseHandle(hPipe);
-
- return(bError);
+ /* Do the transact */
+ bError = TransactNamedPipe(hPipe,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize,
+ lpBytesRead,
+ NULL);
+
+ /* Close the handle and return */
+ CloseHandle(hPipe);
+ return bError;
}
-
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+WINAPI
DisconnectNamedPipe(HANDLE hNamedPipe)
{
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
- Status = NtFsControlFile(hNamedPipe,
- NULL,
- NULL,
- NULL,
- &Iosb,
- FSCTL_PIPE_DISCONNECT,
- NULL,
- 0,
- NULL,
- 0);
- if (Status == STATUS_PENDING)
+ /* Send the FSCTL to the driver */
+ Status = NtFsControlFile(hNamedPipe,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ FSCTL_PIPE_DISCONNECT,
+ NULL,
+ 0,
+ NULL,
+ 0);
+ if (Status == STATUS_PENDING)
{
- Status = NtWaitForSingleObject(hNamedPipe,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
+ /* Wait on NPFS to finish and get updated status */
+ Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
+ if (NT_SUCCESS(Status)) Status = Iosb.Status;
}
- if (!NT_SUCCESS(Status))
+ /* Check for error */
+ if (!NT_SUCCESS(Status))
{
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
- return(TRUE);
+ /* Fail */
+ SetLastErrorByStatus(Status);
+ return FALSE;
+ }
+
+ return TRUE;
}
-
/*
* @unimplemented
*/
return(TRUE);
}
-
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+WINAPI
PeekNamedPipe(HANDLE hNamedPipe,
- LPVOID lpBuffer,
- DWORD nBufferSize,
- LPDWORD lpBytesRead,
- LPDWORD lpTotalBytesAvail,
- LPDWORD lpBytesLeftThisMessage)
+ LPVOID lpBuffer,
+ DWORD nBufferSize,
+ LPDWORD lpBytesRead,
+ LPDWORD lpTotalBytesAvail,
+ LPDWORD lpBytesLeftThisMessage)
{
- PFILE_PIPE_PEEK_BUFFER Buffer;
- IO_STATUS_BLOCK Iosb;
- ULONG BufferSize;
- NTSTATUS Status;
+ PFILE_PIPE_PEEK_BUFFER Buffer;
+ IO_STATUS_BLOCK Iosb;
+ ULONG BufferSize;
+ NTSTATUS Status;
- BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- BufferSize);
-
- Status = NtFsControlFile(hNamedPipe,
- NULL,
- NULL,
- NULL,
- &Iosb,
- FSCTL_PIPE_PEEK,
- NULL,
- 0,
- Buffer,
- BufferSize);
- if (Status == STATUS_PENDING)
- {
- Status = NtWaitForSingleObject(hNamedPipe,
- FALSE,
- NULL);
- if (NT_SUCCESS(Status))
- Status = Iosb.Status;
- }
+ /* Calculate the buffer space that we'll need and allocate it */
+ BufferSize = nBufferSize + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
- if (Status == STATUS_BUFFER_OVERFLOW)
+ /* Tell the driver to seek */
+ Status = NtFsControlFile(hNamedPipe,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ FSCTL_PIPE_PEEK,
+ NULL,
+ 0,
+ Buffer,
+ BufferSize);
+ if (Status == STATUS_PENDING)
{
- Status = STATUS_SUCCESS;
+ /* Wait for npfs to be done, and update the status */
+ Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
+ if (NT_SUCCESS(Status)) Status = Iosb.Status;
}
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
- SetLastErrorByStatus(Status);
- return(FALSE);
- }
+ /* Overflow is success for us */
+ if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_SUCCESS;
- if (lpTotalBytesAvail != NULL)
+ /* If we failed */
+ if (!NT_SUCCESS(Status))
{
- *lpTotalBytesAvail = Buffer->ReadDataAvailable;
+ /* Free the buffer and return failure */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ SetLastErrorByStatus(Status);
+ return FALSE;
}
- if (lpBytesRead != NULL)
+ /* Check if caller requested bytes available */
+ if (lpTotalBytesAvail) *lpTotalBytesAvail = Buffer->ReadDataAvailable;
+
+ /* Check if caller requested bytes read */
+ if (lpBytesRead)
{
- *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER);
+ /* Calculate the bytes returned, minus our structure overhead */
+ *lpBytesRead = (ULONG)(Iosb.Information -
+ FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
}
- if (lpBytesLeftThisMessage != NULL)
+ /* Check if caller requested bytes left */
+ if (lpBytesLeftThisMessage)
{
- *lpBytesLeftThisMessage = Buffer->MessageLength -
- (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER));
+ /* Calculate total minus what we returned and our structure overhead */
+ *lpBytesLeftThisMessage = Buffer->MessageLength -
+ (ULONG)(Iosb.Information -
+ FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
}
- if (lpBuffer != NULL)
+ /* Check if the caller wanted to see the actual data */
+ if (lpBuffer)
{
- memcpy(lpBuffer, Buffer->Data,
- min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)));
+ /* Give him what he wants */
+ RtlCopyMemory(lpBuffer,
+ Buffer->Data,
+ Iosb.Information -
+ FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
}
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
-
- return(TRUE);
+ /* Free the buffer and return success */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+ return TRUE;
}
-
/*
* @implemented
*/