windows-nt/Source/XPSP1/NT/base/win32/client/mailslot.c
2020-09-26 16:20:57 +08:00

361 lines
8.9 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
mailslot.c
Abstract:
This module contains the Win32 Mailslot API
Author:
Manny Weiser (mannyw) 4-Mar-1991
Revision History:
--*/
#include "basedll.h"
HANDLE
APIENTRY
CreateMailslotW(
IN LPCWSTR lpName,
IN DWORD nMaxMessageSize,
IN DWORD lReadTimeout,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
)
/*++
Routine Description:
The create mailslot API creates a local mailslot and return a
server-side handle to the mailslot.
Arguments:
lpName - The name of the mailslot. This must be a local mailslot
name.
nMaxMessageSize - The size (in bytes) of the largest message that
can be written to the mailslot.
lReadTimeout - The initial read timeout, in milliseconds. This
is the amount of time a read operation will block waiting for
a message to be written to the mailslot. This value can be
changed with the SetMailslotInfo API.
lpSecurityAttributes - An optional pointer to security information
for this mailslot.
Return Value:
Returns one of the following:
0xFFFFFFFF --An error occurred. Call GetLastError for more
information.
Anything else --Returns a handle for use in the server side of
subsequent mailslot operations.
--*/
{
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING fileName;
LPWSTR filePart;
RTL_RELATIVE_NAME relativeName;
IO_STATUS_BLOCK ioStatusBlock;
LARGE_INTEGER readTimeout;
HANDLE handle;
NTSTATUS status;
PVOID freeBuffer;
BOOLEAN TranslationStatus;
RtlInitUnicodeString( &fileName, lpName );
TranslationStatus = RtlDosPathNameToNtPathName_U(
lpName,
&fileName,
&filePart,
&relativeName
);
if ( !TranslationStatus ) {
SetLastError(ERROR_PATH_NOT_FOUND);
return INVALID_HANDLE_VALUE;
}
freeBuffer = fileName.Buffer;
if ( relativeName.RelativeName.Length ) {
fileName = *(PUNICODE_STRING)&relativeName.RelativeName;
} else {
relativeName.ContainingDirectory = NULL;
}
InitializeObjectAttributes(
&objectAttributes,
&fileName,
OBJ_CASE_INSENSITIVE,
relativeName.ContainingDirectory,
NULL
);
if ( ARGUMENT_PRESENT(lpSecurityAttributes) ) {
objectAttributes.SecurityDescriptor =
lpSecurityAttributes->lpSecurityDescriptor;
if ( lpSecurityAttributes->bInheritHandle ) {
objectAttributes.Attributes |= OBJ_INHERIT;
}
}
if (lReadTimeout == MAILSLOT_WAIT_FOREVER) {
readTimeout.HighPart = 0xFFFFFFFF;
readTimeout.LowPart = 0xFFFFFFFF;
} else {
readTimeout.QuadPart = - (LONGLONG)UInt32x32To64( lReadTimeout, 10 * 1000 );
}
status = NtCreateMailslotFile (
&handle,
GENERIC_READ | SYNCHRONIZE | WRITE_DAC,
&objectAttributes,
&ioStatusBlock,
FILE_CREATE,
0,
nMaxMessageSize,
(PLARGE_INTEGER)&readTimeout
);
if ( status == STATUS_NOT_SUPPORTED ||
status == STATUS_INVALID_DEVICE_REQUEST ) {
//
// The request must have been processed by some other device driver
// (other than MSFS). Map the error to something reasonable.
//
status = STATUS_OBJECT_NAME_INVALID;
}
RtlFreeHeap( RtlProcessHeap(), 0, freeBuffer );
if (!NT_SUCCESS(status)) {
BaseSetLastNTError( status );
return INVALID_HANDLE_VALUE;
}
return handle;
}
HANDLE
APIENTRY
CreateMailslotA(
IN LPCSTR lpName,
IN DWORD nMaxMessageSize,
IN DWORD lReadTimeout,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
)
{
PUNICODE_STRING unicode;
ANSI_STRING ansiString;
NTSTATUS status;
unicode = &NtCurrentTeb()->StaticUnicodeString;
RtlInitAnsiString( &ansiString, lpName );
status = RtlAnsiStringToUnicodeString( unicode, &ansiString, FALSE );
if ( !NT_SUCCESS( status ) ) {
if ( status == STATUS_BUFFER_OVERFLOW ) {
SetLastError(ERROR_FILENAME_EXCED_RANGE);
} else {
BaseSetLastNTError(status);
}
return INVALID_HANDLE_VALUE;
}
return ( CreateMailslotW( unicode->Buffer,
nMaxMessageSize,
lReadTimeout,
lpSecurityAttributes
) );
}
BOOL
APIENTRY
GetMailslotInfo(
IN HANDLE hMailslot,
OUT LPDWORD lpMaxMessageSize OPTIONAL,
OUT LPDWORD lpNextSize OPTIONAL,
OUT LPDWORD lpMessageCount OPTIONAL,
OUT LPDWORD lpReadTimeout OPTIONAL
)
/*++
Routine Description:
This function will return the requested information about the
specified mailslot.
Arguments:
hMailslot - A handle to the mailslot.
lpMaxMessageSize - If specified returns the size of the largest
message that can be written to the mailslot.
lpNextSize - If specified returns the size of the next message in
the mailslot buffer. It will return MAILSLOT_NO_MESSAGE if
there are no messages in the mailslot.
lpMessageCount - If specified returns the number of unread message
currently in the mailslot.
lpReadTimeout - If specified returns the read timeout, in
milliseconds.
Return Value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;
FILE_MAILSLOT_QUERY_INFORMATION mailslotInfo;
LARGE_INTEGER millisecondTimeout, tmp;
status = NtQueryInformationFile( hMailslot,
&ioStatusBlock,
&mailslotInfo,
sizeof( mailslotInfo ),
FileMailslotQueryInformation );
if ( !NT_SUCCESS( status ) ) {
BaseSetLastNTError( status );
return ( FALSE );
}
if ( ARGUMENT_PRESENT( lpMaxMessageSize ) ) {
*lpMaxMessageSize = mailslotInfo.MaximumMessageSize;
}
if ( ARGUMENT_PRESENT( lpNextSize ) ) {
*lpNextSize = mailslotInfo.NextMessageSize;
}
if ( ARGUMENT_PRESENT( lpMessageCount ) ) {
*lpMessageCount = mailslotInfo.MessagesAvailable;
}
if ( ARGUMENT_PRESENT( lpReadTimeout ) ) {
//
// Convert read timeout from 100 ns intervals to milliseconds.
// The readtime is currently negative, since it is a relative time.
//
if ( mailslotInfo.ReadTimeout.HighPart != 0xFFFFFFFF
|| mailslotInfo.ReadTimeout.LowPart != 0xFFFFFFFF ) {
tmp.QuadPart = - mailslotInfo.ReadTimeout.QuadPart;
millisecondTimeout = RtlExtendedLargeIntegerDivide(
tmp,
10 * 1000,
NULL );
if ( millisecondTimeout.HighPart == 0 ) {
*lpReadTimeout = millisecondTimeout.LowPart;
} else {
//
// The millisecond calculation would overflow the dword.
// Approximate a large number as best we can.
//
*lpReadTimeout = 0xFFFFFFFE;
}
} else {
//
// The mailslot timeout is infinite.
//
*lpReadTimeout = MAILSLOT_WAIT_FOREVER;
}
}
return( TRUE );
}
BOOL
APIENTRY
SetMailslotInfo(
IN HANDLE hMailslot,
IN DWORD lReadTimeout
)
/*++
Routine Description:
This function will set the read timeout for the specified mailslot.
Arguments:
hMailslot - A handle to the mailslot.
lReadTimeout - The new read timeout, in milliseconds.
Return Value:
TRUE - The operation was successful.
FALSE/NULL - The operation failed. Extended error status is available
using GetLastError.
--*/
{
NTSTATUS status;
IO_STATUS_BLOCK ioStatusBlock;
FILE_MAILSLOT_SET_INFORMATION mailslotInfo;
LARGE_INTEGER timeout;
if ( lReadTimeout == MAILSLOT_WAIT_FOREVER ) {
timeout.HighPart = 0xFFFFFFFF;
timeout.LowPart = 0xFFFFFFFF;
} else {
timeout.QuadPart = - (LONGLONG)UInt32x32To64( lReadTimeout, 10 * 1000 );
}
mailslotInfo.ReadTimeout = &timeout;
status = NtSetInformationFile( hMailslot,
&ioStatusBlock,
&mailslotInfo,
sizeof( mailslotInfo ),
FileMailslotSetInformation );
if ( !NT_SUCCESS( status ) ) {
BaseSetLastNTError( status );
return ( FALSE );
}
return TRUE;
}