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.

1613 lines
41 KiB

  1. /*++
  2. Copyright (c) 1991-92 Microsoft Corporation
  3. Module Name:
  4. msginit.c
  5. Abstract:
  6. Messenger Service Initialization Routines.
  7. The following is a list of functions in this file:
  8. MsgInitializeMsgr
  9. BufferInit
  10. InitSharedData
  11. SetComputerName
  12. GetNumNets
  13. MsgGetBufSize
  14. SetUpMessageFile
  15. Author:
  16. Dan Lafferty (danl) 18-Jul-1991
  17. Environment:
  18. User Mode - Win32
  19. Notes:
  20. optional-notes
  21. Revision History:
  22. 19-Aug-1997 wlees
  23. PNP support. Retry if lana's not present yet.
  24. 27-Jun-1995 AnirudhS
  25. LocalFree(dataPtr) must be called AFTER MsgFreeSupportSeg, because
  26. the latter tries to _close a handle stored in dataPtr.
  27. 08-Feb-1994 Danl
  28. Removed the restriction that the memory allocated had to be
  29. restricted to less than a 64K segment. We don't worry about
  30. segments anymore.
  31. 12-Jan-1993 Danl
  32. In error paths where we call MsgCloseWakeupSems, I need to do the
  33. LocalFree(dataPtr) after the call to MsgCloseWakeupSems. Otherwise,
  34. it access violates because MsgCloseWakeupSems uses the shared date
  35. in the block pointed to by the dataPtr.
  36. 21-Apr-1992 JohnRo
  37. Fixed bug printing a status when message name add fails.
  38. Changed to use FORMAT_ equates throughout.
  39. 18-Feb-1992 ritaw
  40. Convert to Win32 service control APIs.
  41. 18-Jul-1991 danl
  42. Created as a composite of the original LM2,0 routines.
  43. --*/
  44. //
  45. // Includes
  46. //
  47. #include <stdlib.h> // atol
  48. #include "msrv.h" // Messenger prototypes and constants
  49. #include <winsvc.h> // Service control APIs
  50. #include <winsock2.h> // Windows sockets
  51. #include <netdebug.h> // NetpAssert, FORMAT_ equates.
  52. #include <rpc.h> // DataTypes and runtime APIs
  53. #include <msgsvc.h> // generated by the MIDL complier
  54. #include <netlibnt.h> // NetpNtStatusToApiStatus prototypes
  55. #include <tstring.h> // Unicode string macros
  56. #include <string.h> // memcpy
  57. #include <lmwksta.h> // NetWrkstaTransportEnum
  58. #include <lmapibuf.h> // NetApiBufferFree
  59. #include <netlib.h> // UNUSED macro
  60. #include <msgrutil.h> // NetpNetBiosReset
  61. #include <apperr2.h> // APE2_ALERTER_PRINTING_SUCCESS
  62. #include "msgdbg.h" // MSG_LOG
  63. #include "heap.h" // heap management routines and macros.
  64. #include "msgdata.h" // Global data
  65. #include "msgsec.h" // Messenger security information
  66. #include "msgnames.h" // MSGR_INTERFACE_NAME
  67. #include "msgtext.h" // MTXT_MsgsvcTitle
  68. #include "msgsvcsend.h" // Broadcast message send interface
  69. #include "apiutil.h" // for MsgAddSessionInList
  70. // The per net data and heap buffer are allocated once. Later on we may
  71. // wish to keep them separate.
  72. #define BOOKKEEPING_SIZE(n) (n * sizeof(NET_DATA))
  73. //
  74. // Global Data
  75. //
  76. static DWORD bufferSize; // Message buffer size
  77. static DWORD msrv_pid; // pid of message server
  78. extern LPTSTR MessageFileName;
  79. //
  80. // Local Function Prototypes
  81. //
  82. VOID
  83. MsgBufferInit(
  84. IN DWORD dwBufLen
  85. );
  86. NET_API_STATUS
  87. MsgInitSharedData(
  88. DWORD NumNets
  89. );
  90. NET_API_STATUS
  91. MsgSetComputerName(
  92. DWORD NumNets
  93. );
  94. DWORD
  95. MsgGetNumNets(VOID);
  96. NET_API_STATUS
  97. MsgGetBufSize (
  98. OUT LPDWORD bufferSize
  99. );
  100. DWORD
  101. MsgSetUpMessageFile(VOID);
  102. STATIC VOID
  103. MsgInitMessageBoxTitle(
  104. VOID
  105. );
  106. NET_API_STATUS
  107. MsgrInitializeMsgrInternal1(
  108. void
  109. );
  110. NET_API_STATUS
  111. MsgrInitializeMsgrInternal2(
  112. void
  113. );
  114. VOID
  115. MsgInitEndpoint(
  116. PVOID Context // This passed in as context
  117. );
  118. NET_API_STATUS
  119. MsgInitializeMsgr(
  120. IN DWORD argc,
  121. IN LPTSTR *argv
  122. )
  123. /*++
  124. Routine Description:
  125. Registers the control handler with the dispatcher thread. Then it
  126. performs all initialization including the starting of the RPC server.
  127. If any of the initialization fails, MsgStatusUpdate is called so that the
  128. status is updated and the thread is terminated.
  129. Arguments:
  130. Return Value:
  131. --*/
  132. {
  133. NET_API_STATUS status;
  134. DWORD msgrState;
  135. DWORD bufLen;
  136. WSADATA wsaData;
  137. NTSTATUS ntStatus;
  138. //
  139. // Initialize the Thread Manager. This initializes some locks used
  140. // on the Thread and Status databases.
  141. //
  142. status = MsgThreadManagerInit();
  143. if (status != NO_ERROR)
  144. {
  145. MSG_LOG1(ERROR,
  146. "MsgInitializeMsgr: Thread manager init failed %d\n",
  147. status);
  148. return MsgBeginForcedShutdown(IMMEDIATE, status);
  149. }
  150. //
  151. // Initialize the status structure
  152. //
  153. MsgStatusInit();
  154. //
  155. // Register this service with the ControlHandler.
  156. // Now we can accept control requests and be requested to UNINSTALL.
  157. //
  158. MSG_LOG(TRACE, "Calling RegisterServiceCtrlHandlerEx\n",0);
  159. if ((MsgrStatusHandle = RegisterServiceCtrlHandlerEx(
  160. SERVICE_MESSENGER,
  161. MsgrCtrlHandler,
  162. NULL
  163. )) == (SERVICE_STATUS_HANDLE) NULL) {
  164. status = GetLastError();
  165. MSG_LOG(ERROR,
  166. "FAILURE: RegisterServiceCtrlHandlerEx status = " FORMAT_API_STATUS
  167. "\n", status);
  168. return( MsgBeginForcedShutdown (
  169. IMMEDIATE,
  170. status));
  171. }
  172. //
  173. // Notify that installation is pending
  174. //
  175. msgrState = MsgStatusUpdate(STARTING);
  176. if (msgrState != STARTING) {
  177. //
  178. // An UNINSTALL control request must have been received
  179. //
  180. return(msgrState);
  181. }
  182. //
  183. // Init the _HYDRA_ WinStation message support
  184. //
  185. status = MultiUserInitMessage();
  186. if (status != NERR_Success)
  187. {
  188. MSG_LOG(ERROR, "MultiUser Initialization Failed " FORMAT_RPC_STATUS "\n",
  189. status);
  190. return (MsgBeginForcedShutdown(
  191. IMMEDIATE,
  192. status));
  193. }
  194. //
  195. // Check that the workstation is started
  196. //
  197. MSG_LOG(TRACE, "Calling NetServiceControl\n",0);
  198. if (! NetpIsServiceStarted(SERVICE_WORKSTATION)) {
  199. MSG_LOG(ERROR, "WorkStation Service is not started\n",0);
  200. return (MsgBeginForcedShutdown(
  201. IMMEDIATE,
  202. NERR_WkstaNotStarted));
  203. }
  204. // *** INSTALLATION HINT ***
  205. msgrState = MsgStatusUpdate(STARTING);
  206. if (msgrState != STARTING) {
  207. return(msgrState);
  208. }
  209. //
  210. // Get the default buffer size.
  211. //
  212. status = MsgGetBufSize(&bufferSize);
  213. if (status != NERR_Success)
  214. {
  215. MSG_LOG(ERROR, "MsgGetBufSize Failed\n",0);
  216. return (MsgBeginForcedShutdown(
  217. IMMEDIATE,
  218. status));
  219. }
  220. // *** INSTALLATION HINT ***
  221. msgrState = MsgStatusUpdate(STARTING);
  222. if (msgrState != STARTING) {
  223. return(msgrState);
  224. }
  225. if (bufferSize > MAX_SIZMESSBUF || bufferSize < MIN_SIZMESSBUF) {
  226. MSG_LOG(ERROR, "Message Buffer Size is illegal\n",0);
  227. return (MsgBeginForcedShutdown(
  228. IMMEDIATE,
  229. ERROR_INVALID_PARAMETER));
  230. }
  231. //
  232. // This is the size of the buffer (that SDBUFFER points to) in the
  233. // shared data area. This is calculated as:
  234. //
  235. // The size of a message buffer (bufferSize)
  236. // plus
  237. // space for 4 Multi-block message headers and names,
  238. // plus
  239. // space for one Multi-block text header for each text block that
  240. // fits into the message buffer. (bufferSize/TXTMAX).
  241. //
  242. // The number of headers is rounded up by one.
  243. // (bufferSize+TXTMAX-1)/TXTMAX
  244. //
  245. bufferSize += (4 * (sizeof(MBB) + (2 * NCBNAMSZ))) +
  246. ((( (bufferSize+TXTMAX-1)/TXTMAX) + 1) * sizeof(MBT));
  247. // ***** INSTALLATION HINT *****
  248. msgrState = MsgStatusUpdate(STARTING);
  249. if (msgrState != STARTING) {
  250. return(msgrState);
  251. }
  252. //
  253. // Ask the Worksta for the computer name. If the computer
  254. // has no name, then abort.
  255. //
  256. // The computername and the username are in unicode format.
  257. //
  258. // NOTE: the username that is returned is a name we may want to add
  259. // to the table.
  260. //
  261. MSG_LOG(TRACE, "Getting the ComputerName\n",0);
  262. bufLen = sizeof(machineName);
  263. *machineName = TEXT('\0');
  264. if (!GetComputerName(machineName,&bufLen)) {
  265. MSG_LOG(ERROR,"GetComputerName failed \n",0);
  266. status = GetLastError();
  267. }
  268. if ( (status != NERR_Success) ||
  269. (*machineName == TEXT('\0')) || (*machineName == TEXT(' ')))
  270. {
  271. //
  272. // fatal error if no name
  273. //
  274. MSG_LOG(ERROR, "GetWkstaNames Failed\n",0);
  275. return (MsgBeginForcedShutdown(
  276. IMMEDIATE,
  277. NERR_NoComputerName));
  278. }
  279. machineName[NCBNAMSZ] = TEXT('\0'); // make sure it's terminated
  280. MachineNameLen = (SHORT) STRLEN(machineName);
  281. // ***** INSTALLATION HINT *****
  282. msgrState = MsgStatusUpdate(STARTING);
  283. if (msgrState != STARTING)
  284. {
  285. return(msgrState);
  286. }
  287. //
  288. // Initialize the configuration lock. This lock covers the allocation and deallocation
  289. // of the data structures related to lan adapters.
  290. //
  291. if (MsgConfigurationLock(MSG_INITIALIZE,"MsgInitializeMsgr"))
  292. {
  293. //
  294. // Do first phase of lan adapter related configuration
  295. //
  296. status = MsgrInitializeMsgrInternal1();
  297. if (status != NERR_Success)
  298. {
  299. MSG_LOG1(ERROR, "MsgrInitializeMsgrInternal1 Failure %d\n", status);
  300. }
  301. }
  302. else
  303. {
  304. MSG_LOG0(ERROR, "MsgConfigurationLock -- MSG_INITIALIZE failed\n");
  305. status = ERROR_NOT_ENOUGH_MEMORY;
  306. }
  307. if (status != NERR_Success)
  308. {
  309. MsgFreeSharedData();
  310. if (wakeupSem != NULL)
  311. {
  312. MsgFreeSupportSeg();
  313. }
  314. MsgCloseWakeupSems(); // Close the ones that have been created
  315. return (MsgBeginForcedShutdown(
  316. IMMEDIATE,
  317. status));
  318. }
  319. // ***** INSTALLATION HINT *****
  320. msgrState = MsgStatusUpdate(STARTING);
  321. if (msgrState != STARTING)
  322. {
  323. return(msgrState);
  324. }
  325. //
  326. // Change from IMMEDIATE Shutdowns to PENDING shutdowns.
  327. // This is because at this point we have names on the adapters
  328. // to clean up.
  329. //
  330. status = MsgrInitializeMsgrInternal2();
  331. if (status != NERR_Success)
  332. {
  333. MSG_LOG1(ERROR, "MsgrInitializeMsgrInternal2 Failure\n", status);
  334. return (MsgBeginForcedShutdown(
  335. PENDING,
  336. status));
  337. }
  338. //
  339. // Build the name of the file that is to be used to get the
  340. // message header and tail.
  341. //
  342. MSG_LOG(TRACE, "Calling MsgSetUpMessageFile\n",0);
  343. status = MsgSetUpMessageFile();
  344. if (status != NO_ERROR)
  345. {
  346. MSG_LOG1(ERROR, "MsgSetUpMessageFile Failure\n", status);
  347. return (MsgBeginForcedShutdown(
  348. PENDING,
  349. status));
  350. }
  351. //
  352. // Start the Group messenger thread to handle all domain messaging
  353. //
  354. MSG_LOG(TRACE, "Calling MsgInitGroupSupport\n",0);
  355. if ( status = MsgInitGroupSupport( SD_NUMNETS() ) )
  356. {
  357. MSG_LOG(ERROR, "InitGroupSupport Failed\n",0);
  358. return (MsgBeginForcedShutdown(
  359. PENDING,
  360. NERR_GrpMsgProcessor));
  361. }
  362. //
  363. // Initialize the Display Code
  364. //
  365. status = MsgDisplayInit();
  366. if (status != NO_ERROR)
  367. {
  368. MSG_LOG1(ERROR, "Could not initialize the display functions %d\n", status);
  369. return (MsgBeginForcedShutdown(
  370. PENDING,
  371. status));
  372. }
  373. //
  374. // Create the security descriptor that is to be used in access
  375. // checks on the API interface.
  376. //
  377. MSG_LOG(TRACE, "Calling MsgCreateMessageNameObject\n",0);
  378. status = MsgCreateMessageNameObject();
  379. if (status != NERR_Success)
  380. {
  381. MSG_LOG(ERROR, "MsgCreateMessageNameObject (security descriptor) "
  382. "Failed\n", 0);
  383. return (MsgBeginForcedShutdown(
  384. PENDING,
  385. status));
  386. }
  387. //
  388. // Initialize the text for the message box title.
  389. //
  390. MsgInitMessageBoxTitle();
  391. //
  392. // Start the Messengers RPC server.
  393. //
  394. // NOTE: Now all RPC servers in services.exe share the same pipe name.
  395. // However, in order to support communication with version 1.0 of WinNt,
  396. // it is necessary for the Client Pipe name to remain the same as
  397. // it was in version 1.0. Mapping to the new name is performed in
  398. // the Named Pipe File System code.
  399. //
  400. MSG_LOG(TRACE,
  401. "MsgInitializeMsgr:Getting ready to start RPC server\n",0);
  402. status = MsgsvcGlobalData->StartRpcServer(
  403. MSGR_INTERFACE_NAME,
  404. msgsvc_ServerIfHandle);
  405. if (!NT_SUCCESS(status)) {
  406. MSG_LOG(ERROR, "RPC Initialization Failed " FORMAT_RPC_STATUS "\n",
  407. status);
  408. return (MsgBeginForcedShutdown(
  409. PENDING,
  410. status));
  411. }
  412. //
  413. // Start thread to register with endpoint mapper (may take a while)
  414. //
  415. ntStatus = RtlQueueWorkItem(MsgInitEndpoint, // Callback
  416. NULL, // pContext
  417. WT_EXECUTEONLYONCE | // Long one-shot callback
  418. WT_EXECUTELONGFUNCTION);
  419. if (!NT_SUCCESS(ntStatus)) {
  420. MSG_LOG(ERROR, "MsgInit: failed to start endpoint registration thread: %#x\n",
  421. ntStatus);
  422. return (MsgBeginForcedShutdown(
  423. PENDING,
  424. status));
  425. }
  426. // Initialize winsock (needed for name resolution)
  427. //
  428. status = WSAStartup(MAKEWORD(2,1),&wsaData);
  429. if (status != ERROR_SUCCESS) {
  430. MSG_LOG(ERROR, "Initialization of Winsock DLL failed " FORMAT_RPC_STATUS "\n",
  431. status);
  432. return (MsgBeginForcedShutdown(
  433. PENDING,
  434. status));
  435. }
  436. //
  437. // Update the status to indicate that installation is complete.
  438. // Get the current state back in case the ControlHandling thread has
  439. // told us to shutdown.
  440. //
  441. MSG_LOG(TRACE, "Exiting MsgInitializeMsgr - Init Done!\n",0);
  442. return (MsgStatusUpdate(RUNNING));
  443. }
  444. NET_API_STATUS
  445. MsgrInitializeMsgrInternal1(
  446. void
  447. )
  448. /*++
  449. Routine Description:
  450. Initialize volatile state related to lanas.
  451. These initializations can be undone immediately if there is an error.
  452. Arguments:
  453. None
  454. Return Value:
  455. None
  456. --*/
  457. {
  458. DWORD NumNets;
  459. NET_API_STATUS status;
  460. MSG_LOG(TRACE, "Calling MsgGetNumNets\n",0);
  461. NumNets = MsgGetNumNets();
  462. if (NumNets == 0)
  463. {
  464. MSG_LOG(TRACE, "FYI: No lana's enabled at this time\n",0);
  465. // Not having any networks is no longer an error, ie Numnets == 0 is ok
  466. }
  467. //
  468. // Initialize shared memory areas.
  469. //
  470. MSG_LOG(TRACE, "Calling MsgInitSharedData\n",0);
  471. status = MsgInitSharedData(NumNets);
  472. if (status != NERR_Success)
  473. {
  474. return status;
  475. }
  476. //*****************************************
  477. //
  478. // STUFF FROM Init_msrv() in MSRV.C
  479. //
  480. //*****************************************
  481. heap = SD_BUFFER(); // Initialize data heap pointer
  482. heapln = SD_BUFLEN(); // Initialize data heap length
  483. //
  484. // Set up the segement to hold the net bios handles, lana-nums
  485. // and wakeup Semaphores.
  486. //
  487. MSG_LOG(TRACE, "Calling MsgInitSupportSeg\n",0);
  488. status = MsgInitSupportSeg();
  489. if (status != NERR_Success)
  490. {
  491. MSG_LOG(ERROR, "InitSupportSeg Failed\n",0);
  492. return status;
  493. }
  494. //
  495. // Now initialize global net bios handles & lana nums. Initializes net_lana_num[]
  496. //
  497. MSG_LOG(TRACE, "Calling MsgInit_NetBios\n",0);
  498. status = MsgInit_NetBios();
  499. if (status != NERR_Success)
  500. {
  501. MSG_LOG1(ERROR, "MsgInit_NetBios failed %d\n", status);
  502. return status;
  503. }
  504. //
  505. // Get the wake up semaphore handles. Initializes wakeupSem[]
  506. //
  507. MSG_LOG(TRACE, "Calling MsgCreateWakeupSems\n",0);
  508. //
  509. // This always returns TRUE
  510. //
  511. MsgCreateWakeupSems(SD_NUMNETS());
  512. //
  513. // Open NETBIOS for use by messenger.
  514. // If any failures occur beyond this we must remember to close.
  515. //
  516. MsgsvcGlobalData->NetBiosOpen();
  517. //
  518. // Set computer name on adapters - if any
  519. //
  520. MSG_LOG(TRACE, "Calling MsgSetComputerName\n",0);
  521. status = MsgSetComputerName(SD_NUMNETS());
  522. if(status != NERR_Success)
  523. {
  524. MSG_LOG1(ERROR, "SetComputerName failed %d\n", status);
  525. MsgsvcGlobalData->NetBiosClose();
  526. return status;
  527. }
  528. return NERR_Success;
  529. }
  530. NET_API_STATUS
  531. MsgrInitializeMsgrInternal2(
  532. void
  533. )
  534. /*++
  535. Routine Description:
  536. Initialize volatile lana state. These initializations cannot be undone easily. If this routine
  537. fails we must go through a full shutdown in order to clean up.
  538. Arguments:
  539. None
  540. Return Value:
  541. None
  542. --*/
  543. {
  544. //
  545. // Installation is successful and complete. If there is a
  546. // user logged on then an attempt is made to add the user name
  547. // to this message server. No attempt is made at error reporting
  548. // if this fails, there may not be a user logged on, and if there is,
  549. // the user name may already exist as a message name on another
  550. // station.
  551. //
  552. // This is when we add usernames to the message table if we can.
  553. // Sometime this needs to handle multiple users??? (not in version 1)
  554. //
  555. if (g_IsTerminalServer)
  556. {
  557. MsgAddAlreadyLoggedOnUserNames();
  558. }
  559. else
  560. {
  561. MsgAddUserNames();
  562. }
  563. return NERR_Success;
  564. }
  565. VOID
  566. MsgBufferInit(
  567. IN DWORD dwBufLen
  568. )
  569. /*++
  570. Routine Description:
  571. This function is called during initialization to set up
  572. the message buffer in the shared data area.
  573. This function assumes that the shared data area is locked
  574. in memory, that the access semaphore for the shared data
  575. area is set, and that the global far pointer, dataPtr, is
  576. valid. BufferInit() initializes the heap structure of the
  577. buffer.
  578. SIDE EFFECTS
  579. The buffer in shared memory is initialized.
  580. Arguments:
  581. dwBuflen - buffer length
  582. Return Value:
  583. none
  584. --*/
  585. {
  586. LPHEAPHDR hp; // Heap block pointer
  587. hp = (LPHEAPHDR) SD_BUFFER(); // Get the address of buffer
  588. HP_SIZE(*hp) = dwBufLen; // Set the size of the first block
  589. HP_FLAG(*hp) = 0; // Unallocated
  590. SD_BUFLEN() = dwBufLen; // Save the length of the buffer
  591. }
  592. DWORD
  593. MsgInitSharedData(
  594. DWORD NumNets
  595. )
  596. /*++
  597. Routine Description:
  598. This function creates and initializes the shared data area.
  599. It sets up the computer name and initializes the message
  600. buffer.
  601. SIDE EFFECTS
  602. Calls MsgBufferInit().
  603. Arguments:
  604. NumNets - Number of network adapters to support.
  605. Return Value:
  606. RETURN
  607. NERR_Success if the operation was successful
  608. ERROR_NOT_ENOUGH_MEMORY - If the memory alloc for the shared
  609. memory segment fails.
  610. --*/
  611. {
  612. DWORD i,j; // Index
  613. ULONG size;
  614. PNCB_DATA pNcbData;
  615. DWORD MinimumNumNets = ((NumNets == 0)? 1 : NumNets); // 1 is the minimum
  616. //
  617. // Create and initialize shared data area.
  618. //
  619. size = bufferSize + BOOKKEEPING_SIZE(MinimumNumNets);
  620. if ((GlobalData.NetData = (PNET_DATA)LocalAlloc(LMEM_ZEROINIT, size)) == NULL) {
  621. goto NoMemory;
  622. }
  623. //
  624. // In case NumNets = 0, keep 1 dummy NetData.
  625. // This is not very pretty but should avoid any trouble, without having to modify
  626. // too much code.
  627. //
  628. GlobalData.Buffer = (PCHAR) (&GlobalData.NetData[MinimumNumNets]);
  629. for (i = 0; i < NumNets ; i++ )
  630. {
  631. // Allocate the list array at the maximum size, but only allocate
  632. // a small initial number of NCBs.
  633. if ((GlobalData.NetData[i].NcbList =
  634. LocalAlloc(LMEM_ZEROINIT,
  635. sizeof(PNCB_DATA) * NCB_MAX_ENTRIES)) == NULL)
  636. {
  637. goto NoMemory;
  638. }
  639. GlobalData.NetData[i].NumNcbs = NCB_INIT_ENTRIES;
  640. for (j=0; j < NCB_INIT_ENTRIES; j++)
  641. {
  642. if ((GlobalData.NetData[i].NcbList[j] = pNcbData =
  643. (PNCB_DATA) LocalAlloc(LMEM_ZEROINIT,
  644. sizeof(NCB_DATA))) == NULL)
  645. {
  646. goto NoMemory;
  647. }
  648. pNcbData->Ncb.ncb_cmd_cplt = 0xff;
  649. pNcbData->Ncb.ncb_retcode = 0;
  650. }
  651. }
  652. //
  653. // Initialize the shared data lock. The shared data is shared between
  654. // the API threads and the worker threads.
  655. //
  656. if (!MsgDatabaseLock(MSG_INITIALIZE,"InitSharedData"))
  657. {
  658. MSG_LOG0(ERROR,
  659. "MsgInitSharedData: MsgDatabaseLock failed\n");
  660. goto NoMemory;
  661. }
  662. //
  663. // Initialize the "used-to-be shared" data
  664. //
  665. SD_NUMNETS() = NumNets;
  666. SD_MESLOG() = 0; // Message logging disabled
  667. for ( j = 0; j < SD_NUMNETS(); j++ )
  668. {
  669. for(i = 0; i < NCBMAX(j); ++i)
  670. {
  671. //
  672. // Mark entries as free
  673. //
  674. SD_NAMEFLAGS(j,i) = NFDEL;
  675. //create empty session lists
  676. InitializeListHead(&(SD_SIDLIST(j,i)));
  677. }
  678. }
  679. //
  680. // Initialize the message buffer
  681. //
  682. MsgBufferInit(bufferSize);
  683. //
  684. // NT NOTE:
  685. // Skip Initializing the Support Set and Wakeup sems.
  686. // Init_msrv will end up doing that.
  687. //
  688. return(NERR_Success);
  689. NoMemory:
  690. MSG_LOG(ERROR,"[MSG]InitSharedData:LocalAlloc Failure "
  691. FORMAT_API_STATUS "\n", GetLastError());
  692. return(ERROR_NOT_ENOUGH_MEMORY);
  693. }
  694. VOID
  695. MsgFreeSharedData(VOID)
  696. {
  697. PNET_DATA pNetData;
  698. PNCB_DATA pNcbData;
  699. DWORD i,j;
  700. if (pNetData = GlobalData.NetData) {
  701. for (i = 0; i < SD_NUMNETS() ; i++, pNetData++ ) {
  702. if (pNetData->NcbList) {
  703. for (j = 0; j < NCBMAX(i) ; j++ ) {
  704. if (pNcbData = GETNCBDATA(i,j)) {
  705. LocalFree(pNcbData);
  706. }
  707. }
  708. LocalFree(pNetData->NcbList);
  709. }
  710. }
  711. LocalFree(GlobalData.NetData);
  712. GlobalData.NetData = NULL;
  713. }
  714. }
  715. NET_API_STATUS
  716. MsgSetComputerName(
  717. IN DWORD NumNets
  718. )
  719. /*++
  720. Routine Description:
  721. This function sets up the shared data area for the computer name
  722. so that it can receive messages.
  723. This function sets things up so that the computer name will be able
  724. to receive messages. First, it adds the user name form of the computer
  725. name to the local adapter. If successful, it then initializes one slot
  726. in the name table in the shared data area: a computer name
  727. receiving messages
  728. SIDE EFFECTS
  729. Locks the init data segment around net bios usage.
  730. Calls the net bios. Makes entries in the shared data area.
  731. Arguments:
  732. NumNets - The number of network adapters that is supported
  733. Return Value:
  734. 0 = success
  735. non-zero = failure
  736. --*/
  737. {
  738. NET_API_STATUS status = NERR_Success;
  739. NCB ncb;
  740. UCHAR res;
  741. DWORD i;
  742. unsigned short j;
  743. struct {
  744. ADAPTER_STATUS AdapterStatus;
  745. NAME_BUFFER NameBuffer[16];
  746. } Astat;
  747. //
  748. // Loop for each net.
  749. //
  750. for ( i = 0; i < NumNets; i++ )
  751. {
  752. // NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
  753. //
  754. // Reset the adapter
  755. //
  756. MSG_LOG1(TRACE,"Calling NetBiosReset for lana #%d\n",GETNETLANANUM(i));
  757. status = MsgsvcGlobalData->NetBiosReset(GETNETLANANUM(i));
  758. if (status != NERR_Success)
  759. {
  760. MSG_LOG(ERROR,"MsgSetComputerName: NetBiosReset failed "
  761. FORMAT_API_STATUS "\n", status);
  762. MSG_LOG(ERROR,"MsgSetComputerName: AdapterNum " FORMAT_DWORD
  763. "\n",i);
  764. //
  765. // If it fails, skip to the Next Net.
  766. //
  767. continue;
  768. }
  769. //
  770. //
  771. // NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
  772. //
  773. // Set call name for local adapter
  774. //
  775. clearncb(&ncb);
  776. status = MsgFmtNcbName(ncb.ncb_name, machineName, 3);
  777. if (status != NERR_Success)
  778. {
  779. MSG_LOG1(ERROR, "SetComputerName: Format name failed!", status);
  780. return status;
  781. }
  782. ncb.ncb_command = NCBADDNAME; // Add name (wait)
  783. ncb.ncb_lana_num = GETNETLANANUM(i); // Use the LANMAN adapter
  784. //
  785. // Copy the name
  786. // (At this point the name is ansi - not unicode)
  787. //
  788. memcpy(SD_NAMES(i,0), ncb.ncb_name, NCBNAMSZ);
  789. if (g_IsTerminalServer)
  790. {
  791. MSG_LOG(TRACE,"SetComputerName: Adding session EVERYBODY_SESSION_ID in the list\n",0);
  792. MsgAddSessionInList(&(SD_SIDLIST(i,0)),(ULONG)EVERYBODY_SESSION_ID);
  793. }
  794. MSG_LOG1(TRACE,"MsgSetComputerName: Adding ComputerName to lana #%d\n",
  795. GETNETLANANUM(i));
  796. res = Msgsendncb( &ncb, i);
  797. //
  798. // If the lana is being reinitialized we need to force a reset
  799. //
  800. if ((res & 0xff) == NRC_ENVNOTDEF)
  801. {
  802. MSG_LOG1(TRACE,"SetComputerName: NetBios ADDNAME failed 0x%x - doing reset\n",res);
  803. status = NetpNetBiosReset(GETNETLANANUM(i));
  804. if (status == NERR_Success)
  805. {
  806. //
  807. // rebuild the add name request
  808. //
  809. clearncb(&ncb);
  810. status = MsgFmtNcbName(ncb.ncb_name, machineName, 3);
  811. if (status != NERR_Success)
  812. {
  813. MSG_LOG1(ERROR, "SetComputerName: Format name failed %d!", status);
  814. return status;
  815. }
  816. ncb.ncb_command = NCBADDNAME; // Add name (wait)
  817. ncb.ncb_lana_num = GETNETLANANUM(i); // Use the LANMAN adapter
  818. MSG_LOG1(TRACE,"MsgSetComputerName: Adding ComputerName<03> to lana #%d\n",
  819. GETNETLANANUM(i));
  820. res = Msgsendncb(&ncb, i); // reissue the ncb
  821. }
  822. }
  823. if(res != 0)
  824. {
  825. MSG_LOG1(TRACE,"SetComputerName: NetBios ADDNAME failed 0x%x\n",res);
  826. if((res & 0xff) == NRC_DUPNAME)
  827. {
  828. //
  829. // If the name already exists on the adapter card (the
  830. // workstation may have added it), we want to get the
  831. // name number and pretend that we just added it.
  832. //
  833. // Name already exists. Issue an ASTAT to find the name
  834. // number.
  835. //
  836. clearncb(&ncb);
  837. ncb.ncb_buffer = (char FAR *) &Astat; // Set buffer address
  838. ncb.ncb_length = sizeof(Astat); // Set buffer length
  839. ncb.ncb_callname[0] = '*'; // local adapter status
  840. ncb.ncb_command = NCBASTAT; // Adapter status (wait)
  841. res = Msgsendncb(&ncb,i);
  842. if( res != NRC_GOODRET)
  843. {
  844. //
  845. // Failed to add name
  846. //
  847. MSG_LOG1(ERROR, "SetComputerName:sendncb (ASTAT) failed 0x%x\n", res);
  848. return MsgMapNetError(res);
  849. }
  850. //
  851. // Loop to name number
  852. //
  853. for(j = 0; j< Astat.AdapterStatus.name_count; ++j)
  854. {
  855. if (((Astat.NameBuffer[j].name_flags & 7) == 4)
  856. &&
  857. (memcmp( Astat.NameBuffer[j].name,
  858. SD_NAMES(i,0),
  859. NCBNAMSZ) == 0))
  860. {
  861. break; // Found the name
  862. }
  863. }
  864. if (j == Astat.AdapterStatus.name_count)
  865. {
  866. //
  867. // Failed to find
  868. //
  869. MSG_LOG(ERROR,
  870. "SetComputerName:DupName-failed to find NameNum\n",0);
  871. return NERR_NoComputerName;
  872. }
  873. SD_NAMENUMS(i,0) = Astat.NameBuffer[j].name_num; // Save num
  874. MSG_LOG1(TRACE,"SetComputerName: use existing name num (%d) instead\n",
  875. Astat.NameBuffer[j].name_num);
  876. }
  877. else
  878. {
  879. //
  880. // Fail if name not on the card after the call
  881. //
  882. MSG_LOG(ERROR, "SetComputerName:Name Not on Card. netbios rc = 0x%x\n",res);
  883. return NERR_NoComputerName;
  884. }
  885. }
  886. else
  887. {
  888. SD_NAMENUMS(i,0) = ncb.ncb_num; // Save the name number
  889. }
  890. SD_NAMEFLAGS(i,0) = NFNEW | NFMACHNAME; // Name is new
  891. } // End for all nets
  892. return NERR_Success;
  893. }
  894. DWORD
  895. MsgGetNumNets(VOID)
  896. /*++
  897. Routine Description:
  898. Arguments:
  899. Return Value:
  900. --*/
  901. {
  902. NCB ncb;
  903. LANA_ENUM lanaBuffer;
  904. unsigned char nbStatus;
  905. //
  906. // Find the number of networks by sending an enum request via Netbios.
  907. //
  908. clearncb(&ncb);
  909. ncb.ncb_command = NCBENUM; // Enumerate LANA nums (wait)
  910. ncb.ncb_buffer = (char FAR *)&lanaBuffer;
  911. ncb.ncb_length = sizeof(LANA_ENUM);
  912. nbStatus = Netbios (&ncb);
  913. if (nbStatus != NRC_GOODRET) {
  914. MSG_LOG(ERROR, "GetNumNets:Netbios LanaEnum failed rc="
  915. FORMAT_DWORD "\n", (DWORD) nbStatus);
  916. return(FALSE);
  917. }
  918. return((DWORD)lanaBuffer.length);
  919. #ifdef replaced
  920. LPBYTE transportInfo;
  921. int count=0;
  922. USHORT loopback_found = 0;
  923. NET_API_STATUS status;
  924. DWORD entriesRead;
  925. DWORD totalEntries;
  926. //
  927. // First try and find the networks mananged by the LAN manager
  928. //
  929. // NOTE: This call will fail if there are more than MSNGR_MAX_NETS
  930. // in the machine. This is not a problem unless there are fewer
  931. // than MSNGR_MAX_NETS that would qualify for messaging service.
  932. // In this case, it might be argued that the messenger should start.
  933. // For now, this is not the case. - ERICPE
  934. //
  935. status = NetWkstaTransportEnum (
  936. NULL, // server name (local)
  937. 0, // level
  938. &transportInfo, // bufptr
  939. -1, // preferred maximum length
  940. &entriesRead, // entries read
  941. &totalEntries, // total entries
  942. NULL); // resumeHandle
  943. //
  944. // Free up the buffer that RPC allocated for us.
  945. //
  946. NetApiBufferFree(transportInfo);
  947. if (status != NERR_Success) {
  948. MSG_LOG(ERROR,"GetNumNets:NetWkstaTransportEnum failed "
  949. FORMAT_API_STATUS "\n", status);
  950. return(0);
  951. }
  952. MSG_LOG(TRACE,"GetNumNets: numnets = " FORMAT_DWORD "\n", totalEntries);
  953. return(totalEntries);
  954. #endif
  955. }
  956. NET_API_STATUS
  957. MsgGetBufSize (
  958. OUT LPDWORD bufferSize
  959. )
  960. /*++
  961. Routine Description:
  962. This routine fills in the default buffer size
  963. Arguments:
  964. bufferSize - This is a pointer to where the buffer size is to be stored.
  965. Return Value:
  966. NERR_Success - No errors, the returned bufferSize is valid.
  967. --*/
  968. {
  969. //
  970. // Use the default.
  971. //
  972. *bufferSize = 8192;
  973. return NERR_Success;
  974. }
  975. DWORD
  976. MsgSetUpMessageFile (
  977. VOID
  978. )
  979. /*++
  980. Routine Description:
  981. Builds the name of the message file that is to be used in any
  982. subsequent DosGetMessage calls. The name is built in the Global
  983. variable MessageFileName.
  984. Arguments:
  985. none
  986. Return Value:
  987. NERR_Success - The operation was successful
  988. ERROR_NOT_ENOUGH_MEMORY - Couldn't allocate memory for MessageFileName.
  989. --*/
  990. {
  991. //
  992. // allocate some space for the message file name to be built.
  993. //
  994. MessageFileName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, (MSGFILENAMLEN+sizeof(TCHAR)));
  995. if (MessageFileName == NULL) {
  996. MSG_LOG(ERROR,"[MSG]SetUpMessageFile:LocalAlloc Failure "
  997. FORMAT_API_STATUS "\n", GetLastError());
  998. return(ERROR_NOT_ENOUGH_MEMORY);
  999. }
  1000. //
  1001. // This message filename (netmsg.dll) is defined in lmcons.h
  1002. //
  1003. STRCPY(MessageFileName,MESSAGE_FILENAME);
  1004. return (NERR_Success);
  1005. }
  1006. STATIC VOID
  1007. MsgInitMessageBoxTitle(
  1008. VOID
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. Obtains the title text for the message box used to display messages.
  1013. If the title is successfully obtained from the message file, then
  1014. that title is pointed to by GlobalAllocatedMsgTitle and
  1015. GlobalMessageBoxTitle. If unsuccessful, then GlobalMessageBoxTitle
  1016. left pointing to the DefaultMessageBoxTitle.
  1017. NOTE: If successful, a buffer is allocated by this function. The
  1018. pointer stored in GlobalAllocatedMsgTitle and it should be freed when
  1019. done with this buffer.
  1020. Arguments:
  1021. Return Value:
  1022. none
  1023. --*/
  1024. {
  1025. LPVOID hModule;
  1026. DWORD msgSize;
  1027. DWORD status=NO_ERROR;
  1028. GlobalAllocatedMsgTitle = NULL;
  1029. hModule = LoadLibrary( L"netmsg.dll");
  1030. if ( hModule == NULL) {
  1031. status = GetLastError();
  1032. MSG_LOG1(ERROR, "LoadLibrary() fails with winError = %d\n", GetLastError());
  1033. return;
  1034. }
  1035. msgSize = FormatMessageW(
  1036. FORMAT_MESSAGE_FROM_HMODULE | // dwFlags
  1037. FORMAT_MESSAGE_ARGUMENT_ARRAY |
  1038. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1039. hModule,
  1040. MTXT_MsgsvcTitle, // MessageId
  1041. 0, // dwLanguageId
  1042. (LPWSTR)&GlobalAllocatedMsgTitle, // lpBuffer
  1043. 0, // nSize
  1044. NULL);
  1045. if (msgSize == 0) {
  1046. status = GetLastError();
  1047. MSG_LOG1(ERROR,"Could not find MessageBox title in a message file %d\n",
  1048. status);
  1049. }
  1050. else {
  1051. GlobalMessageBoxTitle = GlobalAllocatedMsgTitle;
  1052. }
  1053. //
  1054. // Get the messages as Ansi since we'll be comparing them to an
  1055. // Ansi message that comes in from a remote Alerter service.
  1056. //
  1057. msgSize = FormatMessageA(
  1058. FORMAT_MESSAGE_FROM_HMODULE | // dwFlags
  1059. FORMAT_MESSAGE_IGNORE_INSERTS |
  1060. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1061. hModule,
  1062. APE2_ALERTER_PRINTING_SUCCESS, // MessageId
  1063. 0, // dwLanguageId
  1064. (LPSTR) &g_lpAlertSuccessMessage, // lpBuffer
  1065. 0, // nSize
  1066. NULL);
  1067. if (msgSize == 0)
  1068. {
  1069. // No loss -- we just won't be able to filter print success alerts
  1070. status = GetLastError();
  1071. MSG_LOG1(ERROR,
  1072. "Could not find Alerter print success message %d\n",
  1073. status);
  1074. }
  1075. else
  1076. {
  1077. //
  1078. // Trim the message to end after the "Printing Complete" line.
  1079. //
  1080. LPSTR lpTemp = g_lpAlertSuccessMessage;
  1081. g_dwAlertSuccessLen = 0;
  1082. while (*lpTemp && *lpTemp != '\r')
  1083. {
  1084. lpTemp++;
  1085. g_dwAlertSuccessLen++;
  1086. }
  1087. *lpTemp = '\0';
  1088. }
  1089. msgSize = FormatMessageA(
  1090. FORMAT_MESSAGE_FROM_HMODULE | // dwFlags
  1091. FORMAT_MESSAGE_IGNORE_INSERTS |
  1092. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1093. hModule,
  1094. APE2_ALERTER_PRINTING_FAILURE, // MessageId
  1095. 0, // dwLanguageId
  1096. (LPSTR) &g_lpAlertFailureMessage, // lpBuffer
  1097. 0, // nSize
  1098. NULL);
  1099. if (msgSize == 0)
  1100. {
  1101. // No loss -- we just won't be able to filter print success alerts
  1102. status = GetLastError();
  1103. MSG_LOG1(ERROR,
  1104. "Could not find Alerter print failure message %d\n",
  1105. status);
  1106. }
  1107. else
  1108. {
  1109. //
  1110. // Trim the message to end after the "Printing Complete" line.
  1111. //
  1112. LPSTR lpTemp = g_lpAlertFailureMessage;
  1113. g_dwAlertFailureLen = 0;
  1114. while (*lpTemp && *lpTemp != '\r')
  1115. {
  1116. lpTemp++;
  1117. g_dwAlertFailureLen++;
  1118. }
  1119. *lpTemp = '\0';
  1120. }
  1121. FreeLibrary(hModule);
  1122. return;
  1123. }
  1124. VOID
  1125. MsgInitEndpoint(
  1126. PVOID Context // This passed in as context.
  1127. )
  1128. /*++
  1129. Routine Description:
  1130. This function is called to initialize our RPC server entry point. We
  1131. do this in a separate thread because we may have to wait because
  1132. RpcSS is not ready yet.
  1133. Arguments:
  1134. Context - Context parameter
  1135. Return Value:
  1136. None
  1137. --*/
  1138. {
  1139. RPC_BINDING_VECTOR *bindingVector = NULL;
  1140. DWORD status, tries;
  1141. MSG_LOG(TRACE, "MsgInitEndpoint starting in separate thread\n",0);
  1142. //
  1143. // Create endpoint for receiving RPC calls
  1144. // This is for netbiosless notifications
  1145. //
  1146. for( tries = 0; tries < 3; tries++ ) {
  1147. status = RpcServerUseProtseq(
  1148. TEXT("ncadg_ip_udp"),
  1149. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  1150. NULL // Do we need an empty SD here?
  1151. );
  1152. if ( (status == RPC_S_OK) || (status == RPC_S_DUPLICATE_ENDPOINT) ) {
  1153. break;
  1154. }
  1155. MSG_LOG(ERROR, "RPC Init (UseProt Udp) Failed "
  1156. FORMAT_RPC_STATUS " - trying again\n", status);
  1157. Sleep( 30 * 1000 );
  1158. }
  1159. if ( (status != RPC_S_OK) && (status != RPC_S_DUPLICATE_ENDPOINT) ) {
  1160. if (status == RPC_S_SERVER_UNAVAILABLE) {
  1161. MSG_LOG( ERROR, "Failed to use UDP, check RPCSS service\n",0 );
  1162. } else {
  1163. MSG_LOG( ERROR, "Failed to use UDP, check TCP/IP\n",0 );
  1164. }
  1165. // give up
  1166. return;
  1167. }
  1168. status = RpcServerInqBindings(
  1169. &bindingVector
  1170. );
  1171. if (status != ERROR_SUCCESS) {
  1172. MSG_LOG( ERROR, "RpcServerInqBindings failed with %d\n",status );
  1173. return;
  1174. }
  1175. // Try to register in a loop in case RPCSS is not running yet
  1176. for( tries = 0; tries < 3; tries++ ) {
  1177. status = RpcEpRegister(
  1178. msgsvcsend_ServerIfHandle,
  1179. bindingVector,
  1180. NULL,
  1181. TEXT("Messenger Service")
  1182. );
  1183. if (status == RPC_S_OK) {
  1184. break;
  1185. }
  1186. MSG_LOG( ERROR, "Msgr: RpcEpRegister failed with %d - trying again\n", status );
  1187. RpcEpUnregister( msgsvcsend_ServerIfHandle,
  1188. bindingVector,
  1189. NULL );
  1190. // ignore error
  1191. Sleep( 10 * 1000 );
  1192. }
  1193. RpcBindingVectorFree( &bindingVector );
  1194. if (status != RPC_S_OK) {
  1195. // give up
  1196. return;
  1197. }
  1198. //
  1199. // Register RPC interface
  1200. //
  1201. status = RpcServerRegisterIf(
  1202. msgsvcsend_ServerIfHandle, // interface to register
  1203. NULL, // MgrTypeUuid
  1204. NULL); // MgrEpv; null means use default
  1205. if (status != RPC_S_OK) {
  1206. MSG_LOG(ERROR, "RPC Init (RegIf MsgSvcSend) Failed "
  1207. FORMAT_RPC_STATUS "\n", status);
  1208. return;
  1209. }
  1210. MSG_LOG(TRACE, "MsgInitEndpoint final status %d\n", status);
  1211. return;
  1212. }