haskell / win32 Goto Github PK
View Code? Open in Web Editor NEWHaskell support for the Win32 API
Home Page: http://hackage.haskell.org/package/Win32
License: Other
Haskell support for the Win32 API
Home Page: http://hackage.haskell.org/package/Win32
License: Other
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
.
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
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
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?
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
:
win32/System/Win32/FileMapping.hsc
Lines 56 to 60 in 6775f8c
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.
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?
I've been wanting raw input directly from windows, but I can't find any of the bindings explained here: https://docs.microsoft.com/en-nz/windows/desktop/inputdev/raw-input
Program hangs with trackPopupMenu(Ex).
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.
There's a typo in the Process module:
win32/System/Win32/Process.hsc
Line 57 in 6a4e3b0
-- 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
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 :)
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:
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.
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.
I think the definition of alignment for the instance is problematic as it might not be a power of two.
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
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
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.
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
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
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
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
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.
I'm following this tutorial for making a button, and I'm up to this part:
(HINSTANCE)GetWindowLong(m_hwnd, GWL_HINSTANCE)
What should I call from this library's API to achieve the same effect?
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.
Hackage win32 still showing older repo, is this normal behavior? Is it supposed to update automatically with changes to github repo?
Going off the official docs, if I want to watch a directory for changes (and respond to them), I need a wait function. However, I couldn't find any equivalents to (for example) RegisterWaitForSingleObject
, which I assume is what I would need. Am I missing something, or is there another way to do this using this library?
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.
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.
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
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
.
https://msdn.microsoft.com/en-us/library/windows/desktop/gg258116%28v=vs.85%29.aspx
This constants can be used as dwDesiredAccess
parameter in CreateFile routine for open file in Append mode, for example.
The 'OVERLAPPED' 'Storable' instance should check if the `ovl_hEvent' pointer is not null, otherwise it will result in an address violation error:
https://hackage.haskell.org/package/Win32-2.8.5.0/docs/src/System.Win32.File.html#line-650
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
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
.)
FALSE
= False
and got let out of the loop on another ground.)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.
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
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/
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.
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
:
Line 72 in b297380
(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.
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.
base-4.15.0.0
and Win32-2.10.0.0
)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!
The implementation for insertMenuItem does not call pokeFMask. As a result, calls to insertMenuItem always fail.
GHC's ghc-7.10.1-release
tag gitlinks to Win32's 3b573ee commit, so that commit ought to be tagged as 2.3.1.0
or v2.3.1.0
In writing cross-platform Haskell, I have a Handle but need to convert it to a HANDLE for use with System.Win32.File.
There is a private implementation in ansi-terminal.
GHC 7.6.x was released with Win32-2.3.0.0
, which according to http://git.haskell.org tags should correspond to e13098a
however, that release was never uploaded to Hackage
-- not an issue, please close it
I'm poking around with registry things at the moment and have come across a few things:
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).RegQueryValue
is called regQueryValueKey
- again there is no indication to use this in the haddocks.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?REG_TYPE
s 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!
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
cabal-install 3.4.0.0, GHC-9.0.1, Win32-2.10.0.0, Windows 10
In previous times, win32 was available on stackage. The last version available was version 2.5.4.1. After LTS 11.7, win32 is no longer available.
To me, it is unclear if this is on purpose. Maybe something is broken.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.