Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
QueryDosDevice.cs125 linesDownload Raw Back to Windows
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#nullable enable5 6using System;7using System.Buffers;8using System.ComponentModel;9using System.Management.Automation;10using System.Runtime.InteropServices;11 12internal static partial class Interop13{14    internal static partial class Windows15    {16        [LibraryImport(PinvokeDllNames.QueryDosDeviceDllName, EntryPoint = "QueryDosDeviceW", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]17        internal static partial int QueryDosDevice(Span<char> lpDeviceName, Span<char> lpTargetPath, uint ucchMax);18 19        internal static string GetDosDeviceForNetworkPath(char deviceName)20        {21            // By default buffer size is set to 300 which would generally be sufficient in most of the cases.22            const int StartLength =23#if DEBUG24                // In debug, validate ArrayPool growth.25                1;26#else27                300;28#endif29 30            Span<char> buffer = stackalloc char[StartLength + 1];31            Span<char> fullDeviceName = [deviceName, ':', '\0'];32            char[]? rentedArray = null;33 34            try35            {36                while (true)37                {38                    uint length = (uint)buffer.Length;39                    int retValue = QueryDosDevice(fullDeviceName, buffer, length);40                    if (retValue > 0)41                    {42                        if (buffer.StartsWith("\\??\\"))43                        {44                            // QueryDosDevice always return array of NULL-terminating strings with additional final NULL45                            // so the buffer has always two NULL-s on end.46                            //47                            // "\\??\\UNC\\localhost\\c$\\tmp\0\0" -> "UNC\\localhost\\c$\\tmp\0\0"48                            Span<char> res = buffer.Slice(4);49                            if (res.StartsWith("UNC"))50                            {51                                // -> "C\\localhost\\c$\\tmp\0\0" -> "\\\\localhost\\c$\\tmp"52                                //53                                // We need to take only first null-terminated string as QueryDosDevice() docs say.54                                int i = 3;55                                for (; i < res.Length; i++)56                                {57                                    if (res[i] == '\0')58                                    {59                                        break;60                                    }61                                }62 63                                Diagnostics.Assert(i < res.Length, "Broken QueryDosDevice() buffer.");64 65                                res = res.Slice(2, i);66                                res[0] = '\\';67 68                                // If we want always to have terminating slash -> "\\\\localhost\\c$\\tmp\\"69                                // res = res.Slice(2, retValue - 3);70                                // res[0] = '\\';71                                // res[^1] = '\\';72                            }73                            // else if (res[^3] == ':')74                            // {75                            //     Diagnostics.Assert(false, "Really it is a dead code since GetDosDevice() is called only if PSDrive.DriveType == DriveType.Network");76 77                            //     // The substed path is the root path of a drive. For example: subst Y: C:\78                            //     // -> "C:\0\0" -> "C:\"79                            //     res = res.Slice(0, retValue - 1);80                            //     res[^1] = '\\';81                            // }82                            else83                            {84                                throw new Exception("GetDosDeviceForNetworkPath() can be called only if PSDrive.DriveType == DriveType.Network.");85                            }86 87                            return res.ToString();88                        }89                        else90                        {91                            Diagnostics.Assert(false, "Really it is a dead code since GetDosDevice() is called only if PSDrive.DriveType == DriveType.Network");92 93                            // The drive name is not a substed path, then we return the root path of the drive94                            // "C:\0" -> "C:\\"95                            fullDeviceName[^1] = '\\';96                            return fullDeviceName.ToString();97                        }98                    }99 100                    const int ERROR_INSUFFICIENT_BUFFER = 122;101                    int errorCode = Marshal.GetLastPInvokeError();102                    if (errorCode != ERROR_INSUFFICIENT_BUFFER)103                    {104                        throw new Win32Exception((int)errorCode);105                    }106 107                    char[]? toReturn = rentedArray;108                    buffer = rentedArray = ArrayPool<char>.Shared.Rent(buffer.Length * 2);109                    if (toReturn is not null)110                    {111                        ArrayPool<char>.Shared.Return(toReturn);112                    }113                }114            }115            finally116            {117                if (rentedArray is not null)118                {119                    ArrayPool<char>.Shared.Return(rentedArray);120                }121            }122        }123    }124}125