Skip to content

Commit 3bd7236

Browse files
mjr4077auDanGough
authored andcommitted
Add in C#-based method to retrieve domain information as part of CIM code removal.
1 parent 3a55917 commit 3bd7236

6 files changed

Lines changed: 156 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace PSADT.Interop
2+
{
3+
/// <summary>
4+
/// Specifies the status of a computer's membership in a workgroup or domain.
5+
/// </summary>
6+
/// <remarks>This enumeration is typically used to indicate whether a computer is joined to a domain, a
7+
/// workgroup, or is unjoined. The values correspond to the possible states returned by network management APIs when
8+
/// querying the join status of a system.</remarks>
9+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1008:Enums should have zero value", Justification = "There is no zero value in the Win32 API for this.")]
10+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "This is named as per the Win32 API.")]
11+
public enum NETSETUP_JOIN_STATUS
12+
{
13+
/// <summary>
14+
/// Domain join status of the machine is unknown.
15+
/// </summary>
16+
NetSetupUnknownStatus = Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS.NetSetupUnknownStatus,
17+
18+
/// <summary>
19+
/// Machine is not joined to a domain or to a workgroup.
20+
/// </summary>
21+
NetSetupUnjoined = Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS.NetSetupUnjoined,
22+
23+
/// <summary>
24+
/// Machine is joined to a workgroup.
25+
/// </summary>
26+
NetSetupWorkgroupName = Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS.NetSetupWorkgroupName,
27+
28+
/// <summary>
29+
/// Machine is joined to a domain.
30+
/// </summary>
31+
NetSetupDomainName = Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS.NetSetupDomainName,
32+
}
33+
}

src/PSADT/PSADT.Interop/NativeMethods.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3726,6 +3726,37 @@ internal static uint DWRITE_MAKE_OPENTYPE_TAG(char a, char b, char c, char d)
37263726
return (byte)a | ((uint)(byte)b << 8) | ((uint)(byte)c << 16) | ((uint)(byte)d << 24);
37273727
}
37283728

3729+
/// <summary>
3730+
/// Retrieves the join status and name of the domain or workgroup for the specified computer.
3731+
/// </summary>
3732+
/// <remarks>The caller must release the buffer referenced by lpNameBuffer to avoid memory leaks.
3733+
/// This method throws an exception if the underlying Windows API call fails.</remarks>
3734+
/// <param name="lpServer">The name of the remote server to query, or null to specify the local computer. The name must begin with \\
3735+
/// if specified.</param>
3736+
/// <param name="lpNameBuffer">When this method returns, contains a handle to a buffer that receives the name of the domain or workgroup.
3737+
/// The caller is responsible for releasing this handle.</param>
3738+
/// <param name="BufferType">When this method returns, contains a value that indicates the join status of the computer.</param>
3739+
/// <returns>A WIN32_ERROR value that indicates the result of the operation. Returns NERR_Success if successful.</returns>
3740+
internal static WIN32_ERROR NetGetJoinInformation(string? lpServer, out SafeNetApiBufferFreeHandle lpNameBuffer, out Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS BufferType)
3741+
{
3742+
WIN32_ERROR res = ((WIN32_ERROR)PInvoke.NetGetJoinInformation(lpServer, out PWSTR lpNameBufferLocal, out BufferType)).ThrowOnFailure();
3743+
lpNameBuffer = new(lpNameBufferLocal.ToIntPtr().ThrowIfZeroOrMinusOne(), lpNameBufferLocal.Length, true);
3744+
return res;
3745+
}
3746+
3747+
/// <summary>
3748+
/// Retrieves information about the join status of the local computer to a domain or workgroup.
3749+
/// </summary>
3750+
/// <param name="lpNameBuffer">When this method returns, contains a handle to a buffer that receives the name of the domain or workgroup.
3751+
/// The caller is responsible for freeing this buffer.</param>
3752+
/// <param name="BufferType">When this method returns, contains a value that specifies the join status of the local computer.</param>
3753+
/// <returns>A WIN32_ERROR value that indicates the result of the operation. Returns ERROR_SUCCESS if the information is
3754+
/// retrieved successfully; otherwise, returns a system error code.</returns>
3755+
internal static WIN32_ERROR NetGetJoinInformation(out SafeNetApiBufferFreeHandle lpNameBuffer, out Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS BufferType)
3756+
{
3757+
return NetGetJoinInformation(null, out lpNameBuffer, out BufferType);
3758+
}
3759+
37293760
/// <summary>
37303761
/// Lookup table for system information class struct sizes.
37313762
/// </summary>

src/PSADT/PSADT.Interop/NativeMethods.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ MsiSummaryInfoGetProperty
175175
MsiViewExecute
176176
MsiViewFetch
177177
MsiViewModify
178+
NetApiBufferFree
179+
NetGetJoinInformation
180+
NETSETUP_JOIN_STATUS
178181
NtQueryInformationProcess
179182
NtQueryObject
180183
NtQuerySystemInformation
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using PSADT.Interop.Extensions;
3+
using Windows.Win32;
4+
using Windows.Win32.Foundation;
5+
6+
namespace PSADT.Interop.SafeHandles
7+
{
8+
/// <summary>
9+
/// Provides a safe handle for memory buffers allocated by the Net API, ensuring that resources are properly
10+
/// released when no longer needed.
11+
/// </summary>
12+
/// <remarks>This class inherits from SafeMemoryHandle and is designed to manage the lifetime of unmanaged
13+
/// memory buffers allocated by the Net API. When the handle is released, the associated memory is freed using
14+
/// NetApiBufferFree to prevent resource leaks.</remarks>
15+
/// <param name="handle">The pointer to the memory buffer allocated by the Net API.</param>
16+
/// <param name="length">The size, in bytes, of the memory buffer referenced by the handle.</param>
17+
/// <param name="ownsHandle">A value indicating whether this instance is responsible for releasing the handle when it is no longer needed.</param>
18+
internal sealed class SafeNetApiBufferFreeHandle(IntPtr handle, int length, bool ownsHandle) : SafeMemoryHandle<SafeNetApiBufferFreeHandle>(handle, length, ownsHandle)
19+
{
20+
/// <summary>
21+
/// Releases the handle.
22+
/// </summary>
23+
/// <returns></returns>
24+
protected override bool ReleaseHandle()
25+
{
26+
if (default == handle)
27+
{
28+
return true;
29+
}
30+
unsafe
31+
{
32+
_ = ((WIN32_ERROR)PInvoke.NetApiBufferFree((void*)handle)).ThrowOnFailure();
33+
}
34+
handle = default;
35+
return true;
36+
}
37+
}
38+
}

src/PSADT/PSADT/DeviceManagement/DeviceUtilities.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using System.Runtime.InteropServices;
44
using PSADT.Interop;
5+
using PSADT.Interop.SafeHandles;
56
using PSADT.ProcessManagement;
67
using Windows.Win32;
78
using Windows.Win32.Foundation;
@@ -128,5 +129,19 @@ public static DateTime GetSystemBootTime()
128129
{
129130
return DateTime.Now - GetSystemUptime();
130131
}
132+
133+
/// <summary>
134+
/// Retrieves the current domain join status and associated domain or workgroup name of the local computer.
135+
/// </summary>
136+
/// <returns>A <see cref="DomainStatus"/> object containing the join status and the name of the domain or workgroup the
137+
/// computer is joined to.</returns>
138+
public static DomainStatus GetDomainStatus()
139+
{
140+
_ = NativeMethods.NetGetJoinInformation(out SafeNetApiBufferFreeHandle? nameBuffer, out Windows.Win32.NetworkManagement.NetManagement.NETSETUP_JOIN_STATUS bufferType);
141+
using (nameBuffer)
142+
{
143+
return new((NETSETUP_JOIN_STATUS)bufferType, nameBuffer.ToStringUni());
144+
}
145+
}
131146
}
132147
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using PSADT.Interop;
2+
3+
namespace PSADT.DeviceManagement
4+
{
5+
/// <summary>
6+
/// Represents the domain or workgroup join status of a computer, including the associated domain or workgroup name
7+
/// if applicable.
8+
/// </summary>
9+
/// <remarks>Use this type to determine whether a computer is joined to a domain, a workgroup, or is
10+
/// unjoined, and to retrieve the corresponding domain or workgroup name when available. This record is
11+
/// immutable.</remarks>
12+
public sealed record DomainStatus
13+
{
14+
/// <summary>
15+
/// Initializes a new instance of the DomainStatus class with the specified join status and domain or workgroup
16+
/// name.
17+
/// </summary>
18+
/// <param name="joinStatus">The status indicating whether the computer is joined to a domain, a workgroup, or is unjoined.</param>
19+
/// <param name="domainOrWorkgroupName">The name of the domain or workgroup associated with the current join status, or null if not applicable.</param>
20+
public DomainStatus(NETSETUP_JOIN_STATUS joinStatus, string? domainOrWorkgroupName)
21+
{
22+
JoinStatus = joinStatus;
23+
DomainOrWorkgroupName = domainOrWorkgroupName;
24+
}
25+
26+
/// <summary>
27+
/// Gets the status of the computer's domain or workgroup join operation.
28+
/// </summary>
29+
public NETSETUP_JOIN_STATUS JoinStatus { get; }
30+
31+
/// <summary>
32+
/// Gets the name of the domain or workgroup to which the computer belongs.
33+
/// </summary>
34+
public string? DomainOrWorkgroupName { get; }
35+
}
36+
}

0 commit comments

Comments
 (0)