-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS system libraries
+ * PROJECT: ReactOS Win32 Kernel Library
* FILE: lib/kernel32/file/npipe.c
- * PURPOSE: Directory functions
- * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
- * UPDATE HISTORY:
+ * PURPOSE: Named Pipe Functions
+ * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
+ * Ariadne ( ariadne@xs4all.nl)
*/
/* INCLUDES *****************************************************************/
/*
* @implemented
*/
-HANDLE STDCALL
+HANDLE
+WINAPI
CreateNamedPipeA(LPCSTR lpName,
- DWORD dwOpenMode,
- DWORD dwPipeMode,
- DWORD nMaxInstances,
- DWORD nOutBufferSize,
- DWORD nInBufferSize,
- DWORD nDefaultTimeOut,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes)
+ DWORD dwOpenMode,
+ DWORD dwPipeMode,
+ DWORD nMaxInstances,
+ DWORD nOutBufferSize,
+ DWORD nInBufferSize,
+ DWORD nDefaultTimeOut,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
- HANDLE NamedPipeHandle;
- UNICODE_STRING NameU;
- ANSI_STRING NameA;
-
- RtlInitAnsiString(&NameA, (LPSTR)lpName);
- RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
-
- NamedPipeHandle = CreateNamedPipeW(NameU.Buffer,
- dwOpenMode,
- dwPipeMode,
- nMaxInstances,
- nOutBufferSize,
- nInBufferSize,
- nDefaultTimeOut,
- lpSecurityAttributes);
-
- RtlFreeUnicodeString(&NameU);
-
- return(NamedPipeHandle);
+ PUNICODE_STRING NameU = &NtCurrentTeb()->StaticUnicodeString;
+ ANSI_STRING NameA;
+
+ /* Initialize the string as ANSI_STRING and convert to Unicode */
+ RtlInitAnsiString(&NameA, (LPSTR)lpName);
+ RtlAnsiStringToUnicodeString(NameU, &NameA, FALSE);
+
+ /* Call the Unicode API */
+ return CreateNamedPipeW(NameU->Buffer,
+ dwOpenMode,
+ dwPipeMode,
+ nMaxInstances,
+ nOutBufferSize,
+ nInBufferSize,
+ nDefaultTimeOut,
+ lpSecurityAttributes);
}
/*
return(INVALID_HANDLE_VALUE);
}
- DPRINT1("Pipe name: %wZ\n", &NamedPipeName);
- DPRINT1("Pipe name: %S\n", NamedPipeName.Buffer);
+ DPRINT("Pipe name: %wZ\n", &NamedPipeName);
+ DPRINT("Pipe name: %S\n", NamedPipeName.Buffer);
/* Always case insensitive, check if we got extra attributes */
Attributes = OBJ_CASE_INSENSITIVE;
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);
return PipeHandle;
}
-
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+WINAPI
WaitNamedPipeA(LPCSTR lpNamedPipeName,
- DWORD nTimeOut)
+ DWORD nTimeOut)
{
- BOOL r;
- UNICODE_STRING NameU;
- ANSI_STRING NameA;
+ BOOL r;
+ UNICODE_STRING NameU;
- RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName);
- RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
+ /* Convert the name to Unicode */
+ Basep8BitStringToLiveUnicodeString(&NameU, lpNamedPipeName);
- r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
+ /* Call the Unicode API */
+ r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
- RtlFreeUnicodeString(&NameU);
+ /* Free the Unicode string */
+ RtlFreeUnicodeString(&NameU);
- return(r);
+ /* Return result */
+ return r;
}
/*
return FALSE;
}
+ /* 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)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
/* Initialize the object attributes */
DPRINT("Opening: %wZ\n", &DevicePath);
InitializeObjectAttributes(&ObjectAttributes,
DPRINT1("Status: %lx\n", Status);
SetLastErrorByStatus(Status);
RtlFreeUnicodeString(&NamedPipeName);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
return(FALSE);
}
- /* 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);
-
/* Check what timeout we got */
if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
{
/*
* @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);
-
- RtlFreeUnicodeString(&PipeName);
-
- return(Result);
+ PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
+ ANSI_STRING AnsiPipe;
+
+ /* 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
*/
LPSTR lpUserName,
DWORD nMaxUserNameSize)
{
- UNICODE_STRING UserNameW;
+ UNICODE_STRING UserNameW = {0};
ANSI_STRING UserNameA;
BOOL Ret;
if(lpUserName != NULL)
{
- UserNameW.Length = 0;
UserNameW.MaximumLength = nMaxUserNameSize * sizeof(WCHAR);
- UserNameW.Buffer = HeapAlloc(GetCurrentProcess(), 0, UserNameW.MaximumLength);
+ UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
+ if (UserNameW.Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
UserNameA.Buffer = lpUserName;
UserNameA.Length = 0;
if(Ret && lpUserName != NULL)
{
- NTSTATUS Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
+ NTSTATUS Status;
+
+ RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
+ Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
if(!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
if(UserNameW.Buffer != NULL)
{
- HeapFree(GetCurrentProcess(), 0, UserNameW.Buffer);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
}
return Ret;
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)
+ /* 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 (Buffer == NULL)
{
- Status = NtWaitForSingleObject(hNamedPipe,
- FALSE,
- NULL);
- if (NT_SUCCESS(Status))
- Status = Iosb.Status;
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
}
- 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
*/