// NOTE: this function throws a COMException if the object was not found public static object?GetActiveObject(string progId) { if (progId is null) { throw new ArgumentNullException(nameof(progId)); } // get the CLSID for the supplied ProgId var getClsidResult = ExtendedPInvoke.CLSIDFromProgIDEx(progId, out var clsid); if (getClsidResult != (uint)ExtendedPInvoke.S_OK) { switch (getClsidResult) { case (uint)ExtendedPInvoke.Win32ErrorCode.CO_E_CLASSSTRING: throw new COMException("Invalid class string"); case (uint)ExtendedPInvoke.Win32ErrorCode.REGDB_E_WRITEREGDB: throw new COMException("Could not write key to registry"); } } var getActiveObjectResult = ExtendedPInvoke.GetActiveObject(ref clsid, IntPtr.Zero, out var activeObject); if (getActiveObjectResult != (uint)ExtendedPInvoke.S_OK) { // if we could not get the object, return null // NOTE: if we want to distinguish between error results (i.e. object not active vs. others), we could read the win32 "last error" code return(null); } return(activeObject); }
// public static MorphicResult <string, GetPathToExecutableForFileError> GetAssociatedExecutableForFile(string path) { StringBuilder pathToExecutable = new StringBuilder(ExtendedPInvoke.MAX_PATH + 1); var resultCode = ExtendedPInvoke.FindExecutable(path, null, pathToExecutable); if (resultCode.ToInt64() > 32) { // success return(MorphicResult.OkResult(pathToExecutable.ToString())); } else { // failure switch (resultCode.ToInt64()) { case (Int64)ExtendedPInvoke.ShellExecuteErrorCode.SE_ERR_FNF: return(MorphicResult.ErrorResult(GetPathToExecutableForFileError.FileNotFound)); case (Int64)ExtendedPInvoke.ShellExecuteErrorCode.SE_ERR_PNF: return(MorphicResult.ErrorResult(GetPathToExecutableForFileError.PathIsInvalid)); case (Int64)ExtendedPInvoke.ShellExecuteErrorCode.SE_ERR_ACCESSDENIED: return(MorphicResult.ErrorResult(GetPathToExecutableForFileError.AccessDenied)); case (Int64)ExtendedPInvoke.ShellExecuteErrorCode.SE_ERR_OOM: return(MorphicResult.ErrorResult(GetPathToExecutableForFileError.OutOfMemoryOrResources)); case (Int64)ExtendedPInvoke.ShellExecuteErrorCode.SE_ERR_NOASSOC: return(MorphicResult.ErrorResult(GetPathToExecutableForFileError.NoAssociatedExecutable)); default: return(MorphicResult.ErrorResult(GetPathToExecutableForFileError.UnknownShellExecuteErrorCode)); } } }
/* helper functions */ // some more details: https://blog.quarkslab.com/playing-with-the-windows-notification-facility-wnf.html private static MorphicResult <byte[], MorphicUnit> QueryWnfStateData(ExtendedPInvoke.WNF_STATE_NAME stateName) { const uint MAX_BUFFER_LENGTH = 4096; uint bufferSize = MAX_BUFFER_LENGTH; var pointerToBuffer = Marshal.AllocHGlobal((int)bufferSize); try { uint changeStamp; var queryWnfStateDataResult = ExtendedPInvoke.NtQueryWnfStateData(ref stateName, IntPtr.Zero, IntPtr.Zero, out changeStamp, pointerToBuffer, ref bufferSize); if (queryWnfStateDataResult != 0) { return(MorphicResult.ErrorResult()); } var bufferSizeAsInt = (int)bufferSize; var result = new byte[bufferSizeAsInt]; Marshal.Copy(pointerToBuffer, result, 0, bufferSizeAsInt); return(MorphicResult.OkResult(result)); } finally { Marshal.FreeHGlobal(pointerToBuffer); } }
protected virtual void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { // dispose any managed objects here } // free unmanaged resources // NOTE: this function will return false if it fails // NOTE: in theory the system should clean up after this hook handle automatically (so we could probably comment out the following two lines of code) _ = ExtendedPInvoke.UnhookWindowsHookEx(_hookHandle.DangerousGetHandle()); _hookHandle.SetHandleAsInvalid(); // set any large fields to null _isDisposed = true; } }
private static MorphicResult <MorphicUnit, MorphicUnit> UpdateWnfStateData(ExtendedPInvoke.WNF_STATE_NAME stateName, byte[] buffer) { var bufferLength = buffer.Length; var pointerToBuffer = Marshal.AllocHGlobal(bufferLength); try { Marshal.Copy(buffer, 0, pointerToBuffer, bufferLength); var updateWnfStateDataResult = ExtendedPInvoke.NtUpdateWnfStateData(ref stateName, pointerToBuffer, (uint)bufferLength, IntPtr.Zero /* null */, IntPtr.Zero, 0, 0); if (updateWnfStateDataResult != 0) { return(MorphicResult.ErrorResult()); } } finally { Marshal.FreeHGlobal(pointerToBuffer); } return(MorphicResult.OkResult()); }