1 {-# LANGUAGE ScopedTypeVariables #-}
2 {-# LANGUAGE TypeFamilies #-}
3 module Rehi.Win32bits where
10 import Foreign.Ptr(Ptr(), nullPtr)
11 import Foreign.Marshal.Alloc (allocaBytesAligned, alloca)
12 import Foreign.Storable
13 import Numeric (showHex)
15 import qualified System.Win32.Types as WT
21 #if defined(i386_HOST_ARCH)
22 #let WINDOWS_CCONV = "stdcall"
23 #elif defined(x86_64_HOST_ARCH)
24 #let WINDOWS_CCONV = "ccall"
26 # error Unknown mingw32 arch
29 #def typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION {
30 UNICODE_STRING TypeName;
32 } PUBLIC_OBJECT_TYPE_INFORMATION;
35 ObjectNameInformation = 1,
36 } OBJECT_INFORMATION_CLASS;
38 #def NTSTATUS NtQueryObject(
40 OBJECT_INFORMATION_CLASS ObjectInformationClass,
41 *PUBLIC_OBJECT_TYPE_INFORMATION ObjectInformation,
42 ULONG ObjectInformationLength,
46 -- https://stackoverflow.com/a/8354582/2303202
47 -- https://wiki.haskell.org/FFICookBook#Working_with_structs
48 #if __GLASGOW_HASKELL__ < 800
49 #let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
52 data NT_OBJECT_NAME_INFORMATION = NT_OBJECT_NAME_INFORMATION
53 { noniLength :: WT.USHORT
54 , noniMaximumLength :: WT.USHORT
55 , noniBuffer :: WT.LPWSTR }
57 instance Storable NT_OBJECT_NAME_INFORMATION where
58 sizeOf = const #{size PUBLIC_OBJECT_TYPE_INFORMATION}
59 alignment = const #{alignment PUBLIC_OBJECT_TYPE_INFORMATION}
60 peek p = NT_OBJECT_NAME_INFORMATION
61 <$> #{peek UNICODE_STRING, Length} p
62 <*> #{peek UNICODE_STRING, MaximumLength} p
63 <*> #{peek UNICODE_STRING, Buffer} p
65 #{poke UNICODE_STRING, Length} p (noniLength o)
66 #{poke UNICODE_STRING, MaximumLength} p (noniMaximumLength o)
67 #{poke UNICODE_STRING, Buffer} p (noniBuffer o)
69 type ObjectInformationClass = #{type OBJECT_INFORMATION_CLASS}
71 #enum ObjectInformationClass, , hs_ObjectNameInformation = ObjectNameInformation
73 type family Unsigned t :: *
74 type instance Unsigned Int32 = Word32
76 type NTSTATUS = Unsigned #{type NTSTATUS}
80 foreign import #{WINDOWS_CCONV} "NtQueryObject"
81 c_NtQueryObject :: WT.HANDLE
82 -> ObjectInformationClass
83 -> Ptr NT_OBJECT_NAME_INFORMATION
88 toIntegralSizedM :: forall a b . (Bits a, Integral a, Show a, Bits b, Integral b, Typeable b) => a -> IO b
89 toIntegralSizedM v = case toIntegralSized v of
91 Nothing -> fail ("Cannot cast from " ++ show v ++ " to " ++ show (typeRep (undefined :: Proxy b)))
93 getFileNameInformation :: WT.HANDLE -> IO String
94 getFileNameInformation h =
95 alloca $ \ (p_len :: Ptr ULONG) -> do
97 (== 0xC0000004) -- STATUS_INFO_LENGTH_MISMATCH
98 $ c_NtQueryObject h hs_ObjectNameInformation nullPtr 0 p_len
100 len_signed <- toIntegralSizedM len
103 (alignment (undefined :: NT_OBJECT_NAME_INFORMATION))
106 (\s -> s >= 0 && s <= 0x7FFFFFFF) -- https://msdn.microsoft.com/en-us/library/windows/hardware/ff565436.aspx
107 $ c_NtQueryObject h hs_ObjectNameInformation p_oni len p_len
110 oni_length <- toIntegralSizedM (noniLength oni `div` 2)
111 WT.peekTStringLen (noniBuffer oni, oni_length)
113 checkNtStatus :: (NTSTATUS -> Bool) -> IO NTSTATUS -> IO ()
114 checkNtStatus p f = do
118 else fail ("NtQueryObject(ObjectNameInformation) failed: " ++ showHex s "")