Leaked source code of windows server 2003
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.
 
 
 
 
 
 

745 lines
22 KiB

/********************************************************************/
/** 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);
}