Wait-Chain Traversal: Or, How We Can Use PowerShell to JIT C# to Load an Unmanaged Assembly (C++), InterOping With Windows APIs, Returning that Data Back to PowerShell

So, as the long-winded title infers, today I’ll be covering something that I wrote a long time ago and have recently re-written (albeit, probably badly) for you to use and/or learn from.

In this case, we’re using a PowerShell script, which JITs C# code, the C# code calls into an unmanaged DLL (C++), and that calls into an Windows API. Once the data has been obtained from the Windows API, we pass the data back from the unmanaged assembly to the managed code (via Marshal) and then return that back to the PowerShell instance to be displayed to the user.

Before we dive into the what we’re doing, we should cover some key concepts. The first is JIT’ing. JIT stands for “Just-In-Time” (Compilation) and the name is slightly a misnomer but we’ll cover that in a second. So, in JIT, what happens is that the run time precompiles the code before it’s ran. This is important because a key-concept in exception handling is the runtime’s seek operation to find a handler for an exception that is thrown. You’ll often see this as a FirstChanceException in a dump file. In PowerShell, we have the added ability to leverage the JIT compilation by passing source code as a type into the App’s Domain. It’s important to distinguish that once the App Domain has been disposed of, the type specified is lost and has to be re-instantiated again.

So, what – exactly – is this code going to be doing? Well, since Windows Vista, the Windows Operating System exposes the Wait Chain Traversal API. You can see a demonstration of this API in Task Manager: Go to the Details tab, right click on a process and click “Analyze Wait Chain”.

Since Windows Server 2016 Core doesn’t include a desktop or any GUI interfaces, a more robust way was needed to obtain the same information in production, to determine if the reason an application wasn’t responding or performing work was because the threads were blocked.

When you run the code, you can tell if this is the case or not by something like the following:

12972   [7464:12972:blocked]->[ThreadWait]->[7464:12968:blocked]->[End]

Where the first thread is blocked by a thread wait on the the second thread, which is also (itself) blocked.

So, first things first, the PowerShell code. Take a peek here to see that. Note that the Source code is contained with a specific character-delimited string @”<code>”@. After that we add a Type, pointing it to the source code we’ve defined and referencing the assemblies that we’ll need for this type to work. Worthy of noting is that when we add this type, it is exposed in PowerShell the same way any normal .NET type is, via the []:: convention.

Note that in the C# source we import the unmanaged DLL and reference the exposed method. In the body of the code, we also construct an IntPtr to reference for the return. So, now, we get to Marshalling.

An IntPtr is, quite literally, a pointer or handle to an object. A pointer is a reference to memory where an object exists and the object is typically delimited by characters to signify the termination of it (e.g.: the end of a string is null-terminated). A handle is roughly the same premise but the handle abstracts memory management from the caller. So, at 200 ticks, the handle could point to address 0x000001 and at 369 ticks, it could point to 0x34778.

Alright, so why this matters is because when we pass from unmanaged code back to managed code, there’s nothing that implicitly tells the managed code where to find the object in native memory; so, we have to pass a pointer to the object back to managed (I believe managed creates it’s own copy and creates an address for that object) and, using that, we can then try to convert the passed object from a native string into a managed string (via Marshalling).

What about this unmanaged code I keep hearing about? Oh, well… You can find that here. Don’t forget to add the headers referenced in stdafx.h, or your compiler will cry bloody murder.

So, how this works is: The script is called via PowerShell. After some magic to verify that we weren’t given junk data, then PowerShell JIT’s the C# code and performs the runtime operations. The compiler loads the unmanaged DLL into memory. The C# code then calls into the unmanaged DLL via the exposed method (declspec/dllexport/cdecl). The unmanaged code performs it’s work and returns the string back to the caller – unaware that the caller is managed code. The managed code creates an IntPtr to reference the return and then Marshal is called to convert the native string into a managed string. This is then returned back to the user. In the case of multiple instances of a process, the managed string is added to an array and that array is returned.

While it may not seem like much and seem like overglorified complication just to check for threads on wait chaings, it was code that was written to be used in production where we had no desktop environments and we had to determine if this was the case.

I hope that someone gets some kind of use out of it. 🙂

Until next time.

Windows PowerShell: Discovering and Resolving Neighbours in Your Network

Have you ever wanted to find out which computers are on your local network, what their IP addresses are (if you’re using DHCP), and what their hostnames are? Well, I’ve written a PowerShell script to do just that!

You can find it on GitHub, here.

Essentially, the script does one of two things.

If the Prefix parameter is supplied, it attempts to find all hosts in the last octet range (0-255) that are up (e.g.: that respond to pings) and then uses DNS to attempt to resolve the IP address to a known hostname. This can be especially useful for things like trying to find your Plex server, if your router has restarted and you don’t have a static IP address assigned for it.

If the Prefix parameter is not supplied, we attempt to obtain the first IP address available to the system (indexing by zero from the array) and use that range (e.g.: 192.168.0.x) to find the local hosts that are up (e.g.: responding to pings) and attempt to resolve their names in DNS.

The script takes some time to process the entire range and that’s because I didn’t want to deal with trying to add to a collection in a thread-safe manner due to parallelisation in PowerShell. It would be easy enough to do in C# and, if there’s a lot of interest in that, I could devote some time to writing this to be a dynamic-link library, instead.

For now, I hope it does someone some good, at the very least. 🙂

How msExchRecipientDisplayType and msExchangeRecipientTypeDetails Relate to Your On-Premises

Addendum:

It has come to my attention that an explanation of how the values are calculated is necessary in order to help you understand why you would have “differing” values than those defined in the table below.

First, you need to understand what bitwise flags are. Essentially, bitwise flags allow you to have multiple values for an enum type, based on their sum. The linked article discussing bitwise flags on enumerators gives code examples of how and why this might be done.

Second, the specific reason why we give you the hex value is so that you can do the calculation to determine what enum values satisfy the property’s value (as the integer representation that you’re seeing).

So, in the specific example that was presented to me, a customer couldn’t understand why they would have a value of ’97’ for the RemoteRecipientType. In this case, it would be the values of SharedMailbox (0x60) and ProvisionedMailbox (0x1) being added together (meaning/inferring that the mailbox is a shared mailbox that was provisioned in the cloud and was not migrated from on-premises).

0x60 [96] + 0x1 [1] = 0x61 [97]

If needed, you can use PowerShell and it will convert the sum of the hex numbers to an integer value for you, automatically. Try the following in PowerShell to see what I mean: 0x60 + 0x1

Original Post:

Often, in O365, there’s a reference field we use to specify what a recipient type is, as far as on-premises AD/Exchange is concerned. If you weren’t already aware, this is how the attributes relate:

Recipient Display Type = msExchRecipientDisplayType
Recipient Type Details = msExchRecipientTypeDetails

Like many other Active Directory Attributes, these are represented by Integer Values in Active Directory. One important item to note here is that you do not want to arbitrarily change these values: the Recipient Display Type is something that should only be set by Exchange. Changing it via any other method is not supported.

Here is how the Recipient Display Type Breaks down:

Display Type Value
MailboxUser 0
DistributionGroup 1
PublicFolder 2
DynamicDistributionGroup 3
Organization 4
PrivateDistributionList 5
RemoteMailUser 6
ConferenceRoomMailbox 7
EquipmentMailbox 8
ArbitrationMailbox 10
MailboxPlan 11
LinkedUser 12
RoomList 15
SecurityDistributionGroup 1073741833
ACLableMailboxUser 1073741824
ACLableRemoteMailUser 1073741830
SyncedUSGasUDG -2147481343
SyncedUSGasUSG -1073739511
SyncedUSGasContact -2147481338
ACLableSyncedUSGasContact -1073739514
SyncedDynamicDistributionGroup -2147482874
ACLableSyncedMailboxUser -1073741818
SyncedMailboxUser -2147483642
SyncedConferenceRoomMailbox -2147481850
SyncedEquipmentMailbox -2147481594
SyncedRemoteMailUser -2147482106
ACLableSyncedRemoteMailUser -1073740282
SyncedPublicFolder -2147483130

Here is how the Recipient Type Details breaks down:

Value Name RecipientTypeDetails (Decimal Value)
None 0
UserMailbox 1
LinkedMailbox 2
SharedMailbox 4
LegacyMailbox 8
RoomMailbox 16
EquipmentMailbox 32
MailContact 64
MailUser 128
MailUniversalDistributionGroup 256
MailNonUniversalGroup 512
MailUniversalSecurityGroup 1024
DynamicDistributionGroup 2048
PublicFolder 4096
SystemAttendantMailbox 8192
SystemMailbox 16384
MailForestContact 32768
User 65536
Contact 131072
UniversalDistributionGroup 262144
UniversalSecurityGroup 524288
NonUniversalGroup 1048576
DisabledUser 2097152
MicrosoftExchange 4194304
ArbitrationMailbox 8388608
MailboxPlan 16777216
LinkedUser 33554432
RoomList 268435456
DiscoveryMailbox 536870912
RoleGroup 1073741824
RemoteUserMailbox 2147483648
Computer 4294967296
RemoteRoomMailbox 8589934592
RemoteEquipmentMailbox 17179869184
RemoteSharedMailbox 34359738368
PublicFolderMailbox 68719476736
TeamMailbox 137438953472
RemoteTeamMailbox 274877906944
MonitoringMailbox 549755813888
GroupMailbox 1099511627776
LinkedRoomMailbox 2199023255552
AuditLogMailbox 4398046511104
RemoteGroupMailbox 8796093022208
SchedulingMailbox 17592186044416
GuestMailUser 35184372088832
AuxAuditLogMailbox 70368744177664
SupervisoryReviewPolicyMailbox 140737488355328

Here is how the Remote Recipient Types break-down (thanks to cstep for this piece):

Decimal Value Hex Value Value Name
1 0x1 ProvisionedMailbox (Cloud MBX)
2 0x2 ProvisionedArchive (Cloud Archive)
3 0x3 ProvisionedMailbox, ProvisionedArchive (Cloud MBX & Cloud Archive)
4 0x4 Migrated
6 0x6 Migrated, ProvisionedArchive (Migrated MBX & Cloud Archive)
8 0x8 DeprovisionMailbox
16 0x10 DeprovisionArchive
20 0x14 DeprovisionArchive, Migrated
32 0x20 RoomMailbox
36 0x24 Migrated, RoomMailbox
64 0x40 EquipmentMailbox
68 0x44 Migrated, EquipmentMailbox
96 0x60 SharedMailbox
100 0x64 Migrated, SharedMailbox