private static uint HandleChainDlls(IntPtr ChainDlls, uint CalloutVersion) { // ChainDlls is in REG_MULTI_SZ format (non-empty strings separated by null, terminated with an additional null) // read next dll in chain var chainDllPath = Marshal.PtrToStringUni(ChainDlls); // check if no dlls (or we are the last in the chain) if (chainDllPath == null || chainDllPath.Length == 0) { ChainTable = new DHCP_CALLOUT_TABLE(); return(ERROR_SUCCESS); } // ensure dll exists if (!File.Exists(chainDllPath)) { return(0x2); // FILE_NOT_FOUND } // load dll ChainLibraryHandle = Win32Api.LoadLibrary(chainDllPath); if (ChainLibraryHandle == IntPtr.Zero) { return((uint)Marshal.GetLastWin32Error()); } // locate DhcpServerCalloutEntry export var chainCalloutEntryAddress = Win32Api.GetProcAddress(ChainLibraryHandle, "DhcpServerCalloutEntry"); if (chainCalloutEntryAddress == IntPtr.Zero) { return((uint)Marshal.GetLastWin32Error()); } // prepare arguments var chainCalloutEntryDelegate = (DhcpServerCalloutEntryDelegate)Marshal.GetDelegateForFunctionPointer (chainCalloutEntryAddress, typeof(DhcpServerCalloutEntryDelegate)); // ChainDlls should pass a pointer to the next dll (or the final termination null) var chainDllsNext = ChainDlls + Encoding.Unicode.GetByteCount(chainDllPath) + 2; var calloutTbl = new DHCP_CALLOUT_TABLE(); // call chain dll var subsequentResult = chainCalloutEntryDelegate(chainDllsNext, CalloutVersion, ref calloutTbl); if (subsequentResult != ERROR_SUCCESS) { return(subsequentResult); } // store chain dll's callout table ChainTable = calloutTbl; return(ERROR_SUCCESS); }
private static uint DeriveHooks(ref DHCP_CALLOUT_TABLE CalloutTbl) { // always hook control CalloutTbl.DhcpControlHook = new DhcpControlHookUnsafeDelegate(HandleControlHook); // NewPkt if (ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.NewPacket)) { // consumer required CalloutTbl.DhcpNewPktHook = new DhcpNewPktHookUnsafeDelegate(HandleNewPktHook); } else if (ChainTable.DhcpNewPktHook != null) { // only chain required CalloutTbl.DhcpNewPktHook = ChainTable.DhcpNewPktHook; } else { CalloutTbl.DhcpNewPktHook = null; } // PktDrop if (ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.PacketDrop)) { // consumer required CalloutTbl.DhcpPktDropHook = new DhcpPktDropHookUnsafeDelegate(HandleDhcpPktDropHook); } else if (ChainTable.DhcpPktDropHook != null) { // only chain required CalloutTbl.DhcpPktDropHook = ChainTable.DhcpPktDropHook; } else { CalloutTbl.DhcpPktDropHook = null; } // PktSend if (ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.PacketSend)) { // consumer required CalloutTbl.DhcpPktSendHook = new DhcpPktSendHookUnsafeDelegate(HandlePktSendHook); } else if (ChainTable.DhcpPktSendHook != null) { // only chain required CalloutTbl.DhcpPktSendHook = ChainTable.DhcpPktSendHook; } else { CalloutTbl.DhcpPktSendHook = null; } // AddressDel if (ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.AddressDelete)) { // consumer required CalloutTbl.DhcpAddressDelHook = new DhcpAddressDelHookUnsafeDelegate(HandleAddressDelHook); } else if (ChainTable.DhcpAddressDelHook != null) { // only chain required CalloutTbl.DhcpAddressDelHook = ChainTable.DhcpAddressDelHook; } else { CalloutTbl.DhcpAddressDelHook = null; } // AddressOffer if (ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.AddressOffer)) { // consumer required CalloutTbl.DhcpAddressOfferHook = new DhcpAddressOfferHookUnsafeDelegate(HandleAddressOfferHook); } else if (ChainTable.DhcpAddressOfferHook != null) { // only chain required CalloutTbl.DhcpAddressOfferHook = ChainTable.DhcpAddressOfferHook; } else { CalloutTbl.DhcpAddressOfferHook = null; } // HandleOptions // Hook is only derived if the ApiVersion is 0 (as the ServerOptions could change if the version is incremented). if (ApiVersion == 0 && ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.HandleOptions)) { // consumer required CalloutTbl.DhcpHandleOptionsHook = new DhcpHandleOptionsHookUnsafeDelegate(HandleHandleOptionsHook); } else if (ChainTable.DhcpHandleOptionsHook != null) { // only chain required CalloutTbl.DhcpHandleOptionsHook = ChainTable.DhcpHandleOptionsHook; } else { CalloutTbl.DhcpHandleOptionsHook = null; } // DeleteClient if (ConsumerRequirements.HasFlag(CalloutConsumerSupportFlags.DeleteClient)) { // consumer required CalloutTbl.DhcpDeleteClientHook = new DhcpDeleteClientHookUnsafeDelegate(HandleDeleteClientHook); } else if (ChainTable.DhcpDeleteClientHook != null) { // only chain required CalloutTbl.DhcpDeleteClientHook = ChainTable.DhcpDeleteClientHook; } else { CalloutTbl.DhcpDeleteClientHook = null; } // Extension - not supported by DhcpServerAPI if (ChainTable.DhcpExtensionHook != IntPtr.Zero) { CalloutTbl.DhcpExtensionHook = ChainTable.DhcpExtensionHook; } else { CalloutTbl.DhcpExtensionHook = IntPtr.Zero; } // Reserved - not supported by DhcpServerAPI if (ChainTable.DhcpReservedHook != IntPtr.Zero) { CalloutTbl.DhcpReservedHook = ChainTable.DhcpReservedHook; } else { CalloutTbl.DhcpReservedHook = IntPtr.Zero; } return(ERROR_SUCCESS); }
private static uint DhcpServerCalloutEntry(IntPtr ChainDlls, uint CalloutVersion, ref DHCP_CALLOUT_TABLE CalloutTbl) { AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; ApiVersion = CalloutVersion; // locate and initialize consumers var initConsumersResult = InitializeConsumers(); if (initConsumersResult != ERROR_SUCCESS) { return(initConsumersResult); } // chain subsequent dll var chainDllResult = HandleChainDlls(ChainDlls, CalloutVersion); if (chainDllResult != ERROR_SUCCESS) { return(chainDllResult); } // derive hooks var deriveResult = DeriveHooks(ref CalloutTbl); if (deriveResult != ERROR_SUCCESS) { return(deriveResult); } return(ERROR_SUCCESS); }