Преглед изворни кода

windows: allow Windows-style printf debugging via MessageBox

I realize that at this time, x/sys/windows is most certainly not aiming
to be some sort of UI library or anything remotely close to that.
However, MessageBox is sort of the one universal Windows API that's used
even for console programs. It's *the* classic debugging helper. It's
even pretty customary for console programs to display their usage
message in a message box rather than stdout. I realize this might be
somewhat disturbing to consider if you're in the blissful Unix utopia,
but on Windows, this is just sort of how things roll. Easy access to
MessageBox() is important.

Change-Id: I16183b69e8a27a5ddaf73d1d4e106bb7b201a6f0
Reviewed-on: https://go-review.googlesource.com/c/sys/+/178899
Run-TryBot: Jason Donenfeld <Jason@zx2c4.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Jason A. Donenfeld пре 6 година
родитељ
комит
ea4c425e90
3 измењених фајлова са 51 додато и 0 уклоњено
  1. 1 0
      windows/syscall_windows.go
  2. 35 0
      windows/types_windows.go
  3. 15 0
      windows/zsyscall_windows.go

+ 1 - 0
windows/syscall_windows.go

@@ -278,6 +278,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
 //sys	QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) [failretval==0] = QueryDosDeviceW
 //sys	QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) [failretval==0] = QueryDosDeviceW
 //sys	SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW
 //sys	SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) = SetVolumeLabelW
 //sys	SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW
 //sys	SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) = SetVolumeMountPointW
+//sys	MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW
 
 
 // syscall interface implementation for other packages
 // syscall interface implementation for other packages
 
 

+ 35 - 0
windows/types_windows.go

@@ -1298,6 +1298,41 @@ const (
 	ComputerNameMax                       = 8
 	ComputerNameMax                       = 8
 )
 )
 
 
+// For MessageBox()
+const (
+	MB_OK                   = 0x00000000
+	MB_OKCANCEL             = 0x00000001
+	MB_ABORTRETRYIGNORE     = 0x00000002
+	MB_YESNOCANCEL          = 0x00000003
+	MB_YESNO                = 0x00000004
+	MB_RETRYCANCEL          = 0x00000005
+	MB_CANCELTRYCONTINUE    = 0x00000006
+	MB_ICONHAND             = 0x00000010
+	MB_ICONQUESTION         = 0x00000020
+	MB_ICONEXCLAMATION      = 0x00000030
+	MB_ICONASTERISK         = 0x00000040
+	MB_USERICON             = 0x00000080
+	MB_ICONWARNING          = MB_ICONEXCLAMATION
+	MB_ICONERROR            = MB_ICONHAND
+	MB_ICONINFORMATION      = MB_ICONASTERISK
+	MB_ICONSTOP             = MB_ICONHAND
+	MB_DEFBUTTON1           = 0x00000000
+	MB_DEFBUTTON2           = 0x00000100
+	MB_DEFBUTTON3           = 0x00000200
+	MB_DEFBUTTON4           = 0x00000300
+	MB_APPLMODAL            = 0x00000000
+	MB_SYSTEMMODAL          = 0x00001000
+	MB_TASKMODAL            = 0x00002000
+	MB_HELP                 = 0x00004000
+	MB_NOFOCUS              = 0x00008000
+	MB_SETFOREGROUND        = 0x00010000
+	MB_DEFAULT_DESKTOP_ONLY = 0x00020000
+	MB_TOPMOST              = 0x00040000
+	MB_RIGHT                = 0x00080000
+	MB_RTLREADING           = 0x00100000
+	MB_SERVICE_NOTIFICATION = 0x00200000
+)
+
 const (
 const (
 	MOVEFILE_REPLACE_EXISTING      = 0x1
 	MOVEFILE_REPLACE_EXISTING      = 0x1
 	MOVEFILE_COPY_ALLOWED          = 0x2
 	MOVEFILE_COPY_ALLOWED          = 0x2

+ 15 - 0
windows/zsyscall_windows.go

@@ -41,6 +41,7 @@ var (
 	moduserenv  = NewLazySystemDLL("userenv.dll")
 	moduserenv  = NewLazySystemDLL("userenv.dll")
 	modmswsock  = NewLazySystemDLL("mswsock.dll")
 	modmswsock  = NewLazySystemDLL("mswsock.dll")
 	modcrypt32  = NewLazySystemDLL("crypt32.dll")
 	modcrypt32  = NewLazySystemDLL("crypt32.dll")
+	moduser32   = NewLazySystemDLL("user32.dll")
 	modws2_32   = NewLazySystemDLL("ws2_32.dll")
 	modws2_32   = NewLazySystemDLL("ws2_32.dll")
 	moddnsapi   = NewLazySystemDLL("dnsapi.dll")
 	moddnsapi   = NewLazySystemDLL("dnsapi.dll")
 	modiphlpapi = NewLazySystemDLL("iphlpapi.dll")
 	modiphlpapi = NewLazySystemDLL("iphlpapi.dll")
@@ -213,6 +214,7 @@ var (
 	procQueryDosDeviceW                    = modkernel32.NewProc("QueryDosDeviceW")
 	procQueryDosDeviceW                    = modkernel32.NewProc("QueryDosDeviceW")
 	procSetVolumeLabelW                    = modkernel32.NewProc("SetVolumeLabelW")
 	procSetVolumeLabelW                    = modkernel32.NewProc("SetVolumeLabelW")
 	procSetVolumeMountPointW               = modkernel32.NewProc("SetVolumeMountPointW")
 	procSetVolumeMountPointW               = modkernel32.NewProc("SetVolumeMountPointW")
+	procMessageBoxW                        = moduser32.NewProc("MessageBoxW")
 	procWSAStartup                         = modws2_32.NewProc("WSAStartup")
 	procWSAStartup                         = modws2_32.NewProc("WSAStartup")
 	procWSACleanup                         = modws2_32.NewProc("WSACleanup")
 	procWSACleanup                         = modws2_32.NewProc("WSACleanup")
 	procWSAIoctl                           = modws2_32.NewProc("WSAIoctl")
 	procWSAIoctl                           = modws2_32.NewProc("WSAIoctl")
@@ -2316,6 +2318,19 @@ func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err erro
 	return
 	return
 }
 }
 
 
+func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) {
+	r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0)
+	ret = int32(r0)
+	if ret == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
 func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
 func WSAStartup(verreq uint32, data *WSAData) (sockerr error) {
 	r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
 	r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
 	if r0 != 0 {
 	if r0 != 0 {