windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/msgsvc/server/grpmsngr.c

387 lines
9.5 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*--
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;
}