public static bool DeviceIoControl <TOut>(SafeFileHandle hDev, uint ioControlCode, out TOut outVal) where TOut : struct { using (var ptrOut = SafeHGlobalHandle.Alloc <TOut>()) { uint bRet; var ret = Kernel32.DeviceIoControl(hDev, ioControlCode, IntPtr.Zero, 0, (IntPtr)ptrOut, (uint)ptrOut.Size, out bRet, IntPtr.Zero); outVal = ptrOut.ToStructure <TOut>(); return(ret); } }
/// <inheritdoc/> public SafeAllocatedMemoryHandle MarshalManagedToNative(object managedObject) { if (managedObject is IEnumerable <T> ias) { var cnt = ias.Count(); var mem = new SafeHGlobalHandle(hSz + InteropExtensions.SizeOf <T>() * cnt); mem.Write(cnt); mem.Write(ias, true, hSz); return(mem); } throw new ArgumentException("Unexpected type. Value must be of IEnumerable<T>."); }
public static SafeHGlobalHandle GetObject(HGDIOBJ hgdiobj) { var sz = GetObject(hgdiobj, 0, IntPtr.Zero); var ptr = new SafeHGlobalHandle(sz); var ret = GetObject(hgdiobj, ptr.Size, (IntPtr)ptr); if (ret == 0) { Win32Error.ThrowLastError(); } return(ptr); }
public static IEnumerable <NETRESOURCE> WNetEnumResources([Optional] NETRESOURCE root, NETRESOURCEScope dwScope = NETRESOURCEScope.RESOURCE_GLOBALNET, NETRESOURCEType dwType = NETRESOURCEType.RESOURCETYPE_ANY, NETRESOURCEUsage dwUsage = 0, bool recurseContainers = false) { var err = WNetOpenEnum(dwScope, dwType, dwUsage, root, out var h); if (err == Win32Error.ERROR_NOT_CONTAINER || err == Win32Error.ERROR_NO_NETWORK) { yield break; } else if (err.Failed) { throw err.GetException(); } using (h) { var count = -1; var sz = 16 * 1024U; using (var mem = new SafeHGlobalHandle((int)sz)) { do { err = WNetEnumResource(h, ref count, (IntPtr)mem, ref sz); if (err == Win32Error.ERROR_SUCCESS) { foreach (var e in mem.ToEnumerable <NETRESOURCE>((int)count)) { yield return(e); if (recurseContainers && e.dwUsage.IsFlagSet(NETRESOURCEUsage.RESOURCEUSAGE_CONTAINER)) { foreach (var ce in WNetEnumResources(e, dwScope, dwType, dwUsage, recurseContainers)) { yield return(ce); } } } } else if (err == Win32Error.ERROR_NO_MORE_ITEMS) { break; } else { throw err.GetException(); } mem.Zero(); }while (true); } } }
/// <summary> /// Allocates unmanaged memory to represent a structure with a variable length array at the end and marshal these structure elements. It is the /// callers responsibility to marshal what precedes the trailing array into the unmanaged memory. ONLY structures with attribute StructLayout of /// LayoutKind.Sequential are supported. /// </summary> /// <typeparam name="T">Type of the trailing array of structures</typeparam> /// <param name="values">Collection of structure objects</param> /// <param name="count">Number of items in <paramref name="values"/>.</param> /// <param name="prefixBytes">Number of bytes preceding the trailing array of structures</param> /// <returns>SafeHGlobalHandle object to an native (unmanaged) structure with a trail array of structures</returns> public static SafeHGlobalHandle AllocHGlobal <T>(IEnumerable <T> values, int count, int prefixBytes = 0) where T : struct { Debug.Assert(typeof(T).StructLayoutAttribute?.Value == LayoutKind.Sequential); var sz = Marshal.SizeOf(typeof(T)); var result = new SafeHGlobalHandle(prefixBytes + sz * count); var ptr = new IntPtr(result.handle.ToInt64() + prefixBytes); foreach (var value in values) { result.StructureToPtr(value, ptr, false); ptr = new IntPtr(ptr.ToInt64() + sz); } return(result); }
/// <summary>The <c>WNetEnumResources</c> function enumerates network resources.</summary> /// <param name="root"> /// <para> /// Pointer to a <c>NETRESOURCE</c> structure that specifies the container to enumerate. If the dwScope parameter is not /// RESOURCE_GLOBALNET, this parameter must be <c>NULL</c>. /// </para> /// <para> /// If this parameter is <c>NULL</c>, the root of the network is assumed. (The system organizes a network as a hierarchy; the root is /// the topmost container in the network.) /// </para> /// <para> /// If this parameter is not <c>NULL</c>, it must point to a <c>NETRESOURCE</c> structure. This structure can be filled in by the /// application or it can be returned by a call to the <c>WNetEnumResource</c> function. The <c>NETRESOURCE</c> structure must /// specify a container resource; that is, the RESOURCEUSAGE_CONTAINER value must be specified in the dwUsage parameter. /// </para> /// <para> /// To enumerate all network resources, an application can begin the enumeration by calling <c>WNetOpenEnum</c> with the /// lpNetResource parameter set to <c>NULL</c>, and then use the returned handle to call <c>WNetEnumResource</c> to enumerate /// resources. If one of the resources in the <c>NETRESOURCE</c> array returned by the <c>WNetEnumResource</c> function is a /// container resource, you can call <c>WNetOpenEnum</c> to open the resource for further enumeration. /// </para> /// </param> /// <param name="dwScope"> /// <para>Scope of the enumeration. This parameter can be one of the following values.</para> /// <para> /// <list type="table"> /// <listheader> /// <term>Value</term> /// <term>Meaning</term> /// </listheader> /// <item> /// <term>RESOURCE_CONNECTED</term> /// <term> /// Enumerate all currently connected resources. The function ignores the dwUsage parameter. For more information, see the following /// Remarks section. /// </term> /// </item> /// <item> /// <term>RESOURCE_CONTEXT</term> /// <term> /// Enumerate only resources in the network context of the caller. Specify this value for a Network Neighborhood view. The function /// ignores the dwUsage parameter. /// </term> /// </item> /// <item> /// <term>RESOURCE_GLOBALNET</term> /// <term>Enumerate all resources on the network.</term> /// </item> /// <item> /// <term>RESOURCE_REMEMBERED</term> /// <term>Enumerate all remembered (persistent) connections. The function ignores the dwUsage parameter.</term> /// </item> /// </list> /// </para> /// </param> /// <param name="dwType"> /// <para>Resource types to be enumerated. This parameter can be a combination of the following values.</para> /// <para> /// <list type="table"> /// <listheader> /// <term>Value</term> /// <term>Meaning</term> /// </listheader> /// <item> /// <term>RESOURCETYPE_ANY</term> /// <term>All resources. This value cannot be combined with RESOURCETYPE_DISK or RESOURCETYPE_PRINT.</term> /// </item> /// <item> /// <term>RESOURCETYPE_DISK</term> /// <term>All disk resources.</term> /// </item> /// <item> /// <term>RESOURCETYPE_PRINT</term> /// <term>All print resources.</term> /// </item> /// </list> /// </para> /// <para>If a network provider cannot distinguish between print and disk resources, it can enumerate all resources.</para> /// </param> /// <param name="dwUsage"> /// <para>Resource usage type to be enumerated. This parameter can be a combination of the following values.</para> /// <para> /// <list type="table"> /// <listheader> /// <term>Value</term> /// <term>Meaning</term> /// </listheader> /// <item> /// <term>0</term> /// <term>All resources.</term> /// </item> /// <item> /// <term>RESOURCEUSAGE_CONNECTABLE</term> /// <term>All connectable resources.</term> /// </item> /// <item> /// <term>RESOURCEUSAGE_CONTAINER</term> /// <term>All container resources.</term> /// </item> /// <item> /// <term>RESOURCEUSAGE_ATTACHED</term> /// <term> /// Setting this value forces WNetOpenEnum to fail if the user is not authenticated. The function fails even if the network allows /// enumeration without authentication. /// </term> /// </item> /// <item> /// <term>RESOURCEUSAGE_ALL</term> /// <term>Setting this value is equivalent to setting RESOURCEUSAGE_CONNECTABLE, RESOURCEUSAGE_CONTAINER, and RESOURCEUSAGE_ATTACHED.</term> /// </item> /// </list> /// </para> /// <para> /// This parameter is ignored unless the dwScope parameter is equal to RESOURCE_GLOBALNET. For more information, see the following /// Remarks section. /// </para> /// </param> /// <param name="recurseContainers">if set to <see langword="true"/> [recurse containers].</param> /// <returns>The enumeration results. The results are returned as a list of <c>NETRESOURCE</c> structures.</returns> public static IEnumerable <NETRESOURCE> WNetEnumResources([Optional] NETRESOURCE root, NETRESOURCEScope dwScope = NETRESOURCEScope.RESOURCE_GLOBALNET, NETRESOURCEType dwType = NETRESOURCEType.RESOURCETYPE_ANY, NETRESOURCEUsage dwUsage = 0, bool recurseContainers = false) { var err = WNetOpenEnum(dwScope, dwType, dwUsage, root, out var h); if (err == Win32Error.ERROR_NOT_CONTAINER || err == Win32Error.ERROR_NO_NETWORK) { yield break; } else if (err.Failed) { throw err.GetException(); } using (h) { var count = -1; var sz = 16 * 1024U; using (var mem = new SafeHGlobalHandle((int)sz)) { do { mem.Zero(); err = WNetEnumResource(h, ref count, (IntPtr)mem, ref sz); if (err.Succeeded) { foreach (var e in mem.ToEnumerable <NETRESOURCE>(count)) { yield return(e); if (recurseContainers && e.dwUsage.IsFlagSet(NETRESOURCEUsage.RESOURCEUSAGE_CONTAINER)) { foreach (var ce in WNetEnumResources(e, dwScope, dwType, dwUsage, recurseContainers)) { yield return(ce); } } } } else if (err != Win32Error.ERROR_NO_MORE_ITEMS) { throw err.GetException("Last resource = " + (root is null ? "" : $"Type:{root.dwDisplayType}=Prov:{root.lpProvider}; Rem:{root.lpRemoteName}")); } }while (err != Win32Error.ERROR_NO_MORE_ITEMS); } } }
/// <summary> /// Calls a method with buffer for a type and gets the result or error. /// </summary> /// <typeparam name="TOut">The return type.</typeparam> /// <typeparam name="TSize">The type of the size result. This is usually <see cref="int" /> or <see cref="uint" />.</typeparam> /// <param name="getSize">Method to get the size of the buffer.</param> /// <param name="method">The lambda or method to call into.</param> /// <param name="result">The resulting value of <typeparamref name="TOut" />.</param> /// <param name="outConverter">An optional method to convert the pointer to the type specified by <typeparamref name="TOut" />. By default, this will marshal the pointer to the structure.</param> /// <param name="bufErr">The optional error <paramref name="method"/> returns when the buffer size is insufficient. If left <see langword="null"/>, then a list of well known errors will be used.</param> /// <returns> /// Resulting error or <see cref="Win32Error.ERROR_SUCCESS" /> on success. /// </returns> public static Win32Error CallMethodWithTypedBuf <TOut, TSize>(SizeFunc <TSize> getSize, PtrFunc <TSize> method, out TOut result, Func <IntPtr, TSize, TOut> outConverter = null, Win32Error?bufErr = null) where TSize : struct, IConvertible { TSize sz = default; result = default; var err = (getSize ?? GetSize)(ref sz); if (err.Failed && (bufErr == null || bufErr.Value != err) && !buffErrs.Contains(err)) { return(err); } using (var buf = new SafeHGlobalHandle(sz.ToInt32(null))) { var ret = method(buf.DangerousGetHandle(), ref sz); result = (outConverter ?? Conv)(buf.DangerousGetHandle(), sz); return(ret); } Win32Error GetSize(ref TSize sz1) => method(IntPtr.Zero, ref sz1); TOut Conv(IntPtr p, TSize s) => p.ToStructure <TOut>(); }
/// <summary>Allocates unmanaged memory to represent an array of pointers to strings that are then packed in memory behind the array.</summary> /// <param name="values">The list of strings.</param> /// <param name="charSet">The character set.</param> /// <param name="prefixBytes">Number of bytes preceding the trailing array of structures</param> /// <returns>SafeHGlobalHandle object to a native (unmanaged) array of string pointers with trailing strings.</returns> public static SafeHGlobalHandle AllocHGlobal(IEnumerable <string> values, CharSet charSet = CharSet.Auto, int prefixBytes = 0) { var coll = values as IList <string> ?? new List <string>(values); var chSz = charSet == CharSet.Unicode ? 2 : (charSet == CharSet.Auto ? Marshal.SystemDefaultCharSize : 1); var sz = coll.Sum(s => ((s?.Length + 1) * chSz ?? 0) + IntPtr.Size); var result = new SafeHGlobalHandle(prefixBytes + sz); var ptr = new IntPtr(result.handle.ToInt64() + prefixBytes); var enc = chSz == 1 ? System.Text.Encoding.ASCII : System.Text.Encoding.Unicode; var sptr = new IntPtr(ptr.ToInt64() + IntPtr.Size * coll.Count); var iptr = ptr; foreach (var s in coll) { var bytes = enc.GetByteCount(s); Marshal.Copy(enc.GetBytes(s), 0, sptr, bytes); Marshal.WriteIntPtr(iptr, sptr); iptr = new IntPtr(iptr.ToInt64() + IntPtr.Size); sptr = new IntPtr(sptr.ToInt64() + bytes); } return(result); }
public static Win32Error CallMethodWithTypedBuf <TOut, TSize>(SizeFunc <TSize> getSize, PtrFunc <TSize> method, out TOut result, Func <IntPtr, TSize, TOut> outConverter = null) where TSize : struct, IConvertible { TSize sz = default; result = default; var err = getSize(ref sz); if (err.Failed) { return(err); } var len = sz.ToInt32(null); using (var buf = new SafeHGlobalHandle(len)) { var ret = method(buf.DangerousGetHandle(), ref sz); result = (outConverter ?? Conv)(buf.DangerousGetHandle(), sz); return(ret); } TOut Conv(IntPtr p, TSize s) => p.ToStructure <TOut>(); }
public static bool QueryServiceConfig2 <T>(IntPtr hService, ServiceConfigOption dwInfoLevel, out T configInfo) { var b = QueryServiceConfig2(hService, dwInfoLevel, IntPtr.Zero, 0, out uint size); configInfo = default(T); if (!b && Win32Error.GetLastError() != Win32Error.ERROR_INSUFFICIENT_BUFFER) { return(false); } if (size < Marshal.SizeOf(typeof(T))) { throw new ArgumentException("Type mismatch", nameof(configInfo)); } using (var buf = new SafeHGlobalHandle((int)size)) { if (!QueryServiceConfig2(hService, dwInfoLevel, (IntPtr)buf, size, out size)) { return(false); } configInfo = buf.ToStructure <T>(); } return(true); }
public static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor([In] string StringSecurityDescriptor, SDDL_REVISION StringSDRevision, out SafeHGlobalHandle SecurityDescriptor, out uint SecurityDescriptorSize);
public static extern bool ConvertSecurityDescriptorToStringSecurityDescriptor(IntPtr SecurityDescriptor, SDDL_REVISION RequestedStringSDRevision, SECURITY_INFORMATION SecurityInformation, out SafeHGlobalHandle StringSecurityDescriptor, out uint StringSecurityDescriptorLen);
public static extern bool ConvertSidToStringSid(PSID Sid, out SafeHGlobalHandle StringSid);
public static bool SetEnvironmentStrings(IEnumerable <string> NewEnvironment) { using (var mem = SafeHGlobalHandle.CreateFromStringList(NewEnvironment, StringListPackMethod.Concatenated, CharSet.Unicode)) return(SetEnvironmentStringsW(mem.DangerousGetHandle())); }