Win32 Apps with Zig - conflicting Defintions: extern struct vs. *opaque{};

In an attempt to follow the YT Series Handmade Hero with Zig, tried to create a Win32 Application Entry Point. The current issues with Zig surrounding Issue #15066 and Issue #7852 be avoided by using the windows.h header and changing std.zig.c_translation.zig as I outlined in #15066

First off:
Extern structs / their redefinitions in imported headers and the defined structs (*opaque {};) are incompatible, so std.os.windows.HWND and the imported c.HWND wont work together:

Slices.zig:149:57: error: 
	expected type 	'[*c].cimport.struct_HWND__', 
	found 		'*os.windows.HWND__opaque_57354'
            var deviceContext: win32.HDC = c.BeginPaint(window, &paint);
                                                                                        ^~~~~~
Slices.zig:149:57: note: 
	pointer 		 type child 'os.windows.HWND__opaque_57354' 
	cannot cast into pointer type child 'C:.cimport.struct_HWND__'

Zig_w_x86_64_0.12.0-dev.15\lib\std\os\windows.zig:2485:19: note: opaque declared here
	pub const HWND = *opaque {};
        	                          ^~~~~~~~~
cimport.zig:25485:34: note: struct declared here
	pub const struct_HWND__ = extern struct {
	                                            ~~~~~~~^~~~~~
cimport.zig:31861:32: note: parameter type declared here
	pub extern fn BeginPaint(hWnd: HWND, lpPaint: LPPAINTSTRUCT) HDC;

So Functions that are cImported need also be fed c extern structs (like c.HWND), although they in theory are the same.
I suppose this is the reason for my actual current bug:
In my wWinMain function:
pub fn wWinMain(instance: win32.HINSTANCE, prevInstance: ?win32.HINSTANCE, commandLine: win32.LPWSTR, showCode: i32) callconv(win32.WINAPI) i32 {...}

I can either pass a std.os.windows.HINSTANCE or a c.HINSTANCE from the imported header. Using the std.os.windows.HINSTANCE produces a compile error, since the cimport.struct_HDC__' cannot cast into pointer type child 'os.windows.HDC__opaque_58145' (What i mentioned before).

However using the c.HINSTANCE produces another problem, as std.zig.start casts the prevInstance: win32.HInstance into something the wWinMain doesnt like (format might be off):

Zig_w_x86_64_0.12.0-dev.15\lib\std\start.zig:598:43: error: cast increases pointer alignment
    const hInstance = @as(MAIN_HINSTANCE, @ptrCast(std.os.windows.kernel32.GetModuleHandleW(null).?));
                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Zig_w_x86_64_0.12.0-dev.15\lib\std\start.zig:598:98: note: '*os.windows.HMODULE__opaque_55731' has alignment '1'
    const hInstance = @as(MAIN_HINSTANCE, @ptrCast(std.os.windows.kernel32.GetModuleHandleW(null).?));
                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
Zig_w_x86_64_0.12.0-dev.15\lib\std\start.zig:598:43: note: '[*c]C:.cimport.struct_HINSTANCE__' has alignment '4'
Zig_w_x86_64_0.12.0-dev.15\lib\std\start.zig:598:43: note: use @alignCast to assert pointer alignment
Zig_w_x86_64_0.12.0-dev.15\lib\std\start.zig:537:12: note: called from here
    return @call(.always_inline, call_wWinMain, .{});
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Zig_w_x86_64_0.12.0-dev.15\lib\std\start.zig:350:67: note: called from here
    const result: std.os.windows.INT = initEventLoopAndCallWinMain();

I think this issue is because prevInstance is allways null, but the std.zig.start process in currently beyond me. Maybe someone knows hoe to handle this ?

Using the ?c.HINSTANCE for the prevInstance as well does not work since:
parameter of type '?[*c]C:.cimport.struct_HINSTANCE__' not allowed in function with calling convention 'C'

and just c.HINSTANCE causes the last issue described in my first post.

Problem is that as outlined above Cimported Types and std.os.windows types are conflicting:

The std.start function:

pub fn call_wWinMain() std.os.windows.INT {
    const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).Fn.params[0].type.?;
    const hInstance = @as(MAIN_HINSTANCE, @ptrCast(std.os.windows.kernel32.GetModuleHandleW(null).?)); 
    const lpCmdLine = std.os.windows.kernel32.GetCommandLineW();
    const nCmdShow = std.os.windows.user32.SW_SHOW;
    return root.wWinMain(hInstance, null, lpCmdLine, nCmdShow);
}

Tries to cast a callconv(WINAPI) ?HMODULE to a ptr of the type of the first variable, which in this case is a c.HINSTANCE which is defined in the CImport as:

pub const struct_HINSTANCE__ = extern struct {
    unused: c_int,
};
pub const HINSTANCE = [*c]struct_HINSTANCE__;

apart from the different types, the alignment differs, due to the unused: c_int I guess.

Since I cannot / do not know how the Cimport works, I suppose the call_wWinMain() has to be edited to allow for the exact type of the first parameter and not a cast std.os.windows type.

Modifying std.start.call_wWinMain revealed to me that I have another error to solve. This however seems to solve my initial problem for now. If I can get my programm to run by fixing the remaining issues, I will mark this as a solution and post it on Github as a potential pull request.

pub fn call_wWinMain() std.os.windows.INT {
    const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).Fn.params[0].type.?;
	const helpInstance: MAIN_HINSTANCE = null;
    const hInstance = @as(MAIN_HINSTANCE, @ptrCast(helpInstance));
    const lpCmdLine = std.os.windows.kernel32.GetCommandLineW();

    // There's no (documented) way to get the nCmdShow parameter, so we're
    // using this fairly standard default.
    const nCmdShow = std.os.windows.user32.SW_SHOW;

    // second parameter hPrevInstance, MSDN: "This parameter is always NULL"
    return root.wWinMain(hInstance, null, lpCmdLine, nCmdShow);
}

No I am stuck at Issue #13968

Tons of @compileError("unable to translate macro .... ")
and @compileError("unable to translate C expr: unexpected token 'Eof'");

You might want to try defining NO_STRICT before including Windows.h. See:

and std.os.windows: Change HKEY to *opaque {} by squeek502 · Pull Request #13156 · ziglang/zig · GitHub

HANDLE types being an extern struct with one unused field is only done as a way to get a C compiler to be able to differentiate between the different DECLARE_HANDLE types (something that Zig does by default with opaque{}). With NO_STRICT, all handles are void* instead which might help with some of the issues you’re running into.

I have actually resolved all of my issues besides now the C compiler being unable to parse all the various header files included (see my previous last post)