ObjReader Community

SDK programming => 64-bit SDK programming => Topic started by: Patrice Terrier on April 18, 2017, 08:00:57 pm

Title: zTrace version 3.00
Post by: Patrice Terrier on April 18, 2017, 08:00:57 pm
zTrace 3.00 (for 64-bit only)

This Visual Studio 2017 community project, has been totaly reworked to reduce the size down from 91 to 14 Kb.
(with the same technic used to produce the tiny MBox64 OpenGL visual plugins. (http://www.objreader.com/index.php?topic=80.0))

zTrace is a small DLL utility to display debugging information into a popup window tool, and/or a text file.
It uses a distinct thread to work in parallel of the current application you want to debug.

zTrace is very useful at development time to check whether a program operates properly.
It has been modeled onto the WinDev's Trace API, the original Win32 version was written in PowerBASIC.

I first wrote zTrace to debug my addon graphic DLL tools, but it works also very well with any 32-bit or 64-bit EXE.
When i took the decision to convert WinLIFT and GDImage to C++, it was the first on my list, because I couldn't develop anymore without it.

zTrace uses exclusively the core flat API, that is the only common denominator to all the languages I use, and the only way to get rid of extra dependencies.
The source code is provided in pure SDK coding style like documented into Charles Petzold 5th edition (the SDK coder Bible).

zTrace 64-bit is UNICODE based (32-bit is ANSI).

Syntax to use:
zTrace(L"Wide String Information")

Parameter detail:
one single unicode (WCHAR) string, holding the information to display in the trace window.

Trace window:
• The information passed as parameter is displayed on the next line of the zTrace window.
• The trace window is automatically opened when zTrace is called, by default, this window is opened at the top left corner of the screen.
• The zTrace window shuts down automatically when you close the application being debugged.

zDebug.txt report:
• Works exactly like the zTrace window, except that the information is written to a text file.
• The report is automatically created when zDebug is called, it is saved into the same folder than the debugged application.
• zDebug can be used alone or combined with zTrace (when the option is checked in the popup menu).
• zDebug is very handy when the debugged application shuts down unexpectedly or when the application as a short life duration, that won't give you enough time to read what is written in the zTrace window.
• A new fresh zDebug.txt is created each time you start a new zDebug session.

Contextual popup menu (right mouse click on the trace window):
• "Use horizontal scrollbar", show or hide the horizontal scrollbar.
• "Send selection to printer", print the selected lines (or the whole list when none).
• "Copy selection to clipboard", copy the selected lines (or the whole list when none) to clipboard.
• "Clear content", clear the content of the Trace window.
• "Trace window TopMost", open the Trace window on top of all the other windows (including the windows from the other applications).
• "Create zDebug.txt report", the zDebug.txt report is created into the debugged application's folder.
• "Save window coordinates", store the size and position of the zTrace window for the next session.

Screen shot:

(http://www.objreader.com/download/images/zTrace3.png)

Helper function, for EXPLICIT linking:
Code: [Select]
#define long_proc typedef long (__stdcall *zProc)

long zTrace(IN WCHAR* sPtr) {
    long nRet = 0;
    static HMODULE hDll;
    if (hDll == 0) {
        if (sizeof(LONG_PTR) == 8) {
            hDll = LoadLibrary(L"zTrace64");;
        }
        else {
            hDll = LoadLibrary(L"zTrace32");
        }
    }
    if (hDll) {
        long_proc(WCHAR*);
        static zProc hProc;
        if (hProc == 0) { hProc = (zProc)GetProcAddress(hDll, "zTrace"); }
        if (hProc) { nRet = hProc(sPtr); }
    }
    return nRet;
}

I want to say thank you to Fred and James for letting me know how to reduce drastically the size of a 64-bit application.


Settings used to create this tiny 14 Kb 64-bit DLL

zTrace Property Pages
The calling Convention for 64-bit is always using __fastcall (/Gr).
And in 64-bit no need to use a .def file to avoid the decorated names.

(http://www.objreader.com/download/images/zt01.jpg)

(http://www.objreader.com/download/images/zt02.jpg)

(http://www.objreader.com/download/images/zt03.jpg)

(http://www.objreader.com/download/images/zt04.jpg)

(http://www.objreader.com/download/images/zt05.jpg)

(http://www.objreader.com/download/images/zt06.jpg)

(http://www.objreader.com/download/images/zt07.jpg)

(http://www.objreader.com/download/images/zt08.jpg)

(http://www.objreader.com/download/images/zt09.jpg)

Include + Pragma
Code: [Select]
#include <windows.h>
#include "..\TCLib\Strings.cpp"

#pragma warning(disable: 4996) // remove Unsafe notifications
#pragma warning(disable: 4312) // remove warning C4312: 'type cast': conversion from 'long' to 'HMENU' of greater size

History
See it here: http://www.jose.it-berater.org/smfforum/index.php?topic=3092.0

04-26-2017
Fix:
delete [] SelItem;
was unexpectedly missing from the case IDM_Print

Enhancement:
New menu option: "Use Unicode in zDebug.txt"
to switch between ANSI or UNICODE
in case of ANSI, a UTF-8 BOM header is now being used.
UTF-8 BOM is a sequence of bytes (EF BB BF) that allows the reader to identify a file as being encoded in UTF-8.

04-27-2017
I have merged Andrei changes into this new version, with:
further code clean up,
new font set for both the listbox window and the printer,
switched back to XP compatibility,
no more TCLib linking that has been removed.

With more features, and further code optimization, the resulting size of the 64-bit Unicode DLL, is now only 11 Kb.
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on April 26, 2017, 09:58:41 am
from Andrey Unis

By the way with only 14Kb, it could be used to debug any unicode 64-bit application...
Can make 11kb...
By the way, there are few mistakes...
function zDebug() includes NUL characters to log file
WideCharToMultiByte(CP_ACP, 0, sMessage, -1, buffer, BufferSize - 1, 0, 0);
(but better remake this function to support unicode chars (for example chinese language))

function ToolProc()
Code: [Select]
    case WM_GETMINMAXINFO:
         MoveMemory(&pMM, (MINMAXINFO*) lParam, sizeof(pMM));
         SetRect(&rc, 0, 0, MIN_WIDTH, MIN_HEIGHT);
         AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);  // Adjust Window To True Requested Size
         pMM.ptMinTrackSize.x = rc.right;
         pMM.ptMinTrackSize.y = rc.bottom;
         break;
fix
Code: [Select]
case WM_GETMINMAXINFO:
SetRect(&rc, 0, 0, MIN_WIDTH, MIN_HEIGHT);
AdjustWindowRectEx(&rc, WND_Style, FALSE, WND_ExStyle);  // Adjust Window To True Requested Size
((LPMINMAXINFO)lParam)->ptMinTrackSize.x = rc.right;
((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rc.bottom;
break;

case IDM_Print:
  ...
  long* SelItem = new long[nSelItems];
memory leak, missed: delete [] SelItem ;

my variant (11kb) attached
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on April 26, 2017, 04:28:22 pm
The first post of this thread has been updated with a new version.

Fix:
delete [] SelItem;
was unexpectedly missing from the case IDM_Print

Enhancement:
New menu option: "Use Unicode in zDebug.txt"
to switch between ANSI or UNICODE
in case of ANSI, a UTF-8 BOM header is now being used.
UTF-8 BOM is a sequence of bytes (EF BB BF) that allows the reader to identify a file as being encoded in UTF-8.

Thanks to Andrey Unis who reported these to me.
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on April 27, 2017, 06:56:32 pm
The first post of this thread has been updated with a new version.

I have merged Andrei changes into this new version, with:
further code clean up,
new font set for both the listbox window and the printer,
switched back to XP compatibility,
no more TCLib linking that has been removed.

With more features, and further code optimization, the resulting size of the 64-bit Unicode DLL, is now only 11 Kb.
Title: Re: zTrace version 3.00
Post by: Emil Weiss on May 04, 2017, 03:07:04 am
..
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on May 05, 2017, 10:15:37 am
Emil

In PB
DECLARE FUNCTION zTrace LIB "zTrace32.DLL" ALIAS "zTrace" (zMessage AS ASCIIZ) AS LONG
is to be used for IMPLICIT linking, not explicit.

If you want to use EXPLICIT linking with PB, you have to do this:
(assuming that the DLL is in the current path or within the same folder than the EXE).
Code: [Select]
funtion zTrace(zMessage as asciiz) as long
    long nRet
    static hDll, hProc as dword
    if (hDll = 0) then
        hDll = LoadLibrary("zTrace")
    end if
    if (hDll) {
        if (hProc = 0) then hProc = GetProcAddress(hDll, "zTrace")
        if (hProc) then
            call dword hProc USING zTrace(zMessage) to nRet
        end if
    end if
    function = nRet
end function

And the window shows up only when you use zTrace with an ANSI asciiz that is not NULL.

For example in your code you can do this
Code: [Select]
local rNumber as single
rNumber = 12.45!
zTrace("We have been there")
zTrace("And the value of rNumber =" + str$(rNumber))

And with PB10 like with C++, the zTrace code is compiled into your resulting code, only when you use it (compiler optimization).

Title: Re: zTrace version 3.00
Post by: James Fuller on September 07, 2020, 01:16:41 pm
Patrice,
  How can you have Debug.txt active when there is no place in the code you are debugging to pause so you can click the ztrace window?

James
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on September 08, 2020, 03:32:40 pm
James

Did you try to save the zTrace parameters, with zDebug enabled?
Title: Re: zTrace version 3.00
Post by: James Fuller on September 08, 2020, 04:26:05 pm
Patrice,
  I don't understand.
The only save I see when I right click the ztrace window is "Save Window cooridinates" which I do not know what that does?

It always pops up at the top left. (note I am running dual minitors)

I was hoping there was some way to have Debug.txt persistent across runs.

You speak of using zDebug at the top instead/with ztrace????
What is zDebug?

James
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on September 08, 2020, 08:59:05 pm
James

Use zTrace64  (version 3.01) with any application, then check the menu option "Create zDebug.txt report".

And the next time you use zTrace64, the zDebug.txt report will be created with any application using zTrace, until you uncheck it from the contextual menu.
Title: Re: zTrace version 3.00
Post by: James Fuller on September 08, 2020, 10:26:15 pm
James

Use zTrace64  (version 3.01) with any application, then check the menu option "Create zDebug.txt report".

And the next time you use zTrace64, the zDebug.txt report will be created with any application using zTrace, until you uncheck it from the contextual menu.

Patrice,
  I am not finding that the case.
I have to right click every time I use it. It is not persistent.
I am using the download form this forum which is 3.00 64 not 3.01

James
Title: Re: zTrace version 3.00
Post by: James Fuller on September 08, 2020, 10:41:42 pm
Patrice,
  The old zTrace32 2.02 I have works correctly.
I tracked down on old 2.02 64 bit and it works also.
James
Title: zTrace64 version 3.01
Post by: Patrice Terrier on September 09, 2020, 10:31:11 am
James

Here is the complete C++ VS2017 project to version 3.01.

That one works well by me.

Title: Re: zTrace version 3.00
Post by: James Fuller on September 09, 2020, 12:41:03 pm
Patrice,
  I think I found the issue. Your zTrace3.cfg file is never created.

This is my temp folder as returned from GetTempPath()

C:\Users\jcful\AppData\Local\Temp

From your source
Code: [Select]
    WCHAR zPath[MAX_PATH]; __stosb((LPBYTE)&zPath, 0, MAX_PATH * 2);
    GetTempPath(MAX_PATH - 12, zPath); lstrcat(zPath, L"zTrace3.cfg");

You do not add  a "\" before the name.


I was not able to compile the project with VS 2019. There were hard coded paths that VS whined about.

Why zTrace64 works for you ???


James
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on September 09, 2020, 03:02:56 pm
By me, GetTempath always return the path with a trailing back slash

even (from my Windows config) when SET is defined only like this:
TEMP=C:\Tmp
TMP=C:\Tmp

Tell me if you want the project converted to VS2019.
Title: Re: zTrace version 3.00
Post by: James Fuller on September 09, 2020, 04:12:13 pm
Patrice,
   This is much easier. A bit bigger but ....
I just added a few lines to the ztrace.cpp file
I do have to close the zTrace window with the "x" instead of having the program that called it exit for it to be persistent.

James
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on September 09, 2020, 09:07:52 pm
James

GetTempath, should already have a trailing back slash, please check the value returned by the API before adding zTrace3.cfg.

Other way L"\\" should be added only if missing.

See the PathAddBackslash API
Title: Re: zTrace version 3.00
Post by: James Fuller on September 09, 2020, 09:10:22 pm
Patrice,
  I guess I'm just getting too old for coding!
Delete this topic. It was my oversight.
I thought just unloading the zTrace dll by termination of the program that called it would create/update the cfg file.
I also thought I wrote a small snippit that printed GetTempPath and it did not have a trailing "\", but on further review it does,just as you said.
Sorry to have bothered you.
James

 
Title: Re: zTrace version 3.00
Post by: Patrice Terrier on September 10, 2020, 02:27:37 pm
James

How old are you, i think coding is good to keep our neurone at work ;)
Title: Re: zTrace version 3.00
Post by: James Fuller on September 10, 2020, 04:36:42 pm
Patrice,
  After a reboot of me (a good nights sleep) and the computers my OCD would not let me drop this. I found I'm not as bad as I previously thought.
I again used zTrace64.dll from the forum posting.
After the window popped up I right clicked and selected the create debug.txt.
After the popup menu closed I right clicked again and the create debug.txt item was checked.
I then closed the ztrace window using the red "x"
The ztrace.cfg file was created in my user temp folder but nothing was written to it. It had a size of 0
When I ran my app again and right clicked the ztrace window the create debug.txt was not checked.

I then took the ztrace 3.01 ztrace.cpp source and only added a couple of lines at the top. No change to the GetTempPath. I compiled with the attached buildit.bat file.
I replaced zTrace64.dll (3.00) from the forum with the new 3.01 (renamed 3.02 by me).

I deleted ztrace.cfg from the temp folder and repeated the above. This time the ztrace.cfg had a size of 1
and all worked as expected.

The Test_zTrace.cpp was created with BCX and is a non-unicode app that just calls zTrace through ZPRINT which is defined as:
#define ZPRINT(x) zTrace(AnsiToWide((char*)(x)))

platform:
Windows 10 64. version 2004(osbuild 19041.508)

I'm not going to beat on this anymore. I don't know why mine works and your's does not? I now have a working version.

I would like permission to include my version with an upcoming BcxAdp (BCX Application Development Platform)
All of your copyright notices and acknowledgments would be included.

Mr BCX has done a fantastic job on updating BCX. Now with a working pre-compiler meta command $PP I do not have to fork and change BCX to add more of the c++ items I want.

Thank for your patience.
Age: 72
James




Title: Re: zTrace version 3.00
Post by: Patrice Terrier on September 10, 2020, 07:28:24 pm
James

You are just one year older than me ;)

Obviously i can't see any difference between the 2 codes, except that i am using the Visual Studio environment, while you are using the command line.

I am using Windows 10 Professional 2004 OS version 19041.508

Yes, you have my permission to include zTrace64 with the upcoming BcxAdp.

Where are you living?


Title: Re: zTrace version 3.00
Post by: James Fuller on September 10, 2020, 08:02:57 pm
James

You are just one year older than me ;)


Where are you living?

I am here:
https://goo.gl/maps/bA97cRTi8FeZbo2Q9

James
Title: SendUnicodeToClipboard
Post by: Patrice Terrier on October 23, 2021, 05:09:23 pm
There is a memory allocation error in SendUnicodeToClipboard causing a GPF in zTrace 3.01.

Here is the fix to use

Code: [Select]
static void SendUnicodeToClipboard(HWND hWnd) {
    HWND hCtrl = GetDlgItem(hWnd, ID_LISTBOX);
    long nCount = (long)(DWORD)SendMessage(hCtrl, LB_GETCOUNT, 0L, 0L);
    if (nCount > 0) {
        long bufsize = 0;
        long *pSelItems = NULL;
        long nSelItems = (long)SendMessage(hCtrl, LB_GETSELCOUNT, 0L, 0L);
        if (nSelItems > 0) {
            nCount = 0;
            pSelItems = (long *)GlobalAlloc(GPTR, nSelItems * sizeof(long));
            if (pSelItems) {
                nCount = nSelItems;
                SendMessage(hCtrl, LB_GETSELITEMS, nSelItems, (LPARAM)pSelItems);
            }
        }

        for (long i = 0; i < nCount; i++) {
            long index = pSelItems ? pSelItems[i] : i;
            long cch = (long)SendMessage(hCtrl, LB_GETTEXTLEN, (WPARAM)index, 0L);
            if (cch > 0)
                bufsize += cch + 2;
        }

        if (bufsize > 0) {
            HGLOBAL hClipData = GlobalAlloc(GHND | GMEM_DDESHARE, (bufsize + 1) * sizeof(TCHAR));
            if (hClipData) {
                LPTSTR  buffer = (LPTSTR)GlobalLock(hClipData);
                long offset = 0;

                for (long i = 0; i < nCount; i++) {
                    long index = pSelItems ? pSelItems[i] : i;
                    long cch = (long)SendMessage(hCtrl, LB_GETTEXTLEN, (WPARAM)index, 0L);
                    if (cch > 0) {
                        if ((offset + cch + 2) > bufsize)
                            break;

                        cch = (long)SendMessage(hCtrl, LB_GETTEXT, (WPARAM)index, (LPARAM)(buffer + offset));
                        offset += cch;
                        buffer[offset++] = '\r';
                        buffer[offset++] = '\n';
                    }
                }

                buffer[bufsize] = 0;
                GlobalUnlock(hClipData);

                if (OpenClipboard(0)) {
                    EmptyClipboard();
                    SetClipboardData(CF_UNICODETEXT, hClipData);
                    CloseClipboard();
                } else {
                    GlobalFree(hClipData);
                }
            }
        }
    }
}