{-# LINE 1 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE CPP #-}
module System.Environment.ExecutablePath ( getExecutablePath ) where
{-# LINE 36 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
import Control.Exception
import Data.List
import Data.Word
import Foreign.C
import Foreign.Marshal.Array
import Foreign.Ptr
{-# LINE 51 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
getExecutablePath :: IO FilePath
{-# LINE 138 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
{-# LINE 142 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
# define WINDOWS_CCONV ccall
{-# LINE 146 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
getExecutablePath = go 2048
where
go size = allocaArray (fromIntegral size) $ \ buf -> do
ret <- c_GetModuleFileName nullPtr buf size
case ret of
0 -> errorWithoutStackTrace "getExecutablePath: GetModuleFileNameW returned an error"
_ | ret < size -> do
path <- peekCWString buf
real <- getFinalPath path
exists <- withCWString real c_pathFileExists
if exists
then return real
else fail path
| otherwise -> go (size * 2)
getFinalPath :: FilePath -> IO FilePath
getFinalPath path = withCWString path $ \s ->
bracket (createFile s) c_closeHandle $ \h -> do
let invalid = h == wordPtrToPtr (-1)
{-# LINE 174 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
if invalid then pure path else go h bufSize
where go h sz = allocaArray (fromIntegral sz) $ \outPath -> do
ret <- c_getFinalPathHandle h outPath sz (8)
{-# LINE 178 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
if ret < sz
then sanitize . rejectUNCPath <$> peekCWString outPath
else go h (2 * sz)
sanitize s
| "\\\\?\\" `isPrefixOf` s = drop 4 s
| otherwise = s
rejectUNCPath s
| "\\\\?\\UNC\\" `isPrefixOf` s = path
| otherwise = s
bufSize = 1024
foreign import WINDOWS_CCONV unsafe "windows.h GetModuleFileNameW"
c_GetModuleFileName :: Ptr () -> CWString -> Word32 -> IO Word32
foreign import WINDOWS_CCONV unsafe "windows.h PathFileExistsW"
c_pathFileExists :: CWString -> IO Bool
foreign import WINDOWS_CCONV unsafe "windows.h CreateFileW"
c_createFile :: CWString
-> Word32
-> Word32
-> Ptr ()
-> Word32
-> Word32
-> Ptr ()
-> IO (Ptr ())
createFile :: CWString -> IO (Ptr ())
createFile file =
c_createFile file (2147483648)
{-# LINE 216 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
(1)
{-# LINE 217 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
nullPtr
(3)
{-# LINE 219 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
(128)
{-# LINE 220 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}
nullPtr
foreign import WINDOWS_CCONV unsafe "windows.h CloseHandle"
c_closeHandle :: Ptr () -> IO Bool
foreign import WINDOWS_CCONV unsafe "windows.h GetFinalPathNameByHandleW"
c_getFinalPathHandle :: Ptr () -> CWString -> Word32 -> Word32 -> IO Word32
{-# LINE 252 "libraries\\base\\System\\Environment\\ExecutablePath.hsc" #-}