예제 #1
0
 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);
     }
 }
예제 #2
0
 /// <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>.");
 }
예제 #3
0
파일: WinGdi.cs 프로젝트: zuozhu315/Vanara
        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);
        }
예제 #4
0
        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);
        }
예제 #6
0
        /// <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);
                }
            }
        }
예제 #7
0
        /// <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);
        }
예제 #9
0
        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>();
        }
예제 #10
0
        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);
        }
예제 #11
0
 public static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor([In] string StringSecurityDescriptor, SDDL_REVISION StringSDRevision,
                                                                               out SafeHGlobalHandle SecurityDescriptor, out uint SecurityDescriptorSize);
예제 #12
0
 public static extern bool ConvertSecurityDescriptorToStringSecurityDescriptor(IntPtr SecurityDescriptor, SDDL_REVISION RequestedStringSDRevision,
                                                                               SECURITY_INFORMATION SecurityInformation, out SafeHGlobalHandle StringSecurityDescriptor, out uint StringSecurityDescriptorLen);
예제 #13
0
 public static extern bool ConvertSidToStringSid(PSID Sid, out SafeHGlobalHandle StringSid);
예제 #14
0
 public static bool SetEnvironmentStrings(IEnumerable <string> NewEnvironment)
 {
     using (var mem = SafeHGlobalHandle.CreateFromStringList(NewEnvironment, StringListPackMethod.Concatenated, CharSet.Unicode))
         return(SetEnvironmentStringsW(mem.DangerousGetHandle()));
 }