mirror of https://github.com/lianthony/NT4.0
1251 lines
33 KiB
1251 lines
33 KiB
/*++
|
|
|
|
Copyright (c) 1991-92 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
msginit.c
|
|
|
|
Abstract:
|
|
|
|
Messenger Service Initialization Routines.
|
|
The following is a list of functions in this file:
|
|
|
|
MsgInitializeMsgr
|
|
BufferInit
|
|
InitSharedData
|
|
SetComputerName
|
|
GetNumNets
|
|
MsgGetBufSize
|
|
SetUpMessageFile
|
|
|
|
Author:
|
|
|
|
Dan Lafferty (danl) 18-Jul-1991
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Notes:
|
|
|
|
optional-notes
|
|
|
|
Revision History:
|
|
|
|
27-Jun-1995 AnirudhS
|
|
LocalFree(dataPtr) must be called AFTER MsgFreeSupportSeg, because
|
|
the latter tries to _close a handle stored in dataPtr.
|
|
|
|
08-Feb-1994 Danl
|
|
Removed the restriction that the memory allocated had to be
|
|
restricted to less than a 64K segment. We don't worry about
|
|
segments anymore.
|
|
|
|
12-Jan-1993 Danl
|
|
In error paths where we call MsgCloseWakeupSems, I need to do the
|
|
LocalFree(dataPtr) after the call to MsgCloseWakeupSems. Otherwise,
|
|
it access violates because MsgCloseWakeupSems uses the shared date
|
|
in the block pointed to by the dataPtr.
|
|
|
|
21-Apr-1992 JohnRo
|
|
Fixed bug printing a status when message name add fails.
|
|
Changed to use FORMAT_ equates throughout.
|
|
|
|
18-Feb-1992 ritaw
|
|
Convert to Win32 service control APIs.
|
|
|
|
18-Jul-1991 danl
|
|
Created as a composite of the original LM2,0 routines.
|
|
|
|
|
|
--*/
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include <stdlib.h> // atol
|
|
#include "msrv.h" // Messenger prototypes and constants
|
|
#include <winsvc.h> // Service control APIs
|
|
|
|
#include <netdebug.h> // NetpAssert, FORMAT_ equates.
|
|
#include <rpc.h> // DataTypes and runtime APIs
|
|
#include <msgsvc.h> // generated by the MIDL complier
|
|
|
|
#include <netlibnt.h> // NetpNtStatusToApiStatus prototypes
|
|
#include <rpcutil.h> // NetpStartRpcServer
|
|
|
|
#include <tstring.h> // Unicode string macros
|
|
#include <string.h> // memcpy
|
|
#include <lmwksta.h> // NetWrkstaTransportEnum
|
|
#include <lmapibuf.h> // NetApiBufferFree
|
|
#include <netlib.h> // UNUSED macro
|
|
#include <msgrutil.h> // NetpNetBiosReset
|
|
|
|
#include "msgdbg.h" // MSG_LOG
|
|
#include "heap.h" // heap management routines and macros.
|
|
#include "msgdata.h" // Global data
|
|
#include "msgsec.h" // Messenger security information
|
|
|
|
#include "msgnames.h" // MSGR_INTERFACE_NAME
|
|
#include "msgtext.h" // MTXT_MsgsvcTitle
|
|
|
|
//
|
|
// Defines
|
|
//
|
|
// The following is the size of the first offset area in the shared buffer.
|
|
// The size of this area is dependent on a runtime variable - the number
|
|
// of nets. The BOOKKEEPING_SIZE is calculated from the SD offsets
|
|
// described in msrv.h.
|
|
//
|
|
|
|
#define BOOKKEEPING_SIZE(n) (SDNAMEFLAGS + \
|
|
(n * NCBMAX) + \
|
|
(n * NCBMAX) + \
|
|
(n * NCBMAX * (NCBNAMSZ+4)) + \
|
|
(n * NCBMAX * (NCBNAMSZ+4)) + \
|
|
(n * NCBMAX * sizeof(DWORD)))
|
|
|
|
#define MAXSEG (0xffff)
|
|
|
|
#define LMI_PARM_M_SIZMESSBUF TEXT("/sizmessbuf")
|
|
|
|
|
|
//
|
|
// Global Data
|
|
//
|
|
|
|
static DWORD bufferSize; // Message buffer size
|
|
static DWORD msrv_pid; // pid of message server
|
|
|
|
extern LPTSTR MessageFileName;
|
|
|
|
//
|
|
// Local Function Prototypes
|
|
//
|
|
|
|
STATIC VOID
|
|
MsgBufferInit(
|
|
IN USHORT buflen
|
|
);
|
|
|
|
NET_API_STATUS
|
|
MsgInitSharedData(
|
|
DWORD NumNets
|
|
);
|
|
|
|
STATIC BOOL
|
|
MsgSetComputerName(
|
|
DWORD NumNets
|
|
);
|
|
|
|
STATIC DWORD
|
|
MsgGetNumNets(VOID);
|
|
|
|
NET_API_STATUS
|
|
MsgGetBufSize (
|
|
IN DWORD argc,
|
|
IN LPTSTR *argv,
|
|
OUT LPDWORD bufferSize,
|
|
OUT LPTSTR *lastarg
|
|
);
|
|
|
|
DWORD
|
|
MsgSetUpMessageFile(VOID);
|
|
|
|
|
|
STATIC VOID
|
|
MsgInitMessageBoxTitle(
|
|
VOID
|
|
);
|
|
|
|
|
|
NET_API_STATUS
|
|
MsgInitializeMsgr(
|
|
DWORD argc,
|
|
LPTSTR *argv
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers the control handler with the dispatcher thread. Then it
|
|
performs all initialization including the starting of the RPC server.
|
|
If any of the initialization fails, MsgStatusUpdate is called so that the
|
|
status is updated and the thread is terminated.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
LPTSTR lastarg;
|
|
DWORD NumNets;
|
|
DWORD hint_count = 0;
|
|
DWORD msgrState;
|
|
DWORD bufLen;
|
|
|
|
//
|
|
// Initialize the Time format. Since no users are logged on, we use
|
|
// the information for the default user.
|
|
//
|
|
InitializeCriticalSection(&TimeFormatCritSec);
|
|
NetpGetTimeFormat(&GlobalTimeFormat);
|
|
|
|
//
|
|
// Initialize the Thread Manager. This initializes some locks used
|
|
// on the Thread and Status databases.
|
|
//
|
|
MsgThreadManagerInit();
|
|
|
|
//
|
|
// Initialize the status structure
|
|
//
|
|
MsgStatusInit();
|
|
|
|
//
|
|
// Register this service with the ControlHandler.
|
|
// Now we can accept control requests and be requested to UNINSTALL.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling NetServiceRegisterCtrlHandler\n",0);
|
|
if ((MsgrStatusHandle = RegisterServiceCtrlHandler(
|
|
SERVICE_MESSENGER,
|
|
MsgrCtrlHandler
|
|
)) == (SERVICE_STATUS_HANDLE) NULL) {
|
|
|
|
status = GetLastError();
|
|
|
|
MSG_LOG(ERROR,
|
|
"FAILURE: RegisterServiceCtrlHandler status = " FORMAT_API_STATUS
|
|
"\n", status);
|
|
|
|
return( MsgBeginForcedShutdown (
|
|
IMMEDIATE,
|
|
status));
|
|
}
|
|
|
|
//
|
|
// Notify that installation is pending
|
|
//
|
|
|
|
msgrState = MsgStatusUpdate(STARTING);
|
|
|
|
if (msgrState != STARTING) {
|
|
//
|
|
// An UNINSTALL control request must have been received
|
|
//
|
|
return(msgrState);
|
|
}
|
|
|
|
//
|
|
// Check that the workstation is started
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling NetServiceControl\n",0);
|
|
|
|
if (! NetpIsServiceStarted(SERVICE_WORKSTATION)) {
|
|
|
|
MSG_LOG(ERROR, "WorkStation Service is not started\n",0);
|
|
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_WkstaNotStarted));
|
|
}
|
|
|
|
// *** INSTALLATION HINT ***
|
|
msgrState = MsgStatusUpdate(STARTING);
|
|
if (msgrState != STARTING) {
|
|
return(msgrState);
|
|
}
|
|
|
|
//
|
|
// Check command line for buffer size. If none given,
|
|
// use the default buffer size.
|
|
// lastarg is a pointer to the argument string that was found
|
|
// to be bad.
|
|
//
|
|
status = MsgGetBufSize ( argc, argv, &bufferSize, &lastarg );
|
|
|
|
if (status != NERR_Success) {
|
|
MSG_LOG(ERROR, "MsgGetBufSize Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
status));
|
|
}
|
|
|
|
// *** INSTALLATION HINT ***
|
|
msgrState = MsgStatusUpdate(STARTING);
|
|
if (msgrState != STARTING) {
|
|
return(msgrState);
|
|
}
|
|
|
|
|
|
if (bufferSize > MAX_SIZMESSBUF || bufferSize < MIN_SIZMESSBUF) {
|
|
MSG_LOG(ERROR, "Message Buffer Size is illegal\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
ERROR_INVALID_PARAMETER));
|
|
}
|
|
|
|
//
|
|
// This is the size of the buffer (that SDBUFFER points to) in the
|
|
// shared data area. This is calculated as:
|
|
//
|
|
// The size of a message buffer (bufferSize)
|
|
// plus
|
|
// space for 4 Multi-block message headers and names,
|
|
// plus
|
|
// space for one Multi-block text header for each text block that
|
|
// fits into the message buffer. (bufferSize/TXTMAX).
|
|
//
|
|
// The number of headers is rounded up by one.
|
|
// (bufferSize+TXTMAX-1)/TXTMAX
|
|
//
|
|
bufferSize += (4 * (sizeof(MBB) + (2 * NCBNAMSZ))) +
|
|
((( (bufferSize+TXTMAX-1)/TXTMAX) + 1) * sizeof(MBT));
|
|
|
|
MSG_LOG(TRACE, "Calling MsgGetNumNets\n",0);
|
|
NumNets = MsgGetNumNets();
|
|
if ( NumNets == 0 ) {
|
|
MSG_LOG(ERROR, "No nets to connect to\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_NoNetworkResource));
|
|
}
|
|
|
|
// ***** INSTALLATION HINT *****
|
|
msgrState = MsgStatusUpdate(STARTING);
|
|
if (msgrState != STARTING) {
|
|
return(msgrState);
|
|
}
|
|
|
|
//
|
|
// Initialize shared memory areas.
|
|
//
|
|
MSG_LOG(TRACE, "Calling MsgInitSharedData\n",0);
|
|
status = MsgInitSharedData(NumNets);
|
|
|
|
if (status != NERR_Success) {
|
|
MSG_LOG(ERROR, "InitSharedData Failure\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_NoRoom));
|
|
}
|
|
|
|
// ***** INSTALLATION HINT *****
|
|
msgrState = MsgStatusUpdate(STARTING);
|
|
if (msgrState != STARTING) {
|
|
return(msgrState);
|
|
}
|
|
|
|
//*****************************************
|
|
//
|
|
// STUFF FROM Init_msrv() in MSRV.C
|
|
//
|
|
//*****************************************
|
|
|
|
heap = SD_BUFFER(); // Initialize data heap pointer
|
|
heapln = SD_BUFLEN(); // Initialize data heap length
|
|
|
|
//
|
|
// Set up the segement to hold the net bios handles, lana-nums
|
|
// and wakeup Semaphores.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgInitSupportSeg\n",0);
|
|
if ( MsgInitSupportSeg() )
|
|
{
|
|
LocalFree (dataPtr); // Free shared data
|
|
MSG_LOG(ERROR, "InitSupportSeg Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_NoRoom));
|
|
}
|
|
|
|
//
|
|
// Now initialize global net bios handles & lana nums.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgInit_NetBios\n",0);
|
|
if (!MsgInit_NetBios())
|
|
{
|
|
MsgFreeSupportSeg();
|
|
LocalFree (dataPtr); // Free shared data
|
|
MSG_LOG(ERROR, "Init_NetBios Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
ERROR_OPEN_FAILED));
|
|
}
|
|
|
|
//
|
|
// Get the wake up semaphore handles.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgCreateWakeupSems\n",0);
|
|
if (!MsgCreateWakeupSems(SD_NUMNETS())) {
|
|
MsgCloseWakeupSems(); // Close the ones that have been created
|
|
MsgFreeSupportSeg();
|
|
LocalFree (dataPtr); // Free shared data
|
|
MSG_LOG(ERROR, "CreateWakeupSems Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_NoRoom));
|
|
}
|
|
|
|
//
|
|
// Ask the Worksta for the computer name. If the computer
|
|
// has no name, then abort.
|
|
//
|
|
// The computername and the username are in unicode format.
|
|
//
|
|
// NOTE: the username that is returned is a name we may want to add
|
|
// to the table.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Getting the ComputerName\n",0);
|
|
|
|
bufLen = sizeof(machineName);
|
|
|
|
*machineName = TEXT('\0');
|
|
|
|
if (!GetComputerName(machineName,&bufLen)) {
|
|
MSG_LOG(ERROR,"GetComputerName failed \n",0);
|
|
status = GetLastError();
|
|
}
|
|
|
|
|
|
if ( (status != NERR_Success) ||
|
|
(*machineName == TEXT('\0')) || (*machineName == TEXT(' '))) {
|
|
|
|
//
|
|
// fatal error if no name
|
|
//
|
|
MsgCloseWakeupSems();
|
|
MsgFreeSupportSeg();
|
|
LocalFree (dataPtr); // Free shared data
|
|
MSG_LOG(ERROR, "GetWkstaNames Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_NoComputerName));
|
|
}
|
|
machineName[NCBNAMSZ] = TEXT('\0'); // make sure it's terminated
|
|
MachineNameLen = (SHORT) STRLEN(machineName);
|
|
|
|
//
|
|
// Open NETBIOS for use by messenger.
|
|
// If any failures occur beyond this we must remember to close.
|
|
//
|
|
MsgsvcGlobalData->NetBiosOpen();
|
|
|
|
//
|
|
// Set computer name on adapters - if any
|
|
//
|
|
MSG_LOG(TRACE, "Calling MsgSetComputerName\n",0);
|
|
if(MsgSetComputerName(SD_NUMNETS()) != 0) {
|
|
MsgCloseWakeupSems();
|
|
MsgFreeSupportSeg();
|
|
LocalFree (dataPtr); // Free shared data
|
|
MSG_LOG(ERROR, "SetComputerName Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
IMMEDIATE,
|
|
NERR_NoComputerName));
|
|
}
|
|
|
|
//
|
|
// Change from IMMEDIATE Shutdowns to PENDING shutdowns.
|
|
// This is because at this point we have names on the adapters
|
|
// to clean up.
|
|
//
|
|
|
|
|
|
//
|
|
// The NCBs and NCB buffers belong in a seperate segment so
|
|
// DosAlloc the segment here.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgInitNCBSeg\n",0);
|
|
if( MsgInitNCBSeg() )
|
|
{
|
|
MSG_LOG(ERROR, "InitNCBSeg Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
PENDING,
|
|
NERR_NoRoom));
|
|
}
|
|
|
|
//
|
|
// Allocate the the Service segment.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgInitServiceSeg\n",0);
|
|
if ( MsgInitServiceSeg() )
|
|
{
|
|
MSG_LOG(ERROR, "InitServiceSeg Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
PENDING,
|
|
NERR_NoRoom));
|
|
}
|
|
|
|
//
|
|
// Build the name of the file that is to be used to get the
|
|
// message header and tail. Don't care about errors, since
|
|
// any error will result in the file not being used and is
|
|
// resorting to the old standby strings.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgSetUpMessageFile\n",0);
|
|
MsgSetUpMessageFile();
|
|
|
|
//
|
|
// Start the Group messenger thread to handle all domain messaging
|
|
// SD_NUMNETS() is the position in the wakeupSem array for the
|
|
// mailslot event.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgInitGroupSupport\n",0);
|
|
if ( status = MsgInitGroupSupport( SD_NUMNETS() ) )
|
|
{
|
|
MSG_LOG(ERROR, "InitGroupSupport Failed\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
PENDING,
|
|
NERR_GrpMsgProcessor));
|
|
}
|
|
|
|
//
|
|
// Initialize the Display Code
|
|
//
|
|
if (!MsgDisplayInit()) {
|
|
MSG_LOG(ERROR, "Could not initialize the display functions\n",0);
|
|
return (MsgBeginForcedShutdown(
|
|
PENDING,
|
|
NERR_NoRoom)); // BUGBUG: Make this meaningful!
|
|
}
|
|
|
|
|
|
//
|
|
// Create the security descriptor that is to be used in access
|
|
// checks on the API interface.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Calling MsgCreateMessageNameObject\n",0);
|
|
status = MsgCreateMessageNameObject();
|
|
|
|
if (status != NERR_Success) {
|
|
MSG_LOG(ERROR, "MsgCreateMessageNameObject (security descriptor) "
|
|
"Failed\n", 0);
|
|
return (MsgBeginForcedShutdown(
|
|
PENDING,
|
|
status));
|
|
}
|
|
|
|
//
|
|
// Initialize the text for the message box title.
|
|
//
|
|
MsgInitMessageBoxTitle();
|
|
|
|
//
|
|
// Installation is successful and complete. If there is a
|
|
// user logged on then an attempt is made to add the user name
|
|
// to this message server. No attempt is made at error reporting
|
|
// if this fails, there may not be a user logged on, and if there is,
|
|
// the user name may already exist as a message name on another
|
|
// station.
|
|
//
|
|
// This is when we add usernames to the message table if we can.
|
|
// Sometime this needs to handle multiple users??? (not in version 1)
|
|
//
|
|
|
|
MsgAddUserNames();
|
|
|
|
|
|
//
|
|
// Start the Messengers RPC server.
|
|
//
|
|
// NOTE: Now all RPC servers in services.exe share the same pipe name.
|
|
// However, in order to support communication with version 1.0 of WinNt,
|
|
// it is necessary for the Client Pipe name to remain the same as
|
|
// it was in version 1.0. Mapping to the new name is performed in
|
|
// the Named Pipe File System code.
|
|
//
|
|
|
|
MSG_LOG(TRACE,
|
|
"MsgInitializeMsgr:Getting ready to start RPC server\n",0);
|
|
|
|
status = MsgsvcGlobalData->StartRpcServer(
|
|
MsgsvcGlobalData->SvcsRpcPipeName,
|
|
msgsvc_ServerIfHandle);
|
|
|
|
if (status != RPC_S_OK) {
|
|
MSG_LOG(ERROR, "RPC Initialization Failed " FORMAT_RPC_STATUS "\n",
|
|
status);
|
|
|
|
return (MsgBeginForcedShutdown(
|
|
PENDING,
|
|
status));
|
|
}
|
|
|
|
//
|
|
// Update the status to indicate that installation is complete.
|
|
// Get the current state back in case the ControlHandling thread has
|
|
// told us to shutdown.
|
|
//
|
|
|
|
MSG_LOG(TRACE, "Exiting MsgInitializeMsgr - Init Done!\n",0);
|
|
|
|
return (MsgStatusUpdate(RUNNING));
|
|
}
|
|
|
|
STATIC VOID
|
|
MsgBufferInit(
|
|
IN USHORT buflen // Buffer length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called during initialization to set up
|
|
the message buffer in the shared data area.
|
|
|
|
This function assumes that the shared data area is locked
|
|
in memory, that the access semaphore for the shared data
|
|
area is set, and that the global far pointer, dataPtr, is
|
|
valid. BufferInit() initializes the heap structure of the
|
|
buffer.
|
|
|
|
SIDE EFFECTS
|
|
|
|
The buffer in shared memory is initialized.
|
|
|
|
Arguments:
|
|
|
|
buflen - buffer length
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
LPHEAPHDR hp; // Heap block pointer
|
|
|
|
hp = (LPHEAPHDR) SD_BUFFER(); // Get the address of buffer
|
|
HP_SIZE(*hp) = buflen; // Set the size of the first block
|
|
HP_FLAG(*hp) = 0; // Unallocated
|
|
SD_BUFLEN() = buflen; // Save the length of the buffer
|
|
}
|
|
|
|
DWORD
|
|
MsgInitSharedData(
|
|
DWORD NumNets
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates and initializes the shared data area.
|
|
It sets up the computer name and initializes the message
|
|
buffer.
|
|
|
|
SIDE EFFECTS
|
|
|
|
Calls MsgBufferInit().
|
|
|
|
|
|
Arguments:
|
|
|
|
NumNets - Number of network adapters to support.
|
|
|
|
Return Value:
|
|
|
|
RETURN
|
|
NERR_Success if the operation was successful
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - If the memory alloc for the shared
|
|
memory segment fails.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD i,j; // Index
|
|
ULONG size;
|
|
|
|
//
|
|
// Create and initialize shared data area.
|
|
//
|
|
size = bufferSize + BOOKKEEPING_SIZE(NumNets);
|
|
|
|
dataPtr = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, size);
|
|
if (dataPtr == NULL) {
|
|
MSG_LOG(ERROR,"[MSG]InitSharedData:LocalAlloc Failure "
|
|
FORMAT_API_STATUS "\n", GetLastError());
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
//
|
|
// Initialize the shared data lock. The shared data is shared between
|
|
// the API threads and the worker threads.
|
|
//
|
|
MsgDatabaseLock(MSG_INITIALIZE,"InitSharedData");
|
|
|
|
//
|
|
// Initialize the "used-to-be shared" data
|
|
//
|
|
SD_NUMNETS() = NumNets;
|
|
SD_MSRV() = 0; // No message server active
|
|
SD_LOGNAM()[0] = '\0'; // No log file yet
|
|
SD_MESLOG() = 0; // Message logging disabled
|
|
SD_MESQF() = INULL; // Message queue is empty
|
|
SD_MESQB() = INULL;
|
|
|
|
for ( j = 0; j < SD_NUMNETS(); j++ ) {
|
|
|
|
for(i = 0; i < NCBMAX; ++i) {
|
|
|
|
//
|
|
// Mark entries as free
|
|
//
|
|
SD_NAMEFLAGS(j,i) = NFDEL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initialize the message buffer
|
|
//
|
|
MsgBufferInit((USHORT)bufferSize);
|
|
|
|
//
|
|
// NT NOTE:
|
|
// Skip Initializing the Support Set and Wakeup sems.
|
|
// Init_msrv will end up doing that.
|
|
//
|
|
|
|
return(NERR_Success);
|
|
}
|
|
|
|
STATIC BOOL
|
|
MsgSetComputerName(
|
|
IN DWORD NumNets
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets up the shared data area for the computer name
|
|
so that it can receive messages.
|
|
|
|
This function sets things up so that the computer name will be able
|
|
to receive messages. First, it adds the user name form of the computer
|
|
name to the local adapter. If successful, it then initializes one slot
|
|
in the name table in the shared data area: a computer name
|
|
receiving messages
|
|
|
|
SIDE EFFECTS
|
|
|
|
Locks the init data segment around net bios usage.
|
|
Calls the net bios. Makes entries in the shared data area.
|
|
|
|
|
|
Arguments:
|
|
|
|
NumNets - The number of network adapters that is supported
|
|
|
|
Return Value:
|
|
|
|
0 = success
|
|
non-zero = failure
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
NCB ncb; /* Network Control Block */
|
|
// ASTAT adapterStatus; /* Adapter status buffer */
|
|
UCHAR res;
|
|
DWORD i;
|
|
unsigned short j;
|
|
|
|
struct {
|
|
ADAPTER_STATUS AdapterStatus;
|
|
NAME_BUFFER NameBuffer[16];
|
|
} Astat;
|
|
|
|
|
|
//
|
|
// Loop for each net.
|
|
//
|
|
|
|
for ( i = 0; i < NumNets; i++ )
|
|
{
|
|
// NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
|
|
//
|
|
// Reset the adapter
|
|
//
|
|
MSG_LOG1(TRACE,"Calling NetBiosReset for lana #%d\n",net_lana_num[i]);
|
|
status = MsgsvcGlobalData->NetBiosReset(net_lana_num[i]);
|
|
|
|
if (status != NERR_Success) {
|
|
MSG_LOG(ERROR,"MsgSetComputerName: NetBiosReset failed "
|
|
FORMAT_API_STATUS "\n", status);
|
|
MSG_LOG(ERROR,"MsgSetComputerName: AdapterNum " FORMAT_DWORD
|
|
"\n",i);
|
|
//
|
|
// If it fails, skip to the Next Net.
|
|
//
|
|
continue;
|
|
}
|
|
//
|
|
//
|
|
// NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW-NEW
|
|
|
|
//
|
|
// Set call name for local adapter
|
|
//
|
|
clearncb(&ncb);
|
|
status = MsgFmtNcbName( ncb.ncb_name, machineName, 3);
|
|
if (status != NERR_Success) {
|
|
MSG_LOG(ERROR,"SetComputerName: Format name failed!",0);
|
|
return ((BOOL)1);
|
|
}
|
|
ncb.ncb_command = NCBADDNAME; // Add name (wait)
|
|
ncb.ncb_lana_num = net_lana_num[i]; // Use the LANMAN adapter
|
|
|
|
//
|
|
// Copy the name
|
|
// (At this point the name is ansi - not unicode)
|
|
//
|
|
memcpy(SD_NAMES(i,0), ncb.ncb_name, NCBNAMSZ);
|
|
|
|
|
|
MSG_LOG1(TRACE,"MsgSetComputerName: Adding ComputerName to lana #%d\n",
|
|
net_lana_num[i]);
|
|
|
|
if( (res = Msgsendncb( &ncb, i)) != 0)
|
|
{
|
|
MSG_LOG1(TRACE,"SetComputerName: NetBios ADDNAME failed 0x%x\n",res);
|
|
|
|
if( (res & 0xff) == NRC_DUPNAME)
|
|
{
|
|
//
|
|
// If the name already exists on the adapter card (the
|
|
// workstation may have added it), we want to get the
|
|
// name number and pretend that we just added it.
|
|
//
|
|
// Name already exists. Issue an ASTAT to find the name
|
|
// number.
|
|
//
|
|
clearncb(&ncb);
|
|
ncb.ncb_buffer = (char FAR *) &Astat; // Set buffer address
|
|
ncb.ncb_length = sizeof(Astat); // Set buffer length
|
|
ncb.ncb_callname[0] = '*'; // local adapter status
|
|
ncb.ncb_command = NCBASTAT; // Adapter status (wait)
|
|
|
|
res = Msgsendncb(&ncb,i);
|
|
if( res != NRC_GOODRET)
|
|
{
|
|
//
|
|
// Failed to add name
|
|
//
|
|
|
|
//Close_NetBios();
|
|
MSG_LOG1(ERROR, "SetComputerName:sendncb (ASTAT) failed 0x%x\n",res);
|
|
return((BOOL)1);
|
|
}
|
|
|
|
//
|
|
// Loop to name number
|
|
//
|
|
for(j = 0; j< Astat.AdapterStatus.name_count; ++j) {
|
|
if(((Astat.NameBuffer[j].name_flags & 7) == 4) &&
|
|
(memcmp( Astat.NameBuffer[j].name,
|
|
SD_NAMES(i,0),
|
|
NCBNAMSZ) == 0)) {
|
|
|
|
break; // Found the name
|
|
}
|
|
}
|
|
|
|
if( j == Astat.AdapterStatus.name_count)
|
|
{
|
|
//
|
|
// Failed to find
|
|
//
|
|
|
|
//Close_NetBios();
|
|
MSG_LOG(ERROR,
|
|
"SetComputerName:DupName-failed to find NameNum\n",0);
|
|
return((BOOL)1);
|
|
}
|
|
SD_NAMENUMS(i,0) = Astat.NameBuffer[j].name_num; // Save num
|
|
MSG_LOG1(TRACE,"SetComputerName: use existing name num (%d) instead\n",
|
|
Astat.NameBuffer[j].name_num);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Fail if name not on the card after the call
|
|
//
|
|
|
|
// Close_NetBios();
|
|
MSG_LOG(ERROR, "SetComputerName:Name Not on Card. netbios rc = 0x%x\n",res);
|
|
return((BOOL)1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SD_NAMENUMS(i,0) = ncb.ncb_num; // Save the name number
|
|
}
|
|
|
|
|
|
SD_NAMEFLAGS(i,0) = NFNEW | NFMACHNAME; // Name is new
|
|
|
|
|
|
} // End for all nets
|
|
|
|
// Close_NetBios();
|
|
return((BOOL)0); /* Success */
|
|
}
|
|
|
|
STATIC DWORD
|
|
MsgGetNumNets(VOID)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
NCB ncb;
|
|
LANA_ENUM lanaBuffer;
|
|
unsigned char nbStatus;
|
|
|
|
|
|
//
|
|
// Find the number of networks by sending an enum request via Netbios.
|
|
//
|
|
|
|
clearncb(&ncb);
|
|
ncb.ncb_command = NCBENUM; // Enumerate LANA nums (wait)
|
|
ncb.ncb_buffer = (char FAR *)&lanaBuffer;
|
|
ncb.ncb_length = sizeof(LANA_ENUM);
|
|
|
|
nbStatus = Netbios (&ncb);
|
|
if (nbStatus != NRC_GOODRET) {
|
|
MSG_LOG(ERROR, "GetNumNets:Netbios LanaEnum failed rc="
|
|
FORMAT_DWORD "\n", (DWORD) nbStatus);
|
|
return(FALSE);
|
|
}
|
|
|
|
return((DWORD)lanaBuffer.length);
|
|
|
|
#ifdef replaced
|
|
|
|
LPBYTE transportInfo;
|
|
int count=0;
|
|
USHORT loopback_found = 0;
|
|
NET_API_STATUS status;
|
|
DWORD entriesRead;
|
|
DWORD totalEntries;
|
|
|
|
//
|
|
// First try and find the networks mananged by the LAN manager
|
|
//
|
|
// NOTE: This call will fail if there are more than MSNGR_MAX_NETS
|
|
// in the machine. This is not a problem unless there are fewer
|
|
// than MSNGR_MAX_NETS that would qualify for messaging service.
|
|
// In this case, it might be argued that the messenger should start.
|
|
// For now, this is not the case. - ERICPE
|
|
//
|
|
|
|
status = NetWkstaTransportEnum (
|
|
NULL, // server name (local)
|
|
0, // level
|
|
&transportInfo, // bufptr
|
|
-1, // preferred maximum length
|
|
&entriesRead, // entries read
|
|
&totalEntries, // total entries
|
|
NULL); // resumeHandle
|
|
|
|
//
|
|
// Free up the buffer that RPC allocated for us.
|
|
//
|
|
NetApiBufferFree(transportInfo);
|
|
|
|
if (status != NERR_Success) {
|
|
MSG_LOG(ERROR,"GetNumNets:NetWkstaTransportEnum failed "
|
|
FORMAT_API_STATUS "\n", status);
|
|
return(0);
|
|
}
|
|
MSG_LOG(TRACE,"GetNumNets: numnets = " FORMAT_DWORD "\n", totalEntries);
|
|
|
|
return(totalEntries);
|
|
#endif
|
|
}
|
|
|
|
NET_API_STATUS
|
|
MsgGetBufSize (
|
|
IN DWORD argc,
|
|
IN LPTSTR *argv,
|
|
OUT LPDWORD bufferSize,
|
|
OUT LPTSTR *lastarg
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine parses through the command line arguments in search of
|
|
the buffer size. This is the only valid argument and is of the
|
|
following form:
|
|
/sizmessbuf:[bytes]
|
|
Where bytes is the number of bytes for the message buffer defining
|
|
the size of messages the messenger can receive. The range is
|
|
512-62000. The default is 4096.
|
|
|
|
If a passed in sizmessbuf is an illegal value, an error will be returned.
|
|
|
|
Arguments that are not switches (prefixed by "/") are ignored. Invalid
|
|
switches cause a failure, and the text of the bad switch is passed back
|
|
in lastarg.
|
|
|
|
Arguments:
|
|
|
|
argc - This is the count of the number of arguments that is passed in.
|
|
|
|
argv - This is a pointer to an array of pointers to arguments.
|
|
|
|
bufferSize - This is a pointer to where the buffer size is to be stored.
|
|
If a bufferSize was not found on the command line, the default
|
|
is placed in here.
|
|
|
|
lastarg - This is a pointer to a location where a pointer to a
|
|
switch argument that was in error is to be placed.
|
|
|
|
Return Value:
|
|
|
|
NERR_Success - No errors, the returned bufferSize is valid and
|
|
lastarg does not contain any error information.
|
|
|
|
ERROR_INVALID_PARAMETER - The command line switch is not a valid one for
|
|
this service.
|
|
|
|
|
|
--*/
|
|
{
|
|
DWORD switchNameSize;
|
|
BOOL fromCmdLine = FALSE;
|
|
DWORD i;
|
|
LPTSTR pSizeString;
|
|
|
|
//
|
|
// Check the passed in command args.
|
|
//
|
|
*lastarg = NULL;
|
|
*bufferSize = 0;
|
|
|
|
for (i=0; i<argc; i++) {
|
|
if ( *argv[i] == '/') {
|
|
switchNameSize = STRLEN(LMI_PARM_M_SIZMESSBUF);
|
|
|
|
if (STRNICMP (argv[i], LMI_PARM_M_SIZMESSBUF, switchNameSize) == 0) {
|
|
//
|
|
// We received a valid command line switch - see if it is
|
|
// a duplicate of one we already have.
|
|
//
|
|
if (fromCmdLine = TRUE) {
|
|
*lastarg = argv[i];
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
pSizeString = argv[i] + switchNameSize;
|
|
|
|
*bufferSize = ATOL(pSizeString);
|
|
fromCmdLine = TRUE;
|
|
}
|
|
else {
|
|
//
|
|
// We received an invalid command line switch
|
|
//
|
|
MSG_LOG(ERROR,"MsgGetBufSize:Invalid command line switch\n",0);
|
|
*lastarg = argv[i];
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// do nothing - skip things that don't look like switches
|
|
//
|
|
}
|
|
}
|
|
if (!fromCmdLine) {
|
|
//
|
|
// Attempt to get the buffer size from the configuration database.
|
|
// BUGBUG! do this sometime.
|
|
// Actually, it would be nice to do away with this config
|
|
// baggage. Leave it fixed size.
|
|
//
|
|
|
|
//
|
|
// If it isn't in the database, use the default.
|
|
//
|
|
*bufferSize = 8192;
|
|
}
|
|
|
|
if ((*bufferSize < 512) || (*bufferSize > 62000)) {
|
|
MSG_LOG(ERROR,"MsgGetBufSize:BufferSize out of range\n",0);
|
|
return( ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return (NERR_Success);
|
|
}
|
|
|
|
DWORD
|
|
MsgSetUpMessageFile (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Builds the name of the message file that is to be used in any
|
|
subsequent DosGetMessage calls. The name is built in the Global
|
|
variable MessageFileName, and is constructed using the following
|
|
template.
|
|
|
|
lanroot\netprog\net.msg
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
NERR_Success - The operation was successful
|
|
|
|
ERROR_NOT_ENOUGH_MEMORY - Couldn't allocate memory for MessageFileName.
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// allocate some space for the message file name to be built.
|
|
//
|
|
MessageFileName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, (MSGFILENAMLEN+sizeof(TCHAR)));
|
|
|
|
if (MessageFileName == NULL) {
|
|
MSG_LOG(ERROR,"[MSG]SetUpMessageFile:LocalAlloc Failure "
|
|
FORMAT_API_STATUS "\n", GetLastError());
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
//
|
|
// BUGBUG: The following function finds the LAN root directory and
|
|
// builds a filename with that. What will we do in NT?
|
|
//
|
|
#ifdef later
|
|
result = NetIMakeLMFileName ( MESSAGE_FILE, MessageFileName,
|
|
PATHLEN+1);
|
|
if ( result ) {
|
|
MessageFileName[0] = '\0';
|
|
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Temporary fix. Use a fixed filename and use the temporary
|
|
// DosGetMessage (until we get a win32 equivalent).
|
|
// This message filename is defined in lmcons.h
|
|
//
|
|
|
|
STRCPY(MessageFileName,MESSAGE_FILENAME);
|
|
|
|
return (NERR_Success);
|
|
|
|
}
|
|
|
|
STATIC VOID
|
|
MsgInitMessageBoxTitle(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Obtains the title text for the message box used to display messages.
|
|
If the title is successfully obtained from the message file, then
|
|
that title is pointed to by GlobalAllocatedMsgTitle and
|
|
GlobalMessageBoxTitle. If unsuccessful, then GlobalMessageBoxTitle
|
|
left pointing to the DefaultMessageBoxTitle.
|
|
|
|
NOTE: If successful, a buffer is allocated by this function. The
|
|
pointer stored in GlobalAllocatedMsgTitle and it should be freed when
|
|
done with this buffer.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
LPVOID hModule;
|
|
DWORD msgSize;
|
|
DWORD status=NO_ERROR;
|
|
|
|
GlobalAllocatedMsgTitle = NULL;
|
|
|
|
hModule = LoadLibrary( L"netmsg.dll");
|
|
if ( hModule == NULL) {
|
|
status = GetLastError();
|
|
MSG_LOG1(ERROR, "LoadLibrary() fails with winError = %d\n", GetLastError());
|
|
return;
|
|
}
|
|
msgSize = FormatMessageW(
|
|
FORMAT_MESSAGE_FROM_HMODULE | // dwFlags
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
|
hModule,
|
|
MTXT_MsgsvcTitle, // MessageId
|
|
0, // dwLanguageId
|
|
(LPWSTR)&GlobalAllocatedMsgTitle, // lpBuffer
|
|
0, // nSize
|
|
NULL);
|
|
|
|
if (msgSize == 0) {
|
|
status = GetLastError();
|
|
MSG_LOG1(ERROR,"Could not find MessageBox title in a message file %d\n",
|
|
status);
|
|
}
|
|
else {
|
|
GlobalMessageBoxTitle = GlobalAllocatedMsgTitle;
|
|
}
|
|
FreeLibrary(hModule);
|
|
return;
|
|
}
|