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

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1987-1992 **/
  4. /********************************************************************/
  5. /*
  6. ** Routines to log messages
  7. **
  8. ** If message logging is off, all messages are buffered. Further,
  9. ** even if messages are being logged, multi-block messages must
  10. ** be buffered since they must be spooled to the logging file or
  11. ** device. Since there is only one message buffer in which to
  12. ** buffer all messages, this buffer must be managed as a heap.
  13. ** Also, messages are logged in a first-in-first-out manner,
  14. ** so messages in the buffer must be kept in a queue. In order
  15. ** to meet these goals, the following message blocks are defined:
  16. **
  17. ** SBM - single-block message
  18. **
  19. ** length - length of entire block (2 bytes)
  20. ** code - identifies block as single-block message (1 byte)
  21. ** link - link to next message in message queue (2 bytes)
  22. ** date - date message received (2 bytes)
  23. ** time - time message received (2 bytes)
  24. ** from - name of sender (null-terminated string)
  25. ** to - name of recipient (null-terminated string)
  26. ** text - text of message (remainder of block)
  27. **
  28. ** MBB - multi-block message header
  29. **
  30. ** length - length of entire block (2 bytes)
  31. ** code - identifies block as multi-block message header (1 byte)
  32. ** link - link to next message in message queue (2 bytes)
  33. ** date - date message received (2 bytes)
  34. ** time - time message received (2 bytes)
  35. ** btext - link to last text block (2 bytes)
  36. ** ftext - link to first text block (2 bytes)
  37. ** error - error flag (1 byte)
  38. ** from - name of sender (null-terminated string)
  39. ** to - name of recipient (null-terminated string)
  40. **
  41. ** MBT - multi-block message text block
  42. **
  43. ** length - length of entire block (2 bytes)
  44. ** code - identifies block a multi-block message text (1 byte)
  45. ** link - link to next text block (2 bytes)
  46. ** text - text of message (remainder of block)
  47. **/
  48. //
  49. // Includes
  50. //
  51. #include "msrv.h"
  52. #include <string.h> // memcpy
  53. #include <tstring.h> // Unicode string macros
  54. #include <netdebug.h> // NetpAssert
  55. #include <lmalert.h> // Alert stuff
  56. #include <netlib.h> // UNUSED macro
  57. #include <netlibnt.h> // NetpNtStatusToApiStatus
  58. #include <smbtypes.h> // needed for smb.h
  59. #include <smb.h> // Server Message Block definitions
  60. #include <lmerrlog.h> // NELOG_ messages
  61. #include <smbgtpt.h> // SMB field manipulation macros
  62. #include <winuser.h> // MessageBox
  63. #include <winsock2.h> // Windows sockets
  64. #include "msgdbg.h" // MSG_LOG
  65. #include "msgdata.h"
  66. //
  67. // Defines for Hex Dump Function
  68. //
  69. #ifndef MIN
  70. #define MIN(a,b) ( ( (a) < (b) ) ? (a) : (b) )
  71. #endif
  72. #define DWORDS_PER_LINE 4
  73. #define BYTES_PER_LINE (DWORDS_PER_LINE * sizeof(DWORD))
  74. #define SPACE_BETWEEN_BYTES NetpKdPrint((" "))
  75. #define SPACE_BETWEEN_DWORDS NetpKdPrint((" "))
  76. //
  77. // Local Functions
  78. //
  79. NET_API_STATUS
  80. MsgOutputMsg (
  81. USHORT AlertLength,
  82. LPSTR AlertBuffer,
  83. ULONG SessionId,
  84. SYSTEMTIME BigTime
  85. );
  86. //
  87. // Data
  88. //
  89. PSTD_ALERT alert_buf_ptr; // Pointer to DosAlloc'ed alert buffer
  90. USHORT alert_len; // Currently used length of alert buffer
  91. //
  92. // Defines
  93. //
  94. #define ERROR_LOG_SIZE 1024
  95. /*
  96. ** Msglogmbb - log a multi-block message header
  97. **
  98. ** This function is called to log a multi-block message header.
  99. ** The message header is placed in the message buffer which resides
  100. ** in the shared data area.
  101. **
  102. ** This function stores the from and to information in the shared data
  103. ** buffer and initializes the multi-block message header. Then it puts
  104. ** a pointer to the multi-block header into the shared data pointer
  105. ** location for that net index and name index.
  106. **
  107. ** logmbb (from, to, net, ncbi)
  108. **
  109. ** ENTRY
  110. ** from - sender name
  111. ** to - recipient name
  112. ** net - network index
  113. ** ncbi - Network Control Block index
  114. **
  115. ** RETURN
  116. ** zero if successful, non-zero if unable to buffer the message header
  117. **
  118. ** SIDE EFFECTS
  119. **
  120. ** Calls heapalloc() to obtain buffer space.
  121. **/
  122. DWORD
  123. Msglogmbb(
  124. LPSTR from, // Name of sender
  125. LPSTR to, // Name of recipient
  126. DWORD net, // Which network ?
  127. DWORD ncbi // Network Control Block index
  128. )
  129. {
  130. DWORD i; // Heap index
  131. LPSTR fcp; // Far character pointer
  132. LONG ipAddress;
  133. struct hostent *pHostEntry;
  134. //
  135. // Synchronize with Pnp configuration routine
  136. //
  137. MsgConfigurationLock(MSG_GET_SHARED,"Msglogmbb");
  138. //
  139. // Block until the shared database is free
  140. //
  141. MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logmbb");
  142. //
  143. // Check whether the recipient name needs to be formatted
  144. //
  145. ipAddress = inet_addr( to );
  146. if (ipAddress != INADDR_NONE) {
  147. pHostEntry = gethostbyaddr( (char *)&ipAddress,sizeof( LONG ),AF_INET);
  148. if (pHostEntry) {
  149. to = pHostEntry->h_name;
  150. } else {
  151. MSG_LOG2(ERROR,"Msglogmbb: could not lookup addr %s, error %d\n",
  152. to, WSAGetLastError());
  153. }
  154. }
  155. //
  156. // Allocate space for header
  157. //
  158. i = Msgheapalloc(sizeof(MBB) + strlen(from) + strlen(to) + 2);
  159. if(i == INULL) { // If no buffer space
  160. //
  161. // Unlock the shared database
  162. //
  163. MsgDatabaseLock(MSG_RELEASE,"logmbb");
  164. MsgConfigurationLock(MSG_RELEASE,"Msglogmbb");
  165. return((int) i); // Log fails
  166. }
  167. //
  168. // Multi-block message
  169. //
  170. MBB_CODE(*MBBPTR(i)) = SMB_COM_SEND_START_MB_MESSAGE;
  171. MBB_NEXT(*MBBPTR(i)) = INULL; // Last message in buffer
  172. GetLocalTime(&MBB_BIGTIME(*MBBPTR(i))); // Time of message
  173. MBB_BTEXT(*MBBPTR(i)) = INULL; // No text yet
  174. MBB_FTEXT(*MBBPTR(i)) = INULL; // No text yet
  175. MBB_STATE(*MBBPTR(i)) = MESCONT; // Message in progress
  176. fcp = CPTR(i + sizeof(MBB)); // Get far pointer into buffer
  177. strcpy(fcp, from); // Copy the sender name
  178. fcp += strlen(from) + 1; // Increment pointer
  179. strcpy(fcp, to); // Copy the recipient name
  180. SD_MESPTR(net,ncbi) = i; // Save index to this record
  181. //
  182. // Unlock the shared database
  183. //
  184. MsgDatabaseLock(MSG_RELEASE,"logmbb");
  185. MsgConfigurationLock(MSG_RELEASE,"Msglogmbb");
  186. return(0); // Message logged successfully
  187. }
  188. /*
  189. ** Msglogmbe - log end of a multi-block message
  190. **
  191. ** This function is called to log a multi-block message end.
  192. ** The message is marked as finished, and if logging is enabled,
  193. ** an attempt is made to write the message to the log file. If
  194. ** this attempt fails, or if logging is disabled, then the message
  195. ** is placed in the message queue in the message buffer.
  196. **
  197. ** The message is gathered up and placed in the alert buffer and an alert
  198. ** is raised.
  199. **
  200. ** logmbe (state, net,ncbi)
  201. **
  202. ** ENTRY
  203. ** state - final state of message
  204. ** net - Network index
  205. ** ncbi - Network Control Block index
  206. **
  207. ** RETURN
  208. ** int - BUFFERED if the message is left in the buffer
  209. ** int - LOGGED if the message is written to the log file
  210. **
  211. ** FOR NT:
  212. ** SMB_ERR_SUCCESS - success in alerting
  213. ** SMB_ERR_... - an error occured
  214. **
  215. **
  216. **
  217. ** SIDE EFFECTS
  218. **
  219. ** Calls mbmprint() to print the message if logging is enabled. Calls
  220. ** mbmfree() to free the message if logging succeeds.
  221. **/
  222. UCHAR
  223. Msglogmbe(
  224. DWORD state, // Final state of message
  225. DWORD net, // Which network?
  226. DWORD ncbi // Network Control Block index
  227. )
  228. {
  229. DWORD i; // Heap index
  230. DWORD error; // Error code
  231. DWORD meslog; // Message logging status
  232. DWORD alert_flag; // Alert buffer allocated flag
  233. DWORD status; // Dos error for error log
  234. DWORD bufSize; // Buffer Size
  235. SYSTEMTIME bigtime; // Date and time of message
  236. PMSG_SESSION_ID_ITEM pItem;
  237. PLIST_ENTRY pHead;
  238. PLIST_ENTRY pList;
  239. //
  240. // Synchronize with Pnp configuration routine
  241. //
  242. MsgConfigurationLock(MSG_GET_SHARED,"Msglogmbe");
  243. //
  244. // Block until the shared database is free
  245. //
  246. MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logmbe");
  247. pHead = &(SD_SIDLIST(net,ncbi));
  248. pList = pHead;
  249. //
  250. // First get a buffer for an alert
  251. //
  252. bufSize = sizeof( STD_ALERT) +
  253. ALERT_MAX_DISPLAYED_MSG_SIZE +
  254. (2*TXTMAX) + 2;
  255. alert_buf_ptr = (PSTD_ALERT)LocalAlloc(LMEM_ZEROINIT, bufSize);
  256. if (alert_buf_ptr == NULL) {
  257. MSG_LOG(ERROR,"logmbe:Local Alloc failed\n",0);
  258. alert_flag = 0xffffffff; // No alerting if Alloc failed
  259. }
  260. else {
  261. alert_flag = 0; // File and alerting
  262. alert_len = 0;
  263. }
  264. error = 0; // Assume no error
  265. i = SD_MESPTR(net,ncbi); // Get index to message header
  266. MBB_STATE(*MBBPTR(i)) = state; // Record final state
  267. //
  268. // If logging now disabled ...
  269. //
  270. if(!SD_MESLOG())
  271. {
  272. if( alert_flag == 0)
  273. {
  274. //
  275. // Format the message and put it in the alert buffer.
  276. //
  277. // Alert only. alert_flag is only modified if Msgmbmprint
  278. // returns success and we should skip the message (i.e.,
  279. // it's a print notification from a pre-Whistler machine).
  280. //
  281. if (Msgmbmprint(1,i,0, &alert_flag))
  282. {
  283. alert_flag = 0xffffffff;
  284. }
  285. }
  286. }
  287. //
  288. // Add message to buffer queue if logging is off,
  289. // or if the attempt to log the message failed.
  290. //
  291. meslog = SD_MESLOG(); // Get logging status
  292. if(!meslog)
  293. { // If logging disabled
  294. Msgmbmfree(i);
  295. }
  296. if(error != 0)
  297. {
  298. //
  299. // We should never get here
  300. //
  301. NetpAssert(error == 0);
  302. }
  303. //
  304. // Now alert and free up alert buffer if it was successfully allocated
  305. //
  306. if( alert_flag == 0) {
  307. //
  308. // There is an alert buffer, output it.
  309. //
  310. GetLocalTime(&bigtime); // Get the time
  311. if (g_IsTerminalServer)
  312. {
  313. //
  314. // Output the message for all the sessions sharing that name
  315. //
  316. while (pList->Flink != pHead) // loop all over the list
  317. {
  318. pList = pList->Flink;
  319. pItem = CONTAINING_RECORD(pList, MSG_SESSION_ID_ITEM, List);
  320. MsgOutputMsg(alert_len, (LPSTR)alert_buf_ptr, pItem->SessionId, bigtime);
  321. }
  322. }
  323. else // regular NT
  324. {
  325. MsgOutputMsg(alert_len, (LPSTR)alert_buf_ptr, 0, bigtime);
  326. }
  327. }
  328. LocalFree(alert_buf_ptr);
  329. //
  330. // Unlock the shared database
  331. //
  332. MsgDatabaseLock(MSG_RELEASE,"logmbe");
  333. MsgConfigurationLock(MSG_RELEASE,"Msglogmbe");
  334. return(SMB_ERR_SUCCESS); // Message arrived
  335. }
  336. /*
  337. ** Msglogmbt - log a multi-block message text block
  338. **
  339. ** This function is called to log a multi-block message text block.
  340. ** The text block is placed in the message buffer which resides
  341. ** in the shared data area. If there is insufficient room in the
  342. ** buffer, logmbt() removes the header and any previous blocks of
  343. ** the message from the buffer.
  344. **
  345. ** This function gets the current message from the message pointer in
  346. ** the shared data (for that net & name index). It looks in the header
  347. ** to see if there are any text blocks already there. If so, it adds
  348. ** this new one to the list and fixes the last block pointer to point to
  349. ** it.
  350. **
  351. ** logmbt (text, net, ncbi)
  352. **
  353. ** ENTRY
  354. ** text - text header
  355. ** net - Network index
  356. ** ncbi - Network Control Block index
  357. **
  358. ** RETURN
  359. ** zero if successful, non-zero if unable to buffer the message header
  360. **
  361. ** SIDE EFFECTS
  362. **
  363. ** Calls heapalloc() to obtain buffer space. Calls mbmfree() if a call to
  364. ** heapalloc() fails.
  365. **/
  366. DWORD
  367. Msglogmbt(
  368. LPSTR text, // Text of message
  369. DWORD net, // Which network?
  370. DWORD ncbi // Network Control Block index
  371. )
  372. {
  373. DWORD i; // Heap index
  374. DWORD j; // Heap index
  375. DWORD k; // Heap index
  376. USHORT length; // Length of text
  377. //
  378. // Synchronize with Pnp configuration routine
  379. //
  380. MsgConfigurationLock(MSG_GET_SHARED,"Msglogmbt");
  381. // *ALIGNMENT*
  382. length = SmbGetUshort( (PUSHORT)text); // Get length of text block
  383. // length = *((PSHORT) text); // Get length of text block
  384. text += sizeof(short); // Skip over length word
  385. //
  386. // Block until the shared database is free
  387. //
  388. MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logmbt");
  389. i = Msgheapalloc(sizeof(MBT) + length); // Allocate space for block
  390. //
  391. // If buffer space is available
  392. //
  393. if(i != INULL) {
  394. //
  395. // Multi-block message text
  396. //
  397. MBT_CODE(*MBTPTR(i)) = SMB_COM_SEND_TEXT_MB_MESSAGE;
  398. MBT_NEXT(*MBTPTR(i)) = INULL; // Last text block so far
  399. MBT_COUNT(*MBTPTR(i)) = (DWORD)length; // *ALIGNMENT2*
  400. memcpy(CPTR(i + sizeof(MBT)), text, length);
  401. // Copy text into buffer
  402. j = SD_MESPTR(net, ncbi); // Get index to current message
  403. if(MBB_FTEXT(*MBBPTR(j)) != INULL) {
  404. //
  405. // If there is text already, Get pointer to last block and
  406. // add new block
  407. //
  408. k = MBB_BTEXT(*MBBPTR(j)); // Get pointer to last block
  409. MBT_NEXT(*MBTPTR(k)) = i; // Add new block
  410. }
  411. else {
  412. MBB_FTEXT(*MBBPTR(j)) = i; // Else set front pointer
  413. }
  414. MBB_BTEXT(*MBBPTR(j)) = i; // Set back pointer
  415. i = 0; // Success
  416. }
  417. else {
  418. Msgmbmfree(SD_MESPTR(net,ncbi)); // Else deallocate the message
  419. }
  420. //
  421. // Unlock the shared database
  422. //
  423. MsgDatabaseLock(MSG_RELEASE,"logmbt");
  424. MsgConfigurationLock(MSG_RELEASE,"Msglogmbt");
  425. return((int) i); // Return status
  426. }
  427. /*
  428. ** Msglogsbm - log a single-block message
  429. **
  430. ** This function is called to log a single-block message. If
  431. ** logging is enabled, the message is written directly to the
  432. ** logging file or device. If logging is disabled or if the
  433. ** attempt to log the message fails, the message is placed in
  434. ** the message buffer which resides in the shared data area.
  435. **
  436. ** logsbm (from, to, text)
  437. **
  438. ** ENTRY
  439. ** from - sender name
  440. ** to - recipient name
  441. ** text - text of message
  442. **
  443. ** RETURN
  444. ** zero if successful, non-zero if unable to log the message
  445. **
  446. ** SIDE EFFECTS
  447. **
  448. ** Calls hdrprint(), txtprint(), and endprint() to print the message if
  449. ** logging is enabled. Calls heapalloc() to obtain buffer space if
  450. ** the message must be buffered.
  451. **/
  452. DWORD
  453. Msglogsbm(
  454. LPSTR from, // Name of sender
  455. LPSTR to, // Name of recipient
  456. LPSTR text, // Text of message
  457. ULONG SessionId // Session Id
  458. )
  459. {
  460. DWORD i; // Heap index
  461. DWORD error; // Error code
  462. SHORT length; // Length of text
  463. DWORD meslog; // Message logging status
  464. DWORD alert_flag; // Alert buffer allocated flag
  465. DWORD status; // DOS error from mespeint functions
  466. SYSTEMTIME bigtime; // Date and time of message
  467. DWORD bufSize; // Buffer Size
  468. //
  469. // Synchronize with Pnp configuration routine
  470. //
  471. MsgConfigurationLock(MSG_GET_SHARED,"Msglogsbm");
  472. //
  473. // Block until the shared database is free
  474. //
  475. MsgDatabaseLock(MSG_GET_EXCLUSIVE,"logsbm");
  476. //
  477. // First get a buffer for an alert
  478. //
  479. bufSize = sizeof( STD_ALERT) +
  480. ALERT_MAX_DISPLAYED_MSG_SIZE +
  481. (2*TXTMAX) + 2;
  482. alert_buf_ptr = (PSTD_ALERT)LocalAlloc(LMEM_ZEROINIT, bufSize);
  483. if (alert_buf_ptr == NULL) {
  484. MSG_LOG(ERROR,"Msglogsbm:Local Alloc failed\n",0);
  485. alert_flag = 0xffffffff; // No alerting if Alloc failed
  486. }
  487. else {
  488. alert_flag = 0; // File and alerting
  489. alert_len = 0;
  490. }
  491. // *ALIGNMENT*
  492. length = SmbGetUshort( (PUSHORT)text); // Get length of text block
  493. text += sizeof(short); // Skip over length word
  494. error = 0; // Assume no errors
  495. //
  496. // Hack to drop messages sent by pre-Whistler Spoolers. As of
  497. // Whistler, print notifications are done as shell balloon tips
  498. // so don't display print alerts sent from the server as well.
  499. //
  500. // This check is also made in Msgmbmprint to catch multi-block messages.
  501. //
  502. if ((g_lpAlertSuccessMessage
  503. &&
  504. _strnicmp(text, g_lpAlertSuccessMessage, g_dwAlertSuccessLen) == 0)
  505. ||
  506. (g_lpAlertFailureMessage
  507. &&
  508. _strnicmp(text, g_lpAlertFailureMessage, g_dwAlertFailureLen) == 0))
  509. {
  510. MsgDatabaseLock(MSG_RELEASE,"logsbm");
  511. MsgConfigurationLock(MSG_RELEASE,"Msglogsbm");
  512. return 0;
  513. }
  514. GetLocalTime(&bigtime); // Get the time
  515. if (!SD_MESLOG()) // If logging disabled
  516. {
  517. if( alert_flag == 0) // If alert buf is valid
  518. {
  519. if (!Msghdrprint(1,from, to, bigtime,0))
  520. {
  521. if (Msgtxtprint(1, text,length,0))
  522. {
  523. alert_flag = 0xffffffff;
  524. }
  525. }
  526. else
  527. {
  528. alert_flag = 0xffffffff;
  529. }
  530. }
  531. }
  532. meslog = SD_MESLOG(); // Get logging status
  533. i = 0; // No way to fail if not logging
  534. if(error != 0)
  535. {
  536. DbgPrint("meslog.c:logsbm(before ErrorLogWrite): We should never get here\n");
  537. NetpAssert(0);
  538. }
  539. // Now alert and free up alert buffer if it was successfully allocated
  540. if( alert_flag == 0) { // There is an alert buffer
  541. //
  542. // There is an alert buffer, output it.
  543. //
  544. MsgOutputMsg(alert_len, (LPSTR)alert_buf_ptr, SessionId, bigtime);
  545. }
  546. LocalFree(alert_buf_ptr);
  547. //
  548. // Unlock the shared database
  549. //
  550. MsgDatabaseLock(MSG_RELEASE,"logsbm");
  551. MsgConfigurationLock(MSG_RELEASE,"Msglogsbm");
  552. return((int) i); // Return status
  553. }
  554. NET_API_STATUS
  555. MsgOutputMsg (
  556. USHORT AlertLength,
  557. LPSTR AlertBuffer,
  558. ULONG SessionId,
  559. SYSTEMTIME BigTime
  560. )
  561. /*++
  562. Routine Description:
  563. This function translates the alert buffer from an Ansi String to a
  564. Unicode String and outputs the buffer to whereever it is to go.
  565. Currently this just becomes a DbgPrint.
  566. Arguments:
  567. AlertLength - The number of bytes in the AlertBuffer.
  568. AlertBuffer - This is a pointer to the buffer that contains the message
  569. that is to be output. The buffer is expected to contain a
  570. NUL Terminated Ansi String.
  571. BigTime - The SYSTEMTIME that indicates the time the end of the
  572. messsage was received.
  573. Return Value:
  574. --*/
  575. {
  576. UNICODE_STRING unicodeString;
  577. OEM_STRING ansiString;
  578. NTSTATUS ntStatus;
  579. //
  580. // NUL Terminate the message.
  581. // Translate the Ansi message to a Unicode Message.
  582. //
  583. AlertBuffer[AlertLength++] = '\0';
  584. ansiString.Length = AlertLength;
  585. ansiString.MaximumLength = AlertLength;
  586. ansiString.Buffer = AlertBuffer;
  587. ntStatus = RtlOemStringToUnicodeString(
  588. &unicodeString, // Destination
  589. &ansiString, // Source
  590. TRUE); // Allocate the destination.
  591. if (!NT_SUCCESS(ntStatus)) {
  592. MSG_LOG(ERROR,
  593. "MsgOutputMsg:RtlOemStringToUnicodeString Failed rc=%X\n",
  594. ntStatus);
  595. //
  596. // EXPLANATION OF WHY IT RETURNS SUCCESS HERE.
  597. // Returning success even though the alert is not raised is
  598. // consistent with the LM2.0 code which doesn't check the
  599. // return code for the NetAlertRaise API anyway. Returning
  600. // anything else would require a re-design of how errors are
  601. // handled by the caller of this routine.
  602. //
  603. return(NERR_Success);
  604. }
  605. //*******************************************************************
  606. //
  607. // PUT THE MESSAGE IN THE DISPLAY QUEUE
  608. //
  609. MsgDisplayQueueAdd( AlertBuffer, (DWORD)AlertLength, SessionId, BigTime);
  610. //
  611. //
  612. //*******************************************************************
  613. RtlFreeUnicodeString(&unicodeString);
  614. return(NERR_Success);
  615. }