Compare commits

...

3 Commits

Author SHA1 Message Date
David Hall be7eacb1b2 Added nullability to WPF.Extensions 2023-11-02 22:32:07 -06:00
David Hall e706e3a5aa Added nullability to WsmSvc and tests 2023-11-02 22:26:49 -06:00
David Hall 68fc80ed2e Added nullability to WscApi 2023-11-01 07:21:20 -06:00
6 changed files with 3060 additions and 318 deletions

View File

@ -1,12 +1,4 @@

/* Unmerged change from project 'Vanara.PInvoke.WscApi (netcoreapp3.1)'
Before:
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
After:
using System;
*/
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
namespace Vanara.PInvoke;

File diff suppressed because it is too large Load Diff

View File

@ -303,7 +303,7 @@ public static partial class WsmSvc
// connection, long flags, IDispatch *connectionOptions, IDispatch **session );
[PreserveSig, DispId(1)]
HRESULT CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, [Optional] WSManSessionFlags flags,
IWSManConnectionOptions connectionOptions, out IWSManSession session);
IWSManConnectionOptions? connectionOptions, out IWSManSession session);
/// <summary>Creates an IWSManConnectionOptions object that specifies the user name and password used when creating a session.</summary>
/// <param name="connectionOptions">A pointer to a new IWSManConnectionOptions object.</param>
@ -809,7 +809,7 @@ public static partial class WsmSvc
// connection, long flags, IDispatch *connectionOptions, IDispatch **session );
[PreserveSig, DispId(1)]
new HRESULT CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, [Optional] WSManSessionFlags flags,
IWSManConnectionOptions connectionOptions, out IWSManSession session);
IWSManConnectionOptions? connectionOptions, out IWSManSession session);
/// <summary>Creates an IWSManConnectionOptions object that specifies the user name and password used when creating a session.</summary>
/// <param name="connectionOptions">A pointer to a new IWSManConnectionOptions object.</param>
@ -1247,7 +1247,7 @@ public static partial class WsmSvc
// connection, long flags, IDispatch *connectionOptions, IDispatch **session );
[PreserveSig, DispId(1)]
new HRESULT CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, [Optional] WSManSessionFlags flags,
IWSManConnectionOptions connectionOptions, out IWSManSession session);
IWSManConnectionOptions? connectionOptions, out IWSManSession session);
/// <summary>Creates an IWSManConnectionOptions object that specifies the user name and password used when creating a session.</summary>
/// <param name="connectionOptions">A pointer to a new IWSManConnectionOptions object.</param>
@ -1700,7 +1700,7 @@ public static partial class WsmSvc
// connection, long flags, IDispatch *connectionOptions, IDispatch **session );
[PreserveSig, DispId(1)]
new HRESULT CreateSession([MarshalAs(UnmanagedType.BStr)] string connection, [Optional] WSManSessionFlags flags,
IWSManConnectionOptions connectionOptions, out IWSManSession session);
IWSManConnectionOptions? connectionOptions, out IWSManSession session);
/// <summary>Creates an IWSManConnectionOptions object that specifies the user name and password used when creating a session.</summary>
/// <param name="connectionOptions">A pointer to a new IWSManConnectionOptions object.</param>
@ -2572,7 +2572,7 @@ public static partial class WsmSvc
// resourceUri, BSTR filter, BSTR dialect, long flags, IDispatch **resultSet );
[PreserveSig, DispId(6)]
HRESULT Enumerate([In, MarshalAs(UnmanagedType.Struct)] object resourceUri, [MarshalAs(UnmanagedType.BStr)] string filter,
[MarshalAs(UnmanagedType.BStr)] string dialect, WSManEnumFlags flags, out IWSManEnumerator resultSet);
[MarshalAs(UnmanagedType.BStr)] string? dialect, WSManEnumFlags flags, out IWSManEnumerator resultSet);
/// <summary>
/// The <c>IWSManSession::Identify</c> method queries a remote computer to determine if it supports the WS-Management protocol.

2712
PInvoke/WsmSvc/wsmerror.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,17 +7,17 @@ namespace Vanara.PInvoke.Tests;
public class ShellClient : IDisposable
{
private SafeWSMAN_API_HANDLE m_apiHandle;
private SafeWSMAN_API_HANDLE? m_apiHandle;
private WSMAN_SHELL_ASYNC m_async;
private bool m_bExecute;
private bool m_bSetup;
private WSMAN_COMMAND_HANDLE m_command;
private Win32Error m_errorCode;
private SafeEventHandle m_event;
private SafeEventHandle? m_event;
private WSMAN_SHELL_ASYNC m_ReceiveAsync;
private Win32Error m_ReceiveErrorCode;
private SafeEventHandle m_ReceiveEvent;
private SafeWSMAN_SESSION_HANDLE m_session;
private SafeEventHandle? m_ReceiveEvent;
private SafeWSMAN_SESSION_HANDLE? m_session;
private WSMAN_SHELL_HANDLE m_shell;
// Constructor.
@ -26,12 +26,13 @@ public class ShellClient : IDisposable
}
// Clean up the used resources
public void Dispose()
void IDisposable.Dispose()
{
if (!m_command.IsNull)
{
WSManCloseCommand(m_command, 0, m_async);
WaitForSingleObject(m_event, INFINITE);
if (m_event is not null && !m_event.IsClosed)
WaitForSingleObject(m_event, INFINITE);
if (Win32Error.NO_ERROR != m_errorCode)
{
wprintf("WSManCloseCommand failed: {0}\n", m_errorCode);
@ -45,7 +46,8 @@ public class ShellClient : IDisposable
if (!m_shell.IsNull)
{
WSManCloseShell(m_shell, 0, m_async);
WaitForSingleObject(m_event, INFINITE);
if (m_event is not null && !m_event.IsClosed)
WaitForSingleObject(m_event, INFINITE);
if (Win32Error.NO_ERROR != m_errorCode)
{
wprintf("WSManCloseShell failed: {0}\n", m_errorCode);
@ -67,10 +69,12 @@ public class ShellClient : IDisposable
m_bSetup = false;
m_bExecute = false;
GC.SuppressFinalize(this);
}
// Execute shell-related operations
public bool Execute(string resourceUri, string commandLine, byte[] sendData, uint count)
public bool Execute(string resourceUri, string commandLine, byte[]? sendData, uint count)
{
if (!m_bSetup)
{
@ -85,8 +89,9 @@ public class ShellClient : IDisposable
m_bExecute = true;
// WSManCreateShell
WSManCreateShell(m_session, 0, resourceUri, default, default, default, m_async, out m_shell);
WaitForSingleObject(m_event, INFINITE);
WSManCreateShell(m_session!, 0, resourceUri, default, default, default, m_async, out m_shell);
if (m_event is not null && !m_event.IsClosed)
WaitForSingleObject(m_event, INFINITE);
if (Win32Error.NO_ERROR != m_errorCode)
{
wprintf("WSManCreateShell failed: {0}\n", m_errorCode);
@ -95,7 +100,8 @@ public class ShellClient : IDisposable
// WSManRunShellCommand
WSManRunShellCommand(m_shell, 0, commandLine, default, default, m_async, out m_command);
WaitForSingleObject(m_event, INFINITE);
if (m_event is not null && !m_event.IsClosed)
WaitForSingleObject(m_event, INFINITE);
if (Win32Error.NO_ERROR != m_errorCode)
{
wprintf("WSManRunShellCommand failed: {0}\n", m_errorCode);
@ -119,7 +125,8 @@ public class ShellClient : IDisposable
}
// Receive operation is finished
WaitForSingleObject(m_ReceiveEvent, INFINITE);
if (m_ReceiveEvent is not null && !m_ReceiveEvent.IsClosed)
WaitForSingleObject(m_ReceiveEvent, INFINITE);
if (Win32Error.NO_ERROR != m_ReceiveErrorCode)
{
wprintf("WSManReceiveShellOutput failed: {0}\n", m_ReceiveErrorCode);
@ -131,7 +138,7 @@ public class ShellClient : IDisposable
}
// Initialize session for subsequent operations
public bool Setup(string connection, WSManAuthenticationFlags authenticationMechanism, string username, string password)
public bool Setup(string connection, WSManAuthenticationFlags authenticationMechanism, string? username, string? password)
{
if (m_bSetup) return true;
@ -216,7 +223,7 @@ public class ShellClient : IDisposable
m_ReceiveErrorCode = error.code;
// NOTE: if the errorDetail needs to be used outside of the callback, then need to allocate memory, copy the content to that
// memory as error.errorDetail itself is owned by WSMan client stack and will be deallocated and invalid when the callback exits
wprintf(error.errorDetail);
wprintf(error.errorDetail ?? "");
}
// Output the received data to the console
@ -233,7 +240,7 @@ public class ShellClient : IDisposable
// for WSManReceiveShellOutput, needs to wait for state to be done before signalliing the end of the operation
if ((0 != error.code) || (pdata != default && !data.commandState.IsNull && string.Compare(data.commandState, WSMAN_COMMAND_STATE_DONE) == 0))
{
SetEvent(m_ReceiveEvent);
m_ReceiveEvent?.Set();
}
}
@ -246,14 +253,14 @@ public class ShellClient : IDisposable
m_errorCode = error.code;
// NOTE: if the errorDetail needs to be used outside of the callback, then need to allocate memory, copy the content to that
// memory as error->errorDetail itself is owned by WSMan client stack and will be deallocated and invalid when the callback exits
wprintf(error.errorDetail);
wprintf(error.errorDetail ?? "");
}
// for non-receieve operation, the callback simply signals the async operation is finished
SetEvent(m_event);
m_event?.Set();
}
private bool Send(byte[] sendData, bool endOfStream)
private bool Send(byte[]? sendData, bool endOfStream)
{
// WSManSendShellInput
var streamData = new WSMAN_DATA
@ -268,7 +275,8 @@ public class ShellClient : IDisposable
streamData.union.binaryData.data = pSendData;
}
WSManSendShellInput(m_shell, m_command, 0, WSMAN_STREAM_ID_STDIN, streamData, endOfStream, m_async, out SafeWSMAN_OPERATION_HANDLE sendOperation);
WaitForSingleObject(m_event, INFINITE);
if (m_event is not null && !m_event.IsClosed)
WaitForSingleObject(m_event, INFINITE);
if (Win32Error.NO_ERROR != m_errorCode)
{
wprintf("WSManSendShellInput failed: {0}\n", m_errorCode);
@ -279,7 +287,7 @@ public class ShellClient : IDisposable
return true;
}
private void wprintf(string fmt, params object[] p) => TestContext.Write(fmt, p);
private static void wprintf(string fmt, params object[] p) => TestContext.Write(fmt, p);
}
[TestFixture]

View File

@ -11,18 +11,18 @@ public static class GdiObjExtensions2
/// <summary>Creates a <see cref="BitmapSource"/> from an <see cref="SafeHBITMAP"/> preserving transparency, if possible.</summary>
/// <param name="hbmp">The SafeHBITMAP value.</param>
/// <returns>The BitmapSource instance. If <paramref name="hbmp"/> is a <c>NULL</c> handle, <see langword="null"/> is returned.</returns>
public static BitmapSource ToBitmapSource(this SafeHBITMAP hbmp) => hbmp is null || hbmp.IsInvalid ? null : CreateBitmapSourceFromHBitmap(hbmp.DangerousGetHandle(), default, default, BitmapSizeOptions.FromEmptyOptions());
public static BitmapSource? ToBitmapSource(this SafeHBITMAP hbmp) => hbmp is null || hbmp.IsInvalid ? null : CreateBitmapSourceFromHBitmap(hbmp.DangerousGetHandle(), default, default, BitmapSizeOptions.FromEmptyOptions());
/// <summary>Creates a <see cref="BitmapSource"/> from an <see cref="HBITMAP"/> preserving transparency, if possible.</summary>
/// <param name="hbmp">The HBITMAP value.</param>
/// <returns>The BitmapSource instance. If <paramref name="hbmp"/> is a <c>NULL</c> handle, <see langword="null"/> is returned.</returns>
public static BitmapSource ToBitmapSource(this in HBITMAP hbmp) => hbmp.IsNull ? null : CreateBitmapSourceFromHBitmap(hbmp.DangerousGetHandle(), default, default, BitmapSizeOptions.FromEmptyOptions());
public static BitmapSource? ToBitmapSource(this in HBITMAP hbmp) => hbmp.IsNull ? null : CreateBitmapSourceFromHBitmap(hbmp.DangerousGetHandle(), default, default, BitmapSizeOptions.FromEmptyOptions());
/// <summary>Creates a managed <see cref="BitmapSource"/> from a HICON instance.</summary>
/// <returns>A managed bitmap instance.</returns>
public static BitmapSource ToBitmapSource(this in HICON hIcon) => hIcon.IsNull ? null : CreateBitmapSourceFromHIcon(hIcon.DangerousGetHandle(), default, BitmapSizeOptions.FromEmptyOptions());
public static BitmapSource? ToBitmapSource(this in HICON hIcon) => hIcon.IsNull ? null : CreateBitmapSourceFromHIcon(hIcon.DangerousGetHandle(), default, BitmapSizeOptions.FromEmptyOptions());
/// <summary>Creates a managed <see cref="BitmapSource"/> from a SafeHICON instance.</summary>
/// <returns>A managed bitmap instance.</returns>
public static BitmapSource ToBitmapSource(this SafeHICON hIcon) => hIcon is null || hIcon.IsInvalid ? null : CreateBitmapSourceFromHIcon(hIcon.DangerousGetHandle(), default, BitmapSizeOptions.FromEmptyOptions());
public static BitmapSource? ToBitmapSource(this SafeHICON hIcon) => hIcon is null || hIcon.IsInvalid ? null : CreateBitmapSourceFromHIcon(hIcon.DangerousGetHandle(), default, BitmapSizeOptions.FromEmptyOptions());
}