361 lines
8.9 KiB
C
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;
|
|
}
|