29 #define DNATNC_STRUCTURE 0
31 #define DNATNC_FLAGS 2
33 #define DNATNC_NATIVEPATH 4
34 #define DNATNC_MAXIMUM 5
36 #define DNA_TYPE_CLR 1
37 #define DNA_TYPE_APPDOMAIN 2
38 #define DNA_TYPE_ASSEMBLY 3
40 typedef struct _DNA_NODE
44 struct _DNA_NODE *Parent;
78 typedef struct _ASMPAGE_CONTEXT
87 LONG TraceHandleActive;
88 TRACEHANDLE TraceHandle;
95 typedef struct _FLAG_DEFINITION
102 _In_ LPCGUID ProviderId,
103 _In_opt_ LPCGUID SourceId,
104 _In_ TRACEHANDLE TraceHandle,
105 _In_ ULONG IsEnabled,
107 _In_ ULONGLONG MatchAnyKeyword,
108 _In_ ULONGLONG MatchAllKeyword,
109 _In_ ULONG EnableProperty,
110 _In_opt_ PEVENT_FILTER_DESCRIPTOR EnableFilterDesc
121 static GUID ClrRuntimeProviderGuid = { 0xe13c0d23, 0xccbc, 0x4e12, { 0x93, 0x1b, 0xd9, 0xcc, 0x2e, 0xee, 0x27, 0xe4 } };
122 static GUID ClrRundownProviderGuid = { 0xa669021c, 0xc450, 0x4609, { 0xa0, 0x35, 0x5a, 0xf5, 0x9a, 0xf4, 0xdf, 0x18 } };
127 { L
"Executable", 0x2 },
133 { L
"DomainNeutral", 0x1 },
136 { L
"Collectible", 0x8 }
141 { L
"DomainNeutral", 0x1 },
149 { L
"ManagedExe", 0x1 },
150 { L
"HostedCLR", 0x2 },
152 { L
"ComActivated", 0x8 },
158 { L
"CONCURRENT_GC", 0x1 },
159 { L
"LOADER_OPTIMIZATION_SINGLE_DOMAIN", 0x2 },
160 { L
"LOADER_OPTIMIZATION_MULTI_DOMAIN", 0x4 },
161 { L
"LOADER_SAFEMODE", 0x10 },
162 { L
"LOADER_SETPREFERENCE", 0x100 },
163 { L
"SERVER_GC", 0x1000 },
164 { L
"HOARD_GC_VM", 0x2000 },
165 { L
"SINGLE_VERSION_HOSTING_INTERFACE", 0x4000 },
166 { L
"LEGACY_IMPERSONATION", 0x10000 },
167 { L
"DISABLE_COMMITTHREADSTACK", 0x20000 },
168 { L
"ALWAYSFLOW_IMPERSONATION", 0x40000 },
169 { L
"TRIM_GC_COMMIT", 0x80000 },
170 { L
"ETW", 0x100000 },
171 { L
"SERVER_BUILD", 0x200000 },
180 PropContext->PropContext,
198 if (Flags & Map[i].Flag)
217 node = PhAllocate(
sizeof(
DNA_NODE));
222 node->Node.TextCache = node->TextCache;
248 if (Node->u.Assembly.FullyQualifiedAssemblyName)
PhDereferenceObject(Node->u.Assembly.FullyQualifiedAssemblyName);
261 _In_ PWSTR DisplayName
268 node->IsFakeClr =
TRUE;
269 node->u.Clr.ClrInstanceID = 0;
270 node->u.Clr.DisplayName = NULL;
280 _In_ USHORT ClrInstanceID
285 for (i = 0; i < Context->NodeRootList->Count; i++)
287 PDNA_NODE node = Context->NodeRootList->Items[i];
289 if (!node->IsFakeClr && node->u.Clr.ClrInstanceID == ClrInstanceID)
298 _In_ ULONG64 AppDomainID
303 for (i = 0; i < ClrNode->Children->Count; i++)
305 PDNA_NODE node = ClrNode->Children->Items[i];
307 if (node->u.AppDomain.AppDomainID == AppDomainID)
316 _In_ ULONG64 AssemblyID
321 for (i = 0; i < AppDomainNode->Children->Count; i++)
323 PDNA_NODE node = AppDomainNode->Children->Items[i];
325 if (node->u.Assembly.AssemblyID == AssemblyID)
334 _In_ ULONG64 AssemblyID
340 for (i = 0; i < ClrNode->Children->Count; i++)
342 PDNA_NODE appDomainNode = ClrNode->Children->Items[i];
344 for (j = 0; j < appDomainNode->Children->Count; j++)
346 PDNA_NODE assemblyNode = appDomainNode->Children->Items[j];
348 if (assemblyNode->u.Assembly.AssemblyID == AssemblyID)
356 static int __cdecl AssemblyNodeNameCompareFunction(
357 _In_
const void *elem1,
358 _In_
const void *elem2
370 _In_opt_ PVOID Parameter1,
371 _In_opt_ PVOID Parameter2,
372 _In_opt_ PVOID Context
398 qsort(node->Children->Items, node->Children->Count,
sizeof(PVOID), AssemblyNodeNameCompareFunction);
412 isLeaf->
IsLeaf = node->Children->Count == 0;
421 switch (getCellText->
Id)
424 getCellText->
Text = node->StructureText;
456 getCellTooltip->
Text = node->u.Assembly.FullyQualifiedAssemblyName->sr;
472 if (GetKeyState(VK_CONTROL) < 0)
473 SendMessage(context->WindowHandle, WM_COMMAND,
ID_COPY, 0);
485 _Out_ PTRACEHANDLE SessionHandle,
486 _Out_ PEVENT_TRACE_PROPERTIES *Properties
491 PEVENT_TRACE_PROPERTIES properties;
492 TRACEHANDLE sessionHandle;
494 bufferSize =
sizeof(EVENT_TRACE_PROPERTIES) + DotNetLoggerName.
Length +
sizeof(WCHAR);
495 properties = PhAllocate(bufferSize);
496 memset(properties, 0,
sizeof(EVENT_TRACE_PROPERTIES));
498 properties->Wnode.BufferSize = bufferSize;
499 properties->Wnode.ClientContext = 2;
500 properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
501 properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY;
502 properties->LogFileNameOffset = 0;
503 properties->LoggerNameOffset =
sizeof(EVENT_TRACE_PROPERTIES);
505 result = StartTrace(&sessionHandle, DotNetLoggerName.Buffer, properties);
509 *SessionHandle = sessionHandle;
510 *Properties = properties;
514 else if (result == ERROR_ALREADY_EXISTS)
518 result = ControlTrace(0, DotNetLoggerName.Buffer, properties, EVENT_TRACE_CONTROL_QUERY);
526 *SessionHandle = properties->Wnode.HistoricalContext;
527 *Properties = properties;
540 _In_ PEVENT_TRACE_LOGFILE Buffer
547 _In_ PEVENT_RECORD EventRecord
551 PEVENT_HEADER eventHeader = &EventRecord->EventHeader;
552 PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor;
554 if (UlongToHandle(eventHeader->ProcessId) == context->ProcessItem->ProcessId)
558 switch (eventDescriptor->Id)
575 node->StructureText = node->u.Clr.DisplayName->sr;
581 if (startupFlagsString->
Length != 0 && startupModeString->
Length != 0)
587 else if (startupFlagsString->
Length != 0)
589 node->FlagsText = startupFlagsString;
592 else if (startupModeString->
Length != 0)
594 node->FlagsText = startupModeString;
607 SIZE_T appDomainNameLength;
608 USHORT clrInstanceID;
613 clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(
AppDomainLoadUnloadRundown_V1, AppDomainName) + appDomainNameLength +
sizeof(WCHAR) +
sizeof(ULONG));
628 node->StructureText = node->u.AppDomain.DisplayName->sr;
639 SIZE_T fullyQualifiedAssemblyNameLength;
640 USHORT clrInstanceID;
646 clrInstanceID = *(PUSHORT)((PCHAR)data + FIELD_OFFSET(
AssemblyLoadUnloadRundown_V1, FullyQualifiedAssemblyName) + fullyQualifiedAssemblyNameLength +
sizeof(WCHAR));
663 node->u.Assembly.AssemblyID = data->
AssemblyID;
667 if (!
PhSplitStringRefAtChar(&node->u.Assembly.FullyQualifiedAssemblyName->sr,
',', &node->StructureText, &remainingPart))
668 node->StructureText = node->u.Assembly.FullyQualifiedAssemblyName->sr;
681 SIZE_T moduleILPathLength;
682 PWSTR moduleNativePath;
683 SIZE_T moduleNativePathLength;
684 USHORT clrInstanceID;
688 moduleILPathLength =
PhCountStringZ(moduleILPath) *
sizeof(WCHAR);
689 moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength +
sizeof(WCHAR));
690 moduleNativePathLength =
PhCountStringZ(moduleNativePath) *
sizeof(WCHAR);
691 clrInstanceID = *(PUSHORT)((PCHAR)moduleNativePath + moduleNativePathLength +
sizeof(WCHAR));
704 if (moduleNativePathLength != 0)
711 if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1)
713 CloseTrace(context->TraceHandle);
721 if (eventDescriptor->Id == 0)
723 switch (eventDescriptor->Opcode)
729 SIZE_T moduleILPathLength;
730 PWSTR moduleNativePath;
731 SIZE_T moduleNativePathLength;
733 ULONG_PTR indexOfBackslash;
734 ULONG_PTR indexOfLastDot;
737 moduleILPathLength =
PhCountStringZ(moduleILPath) *
sizeof(WCHAR);
738 moduleNativePath = (PWSTR)((PCHAR)moduleILPath + moduleILPathLength +
sizeof(WCHAR));
739 moduleNativePathLength =
PhCountStringZ(moduleNativePath) *
sizeof(WCHAR);
741 if (context->ClrV2Node && (moduleILPathLength != 0 || moduleNativePathLength != 0))
748 if (moduleNativePathLength != 0)
749 node->NativePathText =
PhCreateStringEx(moduleNativePath, moduleNativePathLength);
757 if (indexOfBackslash != -1)
759 node->StructureText.Buffer = node->PathText->Buffer + indexOfBackslash + 1;
761 if (indexOfLastDot != -1 && indexOfLastDot > indexOfBackslash)
763 node->StructureText.Length = (indexOfLastDot - indexOfBackslash - 1) *
sizeof(WCHAR);
767 node->StructureText.Length = node->PathText->Length - indexOfBackslash *
sizeof(WCHAR) -
sizeof(WCHAR);
772 node->StructureText = node->PathText->sr;
781 if (_InterlockedExchange(&context->TraceHandleActive, 0) == 1)
783 CloseTrace(context->TraceHandle);
797 TRACEHANDLE traceHandle;
798 EVENT_TRACE_LOGFILE logFile;
800 memset(&logFile, 0,
sizeof(EVENT_TRACE_LOGFILE));
801 logFile.LoggerName = DotNetLoggerName.Buffer;
802 logFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
805 logFile.Context = Context;
807 traceHandle = OpenTrace(&logFile);
809 if (traceHandle == INVALID_PROCESSTRACE_HANDLE)
810 return GetLastError();
812 Context->TraceHandleActive = 1;
813 Context->TraceHandle = traceHandle;
814 result = ProcessTrace(&traceHandle, 1, NULL, NULL);
816 if (_InterlockedExchange(&Context->TraceHandleActive, 0) == 1)
818 CloseTrace(traceHandle);
832 TRACEHANDLE sessionHandle;
833 PEVENT_TRACE_PROPERTIES properties;
836 if (!EnableTraceEx_I)
838 if (!EnableTraceEx_I)
839 return ERROR_NOT_SUPPORTED;
847 guidToEnable = &ClrRundownProviderGuid;
849 guidToEnable = &ClrRuntimeProviderGuid;
856 TRACE_LEVEL_INFORMATION,
865 ControlTrace(sessionHandle, NULL, properties, EVENT_TRACE_CONTROL_STOP);
879 return STATUS_SUCCESS;
885 _In_opt_ PLARGE_INTEGER Timeout
889 BOOLEAN timeout =
FALSE;
896 Context->TraceClrV2 = ClrV2;
897 Context->TraceResult = 0;
898 Context->TraceHandleActive = 0;
899 Context->TraceHandle = 0;
903 if (NtWaitForSingleObject(threadHandle,
FALSE, Timeout) != STATUS_WAIT_0)
908 if (_InterlockedExchange(&Context->TraceHandleActive, 0) == 1)
910 CloseTrace(Context->TraceHandle);
914 NtWaitForSingleObject(threadHandle,
FALSE, NULL);
917 NtClose(threadHandle);
920 return ERROR_TIMEOUT;
922 return Context->TraceResult;
950 LPPROPSHEETPAGE propSheetPage;
957 context = propPageContext->
Context;
970 LARGE_INTEGER timeout;
975 propPageContext->
Context = context;
976 context->WindowHandle = hwndDlg;
977 context->ProcessItem = processItem;
979 context->ClrVersions = 0;
985 tnHandle = GetDlgItem(hwndDlg,
IDC_LIST);
986 context->TnHandle = tnHandle;
1004 SetCursor(LoadCursor(NULL, IDC_WAIT));
1008 PhShowMessage(hwndDlg, MB_ICONWARNING | MB_YESNO, L
".NET assembly enumeration may not work properly because the process is currently suspended. Do you want to continue?") == IDYES
1011 BOOLEAN timeoutReached =
FALSE;
1012 BOOLEAN nonClrNode =
FALSE;
1032 if (result == ERROR_TIMEOUT)
1034 timeoutReached =
TRUE;
1035 result = ERROR_SUCCESS;
1043 if (result == ERROR_TIMEOUT)
1045 timeoutReached =
TRUE;
1046 result = ERROR_SUCCESS;
1055 for (i = 0; i < context->NodeList->Count; i++)
1057 PDNA_NODE node = context->NodeList->Items[i];
1067 result = ERROR_TIMEOUT;
1072 result = ERROR_INSTALL_SUSPEND;
1076 SetCursor(LoadCursor(NULL, IDC_ARROW));
1080 ShowWindow(tnHandle, SW_HIDE);
1081 ShowWindow(GetDlgItem(hwndDlg,
IDC_ERROR), SW_SHOW);
1083 if (result == ERROR_ACCESS_DENIED)
1085 SetDlgItemText(hwndDlg,
IDC_ERROR, L
"Unable to start the event tracing session. Make sure Process Hacker is running with administrative privileges.");
1087 else if (result == ERROR_INSTALL_SUSPEND)
1089 SetDlgItemText(hwndDlg,
IDC_ERROR, L
"Unable to start the event tracing session because the process is suspended.");
1091 else if (result == ERROR_TIMEOUT)
1093 SetDlgItemText(hwndDlg,
IDC_ERROR, L
"The event tracing session timed out.");
1112 for (i = 0; i < context->NodeList->Count; i++)
1136 switch (LOWORD(wParam))