# 3. Calling MessageBox winAPI from GO

*Windows APIs, or Application Programming Interfaces, are sets of functions, procedures, and protocols provided by the Microsoft Windows operating system to allow software applications to interact with the system and its underlying components.*

A full list of (documented) windows APIs can be found on Microsoft's [website](https://learn.microsoft.com/en-us/windows/win32/apiindex/windows-api-list).&#x20;

For this example we will call the [MessageBox ](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox)API. Microsoft provides the Syntax to call the API from C++.&#x20;

```
int MessageBox(
  [in, optional] HWND    hWnd,
  [in, optional] LPCTSTR lpText,
  [in, optional] LPCTSTR lpCaption,
  [in]           UINT    uType
);
```

There are two packages that will help us call Windows APIs from GO.  Let's explore both ways.&#x20;

## [Windows Package](https://pkg.go.dev/golang.org/x/sys/windows)

The Windows package is the easiest way of calling windows APIs. It provides a Go interface to low level windows APIs.&#x20;

#### PROS:

* Easy to use
* No need to translate between C and GO data types
* IntelliSense will show the arguments needed in the IDE when the package is imported

#### CONS:

* Not every Windows API is included in this package

As mentioned above when the package is imported we will have syntax recommendations straight in the IDE. It shows parameter data types required and any potential errors. Also the return values are shown on the far right. (ret int32, err error)

<figure><img src="https://1525675160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1BtmYYGIbNqDCOEq0YOj%2Fuploads%2F59Edwew90uxgH05lyhUN%2Fimage.png?alt=media&#x26;token=cafd9e0b-4971-4ae0-9a64-4b2036ae88db" alt=""><figcaption><p>IntelliSense recommendation</p></figcaption></figure>

```go
package main

import (
	"golang.org/x/sys/windows"
)

func main() {

	hWnd := uintptr(0)
	windows.MessageBox(
		windows.HWND(hWnd), 		         	  // [in, optional] HWND    hWnd,
		windows.StringToUTF16Ptr("Used Windows Package"), // [in, optional] LPCTSTR lpText,
		windows.StringToUTF16Ptr("MessageBox 1/2"),       // [in, optional] LPCTSTR lpCaption,
		windows.MB_OK) 				          // [in] UINT    uType

}

```

## [Syscall Package](https://pkg.go.dev/syscall)

The syscall package is harder to use but more powerful

#### PROS:

* Call any function from any DLL

#### CONS:&#x20;

* No IntelliSense&#x20;
* Manually convert Windows to GO data types

The following Table from the book "Black Hat Go: Go Programming For Hackers" (Highly recommended btw) helps with the translation of datatypes

| Windows Data Type | Go Data Type |
| ----------------- | ------------ |
| BOOLEAN           | byte         |
| BOOL              | int32        |
| BYTE              | byte         |
| DWORD             | uint32       |
| DWORD32           | uint32       |
| DWORD64           | uint32       |
| WORD              | uint16       |
| HANDLE            | uintptr      |
| LPVOID            | uintptr      |
| SIZE\_T           | uintptr      |
| LPCVOID           | uintptr      |
| HMODULE           | uintptr      |
| LPCSTR            | uintptr      |
| LPDWORD           | uintptr      |

Having All the information we need we can proceed writing the code for our messagebox. From the MessageBox [reference page](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox#requirements) we can see that function MessageBox is exported in the User32.dll.&#x20;

<figure><img src="https://1525675160-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1BtmYYGIbNqDCOEq0YOj%2Fuploads%2FJ6iUCvTBS2Bin7p5jbsA%2Fimage.png?alt=media&#x26;token=f54823a0-99f6-4c9f-871c-7a8ed9e2a882" alt=""><figcaption><p><a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox#requirements">MessageBox Requirements</a></p></figcaption></figure>

We should first import the dll and get the API address using the following code&#x20;

<pre class="language-go"><code class="lang-go">user32dll := syscall.NewLazyDLL("User32.dll")
<strong>procMsgBox := user32dll.NewProc("MessageBoxW")
</strong></code></pre>

We can then get all our parameters declared before passing them to the function

```go
hWnd = uintptr(0)
lpText, _ := syscall.UTF16PtrFromString("Used Syscall Package")
lpCaption, _:= syscall.UTF16PtrFromString("MessageBox 2/2")
uType := uint(0)
```

And finally we can call the function&#x20;

```go
procMsgBox.Call(
		hWnd, 
		uintptr(unsafe.Pointer(lpText)), 
		uintptr(unsafe.Pointer(lpCaption)), 
		uintptr(uType))
```

### Complete Code:

```go
package main

import (
	"log"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
)

func main() {
	// windows package
	hWnd := uintptr(0)
	windows.MessageBox(
		windows.HWND(hWnd), // [in, optional] HWND    hWnd,
		windows.StringToUTF16Ptr("Used Windows Package"), // [in, optional] LPCTSTR lpText,
		windows.StringToUTF16Ptr("MessageBox 1/2"),       // [in, optional] LPCTSTR lpCaption,
		windows.MB_OK) // [in] UINT    uType

	// syscall package
	user32dll := syscall.NewLazyDLL("User32.dll")
	procMsgBox := user32dll.NewProc("MessageBoxW")

	hWnd = uintptr(0)
	lpText, err := syscall.UTF16PtrFromString("Used Syscall Package")
	if err != nil {
		log.Fatalln("lpText UTF16PtrFromString Failed")
	}
	lpCaption, err := syscall.UTF16PtrFromString("MessageBox 2/2")
	if err != nil {
		log.Fatalln("lpCaption UTF16PtrFromString Failed")
	}
	uType := uint(0)

	procMsgBox.Call(
		hWnd, 
		uintptr(unsafe.Pointer(lpText)), 
		uintptr(unsafe.Pointer(lpCaption)), 
		uintptr(uType))
}

```
