public unsafe static string GetCaseSensitivePath(string path) { using SafeFileHandle hFile = PInvoke.CreateFile( lpFileName: path, dwDesiredAccess: (FILE_ACCESS_FLAGS) 0, dwShareMode: FILE_SHARE_FLAGS.FILE_SHARE_READ | FILE_SHARE_FLAGS.FILE_SHARE_WRITE | FILE_SHARE_FLAGS.FILE_SHARE_DELETE, lpSecurityAttributes: null, dwCreationDisposition: FILE_CREATE_FLAGS.OPEN_EXISTING, dwFlagsAndAttributes: FILE_FLAGS_AND_ATTRIBUTES.FILE_FLAG_BACKUP_SEMANTICS, hTemplateFile: null); if (hFile.IsInvalid) { throw new Win32Exception(Marshal.GetLastWin32Error()); } Span <char> name = stackalloc char[1024]; uint size = PInvoke.GetFinalPathNameByHandle( hFile: hFile, lpszFilePath: (char *)Unsafe.AsPointer(ref name[0]), cchFilePath: (uint)name.Length, dwFlags: FILE_NAME.FILE_NAME_NORMALIZED); if (size == 0 || size > name.Length) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (name.StartsWith(@"\\?\")) { name = name.Slice(4); } return(MemoryMarshal.CreateReadOnlySpanFromNullTerminated((char *)Unsafe.AsPointer(ref name[0])).ToString()); }
public static unsafe IDictionary GetEnvironmentVariables() { // Format for GetEnvironmentStrings is: // [=HiddenVar=value\0]* [Variable=value\0]* \0 // See the description of Environment Blocks in MSDN's CreateProcess // page (null-terminated array of null-terminated strings). Note // the =HiddenVar's aren't always at the beginning. // Copy strings out, parsing into pairs and inserting into the table. // The first few environment variable entries start with an '='. // The current working directory of every drive (except for those drives // you haven't cd'ed into in your DOS window) are stored in the // environment block (as =C:=pwd) and the program's exit code is // as well (=ExitCode=00000000). char *stringPtr = Interop.Kernel32.GetEnvironmentStringsW(); if (stringPtr == null) { throw new OutOfMemoryException(); } try { var results = new Hashtable(); char *currentPtr = stringPtr; while (true) { ReadOnlySpan <char> variable = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(currentPtr); if (variable.IsEmpty) { break; } // Find the = separating the key and value. We skip entries that begin with =. We also skip entries that don't // have =, which can happen on some older OSes when the environment block gets corrupted. int i = variable.IndexOf('='); if (i > 0) { // Add the key and value. string key = new string(variable.Slice(0, i)); string value = new string(variable.Slice(i + 1)); try { // Add may throw if the environment block was corrupted leading to duplicate entries. // We allow such throws and eat them (rather than proactively checking for duplication) // to provide a non-fatal notification about the corruption. results.Add(key, value); } catch (ArgumentException) { } } // Move to the end of this variable, after its terminator. currentPtr += variable.Length + 1; } return(results); } finally { Interop.BOOL success = Interop.Kernel32.FreeEnvironmentStringsW(stringPtr); Debug.Assert(success != Interop.BOOL.FALSE); } }
public static unsafe void CreateReadOnlySpanFromNullTerminated_Char_Null() { Assert.True(MemoryMarshal.CreateReadOnlySpanFromNullTerminated((char *)null).IsEmpty); Assert.True(MemoryMarshal.CreateReadOnlySpanFromNullTerminated((byte *)null).IsEmpty); }
internal static nuint wcslen([NativeTypeName("wchar_t const*")] ushort * @_String) { return((uint)MemoryMarshal.CreateReadOnlySpanFromNullTerminated((char *)@_String).Length); }