Source code of Windows XP (NT5)
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.

644 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 ((g_lpAlertSuccessMessage
  339. &&
  340. _strnicmp(&CPTR(text)[sizeof(MBT)], g_lpAlertSuccessMessage, g_dwAlertSuccessLen) == 0)
  341. ||
  342. (g_lpAlertFailureMessage
  343. &&
  344. _strnicmp(&CPTR(text)[sizeof(MBT)], g_lpAlertFailureMessage, g_dwAlertFailureLen) == 0))
  345. {
  346. //
  347. // Tell the caller not to output this message
  348. //
  349. *pdwAlertFlag = 0xffffffff;
  350. return NO_ERROR;
  351. }
  352. if ((status = Msghdrprint(
  353. action,
  354. from,
  355. to,
  356. MBB_BIGTIME(*MBBPTR(mesi)),
  357. file_handle)) != 0)
  358. {
  359. return status; // Fail if error on header write
  360. }
  361. //
  362. // The following loop prints out each text block in the chain.
  363. //
  364. while(text != INULL) { // While not at end of chain
  365. if((status = Msgtxtprint(
  366. action,
  367. &CPTR(text)[sizeof(MBT)],
  368. MBT_COUNT(*MBTPTR(text)), // *ALIGNMENT2*
  369. file_handle)) != 0) {
  370. break; // If write error
  371. }
  372. text = MBT_NEXT(*MBTPTR(text)); // Get link to next block
  373. }
  374. return status;
  375. }
  376. /*
  377. ** Msgtxtprint - print text of message
  378. **
  379. ** This function prints a block of text.
  380. **
  381. ** txtprint ( action, text, length, file_handle)
  382. **
  383. ** ENTRY
  384. ** action : 0 = alert and file
  385. ** -1 = file only
  386. ** 1 = alert only
  387. ** text - pointer to text
  388. ** length - length of text
  389. ** file_handle - log file handle
  390. **
  391. ** RETURN
  392. ** 0 - Success, else file system error
  393. **
  394. ** This function prints the given amount of text. The text pointer is
  395. ** a far pointer so that text blocks in the shared data area do not have
  396. ** to be copied into the automatic data segment in order to process
  397. ** them.
  398. **
  399. ** SIDE EFFECTS
  400. **
  401. ** Converts the character '\024' to the sequence '\015', '\012' on output.
  402. **/
  403. DWORD
  404. Msgtxtprint(
  405. int action, // Alert, File, or Alert and file
  406. LPSTR text, // Pointer to text
  407. DWORD length, // Length of text
  408. HANDLE file_handle // Log file handle
  409. )
  410. {
  411. LPSTR buffer; // Text buffer
  412. LPSTR cp; // Character pointer
  413. DWORD i; // Counter
  414. DWORD status = 0; // error return
  415. // [wlees 3/6/98] This code path is used by larger messages than just single
  416. // block messages, so size the buffer dynamically.
  417. // Double space to be paranoid for eol expansion
  418. if (length == 0)
  419. {
  420. return 1;
  421. }
  422. //
  423. // Add 1 to prevent a message of all linefeed characters
  424. // from causing a buffer overrun when we add the '\0'
  425. //
  426. buffer = LocalAlloc( LMEM_FIXED, 2 * length + 1);
  427. if (buffer == NULL)
  428. {
  429. return 1;
  430. }
  431. cp = buffer; // Initialize
  432. //
  433. // Loop to translate text
  434. //
  435. for(i = length; i != 0; --i)
  436. {
  437. if(*text == '\024')
  438. {
  439. //
  440. // If IBM end-of-line character
  441. //
  442. ++length; // Length has increased
  443. *cp++ = '\r'; // Carriage return
  444. *cp++ = '\n'; // Linefeed
  445. }
  446. else
  447. {
  448. //
  449. // Else copy character as is
  450. //
  451. *cp++ = *text;
  452. }
  453. ++text; // Increment pointer
  454. }
  455. *cp = '\0'; // So can use log_write
  456. if( action >= 0)
  457. {
  458. //
  459. // if alert and file or alert only
  460. //
  461. if( alert_len < ALERT_MAX_DISPLAYED_MSG_SIZE + 1)
  462. {
  463. memcpy( &alert_buf_ptr[alert_len], buffer, strlen(buffer));
  464. alert_len += (USHORT)strlen(buffer);
  465. }
  466. }
  467. if( action < 1)
  468. {
  469. //
  470. // if file and alert or file only, write text to log file
  471. //
  472. status = Msglog_write(buffer,file_handle);
  473. }
  474. LocalFree( buffer );
  475. return status; // Cannot fail on alert only
  476. }
  477. /*
  478. ** Msgopen_append - opens the requested file for read/write and seeks to the
  479. ** end of the file.
  480. **
  481. ** open_append - ( file_name, file_handle_ptr)
  482. **
  483. ** ENTRY
  484. ** file_name - pointer to file_name
  485. ** file_handle_ptr - pointer to unsigned short to store file pointer
  486. **
  487. ** RETURN
  488. ** 0 - Success, else file system error
  489. **
  490. ** SIDE EFFECTS
  491. **
  492. **/
  493. DWORD
  494. Msgopen_append(
  495. LPSTR file_name, // Name of file to open
  496. PHANDLE file_handle_ptr // pointer to storage for file handle
  497. )
  498. {
  499. NetpAssert(0);
  500. UNUSED (file_name);
  501. UNUSED (file_handle_ptr);
  502. return(0);
  503. }
  504. /*
  505. ** Msglog_write - writes a text string to the log file..
  506. **
  507. ** log_write - ( text, file_handle)
  508. **
  509. ** ENTRY
  510. ** text - text string to write to file.
  511. ** file_handle - log file handle
  512. **
  513. ** RETURN
  514. ** 0 - Success, else file system error
  515. **
  516. ** SIDE EFFECTS
  517. **
  518. **/
  519. DWORD
  520. Msglog_write(
  521. LPSTR text, // String to write to log file*/
  522. HANDLE file_handle // log file handle
  523. )
  524. {
  525. NetpAssert(0);
  526. UNUSED (text);
  527. UNUSED (file_handle);
  528. return(0);
  529. }