summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/comctl32_windows.c63
-rw-r--r--redo/comctl32_windows.go70
-rw-r--r--redo/winapi_windows.h7
3 files changed, 76 insertions, 64 deletions
diff --git a/redo/comctl32_windows.c b/redo/comctl32_windows.c
new file mode 100644
index 0000000..d621d2a
--- /dev/null
+++ b/redo/comctl32_windows.c
@@ -0,0 +1,63 @@
+/* 17 july 2014 */
+
+#include "winapi_windows.h"
+
+static ULONG_PTR comctlManifestCookie;
+static HMODULE comctl32;
+
+DWORD initCommonControls(LPCWSTR manifest, char **errmsg)
+{
+ ACTCTX actctx;
+ HANDLE ac;
+ INITCOMMONCONTROLSEX icc;
+ FARPROC f;
+ /* TODO does this take WINAPI? */
+ BOOL (*WINAPI ficc)(const LPINITCOMMONCONTROLSEX);
+
+ ZeroMemory(&actctx, sizeof (ACTCTX));
+ actctx.cbSize = sizeof (ACTCTX);
+ actctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT;
+ actctx.lpSource = manifest;
+ ac = CreateActCtx(&actctx);
+ if (ac == INVALID_HANDLE_VALUE) {
+ *errmsg = "error creating activation context for synthesized manifest file";
+ return GetLastError();
+ }
+ if (ActivateActCtx(ac, &comctlManifestCookie) == FALSE) {
+ *errmsg = "error activating activation context for synthesized manifest file";
+ return GetLastError();
+ }
+
+ ZeroMemory(&icc, sizeof (INITCOMMONCONTROLSEX));
+ icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
+ icc.dwICC = ICC_PROGRESS_CLASS;
+
+ comctl32 = LoadLibraryW(L"comctl32.dll");
+ if (comctl32 == NULL) {
+ *errmsg = "error loading comctl32.dll";
+ return GetLastError();
+ }
+
+ /* GetProcAddress() only takes a multibyte string */
+#define LOAD(fn) f = GetModuleHandle(comctl32, fn); \
+ if (f == NULL) { \
+ *errmsg = "error loading " fn "()"; \
+ return GetLastError(); \
+ }
+
+ LOAD("InitCommonControlsEx");
+ ficc = (BOOL (*WINAPI)(const LPINITCOMMONCONTROLSEX)) f;
+ LOAD("SetWindowSubclass");
+ fv_SetWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR)) f;
+ LOAD("RemoveWindowSubclass");
+ fv_RemoveWindowSubclass = (BOOL (*WINAPI)(HWND, SUBCLASSPROC, UINT_PTR)) f;
+ LOAD("DefSubclassProc");
+ fv_DefSubclassProc = (LRESULT (*WINAPI)(HWND, UINT, WPARAM, LPARAM)) f;
+
+ if ((*ficc)(&icc) == FALSE) {
+ *errmsg = "error initializing Common Controls (comctl32.dll)";
+ return GetLastError();
+ }
+
+ return 0;
+}
diff --git a/redo/comctl32_windows.go b/redo/comctl32_windows.go
index 282d721..a28da69 100644
--- a/redo/comctl32_windows.go
+++ b/redo/comctl32_windows.go
@@ -11,10 +11,6 @@ import (
// pretty much every constant here except _WM_USER is from commctrl.h, except where noted
-var (
- comctlManifestCookie t_ULONG_PTR
-)
-
/*
Windows requires a manifest file to enable Common Controls version 6.
The only way to not require an external manifest is to synthesize the manifest ourselves.
@@ -22,8 +18,9 @@ We can use the activation context API to load it at runtime.
References:
- http://stackoverflow.com/questions/4308503/how-to-enable-visual-styles-without-a-manifest
- http://support.microsoft.com/kb/830033
+The activation context code itself is in comctl32_windows.c.
*/
-func forceCommonControls6() error {
+func initCommonControls() (err error) {
manifestfile, err := ioutil.TempFile("", "gouicomctl32v6manifest")
if err != nil {
return fmt.Errorf("error creating synthesized manifest file: %v", err)
@@ -37,44 +34,12 @@ func forceCommonControls6() error {
// if ioutil.TempFile() ever changes so that the file is deleted when it is closed, this will need to change
manifestfile.Close()
- var actctx s_ACTCTXW
-
- actctx.cbSize = uint32(unsafe.Sizeof(actctx))
- // make this context the process default, just to be safe
- actctx.dwFlags = c_ACTCTX_FLAG_SET_PROCESS_DEFAULT
- actctx.lpSource = syscall.StringToUTF16Ptr(filename)
-
- res, err := f_CreateActCtxW(&actctx)
- if res == c_INVALID_HANDLE_VALUE {
- return fmt.Errorf("error creating activation context for synthesized manifest file: %v", err)
- }
- res, err = f_ActivateActCtx(res, &comctlManifestCookie)
- if res == c_FALSE {
- return fmt.Errorf("error activating activation context for synthesized manifest file: %v", err)
- }
- return nil
-}
-
-func initCommonControls() (err error) {
- var icc s_INITCOMMONCONTROLSEX
-
- err = forceCommonControls6()
- if err != nil {
- return fmt.Errorf("error forcing Common Controls version 6 (or newer): %v", err)
- }
-
- icc.dwSize = uint32(unsafe.Sizeof(icc))
- icc.dwICC = c_ICC_PROGRESS_CLASS
+ var errmsg *C.char
- // TODO call LoadLibraryW() directly
- comctl32 := syscall.NewLazyDLL("comctl32.dll")
- r1, _, err := comctl32.NewProc("InitCommonControlsEx").Call(uintptr(unsafe.Pointer(&icc)))
- if r1 == c_FALSE {
- return fmt.Errorf("error initializing Common Controls (comctl32.dll); Windows last error: %v", err)
+ errcode := C.initCommonControls(C.LPCWSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))), &errmsg)
+ if errcode != 0 || errmsg != nil {
+ return fmt.Errorf("error actually initializing comctl32.dll: %s: %v", C.GoString(errmsg), syscall.Errno(errcode))
}
- fv_SetWindowSubclass = comctl32.NewProc("SetWindowSubclass")
- fv_RemoveWindowSubclass = comctl32.NewProc("RemoveWindowSubclass")
- fv_DefSubclassProc = comctl32.NewProc("DefSubclassProc")
return nil
}
@@ -84,29 +49,6 @@ const (
x_PROGRESS_CLASS = "msctls_progress32"
)
-// this isn't generated by the constants generator because we need to load it from the correct version of comctl32.dll
-
-var (
- fv_SetWindowSubclass *syscall.LazyProc
- fv_RemoveWindowSubclass *syscall.LazyProc
- fv_DefSubclassProc *syscall.LazyProc
-)
-
-func f_SetWindowSubclass(hwnd uintptr, subproc uintptr, id t_UINT_PTR, data t_DWORD_PTR) (uintptr, error) {
- r1, _, err := fv_SetWindowSubclass.Call(hwnd, subproc, uintptr(id), uintptr(data))
- return r1, err
-}
-
-func f_RemoveWindowSubclass(hwnd uintptr, subproc uintptr, id t_UINT_PTR) (uintptr, error) {
- r1, _, err := fv_RemoveWindowSubclass.Call(hwnd, subproc, uintptr(id))
- return r1, err
-}
-
-func f_DefSubclassProc(hwnd uintptr, uMsg t_UINT, wParam t_WPARAM, lParam t_LPARAM) t_LRESULT {
- r1, _, _ := fv_DefSubclassProc.Call(hwnd, uintptr(uMsg), uintptr(wParam), uintptr(lParam))
- return t_LRESULT(r1)
-}
-
var manifest = []byte(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
diff --git a/redo/winapi_windows.h b/redo/winapi_windows.h
index 59b99fe..81bf271 100644
--- a/redo/winapi_windows.h
+++ b/redo/winapi_windows.h
@@ -25,3 +25,10 @@ extern void uimsgloop(void);
extern void issue(void *);
extern HWND msgwin;
extern DWORD makemsgwin(char **);
+
+/* comctl32_windows.c */
+extern DWORD initCommonControls(LPCWSTR, char **);
+/* TODO do any of these take WINAPI? */
+extern BOOL (*WINAPI fv_SetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
+extern BOOL (*WINAPI fv_RemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR);
+extern LRESULT (*WINAPI fv_DefSubclassProc)(HWND, UINT, WPARAM, LPARAM);