{-# LINE 1 "System\\Win32\\File.hsc" #-}



{-# LINE 2 "System\\Win32\\File.hsc" #-}

{-# LANGUAGE Safe #-}



{-# LINE 6 "System\\Win32\\File.hsc" #-}

-----------------------------------------------------------------------------

-- |

-- Module      :  System.Win32.File

-- Copyright   :  (c) Alastair Reid, 1997-2003

-- License     :  BSD-style (see the file libraries/base/LICENSE)

--

-- Maintainer  :  Esa Ilari Vuokko <ei@vuokko.info>

-- Stability   :  provisional

-- Portability :  portable

--

-- A collection of FFI declarations for interfacing with Win32.

--

-----------------------------------------------------------------------------



module System.Win32.File where



import System.Win32.Types

import System.Win32.Time



import Foreign hiding (void)

import Control.Monad

import Control.Concurrent



#include "windows_cconv.h"









----------------------------------------------------------------

-- Enumeration types

----------------------------------------------------------------



type AccessMode   = UINT



gENERIC_NONE :: AccessMode

gENERIC_NONE = 0



gENERIC_READ               :: AccessMode

gENERIC_READ               =  2147483648

gENERIC_WRITE              :: AccessMode

gENERIC_WRITE              =  1073741824

gENERIC_EXECUTE            :: AccessMode

gENERIC_EXECUTE            =  536870912

gENERIC_ALL                :: AccessMode

gENERIC_ALL                =  268435456

dELETE                     :: AccessMode

dELETE                     =  65536

rEAD_CONTROL               :: AccessMode

rEAD_CONTROL               =  131072

wRITE_DAC                  :: AccessMode

wRITE_DAC                  =  262144

wRITE_OWNER                :: AccessMode

wRITE_OWNER                =  524288

sYNCHRONIZE                :: AccessMode

sYNCHRONIZE                =  1048576

sTANDARD_RIGHTS_REQUIRED   :: AccessMode

sTANDARD_RIGHTS_REQUIRED   =  983040

sTANDARD_RIGHTS_READ       :: AccessMode

sTANDARD_RIGHTS_READ       =  131072

sTANDARD_RIGHTS_WRITE      :: AccessMode

sTANDARD_RIGHTS_WRITE      =  131072

sTANDARD_RIGHTS_EXECUTE    :: AccessMode

sTANDARD_RIGHTS_EXECUTE    =  131072

sTANDARD_RIGHTS_ALL        :: AccessMode

sTANDARD_RIGHTS_ALL        =  2031616

sPECIFIC_RIGHTS_ALL        :: AccessMode

sPECIFIC_RIGHTS_ALL        =  65535

aCCESS_SYSTEM_SECURITY     :: AccessMode

aCCESS_SYSTEM_SECURITY     =  16777216

mAXIMUM_ALLOWED            :: AccessMode

mAXIMUM_ALLOWED            =  33554432

fILE_ADD_FILE              :: AccessMode

fILE_ADD_FILE              =  2

fILE_ADD_SUBDIRECTORY      :: AccessMode

fILE_ADD_SUBDIRECTORY      =  4

fILE_ALL_ACCESS            :: AccessMode

fILE_ALL_ACCESS            =  2032127

fILE_APPEND_DATA           :: AccessMode

fILE_APPEND_DATA           =  4

fILE_CREATE_PIPE_INSTANCE  :: AccessMode

fILE_CREATE_PIPE_INSTANCE  =  4

fILE_DELETE_CHILD          :: AccessMode

fILE_DELETE_CHILD          =  64

fILE_EXECUTE               :: AccessMode

fILE_EXECUTE               =  32

fILE_LIST_DIRECTORY        :: AccessMode

fILE_LIST_DIRECTORY        =  1

fILE_READ_ATTRIBUTES       :: AccessMode

fILE_READ_ATTRIBUTES       =  128

fILE_READ_DATA             :: AccessMode

fILE_READ_DATA             =  1

fILE_READ_EA               :: AccessMode

fILE_READ_EA               =  8

fILE_TRAVERSE              :: AccessMode

fILE_TRAVERSE              =  32

fILE_WRITE_ATTRIBUTES      :: AccessMode

fILE_WRITE_ATTRIBUTES      =  256

fILE_WRITE_DATA            :: AccessMode

fILE_WRITE_DATA            =  2

fILE_WRITE_EA              :: AccessMode

fILE_WRITE_EA              =  16



{-# LINE 77 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type ShareMode   = UINT



fILE_SHARE_NONE :: ShareMode

fILE_SHARE_NONE = 0



fILE_SHARE_READ       :: ShareMode

fILE_SHARE_READ       =  1

fILE_SHARE_WRITE      :: ShareMode

fILE_SHARE_WRITE      =  2

fILE_SHARE_DELETE     :: ShareMode

fILE_SHARE_DELETE     =  4



{-# LINE 90 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type CreateMode   = UINT



cREATE_NEW            :: CreateMode

cREATE_NEW            =  1

cREATE_ALWAYS         :: CreateMode

cREATE_ALWAYS         =  2

oPEN_EXISTING         :: CreateMode

oPEN_EXISTING         =  3

oPEN_ALWAYS           :: CreateMode

oPEN_ALWAYS           =  4

tRUNCATE_EXISTING     :: CreateMode

tRUNCATE_EXISTING     =  5



{-# LINE 102 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type FileAttributeOrFlag   = UINT



fILE_ATTRIBUTE_READONLY       :: FileAttributeOrFlag

fILE_ATTRIBUTE_READONLY       =  1

fILE_ATTRIBUTE_HIDDEN         :: FileAttributeOrFlag

fILE_ATTRIBUTE_HIDDEN         =  2

fILE_ATTRIBUTE_SYSTEM         :: FileAttributeOrFlag

fILE_ATTRIBUTE_SYSTEM         =  4

fILE_ATTRIBUTE_DIRECTORY      :: FileAttributeOrFlag

fILE_ATTRIBUTE_DIRECTORY      =  16

fILE_ATTRIBUTE_ARCHIVE        :: FileAttributeOrFlag

fILE_ATTRIBUTE_ARCHIVE        =  32

fILE_ATTRIBUTE_NORMAL         :: FileAttributeOrFlag

fILE_ATTRIBUTE_NORMAL         =  128

fILE_ATTRIBUTE_TEMPORARY      :: FileAttributeOrFlag

fILE_ATTRIBUTE_TEMPORARY      =  256

fILE_ATTRIBUTE_COMPRESSED     :: FileAttributeOrFlag

fILE_ATTRIBUTE_COMPRESSED     =  2048

fILE_ATTRIBUTE_REPARSE_POINT  :: FileAttributeOrFlag

fILE_ATTRIBUTE_REPARSE_POINT  =  1024

fILE_FLAG_WRITE_THROUGH       :: FileAttributeOrFlag

fILE_FLAG_WRITE_THROUGH       =  2147483648

fILE_FLAG_OVERLAPPED          :: FileAttributeOrFlag

fILE_FLAG_OVERLAPPED          =  1073741824

fILE_FLAG_NO_BUFFERING        :: FileAttributeOrFlag

fILE_FLAG_NO_BUFFERING        =  536870912

fILE_FLAG_RANDOM_ACCESS       :: FileAttributeOrFlag

fILE_FLAG_RANDOM_ACCESS       =  268435456

fILE_FLAG_SEQUENTIAL_SCAN     :: FileAttributeOrFlag

fILE_FLAG_SEQUENTIAL_SCAN     =  134217728

fILE_FLAG_DELETE_ON_CLOSE     :: FileAttributeOrFlag

fILE_FLAG_DELETE_ON_CLOSE     =  67108864

fILE_FLAG_BACKUP_SEMANTICS    :: FileAttributeOrFlag

fILE_FLAG_BACKUP_SEMANTICS    =  33554432

fILE_FLAG_POSIX_SEMANTICS     :: FileAttributeOrFlag

fILE_FLAG_POSIX_SEMANTICS     =  16777216



{-# LINE 126 "System\\Win32\\File.hsc" #-}



{-# LINE 127 "System\\Win32\\File.hsc" #-}

sECURITY_ANONYMOUS            :: FileAttributeOrFlag

sECURITY_ANONYMOUS            =  0

sECURITY_IDENTIFICATION       :: FileAttributeOrFlag

sECURITY_IDENTIFICATION       =  65536

sECURITY_IMPERSONATION        :: FileAttributeOrFlag

sECURITY_IMPERSONATION        =  131072

sECURITY_DELEGATION           :: FileAttributeOrFlag

sECURITY_DELEGATION           =  196608

sECURITY_CONTEXT_TRACKING     :: FileAttributeOrFlag

sECURITY_CONTEXT_TRACKING     =  262144

sECURITY_EFFECTIVE_ONLY       :: FileAttributeOrFlag

sECURITY_EFFECTIVE_ONLY       =  524288

sECURITY_SQOS_PRESENT         :: FileAttributeOrFlag

sECURITY_SQOS_PRESENT         =  1048576

sECURITY_VALID_SQOS_FLAGS     :: FileAttributeOrFlag

sECURITY_VALID_SQOS_FLAGS     =  2031616



{-# LINE 137 "System\\Win32\\File.hsc" #-}



{-# LINE 138 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type MoveFileFlag   = DWORD



mOVEFILE_REPLACE_EXISTING     :: MoveFileFlag

mOVEFILE_REPLACE_EXISTING     =  1

mOVEFILE_COPY_ALLOWED         :: MoveFileFlag

mOVEFILE_COPY_ALLOWED         =  2

mOVEFILE_DELAY_UNTIL_REBOOT   :: MoveFileFlag

mOVEFILE_DELAY_UNTIL_REBOOT   =  4



{-# LINE 148 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type FilePtrDirection   = DWORD



fILE_BEGIN    :: FilePtrDirection

fILE_BEGIN    =  0

fILE_CURRENT  :: FilePtrDirection

fILE_CURRENT  =  1

fILE_END      :: FilePtrDirection

fILE_END      =  2



{-# LINE 158 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type DriveType = UINT



dRIVE_UNKNOWN         :: DriveType

dRIVE_UNKNOWN         =  0

dRIVE_NO_ROOT_DIR     :: DriveType

dRIVE_NO_ROOT_DIR     =  1

dRIVE_REMOVABLE       :: DriveType

dRIVE_REMOVABLE       =  2

dRIVE_FIXED           :: DriveType

dRIVE_FIXED           =  3

dRIVE_REMOTE          :: DriveType

dRIVE_REMOTE          =  4

dRIVE_CDROM           :: DriveType

dRIVE_CDROM           =  5

dRIVE_RAMDISK         :: DriveType

dRIVE_RAMDISK         =  6



{-# LINE 172 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type DefineDosDeviceFlags = DWORD



dDD_RAW_TARGET_PATH           :: DefineDosDeviceFlags

dDD_RAW_TARGET_PATH           =  1

dDD_REMOVE_DEFINITION         :: DefineDosDeviceFlags

dDD_REMOVE_DEFINITION         =  2

dDD_EXACT_MATCH_ON_REMOVE     :: DefineDosDeviceFlags

dDD_EXACT_MATCH_ON_REMOVE     =  4



{-# LINE 182 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type BinaryType = DWORD



sCS_32BIT_BINARY      :: BinaryType

sCS_32BIT_BINARY      =  0

sCS_DOS_BINARY        :: BinaryType

sCS_DOS_BINARY        =  1

sCS_WOW_BINARY        :: BinaryType

sCS_WOW_BINARY        =  2

sCS_PIF_BINARY        :: BinaryType

sCS_PIF_BINARY        =  3

sCS_POSIX_BINARY      :: BinaryType

sCS_POSIX_BINARY      =  4

sCS_OS216_BINARY      :: BinaryType

sCS_OS216_BINARY      =  5



{-# LINE 195 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type FileNotificationFlag = DWORD



fILE_NOTIFY_CHANGE_FILE_NAME   :: FileNotificationFlag

fILE_NOTIFY_CHANGE_FILE_NAME   =  1

fILE_NOTIFY_CHANGE_DIR_NAME    :: FileNotificationFlag

fILE_NOTIFY_CHANGE_DIR_NAME    =  2

fILE_NOTIFY_CHANGE_ATTRIBUTES  :: FileNotificationFlag

fILE_NOTIFY_CHANGE_ATTRIBUTES  =  4

fILE_NOTIFY_CHANGE_SIZE        :: FileNotificationFlag

fILE_NOTIFY_CHANGE_SIZE        =  8

fILE_NOTIFY_CHANGE_LAST_WRITE  :: FileNotificationFlag

fILE_NOTIFY_CHANGE_LAST_WRITE  =  16

fILE_NOTIFY_CHANGE_SECURITY    :: FileNotificationFlag

fILE_NOTIFY_CHANGE_SECURITY    =  256



{-# LINE 208 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type FileType = DWORD



fILE_TYPE_UNKNOWN     :: FileType

fILE_TYPE_UNKNOWN     =  0

fILE_TYPE_DISK        :: FileType

fILE_TYPE_DISK        =  1

fILE_TYPE_CHAR        :: FileType

fILE_TYPE_CHAR        =  2

fILE_TYPE_PIPE        :: FileType

fILE_TYPE_PIPE        =  3

fILE_TYPE_REMOTE      :: FileType

fILE_TYPE_REMOTE      =  32768



{-# LINE 220 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type LockMode = DWORD



lOCKFILE_EXCLUSIVE_LOCK    :: LockMode

lOCKFILE_EXCLUSIVE_LOCK    =  2

lOCKFILE_FAIL_IMMEDIATELY  :: LockMode

lOCKFILE_FAIL_IMMEDIATELY  =  1



{-# LINE 229 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



newtype GET_FILEEX_INFO_LEVELS = GET_FILEEX_INFO_LEVELS (Word32)

{-# LINE 233 "System\\Win32\\File.hsc" #-}

    deriving (Eq, Ord)



getFileExInfoStandard  :: GET_FILEEX_INFO_LEVELS

getFileExInfoStandard  = GET_FILEEX_INFO_LEVELS 0

getFileExMaxInfoLevel  :: GET_FILEEX_INFO_LEVELS

getFileExMaxInfoLevel  = GET_FILEEX_INFO_LEVELS 1



{-# LINE 239 "System\\Win32\\File.hsc" #-}



----------------------------------------------------------------



type LPSECURITY_ATTRIBUTES = Ptr ()

type MbLPSECURITY_ATTRIBUTES = Maybe LPSECURITY_ATTRIBUTES



----------------------------------------------------------------

-- Other types

----------------------------------------------------------------



data BY_HANDLE_FILE_INFORMATION = BY_HANDLE_FILE_INFORMATION

    { bhfiFileAttributes :: FileAttributeOrFlag

    , bhfiCreationTime, bhfiLastAccessTime, bhfiLastWriteTime :: FILETIME

    , bhfiVolumeSerialNumber :: DWORD

    , bhfiSize :: DDWORD

    , bhfiNumberOfLinks :: DWORD

    , bhfiFileIndex :: DDWORD

    } deriving (Show)



instance Storable BY_HANDLE_FILE_INFORMATION where

    sizeOf = const ((52))

{-# LINE 260 "System\\Win32\\File.hsc" #-}

    alignment _ = 4

{-# LINE 261 "System\\Win32\\File.hsc" #-}

    poke buf bhi = do

        ((\hsc_ptr -> pokeByteOff hsc_ptr 0))     buf (bhfiFileAttributes bhi)

{-# LINE 263 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 4))       buf (bhfiCreationTime bhi)

{-# LINE 264 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 12))     buf (bhfiLastAccessTime bhi)

{-# LINE 265 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 20))      buf (bhfiLastWriteTime bhi)

{-# LINE 266 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 28)) buf (bhfiVolumeSerialNumber bhi)

{-# LINE 267 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 32))        buf sizeHi

{-# LINE 268 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 36))         buf sizeLow

{-# LINE 269 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 40))       buf (bhfiNumberOfLinks bhi)

{-# LINE 270 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 44))       buf idxHi

{-# LINE 271 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 48))        buf idxLow

{-# LINE 272 "System\\Win32\\File.hsc" #-}

        where

            (sizeHi,sizeLow) = ddwordToDwords $ bhfiSize bhi

            (idxHi,idxLow) = ddwordToDwords $ bhfiFileIndex bhi



    peek buf = do

        attr <- ((\hsc_ptr -> peekByteOff hsc_ptr 0))     buf

{-# LINE 278 "System\\Win32\\File.hsc" #-}

        ctim <- ((\hsc_ptr -> peekByteOff hsc_ptr 4))       buf

{-# LINE 279 "System\\Win32\\File.hsc" #-}

        lati <- ((\hsc_ptr -> peekByteOff hsc_ptr 12))     buf

{-# LINE 280 "System\\Win32\\File.hsc" #-}

        lwti <- ((\hsc_ptr -> peekByteOff hsc_ptr 20))      buf

{-# LINE 281 "System\\Win32\\File.hsc" #-}

        vser <- ((\hsc_ptr -> peekByteOff hsc_ptr 28)) buf

{-# LINE 282 "System\\Win32\\File.hsc" #-}

        fshi <- ((\hsc_ptr -> peekByteOff hsc_ptr 32))        buf

{-# LINE 283 "System\\Win32\\File.hsc" #-}

        fslo <- ((\hsc_ptr -> peekByteOff hsc_ptr 36))         buf

{-# LINE 284 "System\\Win32\\File.hsc" #-}

        link <- ((\hsc_ptr -> peekByteOff hsc_ptr 40))       buf

{-# LINE 285 "System\\Win32\\File.hsc" #-}

        idhi <- ((\hsc_ptr -> peekByteOff hsc_ptr 44))       buf

{-# LINE 286 "System\\Win32\\File.hsc" #-}

        idlo <- ((\hsc_ptr -> peekByteOff hsc_ptr 48))        buf

{-# LINE 287 "System\\Win32\\File.hsc" #-}

        return $ BY_HANDLE_FILE_INFORMATION attr ctim lati lwti vser

            (dwordsToDdword (fshi,fslo)) link (dwordsToDdword (idhi,idlo))



----------------------------------------------------------------



data WIN32_FILE_ATTRIBUTE_DATA = WIN32_FILE_ATTRIBUTE_DATA

    { fadFileAttributes :: DWORD

    , fadCreationTime , fadLastAccessTime , fadLastWriteTime :: FILETIME

    , fadFileSize :: DDWORD

    } deriving (Show)



instance Storable WIN32_FILE_ATTRIBUTE_DATA where

    sizeOf = const ((36))

{-# LINE 300 "System\\Win32\\File.hsc" #-}

    alignment _ = 4

{-# LINE 301 "System\\Win32\\File.hsc" #-}

    poke buf ad = do

        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (fadFileAttributes ad)

{-# LINE 303 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 4))   buf (fadCreationTime ad)

{-# LINE 304 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 12)) buf (fadLastAccessTime ad)

{-# LINE 305 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 20))  buf (fadLastWriteTime ad)

{-# LINE 306 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 28))    buf sizeHi

{-# LINE 307 "System\\Win32\\File.hsc" #-}

        ((\hsc_ptr -> pokeByteOff hsc_ptr 32))     buf sizeLo

{-# LINE 308 "System\\Win32\\File.hsc" #-}

        where

            (sizeHi,sizeLo) = ddwordToDwords $ fadFileSize ad



    peek buf = do

        attr <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf

{-# LINE 313 "System\\Win32\\File.hsc" #-}

        ctim <- ((\hsc_ptr -> peekByteOff hsc_ptr 4))   buf

{-# LINE 314 "System\\Win32\\File.hsc" #-}

        lati <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) buf

{-# LINE 315 "System\\Win32\\File.hsc" #-}

        lwti <- ((\hsc_ptr -> peekByteOff hsc_ptr 20))  buf

{-# LINE 316 "System\\Win32\\File.hsc" #-}

        fshi <- ((\hsc_ptr -> peekByteOff hsc_ptr 28))    buf

{-# LINE 317 "System\\Win32\\File.hsc" #-}

        fslo <- ((\hsc_ptr -> peekByteOff hsc_ptr 32))     buf

{-# LINE 318 "System\\Win32\\File.hsc" #-}

        return $ WIN32_FILE_ATTRIBUTE_DATA attr ctim lati lwti

            (dwordsToDdword (fshi,fslo))



----------------------------------------------------------------

-- File operations

----------------------------------------------------------------



-- | like failIfFalse_, but retried on sharing violations.

-- This is necessary for many file operations; see

--   http://support.microsoft.com/kb/316609

--

failIfWithRetry :: (a -> Bool) -> String -> IO a -> IO a

failIfWithRetry cond msg action = retryOrFail retries

  where

    delay   = 100*1000 -- in ms, we use threadDelay

    retries = 20 :: Int

      -- KB article recommends 250/5



    -- retryOrFail :: Int -> IO a

    retryOrFail times

      | times <= 0 = errorWin msg

      | otherwise  = do

         ret <- action

         if not (cond ret)

            then return ret

            else do

              err_code <- getLastError

              if err_code == (32)

{-# LINE 346 "System\\Win32\\File.hsc" #-}

                then do threadDelay delay; retryOrFail (times - 1)

                else errorWin msg



failIfWithRetry_ :: (a -> Bool) -> String -> IO a -> IO ()

failIfWithRetry_ cond msg action = void $ failIfWithRetry cond msg action



failIfFalseWithRetry_ :: String -> IO Bool -> IO ()

failIfFalseWithRetry_ = failIfWithRetry_ not



deleteFile :: String -> IO ()

deleteFile name =

  withTString name $ \ c_name ->

    failIfFalseWithRetry_ (unwords ["DeleteFile",show name]) $

      c_DeleteFile c_name

foreign import WINDOWS_CCONV unsafe "windows.h DeleteFileW"

  c_DeleteFile :: LPCTSTR -> IO Bool



copyFile :: String -> String -> Bool -> IO ()

copyFile src dest over =

  withTString src $ \ c_src ->

  withTString dest $ \ c_dest ->

  failIfFalseWithRetry_ (unwords ["CopyFile",show src,show dest]) $

    c_CopyFile c_src c_dest over

foreign import WINDOWS_CCONV unsafe "windows.h CopyFileW"

  c_CopyFile :: LPCTSTR -> LPCTSTR -> Bool -> IO Bool



moveFile :: String -> String -> IO ()

moveFile src dest =

  withTString src $ \ c_src ->

  withTString dest $ \ c_dest ->

  failIfFalseWithRetry_ (unwords ["MoveFile",show src,show dest]) $

    c_MoveFile c_src c_dest

foreign import WINDOWS_CCONV unsafe "windows.h MoveFileW"

  c_MoveFile :: LPCTSTR -> LPCTSTR -> IO Bool



moveFileEx :: String -> Maybe String -> MoveFileFlag -> IO ()

moveFileEx src dest flags =

  withTString src $ \ c_src ->

  maybeWith withTString dest $ \ c_dest ->

  failIfFalseWithRetry_ (unwords ["MoveFileEx",show src,show dest]) $

    c_MoveFileEx c_src c_dest flags

foreign import WINDOWS_CCONV unsafe "windows.h MoveFileExW"

  c_MoveFileEx :: LPCTSTR -> LPCTSTR -> MoveFileFlag -> IO Bool



setCurrentDirectory :: String -> IO ()

setCurrentDirectory name =

  withTString name $ \ c_name ->

  failIfFalse_ (unwords ["SetCurrentDirectory",show name]) $

    c_SetCurrentDirectory c_name

foreign import WINDOWS_CCONV unsafe "windows.h SetCurrentDirectoryW"

  c_SetCurrentDirectory :: LPCTSTR -> IO Bool



createDirectory :: String -> Maybe LPSECURITY_ATTRIBUTES -> IO ()

createDirectory name mb_attr =

  withTString name $ \ c_name ->

  failIfFalseWithRetry_ (unwords ["CreateDirectory",show name]) $

    c_CreateDirectory c_name (maybePtr mb_attr)

foreign import WINDOWS_CCONV unsafe "windows.h CreateDirectoryW"

  c_CreateDirectory :: LPCTSTR -> LPSECURITY_ATTRIBUTES -> IO Bool



createDirectoryEx :: String -> String -> Maybe LPSECURITY_ATTRIBUTES -> IO ()

createDirectoryEx template name mb_attr =

  withTString template $ \ c_template ->

  withTString name $ \ c_name ->

  failIfFalseWithRetry_ (unwords ["CreateDirectoryEx",show template,show name]) $

    c_CreateDirectoryEx c_template c_name (maybePtr mb_attr)

foreign import WINDOWS_CCONV unsafe "windows.h CreateDirectoryExW"

  c_CreateDirectoryEx :: LPCTSTR -> LPCTSTR -> LPSECURITY_ATTRIBUTES -> IO Bool



removeDirectory :: String -> IO ()

removeDirectory name =

  withTString name $ \ c_name ->

  failIfFalseWithRetry_ (unwords ["RemoveDirectory",show name]) $

    c_RemoveDirectory c_name

foreign import WINDOWS_CCONV unsafe "windows.h RemoveDirectoryW"

  c_RemoveDirectory :: LPCTSTR -> IO Bool



getBinaryType :: String -> IO BinaryType

getBinaryType name =

  withTString name $ \ c_name ->

  alloca $ \ p_btype -> do

  failIfFalse_ (unwords ["GetBinaryType",show name]) $

    c_GetBinaryType c_name p_btype

  peek p_btype

foreign import WINDOWS_CCONV unsafe "windows.h GetBinaryTypeW"

  c_GetBinaryType :: LPCTSTR -> Ptr DWORD -> IO Bool



----------------------------------------------------------------

-- HANDLE operations

----------------------------------------------------------------



createFile :: String -> AccessMode -> ShareMode -> Maybe LPSECURITY_ATTRIBUTES -> CreateMode -> FileAttributeOrFlag -> Maybe HANDLE -> IO HANDLE

createFile name access share mb_attr mode flag mb_h =

  withTString name $ \ c_name ->

  failIfWithRetry (==iNVALID_HANDLE_VALUE) (unwords ["CreateFile",show name]) $

    c_CreateFile c_name access share (maybePtr mb_attr) mode flag (maybePtr mb_h)

foreign import WINDOWS_CCONV unsafe "windows.h CreateFileW"

  c_CreateFile :: LPCTSTR -> AccessMode -> ShareMode -> LPSECURITY_ATTRIBUTES -> CreateMode -> FileAttributeOrFlag -> HANDLE -> IO HANDLE



closeHandle :: HANDLE -> IO ()

closeHandle h =

  failIfFalse_ "CloseHandle" $ c_CloseHandle h

foreign import WINDOWS_CCONV unsafe "windows.h CloseHandle"

  c_CloseHandle :: HANDLE -> IO Bool



{-# CFILES cbits/HsWin32.c #-}

foreign import ccall "HsWin32.h &CloseHandleFinaliser"

    c_CloseHandleFinaliser :: FunPtr (Ptr a -> IO ())



foreign import WINDOWS_CCONV unsafe "windows.h GetFileType"

  getFileType :: HANDLE -> IO FileType

--Apparently no error code



flushFileBuffers :: HANDLE -> IO ()

flushFileBuffers h =

  failIfFalse_ "FlushFileBuffers" $ c_FlushFileBuffers h

foreign import WINDOWS_CCONV unsafe "windows.h FlushFileBuffers"

  c_FlushFileBuffers :: HANDLE -> IO Bool



setEndOfFile :: HANDLE -> IO ()

setEndOfFile h =

  failIfFalse_ "SetEndOfFile" $ c_SetEndOfFile h

foreign import WINDOWS_CCONV unsafe "windows.h SetEndOfFile"

  c_SetEndOfFile :: HANDLE -> IO Bool



setFileAttributes :: String -> FileAttributeOrFlag -> IO ()

setFileAttributes name attr =

  withTString name $ \ c_name ->

  failIfFalseWithRetry_ (unwords ["SetFileAttributes",show name])

    $ c_SetFileAttributes c_name attr

foreign import WINDOWS_CCONV unsafe "windows.h SetFileAttributesW"

  c_SetFileAttributes :: LPCTSTR -> FileAttributeOrFlag -> IO Bool



getFileAttributes :: String -> IO FileAttributeOrFlag

getFileAttributes name =

  withTString name $ \ c_name ->

  failIfWithRetry (== 0xFFFFFFFF) (unwords ["GetFileAttributes",show name]) $

    c_GetFileAttributes c_name

foreign import WINDOWS_CCONV unsafe "windows.h GetFileAttributesW"

  c_GetFileAttributes :: LPCTSTR -> IO FileAttributeOrFlag



getFileAttributesExStandard :: String -> IO WIN32_FILE_ATTRIBUTE_DATA

getFileAttributesExStandard name =  alloca $ \res -> do

  withTString name $ \ c_name ->

    failIfFalseWithRetry_ "getFileAttributesExStandard" $

      c_GetFileAttributesEx c_name getFileExInfoStandard res

  peek res

foreign import WINDOWS_CCONV unsafe "windows.h GetFileAttributesExW"

  c_GetFileAttributesEx :: LPCTSTR -> GET_FILEEX_INFO_LEVELS -> Ptr a -> IO BOOL



getFileInformationByHandle :: HANDLE -> IO BY_HANDLE_FILE_INFORMATION

getFileInformationByHandle h = alloca $ \res -> do

    failIfFalseWithRetry_ "GetFileInformationByHandle" $ c_GetFileInformationByHandle h res

    peek res

foreign import WINDOWS_CCONV unsafe "windows.h GetFileInformationByHandle"

    c_GetFileInformationByHandle :: HANDLE -> Ptr BY_HANDLE_FILE_INFORMATION -> IO BOOL



----------------------------------------------------------------

-- Read/write files

----------------------------------------------------------------



-- No support for this yet

data OVERLAPPED

  = OVERLAPPED { ovl_internal     :: ULONG_PTR

               , ovl_internalHigh :: ULONG_PTR

               , ovl_offset       :: DWORD

               , ovl_offsetHigh   :: DWORD

               , ovl_hEvent       :: HANDLE

               } deriving (Show)



instance Storable OVERLAPPED where

  sizeOf = const ((32))

{-# LINE 518 "System\\Win32\\File.hsc" #-}

  alignment _ = 8

{-# LINE 519 "System\\Win32\\File.hsc" #-}

  poke buf ad = do

      ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (ovl_internal     ad)

{-# LINE 521 "System\\Win32\\File.hsc" #-}

      ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (ovl_internalHigh ad)

{-# LINE 522 "System\\Win32\\File.hsc" #-}

      ((\hsc_ptr -> pokeByteOff hsc_ptr 16)) buf (ovl_offset       ad)

{-# LINE 523 "System\\Win32\\File.hsc" #-}

      ((\hsc_ptr -> pokeByteOff hsc_ptr 20)) buf (ovl_offsetHigh   ad)

{-# LINE 524 "System\\Win32\\File.hsc" #-}

      ((\hsc_ptr -> pokeByteOff hsc_ptr 24)) buf (ovl_hEvent       ad)

{-# LINE 525 "System\\Win32\\File.hsc" #-}



  peek buf = do

      intnl      <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf

{-# LINE 528 "System\\Win32\\File.hsc" #-}

      intnl_high <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf

{-# LINE 529 "System\\Win32\\File.hsc" #-}

      off        <- ((\hsc_ptr -> peekByteOff hsc_ptr 16)) buf

{-# LINE 530 "System\\Win32\\File.hsc" #-}

      off_high   <- ((\hsc_ptr -> peekByteOff hsc_ptr 20)) buf

{-# LINE 531 "System\\Win32\\File.hsc" #-}

      hevnt      <- ((\hsc_ptr -> peekByteOff hsc_ptr 24)) buf

{-# LINE 532 "System\\Win32\\File.hsc" #-}

      return $ OVERLAPPED intnl intnl_high off off_high hevnt



type LPOVERLAPPED = Ptr OVERLAPPED



type MbLPOVERLAPPED = Maybe LPOVERLAPPED



--Sigh - I give up & prefix win32_ to the next two to avoid

-- senseless Prelude name clashes. --sof.



win32_ReadFile :: HANDLE -> Ptr a -> DWORD -> Maybe LPOVERLAPPED -> IO DWORD

win32_ReadFile h buf n mb_over =

  alloca $ \ p_n -> do

  failIfFalse_ "ReadFile" $ c_ReadFile h buf n p_n (maybePtr mb_over)

  peek p_n

foreign import WINDOWS_CCONV unsafe "windows.h ReadFile"

  c_ReadFile :: HANDLE -> Ptr a -> DWORD -> Ptr DWORD -> LPOVERLAPPED -> IO Bool



win32_WriteFile :: HANDLE -> Ptr a -> DWORD -> Maybe LPOVERLAPPED -> IO DWORD

win32_WriteFile h buf n mb_over =

  alloca $ \ p_n -> do

  failIfFalse_ "WriteFile" $ c_WriteFile h buf n p_n (maybePtr mb_over)

  peek p_n

foreign import WINDOWS_CCONV unsafe "windows.h WriteFile"

  c_WriteFile :: HANDLE -> Ptr a -> DWORD -> Ptr DWORD -> LPOVERLAPPED -> IO Bool



setFilePointerEx :: HANDLE -> LARGE_INTEGER -> FilePtrDirection -> IO LARGE_INTEGER

setFilePointerEx h dist dir =

  alloca $ \p_pos -> do

  failIfFalse_ "SetFilePointerEx" $ c_SetFilePointerEx h dist p_pos dir

  peek p_pos

foreign import WINDOWS_CCONV unsafe "windows.h SetFilePointerEx"

  c_SetFilePointerEx :: HANDLE -> LARGE_INTEGER -> Ptr LARGE_INTEGER -> FilePtrDirection -> IO Bool



----------------------------------------------------------------

-- File Notifications

--

-- Use these to initialise, "increment" and close a HANDLE you can wait

-- on.

----------------------------------------------------------------



findFirstChangeNotification :: String -> Bool -> FileNotificationFlag -> IO HANDLE

findFirstChangeNotification path watch flag =

  withTString path $ \ c_path ->

  failIfNull (unwords ["FindFirstChangeNotification",show path]) $

    c_FindFirstChangeNotification c_path watch flag

foreign import WINDOWS_CCONV unsafe "windows.h FindFirstChangeNotificationW"

  c_FindFirstChangeNotification :: LPCTSTR -> Bool -> FileNotificationFlag -> IO HANDLE



findNextChangeNotification :: HANDLE -> IO ()

findNextChangeNotification h =

  failIfFalse_ "FindNextChangeNotification" $ c_FindNextChangeNotification h

foreign import WINDOWS_CCONV unsafe "windows.h FindNextChangeNotification"

  c_FindNextChangeNotification :: HANDLE -> IO Bool



findCloseChangeNotification :: HANDLE -> IO ()

findCloseChangeNotification h =

  failIfFalse_ "FindCloseChangeNotification" $ c_FindCloseChangeNotification h

foreign import WINDOWS_CCONV unsafe "windows.h FindCloseChangeNotification"

  c_FindCloseChangeNotification :: HANDLE -> IO Bool



----------------------------------------------------------------

-- Directories

----------------------------------------------------------------



type WIN32_FIND_DATA = ()



newtype FindData = FindData (ForeignPtr WIN32_FIND_DATA)



getFindDataFileName :: FindData -> IO FilePath

getFindDataFileName (FindData fp) =

  withForeignPtr fp $ \p ->

    peekTString (((\hsc_ptr -> hsc_ptr `plusPtr` 44)) p)

{-# LINE 604 "System\\Win32\\File.hsc" #-}



findFirstFile :: String -> IO (HANDLE, FindData)

findFirstFile str = do

  fp_finddata <- mallocForeignPtrBytes (592)

{-# LINE 608 "System\\Win32\\File.hsc" #-}

  withForeignPtr fp_finddata $ \p_finddata -> do

    handle <- withTString str $ \tstr -> do

                failIf (== iNVALID_HANDLE_VALUE) "findFirstFile" $

                  c_FindFirstFile tstr p_finddata

    return (handle, FindData fp_finddata)

foreign import WINDOWS_CCONV unsafe "windows.h FindFirstFileW"

  c_FindFirstFile :: LPCTSTR -> Ptr WIN32_FIND_DATA -> IO HANDLE



findNextFile :: HANDLE -> FindData -> IO Bool -- False -> no more files

findNextFile h (FindData finddata) = do

  withForeignPtr finddata $ \p_finddata -> do

    b <- c_FindNextFile h p_finddata

    if b

       then return True

       else do

             err_code <- getLastError

             if err_code == (18)

{-# LINE 625 "System\\Win32\\File.hsc" #-}

                then return False

                else failWith "findNextFile" err_code

foreign import WINDOWS_CCONV unsafe "windows.h FindNextFileW"

  c_FindNextFile :: HANDLE -> Ptr WIN32_FIND_DATA -> IO BOOL



findClose :: HANDLE -> IO ()

findClose h = failIfFalse_ "findClose" $ c_FindClose h

foreign import WINDOWS_CCONV unsafe "windows.h FindClose"

  c_FindClose :: HANDLE -> IO BOOL



----------------------------------------------------------------

-- DOS Device flags

----------------------------------------------------------------



defineDosDevice :: DefineDosDeviceFlags -> String -> Maybe String -> IO ()

defineDosDevice flags name path =

  maybeWith withTString path $ \ c_path ->

  withTString name $ \ c_name ->

  failIfFalse_ "DefineDosDevice" $ c_DefineDosDevice flags c_name c_path

foreign import WINDOWS_CCONV unsafe "windows.h DefineDosDeviceW"

  c_DefineDosDevice :: DefineDosDeviceFlags -> LPCTSTR -> LPCTSTR -> IO Bool



----------------------------------------------------------------



-- These functions are very unusual in the Win32 API:

-- They dont return error codes



foreign import WINDOWS_CCONV unsafe "windows.h AreFileApisANSI"

  areFileApisANSI :: IO Bool



foreign import WINDOWS_CCONV unsafe "windows.h SetFileApisToOEM"

  setFileApisToOEM :: IO ()



foreign import WINDOWS_CCONV unsafe "windows.h SetFileApisToANSI"

  setFileApisToANSI :: IO ()



foreign import WINDOWS_CCONV unsafe "windows.h SetHandleCount"

  setHandleCount :: UINT -> IO UINT



----------------------------------------------------------------



getLogicalDrives :: IO DWORD

getLogicalDrives =

  failIfZero "GetLogicalDrives" $ c_GetLogicalDrives

foreign import WINDOWS_CCONV unsafe "windows.h GetLogicalDrives"

  c_GetLogicalDrives :: IO DWORD



-- %fun GetDriveType :: Maybe String -> IO DriveType



getDiskFreeSpace :: Maybe String -> IO (DWORD,DWORD,DWORD,DWORD)

getDiskFreeSpace path =

  maybeWith withTString path $ \ c_path ->

  alloca $ \ p_sectors ->

  alloca $ \ p_bytes ->

  alloca $ \ p_nfree ->

  alloca $ \ p_nclusters -> do

  failIfFalse_ "GetDiskFreeSpace" $

    c_GetDiskFreeSpace c_path p_sectors p_bytes p_nfree p_nclusters

  sectors <- peek p_sectors

  bytes <- peek p_bytes

  nfree <- peek p_nfree

  nclusters <- peek p_nclusters

  return (sectors, bytes, nfree, nclusters)

foreign import WINDOWS_CCONV unsafe "windows.h GetDiskFreeSpaceW"

  c_GetDiskFreeSpace :: LPCTSTR -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> Ptr DWORD -> IO Bool



setVolumeLabel :: Maybe String -> Maybe String -> IO ()

setVolumeLabel path name =

  maybeWith withTString path $ \ c_path ->

  maybeWith withTString name $ \ c_name ->

  failIfFalse_ "SetVolumeLabel" $ c_SetVolumeLabel c_path c_name

foreign import WINDOWS_CCONV unsafe "windows.h SetVolumeLabelW"

  c_SetVolumeLabel :: LPCTSTR -> LPCTSTR -> IO Bool



----------------------------------------------------------------

-- File locks

----------------------------------------------------------------



-- | Locks a given range in a file handle, To lock an entire file

--   use 0xFFFFFFFFFFFFFFFF for size and 0 for offset.

lockFile :: HANDLE   -- ^ CreateFile handle

         -> LockMode -- ^ Locking mode

         -> DWORD64  -- ^ Size of region to lock

         -> DWORD64  -- ^ Beginning offset of file to lock

         -> IO BOOL  -- ^ Indicates if locking was successful, if not query

                     --   getLastError.

lockFile hwnd mode size f_offset =

  do let s_low = fromIntegral (size .&. 0xFFFFFFFF)

         s_hi  = fromIntegral (size `shiftR` 32)

         o_low = fromIntegral (f_offset .&. 0xFFFFFFFF)

         o_hi  = fromIntegral (f_offset `shiftR` 32)

         ovlp  = OVERLAPPED 0 0 o_low o_hi nullPtr

     with ovlp $ \ptr -> c_LockFileEx hwnd mode 0 s_low s_hi ptr



foreign import WINDOWS_CCONV unsafe "LockFileEx"

  c_LockFileEx :: HANDLE -> DWORD -> DWORD -> DWORD -> DWORD -> LPOVERLAPPED

               -> IO BOOL



-- | Unlocks a given range in a file handle, To unlock an entire file

--   use 0xFFFFFFFFFFFFFFFF for size and 0 for offset.

unlockFile :: HANDLE  -- ^ CreateFile handle

           -> DWORD64 -- ^ Size of region to unlock

           -> DWORD64 -- ^ Beginning offset of file to unlock

           -> IO BOOL -- ^ Indicates if unlocking was successful, if not query

                      --   getLastError.

unlockFile hwnd size f_offset =

  do let s_low = fromIntegral (size .&. 0xFFFFFFFF)

         s_hi  = fromIntegral (size `shiftR` 32)

         o_low = fromIntegral (f_offset .&. 0xFFFFFFFF)

         o_hi  = fromIntegral (f_offset `shiftR` 32)

         ovlp  = OVERLAPPED 0 0 o_low o_hi nullPtr

     with ovlp $ \ptr -> c_UnlockFileEx hwnd 0 s_low s_hi ptr



foreign import WINDOWS_CCONV unsafe "UnlockFileEx"

  c_UnlockFileEx :: HANDLE -> DWORD -> DWORD -> DWORD -> LPOVERLAPPED -> IO BOOL



----------------------------------------------------------------

-- End

----------------------------------------------------------------