windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/msgsvc/server/data.c
2020-09-26 16:20:57 +08:00

398 lines
9.9 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************/
/** 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;
}