示例#1
0
        private static readonly int BUF_LEN = 8192 + 8; //8 bytes for the leading USN

        #endregion Fields

        #region Methods

        public static bool Build_Volume_Mapping(SafeFileHandle roothandle, Win32Api.USN_JOURNAL_DATA currentUsnState, Action<Win32Api.UsnEntry> func)
        {
            Debug.WriteLine("Starting Build_Volume_Mapping");

            DateTime startTime = DateTime.Now;

            Win32Api.MFT_ENUM_DATA med;
            med.StartFileReferenceNumber = 0;
            med.LowUsn = 0;
            med.HighUsn = currentUsnState.NextUsn;

            using(var med_struct = new StructWrapper(med))
            using(var rawdata = new Raw_Array_Wrapper(BUF_LEN))
            {
                uint outBytesReturned = 0;

                while(Win32Api.DeviceIoControl(
                    roothandle.DangerousGetHandle(),
                    Win32Api.FSCTL_ENUM_USN_DATA,
                    med_struct.Ptr,
                    med_struct.Size,
                    rawdata.Ptr,
                    rawdata.Size,
                    out outBytesReturned,
                    IntPtr.Zero))
                {
                    outBytesReturned = outBytesReturned - sizeof(Int64);
                    IntPtr pUsnRecord = System.IntPtr.Add(rawdata.Ptr, sizeof(Int64));//need to skip 8 bytes because the first 8 bytes are to a usn number, which isnt in the structure
                    while(outBytesReturned > 60)
                    {
                        var usnEntry = new Win32Api.UsnEntry(pUsnRecord);
                        pUsnRecord = System.IntPtr.Add(pUsnRecord, (int)usnEntry.RecordLength);
                        func(usnEntry);

                        if(usnEntry.RecordLength > outBytesReturned)
                            outBytesReturned = 0;// prevent overflow
                        else
                            outBytesReturned -= usnEntry.RecordLength;
                    }
                    Marshal.WriteInt64(med_struct.Ptr, Marshal.ReadInt64(rawdata.Ptr, 0));//read the usn that we skipped and place it into the nextusn
                }
                var possiblerror = Marshal.GetLastWin32Error();
                if(possiblerror < 0)
                    throw new Win32Exception(possiblerror);
            }
            Debug.WriteLine("Time took: " + (DateTime.Now - startTime).TotalMilliseconds + "ms");
            return true;
        }
示例#2
0
 public static int Read(SafeFileHandle handle, byte[] buffer, int offset, int count)
 {
     #if __MonoCS__
     int r;
     fixed(byte *p = buffer) {
     do {
         r = (int) Syscall.read (handle.DangerousGetHandle().ToInt32(), p, (ulong) count);
     } while (UnixMarshal.ShouldRetrySyscall ((int) r));
     if(r == -1) {
         int errno = Marshal.GetLastWin32Error();
         if (errno == EAGAIN) {
             return 0;
         }
         throw new Win32Exception();
     }
     return r;
     }
     #else
     return 0;
     #endif
 }
示例#3
0
 public static long GetDiskSize(SafeFileHandle Handle)
 {
     if (Handle.IsInvalid || Handle.IsClosed) throw new Exception("Native.GetDiskSize: Invalid handle specified. It is closed or invalid.");
     long size = 0;
     uint returnedBytes;
     if (DeviceIoControl(Handle.DangerousGetHandle(), (uint)IOCTL_CONTROL_CODE_CONSTANTS.IOCTL_DISK_GET_LENGTH_INFO, IntPtr.Zero, 0, ref size, 8, out returnedBytes, IntPtr.Zero)) return size;
     Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     return 0;
 }
示例#4
0
        private void SetCompletionPort(SafeFileHandle completionPortHandle)
        {
            int length = Marshal.SizeOf(typeof(NativeMethods.JobObjectAssociateCompletionPort));
            IntPtr completionPortPtr = IntPtr.Zero;
            try
            {
                var completionPort = new NativeMethods.JobObjectAssociateCompletionPort
                {
                    CompletionKey = IntPtr.Zero,
                    CompletionPortHandle = completionPortHandle.DangerousGetHandle(),
                };

                completionPortPtr = Marshal.AllocHGlobal(length);

                Marshal.StructureToPtr(completionPort, completionPortPtr, false);

                if (!NativeMethods.SetInformationJobObject(handle, NativeMethods.JobObjectInfoClass.AssociateCompletionPortInformation, completionPortPtr, length))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                if (completionPortPtr != IntPtr.Zero)
                    Marshal.FreeHGlobal(completionPortPtr);
            }
        }
示例#5
0
        /// <summary>
        /// Wraps Win32 GetConsoleScreenBufferInfo
        /// Returns Console Screen Buffer Info
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// Handle for the console where the screen buffer info is obtained
        /// 
        /// </param>
        /// <returns>
        /// 
        /// info about the screen buffer. See the definition of CONSOLE_SCREEN_BUFFER_INFO
        /// 
        /// </returns>
        /// <exception cref="HostException">
        /// If Win32's GetConsoleScreenBufferInfo fails
        /// </exception>
        internal static CONSOLE_SCREEN_BUFFER_INFO GetConsoleScreenBufferInfo(ConsoleHandle consoleHandle)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
            bool result = NativeMethods.GetConsoleScreenBufferInfo(consoleHandle.DangerousGetHandle(), out bufferInfo);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "GetConsoleScreenBufferInfo",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.GetConsoleScreenBufferInfoExceptionTemplate);
                throw e;
            }

            return bufferInfo;
        }
示例#6
0
        /// <summary>
        /// Wraps Win32 GetNumberOfConsoleInputEvents
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where the number of console input events is obtained
        /// 
        /// </param>
        /// <returns>
        /// 
        /// number of console input events
        /// 
        /// </returns>
        /// <exception cref="HostException">
        /// If Win32's GetNumberOfConsoleInputEvents fails
        /// </exception>

        internal static int GetNumberOfConsoleInputEvents(ConsoleHandle consoleHandle)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            DWORD numEvents;
            bool result = NativeMethods.GetNumberOfConsoleInputEvents(consoleHandle.DangerousGetHandle(), out numEvents);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "GetNumberOfConsoleInputEvents",
                    ErrorCategory.ReadError, ConsoleControlStrings.GetNumberOfConsoleInputEventsExceptionTemplate);
                throw e;
            }

            return (int)numEvents;
        }
示例#7
0
        /// <summary>
        ///
        /// Reads input from the console device according to the mode in effect (see GetMode, SetMode) 
        /// 
        /// </summary>
        /// <param name="consoleHandle"></param>
        /// 
        /// Handle to the console device returned by GetInputHandle
        /// 
        /// <param name="initialContent">
        /// 
        /// Initial contents of the edit buffer, if any. charactersToRead should be at least as large as the length of this string.
        /// 
        /// </param>
        /// <param name="charactersToRead">
        /// 
        /// Number of characters to read from the device.
        /// 
        /// </param>
        /// <param name="endOnTab">
        /// 
        /// true to allow the user to terminate input by hitting the tab or shift-tab key, in addition to the enter key
        /// 
        /// </param>
        /// <param name="keyState">
        /// 
        /// bit mask indicating the state of the control/shift keys at the point input was terminated.
        /// 
        /// </param>
        /// <returns></returns>
        /// <exception cref="HostException">
        /// 
        /// If Win32's ReadConsole fails
        /// 
        /// </exception>

        internal static string ReadConsole(ConsoleHandle consoleHandle, string initialContent,
            int charactersToRead, bool endOnTab, out uint keyState)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");
            Dbg.Assert(initialContent != null, "if no initial content is desired, pass String.Empty");
            keyState = 0;

            CONSOLE_READCONSOLE_CONTROL control = new CONSOLE_READCONSOLE_CONTROL();

            control.nLength = (ULONG)Marshal.SizeOf(control);
            control.nInitialChars = (ULONG)initialContent.Length;
            control.dwControlKeyState = 0;
            if (endOnTab)
            {
                const int TAB = 0x9;

                control.dwCtrlWakeupMask = (1 << TAB);
            }

            DWORD charsReadUnused = 0;
            StringBuilder buffer = new StringBuilder(initialContent, charactersToRead);
            bool result =
                NativeMethods.ReadConsole(
                    consoleHandle.DangerousGetHandle(),
                    buffer,
                    (DWORD)charactersToRead,
                    out charsReadUnused,
                    ref control);
            keyState = control.dwControlKeyState;
            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "ReadConsole",
                    ErrorCategory.ReadError, ConsoleControlStrings.ReadConsoleExceptionTemplate);
                throw e;
            }
            if (charsReadUnused > (uint)buffer.Length)
                charsReadUnused = (uint)buffer.Length;
            return buffer.ToString(0, (int)charsReadUnused);
        }
示例#8
0
        /// <summary>
        /// Wraps Win32 SetConsoleCursorInfo
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where cursor info is set
        /// 
        /// </param>
        /// <param name="cursorInfo">
        /// 
        /// cursor info to set the cursor
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's SetConsoleCursorInfo fails
        /// </exception>

        internal static void SetConsoleCursorInfo(ConsoleHandle consoleHandle, CONSOLE_CURSOR_INFO cursorInfo)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            bool result = NativeMethods.SetConsoleCursorInfo(consoleHandle.DangerousGetHandle(), ref cursorInfo);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "SetConsoleCursorInfo",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.SetConsoleCursorInfoExceptionTemplate);
                throw e;
            }
        }
示例#9
0
        /// <summary>
        /// Wraps Win32 SetConsoleCursorPosition
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where cursor position is set
        ///
        /// </param>
        /// <param name="cursorPosition">
        /// 
        /// location to which the cursor will be set
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's SetConsoleCursorPosition fails
        /// </exception>

        internal static void SetConsoleCursorPosition(ConsoleHandle consoleHandle, Coordinates cursorPosition)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            ConsoleControl.COORD c;

            c.X = (short)cursorPosition.X;
            c.Y = (short)cursorPosition.Y;

            bool result = NativeMethods.SetConsoleCursorPosition(consoleHandle.DangerousGetHandle(), c);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "SetConsoleCursorPosition",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.SetConsoleCursorPositionExceptionTemplate);
                throw e;
            }
        }
示例#10
0
        /// <summary>
        /// set the output buffer's size
        /// </summary>
        /// <param name="consoleHandle"></param>
        /// <param name="newSize"></param>
        /// <exception cref="HostException">
        /// If Win32's SetConsoleScreenBufferSize fails
        /// </exception>

        internal static void SetConsoleScreenBufferSize(ConsoleHandle consoleHandle, Size newSize)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            COORD s;

            s.X = (short)newSize.Width;
            s.Y = (short)newSize.Height;

            bool result = NativeMethods.SetConsoleScreenBufferSize(consoleHandle.DangerousGetHandle(), s);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "SetConsoleScreenBufferSize",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.SetConsoleScreenBufferSizeExceptionTemplate);
                throw e;
            }
        }
示例#11
0
        private void OpenSqlFileStream
        (
            string path,
            byte[] transactionContext,
            System.IO.FileAccess access,
            System.IO.FileOptions options,
            Int64 allocationSize
        )
        {
            //-----------------------------------------------------------------
            // precondition validation

            // these should be checked by any caller of this method

            // ensure we have validated and normalized the path before
            Debug.Assert(path != null);
            Debug.Assert(transactionContext != null);

            if (access != FileAccess.Read && access != FileAccess.Write && access != FileAccess.ReadWrite)
            {
                throw ADP.ArgumentOutOfRange("access");
            }

            // FileOptions is a set of flags, so AND the given value against the set of values we do not support
            if ((options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.SequentialScan)) != 0)
            {
                throw ADP.ArgumentOutOfRange("options");
            }

            //-----------------------------------------------------------------

            // normalize the provided path
            //   * compress path to remove any occurences of '.' or '..'
            //   * trim whitespace from the beginning and end of the path
            //   * ensure that the path starts with '\\'
            //   * ensure that the path does not start with '\\.\'
            //   * ensure that the path is not longer than Int16.MaxValue
            path = GetFullPathInternal(path);

            // ensure the running code has permission to read/write the file
            DemandAccessPermission(path, access);

            FileFullEaInformation    eaBuffer   = null;
            SecurityQualityOfService qos        = null;
            UnicodeString            objectName = null;

            Microsoft.Win32.SafeHandles.SafeFileHandle hFile = null;

            int nDesiredAccess = UnsafeNativeMethods.FILE_READ_ATTRIBUTES | UnsafeNativeMethods.SYNCHRONIZE;

            UInt32 dwCreateOptions     = 0;
            UInt32 dwCreateDisposition = 0;

            System.IO.FileShare shareAccess = System.IO.FileShare.None;

            switch (access)
            {
            case System.IO.FileAccess.Read:
                nDesiredAccess     |= UnsafeNativeMethods.FILE_READ_DATA;
                shareAccess         = System.IO.FileShare.Delete | System.IO.FileShare.ReadWrite;
                dwCreateDisposition = (uint)UnsafeNativeMethods.CreationDisposition.FILE_OPEN;
                break;

            case System.IO.FileAccess.Write:
                nDesiredAccess     |= UnsafeNativeMethods.FILE_WRITE_DATA;
                shareAccess         = System.IO.FileShare.Delete | System.IO.FileShare.Read;
                dwCreateDisposition = (uint)UnsafeNativeMethods.CreationDisposition.FILE_OVERWRITE;
                break;

            case System.IO.FileAccess.ReadWrite:
            default:
                // we validate the value of 'access' parameter in the beginning of this method
                Debug.Assert(access == System.IO.FileAccess.ReadWrite);

                nDesiredAccess     |= UnsafeNativeMethods.FILE_READ_DATA | UnsafeNativeMethods.FILE_WRITE_DATA;
                shareAccess         = System.IO.FileShare.Delete | System.IO.FileShare.Read;
                dwCreateDisposition = (uint)UnsafeNativeMethods.CreationDisposition.FILE_OVERWRITE;
                break;
            }

            if ((options & System.IO.FileOptions.WriteThrough) != 0)
            {
                dwCreateOptions |= (uint)UnsafeNativeMethods.CreateOption.FILE_WRITE_THROUGH;
            }

            if ((options & System.IO.FileOptions.Asynchronous) == 0)
            {
                dwCreateOptions |= (uint)UnsafeNativeMethods.CreateOption.FILE_SYNCHRONOUS_IO_NONALERT;
            }

            if ((options & System.IO.FileOptions.SequentialScan) != 0)
            {
                dwCreateOptions |= (uint)UnsafeNativeMethods.CreateOption.FILE_SEQUENTIAL_ONLY;
            }

            if ((options & System.IO.FileOptions.RandomAccess) != 0)
            {
                dwCreateOptions |= (uint)UnsafeNativeMethods.CreateOption.FILE_RANDOM_ACCESS;
            }

            try
            {
                eaBuffer = new FileFullEaInformation(transactionContext);

                qos = new SecurityQualityOfService(UnsafeNativeMethods.SecurityImpersonationLevel.SecurityAnonymous,
                                                   false, false);

                // NOTE: the Name property is intended to reveal the publicly available moniker for the
                //   FILESTREAM attributed column data. We will not surface the internal processing that
                //   takes place to create the mappedPath.
                string mappedPath = InitializeNtPath(path);
                objectName = new UnicodeString(mappedPath);

                UnsafeNativeMethods.OBJECT_ATTRIBUTES oa;
                oa.length                   = Marshal.SizeOf(typeof(UnsafeNativeMethods.OBJECT_ATTRIBUTES));
                oa.rootDirectory            = IntPtr.Zero;
                oa.attributes               = (int)UnsafeNativeMethods.Attributes.CaseInsensitive;
                oa.securityDescriptor       = IntPtr.Zero;
                oa.securityQualityOfService = qos;
                oa.objectName               = objectName;

                UnsafeNativeMethods.IO_STATUS_BLOCK ioStatusBlock;

                uint oldMode;
                uint retval = 0;

                UnsafeNativeMethods.SetErrorModeWrapper(UnsafeNativeMethods.SEM_FAILCRITICALERRORS, out oldMode);
                try
                {
                    Bid.Trace("<sc.SqlFileStream.OpenSqlFileStream|ADV> %d#, desiredAccess=0x%08x, allocationSize=%I64d, fileAttributes=0x%08x, shareAccess=0x%08x, dwCreateDisposition=0x%08x, createOptions=0x%08x\n",
                              ObjectID, (int)nDesiredAccess, allocationSize, 0, (int)shareAccess, dwCreateDisposition, dwCreateOptions);

                    retval = UnsafeNativeMethods.NtCreateFile(out hFile, nDesiredAccess,
                                                              ref oa, out ioStatusBlock, ref allocationSize,
                                                              0, shareAccess, dwCreateDisposition, dwCreateOptions,
                                                              eaBuffer, (uint)eaBuffer.Length);
                }
                finally
                {
                    UnsafeNativeMethods.SetErrorModeWrapper(oldMode, out oldMode);
                }

                switch (retval)
                {
                case 0:
                    break;

                case UnsafeNativeMethods.STATUS_SHARING_VIOLATION:
                    throw ADP.InvalidOperation(Res.GetString(Res.SqlFileStream_FileAlreadyInTransaction));

                case UnsafeNativeMethods.STATUS_INVALID_PARAMETER:
                    throw ADP.Argument(Res.GetString(Res.SqlFileStream_InvalidParameter));

                case UnsafeNativeMethods.STATUS_OBJECT_NAME_NOT_FOUND:
                {
                    System.IO.DirectoryNotFoundException e = new System.IO.DirectoryNotFoundException();
                    ADP.TraceExceptionAsReturnValue(e);
                    throw e;
                }

                default:
                {
                    uint error = UnsafeNativeMethods.RtlNtStatusToDosError(retval);
                    if (error == UnsafeNativeMethods.ERROR_MR_MID_NOT_FOUND)
                    {
                        // status code could not be mapped to a Win32 error code
                        error = retval;
                    }

                    System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(unchecked ((int)error));
                    ADP.TraceExceptionAsReturnValue(e);
                    throw e;
                }
                }

                if (hFile.IsInvalid)
                {
                    System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(UnsafeNativeMethods.ERROR_INVALID_HANDLE);
                    ADP.TraceExceptionAsReturnValue(e);
                    throw e;
                }

                UnsafeNativeMethods.FileType fileType = UnsafeNativeMethods.GetFileType(hFile);
                if (fileType != UnsafeNativeMethods.FileType.Disk)
                {
                    hFile.Dispose();
                    throw ADP.Argument(Res.GetString(Res.SqlFileStream_PathNotValidDiskResource));
                }

                // if the user is opening the SQL FileStream in read/write mode, we assume that they want to scan
                //   through current data and then append new data to the end, so we need to tell SQL Server to preserve
                //   the existing file contents.
                if (access == System.IO.FileAccess.ReadWrite)
                {
                    uint ioControlCode = UnsafeNativeMethods.CTL_CODE(UnsafeNativeMethods.FILE_DEVICE_FILE_SYSTEM,
                                                                      IoControlCodeFunctionCode, (byte)UnsafeNativeMethods.Method.METHOD_BUFFERED,
                                                                      (byte)UnsafeNativeMethods.Access.FILE_ANY_ACCESS);
                    uint cbBytesReturned = 0;

                    if (!UnsafeNativeMethods.DeviceIoControl(hFile, ioControlCode, IntPtr.Zero, 0, IntPtr.Zero, 0, out cbBytesReturned, IntPtr.Zero))
                    {
                        System.ComponentModel.Win32Exception e = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
                        ADP.TraceExceptionAsReturnValue(e);
                        throw e;
                    }
                }

                // now that we've successfully opened a handle on the path and verified that it is a file,
                //   use the SafeFileHandle to initialize our internal System.IO.FileStream instance
                // NOTE: need to assert UnmanagedCode permissions for this constructor. This is relatively benign
                //   in that we've done much the same validation as in the FileStream(string path, ...) ctor case
                //   most notably, validating that the handle type corresponds to an on-disk file.
                bool bRevertAssert = false;
                try
                {
                    SecurityPermission sp = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
                    sp.Assert();
                    bRevertAssert = true;

                    System.Diagnostics.Debug.Assert(m_fs == null);
#if MOBILE
                    m_fs = new System.IO.FileStream(hFile.DangerousGetHandle(), access, ((options & System.IO.FileOptions.Asynchronous) != 0), DefaultBufferSize);
#else
                    m_fs = new System.IO.FileStream(hFile, access, DefaultBufferSize, ((options & System.IO.FileOptions.Asynchronous) != 0));
#endif
                }
                finally
                {
                    if (bRevertAssert)
                    {
                        SecurityPermission.RevertAssert();
                    }
                }
            }
            catch
            {
                if (hFile != null && !hFile.IsInvalid)
                {
                    hFile.Dispose();
                }

                throw;
            }
            finally
            {
                if (eaBuffer != null)
                {
                    eaBuffer.Dispose();
                    eaBuffer = null;
                }

                if (qos != null)
                {
                    qos.Dispose();
                    qos = null;
                }

                if (objectName != null)
                {
                    objectName.Dispose();
                    objectName = null;
                }
            }
        }
示例#12
0
        public static void GetUsnJournalEntries(SafeFileHandle roothandle, Win32Api.USN_JOURNAL_DATA previousUsnState,
            UInt32 reasonMask,
            out List<Win32Api.UsnEntry> usnEntries,
            out Win32Api.USN_JOURNAL_DATA newUsnState)
        {
            usnEntries = new List<Win32Api.UsnEntry>();
            newUsnState = new Win32Api.USN_JOURNAL_DATA();

            QueryUsnJournal(roothandle, ref newUsnState);

            Win32Api.READ_USN_JOURNAL_DATA rujd = new Win32Api.READ_USN_JOURNAL_DATA();
            rujd.StartUsn = previousUsnState.NextUsn;
            rujd.ReasonMask = reasonMask;
            rujd.ReturnOnlyOnClose = 0;
            rujd.Timeout = 0;
            rujd.bytesToWaitFor = 0;
            rujd.UsnJournalId = previousUsnState.UsnJournalID;

            using(var med_struct = new StructWrapper(rujd))
            using(var rawdata = new Raw_Array_Wrapper(BUF_LEN))
            {
                uint outBytesReturned = 0;
                var nextusn = previousUsnState.NextUsn;
                while(nextusn < newUsnState.NextUsn && Win32Api.DeviceIoControl(
                         roothandle.DangerousGetHandle(),
                        Win32Api.FSCTL_READ_USN_JOURNAL,
                        med_struct.Ptr,
                        med_struct.Size,
                        rawdata.Ptr,
                        rawdata.Size,
                        out outBytesReturned,
                        IntPtr.Zero))
                {
                    outBytesReturned = outBytesReturned - sizeof(Int64);
                    IntPtr pUsnRecord = System.IntPtr.Add(rawdata.Ptr, sizeof(Int64));//point safe arithmetic!~!!
                    while(outBytesReturned > 60)   // while there are at least one entry in the usn journal
                    {
                        var usnEntry = new Win32Api.UsnEntry(pUsnRecord);
                        if(usnEntry.USN > newUsnState.NextUsn)
                            break;
                        usnEntries.Add(usnEntry);
                        pUsnRecord = System.IntPtr.Add(pUsnRecord, (int)usnEntry.RecordLength);//point safe arithmetic!~!!
                        outBytesReturned -= usnEntry.RecordLength;
                    }
                    nextusn = Marshal.ReadInt64(rawdata.Ptr, 0);
                    Marshal.WriteInt64(med_struct.Ptr, nextusn);//read the usn that we skipped and place it into the nextusn
                }
            }
        }
示例#13
0
        public static void QueryUsnJournal(SafeFileHandle roothandle, ref Win32Api.USN_JOURNAL_DATA usnJournalState)
        {
            int sizeUsnJournalState = Marshal.SizeOf(usnJournalState);
            UInt32 cb;
            if(!Win32Api.DeviceIoControl(
                   roothandle.DangerousGetHandle(),
                  Win32Api.FSCTL_QUERY_USN_JOURNAL,
                  IntPtr.Zero,
                  0,
                  out usnJournalState,
                  sizeUsnJournalState,
                  out cb,
                  IntPtr.Zero))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());

            }
        }
示例#14
0
		internal static int ReadConsoleInput(SafeFileHandle consoleHandle, ref ConsoleControl.INPUT_RECORD[] buffer)
		{
			int num = 0;
			bool flag = ConsoleControl.NativeMethods.ReadConsoleInput(consoleHandle.DangerousGetHandle(), buffer, buffer.Length, out num);
			if (flag)
			{
				return num;
			}
			else
			{
				int lastWin32Error = Marshal.GetLastWin32Error();
				HostException hostException = ConsoleControl.CreateHostException(lastWin32Error, "ReadConsoleInput", ErrorCategory.ReadError, ConsoleControlStrings.ReadConsoleInputExceptionTemplate);
				throw hostException;
			}
		}
示例#15
0
        private static void WriteConsoleOutputCJK(ConsoleHandle consoleHandle, Coordinates origin, Rectangle contentsRegion, BufferCell[,] contents, BufferCellArrayRowType rowType)
        {
            Dbg.Assert(origin.X >= 0 && origin.Y >= 0,
                "origin must be within the output buffer");
            int rows = contentsRegion.Bottom - contentsRegion.Top + 1;
            int cols = contentsRegion.Right - contentsRegion.Left + 1;

            CONSOLE_FONT_INFO_EX fontInfo = GetConsoleFontInfo(consoleHandle);
            int fontType = fontInfo.FontFamily & NativeMethods.FontTypeMask;
            bool trueTypeInUse = (fontType & NativeMethods.TrueTypeFont) == NativeMethods.TrueTypeFont;

            int bufferLimit = 2 * 1024; // Limit is 8K bytes as each CHAR_INFO takes 4 bytes

            COORD bufferCoord;

            bufferCoord.X = 0;
            bufferCoord.Y = 0;

            // keeps track of which screen area write
            SMALL_RECT writeRegion;

            writeRegion.Top = (short)origin.Y;

            int rowsRemaining = rows;

            while (rowsRemaining > 0)
            {
                // Iteration of columns is nested inside iteration of rows.
                // If the size of contents exceeds the buffer limit, writing is
                // done in blocks of size equal to the bufferlimit from left to right
                // then top to bottom.
                // For each iteration of rows,
                // - writeRegion.Left and bufferSize.X are reset
                // - rowsRemaining, writeRegion.Top, writeRegion.Bottom, and bufferSize.Y
                //     are updated
                //   For each iteration of columns,
                //   - writeRegion.Left, writeRegion.Right and bufferSize.X are updated

                writeRegion.Left = (short)origin.X;

                COORD bufferSize;

                bufferSize.X = (short)Math.Min(cols, bufferLimit);
                bufferSize.Y = (short)Math.Min
                                        (
                                            rowsRemaining,
                                            bufferLimit / bufferSize.X
                                        );
                writeRegion.Bottom = (short)(writeRegion.Top + bufferSize.Y - 1);

                // atRow is at which row of contents a particular iteration is operating
                int atRow = rows - rowsRemaining + contentsRegion.Top;

                // number of columns yet to be written
                int colsRemaining = cols;
                while (colsRemaining > 0)
                {
                    writeRegion.Right = (short)(writeRegion.Left + bufferSize.X - 1);

                    // atCol is at which column of contents a particular iteration is operating
                    int atCol = cols - colsRemaining + contentsRegion.Left;
                    // if this is not the last column iteration &&
                    //   the leftmost BufferCell is a leading cell, don't write that cell
                    if (colsRemaining > bufferSize.X &&
                         contents[atRow, atCol + bufferSize.X - 1].BufferCellType == BufferCellType.Leading)
                    {
                        bufferSize.X--;
                        writeRegion.Right--;
                    }
                    CHAR_INFO[] characterBuffer = new CHAR_INFO[bufferSize.Y * bufferSize.X];

                    // copy characterBuffer to contents;
                    int characterBufferIndex = 0;
                    bool lastCharIsLeading = false;
                    BufferCell lastLeadingCell = new BufferCell();
                    for (int r = atRow; r < bufferSize.Y + atRow; r++)
                    {
                        for (int c = atCol; c < bufferSize.X + atCol; c++, characterBufferIndex++)
                        {
                            if (contents[r, c].BufferCellType == BufferCellType.Complete)
                            {
                                characterBuffer[characterBufferIndex].UnicodeChar =
                                    (ushort)contents[r, c].Character;
                                characterBuffer[characterBufferIndex].Attributes =
                                    (ushort)(ColorToWORD(contents[r, c].ForegroundColor, contents[r, c].BackgroundColor));

                                lastCharIsLeading = false;
                            }
                            else if (contents[r, c].BufferCellType == BufferCellType.Leading)
                            {
                                characterBuffer[characterBufferIndex].UnicodeChar =
                                    (ushort)contents[r, c].Character;
                                characterBuffer[characterBufferIndex].Attributes =
                                    (ushort)(ColorToWORD(contents[r, c].ForegroundColor, contents[r, c].BackgroundColor)
                                                | (ushort)NativeMethods.CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE);

                                lastCharIsLeading = true;
                                lastLeadingCell = contents[r, c];
                            }
                            else if (contents[r, c].BufferCellType == BufferCellType.Trailing)
                            {
                                // The FontFamily is a 8-bit integer. The low-order bit (bit 0) specifies the pitch of the font. 
                                // If it is 1, the font is variable pitch (or proportional). If it is 0, the font is fixed pitch 
                                // (or monospace). Bits 1 and 2 specify the font type. If both bits are 0, the font is a raster font; 
                                // if bit 1 is 1 and bit 2 is 0, the font is a vector font; if bit 1 is 0 and bit 2 is set, or if both 
                                // bits are 1, the font is true type. Bit 3 is 1 if the font is a device font; otherwise, it is 0.
                                // We only care about the bit 1 and 2, which indicate the font type.
                                // There are only two font type defined for the Console, at
                                // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\.
                                //     Console\Nls           --- national language supports
                                //     Console\RasterFonts   --- raster type font
                                //     Console\TrueTypeFont  --- true type font
                                // For CJK characters, if it's TrueType, we need to output the trailing character marked with "Trailing_byte"
                                // attribute. But if it's RasterFont, we ignore the trailing character, and the "Leading_byte"/"Trailing_byte"
                                // attributes are not effective at all when reading the character from the console buffer.
                                if (lastCharIsLeading && trueTypeInUse)
                                {
                                    // For TrueType Font, we output the trailing byte with "Trailing_byte" attribute
                                    characterBuffer[characterBufferIndex].UnicodeChar = lastLeadingCell.Character;
                                    characterBuffer[characterBufferIndex].Attributes =
                                        (ushort)(ColorToWORD(contents[r, c].ForegroundColor, contents[r, c].BackgroundColor)
                                                | (ushort)NativeMethods.CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE);
                                }
                                else
                                {
                                    // We don't output anything for this cell if Raster font is in use, or if the last cell is not a leading byte
                                    characterBufferIndex--;
                                }
                                lastCharIsLeading = false;
                            }
                        }
                    }

                    // Now writeRegion, bufferSize and characterBuffer are updated.
                    // Call NativeMethods.WriteConsoleOutput
                    bool result;
                    if ((rowType & BufferCellArrayRowType.RightLeading) != 0 &&
                            colsRemaining == bufferSize.X)
                    {
                        COORD bSize = bufferSize;
                        bSize.X++;
                        SMALL_RECT wRegion = writeRegion;
                        wRegion.Right++;
                        // Suppress the PreFAST warning about not using Marshal.GetLastWin32Error() to
                        // get the error code.
#pragma warning disable 56523
                        result = NativeMethods.WriteConsoleOutput(
                            consoleHandle.DangerousGetHandle(),
                            characterBuffer,
                            bSize,
                            bufferCoord,
                            ref wRegion);
                    }
                    else
                    {
                        // Suppress the PreFAST warning about not using Marshal.GetLastWin32Error() to
                        // get the error code.
#pragma warning disable 56523
                        result = NativeMethods.WriteConsoleOutput(
                            consoleHandle.DangerousGetHandle(),
                            characterBuffer,
                            bufferSize,
                            bufferCoord,
                            ref writeRegion);
                    }
                    if (result == false)
                    {
                        // When WriteConsoleOutput fails, half bufferLimit
                        if (bufferLimit < 2)
                        {
                            int err = Marshal.GetLastWin32Error();
                            HostException e = CreateHostException(err, "WriteConsoleOutput",
                                ErrorCategory.WriteError, ConsoleControlStrings.WriteConsoleOutputExceptionTemplate);
                            throw e;
                        }
                        bufferLimit /= 2;
                        if (cols == colsRemaining)
                        {
                            // if cols == colsRemaining, nothing is guaranteed written in this pass and
                            //  the unwritten area is still rectangular
                            bufferSize.Y = 0;
                            break;
                        }
                        else
                        {
                            // some areas have been written. This could only happen when the number of columns
                            // to write is larger than bufferLimit. In that case, the algorithm writes one row
                            // at a time => bufferSize.Y == 1. Then, we can safely leave bufferSize.Y unchanged
                            // to retry with a smaller bufferSize.X.
                            Dbg.Assert(bufferSize.Y == 1, string.Format(CultureInfo.InvariantCulture, "bufferSize.Y should be 1, but is {0}", bufferSize.Y));
                            bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                            continue;
                        }
                    }

                    colsRemaining -= bufferSize.X;
                    writeRegion.Left += bufferSize.X;
                    bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                }  // column iteration

                rowsRemaining -= bufferSize.Y;
                writeRegion.Top += bufferSize.Y;
            }  // row iteration
        }
示例#16
0
        /// <summary>
        /// 
        /// Wrap Win32 WriteConsole
        /// 
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where the string is written
        /// 
        /// </param>
        /// <param name="output">
        /// 
        /// string that is written
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// 
        /// if the Win32's WriteConsole fails 
        /// 
        /// </exception>

        internal static void WriteConsole(ConsoleHandle consoleHandle, string output)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            if (String.IsNullOrEmpty(output))
                return;

            // Native WriteConsole doesn't support output buffer longer than 64K. 
            // We need to chop the output string if it is too long. 

            int cursor = 0; // This records the chopping position in output string
            const int maxBufferSize = 16383; // this is 64K/4 - 1 to account for possible width of each character.

            while (cursor < output.Length)
            {
                string outBuffer;

                if (cursor + maxBufferSize < output.Length)
                {
                    outBuffer = output.Substring(cursor, maxBufferSize);
                    cursor += maxBufferSize;
                }
                else
                {
                    outBuffer = output.Substring(cursor);
                    cursor = output.Length;
                }

                DWORD charsWritten;
                bool result =
                    NativeMethods.WriteConsole(
                        consoleHandle.DangerousGetHandle(),
                        outBuffer,
                        (DWORD)outBuffer.Length,
                        out charsWritten,
                        IntPtr.Zero);

                if (result == false)
                {
                    int err = Marshal.GetLastWin32Error();

                    HostException e = CreateHostException(err, "WriteConsole",
                        ErrorCategory.WriteError, ConsoleControlStrings.WriteConsoleExceptionTemplate);
                    throw e;
                }
            }
        }
示例#17
0
        private static void WriteConsoleOutputPlain(ConsoleHandle consoleHandle, Coordinates origin, BufferCell[,] contents)
        {
            int rows = contents.GetLength(0);
            int cols = contents.GetLength(1);

            if ((rows <= 0) || cols <= 0)
            {
                tracer.WriteLine("contents passed in has 0 rows and columns");
                return;
            }
            int bufferLimit = 2 * 1024; // Limit is 8K bytes as each CHAR_INFO takes 4 bytes

            COORD bufferCoord;

            bufferCoord.X = 0;
            bufferCoord.Y = 0;

            // keeps track of which screen area write
            SMALL_RECT writeRegion;

            writeRegion.Top = (short)origin.Y;

            int rowsRemaining = rows;

            while (rowsRemaining > 0)
            {
                // Iteration of columns is nested inside iteration of rows.
                // If the size of contents exceeds the buffer limit, writing is
                // done in blocks of size equal to the bufferlimit from left to right
                // then top to bottom.
                // For each iteration of rows,
                // - writeRegion.Left and bufferSize.X are reset
                // - rowsRemaining, writeRegion.Top, writeRegion.Bottom, and bufferSize.Y
                //     are updated
                //   For each iteration of columns,
                //   - writeRegion.Left, writeRegion.Right and bufferSize.X are updated

                writeRegion.Left = (short)origin.X;

                COORD bufferSize;

                bufferSize.X = (short)Math.Min(cols, bufferLimit);
                bufferSize.Y = (short)Math.Min
                                        (
                                            rowsRemaining,
                                            bufferLimit / bufferSize.X
                                        );
                writeRegion.Bottom = (short)(writeRegion.Top + bufferSize.Y - 1);

                // atRow is at which row of contents a particular iteration is operating
                int atRow = rows - rowsRemaining + contents.GetLowerBound(0);

                // number of columns yet to be written
                int colsRemaining = cols;

                while (colsRemaining > 0)
                {
                    writeRegion.Right = (short)(writeRegion.Left + bufferSize.X - 1);

                    // atCol is at which column of contents a particular iteration is operating
                    int atCol = cols - colsRemaining + contents.GetLowerBound(1);
                    CHAR_INFO[] characterBuffer = new CHAR_INFO[bufferSize.Y * bufferSize.X];

                    // copy characterBuffer to contents;
                    for (int r = atRow, characterBufferIndex = 0;
                        r < bufferSize.Y + atRow; r++)
                    {
                        for (int c = atCol; c < bufferSize.X + atCol; c++, characterBufferIndex++)
                        {
                            characterBuffer[characterBufferIndex].UnicodeChar =
                                (ushort)contents[r, c].Character;
                            characterBuffer[characterBufferIndex].Attributes =
                                ColorToWORD(contents[r, c].ForegroundColor, contents[r, c].BackgroundColor);
                        }
                    }

                    // Now writeRegion, bufferSize and characterBuffer are updated.
                    // Call NativeMethods.WriteConsoleOutput
                    bool result =
                        NativeMethods.WriteConsoleOutput(
                            consoleHandle.DangerousGetHandle(),
                            characterBuffer,
                            bufferSize,
                            bufferCoord,
                            ref writeRegion);

                    if (result == false)
                    {
                        // When WriteConsoleOutput fails, half bufferLimit
                        if (bufferLimit < 2)
                        {
                            int err = Marshal.GetLastWin32Error();
                            HostException e = CreateHostException(err, "WriteConsoleOutput",
                                ErrorCategory.WriteError, ConsoleControlStrings.WriteConsoleOutputExceptionTemplate);
                            throw e;
                        }
                        bufferLimit /= 2;
                        if (cols == colsRemaining)
                        {
                            // if cols == colsRemaining, nothing is guaranteed written in this pass and
                            //  the unwritten area is still rectangular
                            bufferSize.Y = 0;
                            break;
                        }
                        else
                        {
                            // some areas have been written. This could only happen when the number of columns
                            // to write is larger than bufferLimit. In that case, the algorithm writes one row
                            // at a time => bufferSize.Y == 1. Then, we can safely leave bufferSize.Y unchanged
                            // to retry with a smaller bufferSize.X.
                            Dbg.Assert(bufferSize.Y == 1, string.Format(CultureInfo.InvariantCulture, "bufferSize.Y should be 1, but is {0}", bufferSize.Y));
                            bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                            continue;
                        }
                    }

                    colsRemaining -= bufferSize.X;
                    writeRegion.Left += bufferSize.X;
                    bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                }  // column iteration

                rowsRemaining -= bufferSize.Y;
                writeRegion.Top += bufferSize.Y;
            }  // row iteration
        }
示例#18
0
        internal static CONSOLE_FONT_INFO_EX GetConsoleFontInfo(ConsoleHandle consoleHandle)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            CONSOLE_FONT_INFO_EX fontInfo = new CONSOLE_FONT_INFO_EX();
            fontInfo.cbSize = Marshal.SizeOf(fontInfo);
            bool result = NativeMethods.GetCurrentConsoleFontEx(consoleHandle.DangerousGetHandle(), false, ref fontInfo);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "GetConsoleFontInfo",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.GetConsoleFontInfoExceptionTemplate);
                throw e;
            }
            return fontInfo;
        }
示例#19
0
        private static bool ReadConsoleOutputCJKSmall
        (
            ConsoleHandle consoleHandle,
            uint codePage,
            Coordinates origin,
            Rectangle contentsRegion,
            ref BufferCell[,] contents
        )
        {
            COORD bufferSize;
            bufferSize.X = (short)(contentsRegion.Right - contentsRegion.Left + 1);
            bufferSize.Y = (short)(contentsRegion.Bottom - contentsRegion.Top + 1);
            COORD bufferCoord;
            bufferCoord.X = 0;
            bufferCoord.Y = 0;
            CHAR_INFO[] characterBuffer = new CHAR_INFO[bufferSize.X * bufferSize.Y];
            SMALL_RECT readRegion;
            readRegion.Left = (short)origin.X;
            readRegion.Top = (short)origin.Y;
            readRegion.Right = (short)(origin.X + bufferSize.X - 1);
            readRegion.Bottom = (short)(origin.Y + bufferSize.Y - 1);
            // Suppress the PreFAST warning about not using Marshal.GetLastWin32Error() to
            // get the error code.
#pragma warning disable 56523
            bool result = NativeMethods.ReadConsoleOutput(
                                        consoleHandle.DangerousGetHandle(),
                                        characterBuffer,
                                        bufferSize,
                                        bufferCoord,
                                        ref readRegion);
            if (!result)
            {
                return false;
            }
            int characterBufferIndex = 0;

            for (int r = contentsRegion.Top; r <= contentsRegion.Bottom; r++)
            {
                for (int c = contentsRegion.Left; c <= contentsRegion.Right; c++, characterBufferIndex++)
                {
                    ConsoleColor fgColor, bgColor;

                    contents[r, c].Character = (char)characterBuffer[characterBufferIndex].UnicodeChar;
                    WORDToColor(characterBuffer[characterBufferIndex].Attributes,
                                out fgColor,
                                out bgColor);
                    contents[r, c].ForegroundColor = fgColor;
                    contents[r, c].BackgroundColor = bgColor;

                    // Set the attributes of the buffercells to be the same as that of the 
                    // incoming CHAR_INFO. In case where the CHAR_INFO character is a 
                    // trailing byte set the Character of BufferCell to 0. This is done
                    // because at a lot of places this check is being done. Having a trailing
                    // character to be 0 is by design.

                    if ((characterBuffer[characterBufferIndex].Attributes & (ushort)NativeMethods.CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE)
                            == (ushort)NativeMethods.CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE)
                    {
                        contents[r, c].BufferCellType = BufferCellType.Leading;
                    }
                    else if ((characterBuffer[characterBufferIndex].Attributes & (ushort)NativeMethods.CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE)
                            == (ushort)NativeMethods.CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE)
                    {
                        contents[r, c].Character = (char)0;
                        contents[r, c].BufferCellType = BufferCellType.Trailing;
                    }
                    else
                    {
                        int charLength = LengthInBufferCells(contents[r, c].Character);
                        if (charLength == 2)
                        {
                            // When it's RasterFont, the "Leading_byte"/"Trailing_byte" are not effective, we
                            // need to decide the leading byte by checking the char length.
                            contents[r, c].BufferCellType = BufferCellType.Leading;
                            c++;
                            contents[r, c].Character = (char)0;
                            contents[r, c].ForegroundColor = fgColor;
                            contents[r, c].BackgroundColor = bgColor;
                            contents[r, c].BufferCellType = BufferCellType.Trailing;
                        }
                        else
                        {
                            contents[r, c].BufferCellType = BufferCellType.Complete;
                        }
                    }
                }
            }
            return true;
        }
示例#20
0
        /// <summary>
        /// 
        /// Sets the current mode of the console device
        /// 
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// Handle to the console device returned by GetInputHandle
        /// 
        /// </param>
        /// <param name="mode">
        /// 
        /// Mask of mode flags
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// 
        /// If Win32's SetConsoleMode fails
        /// 
        /// </exception>

        internal static void SetMode(ConsoleHandle consoleHandle, ConsoleModes mode)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "consoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            bool result = NativeMethods.SetConsoleMode(consoleHandle.DangerousGetHandle(), (DWORD)mode);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "SetConsoleMode",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.SetModeExceptionTemplate);
                throw e;
            }
        }
示例#21
0
        private static void ReadConsoleOutputPlain
        (
            ConsoleHandle consoleHandle,
            Coordinates origin,
            Rectangle contentsRegion,
            ref BufferCell[,] contents
        )
        {
            int rows = contentsRegion.Bottom - contentsRegion.Top + 1;
            int cols = contentsRegion.Right - contentsRegion.Left + 1;

            if ((rows <= 0) || cols <= 0)
            {
                tracer.WriteLine("invalid contents region");
                return;
            }

            int bufferLimit = 2 * 1024; // Limit is 8K bytes as each CHAR_INFO takes 4 bytes

            COORD bufferCoord;

            bufferCoord.X = 0;
            bufferCoord.Y = 0;

            // keeps track of which screen area read
            SMALL_RECT readRegion;

            readRegion.Top = (short)origin.Y;

            int rowsRemaining = rows;

            while (rowsRemaining > 0)
            {
                // Iteration of columns is nested inside iteration of rows.
                // If the size of contents exceeds the buffer limit, reading is
                // done in blocks of size equal to the bufferlimit from left to right
                // then top to bottom.
                // For each iteration of rows,
                // - readRegion.Left and bufferSize.X are reset
                // - rowsRemaining, readRegion.Top, readRegion.Bottom, and bufferSize.Y
                //     are updated
                //   For each iteration of columns,
                //   - readRegion.Left, readRegion.Right and bufferSize.X are updated

                readRegion.Left = (short)origin.X;

                COORD bufferSize;
                bufferSize.X = (short)Math.Min(cols, bufferLimit);
                bufferSize.Y = (short)Math.Min
                                        (
                                            rowsRemaining,
                                            bufferLimit / bufferSize.X
                                        );
                readRegion.Bottom = (short)(readRegion.Top + bufferSize.Y - 1);

                // atContentsRow is at which row of contents a particular iteration is operating
                int atContentsRow = rows - rowsRemaining + contentsRegion.Top;

                // number of columns yet to be read
                int colsRemaining = cols;

                while (colsRemaining > 0)
                {
                    readRegion.Right = (short)(readRegion.Left + bufferSize.X - 1);

                    // Now readRegion and bufferSize are updated.
                    // Call NativeMethods.ReadConsoleOutput
                    CHAR_INFO[] characterBuffer = new CHAR_INFO[bufferSize.Y * bufferSize.X];
                    bool result = NativeMethods.ReadConsoleOutput(
                                        consoleHandle.DangerousGetHandle(),
                                        characterBuffer,
                                        bufferSize,
                                        bufferCoord,
                                        ref readRegion);

                    if (result == false)
                    {
                        // When WriteConsoleOutput fails, half bufferLimit
                        if (bufferLimit < 2)
                        {
                            int err = Marshal.GetLastWin32Error();

                            HostException e = CreateHostException(err, "ReadConsoleOutput",
                                ErrorCategory.ReadError, ConsoleControlStrings.ReadConsoleOutputExceptionTemplate);
                            throw e;
                        }
                        // if cols == colsRemaining, nothing is guaranteed read in this pass and
                        //  the unread area is still rectangular
                        bufferLimit /= 2;
                        if (cols == colsRemaining)
                        {
                            bufferSize.Y = 0;
                            break;
                        }
                        else
                        {
                            // some areas have been read. This could only happen when the number of columns
                            // to write is larger than bufferLimit. In that case, the algorithm reads one row
                            // at a time => bufferSize.Y == 1. Then, we can safely leave bufferSize.Y unchanged
                            // to retry with a smaller bufferSize.X.
                            Dbg.Assert(bufferSize.Y == 1, string.Format(CultureInfo.InvariantCulture, "bufferSize.Y should be 1, but is {0}", bufferSize.Y));
                            bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                            continue;
                        }
                    }

                    // atContentsCol is at which column of contents a particular iteration is operating
                    int atContentsCol = cols - colsRemaining + contentsRegion.Left;

                    // copy characterBuffer to contents;
                    int characterBufferIndex = 0;
                    for (int r = atContentsRow; r < bufferSize.Y + atContentsRow; r++)
                    {
                        for (int c = atContentsCol; c < bufferSize.X + atContentsCol; c++, characterBufferIndex++)
                        {
                            contents[r, c].Character = (char)
                                characterBuffer[characterBufferIndex].UnicodeChar;
                            ConsoleColor fgColor, bgColor;
                            WORDToColor(characterBuffer[characterBufferIndex].Attributes,
                                out fgColor,
                                out bgColor);
                            contents[r, c].ForegroundColor = fgColor;
                            contents[r, c].BackgroundColor = bgColor;
                        }
                    }
                    colsRemaining -= bufferSize.X;
                    readRegion.Left += bufferSize.X;
                    bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                }  // column iteration

                rowsRemaining -= bufferSize.Y;
                readRegion.Top += bufferSize.Y;
            }  // row iteration

            // The following nested loop set the value of the empty cells in contents:
            // character to ' '
            // foreground color to console's foreground color
            // background color to console's background color
            int rowIndex = contents.GetLowerBound(0);
            int rowEnd = contents.GetUpperBound(0);
            int colBegin = contents.GetLowerBound(1);
            int colEnd = contents.GetUpperBound(1);
            CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
                        GetConsoleScreenBufferInfo(consoleHandle);
            ConsoleColor foreground = 0;
            ConsoleColor background = 0;

            WORDToColor(
                            bufferInfo.Attributes,
                            out foreground,
                            out background
                       );

            while (rowIndex <= rowEnd)
            {
                int colIndex = colBegin;
                while (true)
                {
                    // if contents[rowIndex,colIndex] is in contentsRegion, hence a non-empty cell,
                    // move colIndex to one past the right end of contentsRegion
                    if (contentsRegion.Top <= rowIndex && rowIndex <= contentsRegion.Bottom &&
                        contentsRegion.Left <= colIndex && colIndex <= contentsRegion.Right)
                    {
                        colIndex = contentsRegion.Right + 1;
                    }
                    // colIndex past contents last column
                    if (colIndex > colEnd)
                    {
                        break;
                    }
                    contents[rowIndex, colIndex].Character = ' ';
                    contents[rowIndex, colIndex].ForegroundColor = foreground;
                    contents[rowIndex, colIndex].BackgroundColor = background;
                    colIndex++;
                }
                rowIndex++;
            }
        }
示例#22
0
        /// <summary>
        /// Wraps Win32 PeekConsoleInput
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where input is peeked
        /// 
        /// </param>
        /// <param name="buffer">
        /// 
        /// array where data read are stored
        /// 
        /// </param>
        /// <returns>
        /// 
        /// actual number of input records peeked
        /// 
        /// </returns>
        /// <exception cref="HostException">
        /// If Win32's PeekConsoleInput fails
        /// </exception>

        internal static int PeekConsoleInput
        (
            ConsoleHandle consoleHandle,
            ref INPUT_RECORD[] buffer
        )
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            DWORD recordsRead;
            bool result =
                NativeMethods.PeekConsoleInput(
                    consoleHandle.DangerousGetHandle(),
                    buffer,
                    (DWORD)buffer.Length,
                    out recordsRead);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "PeekConsoleInput",
                    ErrorCategory.ReadError, ConsoleControlStrings.PeekConsoleInputExceptionTemplate);
                throw e;
            }

            return (int)recordsRead;
        }
示例#23
0
        /// <summary>
        /// Wraps Win32 FillConsoleOutputCharacter
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where output is filled
        /// 
        /// </param>
        /// <param name="character">
        /// 
        /// character to fill the console output
        /// 
        /// </param>
        /// <param name="numberToWrite">
        /// 
        /// number of times to write character
        /// 
        /// </param>
        /// <param name="origin">
        /// 
        /// location on screen buffer where writing starts
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's FillConsoleOutputCharacter fails
        /// </exception>
        internal static void FillConsoleOutputCharacter
        (
            ConsoleHandle consoleHandle,
            char character,
            int numberToWrite,
            Coordinates origin
        )
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            COORD c;

            c.X = (short)origin.X;
            c.Y = (short)origin.Y;

            DWORD unused = 0;
            bool result =
                NativeMethods.FillConsoleOutputCharacter(
                    consoleHandle.DangerousGetHandle(),
                    character,
                    (DWORD)numberToWrite,
                    c,
                    out unused);
            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "FillConsoleOutputCharacter",
                    ErrorCategory.WriteError, ConsoleControlStrings.FillConsoleOutputCharacterExceptionTemplate);
                throw e;
            }
            // we don't assert that the number actually written matches the number we asked for, as the function may clip if
            // the number of cells to write extends past the end of the screen buffer.
        }
示例#24
0
        /// <summary>
        /// Wraps Win32 FlushConsoleInputBuffer
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where the input buffer is flushed
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's FlushConsoleInputBuffer fails
        /// </exception>
        internal static void FlushConsoleInputBuffer(ConsoleHandle consoleHandle)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            bool result = false;
            NakedWin32Handle h = consoleHandle.DangerousGetHandle();
            result = NativeMethods.FlushConsoleInputBuffer(h);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "FlushConsoleInputBuffer",
                    ErrorCategory.ReadError, ConsoleControlStrings.FlushConsoleInputBufferExceptionTemplate);
                throw e;
            }
        }
示例#25
0
        /// <summary>
        /// Wraps Win32 FillConsoleOutputAttribute
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where output is filled
        /// 
        /// </param>
        /// <param name="attribute">
        /// 
        /// attribute to fill the console output
        /// 
        /// </param>
        /// <param name="numberToWrite">
        /// 
        /// number of times to write attribute
        /// 
        /// </param>
        /// <param name="origin">
        /// 
        /// location on screen buffer where writing starts
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's FillConsoleOutputAttribute fails
        /// </exception>
        internal static void FillConsoleOutputAttribute
        (
            ConsoleHandle consoleHandle,
            WORD attribute,
            int numberToWrite,
            Coordinates origin
        )
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            COORD c;

            c.X = (short)origin.X;
            c.Y = (short)origin.Y;

            DWORD unused = 0;
            bool result =
                NativeMethods.FillConsoleOutputAttribute(
                    consoleHandle.DangerousGetHandle(),
                    attribute,
                    (DWORD)numberToWrite,
                    c,
                    out unused);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "FillConsoleOutputAttribute",
                    ErrorCategory.WriteError, ConsoleControlStrings.FillConsoleOutputAttributeExceptionTemplate);
                throw e;
            }
        }
示例#26
0
		public static string GetFinalPathNameByHandle(SafeFileHandle safeHandle, DWORD dwFlags)
		{
			Contract.Requires(safeHandle != null);

			var rawHandle = safeHandle.DangerousGetHandle();
			if (safeHandle.IsClosed || safeHandle.IsInvalid) throw new ArgumentException();

			var pathLength = GetFinalPathNameByHandle(rawHandle, null, 0, dwFlags);
			NativeMethods.CheckWin32(pathLength > 0);
			var pathBuilder = new StringBuilder((int)pathLength);
			pathBuilder.Length = (int)pathLength;
			NativeMethods.CheckWin32(GetFinalPathNameByHandle(rawHandle, pathBuilder, pathLength, dwFlags) > 0);
			return pathBuilder.ToString();
		}
示例#27
0
        /// <summary>
        /// Wrap Win32 ScrollConsoleScreenBuffer
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where screen buffer is scrolled
        /// 
        /// </param>
        /// <param name="scrollRectangle">
        /// 
        /// area to be scrolled
        /// 
        /// </param>
        /// <param name="clipRectangle">
        /// 
        /// area to be updated after scrolling
        /// 
        /// </param>
        /// <param name="destOrigin">
        /// 
        /// location to which the top left corner of scrollRectangle move
        /// 
        /// </param>
        /// <param name="fill">
        /// 
        /// character and attribute to fill the area vacated by the scroll
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's ScrollConsoleScreenBuffer fails
        /// </exception>

        internal static void ScrollConsoleScreenBuffer
        (
            ConsoleHandle consoleHandle,
            SMALL_RECT scrollRectangle,
            SMALL_RECT clipRectangle,
            COORD destOrigin, CHAR_INFO fill
        )
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            bool result =
                NativeMethods.ScrollConsoleScreenBuffer(
                    consoleHandle.DangerousGetHandle(),
                    ref scrollRectangle,
                    ref clipRectangle,
                    destOrigin,
                    ref fill);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "ScrollConsoleScreenBuffer",
                    ErrorCategory.WriteError, ConsoleControlStrings.ScrollConsoleScreenBufferExceptionTemplate);
                throw e;
            }
        }
示例#28
0
        internal static CONSOLE_FONT_INFO_EX GetConsoleFontInfo(SafeFileHandle consoleHandle)
        {

            CONSOLE_FONT_INFO_EX fontInfo = new CONSOLE_FONT_INFO_EX();
            fontInfo.cbSize = Marshal.SizeOf(fontInfo);
            bool result = NativeMethods.GetCurrentConsoleFontEx(consoleHandle.DangerousGetHandle(), false, ref fontInfo);

            if (result == false)
            {
                int err = Marshal.GetLastWin32Error();
                Win32Exception innerException = new Win32Exception(err);
                throw new Exception("Failed to get console font information.", innerException);
            }
            return fontInfo;
        }
示例#29
0
        /// <summary>
        /// Wraps Win32 GetLargestConsoleWindowSize
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console for which the largest window size is obtained
        /// 
        /// </param>
        /// <returns>
        /// 
        /// the largest window size
        /// 
        /// </returns>
        /// <exception cref="HostException">
        /// If Win32's GetLargestConsoleWindowSize fails
        /// </exception>

        internal static Size GetLargestConsoleWindowSize(ConsoleHandle consoleHandle)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");

            COORD result = NativeMethods.GetLargestConsoleWindowSize(consoleHandle.DangerousGetHandle());

            if ((result.X == 0) && (result.Y == 0))
            {
                int err = Marshal.GetLastWin32Error();

                HostException e = CreateHostException(err, "GetLargestConsoleWindowSize",
                    ErrorCategory.ResourceUnavailable, ConsoleControlStrings.GetLargestConsoleWindowSizeExceptionTemplate);
                throw e;
            }

            return new Size(result.X, result.Y);
        }
示例#30
0
 public static DISK_GEOMETRY GetGeometry(SafeFileHandle Handle)
 {
     if (Handle.IsInvalid || Handle.IsClosed) throw new Exception("Native.GetGeometry: Invalid handle specified. It is closed or invalid.");
     var geom = new DISK_GEOMETRY();
     uint returnedBytes;
     if (DeviceIoControl(Handle.DangerousGetHandle(), (uint)IOCTL_CONTROL_CODE_CONSTANTS.IOCTL_DISK_GET_DRIVE_GEOMETRY, IntPtr.Zero, 0, ref geom, (uint)Marshal.SizeOf(typeof(DISK_GEOMETRY)), out returnedBytes, IntPtr.Zero)) return geom;
     Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
     return new DISK_GEOMETRY();
 }
示例#31
0
		internal static string ReadConsole(SafeFileHandle consoleHandle, string initialContent, int charactersToRead, bool endOnTab, out int keyState)
		{
			keyState = 0;
			ConsoleControl.CONSOLE_READCONSOLE_CONTROL length = new ConsoleControl.CONSOLE_READCONSOLE_CONTROL();
			length.nLength = Marshal.SizeOf(length);
			length.nInitialChars = initialContent.Length;
			length.dwControlKeyState = 0;
			if (endOnTab)
			{
				length.dwCtrlWakeupMask = 0x200;
			}
			int num = 0;
			StringBuilder stringBuilder = new StringBuilder(initialContent, charactersToRead);
			bool flag = ConsoleControl.NativeMethods.ReadConsole(consoleHandle.DangerousGetHandle(), stringBuilder, charactersToRead, out num, ref length);
			keyState = length.dwControlKeyState;
			if (flag)
			{
				if (num > stringBuilder.Length)
				{
					num = stringBuilder.Length;
				}
				return stringBuilder.ToString(0, num);
			}
			else
			{
				int lastWin32Error = Marshal.GetLastWin32Error();
				HostException hostException = ConsoleControl.CreateHostException(lastWin32Error, "ReadConsole", ErrorCategory.ReadError, ConsoleControlStrings.ReadConsoleExceptionTemplate);
				throw hostException;
			}
		}