{-# LANGUAGE ForeignFunctionInterface #-} module System.Win32.DHCP.Internal where import Foreign import Foreign.C import System.Win32.DLL import System.Win32.Types import System.Win32.DHCP.Client import System.Win32.DHCP.SEARCH_INFO import System.Win32.DHCP.SUBNET_CLIENT_INFO_ARRAY_V4 import System.Win32.DHCP.SUBNET_ELEMENT_INFO_ARRAY_V4 import System.Win32.DHCP.SUBNET_ELEMENT_DATA_V4 import System.Win32.DHCP.Types -- DWORD DHCP_API_FUNCTION DhcpDeleteClientInfo( -- _In_ DHCP_CONST WCHAR *ServerIpAddress, -- _In_ DHCP_CONST DHCP_SEARCH_INFO *ClientInfo -- ); type DeleteClientInfo = CWString -> Ptr SEARCH_INFO -> IO DWORD foreign import stdcall "dynamic" mkDeleteClientInfo :: FunPtr DeleteClientInfo -> DeleteClientInfo -- DWORD DHCP_API_FUNCTION DhcpEnumSubnetClientsV4( -- _In_ DHCP_CONST WCHAR *ServerIpAddress, -- _In_ DHCP_IP_ADDRESS SubnetAddress, -- _Inout_ DHCP_RESUME_HANDLE *ResumeHandle, -- _In_ DWORD PreferredMaximum, -- _Out_ LPDHCP_CLIENT_INFO_ARRAY_V4 *ClientInfo, -- _Out_ DWORD *ClientsRead, -- _Out_ DWORD *ClientsTotal -- ); type EnumSubnetClientsV4 = CWString -> Word32 -> Ptr RESUME_HANDLE -> DWORD -> Ptr (Ptr SUBNET_CLIENT_INFO_ARRAY_V4) -> Ptr DWORD -> Ptr DWORD -> IO DWORD foreign import stdcall "dynamic" mkEnumSubnetClientsV4 :: FunPtr EnumSubnetClientsV4 -> EnumSubnetClientsV4 -- DWORD DHCP_API_FUNCTION DhcpEnumSubnetElementsV4( -- __in DHCP_CONST WCHAR *ServerIpAddress, -- __in DHCP_IP_ADDRESS SubnetAddress, -- __in DHCP_SUBNET_ELEMENT_TYPE EnumElementType, -- __inout DHCP_RESUME_HANDLE *ResumeHandle, -- __in DWORD PreferredMaximum, -- __out LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 *EnumElementInfo, -- __out DWORD *ElementsRead, -- __out DWORD *ElementsTotal -- ); type EnumSubnetElementsV4 = CWString -> Word32 -> CInt -> Ptr RESUME_HANDLE -> DWORD -> Ptr (Ptr SUBNET_ELEMENT_INFO_ARRAY_V4) -> Ptr DWORD -> Ptr DWORD -> IO DWORD foreign import stdcall "dynamic" mkEnumSubnetElementsV4 :: FunPtr EnumSubnetElementsV4 -> EnumSubnetElementsV4 -- DWORD DHCP_API_FUNCTION DhcpGetClientInfoV4( -- _In_ DHCP_CONST WCHAR ServerIpAddress, -- _In_ DHCP_CONST DHCP_SEARCH_INFO SearchInfo, -- _Out_ LPDHCP_CLIENT_INFO_V4 *ClientInfo -- ); type GetClientInfoV4 = CWString -> SEARCH_INFO_TYPE -> Ptr () -> Ptr (Ptr Client) -> IO DWORD foreign import stdcall "dynamic" mkGetClientInfoV4 :: FunPtr GetClientInfoV4 -> GetClientInfoV4 -- | Foreign wrapper to DhcpRemoveSubnetElementV4. -- -- The DhcpRemoveSubnetElementV4 function removes an IPv4 subnet element -- from an IPv4 subnet defined on the DHCPv4 server. The function extends -- the functionality provided by DhcpRemoveSubnetElement by allowing the -- specification of a subnet that contains client type (DHCP or BOOTP) -- information. -- -- See for -- official documentation. -- -- @ -- DWORD DHCP_API_FUNCTION DhcpRemoveSubnetElementV4( -- __in DHCP_CONST WCHAR *ServerIpAddress, -- __in DHCP_IP_ADDRESS SubnetAddress, -- __in DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V4 *RemoveElementInfo, -- __in DHCP_FORCE_FLAG ForceFlag -- ); -- @ type RemoveSubnetElementV4 = CWString -> Word32 -> Ptr SUBNET_ELEMENT_DATA_V4 -> CInt -> IO DWORD foreign import stdcall "dynamic" mkRemoveSubnetElementV4 :: FunPtr RemoveSubnetElementV4 -> RemoveSubnetElementV4 -- DWORD DhcpAddSubnetElementV4( -- __in DHCP_CONST WCHAR *ServerIpAddress, -- __in DHCP_IP_ADDRESS SubnetAddress, -- __in DHCP_CONST DHCP_SUBNET_ELEMENT_DATA_V4 AddElementInfo -- ); type AddSubnetElementV4 = CWString -> Word32 -> Ptr SUBNET_ELEMENT_DATA_V4 -> IO DWORD foreign import stdcall "dynamic" mkAddSubnetElementV4 :: FunPtr AddSubnetElementV4 -> AddSubnetElementV4 -- VOID DHCP_API_FUNCTION DhcpRpcFreeMemory( -- PVOID BufferPointer -- ); type RpcFreeMemory = Ptr () -> IO () foreign import stdcall "dynamic" mkRpcFreeMemory :: FunPtr RpcFreeMemory -> RpcFreeMemory -- | In an effort to avoid potential compile-time linker errors this package -- uses runtime dynamic linking. Internally a `DhcpApi` is a dictionary of -- dynamically bound foreign calls. Most actions require one to be passed. -- Simply call `loadDhcp` to obtain one. data DhcpApi = DhcpApi { c_DeleteClientInfo :: DeleteClientInfo , c_EnumSubnetClientsV4 :: EnumSubnetClientsV4 , c_EnumSubnetElementsV4 :: EnumSubnetElementsV4 , c_GetClientInfoV4 :: GetClientInfoV4 , c_RemoveSubnetElementV4 :: RemoveSubnetElementV4 , c_AddSubnetElementV4 :: AddSubnetElementV4 , c_RpcFreeMemory :: RpcFreeMemory } -- | Calling this function performs runtime dynamic linking for every internal -- foreign call into the Dhcp Server Management Api. It is safe to call this -- action multiple times. I recommend calling this function once as the part -- of a process's initialization, and then pass the returned `DhcpApi` to -- functions that need it. loadDHCP :: IO DhcpApi loadDHCP = do lib <- loadLibrary "dhcpsapi" deleteclient <- getProcAddress lib "DhcpDeleteClientInfo" enumClients <- getProcAddress lib "DhcpEnumSubnetClientsV4" enumElements <- getProcAddress lib "DhcpEnumSubnetElementsV4" getclient <- getProcAddress lib "DhcpGetClientInfoV4" remove <- getProcAddress lib "DhcpRemoveSubnetElementV4" add <- getProcAddress lib "DhcpAddSubnetElementV4" rpcfree <- getProcAddress lib "DhcpRpcFreeMemory" return $ DhcpApi (mkDeleteClientInfo . castPtrToFunPtr $ deleteclient) (mkEnumSubnetClientsV4 . castPtrToFunPtr $ enumClients) (mkEnumSubnetElementsV4 . castPtrToFunPtr $ enumElements) (mkGetClientInfoV4 . castPtrToFunPtr $ getclient) (mkRemoveSubnetElementV4 . castPtrToFunPtr $ remove) (mkAddSubnetElementV4 . castPtrToFunPtr $ add) (mkRpcFreeMemory . castPtrToFunPtr $ rpcfree) -- |Free a block of memory created by DHCP's api. -- MSDN only mensions this function in DhcpEnumSubnetElementsV5. The original, -- v4, and v6 variants of the function don't say how memory should be freed. rpcFreeMemory :: DhcpApi -> Ptr a -> IO () rpcFreeMemory api ptr = c_RpcFreeMemory api $ castPtr ptr