398 lines
9.9 KiB
C
398 lines
9.9 KiB
C
/*****************************************************************/
|
||
/** Microsoft LAN Manager **/
|
||
/** Copyright(c) Microsoft Corp., 1990 **/
|
||
/*****************************************************************/
|
||
// data.c
|
||
//
|
||
// This file contains most of the data declarations and set up routines
|
||
// used by the messenger service.
|
||
//
|
||
//
|
||
// Revision History:
|
||
// 02-Sep-1993 wlees
|
||
// Provide synchronization between rpc routines and Pnp reconfiguration
|
||
|
||
|
||
#include "msrv.h" // Message server declarations
|
||
#include <rpc.h> // RPC_HANDLE
|
||
#include <winsvc.h> // Defines for using service API
|
||
|
||
#include <smbtypes.h> // needed for smb.h
|
||
#include <smb.h> // Server Message Block definition
|
||
#include <netlib.h> // UNUSED macro
|
||
#include <align.h> // ROUND_UP_POINTER
|
||
|
||
#include "msgdbg.h" // MSG_LOG
|
||
#include <svcs.h> // Intrinsic service data
|
||
|
||
GLOBAL_DATA GlobalData;
|
||
|
||
HANDLE wakeupEvent = 0; // Master copy of wakeup event
|
||
HANDLE GrpMailslotHandle = INVALID_HANDLE_VALUE; // Event to signal mailslot has data
|
||
PHANDLE wakeupSem; // Semaphores to clear on NCB completion
|
||
|
||
|
||
//
|
||
// Other Global Data
|
||
//
|
||
// The other misc. global data that the messenger uses.
|
||
//
|
||
|
||
DWORD MsgsvcDebugLevel; // Debug level flag used by MSG_LOG
|
||
|
||
LPTSTR MessageFileName;
|
||
|
||
//
|
||
// The local machine name and length/
|
||
//
|
||
TCHAR machineName[NCBNAMSZ+sizeof(TCHAR)];
|
||
SHORT MachineNameLen;
|
||
|
||
SHORT mgid; // The message group i.d. counter
|
||
|
||
//
|
||
// The following is used to keep store the state of the messenger service
|
||
// Either it is RUNNING or STOPPING.
|
||
//
|
||
DWORD MsgrState;
|
||
|
||
|
||
|
||
//
|
||
// Handle returned by RegisterServiceCtrlHandle and needed to
|
||
// set the service status via SetServiceStatus
|
||
//
|
||
SERVICE_STATUS_HANDLE MsgrStatusHandle;
|
||
|
||
|
||
//
|
||
// This string is used to mark the location of the time string in
|
||
// a message header so that the display thread can find after it reads
|
||
// it from the queue.
|
||
//
|
||
LPSTR GlobalTimePlaceHolder = "***";
|
||
LPWSTR GlobalTimePlaceHolderUnicode = L"***";
|
||
|
||
//
|
||
// This is the string used in the title bar of the Message Box used
|
||
// to display messages.
|
||
// GlobalMessageBoxTitle will either point to the default string, or
|
||
// to the string allocated in the FormatMessage Function.
|
||
//
|
||
WCHAR DefaultMessageBoxTitle[]= L"Messenger Service";
|
||
LPWSTR GlobalAllocatedMsgTitle=NULL;
|
||
LPWSTR GlobalMessageBoxTitle=DefaultMessageBoxTitle;
|
||
|
||
//
|
||
// This is where well-known SIDs and pointers to RpcServer routines are
|
||
// stored.
|
||
//
|
||
PSVCHOST_GLOBAL_DATA MsgsvcGlobalData;
|
||
|
||
|
||
//
|
||
// Functions
|
||
//
|
||
// The following routines are defined for creating and destroying the
|
||
// data (arrays, etc.) defined above.
|
||
//
|
||
|
||
/* MsgInitSupportSeg
|
||
*
|
||
* Allocates and initializes the segment containing the Support
|
||
* arrays.
|
||
*
|
||
*/
|
||
|
||
NET_API_STATUS
|
||
MsgInitSupportSeg(VOID)
|
||
{
|
||
|
||
unsigned int size;
|
||
DWORD i;
|
||
char far * memPtr;
|
||
DWORD status;
|
||
|
||
//
|
||
// Calculate the buffer size.
|
||
// *ALIGNMENT* (Note the extra four bytes for alignment)
|
||
//
|
||
|
||
size = ((SD_NUMNETS() + 1) * sizeof(HANDLE));
|
||
|
||
wakeupSem = (PHANDLE) LocalAlloc(LMEM_ZEROINIT, size);
|
||
if (wakeupSem == NULL) {
|
||
status = GetLastError();
|
||
MSG_LOG(ERROR,"[MSG]InitSupportSeg:LocalAlloc Failure %X\n", status);
|
||
return(status);
|
||
}
|
||
|
||
return (NERR_Success);
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
MsgFreeSupportSeg(VOID)
|
||
{
|
||
HANDLE status;
|
||
|
||
status = LocalFree (wakeupSem);
|
||
if (status != 0) {
|
||
MSG_LOG(ERROR,"FreeSupportSeg:LocalFree Failed %X\n",
|
||
GetLastError());
|
||
}
|
||
wakeupSem = NULL;
|
||
return;
|
||
}
|
||
|
||
|
||
BOOL
|
||
MsgDatabaseLock(
|
||
IN MSG_LOCK_REQUEST request,
|
||
IN LPSTR idString
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all access to the Messenger Service database
|
||
lock. This lock is used to protect access in the shared data segment.
|
||
|
||
Reading the Database is handled with shared access. This allows several
|
||
threads to read the database at the same time.
|
||
|
||
Writing (or modifying) the database is handled with exclusive access.
|
||
This access is not granted if other threads have read access. However,
|
||
shared access can be made into exclusive access as long as no other
|
||
threads have shared or exclusive access.
|
||
|
||
Arguments:
|
||
|
||
request - This indicates what should be done with the lock. Lock
|
||
requests are listed in dataman.h
|
||
|
||
idString - This is a string that identifies who is requesting the lock.
|
||
This is used for debugging purposes so I can see where in the code
|
||
a request is coming from.
|
||
|
||
Return Value:
|
||
|
||
none:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fRet = TRUE;
|
||
NTSTATUS status;
|
||
|
||
static RTL_RESOURCE MSG_DatabaseLock;
|
||
static BOOL s_fInitialized;
|
||
|
||
switch(request) {
|
||
|
||
case MSG_INITIALIZE:
|
||
|
||
if (!s_fInitialized)
|
||
{
|
||
status = MsgInitResource(&MSG_DatabaseLock);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
MSG_LOG1(ERROR,
|
||
"MsgDatabaseLock: MsgInitResource failed %#x\n",
|
||
status);
|
||
|
||
fRet = FALSE;
|
||
}
|
||
else
|
||
{
|
||
s_fInitialized = TRUE;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case MSG_GET_SHARED:
|
||
MSG_LOG(LOCKS,"%s:Asking for MSG Database Lock shared...\n",idString);
|
||
fRet = RtlAcquireResourceShared( &MSG_DatabaseLock, TRUE );
|
||
MSG_LOG(LOCKS,"%s:Acquired MSG Database Lock shared\n",idString);
|
||
break;
|
||
|
||
case MSG_GET_EXCLUSIVE:
|
||
MSG_LOG(LOCKS,"%s:Asking for MSG Database Lock exclusive...\n",idString);
|
||
fRet = RtlAcquireResourceExclusive( &MSG_DatabaseLock, TRUE );
|
||
MSG_LOG(LOCKS,"%s:Acquired MSG Database Lock exclusive\n",idString);
|
||
break;
|
||
|
||
case MSG_RELEASE:
|
||
MSG_LOG(LOCKS,"%s:Releasing MSG Database Lock...\n",idString);
|
||
RtlReleaseResource( &MSG_DatabaseLock );
|
||
MSG_LOG(LOCKS,"%s:Released MSG Database Lock\n",idString);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return fRet;
|
||
}
|
||
|
||
|
||
BOOL
|
||
MsgConfigurationLock(
|
||
IN MSG_LOCK_REQUEST request,
|
||
IN LPSTR idString
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles all access to the Messenger Service Pnp Configuration
|
||
lock. This lock is used to protect access in the shared data segment.
|
||
|
||
Reading the Database is handled with shared access. This allows several
|
||
threads to read the database at the same time.
|
||
|
||
Writing (or modifying) the database is handled with exclusive access.
|
||
This access is not granted if other threads have read access. However,
|
||
shared access can be made into exclusive access as long as no other
|
||
threads have shared or exclusive access.
|
||
|
||
Arguments:
|
||
|
||
request - This indicates what should be done with the lock. Lock
|
||
requests are listed in dataman.h
|
||
|
||
idString - This is a string that identifies who is requesting the lock.
|
||
This is used for debugging purposes so I can see where in the code
|
||
a request is coming from.
|
||
|
||
Return Value:
|
||
|
||
none:
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fRet = TRUE;
|
||
NTSTATUS status;
|
||
|
||
static RTL_RESOURCE MSG_ConfigurationLock;
|
||
static BOOL s_fInitialized;
|
||
|
||
switch(request) {
|
||
|
||
case MSG_INITIALIZE:
|
||
if (!s_fInitialized)
|
||
{
|
||
status = MsgInitResource(&MSG_ConfigurationLock);
|
||
|
||
if (!NT_SUCCESS(status))
|
||
{
|
||
MSG_LOG1(ERROR,
|
||
"MsgConfigurationLock: MsgInitResource failed %#x\n",
|
||
status);
|
||
|
||
fRet = FALSE;
|
||
}
|
||
else
|
||
{
|
||
s_fInitialized = TRUE;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case MSG_GET_SHARED:
|
||
MSG_LOG(LOCKS,"%s:Asking for MSG Configuration Lock shared...\n",idString);
|
||
fRet = RtlAcquireResourceShared( &MSG_ConfigurationLock, TRUE );
|
||
MSG_LOG(LOCKS,"%s:Acquired MSG Configuration Lock shared\n",idString);
|
||
break;
|
||
|
||
case MSG_GET_EXCLUSIVE:
|
||
MSG_LOG(LOCKS,"%s:Asking for MSG Configuration Lock exclusive...\n",idString);
|
||
fRet = RtlAcquireResourceExclusive( &MSG_ConfigurationLock, TRUE );
|
||
MSG_LOG(LOCKS,"%s:Acquired MSG Configuration Lock exclusive\n",idString);
|
||
break;
|
||
|
||
case MSG_RELEASE:
|
||
MSG_LOG(LOCKS,"%s:Releasing MSG Configuration Lock...\n",idString);
|
||
RtlReleaseResource( &MSG_ConfigurationLock );
|
||
MSG_LOG(LOCKS,"%s:Released MSG Configuration Lock\n",idString);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return fRet;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MsgInitCriticalSection(
|
||
PRTL_CRITICAL_SECTION pCritsec
|
||
)
|
||
{
|
||
NTSTATUS ntStatus;
|
||
|
||
//
|
||
// RtlInitializeCriticalSection will raise an exception
|
||
// if it runs out of resources
|
||
//
|
||
|
||
try
|
||
{
|
||
ntStatus = RtlInitializeCriticalSection(pCritsec);
|
||
|
||
if (!NT_SUCCESS(ntStatus))
|
||
{
|
||
MSG_LOG1(ERROR,
|
||
"MsgInitCriticalSection: RtlInitializeCriticalSection failed %#x\n",
|
||
ntStatus);
|
||
}
|
||
}
|
||
except(EXCEPTION_EXECUTE_HANDLER)
|
||
{
|
||
MSG_LOG1(ERROR,
|
||
"MsgInitCriticalSection: Exception %#x caught initializing critsec\n",
|
||
GetExceptionCode());
|
||
|
||
ntStatus = STATUS_NO_MEMORY;
|
||
}
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MsgInitResource(
|
||
PRTL_RESOURCE pResource
|
||
)
|
||
{
|
||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
|
||
//
|
||
// RtlInitializeResource will raise an exception
|
||
// if it runs out of resources
|
||
//
|
||
|
||
try
|
||
{
|
||
RtlInitializeResource(pResource);
|
||
}
|
||
except(EXCEPTION_EXECUTE_HANDLER)
|
||
{
|
||
MSG_LOG1(ERROR,
|
||
"MsgInitResource: Exception %#x caught initializing resource\n",
|
||
GetExceptionCode());
|
||
|
||
ntStatus = STATUS_NO_MEMORY;
|
||
}
|
||
|
||
return ntStatus;
|
||
}
|