/*++ 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; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER readTimeout; HANDLE handle; NTSTATUS status; PVOID freeBuffer; BOOLEAN TranslationStatus; RtlInitUnicodeString( &fileName, lpName ); TranslationStatus = RtlDosPathNameToNtPathName_U( lpName, &fileName, &filePart, NULL ); if ( !TranslationStatus ) { SetLastError(ERROR_PATH_NOT_FOUND); return INVALID_HANDLE_VALUE; } freeBuffer = fileName.Buffer; InitializeObjectAttributes( &objectAttributes, &fileName, OBJ_CASE_INSENSITIVE, NULL, 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; }