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.

386 lines
9.5 KiB

  1. /*--
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. grpmsngr.c
  5. Abstract:
  6. This file contains the routines that provide support for messaging
  7. in a multi-domaign lan. These routines comprise the group message thread
  8. of the messenger service. The support of domain messaging is broken up
  9. into two phases. The first, which takes place at initialization time of
  10. the messenger, sets up a mailslot thru which the second phase receives the
  11. information that it will need to process. The second, phase, which runs
  12. in parallel with the existing messenger thread, reads messages out of this
  13. mailslot and logs them.
  14. Author:
  15. Dan Lafferty (danl) 17-Jul-1991
  16. Environment:
  17. User Mode -Win32
  18. Notes:
  19. These routines receive and manipulate ansi strings, not UNICODE strings.
  20. The ANSI to UNICODE translation will be done in logsmb().
  21. Revision History:
  22. 17-Jul-1991 danl
  23. ported from LM2.0
  24. --*/
  25. #include "msrv.h"
  26. #include <string.h>
  27. #include <stdio.h>
  28. #include <netlib.h> // UNUSED macro
  29. #include "msgdbg.h" // MSG_LOG
  30. #include "msgdata.h"
  31. //
  32. // GLOBALS
  33. //
  34. LPSTR DieMessage = "DIE";
  35. extern HANDLE g_hGrpEvent;
  36. //
  37. // PROTOTYPES of internal functions
  38. //
  39. STATIC VOID
  40. MsgDisectMessage(
  41. IN LPSTR message,
  42. OUT LPSTR *from,
  43. OUT LPSTR *to,
  44. IN LPSTR text);
  45. //
  46. // Defines
  47. //
  48. //
  49. // Size of mailslot messages (bytes)
  50. //
  51. #define MESSNGR_MS_MSIZE 512
  52. //
  53. // size of mailslot (bytes)
  54. //
  55. #define MESSNGR_MS_SIZE (5*MESSNGR_MS_MSIZE)
  56. static char Msg_Buf[MESSNGR_MS_MSIZE + 3]; // Buffer for messages + 3 NULs
  57. static OVERLAPPED Overlapped;
  58. static DWORD bytes_read = 0;
  59. NET_API_STATUS
  60. MsgInitGroupSupport(DWORD iGrpMailslotWakeupSem)
  61. {
  62. DWORD err = 0; // Error code info from the group processor.
  63. GrpMailslotHandle = CreateMailslotA(
  64. MESSNGR_MS_NAME, // lpName
  65. MESSNGR_MS_MSIZE, // nMaxMessageSize
  66. MAILSLOT_WAIT_FOREVER, // lReadTimeout
  67. NULL); // lpSecurityAttributes
  68. if (GrpMailslotHandle == INVALID_HANDLE_VALUE) {
  69. err = GetLastError();
  70. MSG_LOG(ERROR,"GroupMsgProcessor: CreateMailslot FAILURE %d\n",
  71. err);
  72. }
  73. else {
  74. MSG_LOG1(GROUP,"InitGroupSupport: MailSlotHandle = 0x%lx\n",
  75. GrpMailslotHandle);
  76. }
  77. return err;
  78. }
  79. VOID
  80. MsgReadGroupMailslot(
  81. VOID
  82. )
  83. {
  84. NET_API_STATUS Err = 0;
  85. //
  86. // Clean out receive buffers before each message
  87. //
  88. memset(Msg_Buf, 0, sizeof(Msg_Buf));
  89. memset(&Overlapped, 0, sizeof(Overlapped));
  90. if (!ReadFile(
  91. GrpMailslotHandle,
  92. Msg_Buf,
  93. sizeof(Msg_Buf) - 3, // Leave 3 NULs at the end (see MsgDisectMessage)
  94. &bytes_read,
  95. &Overlapped) )
  96. {
  97. Err = GetLastError();
  98. if (Err == ERROR_INVALID_HANDLE)
  99. {
  100. //
  101. // If this handle is no longer good, it means the
  102. // mailslot system is down. So we can't go on using
  103. // mailslots in the messenger. Therefore, we want to
  104. // log that fact and shutdown this thread.
  105. //
  106. MsgErrorLogWrite(
  107. Err, // Error Code
  108. SERVICE_MESSENGER, // Component
  109. NULL, // Buffer
  110. 0L, // BufferSize
  111. NULL, // Insertion strings
  112. 0); // NumStrings
  113. }
  114. }
  115. return;
  116. }
  117. NET_API_STATUS
  118. MsgServeGroupMailslot()
  119. {
  120. LPSTR from;
  121. LPSTR to;
  122. CHAR text[MAXGRPMSGLEN+3]; // +3 is for length word at
  123. // start of string (for
  124. // logsbm) and for NULL
  125. // terminator at end. NOTE:
  126. // disect_message() below
  127. // makes assumptions about
  128. // the length of this array.
  129. DWORD code;
  130. //
  131. // Process the message
  132. //
  133. if( !GetOverlappedResult( GrpMailslotHandle,
  134. &Overlapped,
  135. &bytes_read,
  136. TRUE ) ) {
  137. MSG_LOG1(ERROR,"MsgServeGroupMailslot: GetOverlappedResult failed %d\n",
  138. GetLastError());
  139. return(GetMsgrState());
  140. }
  141. //
  142. // Check for Shutdown...
  143. //
  144. if ((bytes_read == 4) && (strcmp(Msg_Buf, DieMessage)==0)) {
  145. return(GetMsgrState());
  146. }
  147. MSG_LOG(TRACE,"MailSlot Message Received\n",0);
  148. __try {
  149. MsgDisectMessage( Msg_Buf, &from, &to, text );
  150. if (g_IsTerminalServer)
  151. {
  152. Msglogsbm (from, to, text, (ULONG)EVERYBODY_SESSION_ID);
  153. }
  154. else
  155. {
  156. Msglogsbm (from, to, text, 0);
  157. }
  158. }
  159. __except( EXCEPTION_EXECUTE_HANDLER, code = GetExceptionCode() ) {
  160. MSG_LOG(ERROR,"MsgServerGroupMailslot: Caught exception %d\n",code);
  161. }
  162. return(RUNNING);
  163. }
  164. /* Function: MsgDisectMessage
  165. *
  166. * This function isolates the details of the structure of the message
  167. * that gets sent through the mailslot from the rest of the thread. Given
  168. * the message buffer, this routine fills in the module globals From, To
  169. * and Text with the proper parts of the message.
  170. *
  171. * ENTRY
  172. *
  173. * Expects one argument, which is a pointer to the buffer containing
  174. * the message.
  175. *
  176. * EXIT
  177. *
  178. * This function does not return a value.
  179. *
  180. * SIDE EFFECTS
  181. *
  182. * Modifies the variables from, to and text. The Msg_Buf
  183. * may also be modified.
  184. * Assumes the length of Text is at least MAXGRPMSGLEN+3.
  185. *
  186. */
  187. VOID
  188. MsgDisectMessage(
  189. IN LPSTR message,
  190. OUT LPSTR *from,
  191. OUT LPSTR *to,
  192. IN LPSTR text)
  193. {
  194. LPSTR txt_ptr;
  195. PSHORT size_ptr;
  196. //
  197. // Note that message (a.k.a. Msg_Buf) is always triple-NUL terminated,
  198. // so calling strlen twice and adding 1 will always succeed, even if
  199. // the message isn't properly NUL-terminated (in that case, "from" will
  200. // point to all the text in the buffer and both "to" and "text will
  201. // point to empty strings).
  202. //
  203. *from = message;
  204. *to = (*from) + strlen(*from) +1;
  205. txt_ptr = (*to) + strlen(*to) +1;
  206. text[2] = '\0';
  207. strncpy(text+2, txt_ptr, MAXGRPMSGLEN);
  208. //
  209. // make sure it is NULL terminated
  210. //
  211. text[MAXGRPMSGLEN+2] = '\0';
  212. //
  213. // The first two bytes in the text buffer are to contain the length
  214. // the message. (in bytes).
  215. //
  216. size_ptr = (PSHORT)text;
  217. *size_ptr = (SHORT)strlen(text+2);
  218. }
  219. VOID
  220. MsgGrpThreadShutdown(
  221. VOID
  222. )
  223. /*++
  224. Routine Description:
  225. This routine wakes up the wait on the Group Mailslot handle.
  226. Arguments:
  227. none
  228. Return Value:
  229. none
  230. --*/
  231. {
  232. DWORD i;
  233. DWORD numWritten;
  234. HANDLE mailslotHandle;
  235. // If already stopped, don't bother
  236. if (GrpMailslotHandle == INVALID_HANDLE_VALUE) {
  237. MSG_LOG0(TRACE,"MsgGroupThreadShutdown: Group Thread has completed\n");
  238. return;
  239. }
  240. //
  241. // Wake up the Group Thread by sending "DIE" to its mailbox.
  242. //
  243. MSG_LOG(TRACE,"MsgThreadWakeup:Wake up Group Thread & tell it to DIE\n",0);
  244. mailslotHandle = CreateFileA (
  245. MESSNGR_MS_NAME, // lpFileName
  246. GENERIC_WRITE, // dwDesiredAccess
  247. FILE_SHARE_WRITE | FILE_SHARE_READ, // dwShareMode
  248. NULL, // lpSecurityAttributes
  249. OPEN_EXISTING, // dwCreationDisposition
  250. FILE_ATTRIBUTE_NORMAL, // dwFileAttributes
  251. 0L); // hTemplateFile
  252. if (mailslotHandle == INVALID_HANDLE_VALUE) {
  253. //
  254. // A failure occured. It is assumed that the mailslot hasn't
  255. // been created yet. In which case, the GrpMessageProcessor will
  256. // check the MsgrState directly after it creates the Mailslot and
  257. // will shut down as required.
  258. //
  259. MSG_LOG(TRACE,"MsgThreadWakeup: CreateFile on Mailslot Failed %d\n",
  260. GetLastError());
  261. //
  262. // Deregister the group work item lest the mailslot handle get closed
  263. // while the thread pool is still waiting on it when this function returns
  264. //
  265. DEREGISTER_WORK_ITEM(g_hGrpEvent);
  266. return;
  267. }
  268. MSG_LOG(TRACE,"MsgGroupThreadShutdown: MailSlotHandle = 0x%lx\n",mailslotHandle);
  269. if ( !WriteFile (
  270. mailslotHandle,
  271. DieMessage,
  272. strlen(DieMessage)+1,
  273. &numWritten,
  274. NULL)) {
  275. MSG_LOG(TRACE,"MsgThreadWakeup: WriteFile on Mailslot Failed %d\n",
  276. GetLastError())
  277. //
  278. // Since we can't wake up the group thread,
  279. // deregister the work item here instead
  280. //
  281. DEREGISTER_WORK_ITEM(g_hGrpEvent);
  282. }
  283. CloseHandle(mailslotHandle);
  284. //
  285. // Wait for the group messenger to be shutdown.
  286. // We will wait up to 20.300 seconds for this before going on.
  287. //
  288. Sleep(300);
  289. for (i=0; i<20; i++) {
  290. if (GrpMailslotHandle == INVALID_HANDLE_VALUE) {
  291. MSG_LOG0(TRACE,"MsgGroupThreadShutdown: Group Thread has completed\n");
  292. break;
  293. }
  294. MSG_LOG1(TRACE,"MsgGroupThreadShutdown: Group Thread alive after %d seconds\n",
  295. (i + 1) * 1000);
  296. Sleep(1000);
  297. }
  298. return;
  299. }