Git Product home page Git Product logo

win32's Introduction

The Win32 Package

Hackage PyPI Windows build status

See Win32 on Hackage for more information.

Installing from Git

This package requires no special installation instructions.

To install use cabal install

Documentation

This library is just a direct binding to Windows API calls and as such contains no documentation. The documentation for functions can be found in the equivalently named functions on MSDN https://msdn.microsoft.com/library/windows/desktop/hh920508.aspx

Getting Started

The Win32 library is a core GHC library and as such aims to have an as little as possible footprint when it comes to dependencies.

When submitting new requests think hard if any new Haskell dependencies are actually needed. (note that this does not apply to C dependencies.)

The best way to get started is using cabal new-build and cabal sandboxes:

git clone [email protected]:haskell/win32.git
cd win32
cabal v2-repl

win32's People

Contributors

a3f avatar alexbiehl avatar batterseapower avatar bgamari avatar binderdavid avatar bos avatar clefru avatar coot avatar hamishmack avatar hasufell avatar hvr avatar igfoo avatar javalight avatar joeyh avatar jship avatar kludgy avatar mistuke avatar mpilgrem avatar ndmitchell avatar nightra avatar nkpart avatar pcapriotti avatar redneb avatar rufflewind avatar ryanglscott avatar shekeru avatar simonmar avatar thoughtpolice avatar tmcl avatar tswelsh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

win32's Issues

Clarify the decision behind the HWND/HANDLE/Ptr() type synonyms

I was surprised to find that these aren't the definitions for HWND and HANDLE

newtype HWND = HWND { unsafeHWNDToHANDLE :: HANDLE }

newtype HANDLE = HANDLE { unsafeHANDLEToPtr :: Ptr () }

I'm not an expert in Win32 programming, but I don't think that conversions between these three types are so pervasive (and without consequence) as to necessitate using synonyms here rather than something which protects the programmer a little more. If this is required, it would be great to document the declarations with this information, if not then perhaps there could be a major version update replacing the synonyms.

The same thing could probably be said for any of the other type synonyms of HANDLE in Win32.

"Pattern match failure in do expression at libraries\Win32\System\Win32\Types.hsc:311:9-15"

When running the test suite of temporary-1.3 with --io-manager=native I get the error above:

Test suite test: RUNNING...
test.exe: user error (Pattern match failure in do expression at libraries\Win32\System\Win32\Types.hsc:311:9-15)
Test suite test: FAIL
Test suite logged to: C:\Users\hasuf\temporary\dist-newstyle\build\x86_64-windows\ghc-9.0.1\temporary-1.3\t\test\test\temporary-1.3-test.log

Steps to Reproduce (for bugs)

  1. Run the test suite with new IO manager

Your Environment

cabal-install 3.4.0.0, GHC-9.0.1, Win32-2.10.0.0, Windows 10

Bump version and cut release for GHC 7.8.1

Currently, GHC HEAD still reports Win32-2.3.0.0 in its package registry (which is incorrect, as 2.3.0.0 is what GHC 7.6.3 shipped with, and there have been non-trivial commits since then)

Moreover, the GHC 7.8.1 release candidate is getting closer, and we should get the boot lib versioning in order asap.

/cc @thoughtpolice

Hackage docs

Would you mind manually uploading the documentation for this library to Hackage? Their auto-generated docs fail since this library requires linking to some Windows only code which their build servers don't have.

The easiest way to do it is to use this script.

Thanks.

(Maybe String) parameters in API functions

There are quite some functions with optional LPTSTR parameters in the Winpi, where passing NULL invokes the default behaviour. An example for this is FindWindow (msdn).

The available Haskell wrappers don't support passing NULL to these functions.
The solution would be using Maybe String and writing a new withTString that returns nullPtr if Nothing is passed to it (i.e.: Maybe String -> (CString -> IO a) -> IO a). I can't find any readily available way to achieve the same, so I would make a group of functions ร  la withOptCWString and so on.

I'd be glad to give something back to the community by doing these changes, but as this also affects Foreign.C.String in ghc-base I wanted to ask for guidance first whether that's the right way to go :)

Exports are too unconstrained

Currently many of Win32's modules have no export list, meaning that they often unintentionally export what were supposed to be internal functions (e.g. FFI imports). For instance, see System.Win32.Event, which exports c_WaitForSingleObject and many others. This ends up breaking haskeline.

As a rule in a library like this all modules should have an export list.

Package fails to compile on Windows x64

Loading package Win32-2.3.0.0 ... linking ... ghc.exe: internal error: R_X86_64_
PC32: High bits are set in 7ffd8d3da4d4 for DefDlgProcW
    (GHC version 7.6.3 for x86_64_unknown_mingw32)
    Please report this as a GHC bug:  http://www.haskell.org/ghc/reportabug

I'm getting the above error when attempting to build the Win32 package with GHC 7.6.3 on Windows 8.1 x64. I'm not sure if this is a bug with the Win32 package or with GHC or if this package simply doesn't support 64 bit. So I would appreciate any feed back about why this might be happening.

2.10.0.0 tarball is unbuildable

PS C:\Users\Oleg Grenrus\Documents\postgresql-libpq> cabal build --constraint='Win32 ^>=2.10'
Resolving dependencies...
Build profile: -w ghc-8.8.4 -O1
In order, the following will be built (use -v for more details):
 - Win32-2.10.0.0 (lib) (requires download & build)
 - postgresql-libpq-0.9.4.3 (lib:postgresql-libpq) (configuration changed)
Downloading  Win32-2.10.0.0
Downloaded   Win32-2.10.0.0
Starting     Win32-2.10.0.0 (lib)
Building     Win32-2.10.0.0 (lib)

Failed to build Win32-2.10.0.0.
Build log ( C:\Users\Oleg
Grenrus\AppData\Roaming\cabal\logs\ghc-8.8.4\Win32-2.10.0.0-3884a87f6116e1eb131fdcd63a8c4f0391e40976.log
):
Preprocessing library for Win32-2.10.0.0..
compiling dist\build\System\Win32\NLS_hsc_make.c failed (exit code 1)
rsp file was: "dist\\build\\System\\Win32\\hsc8915.rsp"
command was: C:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.8.4\lib\../mingw/bin\gcc.exe -c dist\build\System\Win32\NLS_hsc_make.c -o dist\build\System\Win32\NLS_hsc_make.o -D__GLASGOW_HASKELL__=808 -Dmingw32_BUILD_OS=1 -Dx86_64_BUILD_ARCH=1 -Dmingw32_HOST_OS=1 -Dx86_64_HOST_ARCH=1 -Iinclude -IC:\tools\msys64\mingw64\include -Idist\build\include -IC:\tools\msys64\mingw64\include -fno-strict-aliasing -Wall -Idist\build\autogen -Idist\build\global-autogen -include dist\build\autogen\cabal_macros.h -IC:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.8.4\lib\bytestring-0.10.10.1\include -IC:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.8.4\lib\base-4.13.0.0\include -IC:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.8.4\lib\integer-gmp-1.0.2.0\include -IC:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.8.4\lib/include -IC:\ProgramData\chocolatey\lib\ghc\tools\ghc-8.8.4/lib/include/
error: NLS.hsc:56:10: fatal error: winnls_compat.h: No such file or directory
compilation terminated.

When I added

install-includes: "winnls_compat.h", "winnt_compat.h"

and made sdist package, that one build fine.

I'm not sure whether these includes should be install-includes or just includes so I won't make a PR.

alignment implementations are wrong for most Storable instances in Win32

There are several Storable instances in Win32, but most of them implement alignment like so (example taken from System.Win32.Mem):

instance Storable MEMORY_BASIC_INFORMATION where
    sizeOf _ = #size MEMORY_BASIC_INFORMATION
    alignment = sizeOf

Defining alignment = sizeOf is usually wrong, and in the case of MEMORY_BASIC_INFORMATION, it's definitely wrong, as this C program shows:

#include <windows.h>
#include <inttypes.h>
#include <stdio.h>

int main(int argc, char **argv) {
    printf("Size: %" PRIu64 ", alignment: %" PRIu64 "\n",
           sizeof(MEMORY_BASIC_INFORMATION),
           __alignof__(MEMORY_BASIC_INFORMATION));

    return 0;
}
$ ./foo.exe
Size: 48, alignment: 8

We should define alignment properly using hsc2hs's #alignment macro, introduced in GHC 8.0. Or, on older versions of GHC, use this hsc2hs macro:

#if __GLASGOW_HASKELL__ < 711
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
#endif

Consolidate CodePage in System.Win32.NLS with the CodePage in base-4.15

Both Win32 and base-4.15 define identical (but distinct) type synonyms named CodePage. I propose that Win32 re-export the CodePage from base when possible.

Current Behavior

As of base-4.15, the GHC.IO.Encoding.CodePage module defines a type synonym named CodePage:

type CodePage = DWORD

As it turns out, the Win32 library also defines an identical (but distinct) type synonym named CodePage in System.Win32.NLS:

type CodePage = UINT

(Note that DWORD = UINT = Word32.) This creates problems for code that tries to use both System.Win32.NLS and GHC.IO.Encoding.CodePage together, as their two CodePage definitions will clash.

Steps to Reproduce (for bugs)

An example of a library that this actually affected in practice in code-page, which stopped building after base-4.15's release. See RyanGlScott/code-page#5. It's possible to work around the issue, but if Win32 simply re-exported CodePage from base, this bug would have never happened in the first place.

Your Environment

  • Version used: GHC 9.0.1 (base-4.15.0.0 and Win32-2.10.0.0)
  • Operating System and version: 64-bit Windows 10

Untie Win32 from bytestring

I am working on refactoring bytestring test suite. It is currently organized as two packages. There is a bytestring package, which reside in a top-level folder, and a bytestring-tests package in tests sub-folder with the following configuration:

test-suite {foo,bar,baz}
  hs-source-dirs:   . ..
  main-is:          {Foo,Bar,Baz}.hs
  other-modules:    Data.ByteString
                    Data.ByteString.Char8
                    Data.ByteString.Internal
                    Data.ByteString.Lazy
                    Data.ByteString.Lazy.Char8
                    Data.ByteString.Lazy.Internal
                    Data.ByteString.Short
                    Data.ByteString.Short.Internal
                    ...many more...
  build-depends:    base, ghc-prim, deepseq, random,
                    tasty, tasty-quickcheck, QuickCheck

So tests do not depend on bytestring package explicitly, but rather just happen to share source files. This is unfortunate for many reasons. For example, each test component recompiles all modules of bytestring anew. Tooling such as HLS cannot figure out which source file belongs to what. But most importantly this way we do not actually test bytestring package, because there are no guarantees that the configuration in bytestring.cabal (GHC flags, C sources, etc.) is the same.

An obvious solution is to abandon the hack with hs-source-dirs: .. and add bytestring as a proper build-depends of bytestring-tests package. This still does not work in a satisfactory manner, because now any change to bytestring causes rebuilding of random, directory, QuickCheck, process, optparse-applicative, tasty, tasty-quickcheck (all of them depend on bytestring transitively) and, as you can imagine, it takes obnoxiously long for any sort of interactive development.

Ideally I would like to eliminate bytestring as a transitive dependency of the test suite. Not only it would enable us to run tests quicker, but also the very reason for having a separate package bytestring-tests would disappear.

This idea proved to be fruitful for Linux and MacOS builds: I patched optparse-applicative and tasty ecosystem so that they no longer depend on bytestring, when compiled with right flags. Unfortunately, there is a nasty complication on Windows. The reason is that several packages (e. g., ansi-terminal) depend on Win32, which depends on bytestring, which makes it a circular dependency.


I was initially writing this to ask about a possibility to make bytestring an optional dependency of Win32, guarding relevant calls by a Cabal flag. But actually I found out that there is only a single spot of Win32, which involves bytestring:

-- | As mapFile, but returns ByteString
mapFileBs :: FilePath -> IO ByteString
mapFileBs p = do
(fp,i) <- mapFile p
return $ fromForeignPtr fp 0 i

Moreover, this function is unused: neither Hackage nor GHC refer to it. The code itself is prone to be broken in future, because it relies on an internal API (there are actually ideas to back ByteString by ByteArray# instead of ForeignPtr).

How do you feel about removing mapFileBs (and bytestring dependency) in the future release of Win32?

Not only this would resolve my problem and facilitate smooth testing of bytestring, but it would genuinely untie two boot packages from one another.

build failure 'INPUT' undeclared

Win32-2.5 (and I think also 2.6) fails to build on a Windows system. This had been previously using Win32-2.4, which built ok. The problem is in the new System.Win32.Automation module.

Failed to install Win32-2.5.4.1
Build log ( C:\Users\jenkins\AppData\Roaming\cabal\logs\Win32-2.5.4.1.log ):
Building Win32-2.5.4.1...
Preprocessing library Win32-2.5.4.1...
Input.hsc: In function 'main':
Input.hsc:73:5: error: 'INPUT' undeclared (first use in this function)
Input.hsc:73:5: note: each undeclared identifier is reported only once for each function it appears in
Input.hsc:74:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:74:5: error: 'struct ' has no member named 'y__'
Input.hsc:77:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:77:5: error: expected ';' before ')' token
Input.hsc:77:5: error: expected statement before ')' token
Input.hsc:78:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:78:5: error: expected ';' before ')' token
Input.hsc:78:5: error: expected statement before ')' token
Input.hsc:80:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:80:5: error: expected ';' before ')' token
Input.hsc:80:5: error: expected statement before ')' token
Input.hsc:81:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:81:5: error: expected ';' before ')' token
Input.hsc:81:5: error: expected statement before ')' token
Input.hsc:83:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:83:5: error: expected ';' before ')' token
Input.hsc:83:5: error: expected statement before ')' token
Input.hsc:84:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:84:5: error: expected ';' before ')' token
Input.hsc:84:5: error: expected statement before ')' token
Input.hsc:87:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:87:5: error: expected ';' before ')' token
Input.hsc:87:5: error: expected statement before ')' token
Input.hsc:90:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:90:5: error: expected ';' before ')' token
Input.hsc:90:5: error: expected statement before ')' token
Input.hsc:92:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:92:5: error: expected ';' before ')' token
Input.hsc:92:5: error: expected statement before ')' token
Input.hsc:93:5: error: expected specifier-qualifier-list before 'INPUT'
Input.hsc:93:5: error: expected ';' before ')' token
Input.hsc:93:5: error: expected statement before ')' token
Input.hsc:105:5: error: 'HARDWAREINPUT' undeclared (first use in this function)
Input.hsc:106:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:106:5: error: 'struct ' has no member named 'y__'
Input.hsc:108:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:108:5: error: expected ';' before ')' token
Input.hsc:108:5: error: expected statement before ')' token
Input.hsc:109:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:109:5: error: expected ';' before ')' token
Input.hsc:109:5: error: expected statement before ')' token
Input.hsc:110:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:110:5: error: expected ';' before ')' token
Input.hsc:110:5: error: expected statement before ')' token
Input.hsc:112:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:112:5: error: expected ';' before ')' token
Input.hsc:112:5: error: expected statement before ')' token
Input.hsc:113:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:113:5: error: expected ';' before ')' token
Input.hsc:113:5: error: expected statement before ')' token
Input.hsc:114:5: error: expected specifier-qualifier-list before 'HARDWAREINPUT'
Input.hsc:114:5: error: expected ';' before ')' token
Input.hsc:114:5: error: expected statement before ')' token
compiling dist\build\System\Win32\Automation\Input_hsc_make.c failed (exit code 1)
command was: c:\haskell\7.10.2-a\mingw\bin\gcc.exe -c dist\build\System\Win32\Automation\Input_hsc_make.c -o dist\build\System\Win32\Automation\Input_hsc_make.o -D__GLASGOW_HASKELL__=710 -Dmingw32_BUILD_OS=1 -Di386_BUILD_ARCH=1 -Dmingw32_HOST_OS=1 -Di386_HOST_ARCH=1 -Iinclude -fno-strict-aliasing -Wall -Idist\build\autogen -include dist\build\autogen\cabal_macros.h -IC:\haskell\7.10.2-a\lib\bytes_6elQVSg5cWdFrvRnfxTUrH\include -IC:\haskell\7.10.2-a\lib\base_GDytRqRVSUX7zckgKqJjgw\include -IC:\haskell\7.10.2-a\lib\integ_2aU3IZNMF9a7mQ0OzsZ0dS\include -IC:\haskell\7.10.2-a\lib/include -IC:\haskell\7.10.2-a/lib/include/

System.Win32 exports `x`

It seems like System.Win32 now exports a few rather common symbols, including x. It will cause quite some inconvenience for such a widely-used module to export such a common name. Was this intentional?

Build failure with GHC-7.8.4 (x86)

https://ci.appveyor.com/project/hvr/paths/builds/29725968/job/q88c02jr7k66i2sp

Edit: cabal seems to use hsc2hc-0.68.3, maybe that's relevant.

On x86-64 version it seems to build fine.

Preprocessing library for Win32-2.8.4.0..
Types.hsc: In function '_hsc2hs_test41':
Types.hsc:217:20: error: storage size of 'test_array' isn't constant
Types.hsc:217:20: warning: unused variable 'test_array'
Types.hsc:217:20: error: storage size of 'test_array' isn't constant
Types.hsc:217:20: warning: unused variable 'test_array'
Types.hsc:217:20: error: storage size of 'test_array' isn't constant
Types.hsc:217:20: warning: unused variable 'test_array'
Types.hsc:217:20: error: storage size of 'test_array' isn't constant
Types.hsc:217:20: warning: unused variable 'test_array'
compilation failed
cabal.exe: Failed to build Win32-2.8.4.0 (which is required by paths-0.2.0.0).
See the build log above for details.
Command exited with code 1

Incorrect usage of PHANDLE type.

In convension of win32 API, PHANDLE means "A pointer to a HANDLE"[1]. However in System/Win32/DebugApi.hsc PHANDLE was wrongly used to represent "process handle". Maybe some more precise tokens such as ProcHANDLE and ThreadHandle can be used to distinguish process handle, thread handle and ordinay handles.

I think the type synonym PHANDLE should be defined as type PHANDLE = Ptr HANDLE in System/Win32/Types.hs and should be available after we import the module System.Win32.Types and then it can be used directly with some win32 functions like CreatePipe.

1: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx

Function to detect if GHC is running in MinTTY

GHC will soon have support for detecting whether it's running in MinTTY (Cygwin/MSYS2/etc.). The code for detecting this looks something like this.

queryCygwinTerminal :: Win32.HANDLE -> IO Bool
queryCygwinTerminal h = do
    fileType <- Win32.getFileType h
    if fileType /= Win32.fILE_TYPE_PIPE
      then pure False
      else do
        fn <- getFileNameByHandle h
        pure (("\\cygwin-" `isPrefixOf` fn || "\\msys-" `isPrefixOf` fn) &&
              "-pty" `isInfixOf` fn &&
              "-master" `isSuffixOf` fn)
  `catch` \ (_ :: IOError) ->
    pure False

getFileNameByHandle :: Win32.HANDLE -> IO String
getFileNameByHandle h = do
  let sizeOfDWORD = sizeOf (undefined :: Win32.DWORD)
  let sizeOfWchar = sizeOf (undefined :: CWchar)
  -- note: implicitly assuming that DWORD has stronger alignment than wchar_t
  let bufSize = sizeOfDWORD + mAX_PATH * sizeOfWchar
  allocaBytes bufSize $ \ buf -> do
    getFileInformationByHandleEx h fileNameInfo buf (fromIntegral bufSize)
    len :: Win32.DWORD <- peek buf
    let len' = fromIntegral len `div` sizeOfWchar
    peekCWStringLen (buf `plusPtr` sizeOfDWORD, min len' mAX_PATH)

getFileInformationByHandleEx
  :: Win32.HANDLE -> CInt -> Ptr a -> Win32.DWORD -> IO ()
getFileInformationByHandleEx h cls buf bufSize = do
  lib <- Win32.getModuleHandle (Just "kernel32.dll")
  ptr <- Win32.getProcAddress lib "GetFileInformationByHandleEx"
  let c_GetFileInformationByHandleEx =
        mk_GetFileInformationByHandleEx (castPtrToFunPtr ptr)
  Win32.failIfFalse_ "getFileInformationByHandleEx"
    (c_GetFileInformationByHandleEx h cls buf bufSize)

type F_GetFileInformationByHandleEx a =
  Win32.HANDLE -> CInt -> Ptr a -> Win32.DWORD -> IO Win32.BOOL

foreign import WINAPI "dynamic"
  mk_GetFileInformationByHandleEx
  :: FunPtr (F_GetFileInformationByHandleEx a)
  -> F_GetFileInformationByHandleEx a

We should add something like this to Win32.

The problem is that GetFileInformationByHandleEx was only introduced in Windows Vista. We should try to have a version that can also support Windows earlier than Vista. @Mistuke tells me this should be possible using NtQueryObject.

trackPopupMenuEx, trackPopupMenu

I get unsafe reentries when trying to use either trackPopupMenuEx or trackPopupMenu. They are fixed when I use a safe imports instead.
Also the Microsoft documentation calls the return value of the API functions a BOOL, but the value is actually needed for identifying which option was clicked when the TPM_RETURNCMD flag is set.
I think the return value should be IO (Maybe MenuID). If they get back a zero they should fail like now, if they get back a positive value but the flag wasn't set they should return Nothing and if the flag was set they should return Just MenuID.

Should I send a pull request?

getMessage/peekMessage fail to detect return errors

Current Behavior

Back in 2018, #119 replaced -1 :: LONG with maxBound :: LONG in the implementation of getMessage and peekMessage. This is not correct since -1 :: LONG is FFFF FFFF, whereas maxBound :: LONG is only 7FFF FFFF. Consequently, error cases are not correctly identified. (LONG = Int32. Note that under the Windows.h definition of getMessage, they return BOOL = int ~= our INT = Int32, but we are saying they return LONG = Int32.)

Steps to Reproduce (for bugs)

  1. Use the same Main.hs file I provided in #142
  2. Test on a version from 2.8.2 on.
  3. Close the window.
  4. Notice the process is stuck in an infinite loop as it perpetually receives an error and never reaches a terminating condition. (On the other hand, I thought the code should have returned FALSE = False and got let out of the loop on another ground.)

Your Environment

  • Version used: bisecting through 2.6.1 (which I wrote the code on) and 51825ad
  • Operating System and version: Windows 10
  • GHC 8.8.3

poke and peek aren't inverses for TIME_ZONE_INFORMATION

module Main where

import Control.Exception (assert)
import Foreign
import System.Win32.Time

main :: IO ()
main = do
    (_, tzi) <- getTimeZoneInformation
    alloca $ \buf -> do
        poke buf tzi
        tzi' <- peek buf
        print tzi
        print tzi'
        assert (tzi == tzi') $ return ()
$ runghc TZI.hs
TIME_ZONE_INFORMATION {tziBias = 300, tziStandardName = "Eastern Standard Time", tziStandardDate = SYSTEMTIME {wYear = 0, wMonth = 11, wDayOfWeek = 0, wDay = 1, wHour = 2, wMinute = 0, wSecond = 0, wMilliseconds = 0}, tziStandardBias = 0, tziDaylightName = "Eastern Daylight Time", tziDaylightDate = SYSTEMTIME {wYear = 0, wMonth = 3, wDayOfWeek = 0, wDay = 2, wHour = 2, wMinute = 0, wSecond = 0, wMilliseconds = 0}, tziDaylightBias = -60}
TIME_ZONE_INFORMATION {tziBias = 300, tziStandardName = "", tziStandardDate = SYSTEMTIME {wYear = 0, wMonth = 11, wDayOfWeek = 0, wDay = 1, wHour = 2, wMinute = 0, wSecond = 0, wMilliseconds = 0}, tziStandardBias = 0, tziDaylightName = "\54232\2564", tziDaylightDate = SYSTEMTIME {wYear = 0, wMonth = 3, wDayOfWeek = 0, wDay = 2, wHour = 2, wMinute = 0, wSecond = 0, wMilliseconds = 0}, tziDaylightBias = -60}
TZI.hs: Assertion failed
CallStack (from HasCallStack):
  assert, called at TZI.hs:15:9 in main:Main

You'll notice that tzi and tzi' are almost the same, but their String values are different. I believe I know what's causing this, so I'll open a PR to fix it.

insertMenuItem bug

The implementation for insertMenuItem does not call pokeFMask. As a result, calls to insertMenuItem always fail.

Compilation failure on 7.6.3

With GHC 7.6.3, the latest version (2.8.1.0) is selected by cabal's solver but fails to build with:

Building library for Win32-2.8.1.0..
GraphicsWin32Window.hsc:2:14:
    Unsupported extension: NegativeLiterals

If you don't want to support GHCs this old (fair enough!) would you remind revising the bound on base to reflect supported versions, so that cabal will select an older version as needed?

See https://ci.appveyor.com/project/adamgundry/acid-state/build/job/b79whx1g7h85sgop for a build log.

setWindowClosure/createWindowEx leaks memory

setWindowClosure leaks memory. It creates a function pointer using "wrapper", but then it seems to forget about it. Every function pointer created with "wrapper" must be freed, since the runtime has to keep a reference to everything which is closed over in order for the code to run whenever outsiders call.

I believe a viable solution is to change defWindowProc to something like:

defWindowProc :: Maybe HWND -> WindowMessage -> WPARAM -> LPARAM -> IO LRESULT
defWindowProc mb_wnd msg w l = do
  when (msg == wM_NCDESTROY) (maybe (return ()) freeWindowProc mb_wnd)
  c_DefWindowProc (maybePtr mb_wnd) msg w l 

freeWindowProc :: HWND -> IO ()
freeWindowProc hwnd = do
   fp <- c_GetWindowLongPtr hwnd GWLP_USERDATA
   unless (fp == nullPtr) $ 
      freeHaskellFunPtr $ castPtrToFunPtr . intPtrToPtr . fromIntegral $ fp

We aren't strictly guaranteed the user data will still be what we want but I suppose genericWndProc will have broken by then already. According to Raymond Chen https://devblogs.microsoft.com/oldnewthing/20050726-00/?p=34803 WM_NCDESTROY is the last message a window receives before it dies.

I have attached a program which demonstrates the difference Main.hs. You can track the memory in the Task Manager. The program creates a series of windows. Each window closure holds a reference to big pack of data which it prints out when it gets WM_DESTROY. A weak reference is also created and returned. Once the last window has been output, the weak references are inspected. If you're bored or discover you are using too much memory and want to abort early - Ctrl-C doesn't effectively quit the process. Instead, minimise the window. The WM_SIZE handler will immediately terminate the process if the window is minimised.

Using Graphics.Win32.defWindowProc in the otherwise case of mainWndProc, each weak reference contains the strings and the memory increases; for me it usually ends up in the range 60-120 MB. With my proposed replacement, Main.defWindowProc, in the otherwise case of mainWndProc, only the final weak reference contains a string at the end - the rest print out "all's well" to indicate deRefWeak returned Nothing - and the memory stays low, alternating between about 10-13 MB each iteration after the first.

It's way too late but I can probably throw together a pr tomorrow.

Program hangs when I use trackPopupMenuEx

Current Behavior

Program hangs with trackPopupMenu(Ex).

Steps to Reproduce (for bugs)

My code is based on https://github.com/haskell/win32/blob/v2.6.1.0/examples/hello.lhs, except I do not do painting.

wndProc ::
       Graphics.Win32.HWND
    -> Graphics.Win32.WindowMessage
    -> Graphics.Win32.WPARAM
    -> Graphics.Win32.LPARAM
    -> IO Graphics.Win32.LRESULT
wndProc hwnd wmsg wParam lParam
    | wmsg == Graphics.Win32.wM_COMMAND && wParam == fromIntegral iDM_QUIT = do
        Graphics.Win32.destroyWindow hwnd
        return 0
    | wmsg == 0x007B = do
        showContextMenu hwnd
        return 0
    | wmsg == Graphics.Win32.wM_DESTROY = do
        Graphics.Win32.sendMessage hwnd Graphics.Win32.wM_QUIT 1 0
        return 0
    | otherwise = do
        Graphics.Win32.defWindowProc (Just hwnd) wmsg wParam lParam

showContextMenu :: Graphics.Win32.HWND -> IO ()
showContextMenu hwnd = do
    hMenu <- createPopupMenu
    pt <- Graphics.Win32.Misc.getCursorPos
    appendMenu hMenu mFT_STRING iDM_Exit (Just "&Exit")
    trackPopupMenuEx hMenu tPM_RIGHTBUTTON (fromIntegral $ fst pt) (fromIntegral $ snd pt) hwnd Nothing
    destroyMenu hMenu

A pop-up menu appears, but the program ends up freezing after that. I've tried to remove WM_COMMAND branch from wndProc, but this does not help.

Your Environment

  • I'm using stack, tried resolvers lts-6.2, lts-16.8
  • Versions used: 2.3.1.1, 2.6.1.0
  • Operating System and version: Windows 10 Home

Windows API date/time format pictures to `formatTime` format string

Further to my recent NLS-related pull requests, I have two utility functions that translate the date or time format pictures used by the Windows API (see here and here) to the nearest equivalent format strings used by Data.Time.Format.formatTime of the time package.

For example (for locale nl-NL), Windows format picture dddd d MMMM yyyy is translated to format string %A %-e %B %Y.

Currently, they are implemented in a fork of this repository. If this package is an appropriate place for them, I'll propose a pull request. My thinking was that a 'bridge' between the Windows API and the time package could usefully be included in this package, as time may be more Unix-centric.

They are:

-- | Translate from a Windows API day, month, year, and era format picture to
-- the closest corresponding format string used by
-- 'Data.Time.Format.formatTime'.
fromDateFormatPicture :: String -> Maybe String

-- | Translate from a Windows API hour, minute, and second format picture to
-- the closest corresponding format string used by
-- 'Data.Time.Format.formatTime'.
fromTimeFormatPicture :: String -> Maybe String

Please add getUserName

As far as I can tell, there is no binding to getUserName. Something like this would be nice: http://hpaste.org/41521#a75828

It seems that getEnv "USERNAME" work in some cases, but I think it would still be nice to have a binding to this function.

Thanks!

Fix cross-compilation of HWND_BOTTOM and friends (those are defined as pointers in windows.h)

A fallout from #87

In file Graphics/Win32/GDI/Types.hsc the following code fails to cross-compile:

 #{enum HWND, castUINTPtrToPtr
  , hWND_BOTTOM    = (UINT_PTR)HWND_BOTTOM
  , hWND_NOTOPMOST = (UINT_PTR)HWND_NOTOPMOST
  , hWND_TOP       = (UINT_PTR)HWND_TOP
  , hWND_TOPMOST   = (UINT_PTR)HWND_TOPMOST
  }
$ cabal configure             --with-ghc=$HOME/dev/git/ghc-w32/inplace/bin/ghc-stage1             --hsc2hs-options='--cross-safe --cross-compile'
$ cabal build -v

/home/slyfox/dev/git/ghc-w32/inplace/bin/hsc2hs '--cc=/usr/bin/i686-w64-mingw32-gcc' '--ld=/usr/bin/i686-w64-mingw32-gcc' '--cflag=-fno-stack-protector' '--lflag=-fno-stack-protector' '--cflag=-D__GLASGOW_HASKELL__=803' '--cflag=-Dlinux_BUILD_OS=1' '--cflag=-Dx86_64_BUILD_ARCH=1' '--cflag=-Dmingw32_HOST_OS=1' '--cflag=-Di386_HOST_ARCH=1' '--cflag=-Iinclude' '--cflag=-fno-strict-aliasing' '--cflag=-Wall' '--cflag=-Idist/build/autogen' '--cflag=-include' '--cflag=dist/build/autogen/cabal_macros.h' '--lflag=-luser32' '--lflag=-lgdi32' '--lflag=-lwinmm' '--lflag=-ladvapi32' '--lflag=-lshell32' '--lflag=-lshfolder' '--lflag=-lshlwapi' '--lflag=-lmsimg32' '--lflag=-limm32' '--cflag=-I/home/slyfox/dev/git/ghc-w32/libraries/bytestring/include' '--cflag=-I/home/slyfox/dev/git/ghc-w32/libraries/base/include' '--cflag=-I/home/slyfox/dev/git/ghc-w32/libraries/integer-gmp/include' '--cflag=-I/home/slyfox/dev/git/ghc-w32/rts/dist/build' '--cflag=-I/home/slyfox/dev/git/ghc-w32/includes' '--cflag=-I/home/slyfox/dev/git/ghc-w32/includes/dist-derivedconstants/header' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/filepath/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/filepath/dist-install/build' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/bytestring/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/bytestring/dist-install/build' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/deepseq/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/deepseq/dist-install/build' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/array/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/array/dist-install/build' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/base/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/base/dist-install/build' '--lflag=-lwsock32' '--lflag=-luser32' '--lflag=-lshell32' '--lflag=-lmsvcrt' '--lflag=-lmingw32' '--lflag=-lmingwex' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/integer-gmp/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/integer-gmp/dist-install/build' '--lflag=-lgmp' '--lflag=-L/home/slyfox/dev/git/ghc-w32/libraries/ghc-prim/dist-install/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/libraries/ghc-prim/dist-install/build' '--lflag=-luser32' '--lflag=-lmingw32' '--lflag=-lmingwex' '--lflag=-L/home/slyfox/dev/git/ghc-w32/rts/dist/build' '--lflag=-Wl,-R,/home/slyfox/dev/git/ghc-w32/rts/dist/build' '--lflag=-lm' '--lflag=-lwsock32' '--lflag=-lgdi32' '--lflag=-lwinmm' '--lflag=-lmingwex' -o dist/build/Graphics/Win32/GDI/Types.hs Graphics/Win32/GDI/Types.hsc --cross-safe --cross-compile
Types.hsc: In function '_hsc2hs_test44':
Types.hsc:219:20: error: storage size of 'test_array' isn't constant
Types.hsc:219:20: warning: unused variable 'test_array' [-Wunused-variable]
Types.hsc:219:20: error: storage size of 'test_array' isn't constant
Types.hsc:219:20: warning: unused variable 'test_array' [-Wunused-variable]
Types.hsc:219:20: error: storage size of 'test_array' isn't constant
Types.hsc:219:20: warning: unused variable 'test_array' [-Wunused-variable]
Types.hsc:219:20: error: storage size of 'test_array' isn't constant
Types.hsc:219:20: warning: unused variable 'test_array' [-Wunused-variable]

The problem here is in HWND_BOTTOM definition in <windows.h>:

typedef void *HWND;
...
#define HWND_BOTTOM ((HWND)1)

There is no easy way to detect the pointer value at compile-time (without running the code on target).

Locallly i'm working it around by breaking API:

+#if !defined(SKIP_NON_CROSSCOMPILABLE)
 #{enum HWND, castUINTPtrToPtr
  , hWND_BOTTOM    = (UINT_PTR)HWND_BOTTOM
  , hWND_NOTOPMOST = (UINT_PTR)HWND_NOTOPMOST
  , hWND_TOP       = (UINT_PTR)HWND_TOP
  , hWND_TOPMOST   = (UINT_PTR)HWND_TOPMOST
  }
+#endif

One of workarounds would be to encode raw values as they appear in headers:

 #{enum HWND, castUINTPtrToPtr
  , hWND_BOTTOM    = 1
  , hWND_NOTOPMOST = (some_cast)(-2)
  , hWND_TOP       = 0
  , hWND_TOPMOST   = (some_cast)(-1)
  }

There a few of pointer-looking enums in win32 package:

  • HWND_BOTTOM
  • IDC_ARROW
  • IDI_APPLICATION
  • RT_ACCELERATOR
  • HWND_BROADCAST
  • HKEY_CLASSES_ROOT

installation fails because PostMessage_hsc_make.exe is flagged as malware

Current Behavior

Steps to Reproduce (for bugs)

  1. install kaspersky total security
  2. run 'stack install Win32'
  3. Kaspersky blocks the execution of PostMessage_hsc_make.exe
  4. build fails with
--  While building custom Setup.hs for package Win32-2.5.4.1 using:
      C:\sr\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_2.2.0.1_ghc-8.4.4.exe --builddir=.stack-work\dist\7d103d30 build --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
    Process exited with code: ExitFailure 1
    Logs have been written to: C:\Users\pti\playpen\spago\.stack-work\logs\Win32-2.5.4.1.log

    Configuring Win32-2.5.4.1...
    Preprocessing library for Win32-2.5.4.1..
    hsc2hs.exe: .stack-work\dist\7d103d30\build\Graphics\Win32\Window\PostMessage_hsc_make.exe: runProcess: permission denied (Permission denied)

this is the log of kaspersky

trojan.txt

Your Environment

  • Version used:
  • Operating System and version: Windows 10 Pro

CreateProcess does not exist?

Hello,
I'm working on a small debugger for windows which means I need to pass creation flags that I cannot pass with the process library. I found it strange that there is no binding for that function in Win32. Even more, as there is DebugApi which seems to me that it can only be used on an already started process.
Yotam

Incorrect types break 64 bit

The following types in System.Win32.Types are the wrong size on 64 bit Windows:

type UINT_PTR = Word
type ATOM          = UINT
type WPARAM        = UINT
type LPARAM        = LONG
type LRESULT       = LONG
type SIZE_T = DWORD

Propose adding LONG_PTR:

type LONG_PTR = CIntPtr

and changing to:

type UINT_PTR = CUIntPtr
type ATOM          = WORD
type WPARAM        = UINT_PTR
type LPARAM        = LONG_PTR
type LRESULT       = LONG_PTR
type SIZE_T = CSize

add terminateProcess

There currently seems to be no way to use this library to terminate an arbitrary process by ProcessID.

Some code that has worked for me to do this in the past is this:

import System.Win32.Process
import Control.Exception (bracket)
import Control.Monad

terminateProcess :: ProcessID -> IO ()
terminateProcess p = bracket 
        (openProcess pROCESS_TERMINATE False p)
        (void . c_closeProcess)
       (\h -> void $ c_TerminateProcess h 1)
 
 foreign import ccall unsafe "windows.h TerminateProcess"
        c_TerminateProcess :: ProcessHandle -> Int -> IO Int

The scope of this package?

I'm curious how it is decided what parts of the Win32 api make it into this package or not. On the one hand, there's decent coverage of a bunch of UI areas (e.g. GDI) but certain things are strangely absent (e.g. radio buttons can be created, but not Rebars). On the other hand, certain lower-level things are missing (I just found that AllocConsole was missing).

I'm guessing we're in one of two situations:

  • Since this is a boot package, only some curated "core" of Win32 functionality is included to keep library size manageable.
  • Since the Win32 API is massive, things have been added piecemeal as they're needed.

In the latter case, I'd be happy to help add some missing parts! In the former case, I'm curious how this subset was chosen.

Hackage not up to date

Hackage win32 still showing older repo, is this normal behavior? Is it supposed to update automatically with changes to github repo?

Fishy instance for `Storable LASTINPUTINFO`

I think the definition of alignment for the instance is problematic as it might not be a power of two.

Current Behavior

Currently this is defined as:

instance Storable LASTINPUTINFO where
    sizeOf = const (#size LASTINPUTINFO)
    alignment = sizeOf
    ...

So alignment might end up being 123. It's fair to assume that alignment should be a power of two here.
This didn't cause issues in the past. But some functions in base on GHC HEAD now actually check alignment
and will fail with an error if the alignment isn't a power of two.

Another instance of this kind already caused issues for GHC (https://gitlab.haskell.org/ghc/ghc/-/issues/19392). So I looked for other occurences and found this instance.


It could be fixed with a utility function like the one below which GHC should be able to evaluate at compile time.

{-# INLINE alignmentFromSize #-}
-- Return the next largest power of two if the argument isn't one already.
alignmentFromSize :: Int -> Int
alignmentFromSize size
    | isPowerOfTwo size = size
    | otherwise = alignment
    where
        isPowerOfTwo :: (Bits i, Integral i) => i -> Bool
        isPowerOfTwo x = x .&. (x-1) == 0
        -- Rounding down
        logBase2 x = finiteBitSize x - 1 - countLeadingZeros x
        -- Get the next power of two
        alignment = 2^(logBase2 size + 1)

Then the instance can define alignment as alignment = alignmentFromSize . sizeOf

Missing (or bad) header file: HsWin32.h

Hi, when I try cabal install I get this error:

Configuring Win32-2.3.1.0...
cabal: Missing dependencies on foreign libraries:
* Missing (or bad) header file: HsWin32.h
* Missing C libraries: user32, gdi32, winmm, advapi32, shell32, shfolder
This problem can usually be solved by installing the system packages that
provide these libraries (you may need the "-dev" versions). If the libraries
are already installed but in a non-standard location then you can use the
flags --extra-include-dirs= and --extra-lib-dirs= to specify where they are.
If the header file does exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.
Failed to install Win32-2.3.1.0
cabal: Error: some packages failed to install:
Win32-2.3.1.0 failed during the configure step. The exception was:
ExitFailure 1

So I try cabal install --extra-include-dirs=~/win32/include --extra-lib-dirs=/usr/i686-w64-mingw32/lib, but it gives the same error.

I'm trying to install this because of this: https://ghc.haskell.org/trac/ghc/ticket/10070

Issues with using `System.Win32.Registry`

I'm poking around with registry things at the moment and have come across a few things:

  1. The provided regQueryValue function doesn't match up with the RegQueryValue API method. I suppose you could guess that something is odd because it always returns a String, when the registry value may be of another type, but it does plenty of other stuff underneath. You can only find out what it actually does by reading the source and the comment there (although the comment itself appears to be incorrect, as it says "[RegQueryValue] just allows you to get at the default values of keys", which doesn't match up with what MSDN says).
  2. The function that actually matches RegQueryValue is called regQueryValueKey - again there is no indication to use this in the haddocks.
  3. I think the function that I actually want is RegGetValue, which isn't implemented. There is a comment thats point out its absence - is there a reason it's not there, or could it be added?
  4. I wonder if it might be worth providing convenience functions to get at the different REG_TYPEs that you can get. For example, the could be a function that looks up a value of REG_BINARY type and decodes it into the Storable object of choice; I have written a function that looks like that with type getStorableRegValue :: forall a. Storable a => HKEY -> String -> IO a. It might be worth providing others as well, particularly for string types which involves a little bit of fiddling around.

It would be a breaking change to make regQueryValue do the right thing, and the extra helper functions maybe stray away from the Win32 package's guideline of just wrapping the Win32 API, but I think it would all be helpful so wanted to see what you thought of it.

Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.