387 lines
9.5 KiB
C
387 lines
9.5 KiB
C
|
|
|||
|
/*--
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
grpmsngr.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file contains the routines that provide support for messaging
|
|||
|
in a multi-domaign lan. These routines comprise the group message thread
|
|||
|
of the messenger service. The support of domain messaging is broken up
|
|||
|
into two phases. The first, which takes place at initialization time of
|
|||
|
the messenger, sets up a mailslot thru which the second phase receives the
|
|||
|
information that it will need to process. The second, phase, which runs
|
|||
|
in parallel with the existing messenger thread, reads messages out of this
|
|||
|
mailslot and logs them.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Dan Lafferty (danl) 17-Jul-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode -Win32
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
These routines receive and manipulate ansi strings, not UNICODE strings.
|
|||
|
The ANSI to UNICODE translation will be done in logsmb().
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
17-Jul-1991 danl
|
|||
|
ported from LM2.0
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "msrv.h"
|
|||
|
#include <string.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <netlib.h> // UNUSED macro
|
|||
|
|
|||
|
#include "msgdbg.h" // MSG_LOG
|
|||
|
#include "msgdata.h"
|
|||
|
|
|||
|
//
|
|||
|
// GLOBALS
|
|||
|
//
|
|||
|
LPSTR DieMessage = "DIE";
|
|||
|
|
|||
|
extern HANDLE g_hGrpEvent;
|
|||
|
|
|||
|
//
|
|||
|
// PROTOTYPES of internal functions
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
STATIC VOID
|
|||
|
MsgDisectMessage(
|
|||
|
IN LPSTR message,
|
|||
|
OUT LPSTR *from,
|
|||
|
OUT LPSTR *to,
|
|||
|
IN LPSTR text);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Defines
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Size of mailslot messages (bytes)
|
|||
|
//
|
|||
|
#define MESSNGR_MS_MSIZE 512
|
|||
|
|
|||
|
//
|
|||
|
// size of mailslot (bytes)
|
|||
|
//
|
|||
|
#define MESSNGR_MS_SIZE (5*MESSNGR_MS_MSIZE)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static char Msg_Buf[MESSNGR_MS_MSIZE + 3]; // Buffer for messages + 3 NULs
|
|||
|
|
|||
|
static OVERLAPPED Overlapped;
|
|||
|
|
|||
|
static DWORD bytes_read = 0;
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
MsgInitGroupSupport(DWORD iGrpMailslotWakeupSem)
|
|||
|
{
|
|||
|
DWORD err = 0; // Error code info from the group processor.
|
|||
|
|
|||
|
GrpMailslotHandle = CreateMailslotA(
|
|||
|
MESSNGR_MS_NAME, // lpName
|
|||
|
MESSNGR_MS_MSIZE, // nMaxMessageSize
|
|||
|
MAILSLOT_WAIT_FOREVER, // lReadTimeout
|
|||
|
NULL); // lpSecurityAttributes
|
|||
|
|
|||
|
if (GrpMailslotHandle == INVALID_HANDLE_VALUE) {
|
|||
|
err = GetLastError();
|
|||
|
MSG_LOG(ERROR,"GroupMsgProcessor: CreateMailslot FAILURE %d\n",
|
|||
|
err);
|
|||
|
}
|
|||
|
else {
|
|||
|
MSG_LOG1(GROUP,"InitGroupSupport: MailSlotHandle = 0x%lx\n",
|
|||
|
GrpMailslotHandle);
|
|||
|
}
|
|||
|
|
|||
|
return err;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
MsgReadGroupMailslot(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
NET_API_STATUS Err = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Clean out receive buffers before each message
|
|||
|
//
|
|||
|
memset(Msg_Buf, 0, sizeof(Msg_Buf));
|
|||
|
memset(&Overlapped, 0, sizeof(Overlapped));
|
|||
|
|
|||
|
if (!ReadFile(
|
|||
|
GrpMailslotHandle,
|
|||
|
Msg_Buf,
|
|||
|
sizeof(Msg_Buf) - 3, // Leave 3 NULs at the end (see MsgDisectMessage)
|
|||
|
&bytes_read,
|
|||
|
&Overlapped) )
|
|||
|
{
|
|||
|
Err = GetLastError();
|
|||
|
|
|||
|
if (Err == ERROR_INVALID_HANDLE)
|
|||
|
{
|
|||
|
//
|
|||
|
// If this handle is no longer good, it means the
|
|||
|
// mailslot system is down. So we can't go on using
|
|||
|
// mailslots in the messenger. Therefore, we want to
|
|||
|
// log that fact and shutdown this thread.
|
|||
|
//
|
|||
|
MsgErrorLogWrite(
|
|||
|
Err, // Error Code
|
|||
|
SERVICE_MESSENGER, // Component
|
|||
|
NULL, // Buffer
|
|||
|
0L, // BufferSize
|
|||
|
NULL, // Insertion strings
|
|||
|
0); // NumStrings
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
MsgServeGroupMailslot()
|
|||
|
{
|
|||
|
LPSTR from;
|
|||
|
LPSTR to;
|
|||
|
CHAR text[MAXGRPMSGLEN+3]; // +3 is for length word at
|
|||
|
// start of string (for
|
|||
|
// logsbm) and for NULL
|
|||
|
// terminator at end. NOTE:
|
|||
|
// disect_message() below
|
|||
|
// makes assumptions about
|
|||
|
// the length of this array.
|
|||
|
DWORD code;
|
|||
|
|
|||
|
//
|
|||
|
// Process the message
|
|||
|
//
|
|||
|
if( !GetOverlappedResult( GrpMailslotHandle,
|
|||
|
&Overlapped,
|
|||
|
&bytes_read,
|
|||
|
TRUE ) ) {
|
|||
|
MSG_LOG1(ERROR,"MsgServeGroupMailslot: GetOverlappedResult failed %d\n",
|
|||
|
GetLastError());
|
|||
|
return(GetMsgrState());
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check for Shutdown...
|
|||
|
//
|
|||
|
if ((bytes_read == 4) && (strcmp(Msg_Buf, DieMessage)==0)) {
|
|||
|
return(GetMsgrState());
|
|||
|
}
|
|||
|
|
|||
|
MSG_LOG(TRACE,"MailSlot Message Received\n",0);
|
|||
|
|
|||
|
__try {
|
|||
|
MsgDisectMessage( Msg_Buf, &from, &to, text );
|
|||
|
|
|||
|
if (g_IsTerminalServer)
|
|||
|
{
|
|||
|
Msglogsbm (from, to, text, (ULONG)EVERYBODY_SESSION_ID);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Msglogsbm (from, to, text, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
__except( EXCEPTION_EXECUTE_HANDLER, code = GetExceptionCode() ) {
|
|||
|
MSG_LOG(ERROR,"MsgServerGroupMailslot: Caught exception %d\n",code);
|
|||
|
}
|
|||
|
|
|||
|
return(RUNNING);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/* Function: MsgDisectMessage
|
|||
|
*
|
|||
|
* This function isolates the details of the structure of the message
|
|||
|
* that gets sent through the mailslot from the rest of the thread. Given
|
|||
|
* the message buffer, this routine fills in the module globals From, To
|
|||
|
* and Text with the proper parts of the message.
|
|||
|
*
|
|||
|
* ENTRY
|
|||
|
*
|
|||
|
* Expects one argument, which is a pointer to the buffer containing
|
|||
|
* the message.
|
|||
|
*
|
|||
|
* EXIT
|
|||
|
*
|
|||
|
* This function does not return a value.
|
|||
|
*
|
|||
|
* SIDE EFFECTS
|
|||
|
*
|
|||
|
* Modifies the variables from, to and text. The Msg_Buf
|
|||
|
* may also be modified.
|
|||
|
* Assumes the length of Text is at least MAXGRPMSGLEN+3.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
MsgDisectMessage(
|
|||
|
IN LPSTR message,
|
|||
|
OUT LPSTR *from,
|
|||
|
OUT LPSTR *to,
|
|||
|
IN LPSTR text)
|
|||
|
{
|
|||
|
|
|||
|
LPSTR txt_ptr;
|
|||
|
PSHORT size_ptr;
|
|||
|
|
|||
|
//
|
|||
|
// Note that message (a.k.a. Msg_Buf) is always triple-NUL terminated,
|
|||
|
// so calling strlen twice and adding 1 will always succeed, even if
|
|||
|
// the message isn't properly NUL-terminated (in that case, "from" will
|
|||
|
// point to all the text in the buffer and both "to" and "text will
|
|||
|
// point to empty strings).
|
|||
|
//
|
|||
|
*from = message;
|
|||
|
|
|||
|
*to = (*from) + strlen(*from) +1;
|
|||
|
|
|||
|
txt_ptr = (*to) + strlen(*to) +1;
|
|||
|
|
|||
|
text[2] = '\0';
|
|||
|
|
|||
|
strncpy(text+2, txt_ptr, MAXGRPMSGLEN);
|
|||
|
|
|||
|
//
|
|||
|
// make sure it is NULL terminated
|
|||
|
//
|
|||
|
|
|||
|
text[MAXGRPMSGLEN+2] = '\0';
|
|||
|
|
|||
|
//
|
|||
|
// The first two bytes in the text buffer are to contain the length
|
|||
|
// the message. (in bytes).
|
|||
|
//
|
|||
|
size_ptr = (PSHORT)text;
|
|||
|
*size_ptr = (SHORT)strlen(text+2);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
MsgGrpThreadShutdown(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine wakes up the wait on the Group Mailslot handle.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
DWORD numWritten;
|
|||
|
HANDLE mailslotHandle;
|
|||
|
|
|||
|
// If already stopped, don't bother
|
|||
|
if (GrpMailslotHandle == INVALID_HANDLE_VALUE) {
|
|||
|
MSG_LOG0(TRACE,"MsgGroupThreadShutdown: Group Thread has completed\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Wake up the Group Thread by sending "DIE" to its mailbox.
|
|||
|
//
|
|||
|
|
|||
|
MSG_LOG(TRACE,"MsgThreadWakeup:Wake up Group Thread & tell it to DIE\n",0);
|
|||
|
|
|||
|
mailslotHandle = CreateFileA (
|
|||
|
MESSNGR_MS_NAME, // lpFileName
|
|||
|
GENERIC_WRITE, // dwDesiredAccess
|
|||
|
FILE_SHARE_WRITE | FILE_SHARE_READ, // dwShareMode
|
|||
|
NULL, // lpSecurityAttributes
|
|||
|
OPEN_EXISTING, // dwCreationDisposition
|
|||
|
FILE_ATTRIBUTE_NORMAL, // dwFileAttributes
|
|||
|
0L); // hTemplateFile
|
|||
|
|
|||
|
if (mailslotHandle == INVALID_HANDLE_VALUE) {
|
|||
|
//
|
|||
|
// A failure occured. It is assumed that the mailslot hasn't
|
|||
|
// been created yet. In which case, the GrpMessageProcessor will
|
|||
|
// check the MsgrState directly after it creates the Mailslot and
|
|||
|
// will shut down as required.
|
|||
|
//
|
|||
|
MSG_LOG(TRACE,"MsgThreadWakeup: CreateFile on Mailslot Failed %d\n",
|
|||
|
GetLastError());
|
|||
|
|
|||
|
//
|
|||
|
// Deregister the group work item lest the mailslot handle get closed
|
|||
|
// while the thread pool is still waiting on it when this function returns
|
|||
|
//
|
|||
|
DEREGISTER_WORK_ITEM(g_hGrpEvent);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
MSG_LOG(TRACE,"MsgGroupThreadShutdown: MailSlotHandle = 0x%lx\n",mailslotHandle);
|
|||
|
if ( !WriteFile (
|
|||
|
mailslotHandle,
|
|||
|
DieMessage,
|
|||
|
strlen(DieMessage)+1,
|
|||
|
&numWritten,
|
|||
|
NULL)) {
|
|||
|
|
|||
|
MSG_LOG(TRACE,"MsgThreadWakeup: WriteFile on Mailslot Failed %d\n",
|
|||
|
GetLastError())
|
|||
|
|
|||
|
//
|
|||
|
// Since we can't wake up the group thread,
|
|||
|
// deregister the work item here instead
|
|||
|
//
|
|||
|
DEREGISTER_WORK_ITEM(g_hGrpEvent);
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle(mailslotHandle);
|
|||
|
|
|||
|
//
|
|||
|
// Wait for the group messenger to be shutdown.
|
|||
|
// We will wait up to 20.300 seconds for this before going on.
|
|||
|
//
|
|||
|
Sleep(300);
|
|||
|
for (i=0; i<20; i++) {
|
|||
|
|
|||
|
if (GrpMailslotHandle == INVALID_HANDLE_VALUE) {
|
|||
|
MSG_LOG0(TRACE,"MsgGroupThreadShutdown: Group Thread has completed\n");
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
MSG_LOG1(TRACE,"MsgGroupThreadShutdown: Group Thread alive after %d seconds\n",
|
|||
|
(i + 1) * 1000);
|
|||
|
Sleep(1000);
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|