win_LoadResource() fails on zig compiled code

196 views
Skip to first unread message

Maurizio la Cecilia

unread,
Nov 15, 2025, 6:43:57 PM (14 days ago) Nov 15
to harbou...@googlegroups.com
I was able to build Harbour and an application using zig from
https://ziglang.org/download/ (msys2 zig package failed the build as
Aleksander said).
All seems working fine apart in code calling win_LoadResource().
The exe has right resource section, I can inspect it using
ResourceHacker or Hex Editor.

Below a self contained set of files demonstrating the issue.

Obviously, both my application and the code below works fine when
compiled with mingw64...


Any help will be very appreciated.
--
Maurizio

-------------------------------------------------------------------------
testzig.hbp
-------------------------------------------------------------------------

hbwin.hbc

testzig.prg
testzig.rc

-------------------------------------------------------------------------
testzig.prg
-------------------------------------------------------------------------

procedure main()

local s

s := win_LoadResource( "HLPFILE", "RESFILE" )

?  "->" + s + "<-"
inkey( 0 )

-------------------------------------------------------------------------
testzig.rc
-------------------------------------------------------------------------

HLPFILE RESFILE "help.txt"

-------------------------------------------------------------------------
help.txt
-------------------------------------------------------------------------

Help me
I'm not read by win_LoadResource()

Grigory Filatov

unread,
Nov 16, 2025, 4:33:33 AM (13 days ago) Nov 16
to Harbour Developers
Hi Maurizio,

> Any help will be very appreciated.
I've solved this problem by using a modified win_Load Resource() function, which was renamed to win_LoadResource2() to link correctly.

Please look at the updated code snippet below.

/*-------------------------------------------------------------------------
testzig.prg
-------------------------------------------------------------------------*/

procedure main()

local s

s := win_LoadResource2( "HLPFILE", "RESFILE" )

MsgInfo( "->" + s + "<-" )


#pragma BEGINDUMP

#include <windows.h>

#include "hbapi.h"

#include "hbwapi.h"
#include "hbapiitm.h"

HB_FUNC( WIN_LOADRESOURCE2 )
{
   HANDLE hInstance = NULL;

   /* Set default return value */
   hb_retc_null();

   if( !hb_winmainArgGet( &hInstance, NULL, NULL ) )
         hInstance = GetModuleHandle( NULL );

   {
      void * hName;
      void * hType;

      HRSRC hRes = FindResource( ( HMODULE ) hInstance,
                                 HB_PARSTRDEF( 1, &hName, NULL ),
                                 HB_PARSTRDEF( 2, &hType, NULL ) );

      if( hRes )
      {
         HGLOBAL hMem = LoadResource( hInstance, hRes );

         if( hMem )
         {
            void * pMem = LockResource( hMem );

            if( pMem )
               hb_retclen( ( char * ) pMem, SizeofResource( hInstance, hRes ) );
         }
      }

      hb_strfree( hName );
      hb_strfree( hType );
   }
}
#pragma ENDDUMP

You can see the result in the picture.
image.png

Hope this is helpful.

Best regards,
Grigory Filatov

воскресенье, 16 ноября 2025 г. в 00:43:57 UTC+1, Maurizio la Cecilia:

Aleksander Czajczynski

unread,
Nov 17, 2025, 4:35:38 AM (12 days ago) Nov 17
to harbou...@googlegroups.com
Hey!

Thank you for reporting.

I suppose the sample should be compiled with hbmk2 -gui testzig.hbp
Anyway it doesn't seem to work either, or am I wrong?

It seem Zig responds correctly to this switch, by inspecting with MSVC tool: dumpbin.exe /headers testzig.exe

Dump of file x:\testzig.exe (compiled with -gui)

PE signature found

File Type: EXECUTABLE IMAGE

OPTIONAL HEADER VALUES
             20B magic # (PE32+)
           14.00 linker version
           F8E00 size of code
           32A00 size of initialized data
               0 size of uninitialized data
            11F0 entry point (00000001400011F0) WinMainCRTStartup


Dump of file x:\testzig.exe (compiled without -gui)

PE signature found

File Type: EXECUTABLE IMAGE

OPTIONAL HEADER VALUES
             20B magic # (PE32+)
           14.00 linker version
           F8E00 size of code
           32A00 size of initialized data
               0 size of uninitialized data
            1420 entry point (0000000140001420) mainCRTStartup


Well, I don't know the contents of WinMainCRTStartup, it should call WinMain, appearantly it isn't?

I won't commit any hackfix for this, before the cause is known. If you want a better one, because win_LoadResource() will be not only failing place (where hb_winMainArgGet is used)

Something like this would fix more locations. Basically GetModuleHandle( NULL ) should be equal to WinMain's phInstance for .exe's.

diff --git a/src/vm/cmdarg.c b/src/vm/cmdarg.c
index 130ab5fe69..cf81f39bee 100644
--- a/src/vm/cmdarg.c
+++ b/src/vm/cmdarg.c
@@ -281,6 +281,9 @@ HB_BOOL hb_winmainArgGet( void * phInstance, void * phPrevInstance, int * piCmdShow )
 {
    if( phInstance )
       *( ( HANDLE * ) phInstance ) = s_hInstance;
+   else
+      *( ( HANDLE * ) phInstance ) = GetModuleHandle( NULL );;
+
    if( phPrevInstance )
       *( ( HANDLE * ) phPrevInstance ) = s_hPrevInstance;
    if( piCmdShow )

Best regards, Aleksander

Grigory Filatov wrote:
--
You received this message because you are subscribed to the Google Groups "Harbour Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-deve...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/harbour-devel/93432eba-1f68-4a5c-9273-ea3af970176dn%40googlegroups.com.

Maurizio la Cecilia

unread,
Nov 17, 2025, 5:59:04 AM (12 days ago) Nov 17
to Harbour developers group
Hi Grigory,
thank you very much. 
Your patch solves the problem. 
Now my doubt is about other functions quering for
hb_winMainArgGet().
I'll search extensively in Harbour sources and in my c functions for other references and report them. 
My best regards. 
--
Maurizio 


Aleksander Czajczynski

unread,
Nov 17, 2025, 6:56:48 AM (12 days ago) Nov 17
to harbou...@googlegroups.com
Oops, not seeing things as they are today. So the hack-fix is more as follows:

diff --git a/src/vm/cmdarg.c b/src/vm/cmdarg.c
index 130ab5fe69..c01c590a4a 100644
--- a/src/vm/cmdarg.c
+++ b/src/vm/cmdarg.c
@@ -280,7 +280,13 @@ void hb_winmainArgInit( void * hInstance, void * hPrevInstance, int iCmdShow )

 HB_BOOL hb_winmainArgGet( void * phInstance, void * phPrevInstance, int * piCmdShow )
 {
    if( phInstance )
-      *( ( HANDLE * ) phInstance ) = s_hInstance;
+   {
+      if( s_hInstance )
+         *( ( HANDLE * ) phInstance ) = s_hInstance;

+      else
+         *( ( HANDLE * ) phInstance ) = GetModuleHandle( NULL );
+   }
+

Best regards, Aleksander

Maurizio la Cecilia wrote:

Maurizio la Cecilia

unread,
Nov 18, 2025, 3:05:28 PM (11 days ago) Nov 18
to harbou...@googlegroups.com
Hi Aleksander,
first of all, sorry for the long delay in responding and thank you for your interest.

Let's go in order:
My test build doesn't include -gui, so from what I remember, gtwin should be enabled in a Windows environment; but that's irrelevant because the problem also occurs with gtwvt.
However, I delayed my response because your patch seems completely correct and should avoid affecting all the places where hb_hb_winmainArgGet is used (and there are many, especially in gtwvw and gtwvg), replacing the call with what Grigory suggested:
if( ! hb_winmainArgGet( &hInstance, NULL, NULL ))

hInstance = GetModuleHandle( NULL );
But in fact, incredibly, your patch doesn't solve the problem, while Grigory's patch does.
I probably manually applied the patch incorrectly (git apply returns a broken patch error), so please check if the correct code should be this:

HB_BOOL hb_winmainArgGet( void * phInstance, void * phPrevInstance, int * piCmdShow )
{
   if( phInstance )
      {
      if( s_hInstance )
         *( ( HANDLE * ) phInstance ) = s_hInstance;
      else
         *( ( HANDLE * ) phInstance ) = GetModuleHandle( NULL );
      }
   if( phPrevInstance )
      *( ( HANDLE * ) phPrevInstance ) = s_hPrevInstance;
   if( piCmdShow )
      *piCmdShow = s_iCmdShow;
   return s_WinMainParam;
}

Also, hb_winmainArgGet always returns true unless hb_winmainArgInit() hasn't been called previously (in fact, it's the only function that sets s_WinMainParam to true...).
At this point, I'm quite confused.
What's the problem?
Unfortunately, I'm not an expert at debugging C; I'll try using hb_trace or OutputDebugString, but surely you can clarify this first.
TIA and best regards.
--
Maurizio

Aleksander Czajczynski

unread,
Nov 19, 2025, 4:45:40 AM (10 days ago) Nov 19
to harbou...@googlegroups.com
Hello Maurizio!

Probably I'm the one that started it, by adding Zig to the supported toolchains.

Anyway, such patch works here (attached the modified file). At least it does after "make clean".
With minor note, trying -gtwin build under MSYS2 shell, it outputted only "<-" (shell bug?). Under regular Windows terminal it's ok.

But the original issue is something that I haven't looked into. If it's related to WinMain, then it's probably related to -gui. But then how does usual MinGW toolset cope with that?
To answer these, some extened tracing should be set up, maybe I will make ready to use tracing/debug Harbour+zig build, but to not increase confusion on the list without giving answers, I'll try to reach you in a direct e-mail.
cmdarg.c

Aleksander Czajczynski

unread,
Nov 21, 2025, 5:51:44 AM (8 days ago) Nov 21
to harbou...@googlegroups.com
Escalated into another direction. Trying to make a debug and _unoptimized_ build with Zig (LLVM) ended up with run time undefined behaviour sanitizer panic. Other Clang/LLVM distros do not seem to include such sanitizer in debug version.

thread 97770 panic: left shift of 255 by 24 places cannot be represented in type 'HB_I32' (aka 'int')
../../../hbopt.c:1044:17: 0x125c203 in hb_compJumpGetOffset (../../../hbopt.c)
../../../hbopt.c:1334:33: 0x125b0db in hb_compPCodeTraceAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1342:14: 0x125b26f in hb_compPCodeTraceAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1342:14: 0x125b26f in hb_compPCodeTraceAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1342:14: 0x125b26f in hb_compPCodeTraceAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1473:19: 0x1244e23 in hb_compPCodeEnumAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1698:4: 0x123f7cb in hb_compPCodeTraceOptimizer (../../../hbopt.c)
../../../hbopt.c../../../hbmain.c:1918:10: 0x106bcd7 in hb_compFinalizeFunction (../../../hbmain.c)
../../../hbmain.c:2212:4: 0x106a827 in hb_compFunctionAdd (../../../hbmain.c)
:1044:17: 0x125c203 in hb_compJumpGetOffset (../../../hbopt.c)
../../../hbopt.c:1334:33: 0x125b0db in hb_compPCodeTraceAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1342:14: 0x125b26f in hb_compPCodeTraceAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1473:19: 0x1244e23 in hb_compPCodeEnumAssignedUnused (../../../hbopt.c)
../../../hbopt.c:1698:4: 0x123f7cb in hb_compPCodeTraceOptimizer (../../../hbopt.c)

Przemysław, can you confirm that patching the macro like this is OK? Patch is attached. Fixing these debug diagnostics with signed integer overflows may be "interesting", seems more will come around this area.

Best regards, Aleksander


Aleksander Czajczynski wrote:
--
You received this message because you are subscribed to the Google Groups "Harbour Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-deve...@googlegroups.com.
patch-02.txt

Przemyslaw Czerpak

unread,
Nov 21, 2025, 9:29:38 AM (8 days ago) Nov 21
to harbou...@googlegroups.com
Hi Aleksander,

It's correct though if possible please keep indenting ;)
We already have some set of such fixes in the source code,
i.e. HB_CAST_*() macros. It was workaround for some
versions of GCC which used to mark overflow in conversion
from double to smaller signed integer values setting the
result to -1.

best regards,
Przemek


W dniu 21.11.2025 o 11:51, Aleksander Czajczynski pisze:
Reply all
Reply to author
Forward
0 new messages