[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void SingleOperationOverSingleHandle() { const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"SingleOverlappedOverSingleHandle.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext result = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; data[0] = (byte)'A'; data[1] = (byte)'B'; NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result, data); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastPInvokeError()); } // Wait for overlapped operation to complete result.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); boundHandle.Dispose(); handle.Dispose(); Assert.Equal(0, result.ErrorCode); Assert.Equal(DATA_SIZE, result.BytesWritten); }
public void LastPInvokeError_RoundTrip() { int errorExpected = 123; Marshal.SetLastPInvokeError(errorExpected); Assert.Equal(errorExpected, Marshal.GetLastPInvokeError()); }
internal static void ValidateFileTypeForNonExtendedPaths(SafeFileHandle handle, string originalPath) { if (!PathInternal.IsExtended(originalPath)) { // To help avoid stumbling into opening COM/LPT ports by accident, we will block on non file handles unless // we were explicitly passed a path that has \\?\. GetFullPath() will turn paths like C:\foo\con.txt into // \\.\CON, so we'll only allow the \\?\ syntax. int fileType = handle.GetFileType(); if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK) { int errorCode = fileType == Interop.Kernel32.FileTypes.FILE_TYPE_UNKNOWN ? Marshal.GetLastPInvokeError() : Interop.Errors.ERROR_SUCCESS; handle.Dispose(); if (errorCode != Interop.Errors.ERROR_SUCCESS) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); } } }
private static unsafe void ThrowExceptionEncryptDecryptFail(string fullPath) { int errorCode = Marshal.GetLastPInvokeError(); if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED) { // Check to see if the file system support the Encrypted File System (EFS) string name = DriveInfoInternal.NormalizeDriveName(Path.GetPathRoot(fullPath) !); using (DisableMediaInsertionPrompt.Create()) { if (!Interop.Kernel32.GetVolumeInformation(name, null, 0, null, null, out int fileSystemFlags, null, 0)) { errorCode = Marshal.GetLastPInvokeError(); throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } if ((fileSystemFlags & Interop.Kernel32.FILE_SUPPORTS_ENCRYPTION) == 0) { throw new NotSupportedException(SR.PlatformNotSupported_FileEncryption); } } } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); }
// // Wrapper around advapi32.CreateWellKnownSid // internal static int CreateWellKnownSid( WellKnownSidType sidType, SecurityIdentifier?domainSid, out byte[]?resultSid ) { // // Passing an array as big as it can ever be is a small price to pay for // not having to P/Invoke twice (once to get the buffer, once to get the data) // uint length = (uint)SecurityIdentifier.MaxBinaryLength; resultSid = new byte[length]; if (FALSE != Interop.Advapi32.CreateWellKnownSid((int)sidType, domainSid?.BinaryForm, resultSid, ref length)) { return(Interop.Errors.ERROR_SUCCESS); } else { resultSid = null; return(Marshal.GetLastPInvokeError()); } }
private unsafe ICertificatePal?CopyWithPersistedCapiKey(CspKeyContainerInfo keyContainerInfo) { if (string.IsNullOrEmpty(keyContainerInfo.KeyContainerName)) { return(null); } // Make a new pal from bytes. CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet); Interop.Crypt32.CRYPT_KEY_PROV_INFO keyProvInfo = default; fixed(char *keyName = keyContainerInfo.KeyContainerName) fixed(char *provName = keyContainerInfo.ProviderName) { keyProvInfo.pwszContainerName = keyName; keyProvInfo.pwszProvName = provName; keyProvInfo.dwFlags = keyContainerInfo.MachineKeyStore ? Interop.Crypt32.CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET : 0; keyProvInfo.dwProvType = keyContainerInfo.ProviderType; keyProvInfo.dwKeySpec = (int)keyContainerInfo.KeyNumber; if (!Interop.Crypt32.CertSetCertificateContextProperty( pal._certContext, Interop.Crypt32.CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, Interop.Crypt32.CertSetPropertyFlags.None, &keyProvInfo)) { Exception e = Marshal.GetLastPInvokeError().ToCryptographicException(); pal.Dispose(); throw e; } } return(pal); }
private static unsafe void Preallocate(string fullPath, long preallocationSize, SafeFileHandle fileHandle) { var allocationInfo = new Interop.Kernel32.FILE_ALLOCATION_INFO { AllocationSize = preallocationSize }; if (!Interop.Kernel32.SetFileInformationByHandle( fileHandle, Interop.Kernel32.FileAllocationInfo, &allocationInfo, (uint)sizeof(Interop.Kernel32.FILE_ALLOCATION_INFO))) { int errorCode = Marshal.GetLastPInvokeError(); // Only throw for errors that indicate there is not enough space. if (errorCode == Interop.Errors.ERROR_DISK_FULL || errorCode == Interop.Errors.ERROR_FILE_TOO_LARGE) { fileHandle.Dispose(); // Delete the file we've created. Interop.Kernel32.DeleteFile(fullPath); throw new IOException(SR.Format(errorCode == Interop.Errors.ERROR_DISK_FULL ? SR.IO_DiskFull_Path_AllocationSize : SR.IO_FileTooLarge_Path_AllocationSize, fullPath, preallocationSize)); } } }
/// <summary> /// Used by the 2 Create factory method groups. A null fileHandle specifies that the /// memory mapped file should not be associated with an existing file on disk (i.e. start /// out empty). /// </summary> private static SafeMemoryMappedFileHandle CreateCore( SafeFileHandle?fileHandle, string?mapName, HandleInheritability inheritability, MemoryMappedFileAccess access, MemoryMappedFileOptions options, long capacity, long fileSize) { Debug.Assert(fileHandle is null || fileSize >= 0); Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(inheritability); if (fileHandle != null) { VerifyMemoryMappedFileAccess(access, capacity, fileSize); } SafeMemoryMappedFileHandle handle = fileHandle != null? Interop.CreateFileMapping(fileHandle, ref secAttrs, GetPageAccess(access) | (int)options, capacity, mapName) : Interop.CreateFileMapping(new IntPtr(-1), ref secAttrs, GetPageAccess(access) | (int)options, capacity, mapName); int errorCode = Marshal.GetLastPInvokeError(); if (!handle.IsInvalid) { if (errorCode == Interop.Errors.ERROR_ALREADY_EXISTS) { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } } else // handle.IsInvalid { handle.Dispose(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } return(handle); }
// Flushes the changes such that they are in sync with the FileStream bits (ones obtained // with the win32 ReadFile and WriteFile functions). Need to call FileStream's Flush to // flush to the disk. // NOTE: This will flush all bytes before and after the view up until an offset that is a multiple // of SystemPageSize. public unsafe void Flush(UIntPtr capacity) { byte *firstPagePtr = null; try { _viewHandle.AcquirePointer(ref firstPagePtr); if (Interop.Kernel32.FlushViewOfFile((IntPtr)firstPagePtr, capacity)) { return; } // It is a known issue within the NTFS transaction log system that // causes FlushViewOfFile to intermittently fail with ERROR_LOCK_VIOLATION // As a workaround, we catch this particular error and retry the flush operation // a few milliseconds later. If it does not work, we give it a few more tries with // increasing intervals. Eventually, however, we need to give up. In ad-hoc tests // this strategy successfully flushed the view after no more than 3 retries. int error = Marshal.GetLastPInvokeError(); if (error != Interop.Errors.ERROR_LOCK_VIOLATION) { throw Win32Marshal.GetExceptionForWin32Error(error); } SpinWait spinWait = default; for (int w = 0; w < MaxFlushWaits; w++) { int pause = (1 << w); // MaxFlushRetries should never be over 30 Thread.Sleep(pause); for (int r = 0; r < MaxFlushRetriesPerWait; r++) { if (Interop.Kernel32.FlushViewOfFile((IntPtr)firstPagePtr, capacity)) { return; } error = Marshal.GetLastPInvokeError(); if (error != Interop.Errors.ERROR_LOCK_VIOLATION) { throw Win32Marshal.GetExceptionForWin32Error(error); } spinWait.SpinOnce(); } } // We got to here, so there was no success: throw Win32Marshal.GetExceptionForWin32Error(error); } finally { if (firstPagePtr != null) { _viewHandle.ReleasePointer(); } } }
private void CreateEventCore(bool initialState, EventResetMode mode, string?name, out bool createdNew) { #if TARGET_UNIX || TARGET_BROWSER if (name != null) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); } #endif uint eventFlags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0; if (mode == EventResetMode.ManualReset) { eventFlags |= (uint)Interop.Kernel32.CREATE_EVENT_MANUAL_RESET; } SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(IntPtr.Zero, name, eventFlags, AccessRights); int errorCode = Marshal.GetLastPInvokeError(); if (handle.IsInvalid) { handle.SetHandleAsInvalid(); if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); } throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS; SafeWaitHandle = handle; }
private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle?result) { #if TARGET_WINDOWS ArgumentException.ThrowIfNullOrEmpty(name); result = null; SafeWaitHandle myHandle = Interop.Kernel32.OpenEvent(AccessRights, false, name); if (myHandle.IsInvalid) { int errorCode = Marshal.GetLastPInvokeError(); if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME) { return(OpenExistingResult.NameNotFound); } if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND) { return(OpenExistingResult.PathNotFound); } if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { return(OpenExistingResult.NameInvalid); } throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } result = new EventWaitHandle(myHandle); return(OpenExistingResult.Success); #else throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); #endif }
private static OpenExistingResult OpenExistingWorker(string name, out Semaphore?result) { #if TARGET_WINDOWS ArgumentException.ThrowIfNullOrEmpty(name); // Pass false to OpenSemaphore to prevent inheritedHandles SafeWaitHandle myHandle = Interop.Kernel32.OpenSemaphore(AccessRights, false, name); if (myHandle.IsInvalid) { result = null; int errorCode = Marshal.GetLastPInvokeError(); if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME) { return(OpenExistingResult.NameNotFound); } if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND) { return(OpenExistingResult.PathNotFound); } if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { return(OpenExistingResult.NameInvalid); } // this is for passed through NativeMethods Errors throw Win32Marshal.GetExceptionForLastWin32Error(); } result = new Semaphore(myHandle); return(OpenExistingResult.Success); #else throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); #endif }
private void CreateSemaphoreCore(int initialCount, int maximumCount, string?name, out bool createdNew) { Debug.Assert(initialCount >= 0); Debug.Assert(maximumCount >= 1); Debug.Assert(initialCount <= maximumCount); #if TARGET_UNIX || TARGET_BROWSER if (name != null) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives); } #endif SafeWaitHandle myHandle = Interop.Kernel32.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights); int errorCode = Marshal.GetLastPInvokeError(); if (myHandle.IsInvalid) { if (!string.IsNullOrEmpty(name) && errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { throw new WaitHandleCannotBeOpenedException( SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); } throw Win32Marshal.GetExceptionForLastWin32Error(); } createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS; this.SafeWaitHandle = myHandle; }
/// <summary> /// Calls GetFullPathName on the given path. /// </summary> /// <param name="path">The path name. MUST be null terminated after the span.</param> /// <param name="builder">Builder that will store the result.</param> private static void GetFullPathName(ReadOnlySpan <char> path, ref ValueStringBuilder builder) { // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. Debug.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path)); uint result; while ((result = Interop.Kernel32.GetFullPathNameW(ref MemoryMarshal.GetReference(path), (uint)builder.Capacity, ref builder.GetPinnableReference(), IntPtr.Zero)) > builder.Capacity) { // Reported size is greater than the buffer size. Increase the capacity. builder.EnsureCapacity(checked ((int)result)); } if (result == 0) { // Failure, get the error and throw int errorCode = Marshal.GetLastPInvokeError(); if (errorCode == 0) { errorCode = Interop.Errors.ERROR_BAD_PATHNAME; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, path.ToString()); } builder.Length = (int)result; }
// // SID Utilities // internal static string ConvertSidToSDDL(byte[] sid) { // To put the byte[] SID into SDDL, we use ConvertSidToStringSid. // Calling that requires we first copy the SID into native memory. IntPtr pSid = IntPtr.Zero; try { pSid = ConvertByteArrayToIntPtr(sid); if (Interop.Advapi32.ConvertSidToStringSid(pSid, out string sddlSid) != Interop.BOOL.FALSE) { return(sddlSid); } else { int lastErrorCode = Marshal.GetLastPInvokeError(); GlobalDebug.WriteLineIf( GlobalDebug.Warn, "Utils", "ConvertSidToSDDL: ConvertSidToStringSid failed, " + lastErrorCode); return(null); } } finally { if (pSid != IntPtr.Zero) { Marshal.FreeHGlobal(pSid); } } }
private static FileStream?OpenFirstAvailableDeviceInterface() { const int DIGCF_PRESENT = 0x2; const int DIGCF_DEVICEINTERFACE = 0x10; const int ERROR_NO_MORE_ITEMS = 259; HidD_GetHidGuid(out Guid HidGuid); IntPtr deviceInfoSet = SetupDiGetClassDevs(in HidGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); try { SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA(); deviceInfoData.cbSize = (uint)Marshal.SizeOf(deviceInfoData); uint deviceIndex = 0; while (SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex++, ref deviceInfoData)) { if (Marshal.GetLastPInvokeError() == ERROR_NO_MORE_ITEMS) { break; } SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA(); deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData); if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, in HidGuid, deviceIndex, ref deviceInterfaceData)) { continue; } SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA(); deviceInterfaceDetailData.cbSize = IntPtr.Size == 8 ? 8 : 6; uint size = (uint)Marshal.SizeOf(deviceInterfaceDetailData); if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, ref deviceInterfaceDetailData, size, ref size, IntPtr.Zero)) { continue; } string devicePath = deviceInterfaceDetailData.DevicePath; Assert.StartsWith(@"\\?\hid", devicePath); try { return(new FileStream(devicePath, FileMode.Open, FileAccess.Read, FileShare.Read, 0, FileOptions.Asynchronous)); } catch (Exception ex) when(ex is IOException || ex is UnauthorizedAccessException) { continue; // device has been locked by another process or we don't have permissions to access it } } } finally { SetupDiDestroyDeviceInfoList(deviceInfoSet); } return(null); }
public static void Mount(string volumeName, string mountPoint) { if (volumeName[volumeName.Length - 1] != Path.DirectorySeparatorChar) { volumeName += Path.DirectorySeparatorChar; } if (mountPoint[mountPoint.Length - 1] != Path.DirectorySeparatorChar) { mountPoint += Path.DirectorySeparatorChar; } Console.WriteLine(string.Format("Mounting volume {0} at {1}", volumeName, mountPoint)); bool r; StringBuilder sb = new StringBuilder(1024); r = GetVolumeNameForVolumeMountPoint(volumeName, sb, sb.Capacity); if (!r) { throw new Exception(string.Format("Win32 error: {0}", Marshal.GetLastPInvokeError())); } string uniqueName = sb.ToString(); Console.WriteLine(string.Format("uniqueName: <{0}>", uniqueName)); r = SetVolumeMountPoint(mountPoint, uniqueName); if (!r) { throw new Exception(string.Format("Win32 error: {0}", Marshal.GetLastPInvokeError())); } Task.Delay(100).Wait(); // adding sleep for the file system to settle down so that reparse point mounting works }
private static unsafe void Preallocate(string fullPath, long preallocationSize, SafeFileHandle fileHandle) { var allocationInfo = new Interop.Kernel32.FILE_ALLOCATION_INFO { AllocationSize = preallocationSize }; if (!Interop.Kernel32.SetFileInformationByHandle( fileHandle, Interop.Kernel32.FileAllocationInfo, &allocationInfo, (uint)sizeof(Interop.Kernel32.FILE_ALLOCATION_INFO))) { int errorCode = Marshal.GetLastPInvokeError(); // we try to mimic the atomic NtCreateFile here: // if preallocation fails, close the handle and delete the file fileHandle.Dispose(); Interop.Kernel32.DeleteFile(fullPath); switch (errorCode) { case Interop.Errors.ERROR_DISK_FULL: throw new IOException(SR.Format(SR.IO_DiskFull_Path_AllocationSize, fullPath, preallocationSize)); case Interop.Errors.ERROR_FILE_TOO_LARGE: throw new IOException(SR.Format(SR.IO_FileTooLarge_Path_AllocationSize, fullPath, preallocationSize)); default: throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } } }
private ICertificatePal CopyWithEphemeralKey(CngKey cngKey) { Debug.Assert(string.IsNullOrEmpty(cngKey.KeyName)); // Handle makes a copy of the handle. This is required given that CertSetCertificateContextProperty accepts a SafeHandle // and transfers ownership of the handle to the certificate. We can't transfer that ownership out of the cngKey, as it's // owned by the caller, so we make a copy (using Handle rather than HandleNoDuplicate). using (SafeNCryptKeyHandle handle = cngKey.Handle) { // Make a new pal from bytes. CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet); try { if (!Interop.Crypt32.CertSetCertificateContextProperty( pal._certContext, Interop.Crypt32.CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID, Interop.Crypt32.CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, handle)) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } // The value was transferred to the certificate. handle.SetHandleAsInvalid(); return(pal); } catch { pal.Dispose(); throw; } } }
private static void SetEnvironmentVariableCore(string variable, string?value) { if (!Interop.Kernel32.SetEnvironmentVariable(variable, value)) { int errorCode = Marshal.GetLastPInvokeError(); switch (errorCode) { case Interop.Errors.ERROR_ENVVAR_NOT_FOUND: // Allow user to try to clear a environment variable return; case Interop.Errors.ERROR_FILENAME_EXCED_RANGE: // The error message from Win32 is "The filename or extension is too long", // which is not accurate. throw new ArgumentException(SR.Argument_LongEnvVarValue); case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY: case Interop.Errors.ERROR_NO_SYSTEM_RESOURCES: throw new OutOfMemoryException(Interop.Kernel32.GetMessage(errorCode)); default: throw new ArgumentException(Interop.Kernel32.GetMessage(errorCode)); } } }
internal long GetFileLength() { if (!_lengthCanBeCached) { return(GetFileLengthCore()); } // On Windows, when the file is locked for writes we can cache file length // in memory and avoid subsequent native calls which are expensive. if (_length < 0) { _length = GetFileLengthCore(); } return(_length); unsafe long GetFileLengthCore() { Interop.Kernel32.FILE_STANDARD_INFO info; if (Interop.Kernel32.GetFileInformationByHandleEx(this, Interop.Kernel32.FileStandardInfo, &info, (uint)sizeof(Interop.Kernel32.FILE_STANDARD_INFO))) { return(info.EndOfFile); } // In theory when GetFileInformationByHandleEx fails, then // a) IsDevice can modify last error (not true today, but can be in the future), // b) DeviceIoControl can succeed (last error set to ERROR_SUCCESS) but return fewer bytes than requested. // The error is stored and in such cases exception for the first failure is going to be thrown. int lastError = Marshal.GetLastPInvokeError(); if (Path is null || !PathInternal.IsDevice(Path)) { throw Win32Marshal.GetExceptionForWin32Error(lastError, Path); } Interop.Kernel32.STORAGE_READ_CAPACITY storageReadCapacity; bool success = Interop.Kernel32.DeviceIoControl( this, dwIoControlCode: Interop.Kernel32.IOCTL_STORAGE_READ_CAPACITY, lpInBuffer: null, nInBufferSize: 0, lpOutBuffer: &storageReadCapacity, nOutBufferSize: (uint)sizeof(Interop.Kernel32.STORAGE_READ_CAPACITY), out uint bytesReturned, IntPtr.Zero); if (!success) { throw Win32Marshal.GetExceptionForLastWin32Error(Path); } else if (bytesReturned != sizeof(Interop.Kernel32.STORAGE_READ_CAPACITY)) { throw Win32Marshal.GetExceptionForWin32Error(lastError, Path); } return(storageReadCapacity.DiskLength); } } }
// This will wait until the client calls Connect(). If we return from this method, we guarantee that // the client has returned from its Connect call. The client may have done so before this method // was called (but not before this server is been created, or, if we were servicing another client, // not before we called Disconnect), in which case, there may be some buffer already in the pipe waiting // for us to read. See NamedPipeClientStream.Connect for more information. public void WaitForConnection() { CheckConnectOperationsServerWithHandle(); if (IsAsync) { WaitForConnectionCoreAsync(CancellationToken.None).AsTask().GetAwaiter().GetResult(); } else { if (!Interop.Kernel32.ConnectNamedPipe(InternalHandle !, IntPtr.Zero)) { int errorCode = Marshal.GetLastPInvokeError(); if (errorCode != Interop.Errors.ERROR_PIPE_CONNECTED) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } // pipe already connected if (State == PipeState.Connected) { throw new InvalidOperationException(SR.InvalidOperation_PipeAlreadyConnected); } // If we reach here then a connection has been established. This can happen if a client // connects in the interval between the call to CreateNamedPipe and the call to ConnectNamedPipe. // In this situation, there is still a good connection between client and server, even though // ConnectNamedPipe returns zero. } State = PipeState.Connected; } }
private void CreateMutexCore(bool initiallyOwned, string?name, out bool createdNew) { uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0; SafeWaitHandle mutexHandle = Interop.Kernel32.CreateMutexEx(IntPtr.Zero, name, mutexFlags, AccessRights); int errorCode = Marshal.GetLastPInvokeError(); if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); #if TARGET_UNIX || TARGET_BROWSER if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE) { // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8 throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name)); } #endif if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name)); } throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS; SafeWaitHandle = mutexHandle; }
protected override string GetTestFilePath(int?index = null, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { string filePath = Path.GetFullPath(base.GetTestFilePath(index, memberName, lineNumber)); string drive = Path.GetPathRoot(filePath); StringBuilder volumeNameBuffer = new StringBuilder(filePath.Length + 1024); // the following method maps drive letter like "C:\" to a DeviceID (a DOS device path) // example: "\\?\Volume{724edb31-eaa5-4728-a4e3-f2474fd34ae2}\" if (!GetVolumeNameForVolumeMountPoint(drive, volumeNameBuffer, volumeNameBuffer.Capacity)) { throw new Win32Exception(Marshal.GetLastPInvokeError(), "GetVolumeNameForVolumeMountPoint failed"); } // instead of: // 'C:\Users\x\AppData\Local\Temp\y\z // we want something like: // '\\.\Volume{724edb31-eaa5-4728-a4e3-f2474fd34ae2}\Users\x\AppData\Local\Temp\y\z string devicePath = filePath.Replace(drive, volumeNameBuffer.ToString()); Assert.StartsWith(@"\\?\", devicePath); #if DEBUG // we do want to test \\.\ prefix as well devicePath = devicePath.Replace(@"\\?\", @"\\.\"); #endif return(devicePath); }
// // Wrapper around avdapi32.GetWindowsAccountDomainSid // internal static int GetWindowsAccountDomainSid( SecurityIdentifier sid, out SecurityIdentifier?resultSid ) { // // Passing an array as big as it can ever be is a small price to pay for // not having to P/Invoke twice (once to get the buffer, once to get the data) // byte[] BinaryForm = new byte[sid.BinaryLength]; sid.GetBinaryForm(BinaryForm, 0); uint sidLength = (uint)SecurityIdentifier.MaxBinaryLength; byte[] resultSidBinary = new byte[sidLength]; if (FALSE != Interop.Advapi32.GetWindowsAccountDomainSid(BinaryForm, resultSidBinary, ref sidLength)) { resultSid = new SecurityIdentifier(resultSidBinary, 0); return(Interop.Errors.ERROR_SUCCESS); } else { resultSid = null; return(Marshal.GetLastPInvokeError()); } }
public X509ContentType GetCertContentType(ReadOnlySpan <byte> rawData) { Interop.Crypt32.ContentType contentType; unsafe { fixed(byte *pRawData = rawData) { Interop.Crypt32.DATA_BLOB certBlob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData), (uint)rawData.Length); if (!Interop.Crypt32.CryptQueryObject( Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_BLOB, &certBlob, Interop.Crypt32.ExpectedContentTypeFlags.CERT_QUERY_CONTENT_FLAG_ALL, Interop.Crypt32.ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL, 0, IntPtr.Zero, out contentType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } } } return(MapContentType(contentType)); }
public static void LastErrorHasExpectedValue() { // Default (same behaviour as SetLastError=false) { int expected = Marshal.GetLastPInvokeError(); SetLastErrorNative.SetError_Default(expected + 1, shouldSetError: true); int actual = Marshal.GetLastPInvokeError(); Assert.Equal(expected, actual); } // SetLastError=false { int expected = Marshal.GetLastPInvokeError(); SetLastErrorNative.SetError_False(expected + 1, shouldSetError: true); int actual = Marshal.GetLastPInvokeError(); Assert.Equal(expected, actual); } // SetLastError=true { int expected = Marshal.GetLastPInvokeError(); expected++; SetLastErrorNative.SetError_True(expected, shouldSetError: true); int actual = Marshal.GetLastPInvokeError(); Assert.Equal(expected, actual); } }
public X509ContentType GetCertContentType(string fileName) { Interop.Crypt32.ContentType contentType; unsafe { fixed(char *pFileName = fileName) { if (!Interop.Crypt32.CryptQueryObject( Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_FILE, pFileName, Interop.Crypt32.ExpectedContentTypeFlags.CERT_QUERY_CONTENT_FLAG_ALL, Interop.Crypt32.ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL, 0, IntPtr.Zero, out contentType, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } } } return(MapContentType(contentType)); }
internal static int GetLastWin32ErrorAndDisposeHandleIfInvalid(SafeFileHandle handle) { int errorCode = Marshal.GetLastPInvokeError(); // If ERROR_INVALID_HANDLE is returned, it doesn't suffice to set // the handle as invalid; the handle must also be closed. // // Marking the handle as invalid but not closing the handle // resulted in exceptions during finalization and locked column // values (due to invalid but unclosed handle) in SQL Win32FileStream // scenarios. // // A more mainstream scenario involves accessing a file on a // network share. ERROR_INVALID_HANDLE may occur because the network // connection was dropped and the server closed the handle. However, // the client side handle is still open and even valid for certain // operations. // // Note that _parent.Dispose doesn't throw so we don't need to special case. // SetHandleAsInvalid only sets _closed field to true (without // actually closing handle) so we don't need to call that as well. if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { handle.Dispose(); } return(errorCode); }
internal static unsafe int ForkAndExecProcess( string filename, string[] argv, string[] envp, string?cwd, bool redirectStdin, bool redirectStdout, bool redirectStderr, bool setUser, uint userId, uint groupId, uint[]?groups, out int lpChildPid, out int stdinFd, out int stdoutFd, out int stderrFd, bool shouldThrow = true) { byte **argvPtr = null, envpPtr = null; int result = -1; try { AllocNullTerminatedArray(argv, ref argvPtr); AllocNullTerminatedArray(envp, ref envpPtr); fixed(uint *pGroups = groups) { result = ForkAndExecProcess( filename, argvPtr, envpPtr, cwd, redirectStdin ? 1 : 0, redirectStdout ? 1 : 0, redirectStderr ? 1 :0, setUser ? 1 : 0, userId, groupId, pGroups, groups?.Length ?? 0, out lpChildPid, out stdinFd, out stdoutFd, out stderrFd); } return(result == 0 ? 0 : Marshal.GetLastPInvokeError()); } finally { FreeArray(envpPtr, envp.Length); FreeArray(argvPtr, argv.Length); } }