mirror of https://github.com/lianthony/NT4.0
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.
339 lines
7.1 KiB
339 lines
7.1 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
mailslot.cxx
|
|
|
|
Abstract:
|
|
|
|
This file contains the system dependent mailslot functions for NT.
|
|
|
|
Author:
|
|
|
|
Steven Zeck (stevez) 07/01/91
|
|
|
|
--*/
|
|
|
|
#define NULL 0
|
|
|
|
#include "core.hxx"
|
|
#include "mailslot.hxx"
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
|
|
|
|
|
|
WRITE_MAIL_SLOT::WRITE_MAIL_SLOT(
|
|
IN PUZ NameI,
|
|
IN PUZ DomainI,
|
|
OUT unsigned short *Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a NT MailSlot for writing.
|
|
|
|
Arguments:
|
|
|
|
NameI - name of the WRITE_MAIL_SLOT
|
|
|
|
DomainI - the domain used for broadcasts
|
|
|
|
Status - place to return results
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectattributes;
|
|
IO_STATUS_BLOCK iostatus;
|
|
UNICODE_STRING unicodestring;
|
|
UICHAR Buffer[200];
|
|
|
|
hHandle = 0;
|
|
|
|
// Form the name of the WRITE_MAIL_SLOT. For Write, we open an name to the
|
|
// redirector with the current domain we are on.
|
|
|
|
Buffer[0] = NIL;
|
|
CatUZ(Buffer, (PUZ) L"\\Device\\LanmanRedirector\\");
|
|
|
|
if (DomainI)
|
|
CatUZ(Buffer, DomainI);
|
|
else
|
|
NameI += 2; // skip past the \\ in the name: \\server
|
|
|
|
CatUZ(Buffer, NameI);
|
|
|
|
DLIST(3, "Creating WRITE_MAIL_SLOT: " << Buffer << nl);
|
|
|
|
// map the name of the WRITE_MAIL_SLOT into the required format
|
|
|
|
RtlInitUnicodeString(&unicodestring, Buffer);
|
|
|
|
InitializeObjectAttributes(&objectattributes, &unicodestring,
|
|
OBJ_CASE_INSENSITIVE, 0, 0);
|
|
status = NtOpenFile(&hHandle,
|
|
GENERIC_WRITE | SYNCHRONIZE,
|
|
&objectattributes, &iostatus,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
*Status = !NT_SUCCESS(status);
|
|
}
|
|
|
|
|
|
WRITE_MAIL_SLOT::~WRITE_MAIL_SLOT(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deallocate a WRITE_MAIL_SLOT.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if (hHandle) {
|
|
status = NtClose(hHandle);
|
|
ASSERT(NT_SUCCESS(status));
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
WRITE_MAIL_SLOT::Write(
|
|
IN PB Buffer,
|
|
IN int Size
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write data to a mailslot. The mailslot is created with sync attributes,
|
|
so there is no need to wait for the operation.
|
|
|
|
Arguments:
|
|
|
|
Buffer - buffer to write.
|
|
|
|
Size - size of buffer to write.
|
|
|
|
Returns:
|
|
|
|
FALSE if write went OK.
|
|
|
|
--*/
|
|
{
|
|
|
|
IO_STATUS_BLOCK iostatus;
|
|
|
|
DLIST(3, "**\n ==a write of **" << Size << " Bytes**\n");
|
|
return(NT_ERROR(NtWriteFile(hHandle, 0, 0, 0,
|
|
&iostatus, Buffer, Size,0,0)));
|
|
}
|
|
|
|
|
|
|
|
READ_MAIL_SLOT::READ_MAIL_SLOT(
|
|
IN PUZ NameI,
|
|
IN int SizeI,
|
|
OUT int *Status
|
|
) : SerializeReaders(Status)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a NT READ_MAIL_SLOT. If you want to receive data on the MS, you
|
|
must use the READ_MAIL_SLOT API to create one, else it's just like a file.
|
|
|
|
Arguments:
|
|
|
|
NameI - name of the READ_MAIL_SLOT
|
|
|
|
SizeI - the size of buffer to allocate for replies.
|
|
|
|
Status - place to return results
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectattributes;
|
|
IO_STATUS_BLOCK iostatus;
|
|
UNICODE_STRING unicodestring;
|
|
UICHAR Buffer[200];
|
|
|
|
Size = SizeI; // max buffer size for reads
|
|
hHandle = 0;
|
|
|
|
// Form the name of the READ_MAIL_SLOT. For Write, we open an name to the
|
|
// redirector with the current domain we are on.
|
|
|
|
Buffer[0] = NIL;
|
|
CatUZ(CatUZ(Buffer, (PUZ) L"\\Device"), NameI);
|
|
|
|
DLIST(3, "Creating READ_MAIL_SLOT: " << Buffer << nl);
|
|
|
|
// map the name of the READ_MAIL_SLOT into the required format
|
|
|
|
RtlInitUnicodeString(&unicodestring, Buffer);
|
|
|
|
InitializeObjectAttributes(&objectattributes, &unicodestring,
|
|
OBJ_CASE_INSENSITIVE, 0, 0);
|
|
|
|
status = NtCreateMailslotFile(&hHandle,
|
|
GENERIC_READ | SYNCHRONIZE,
|
|
&objectattributes, &iostatus,
|
|
0, MAILSLOT_SIZE_AUTO, Size, 0);
|
|
|
|
|
|
*Status = !NT_SUCCESS(status);
|
|
}
|
|
|
|
|
|
READ_MAIL_SLOT::~READ_MAIL_SLOT(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deallocate a READ_MAIL_SLOT.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
if (hHandle) {
|
|
status = NtClose(hHandle);
|
|
ASSERT(NT_SUCCESS(status));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
READ_MAIL_SLOT::Read(
|
|
OUT PB Buffer,
|
|
IN OUT int &SizeOut,
|
|
IN long TimeOut
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read data from a mailslot. The mailslot is created with async
|
|
atrributes so that the read can be timed out.
|
|
|
|
Arguments:
|
|
|
|
Buffer - buffer to read data into
|
|
|
|
SizeOut - the size of the buffer
|
|
|
|
TimeOut - time to wait for a response.
|
|
|
|
Returns:
|
|
|
|
FALSE if there is a new message. SizeOut is updated to the new
|
|
message size.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status, err;
|
|
IO_STATUS_BLOCK iostatus, CancelStatus;
|
|
TIME Time;
|
|
ULONG h = (ULONG) hHandle;
|
|
iostatus.Information = (ULONG)-1;
|
|
iostatus.Status = -1;
|
|
/*
|
|
DWORD Id;
|
|
*/
|
|
SerializeReaders.Request();
|
|
|
|
status = NtReadFile(hHandle, 0,0,0, &iostatus, Buffer, Size, 0,0);
|
|
/*
|
|
Id = GetCurrentThreadId();
|
|
DLIST(3, "Thread " << Id <<
|
|
" read on hndl " << h << " ret " << status << "\n");
|
|
if (!status)
|
|
{
|
|
DLIST ( 3, "Thread " << Id << "hndl " << h <<
|
|
"iostatus info = " << iostatus.Information <<
|
|
"iostatus status = " << iostatus.Status << "\n");
|
|
}
|
|
*/
|
|
|
|
if (status == STATUS_PENDING)
|
|
{
|
|
// Read was not satisified, so wait the reqested period.
|
|
// Convert to 10,000 from 1,000 of a seconds.
|
|
|
|
Time = RtlEnlargedIntegerMultiply(-10000, TimeOut);
|
|
|
|
do {
|
|
status = NtWaitForSingleObject(hHandle,
|
|
TRUE,
|
|
(TimeOut == -1)? 0: &Time);
|
|
/*
|
|
|
|
DLIST(3, "Thread " << Id << "status from WtFSnglO= on hndl " <<
|
|
h << " ret " << status << " \n");
|
|
|
|
if (!status)
|
|
{
|
|
DLIST ( 3, "Thread " << Id <<
|
|
"info on read on hndl " << h <<
|
|
"iostatus info = " << iostatus.Information <<
|
|
"iostatus status = " << iostatus.Status << "\n");
|
|
}
|
|
*/
|
|
|
|
//if the status was time out cancel the IO
|
|
|
|
if (status == STATUS_TIMEOUT)
|
|
{
|
|
err = NtCancelIoFile(hHandle, &CancelStatus);
|
|
break;
|
|
}
|
|
|
|
} while ((status == STATUS_USER_APC) || (status == STATUS_ALERTED));
|
|
|
|
//NtWait..SingleObject can return stuff w/o coping stuff!
|
|
//loop on these two!
|
|
}
|
|
|
|
//if wait completed successfully, IoStatus block has the good info
|
|
//
|
|
if (status)
|
|
{
|
|
SizeOut = 0;
|
|
}
|
|
else
|
|
{
|
|
SizeOut = (int) iostatus.Information;
|
|
status = iostatus.Status;
|
|
}
|
|
|
|
if ((SizeOut == 0) && (status != STATUS_TIMEOUT))
|
|
{
|
|
DLIST(3, "\n\n Serious Problem Dude - 0ByteRead\n\n");
|
|
DLIST(3, "Status returned = " << status << "\n");
|
|
}
|
|
|
|
if (status == STATUS_TIMEOUT)
|
|
DLIST(3, "\n\n--Timed out the read\n\n");
|
|
|
|
ASSERT( (SizeOut > 0) || ( status == STATUS_TIMEOUT) );
|
|
|
|
if (!status)
|
|
DLIST(3, "Read .." << SizeOut << "..Bytes\n");
|
|
|
|
SerializeReaders.Clear();
|
|
|
|
return(NT_ERROR(status) || status == STATUS_TIMEOUT);
|
|
}
|