Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

712 lines
19 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dllmsl16.c
Abstract:
This module implements the OS/2 V1.x Lanman Mailslot APIs.
Author:
Beni Lavi (benil) 3-Mar-1992
Revision History:
--*/
#define INCL_OS2V20_ERRORS
#define INCL_OS2V20_FILESYS
#include "os2dll.h"
#define NERR_NetNotStarted 2102
APIRET
Dos16MakeMailslot(
IN PSZ pName,
IN ULONG MessageSize,
IN ULONG MailslotSize,
OUT PUSHORT pMailslot
)
{
APIRET RetCode;
NTSTATUS Status;
HFILE hLocalHandle;
PFILE_HANDLE hFileRecord;
STRING CanonicalNameString;
UNICODE_STRING CanonicalNameString_U;
ULONG FileType;
ULONG FileFlags;
ULONG CalculatedMailslotSize;
HANDLE NtFileHandle;
OBJECT_ATTRIBUTES Obja;
IO_STATUS_BLOCK IoStatus;
PSECURITY_DESCRIPTOR securityDescriptor;
CHAR localSecurityDescriptor[SECURITY_DESCRIPTOR_MIN_LENGTH];
#if DBG
PSZ RoutineName = "DosMakeMailslot";
#endif
try {
Od2ProbeForWrite(pMailslot, sizeof(USHORT), 1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
AcquireFileLockExclusive(
#if DBG
RoutineName
#endif
);
RetCode = AllocateHandle(&hLocalHandle);
ReleaseFileLockExclusive(
#if DBG
RoutineName
#endif
);
if (RetCode) {
return RetCode;
}
RetCode = Od2Canonicalize(pName,
CANONICALIZE_MAILSLOT,
&CanonicalNameString,
&NtFileHandle,
&FileFlags, // BUGBUG shouldn't we check for root dir
&FileType
);
if ((RetCode != NO_ERROR)|| (FileFlags & CANONICALIZE_META_CHARS_FOUND)) {
AcquireFileLockExclusive(
#if DBG
RoutineName
#endif
);
FreeHandle(hLocalHandle);
ReleaseFileLockExclusive(
#if DBG
RoutineName
#endif
);
if (RetCode == NO_ERROR && (FileFlags & CANONICALIZE_META_CHARS_FOUND)) {
RtlFreeHeap(Od2Heap,0,CanonicalNameString.Buffer);
RetCode = ERROR_FILE_NOT_FOUND;
}
return RetCode;
}
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("canonical name is %s\n",CanonicalNameString.Buffer);
}
#endif
//
// UNICODE conversion -
//
RetCode = Od2MBStringToUnicodeString(
&CanonicalNameString_U,
&CanonicalNameString,
TRUE);
if (RetCode)
{
#if DBG
IF_OD2_DEBUG( FILESYS )
{
DbgPrint("Dos16MakeMailslot: no memory for Unicode Conversion\n");
}
#endif
RtlFreeHeap(Od2Heap,0,CanonicalNameString.Buffer);
AcquireFileLockExclusive(
#if DBG
RoutineName
#endif
);
FreeHandle(hLocalHandle);
ReleaseFileLockExclusive(
#if DBG
RoutineName
#endif
);
return RetCode;
}
Status = RtlCreateSecurityDescriptor( (PSECURITY_DESCRIPTOR)
&localSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION );
if (!NT_SUCCESS( Status )) {
#if DBG
DbgPrint("DosMakeMailslot: failed at RtlCreateSecurityDescriptor %x\n", Status);
ASSERT(FALSE);
#endif
return ERROR_ACCESS_DENIED;
}
Status = RtlSetDaclSecurityDescriptor( (PSECURITY_DESCRIPTOR)
&localSecurityDescriptor,
(BOOLEAN)TRUE,
(PACL) NULL,
(BOOLEAN)FALSE );
if (!NT_SUCCESS( Status )) {
#if DBG
DbgPrint("DosMakeMailslot: failed at RtlSetDaclSecurityDescriptor %x\n", Status);
ASSERT(FALSE);
#endif
return ERROR_ACCESS_DENIED;
}
securityDescriptor = (PSECURITY_DESCRIPTOR) &localSecurityDescriptor;
InitializeObjectAttributes( &Obja,
&CanonicalNameString_U,
OBJ_CASE_INSENSITIVE,
NtFileHandle,
securityDescriptor
);
CalculatedMailslotSize = MailslotSize * 2;
if (CalculatedMailslotSize < 4096) {
CalculatedMailslotSize = 4096;
}
Status = NtCreateMailslotFile(
&NtFileHandle,
SYNCHRONIZE |
FILE_READ_DATA | FILE_WRITE_DATA |
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
&Obja,
&IoStatus,
FILE_SYNCHRONOUS_IO_ALERT,
CalculatedMailslotSize,
MessageSize,
NULL // WAIT FOREVER
);
RtlFreeHeap(Od2Heap,0,CanonicalNameString.Buffer);
RtlFreeUnicodeString (&CanonicalNameString_U);
if (!(NT_SUCCESS(Status))) {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("St == %X\n",Status);
}
#endif
AcquireFileLockExclusive(
#if DBG
RoutineName
#endif
);
FreeHandle(hLocalHandle);
ReleaseFileLockExclusive(
#if DBG
RoutineName
#endif
);
//
// Map some of the NT error codes where there is a clear mapping
//
switch (Status) {
case STATUS_OBJECT_NAME_COLLISION:
return ERROR_ALREADY_EXISTS;
default:
return (Or2MapNtStatusToOs2Error(Status, ERROR_PATH_NOT_FOUND));
}
}
AcquireFileLockExclusive(
#if DBG
RoutineName
#endif
);
hFileRecord = DereferenceFileHandleNoCheck(hLocalHandle);
hFileRecord->NtHandle = NtFileHandle;
hFileRecord->FileType = (USHORT) FILE_TYPE_MAILSLOT;
hFileRecord->Flags |= OPEN_SHARE_DENYREAD & QFHSTATE_FLAGS;
hFileRecord->DeviceAttribute = 0;
hFileRecord->IoVectorType = FileVectorType;
//
// validate file handle
//
ValidateHandle(hFileRecord);
ReleaseFileLockExclusive(
#if DBG
RoutineName
#endif
);
*pMailslot = (USHORT)hLocalHandle;
return NO_ERROR;
}
APIRET
Dos16DeleteMailslot(
IN HFILE Mailslot
)
{
APIRET RetCode;
RetCode = DosClose(Mailslot);
return NO_ERROR;
}
APIRET
Dos16MailslotInfo(
IN HFILE Mailslot,
OUT PUSHORT pMessageSize,
OUT PUSHORT pMailslotSize,
OUT PUSHORT pNextSize,
OUT PUSHORT pNextPriority,
OUT PUSHORT pMessages
)
{
APIRET RetCode;
NTSTATUS Status;
PFILE_HANDLE hFileRecord;
HANDLE NtFileHandle;
IO_STATUS_BLOCK IoStatus;
FILE_MAILSLOT_QUERY_INFORMATION MailslotInfo;
#if DBG
PSZ RoutineName = "DosMakeMailslot";
#endif
try {
Od2ProbeForWrite(pMessageSize, sizeof(USHORT), 1);
Od2ProbeForWrite(pMailslotSize, sizeof(USHORT), 1);
Od2ProbeForWrite(pNextSize, sizeof(USHORT), 1);
Od2ProbeForWrite(pNextPriority, sizeof(USHORT), 1);
Od2ProbeForWrite(pMessages, sizeof(USHORT), 1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
AcquireFileLockShared(
#if DBG
RoutineName
#endif
);
RetCode = DereferenceFileHandle(Mailslot, &hFileRecord);
if (RetCode) {
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
return RetCode;
}
if (hFileRecord->FileType != FILE_TYPE_MAILSLOT) {
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
return ERROR_INVALID_HANDLE;
}
NtFileHandle = hFileRecord->NtHandle;
Status = NtQueryInformationFile(
NtFileHandle,
&IoStatus,
&MailslotInfo,
sizeof(FILE_MAILSLOT_QUERY_INFORMATION),
FileMailslotQueryInformation
);
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
if (!(NT_SUCCESS(Status))) {
return ERROR_INVALID_HANDLE;
}
*pMessageSize = (USHORT)MailslotInfo.MaximumMessageSize;
*pMailslotSize = (USHORT)MailslotInfo.MailslotQuota;
*pNextSize = (USHORT)((MailslotInfo.NextMessageSize == MAILSLOT_NO_MESSAGE)
? 0 : MailslotInfo.NextMessageSize);
*pNextPriority = 0;
*pMessages = (USHORT)MailslotInfo.MessagesAvailable;
return NO_ERROR;
}
APIRET
Dos16ReadMailslot(
IN HANDLE Mailslot,
OUT PCHAR pBuffer,
OUT PUSHORT pReturned,
OUT PUSHORT pNextSize,
OUT PUSHORT pNextPriority,
IN LONG Timeout
)
{
APIRET RetCode;
NTSTATUS Status;
PFILE_HANDLE hFileRecord;
HANDLE NtFileHandle;
IO_STATUS_BLOCK IoStatus;
ULONG FileType;
LARGE_INTEGER NtTimeout;
ULONG BytesRead;
FILE_MAILSLOT_QUERY_INFORMATION MailslotQueryInfo;
FILE_MAILSLOT_SET_INFORMATION MailslotSetInfo;
#if DBG
PSZ RoutineName = "DosReadMailslot";
#endif
try {
Od2ProbeForWrite(pReturned, sizeof(USHORT), 1);
Od2ProbeForWrite(pNextSize, sizeof(USHORT), 1);
Od2ProbeForWrite(pNextPriority, sizeof(USHORT), 1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
AcquireFileLockShared(
#if DBG
RoutineName
#endif
);
//
// Check for invalid handle.
//
RetCode = DereferenceFileHandle(Mailslot, &hFileRecord);
if (RetCode) {
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
return RetCode;
}
NtFileHandle = hFileRecord->NtHandle;
FileType = hFileRecord->FileType;
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
if (FileType != FILE_TYPE_MAILSLOT) {
return ERROR_INVALID_HANDLE;
}
//
// Set the timeout to the value requested by the read operation
//
if (Timeout == -1 /*MAILSLOT_NO_TIMEOUT*/) {
NtTimeout = RtlConvertLongToLargeInteger(MAILSLOT_WAIT_FOREVER);
}
else {
NtTimeout = RtlEnlargedIntegerMultiply(-10000, Timeout);
}
MailslotSetInfo.ReadTimeout = &NtTimeout;
Status = NtSetInformationFile(
NtFileHandle,
&IoStatus,
&MailslotSetInfo,
sizeof(FILE_MAILSLOT_SET_INFORMATION),
FileMailslotSetInformation
);
if (!(NT_SUCCESS(Status))) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_BROKEN_PIPE));
}
//
// Get the maximum possible size of the buffer
//
Status = NtQueryInformationFile(
NtFileHandle,
&IoStatus,
&MailslotQueryInfo,
sizeof(FILE_MAILSLOT_QUERY_INFORMATION),
FileMailslotQueryInformation
);
if (!(NT_SUCCESS(Status))) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_BROKEN_PIPE));
}
Status = NtReadFile(
NtFileHandle,
0,
NULL,
NULL,
&IoStatus,
pBuffer,
MailslotQueryInfo.MaximumMessageSize,
NULL,
NULL
);
if (!(NT_SUCCESS(Status))) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_BROKEN_PIPE));
}
BytesRead = IoStatus.Information;
//
// Get Info about next message in buffer
//
Status = NtQueryInformationFile(
NtFileHandle,
&IoStatus,
&MailslotQueryInfo,
sizeof(FILE_MAILSLOT_QUERY_INFORMATION),
FileMailslotQueryInformation
);
if (!(NT_SUCCESS(Status))) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_BROKEN_PIPE));
}
*pReturned = (USHORT)BytesRead;
if (MailslotQueryInfo.NextMessageSize == MAILSLOT_NO_MESSAGE) {
*pNextSize = 0;
}
else {
*pNextSize = (USHORT)MailslotQueryInfo.NextMessageSize;
}
*pNextPriority = 0;
return NO_ERROR;
}
APIRET
Dos16PeekMailslot(
IN HANDLE Mailslot,
OUT PCHAR pBuffer,
OUT PUSHORT pReturned,
OUT PUSHORT pNextSize,
OUT PUSHORT pNextPriority
)
{
APIRET RetCode;
NTSTATUS Status;
PFILE_HANDLE hFileRecord;
HANDLE NtFileHandle;
IO_STATUS_BLOCK IoStatus;
ULONG FileType;
FILE_MAILSLOT_QUERY_INFORMATION MailslotInfo;
FILE_MAILSLOT_PEEK_BUFFER MailslotPeekBuffer;
#if DBG
PSZ RoutineName = "DosPeekMailslot";
#endif
try {
Od2ProbeForWrite(pReturned, sizeof(USHORT), 1);
Od2ProbeForWrite(pNextSize, sizeof(USHORT), 1);
Od2ProbeForWrite(pNextPriority, sizeof(USHORT), 1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
AcquireFileLockShared(
#if DBG
RoutineName
#endif
);
//
// Check for invalid handle.
//
RetCode = DereferenceFileHandle(Mailslot, &hFileRecord);
if (RetCode) {
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
return RetCode;
}
NtFileHandle = hFileRecord->NtHandle;
FileType = hFileRecord->FileType;
ReleaseFileLockShared(
#if DBG
RoutineName
#endif
);
if (FileType != FILE_TYPE_MAILSLOT) {
return ERROR_INVALID_HANDLE;
}
Status = NtQueryInformationFile(
NtFileHandle,
&IoStatus,
&MailslotInfo,
sizeof(FILE_MAILSLOT_QUERY_INFORMATION),
FileMailslotQueryInformation
);
if (!(NT_SUCCESS(Status))) {
return ERROR_BROKEN_PIPE;
}
if (MailslotInfo.NextMessageSize == (ULONG)(MAILSLOT_NO_MESSAGE)) {
*pReturned = 0;
*pNextSize = 0;
*pNextPriority = 0;
return (NO_ERROR);
}
Status = NtFsControlFile( NtFileHandle,
0,
NULL,
NULL,
&IoStatus,
FSCTL_MAILSLOT_PEEK,
&MailslotPeekBuffer,
sizeof(FILE_MAILSLOT_PEEK_BUFFER),
pBuffer,
MailslotInfo.NextMessageSize
);
if (!NT_SUCCESS(Status)) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_BROKEN_PIPE));
}
*pReturned = (USHORT)MailslotPeekBuffer.MessageLength;
if (MailslotPeekBuffer.NumberOfMessages <= 1) {
*pNextSize = 0;
}
else {
//
// We don't have enough information to determine the NextSize
// value so we play it safe
//
*pNextSize = (USHORT)MailslotInfo.MaximumMessageSize;
}
*pNextPriority = 0;
return NO_ERROR;
}
APIRET
Dos16WriteMailslot(
IN PSZ pName,
OUT PCHAR pBuffer,
IN ULONG BufferSize,
IN ULONG Priority,
IN ULONG Class,
IN LONG Timeout
)
{
APIRET RetCode;
NTSTATUS Status;
ULONG FileType;
ULONG FileFlags;
STRING CanonicalNameString;
UNICODE_STRING CanonicalNameString_U;
HANDLE NtFileHandle;
OBJECT_ATTRIBUTES Obja;
IO_STATUS_BLOCK IoStatus;
UNREFERENCED_PARAMETER(Priority);
UNREFERENCED_PARAMETER(Class);
UNREFERENCED_PARAMETER(Timeout);
try {
Od2ProbeForRead(pBuffer, BufferSize, 1);
} except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
RetCode = Od2Canonicalize(pName,
CANONICALIZE_MAILSLOT,
&CanonicalNameString,
&NtFileHandle,
&FileFlags,
&FileType
);
if (RetCode != NO_ERROR) {
return (ERROR_FILE_NOT_FOUND);
}
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("canonical name is %s\n",CanonicalNameString.Buffer);
}
#endif
//
// UNICODE conversion -
//
RetCode = Od2MBStringToUnicodeString(
&CanonicalNameString_U,
&CanonicalNameString,
TRUE);
if (RetCode)
{
#if DBG
IF_OD2_DEBUG( FILESYS )
{
DbgPrint("Dos16WriteMailslot: no memory for Unicode Conversion\n");
}
#endif
RtlFreeHeap(Od2Heap,0,CanonicalNameString.Buffer);
return RetCode;
}
InitializeObjectAttributes(&Obja,
&CanonicalNameString_U,
OBJ_CASE_INSENSITIVE,
NtFileHandle,
NULL);
Status = NtOpenFile(
&NtFileHandle,
SYNCHRONIZE | FILE_WRITE_DATA | FILE_READ_DATA,
&Obja,
&IoStatus,
FILE_SHARE_WRITE | FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_ALERT
);
RtlFreeHeap(Od2Heap,0,CanonicalNameString.Buffer);
RtlFreeUnicodeString (&CanonicalNameString_U);
if (!(NT_SUCCESS(Status))) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_PATH_NOT_FOUND));
}
Status = NtWriteFile(
NtFileHandle,
0,
NULL,
NULL,
&IoStatus,
pBuffer,
BufferSize,
NULL,
0
);
if (!(NT_SUCCESS(Status))) {
return (Or2MapNtStatusToOs2Error(Status, ERROR_BROKEN_PIPE));
}
Status = NtClose(NtFileHandle);
return NO_ERROR;
}