|
|
/********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1987-1992 **/ /********************************************************************/
/*
** Routines to log messages ** ** If message logging is off, all messages are buffered. Further, ** even if messages are being logged, multi-block messages must ** be buffered since they must be spooled to the logging file or ** device. Since there is only one message buffer in which to ** buffer all messages, this buffer must be managed as a heap. ** Also, messages are logged in a first-in-first-out manner, ** so messages in the buffer must be kept in a queue. In order ** to meet these goals, the following message blocks are defined: ** ** SBM - single-block message ** ** length - length of entire block (2 bytes) ** code - identifies block as single-block message (1 byte) ** link - link to next message in message queue (2 bytes) ** date - date message received (2 bytes) ** time - time message received (2 bytes) ** from - name of sender (null-terminated string) ** to - name of recipient (null-terminated string) ** text - text of message (remainder of block) ** ** MBB - multi-block message header ** ** length - length of entire block (2 bytes) ** code - identifies block as multi-block message header (1 byte) ** link - link to next message in message queue (2 bytes) ** date - date message received (2 bytes) ** time - time message received (2 bytes) ** btext - link to last text block (2 bytes) ** ftext - link to first text block (2 bytes) ** error - error flag (1 byte) ** from - name of sender (null-terminated string) ** to - name of recipient (null-terminated string) ** ** MBT - multi-block message text block ** ** length - length of entire block (2 bytes) ** code - identifies block a multi-block message text (1 byte) ** link - link to next text block (2 bytes) ** text - text of message (remainder of block) **/
//
// Includes
//
#include "msrv.h"
#include <string.h> // memcpy
#include <tstring.h> // Unicode string macros
#include <netdebug.h> // NetpAssert
#include <lmalert.h> // Alert stuff
#include <netlib.h> // UNUSED macro
#include <netlibnt.h> // NetpNtStatusToApiStatus
#include <smbtypes.h> // needed for smb.h
#include <smb.h> // Server Message Block definitions
#include <lmerrlog.h> // NELOG_ messages
#include <smbgtpt.h> // SMB field manipulation macros
#include <winuser.h> // MessageBox
#include <winsock2.h> // Windows sockets
#include "msgdbg.h" // MSG_LOG
#include "msgdata.h"
//
// Defines for Hex Dump Function
//
#ifndef MIN
#define MIN(a,b) ( ( (a) < (b) ) ? (a) : (b) )
#endif
#define DWORDS_PER_LINE 4
#define BYTES_PER_LINE (DWORDS_PER_LINE * sizeof(DWORD))
#define SPACE_BETWEEN_BYTES NetpKdPrint((" "))
#define SPACE_BETWEEN_DWORDS NetpKdPrint((" "))
//
// Local Functions
//
NET_API_STATUS MsgOutputMsg ( USHORT AlertLength, LPSTR AlertBuffer, ULONG SessionId, SYSTEMTIME BigTime );
//
// Data
//
PSTD_ALERT alert_buf_ptr; // Pointer to DosAlloc'ed alert buffer
USHORT alert_len; // Currently used length of alert buffer
//
// Defines
//
#define ERROR_LOG_SIZE 1024
/*
** Msglogmbb - log a multi-block message header ** ** This function is called to log a multi-block message header. ** The message header is placed in the message buffer which resides ** in the shared data area. ** ** This function stores the from and to information in the shared data ** buffer and initializes the multi-block message header. Then it puts ** a pointer to the multi-block header into the shared data pointer ** location for that net index and name index. ** ** logmbb (from, to, net, ncbi) ** ** ENTRY ** from - sender name ** to - recipient name ** net - network index ** ncbi - Network Control Block index ** ** RETURN ** zero if successful, non-zero if unable to buffer the message header ** ** SIDE EFFECTS ** ** Calls heapalloc() to obtain buffer space. **/
DWORD Msglogmbb( LPSTR from, // Name of sender
LPSTR to, // Name of recipient
DWORD net, // Which network ?
DWORD ncbi // Network Control Block index
)
{ DWORD i; // Heap index
LPSTR fcp; // Far character pointer
LONG ipAddress; struct hostent *pHostEntry;
//
// Synchronize with Pnp configuration routine
//
MsgConfigurationLock(MSG_GET_SHARED,"Msglogmbb");
//
// Block until the shared database is free
//
MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logmbb");
//
// Check whether the recipient name needs to be formatted
//
ipAddress = inet_addr( to ); if (ipAddress != INADDR_NONE) { pHostEntry = gethostbyaddr( (char *)&ipAddress,sizeof( LONG ),AF_INET); if (pHostEntry) { to = pHostEntry->h_name; } else { MSG_LOG2(ERROR,"Msglogmbb: could not lookup addr %s, error %d\n", to, WSAGetLastError()); } }
//
// Allocate space for header
//
i = Msgheapalloc(sizeof(MBB) + strlen(from) + strlen(to) + 2);
if(i == INULL) { // If no buffer space
//
// Unlock the shared database
//
MsgDatabaseLock(MSG_RELEASE,"logmbb"); MsgConfigurationLock(MSG_RELEASE,"Msglogmbb");
return((int) i); // Log fails
}
//
// Multi-block message
//
MBB_CODE(*MBBPTR(i)) = SMB_COM_SEND_START_MB_MESSAGE; MBB_NEXT(*MBBPTR(i)) = INULL; // Last message in buffer
GetLocalTime(&MBB_BIGTIME(*MBBPTR(i))); // Time of message
MBB_BTEXT(*MBBPTR(i)) = INULL; // No text yet
MBB_FTEXT(*MBBPTR(i)) = INULL; // No text yet
MBB_STATE(*MBBPTR(i)) = MESCONT; // Message in progress
fcp = CPTR(i + sizeof(MBB)); // Get far pointer into buffer
strcpy(fcp, from); // Copy the sender name
fcp += strlen(from) + 1; // Increment pointer
strcpy(fcp, to); // Copy the recipient name
SD_MESPTR(net,ncbi) = i; // Save index to this record
//
// Unlock the shared database
//
MsgDatabaseLock(MSG_RELEASE,"logmbb"); MsgConfigurationLock(MSG_RELEASE,"Msglogmbb");
return(0); // Message logged successfully
}
/*
** Msglogmbe - log end of a multi-block message ** ** This function is called to log a multi-block message end. ** The message is marked as finished, and if logging is enabled, ** an attempt is made to write the message to the log file. If ** this attempt fails, or if logging is disabled, then the message ** is placed in the message queue in the message buffer. ** ** The message is gathered up and placed in the alert buffer and an alert ** is raised. ** ** logmbe (state, net,ncbi) ** ** ENTRY ** state - final state of message ** net - Network index ** ncbi - Network Control Block index ** ** RETURN ** int - BUFFERED if the message is left in the buffer ** int - LOGGED if the message is written to the log file ** ** FOR NT: ** SMB_ERR_SUCCESS - success in alerting ** SMB_ERR_... - an error occured ** ** ** ** SIDE EFFECTS ** ** Calls mbmprint() to print the message if logging is enabled. Calls ** mbmfree() to free the message if logging succeeds. **/
UCHAR Msglogmbe( DWORD state, // Final state of message
DWORD net, // Which network?
DWORD ncbi // Network Control Block index
) { DWORD i; // Heap index
DWORD error; // Error code
DWORD meslog; // Message logging status
DWORD alert_flag; // Alert buffer allocated flag
DWORD status; // Dos error for error log
DWORD bufSize; // Buffer Size
SYSTEMTIME bigtime; // Date and time of message
PMSG_SESSION_ID_ITEM pItem; PLIST_ENTRY pHead; PLIST_ENTRY pList;
//
// Synchronize with Pnp configuration routine
//
MsgConfigurationLock(MSG_GET_SHARED,"Msglogmbe");
//
// Block until the shared database is free
//
MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logmbe");
pHead = &(SD_SIDLIST(net,ncbi)); pList = pHead;
//
// First get a buffer for an alert
//
bufSize = sizeof( STD_ALERT) + ALERT_MAX_DISPLAYED_MSG_SIZE + (2*TXTMAX) + 2;
alert_buf_ptr = (PSTD_ALERT)LocalAlloc(LMEM_ZEROINIT, bufSize);
if (alert_buf_ptr == NULL) { MSG_LOG(ERROR,"logmbe:Local Alloc failed\n",0); alert_flag = 0xffffffff; // No alerting if Alloc failed
} else { alert_flag = 0; // File and alerting
alert_len = 0;
}
error = 0; // Assume no error
i = SD_MESPTR(net,ncbi); // Get index to message header
MBB_STATE(*MBBPTR(i)) = state; // Record final state
//
// If logging now disabled ...
//
if(!SD_MESLOG()) { if( alert_flag == 0) { //
// Format the message and put it in the alert buffer.
//
// Alert only. alert_flag is only modified if Msgmbmprint
// returns success and we should skip the message (i.e.,
// it's a print notification from a pre-Whistler machine).
//
if (Msgmbmprint(1,i,0, &alert_flag)) { alert_flag = 0xffffffff; } } }
//
// Add message to buffer queue if logging is off,
// or if the attempt to log the message failed.
//
meslog = SD_MESLOG(); // Get logging status
if(!meslog) { // If logging disabled
Msgmbmfree(i); }
if(error != 0) { //
// We should never get here
//
NetpAssert(error == 0); }
//
// Now alert and free up alert buffer if it was successfully allocated
//
if( alert_flag == 0) { //
// There is an alert buffer, output it.
//
GetLocalTime(&bigtime); // Get the time
if (g_IsTerminalServer) { //
// Output the message for all the sessions sharing that name
//
while (pList->Flink != pHead) // loop all over the list
{ pList = pList->Flink; pItem = CONTAINING_RECORD(pList, MSG_SESSION_ID_ITEM, List); MsgOutputMsg(alert_len, (LPSTR)alert_buf_ptr, pItem->SessionId, bigtime); } } else // regular NT
{ MsgOutputMsg(alert_len, (LPSTR)alert_buf_ptr, 0, bigtime); } }
LocalFree(alert_buf_ptr);
//
// Unlock the shared database
//
MsgDatabaseLock(MSG_RELEASE,"logmbe");
MsgConfigurationLock(MSG_RELEASE,"Msglogmbe");
return(SMB_ERR_SUCCESS); // Message arrived
}
/*
** Msglogmbt - log a multi-block message text block ** ** This function is called to log a multi-block message text block. ** The text block is placed in the message buffer which resides ** in the shared data area. If there is insufficient room in the ** buffer, logmbt() removes the header and any previous blocks of ** the message from the buffer. ** ** This function gets the current message from the message pointer in ** the shared data (for that net & name index). It looks in the header ** to see if there are any text blocks already there. If so, it adds ** this new one to the list and fixes the last block pointer to point to ** it. ** ** logmbt (text, net, ncbi) ** ** ENTRY ** text - text header ** net - Network index ** ncbi - Network Control Block index ** ** RETURN ** zero if successful, non-zero if unable to buffer the message header ** ** SIDE EFFECTS ** ** Calls heapalloc() to obtain buffer space. Calls mbmfree() if a call to ** heapalloc() fails. **/
DWORD Msglogmbt( LPSTR text, // Text of message
DWORD net, // Which network?
DWORD ncbi // Network Control Block index
) { DWORD i; // Heap index
DWORD j; // Heap index
DWORD k; // Heap index
USHORT length; // Length of text
//
// Synchronize with Pnp configuration routine
//
MsgConfigurationLock(MSG_GET_SHARED,"Msglogmbt");
// *ALIGNMENT*
length = SmbGetUshort( (PUSHORT)text); // Get length of text block
// length = *((PSHORT) text); // Get length of text block
text += sizeof(short); // Skip over length word
//
// Block until the shared database is free
//
MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logmbt");
i = Msgheapalloc(sizeof(MBT) + length); // Allocate space for block
//
// If buffer space is available
//
if(i != INULL) {
//
// Multi-block message text
//
MBT_CODE(*MBTPTR(i)) = SMB_COM_SEND_TEXT_MB_MESSAGE;
MBT_NEXT(*MBTPTR(i)) = INULL; // Last text block so far
MBT_COUNT(*MBTPTR(i)) = (DWORD)length; // *ALIGNMENT2*
memcpy(CPTR(i + sizeof(MBT)), text, length);
// Copy text into buffer
j = SD_MESPTR(net, ncbi); // Get index to current message
if(MBB_FTEXT(*MBBPTR(j)) != INULL) { //
// If there is text already, Get pointer to last block and
// add new block
//
k = MBB_BTEXT(*MBBPTR(j)); // Get pointer to last block
MBT_NEXT(*MBTPTR(k)) = i; // Add new block
} else { MBB_FTEXT(*MBBPTR(j)) = i; // Else set front pointer
}
MBB_BTEXT(*MBBPTR(j)) = i; // Set back pointer
i = 0; // Success
} else { Msgmbmfree(SD_MESPTR(net,ncbi)); // Else deallocate the message
}
//
// Unlock the shared database
//
MsgDatabaseLock(MSG_RELEASE,"logmbt");
MsgConfigurationLock(MSG_RELEASE,"Msglogmbt");
return((int) i); // Return status
}
/*
** Msglogsbm - log a single-block message ** ** This function is called to log a single-block message. If ** logging is enabled, the message is written directly to the ** logging file or device. If logging is disabled or if the ** attempt to log the message fails, the message is placed in ** the message buffer which resides in the shared data area. ** ** logsbm (from, to, text) ** ** ENTRY ** from - sender name ** to - recipient name ** text - text of message ** ** RETURN ** zero if successful, non-zero if unable to log the message ** ** SIDE EFFECTS ** ** Calls hdrprint(), txtprint(), and endprint() to print the message if ** logging is enabled. Calls heapalloc() to obtain buffer space if ** the message must be buffered. **/
DWORD Msglogsbm( LPSTR from, // Name of sender
LPSTR to, // Name of recipient
LPSTR text, // Text of message
ULONG SessionId // Session Id
) { DWORD i; // Heap index
DWORD error; // Error code
SHORT length; // Length of text
DWORD meslog; // Message logging status
DWORD alert_flag; // Alert buffer allocated flag
DWORD status; // DOS error from mespeint functions
SYSTEMTIME bigtime; // Date and time of message
DWORD bufSize; // Buffer Size
//
// Synchronize with Pnp configuration routine
//
MsgConfigurationLock(MSG_GET_SHARED,"Msglogsbm");
//
// Block until the shared database is free
//
MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logsbm");
//
// First get a buffer for an alert
//
bufSize = sizeof( STD_ALERT) + ALERT_MAX_DISPLAYED_MSG_SIZE + (2*TXTMAX) + 2;
alert_buf_ptr = (PSTD_ALERT)LocalAlloc(LMEM_ZEROINIT, bufSize);
if (alert_buf_ptr == NULL) { MSG_LOG(ERROR,"Msglogsbm:Local Alloc failed\n",0); alert_flag = 0xffffffff; // No alerting if Alloc failed
} else { alert_flag = 0; // File and alerting
alert_len = 0; }
// *ALIGNMENT*
length = SmbGetUshort( (PUSHORT)text); // Get length of text block
text += sizeof(short); // Skip over length word
error = 0; // Assume no errors
//
// Hack to drop messages sent by pre-Whistler Spoolers. As of
// Whistler, print notifications are done as shell balloon tips
// so don't display print alerts sent from the server as well.
//
// This check is also made in Msgmbmprint to catch multi-block messages.
//
if ((g_lpAlertSuccessMessage && _strnicmp(text, g_lpAlertSuccessMessage, g_dwAlertSuccessLen) == 0) || (g_lpAlertFailureMessage && _strnicmp(text, g_lpAlertFailureMessage, g_dwAlertFailureLen) == 0)) { MsgDatabaseLock(MSG_RELEASE,"logsbm"); MsgConfigurationLock(MSG_RELEASE,"Msglogsbm"); return 0; }
GetLocalTime(&bigtime); // Get the time
if (!SD_MESLOG()) // If logging disabled
{ if( alert_flag == 0) // If alert buf is valid
{ if (!Msghdrprint(1,from, to, bigtime,0)) { if (Msgtxtprint(1, text,length,0)) { alert_flag = 0xffffffff; } } else { alert_flag = 0xffffffff; } } }
meslog = SD_MESLOG(); // Get logging status
i = 0; // No way to fail if not logging
if(error != 0) { DbgPrint("meslog.c:logsbm(before ErrorLogWrite): We should never get here\n"); NetpAssert(0); }
// Now alert and free up alert buffer if it was successfully allocated
if( alert_flag == 0) { // There is an alert buffer
//
// There is an alert buffer, output it.
//
MsgOutputMsg(alert_len, (LPSTR)alert_buf_ptr, SessionId, bigtime); }
LocalFree(alert_buf_ptr);
//
// Unlock the shared database
//
MsgDatabaseLock(MSG_RELEASE,"logsbm");
MsgConfigurationLock(MSG_RELEASE,"Msglogsbm");
return((int) i); // Return status
}
NET_API_STATUS MsgOutputMsg ( USHORT AlertLength, LPSTR AlertBuffer, ULONG SessionId, SYSTEMTIME BigTime )
/*++
Routine Description:
This function translates the alert buffer from an Ansi String to a Unicode String and outputs the buffer to whereever it is to go. Currently this just becomes a DbgPrint.
Arguments:
AlertLength - The number of bytes in the AlertBuffer.
AlertBuffer - This is a pointer to the buffer that contains the message that is to be output. The buffer is expected to contain a NUL Terminated Ansi String.
BigTime - The SYSTEMTIME that indicates the time the end of the messsage was received.
Return Value:
--*/
{ UNICODE_STRING unicodeString; OEM_STRING ansiString;
NTSTATUS ntStatus;
//
// NUL Terminate the message.
// Translate the Ansi message to a Unicode Message.
//
AlertBuffer[AlertLength++] = '\0';
ansiString.Length = AlertLength; ansiString.MaximumLength = AlertLength; ansiString.Buffer = AlertBuffer;
ntStatus = RtlOemStringToUnicodeString( &unicodeString, // Destination
&ansiString, // Source
TRUE); // Allocate the destination.
if (!NT_SUCCESS(ntStatus)) { MSG_LOG(ERROR, "MsgOutputMsg:RtlOemStringToUnicodeString Failed rc=%X\n", ntStatus);
//
// EXPLANATION OF WHY IT RETURNS SUCCESS HERE.
// Returning success even though the alert is not raised is
// consistent with the LM2.0 code which doesn't check the
// return code for the NetAlertRaise API anyway. Returning
// anything else would require a re-design of how errors are
// handled by the caller of this routine.
//
return(NERR_Success); }
//*******************************************************************
//
// PUT THE MESSAGE IN THE DISPLAY QUEUE
//
MsgDisplayQueueAdd( AlertBuffer, (DWORD)AlertLength, SessionId, BigTime);
//
//
//*******************************************************************
RtlFreeUnicodeString(&unicodeString); return(NERR_Success); }
|