519 lines
12 KiB
C
519 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
LSAWMI.C
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implement LSA Server event tracing by using WMI trace infrastructure.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
16-March-1999 kumarp
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <lsapch2.h>
|
||
|
#include <wmistr.h>
|
||
|
#define INITGUID
|
||
|
#include <lsawmi.h>
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Globals
|
||
|
//
|
||
|
ULONG LsapEventTraceFlag = FALSE;
|
||
|
TRACEHANDLE LsapTraceRegistrationHandle = (TRACEHANDLE) 0;
|
||
|
TRACEHANDLE LsapTraceLoggerHandle = (TRACEHANDLE) 0;
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Forward declaration
|
||
|
//
|
||
|
|
||
|
ULONG
|
||
|
LsapTraceControlCallBack(
|
||
|
IN WMIDPREQUESTCODE RequestCode,
|
||
|
IN PVOID RequestContext,
|
||
|
IN OUT ULONG *InOutBufferSize,
|
||
|
IN OUT PVOID Buffer
|
||
|
);
|
||
|
|
||
|
LPWSTR
|
||
|
LsapMakeNullTerminatedString(
|
||
|
IN PUNICODE_STRING u
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// before you change the elements of the following structure,
|
||
|
// read notes in lsawmi.h file
|
||
|
//
|
||
|
TRACE_GUID_REGISTRATION LsapTraceGuids[] =
|
||
|
{
|
||
|
{&LsapTraceEventGuid_QuerySecret, NULL},
|
||
|
{&LsaTraceEventGuid_Close, NULL},
|
||
|
{&LsaTraceEventGuid_OpenPolicy, NULL},
|
||
|
{&LsaTraceEventGuid_QueryInformationPolicy, NULL},
|
||
|
{&LsaTraceEventGuid_SetInformationPolicy, NULL},
|
||
|
{&LsaTraceEventGuid_EnumerateTrustedDomains, NULL},
|
||
|
{&LsaTraceEventGuid_LookupNames, NULL},
|
||
|
{&LsaTraceEventGuid_LookupSids, NULL},
|
||
|
{&LsaTraceEventGuid_OpenTrustedDomain, NULL},
|
||
|
{&LsaTraceEventGuid_QueryInfoTrustedDomain, NULL},
|
||
|
{&LsaTraceEventGuid_SetInformationTrustedDomain, NULL},
|
||
|
{&LsaTraceEventGuid_QueryTrustedDomainInfoByName, NULL},
|
||
|
{&LsaTraceEventGuid_SetTrustedDomainInfoByName, NULL},
|
||
|
{&LsaTraceEventGuid_EnumerateTrustedDomainsEx, NULL},
|
||
|
{&LsaTraceEventGuid_CreateTrustedDomainEx, NULL},
|
||
|
{&LsaTraceEventGuid_QueryDomainInformationPolicy, NULL},
|
||
|
{&LsaTraceEventGuid_SetDomainInformationPolicy, NULL},
|
||
|
{&LsaTraceEventGuid_OpenTrustedDomainByName, NULL},
|
||
|
{&LsaTraceEventGuid_QueryForestTrustInformation, NULL},
|
||
|
{&LsaTraceEventGuid_SetForestTrustInformation, NULL},
|
||
|
{&LsaTraceEventGuid_LookupIsolatedNameInTrustedDomains, NULL},
|
||
|
};
|
||
|
|
||
|
|
||
|
#define LsapTraceGuidCount (sizeof(LsapTraceGuids) / sizeof(TRACE_GUID_REGISTRATION))
|
||
|
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
_stdcall
|
||
|
LsapInitializeWmiTrace( LPVOID ThreadParams )
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
|
||
|
Register WMI Trace Guids.
|
||
|
This routine is called during LSA initialization. LSA gets initialized
|
||
|
before WMI therefore we call this from a seaprate thread. This
|
||
|
thread can then wait on WMI.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
ThreadParams - Currently ignored.
|
||
|
|
||
|
Reture Values:
|
||
|
|
||
|
NTSTATUS - Standard Nt Result Code
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG Status = ERROR_SUCCESS;
|
||
|
HMODULE hModule;
|
||
|
TCHAR FileName[MAX_PATH+1];
|
||
|
DWORD nLen = 0;
|
||
|
|
||
|
#define RESOURCE_NAME TEXT("LsaMofResource")
|
||
|
#define IMAGE_PATH TEXT("lsass.exe")
|
||
|
|
||
|
LsapEnterFunc("LsapInitializeWmiTrace");
|
||
|
|
||
|
hModule = GetModuleHandle(IMAGE_PATH);
|
||
|
if (hModule != NULL) {
|
||
|
nLen = GetModuleFileName(hModule, FileName, MAX_PATH);
|
||
|
}
|
||
|
if (nLen == 0) {
|
||
|
lstrcpy(FileName, IMAGE_PATH);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Register Trace GUIDs
|
||
|
//
|
||
|
Status = RegisterTraceGuids(
|
||
|
LsapTraceControlCallBack,
|
||
|
NULL,
|
||
|
&LsapTraceControlGuid,
|
||
|
LsapTraceGuidCount,
|
||
|
LsapTraceGuids,
|
||
|
FileName,
|
||
|
RESOURCE_NAME,
|
||
|
&LsapTraceRegistrationHandle);
|
||
|
|
||
|
#if DBG
|
||
|
if (Status != ERROR_SUCCESS)
|
||
|
{
|
||
|
DebugLog(( DEB_ERROR, "LsapInitializeWmiTrace failed: 0x%x\n", Status));
|
||
|
}
|
||
|
#endif // DBG
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
ULONG
|
||
|
LsapTraceControlCallBack(
|
||
|
IN WMIDPREQUESTCODE RequestCode,
|
||
|
IN PVOID RequestContext,
|
||
|
IN OUT ULONG *InOutBufferSize,
|
||
|
IN OUT PVOID Buffer
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Call back function called by the WMI module to enable or
|
||
|
disable LSA tracing.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RequestCode - WMI_ENABLE_EVENTS or WMI_DISABLE_EVENTS
|
||
|
|
||
|
RequestContext - currently ignored
|
||
|
|
||
|
InOutBufferSize - size of data returned by this call back.
|
||
|
Currently always set to 0.
|
||
|
|
||
|
Buffer - pointer to data received. In case of WMI_ENABLE_EVENTS,
|
||
|
this is a pointer to the trace handle.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Win32 error code.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG Status = ERROR_SUCCESS;
|
||
|
|
||
|
LsapEnterFunc("LsapTraceControlCallBack");
|
||
|
|
||
|
switch (RequestCode)
|
||
|
{
|
||
|
case WMI_ENABLE_EVENTS:
|
||
|
{
|
||
|
LsapTraceLoggerHandle = GetTraceLoggerHandle(Buffer);
|
||
|
LsapEventTraceFlag = TRUE; // enable flag
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WMI_DISABLE_EVENTS:
|
||
|
{
|
||
|
LsapTraceLoggerHandle = (TRACEHANDLE) 0;
|
||
|
LsapEventTraceFlag = FALSE; // disable flag
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
Status = ERROR_INVALID_PARAMETER;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*InOutBufferSize = 0;
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
LsapStartWmiTraceInitThread(void)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Start the thread that registers WMI trace guids.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
NTSTATUS - Standard Nt Result Code
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS Status=STATUS_SUCCESS;
|
||
|
HANDLE ThreadHandle;
|
||
|
ULONG ThreadId = 0;
|
||
|
ULONG WinError;
|
||
|
|
||
|
ThreadHandle = CreateThread(NULL,
|
||
|
0,
|
||
|
LsapInitializeWmiTrace,
|
||
|
NULL,
|
||
|
0,
|
||
|
&ThreadId);
|
||
|
|
||
|
if (NULL == ThreadHandle)
|
||
|
{
|
||
|
Status = STATUS_UNSUCCESSFUL;
|
||
|
WinError = GetLastError();
|
||
|
DebugLog((DEB_ERROR, "Failed to create thread for LsapInitializeWmiTrace: 0x%x", WinError));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CloseHandle(ThreadHandle);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
LsapTraceEvent(
|
||
|
IN ULONG WmiEventType,
|
||
|
IN LSA_TRACE_EVENT_TYPE LsaTraceEventType
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine will do a WMI event trace.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
WmiEventType - Event Type, valid values are:
|
||
|
EVENT_TRACE_TYPE_START
|
||
|
EVENT_TRACE_TYPE_END
|
||
|
|
||
|
TraceGuid - Index in LsapTraceGuids[]
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LsapTraceEventWithData(WmiEventType,
|
||
|
LsaTraceEventType,
|
||
|
0,
|
||
|
NULL);
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
LsapTraceEventWithData(
|
||
|
IN ULONG WmiEventType,
|
||
|
IN LSA_TRACE_EVENT_TYPE LsaTraceEventType,
|
||
|
IN ULONG ItemCount,
|
||
|
IN PUNICODE_STRING Items OPTIONAL
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine will do a WMI event trace.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
WmiEventType - Event Type, valid values are:
|
||
|
EVENT_TRACE_TYPE_START
|
||
|
EVENT_TRACE_TYPE_END
|
||
|
EVENT_TRACE_TYPE_INFO
|
||
|
|
||
|
TraceGuid - Index in LsapTraceGuids[]
|
||
|
|
||
|
ItemCount - the number of elements in Items
|
||
|
|
||
|
Items - an array of information. The unicode strings don't have
|
||
|
to represent strings -- can be binary data whose length
|
||
|
is denoted by the Length field.
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#if DBG
|
||
|
ULONG WinError;
|
||
|
#endif
|
||
|
|
||
|
WCHAR NullChar = UNICODE_NULL;
|
||
|
PVOID BuffersToFree[10];
|
||
|
ULONG BuffersToFreeCount = 0;
|
||
|
ULONG i;
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
EVENT_TRACE_HEADER EventTrace;
|
||
|
MOF_FIELD EventInfo[2];
|
||
|
} Event;
|
||
|
|
||
|
//
|
||
|
// Theoretically, only test LsapEventTraceFlag would be enough, since
|
||
|
// LsapEventTraceFlag will remain FALSE in Registry Mode, because
|
||
|
// LsapInitializeTrace() will never been called in Registry Mode.
|
||
|
// Thus nobody will change the value of LsapEventTraceFlag
|
||
|
//
|
||
|
if (!LsapEventTraceFlag) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Fill the event information.
|
||
|
//
|
||
|
ZeroMemory(&Event, sizeof(Event));
|
||
|
Event.EventTrace.GuidPtr = (ULONGLONG) LsapTraceGuids[LsaTraceEventType].Guid;
|
||
|
Event.EventTrace.Class.Type = (UCHAR) WmiEventType;
|
||
|
Event.EventTrace.Flags |= (WNODE_FLAG_USE_GUID_PTR | // GUID is actually a pointer
|
||
|
WNODE_FLAG_TRACED_GUID); // denotes a trace
|
||
|
Event.EventTrace.Size = sizeof(Event.EventTrace); // no other parameters/information
|
||
|
|
||
|
|
||
|
if ( (LsaTraceEventType == LsaTraceEvent_LookupIsolatedNameInTrustedDomains) ) {
|
||
|
|
||
|
//
|
||
|
// Add the flag that indicates that there is more data
|
||
|
//
|
||
|
Event.EventTrace.Flags |= WNODE_FLAG_USE_MOF_PTR;
|
||
|
|
||
|
//
|
||
|
// Make sure enough space has been allocated on the stack for us
|
||
|
//
|
||
|
ASSERT(sizeof(Event.EventInfo) >= (sizeof(MOF_FIELD) * 2));
|
||
|
ASSERT( (ItemCount == 2) && (Items != NULL) );
|
||
|
|
||
|
//
|
||
|
// Fill in the data requested
|
||
|
//
|
||
|
for (i = 0; i < ItemCount; i++) {
|
||
|
|
||
|
LPWSTR String = NULL;
|
||
|
ULONG Length;
|
||
|
|
||
|
//
|
||
|
// Re'alloc to get a NULL terminated string
|
||
|
//
|
||
|
String = LsapMakeNullTerminatedString(&Items[i]);
|
||
|
if (NULL == String) {
|
||
|
String = &NullChar;
|
||
|
Length = sizeof(NullChar);
|
||
|
} else {
|
||
|
Length = Items[i].Length + sizeof(WCHAR);
|
||
|
}
|
||
|
Event.EventInfo[i].Length = Length;
|
||
|
Event.EventInfo[i].DataPtr = (ULONGLONG)String;
|
||
|
Event.EventTrace.Size += sizeof(Event.EventInfo[i]);
|
||
|
|
||
|
if (&NullChar != String) {
|
||
|
ASSERT(BuffersToFreeCount < sizeof(BuffersToFree)/sizeof(BuffersToFree[0]));
|
||
|
BuffersToFree[BuffersToFreeCount++] = String;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
WinError =
|
||
|
#endif
|
||
|
TraceEvent(LsapTraceLoggerHandle, (PEVENT_TRACE_HEADER) &Event);
|
||
|
|
||
|
#if DBG
|
||
|
if (WinError != ERROR_SUCCESS)
|
||
|
{
|
||
|
DebugLog(( DEB_ERROR, "WMI TraceEvent failed, status %x\n", WinError));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
for (i = 0; i < BuffersToFreeCount; i++) {
|
||
|
LsapFreeLsaHeap(BuffersToFree[i]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
LsapGetClientNetworkAddress(
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns a NULL terminated string that represents the network
|
||
|
address of the client. If the address cannot be obtained, NULL is returned.
|
||
|
If the return value is non-NULL, the string must be freed with
|
||
|
RpcStringFreeW.
|
||
|
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
See description.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG RpcStatus;
|
||
|
RPC_BINDING_HANDLE ServerBinding = NULL;
|
||
|
PWSTR StringBinding = NULL;
|
||
|
LPWSTR NetworkAddr = NULL;
|
||
|
|
||
|
RpcStatus = RpcBindingServerFromClient(NULL, &ServerBinding);
|
||
|
|
||
|
if (RPC_S_OK == RpcStatus) {
|
||
|
|
||
|
RpcStatus = RpcBindingToStringBindingW(ServerBinding, &StringBinding);
|
||
|
|
||
|
if (RPC_S_OK == RpcStatus) {
|
||
|
|
||
|
RpcStatus = RpcStringBindingParseW(StringBinding,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&NetworkAddr,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
RpcStringFreeW(&StringBinding);
|
||
|
}
|
||
|
|
||
|
RpcBindingFree(&ServerBinding);
|
||
|
|
||
|
}
|
||
|
|
||
|
return NetworkAddr;
|
||
|
}
|
||
|
|
||
|
|
||
|
LPWSTR
|
||
|
LsapMakeNullTerminatedString(
|
||
|
IN PUNICODE_STRING u
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine returns a NULL terminated string composed of the data in
|
||
|
u. The string must be freed with LsapFreeLsaHeap().
|
||
|
|
||
|
If u->Length is 0, a non-NULL string with the NULL character as the first
|
||
|
character is returned.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
u -- a unicode string
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
See description.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LPWSTR String = NULL;
|
||
|
ULONG Length;
|
||
|
if (u) {
|
||
|
Length = u->Length + sizeof(WCHAR);
|
||
|
String = LsapAllocateLsaHeap(Length);
|
||
|
if (String != NULL) {
|
||
|
RtlCopyMemory(String, u->Buffer, u->Length);
|
||
|
String[u->Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||
|
}
|
||
|
}
|
||
|
return String;
|
||
|
}
|