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.

613 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. mesprint.c
  5. Abstract:
  6. Routines that format messages and place them in the alert buffer.
  7. Author:
  8. Dan Lafferty (danl) 16-Jul-1991
  9. Environment:
  10. User Mode -Win32
  11. Revision History:
  12. 16-Jul-1991 danl
  13. ported from LM2.0
  14. --*/
  15. //
  16. // Includes
  17. //
  18. #include "msrv.h"
  19. #include <string.h> // memcpy
  20. #include <tstring.h> // Unicode string macros
  21. #include <netdebug.h> // NetpAssert
  22. #include <netlib.h> // UNUSED macro
  23. #include <smbtypes.h> // needed for smb.h
  24. #include <smb.h> // Server Message Block definitions
  25. #include <apperr.h> // APE_MSNGR_ definitions
  26. #include "msgdbg.h" // MSG_LOG
  27. #include "heap.h"
  28. #include "msgdata.h"
  29. #include <time.h> // struct tm, time_t
  30. //
  31. // Local Functions
  32. //
  33. DWORD
  34. Msgappend_message(
  35. IN USHORT msgno,
  36. IN LPSTR buf,
  37. IN LPSTR *strarr,
  38. IN USHORT nstrings
  39. );
  40. DWORD
  41. Msglog_write(
  42. LPSTR text,
  43. HANDLE file_handle
  44. );
  45. //
  46. // Global alert buffer data areas. Not used when called from API
  47. //
  48. LPSTR alert_buf_ptr; // Pointer to DosAlloc'ed alert buffer
  49. USHORT alert_len; // Currently used length of alert buffer
  50. extern LPTSTR MessageFileName;
  51. /*
  52. ** append_message --
  53. **
  54. ** Gets a message from the message file, and appends it to the
  55. ** given string buffer.
  56. ** The message file used is the one named in the Global MessageFileName,
  57. ** and thus in the Messenger we assume that SetUpMessageFile is called
  58. ** before this to properly fill in this variable.
  59. **
  60. ** NOTE: This function deals only with Ansi Strings - Not Unicode Strings.
  61. ** The Unicode translation is done all at once just before the alert
  62. ** is raised.
  63. **
  64. **/
  65. DWORD
  66. Msgappend_message(
  67. IN USHORT msgno,
  68. IN LPSTR buf,
  69. IN LPSTR *strarr,
  70. IN USHORT nstrings
  71. )
  72. {
  73. WORD msglen=0;
  74. DWORD result;
  75. LPSTR mymsgbuf = 0;
  76. LPSTR msgfile = 0;
  77. LPSTR pmb;
  78. //
  79. // get a segment to read the message into
  80. //
  81. result = 0;
  82. mymsgbuf = LocalAlloc(LMEM_ZEROINIT,(int)max(MAXHEAD+1, MAXEND+1));
  83. if (mymsgbuf == NULL) {
  84. result = GetLastError();
  85. MSG_LOG(ERROR,"append_message:LocalAlloc failed %X\n",result);
  86. return (result);
  87. }
  88. //
  89. // Need to fix DosGetMessage to only take ansi strings.
  90. //
  91. if (result == 0)
  92. {
  93. result = DosGetMessage(
  94. strarr, // String substitution table
  95. nstrings, // Num Entries in table above
  96. mymsgbuf, // Buffer receiving message
  97. (WORD)max(MAXHEAD, MAXEND), // size of buffer receiving msg
  98. msgno, // message num to retrieve
  99. MessageFileName, // Name of message file
  100. &msglen); // Num bytes returned
  101. #ifdef later // Currently there is no backup name
  102. if ( result != 0) {
  103. //
  104. // if the attempt to get the message out of the message file fails,
  105. // get it out of the messages that were bound in to our exe at
  106. // build time. These are the same, but are from bak.msg. The
  107. // Backup message file is never really there, but the messages
  108. // needed from it are bound in to the exe, so we will get them.
  109. //
  110. result = DosGetMessage(
  111. strarr,
  112. nstrings,
  113. mymsgbuf,
  114. (int)max(MAXHEAD, MAXEND),
  115. msgno,
  116. BACKUP_MSG_FILENAME,
  117. (unsigned far *) &msglen);
  118. }
  119. #endif
  120. }
  121. //
  122. // if there is still an error we are in big trouble. Return whatever
  123. // dosgetmessage put into the buffer for us. It is supposed to be
  124. // printable.
  125. //
  126. if ( result != 0 ) {
  127. LocalFree (mymsgbuf);
  128. return (result);
  129. }
  130. mymsgbuf[msglen] = 0;
  131. #ifdef removeForNow
  132. //
  133. // NOTE: The following logic is skipped because DosGetMessage doesn't
  134. // seem to return any NETxxxx field.
  135. //
  136. // now get rid of the NETxxxx: from the beginning (9 chars)
  137. //
  138. pmb = strchrf(mymsgbuf,' '); // find first space
  139. if ( pmb == NULL ) {
  140. pmb = mymsgbuf; // Just so strcatf doesn't GP Fault.
  141. }
  142. else {
  143. pmb++; // start with next char
  144. }
  145. strcatf(buf,pmb); // copy over the buffer
  146. #else
  147. UNUSED(pmb);
  148. strcpy(buf,mymsgbuf); // copy over the buffer
  149. #endif
  150. LocalFree (mymsgbuf);
  151. return (result);
  152. }
  153. /*
  154. ** Msghdrprint - print a message header
  155. **
  156. ** This function prints a message header using the time and
  157. ** date format appropriate for the current country.
  158. **
  159. ** hdrprint (action, from, to, date, time, file_handle)
  160. **
  161. ** ENTRY
  162. ** action : 0 = alert and file
  163. ** -1 = file only
  164. ** 1 = alert only
  165. ** from - name of sender
  166. ** to - name of intended recipient
  167. ** bigtime - bigtime of message
  168. ** file_handle - log file handle
  169. **
  170. ** RETURN
  171. ** 0 - Success, else file system error
  172. **
  173. ** This function prints the given information in the appropriate
  174. ** format. The names are passed as far pointers so that names in
  175. ** the shared data area do not have to be copied into the automatic
  176. ** data segment in order to print them.
  177. **
  178. ** SIDE EFFECTS
  179. **
  180. ** Calls the DOS to get country-dependent information.
  181. **/
  182. #define SINGLE_SPACE "\n\r"
  183. #define SINGLE_SPACE_LEN (sizeof("\n\r") - 1)
  184. DWORD
  185. Msghdrprint(
  186. int action, // Where to log the header to.
  187. LPSTR from, // Name of sender
  188. LPSTR to, // Name of recipient
  189. SYSTEMTIME bigtime, // Bigtime of message
  190. HANDLE file_handle // Output file handle
  191. )
  192. {
  193. //
  194. // hdr_buf didn't account for the extra line feed, carriage ret.
  195. //
  196. char hdr_buf[MAXHEAD + SINGLE_SPACE_LEN + 1]; // Buffer header text
  197. char time_buf[TIME_BUF_SIZE];
  198. DWORD status; // file write status
  199. DWORD i=0; // Index into header_buf
  200. LPSTR str_table[3]; // For DosGetMessage
  201. *(hdr_buf + MAXHEAD) = '\0'; // for strlen
  202. hdr_buf[0] = '\0';
  203. str_table[0] = from;
  204. str_table[1] = to;
  205. //******************************
  206. //
  207. // Because we queue messages, and a user my not be logged on when the
  208. // message is queued. We want to instead, put a place-holder in the
  209. // message buffer for the time. Later, when we read from the queue, we
  210. // will add the time string formatted for the logged on user.
  211. //
  212. strcpy (time_buf, GlobalTimePlaceHolder);
  213. //******************************
  214. str_table[2] = time_buf;
  215. // Try to get the message from the message file or from the backup
  216. // in memory. This will always leave something in the hdr_buf that
  217. // is printable, if not correct.
  218. //
  219. // 11-13-96 : It is not sufficient to ignore the Msgappend_message return
  220. // code and plod onward. If Msgappend_message fails, there
  221. // may be simply "\r\n" left in hdr_buf. Printable, yes, but
  222. // it will cause an A/V later. Check the return code and bail
  223. // if this call fails.
  224. //
  225. status = Msgappend_message(APE_MSNGR_HDR, hdr_buf, str_table, 3);
  226. if (status) {
  227. return(status);
  228. }
  229. strcat( hdr_buf,"\r\n");
  230. status = 0; // assume success
  231. if( action >= 0 ) {
  232. //
  233. // If alert and file or alert only,
  234. // then copy hdr_buf to alert buffer.
  235. //
  236. memcpy( &(alert_buf_ptr[alert_len]),
  237. hdr_buf,
  238. i = strlen(hdr_buf));
  239. alert_len += (USHORT)i;
  240. }
  241. if( action < 1) {
  242. DbgPrint("mesprint.c:hdrprint:We should never get here\n");
  243. NetpAssert(0);
  244. //
  245. // if file and alert or file only, attempt to write
  246. // header to log file.
  247. //
  248. status = Msglog_write(hdr_buf, file_handle);
  249. }
  250. return(status);
  251. }
  252. /*
  253. ** Msgmbmfree - deallocate the pieces of a multi-block message
  254. **
  255. ** Given an index to the header of a multi-block message, this function
  256. ** deallocates the header block and all of the text blocks.
  257. **
  258. ** mbmfree (mesi)
  259. **
  260. ** ENTRY
  261. ** mesi - index into the message buffer
  262. **
  263. ** RETURN
  264. ** nothing
  265. **
  266. ** This function deallocates a multi-block message piece by piece.
  267. **
  268. ** SIDE EFFECTS
  269. **
  270. ** Calls heapfree() to deallocate each piece.
  271. **/
  272. VOID
  273. Msgmbmfree(
  274. DWORD mesi // Message index
  275. )
  276. {
  277. DWORD text; // Index to text
  278. text = MBB_FTEXT(*MBBPTR(mesi)); // Get the index to the text
  279. Msgheapfree(mesi); // Deallocate the message header
  280. //
  281. // The following loop deallocates each text block in the chain.
  282. //
  283. while(text != INULL) { // While not at end of chain
  284. mesi = text; // Save index
  285. text = MBT_NEXT(*MBTPTR(text)); // Get link to next block
  286. Msgheapfree(mesi); // Free this block
  287. }
  288. }
  289. /*
  290. ** Msgmbmprint - print a multi-block message
  291. **
  292. ** This function writes a multi-block message to the log file.
  293. **
  294. ** mbmprint (action, mesi, file_handle)
  295. **
  296. ** ENTRY
  297. ** action : 0 = alert and file
  298. ** -1 = file only
  299. ** 1 = alert only
  300. ** mesi - index into the message buffer
  301. ** file_handle - log file handle
  302. **
  303. ** RETURN
  304. ** 0 - Success, else file system error
  305. **
  306. ** This function writes the message starting at the mesi'th byte in the
  307. ** message buffer (in the shared data area) to the log file. It returns
  308. ** the value EOF if the writing of the message fails.
  309. **
  310. ** SIDE EFFECTS
  311. **
  312. ** Calls hdrprint(), txtprint(), and endprint().
  313. **/
  314. DWORD
  315. Msgmbmprint(
  316. int action, // Alert, File, or Alert and file
  317. DWORD mesi, // Message index
  318. HANDLE file_handle, // Log file handle
  319. LPDWORD pdwAlertFlag
  320. )
  321. {
  322. LPSTR from; // Sender
  323. LPSTR to; // Recipient
  324. DWORD text; // Index to text
  325. DWORD state; // Final state of message
  326. DWORD status; // File write status
  327. from = &CPTR(mesi)[sizeof(MBB)]; // Get pointer to sender name
  328. to = &from[strlen(from) + 1]; // Get pointer to recipient name
  329. state = MBB_STATE(*MBBPTR(mesi)); // Save the state
  330. text = MBB_FTEXT(*MBBPTR(mesi)); // Get the index to the text
  331. //
  332. // Hack to drop messages sent by pre-Whistler Spoolers. As of
  333. // Whistler, print notifications are done as shell balloon tips
  334. // so don't display print alerts sent from the server as well.
  335. //
  336. // This same check is done in Msglogsbm for single-block messages.
  337. //
  338. if (text != INULL)
  339. {
  340. if ((g_lpAlertSuccessMessage
  341. &&
  342. _strnicmp(&CPTR(text)[sizeof(MBT)], g_lpAlertSuccessMessage, g_dwAlertSuccessLen) == 0)
  343. ||
  344. (g_lpAlertFailureMessage
  345. &&
  346. _strnicmp(&CPTR(text)[sizeof(MBT)], g_lpAlertFailureMessage, g_dwAlertFailureLen) == 0))
  347. {
  348. //
  349. // Tell the caller not to output this message
  350. //
  351. *pdwAlertFlag = 0xffffffff;
  352. return NO_ERROR;
  353. }
  354. }
  355. if ((status = Msghdrprint(
  356. action,
  357. from,
  358. to,
  359. MBB_BIGTIME(*MBBPTR(mesi)),
  360. file_handle)) != 0)
  361. {
  362. return status; // Fail if error on header write
  363. }
  364. //
  365. // The following loop prints out each text block in the chain.
  366. //
  367. while (text != INULL) // While not at end of chain
  368. {
  369. if ((status = Msgtxtprint(action,
  370. &CPTR(text)[sizeof(MBT)],
  371. MBT_COUNT(*MBTPTR(text)), // *ALIGNMENT2*
  372. file_handle)) != 0)
  373. {
  374. break; // If write error
  375. }
  376. text = MBT_NEXT(*MBTPTR(text)); // Get link to next block
  377. }
  378. return status;
  379. }
  380. /*
  381. ** Msgtxtprint - print text of message
  382. **
  383. ** This function prints a block of text.
  384. **
  385. ** txtprint ( action, text, length, file_handle)
  386. **
  387. ** ENTRY
  388. ** action : 0 = alert and file
  389. ** -1 = file only
  390. ** 1 = alert only
  391. ** text - pointer to text
  392. ** length - length of text
  393. ** file_handle - log file handle
  394. **
  395. ** RETURN
  396. ** 0 - Success, else file system error
  397. **
  398. ** This function prints the given amount of text. The text pointer is
  399. ** a far pointer so that text blocks in the shared data area do not have
  400. ** to be copied into the automatic data segment in order to process
  401. ** them.
  402. **
  403. ** SIDE EFFECTS
  404. **
  405. ** Converts the character '\024' to the sequence '\015', '\012' on output.
  406. **/
  407. DWORD
  408. Msgtxtprint(
  409. int action, // Alert, File, or Alert and file
  410. LPSTR text, // Pointer to text
  411. DWORD length, // Length of text
  412. HANDLE file_handle // Log file handle
  413. )
  414. {
  415. LPSTR buffer; // Text buffer
  416. LPSTR cp; // Character pointer
  417. DWORD i; // Counter
  418. DWORD status = 0; // error return
  419. // [wlees 3/6/98] This code path is used by larger messages than just single
  420. // block messages, so size the buffer dynamically.
  421. // Double space to be paranoid for eol expansion
  422. if (length == 0)
  423. {
  424. return 1;
  425. }
  426. //
  427. // Add 1 to prevent a message of all linefeed characters
  428. // from causing a buffer overrun when we add the '\0'
  429. //
  430. buffer = LocalAlloc( LMEM_FIXED, 2 * length + 1);
  431. if (buffer == NULL)
  432. {
  433. return 1;
  434. }
  435. cp = buffer; // Initialize
  436. //
  437. // Loop to translate text
  438. //
  439. for(i = length; i != 0; --i)
  440. {
  441. if(*text == '\024')
  442. {
  443. //
  444. // If IBM end-of-line character
  445. //
  446. ++length; // Length has increased
  447. *cp++ = '\r'; // Carriage return
  448. *cp++ = '\n'; // Linefeed
  449. }
  450. else
  451. {
  452. //
  453. // Else copy character as is
  454. //
  455. *cp++ = *text;
  456. }
  457. ++text; // Increment pointer
  458. }
  459. *cp = '\0'; // So can use log_write
  460. if( action >= 0)
  461. {
  462. //
  463. // if alert and file or alert only
  464. //
  465. if( alert_len < ALERT_MAX_DISPLAYED_MSG_SIZE + 1)
  466. {
  467. memcpy( &alert_buf_ptr[alert_len], buffer, strlen(buffer));
  468. alert_len += (USHORT)strlen(buffer);
  469. }
  470. }
  471. if( action < 1)
  472. {
  473. //
  474. // if file and alert or file only, write text to log file
  475. //
  476. status = Msglog_write(buffer,file_handle);
  477. }
  478. LocalFree( buffer );
  479. return status; // Cannot fail on alert only
  480. }
  481. /*
  482. ** Msglog_write - writes a text string to the log file..
  483. **
  484. ** log_write - ( text, file_handle)
  485. **
  486. ** ENTRY
  487. ** text - text string to write to file.
  488. ** file_handle - log file handle
  489. **
  490. ** RETURN
  491. ** 0 - Success, else file system error
  492. **
  493. ** SIDE EFFECTS
  494. **
  495. **/
  496. DWORD
  497. Msglog_write(
  498. LPSTR text, // String to write to log file*/
  499. HANDLE file_handle // log file handle
  500. )
  501. {
  502. NetpAssert(0);
  503. UNUSED (text);
  504. UNUSED (file_handle);
  505. return(0);
  506. }