977 lines
26 KiB
C
977 lines
26 KiB
C
/********************************************************************/
|
||
/** 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 <netdebug.h> // NetpDbgHexDump
|
||
#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
|
||
);
|
||
|
||
#if DBG
|
||
VOID
|
||
MsgDbgHexDumpLine(
|
||
IN LPBYTE StartAddr,
|
||
IN DWORD BytesInThisLine
|
||
);
|
||
|
||
VOID
|
||
MsgDbgHexDump(
|
||
IN LPBYTE StartAddr,
|
||
IN DWORD Length
|
||
);
|
||
#endif //DBG
|
||
|
||
//
|
||
// 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) {
|
||
|
||
//
|
||
// Report to error log
|
||
//
|
||
|
||
NetpAssert(0); // NT code should never get here.
|
||
|
||
MsgErrorLogWrite(
|
||
error,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE)&status,
|
||
sizeof(DWORD),
|
||
NULL,
|
||
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);
|
||
|
||
MsgErrorLogWrite( // Report to error log
|
||
error,
|
||
SERVICE_MESSENGER,
|
||
(LPBYTE)&status,
|
||
sizeof(DWORD),
|
||
NULL,
|
||
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
|
||
MsgErrorLogWrite(
|
||
IN DWORD Code,
|
||
IN LPTSTR Component,
|
||
IN LPBYTE Buffer,
|
||
IN DWORD BufferSize,
|
||
IN LPSTR Strings,
|
||
IN DWORD NumStrings
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Writes an entry to the event manager on the local computer.
|
||
|
||
This function needs to get the error message text out of the message
|
||
file and send it to the event logger.
|
||
|
||
Arguments:
|
||
|
||
Code - Specifies the code of the error that occured.
|
||
|
||
Component - Points to a NUL terminated string that specifies which
|
||
component encountered the error. UNICODE STRING.
|
||
|
||
Buffer - Points to a string of raw data associated with the error
|
||
condition.
|
||
|
||
BufferSize - size (in bytes) of the buffer.
|
||
|
||
Strings - NOT USED.
|
||
Points to NUL terminated strings that contain the
|
||
error message. ANSI STRINGS.
|
||
|
||
NumStrings - NOT USED.
|
||
Specifies how many concatenated NUL terminated strings
|
||
are stored in Strings.
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
|
||
--*/
|
||
{
|
||
DWORD status;
|
||
WORD msglen=0;
|
||
LPBYTE msgBuf;
|
||
|
||
//
|
||
// Get a message associated with the message code from the message
|
||
// file.
|
||
//
|
||
|
||
msgBuf = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, ERROR_LOG_SIZE);
|
||
|
||
if (msgBuf == NULL) {
|
||
status = GetLastError();
|
||
MSG_LOG(ERROR,"MsgErrorLogWrite: LocalAlloc FAILURE %X\n",
|
||
status);
|
||
return(status);
|
||
}
|
||
|
||
//
|
||
// TODO ITEM:
|
||
// If we actually used strings, then they must be converted to unicode.
|
||
// However, since they are never used, this isn't very important.
|
||
//
|
||
|
||
status = DosGetMessage (
|
||
&Strings, // String substitution table
|
||
(USHORT)NumStrings, // Num Entries in table above
|
||
msgBuf, // Buffer receiving message
|
||
ERROR_LOG_SIZE, // size of buffer receiving msg
|
||
(USHORT)Code, // message num to retrieve
|
||
MessageFileName, // Name of message file
|
||
&msglen); // Num bytes returned
|
||
|
||
if (status != NERR_Success) {
|
||
LocalFree(msgBuf);
|
||
return(status);
|
||
}
|
||
|
||
#if DBG
|
||
|
||
DbgPrint("MsgErrorLogWrite: COMPONENT = %ws\n",Component);
|
||
DbgPrint("MsgErrorLogWrite: %s\n",msgBuf);
|
||
|
||
if ( Buffer != NULL )
|
||
{
|
||
MsgDbgHexDump( (LPBYTE)Buffer, BufferSize);
|
||
}
|
||
|
||
#endif //DBG
|
||
|
||
UNREFERENCED_PARAMETER(Buffer);
|
||
UNREFERENCED_PARAMETER(BufferSize);
|
||
|
||
LocalFree(msgBuf);
|
||
return(NERR_Success);
|
||
}
|
||
|
||
|
||
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);
|
||
}
|
||
|
||
#if DBG
|
||
VOID
|
||
MsgDbgHexDumpLine(
|
||
IN LPBYTE StartAddr,
|
||
IN DWORD BytesInThisLine
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
LPBYTE BytePtr;
|
||
DWORD BytesDone;
|
||
DWORD HexPosition;
|
||
|
||
DbgPrint(FORMAT_LPVOID " ", (LPVOID) StartAddr);
|
||
|
||
BytePtr = StartAddr;
|
||
BytesDone = 0;
|
||
while (BytesDone < BytesInThisLine) {
|
||
DbgPrint("%02X", *BytePtr); // space for "xx" (see pad below).
|
||
SPACE_BETWEEN_BYTES;
|
||
++BytesDone;
|
||
if ( (BytesDone % sizeof(DWORD)) == 0) {
|
||
SPACE_BETWEEN_DWORDS;
|
||
}
|
||
++BytePtr;
|
||
}
|
||
|
||
HexPosition = BytesDone;
|
||
while (HexPosition < BYTES_PER_LINE) {
|
||
DbgPrint(" "); // space for "xx" (see byte above).
|
||
SPACE_BETWEEN_BYTES;
|
||
++HexPosition;
|
||
if ( (HexPosition % sizeof(DWORD)) == 0) {
|
||
SPACE_BETWEEN_DWORDS;
|
||
}
|
||
}
|
||
|
||
BytePtr = StartAddr;
|
||
BytesDone = 0;
|
||
while (BytesDone < BytesInThisLine) {
|
||
if (isprint(*BytePtr)) {
|
||
DbgPrint( FORMAT_CHAR, (CHAR) *BytePtr );
|
||
} else {
|
||
DbgPrint( "." );
|
||
}
|
||
++BytesDone;
|
||
++BytePtr;
|
||
}
|
||
DbgPrint("\n");
|
||
|
||
} // MsgDbgHexDumpLine
|
||
|
||
VOID
|
||
MsgDbgHexDump(
|
||
IN LPBYTE StartAddr,
|
||
IN DWORD Length
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
MsgDbgHexDump: do a hex dump of some number of bytes to the debug
|
||
terminal or whatever. This is a no-op in a nondebug build.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
DWORD BytesLeft = Length;
|
||
LPBYTE LinePtr = StartAddr;
|
||
DWORD LineSize;
|
||
|
||
while (BytesLeft > 0) {
|
||
LineSize = MIN(BytesLeft, BYTES_PER_LINE);
|
||
MsgDbgHexDumpLine( LinePtr, LineSize );
|
||
BytesLeft -= LineSize;
|
||
LinePtr += LineSize;
|
||
}
|
||
|
||
} // NetpDbgHexDump
|
||
|
||
#endif // DBG
|