[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);
    }
コード例 #2
0
        public void LastPInvokeError_RoundTrip()
        {
            int errorExpected = 123;

            Marshal.SetLastPInvokeError(errorExpected);
            Assert.Equal(errorExpected, Marshal.GetLastPInvokeError());
        }
コード例 #3
0
        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);
                }
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
ファイル: Win32.cs プロジェクト: mikem8361/runtime
        //
        // 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());
            }
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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));
                }
            }
        }
コード例 #8
0
        /// <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);
        }
コード例 #9
0
        // 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();
                }
            }
        }
コード例 #10
0
        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;
        }
コード例 #11
0
        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
        }
コード例 #12
0
        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
        }
コード例 #13
0
        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;
        }
コード例 #14
0
        /// <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;
        }
コード例 #15
0
        //
        // 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);
                }
            }
        }
コード例 #16
0
        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);
        }
コード例 #17
0
    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
    }
コード例 #18
0
        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);
                }
            }
        }
コード例 #19
0
        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;
                }
            }
        }
コード例 #20
0
        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));
                }
            }
        }
コード例 #21
0
        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);
            }
        }
    }
コード例 #22
0
        // 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;
            }
        }
コード例 #23
0
        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;
        }
コード例 #24
0
        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);
        }
コード例 #25
0
ファイル: Win32.cs プロジェクト: mikem8361/runtime
        //
        // 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());
            }
        }
コード例 #26
0
        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));
        }
コード例 #27
0
    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);
        }
    }
コード例 #28
0
        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));
        }
コード例 #29
0
        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);
        }
コード例 #30
0
        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);
            }
        }