// 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; }
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; } }