Example #1
0
        private void IoFlowRuntimeInternal(uint maxIocpThreads, bool useIocpEx)
        {
            Console.WriteLine("IoFlowRuntime created with {0} iocp threads", maxIocpThreads);

            this.countIocpThreads = maxIocpThreads;

            LockIoFlow = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

            if (this.countIocpThreads < System.Environment.ProcessorCount)
                Console.WriteLine("IoFlowRuntime: Warning: MPL {0} < ProcessorCount {1}",
                    this.countIocpThreads, System.Environment.ProcessorCount);
            uint HResult;
            TenantId = (uint)Process.GetCurrentProcess().Id;

            //
            // Open FltMgr comms port for asynchronous data exchange with IoFlowUser minifilter driver.
            //
            string strDataPortName = Parameters.DATA_PORT_NAME;

            HResult = FilterConnectCommunicationPort(strDataPortName,      // LPCWSTR lpPortName,
                                                     0,                    // DWORD dwOptions,
                                                     IntPtr.Zero,          // LPCVOID lpContext,
                                                     0,                    // WORD dwSizeOfContext
                                                     IntPtr.Zero,          // LP_SECURITY_ATTRIBUTES lpSecurityAttributes
                                                     out hDataAsyncPort); // HANDLE *hPort

            if (HResult != S_OK)
            {
                Console.WriteLine("IoFlowRuntime failed to contact IoFlow minifilter driver async: check the driver is loaded.");
                Marshal.ThrowExceptionForHR((int)HResult);
            }

            //
            // Open FltMgr comms port for control messages to IoFlowUser minifilter driver.
            // We open the control port for synchronous I/O because we required calls to
            // FilterReplyMessage to complete synchronously when pending IRPs to kernel-mode
            // cancelsafe queue *before* the app calls CompletePendedPreOp() or
            // CompletePendedPostOp() in the days when we supported pending ops.
            //
            string strControlPortName = Parameters.CONTROL_PORT_NAME;

            HResult = FilterConnectCommunicationPort(strControlPortName, // LPCWSTR lpPortName,
                                                     0,                  // DWORD dwOptions,
                                                     IntPtr.Zero,        // LPCVOID lpContext,
                                                     0,                  // WORD dwSizeOfContext
                                                     IntPtr.Zero,        // LP_SECURITY_ATTRIBUTES lpSecurityAttributes
                                                     out hControlPort);  // HANDLE *hPort

            if (HResult != S_OK)
            {
                Marshal.ThrowExceptionForHR((int)HResult);
            }

            //
            // Purge any old state from the minifilter driver.
            //
            DriverReset();

            //
            // Dictionary implements lookup func f(FlowId)=>IoFlow
            //
            DictIoFlow = new Dictionary<uint, IoFlow>();

            //
            // Open I/O completion port for completing async I/O to the minifilter driver.
            //
            hCompletionPort = CreateIoCompletionPort(hDataAsyncPort,
                                                     hCompletionPort,         // HANDLE ExistingCompletionPort
                                                     IntPtr.Zero,             // ULONG_PTR CompletionKey
                                                     (uint)maxIocpThreads); // DWORD NumberOfConcurrentThreads
            if (hCompletionPort == IntPtr.Zero)
            {
                int err = Marshal.GetHRForLastWin32Error();
                Console.WriteLine("CreateIoCompletionPort err={0:X8}", err);
                Marshal.ThrowExceptionForHR(err);
            }

            //
            // Init dict for translating friendly drive names to unfriendly device names.
            // For example on my dev machine "D:" => "\Device\HarddiskVolume4"
            // No .NET support for discovering this, so we scan stdout from "fltmc volume".
            //
            DriveNameToVolumeName = new Dictionary<string, string>();
            Process process = new Process();
            process.StartInfo = new ProcessStartInfo("fltmc.exe", "volumes");
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();
            string s1 = null;
            string[] separators = new string[] { " ", "\t" };
            while ((s1 = process.StandardOutput.ReadLine()) != null)
            {
                if (s1.Length > 1 && s1.Contains(@":"))
                {
                    string[] toks = s1.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                    if (toks.Length > 1 &&
                        toks[0].Length == 2 &&
                        toks[0].Substring(1, 1).Equals(@":") &&
                        toks[1].Length > DeviceHarddiskVolume.Length &&
                        toks[1].ToLower().StartsWith(DeviceHarddiskVolume))
                    {
                        DriveNameToVolumeName.Add(toks[0].ToLower(), toks[1].ToLower());
                    }
                }
            }
            process.WaitForExit();

            VolumeNameToDriveName = DriveNameToVolumeName.ToDictionary(x => x.Value, x => x.Key); //gets the reverse dictionary (this assumes no duplicate values)

            //
            // Allocate pool of statically allocated Irp objects for I/O to/from minifilter driver.
            //
            int countIrps = Parameters.IRP_POOL_SIZE * (int)maxIocpThreads;
            FindIrp = new Dictionary<IntPtr, IRP>(countIrps);
            irpArray = new IRP[countIrps];
            for (int i = 0; i < irpArray.Length; i++)
            {
                IRP irp = new IRP(this, hDataAsyncPort);
                FindIrp.Add(irp.addrOverlapped, irp);
                irpArray[i] = irp;
                irp.State = IrpState.Free;
                FreeIrp(irp);
            }

            //
            // Prep the requested number of IO completion worker threads.
            //
            arrayIocpThreads = new Thread[countIocpThreads];
            for (int i = 0; i < countIocpThreads; i++)
            {
                if (useIocpEx)
                    arrayIocpThreads[i] = new Thread(IocpThreadProcEx);
                else
                    arrayIocpThreads[i] = new Thread(IocpThreadProc);
            }

            //
            // Iff a local oktofsagent exists try for a connection for fast sid lookup.
            // Assumes oktofsagent is listening on its default TCP port.
            //
            bridgeOktofsAgent = new BridgeOktofsAgent();
            if (bridgeOktofsAgent.Connect() && bridgeOktofsAgent.SendMessageRegister())
                Console.WriteLine("Registered with local oktofsAgent for fast (account,SID) lookup.");
            else
                bridgeOktofsAgent = null;

        }
Example #2
0
        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        void Dispose(bool calledByUserCode)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                if (calledByUserCode)
                {
                    //
                    // Dispose managed resources here.
                    //
                    if (bridgeOktofsAgent != null)
                        bridgeOktofsAgent.Close();
                    bridgeOktofsAgent = null;

                    // Start shutdown.
                    ShuttingDown = true;
                    if (hCompletionPort != IntPtr.Zero)
                    {
                        CloseHandle(hCompletionPort);
                        hCompletionPort = IntPtr.Zero;
                    }

                    Thread.Sleep(100);

                    for (int i = 0; i < irpArray.Length; i++)
                        irpArray[i].Close();

                }

                // 
                // Dispose unmanaged resources here.
                //
                if (hDataAsyncPort != null)
                    hDataAsyncPort.Close();
                hDataAsyncPort = null;
                if (hControlPort != null)
                    hControlPort.Close();
                hControlPort = null;
                if (hCompletionPort != IntPtr.Zero)
                    CloseHandle(hCompletionPort);
                hCompletionPort = IntPtr.Zero;


            }
            disposed = true;
        }