1

In my Window_manager.c file I nowhere edit the Value of *wm->actStkSize by hand (!?), however after calling DispatchMessage(&msg); in the RunMessageLoop function, the Value somehow changed from 0 to 66, I have absolutely no idea how.

main.c:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WindowManager wm;
    InitWindowManager(&wm);
    printf("from main: %d %d\n", *wm.actBfrSize, *wm.actStkSize);

    if (CreateAndShowWindow(&wm, hInstance, nCmdShow) != 0)
    {
        MessageBox(NULL, L"Failed to create window.", L"Error", MB_OK | MB_ICONERROR);
        return 1;
    }

    int result = RunMessageLoop(&wm);
    CleanupWindowManager(&wm);

    return result;
}

Window_manager.c:

#include "window_manager.h"
#include <stdio.h>
#include <windows.h>
#include <windowsx.h>
#include "config.h"
#include "graphics.h"

void InitWindowManager(WindowManager *wm) {
    wm->hwnd = NULL;
    wm->logFile = NULL;

    Document doc;
    Page pg;
    RawPoint** stack = (RawPoint**)malloc(sizeof(RawPoint*));
    RawPoint* buffer = (RawPoint*)malloc(SIZE_OF_BUFFER * sizeof(RawPoint));
    *stack = buffer;

    pg.rawStk = stack;
    pg.rawBfrSize = 0;
    pg.rawStkSize = 0;
    doc.page = &pg;
    wm->document = &doc;
    wm->actBuffer = buffer;
    wm->actPt = buffer;
    wm->actBfrSize = &pg.rawBfrSize;
    wm->actStkSize = &pg.rawStkSize;

    // Initialize penData attributes
    wm->penData.position.x = 0;
    wm->penData.position.y = 0;
    wm->penData.pressure = 0.0f;
    wm->penData.azimuth = 0.0f;
    wm->penData.altitude = 0.0f;
    wm->penData.tiltX = 0.0f;
    wm->penData.tiltY = 0.0f;
    wm->penData.twist = 0.0f;
    wm->penData.touching = FALSE;
    wm->penData.buttonPressed = FALSE;

    wcscpy_s(wm->displayText, MAX_TEXT_LENGTH, L"Pointer Events: None");
    wcscpy_s(wm->logFileName, MAX_TEXT_LENGTH, L"logs/pen_pressure_log.txt");
    // Open the log file for writing
    _wfopen_s(&wm->logFile, wm->logFileName, L"w");
}

int CreateAndShowWindow(WindowManager *wm, HINSTANCE hInstance, int nCmdShow) {
    
    // Register window class
    // Register window class
    WNDCLASSW wc = {}; // Note the use of WNDCLASSW for wide strings
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = L"MyWindowClass"; // Use wide-character string

    if (RegisterClassW(&wc) == 0) {
        // Handle registration failure
        return 1;
    }
    // Create window
    wm->hwnd = CreateWindowExW(0, L"MyWindowClass", L"My Window Title",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        500, 300, NULL, NULL, hInstance, wm);
    HWND hButton = CreateWindowExW(0, L"BUTTON", L"redraw",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
        10, 50, 100, 30,
        wm->hwnd, (HMENU)1001, GetModuleHandle(NULL), NULL);
    if (wm->hwnd == NULL) {
        return 1;
    }
    ShowWindow(wm->hwnd, nCmdShow);
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    WindowManager *wm;
    if (uMsg == WM_NCCREATE) {
        // Retrieve the pointer to the WindowManager from the CREATESTRUCT
        CREATESTRUCT *pCreate = (CREATESTRUCT *)lParam;
        wm = (WindowManager *)pCreate->lpCreateParams;
        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)wm);
        wm->hwnd = hwnd;
        printf("from ProcIf: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));

        // printf("%s",wm->displayText);
        // printf("if");
    } else {
        wm = (WindowManager *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
        // printf("from ProcElse: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
    }
    // printf("from Proc: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
    // printf("WindowPrc: %i\n", *wm->actStkSize);
    switch (uMsg) {
        case WM_CLOSE: {
            printf("from WM_CLOSE: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            DestroyWindow(hwnd);
            break;
        }
        case WM_DESTROY: {
            printf("from WM_DESTROY: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            PostQuitMessage(0);
            break;
        }
        case WM_POINTERDOWN: {
            printf("from WM_POINTERDOWN: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            wm->penData.touching = TRUE; // Pen is down
            break;
        }
        case WM_POINTERUP: {
            printf("from WM_POINTERDOWN: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            wm->penData.touching = FALSE;
            break;
        }
        case WM_POINTERUPDATE: {
            printf("from WM_POINTERUPDATE: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            // Handle pointer events
            wm->penData.position.x = GET_X_LPARAM(lParam);
            wm->penData.position.y = GET_Y_LPARAM(lParam);
            ScreenToClient(wm->hwnd, &wm->penData.position);
            wm->actPt->coords.x = wm->penData.position.x;
            wm->actPt->coords.y = wm->penData.position.y;
            wm->actPt->touching = wm->penData.touching;
            wm->actPt->pressure = GET_POINTERID_WPARAM(wParam) / 5551.0f;
            UpdateDisplay(wm);
            InvalidateRect(hwnd, NULL, TRUE); // Request a redraw of the window
            
            (*wm->actBfrSize)++;
            if (*wm->actBfrSize == SIZE_OF_BUFFER) {
                printf("Stoooooooooop!!!");
            }
            else {
                // printf("actStkSize: %i\n", *(wm->actStkSize));
                wm->actPt++;
            }
            break;
        }
        case WM_SIZE: {
            printf("from WM_SIZE: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            Do Some Stuff
            break;}
        case WM_PAINT: {
            printf("from WM_PAINT: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            // Do some Stuff
            break;}
        case WM_COMMAND: {
            printf("from WM_COMMAND: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            //Do some Stuff
        }
        default: {
            // printf("from default: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
    }
    return 0;
}

int RunMessageLoop(WindowManager *wm) {
    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        printf("from beginLoop: %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
        TranslateMessage(&msg);
        printf("from midLoop:   %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
        DispatchMessage(&msg);
        printf("from endLoop:   %d %d\n", *(wm->actBfrSize), *(wm->actStkSize));
    }
    return (int)msg.wParam;
}

void CleanupWindowManager(WindowManager *wm) {
    // Close the log file if it's open
    if (wm->logFile != NULL) {
        fclose(wm->logFile);
    }
}

This is the output:

from main: 0 0
from ProcIf: 0 0
from WM_SIZE: 0 0
from beginLoop: 0 0
from midLoop:   0 0
from endLoop:   0 66
from beginLoop: 0 66
from midLoop:   0 66
from endLoop:   0 66

Passing wm->hwnd when calling GetMessageW doesn't change anything.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
flotschi
  • 13
  • 3
  • Please [edit] your question and copy&paste the contents of `window_manager.h` and maybe other missing files. If the files do not contain the type `WindowManager`, also add the type definition (or a link to it in case of a standard type). Create a [mre]. – Bodo Aug 08 '23 at 10:50
  • How do the lines allocating "stack" and "buffer" make any sense? What are you trying to do, allocate a 2D array? This is not how that's done. – Lundin Aug 08 '23 at 10:52
  • The lifetime of the `doc` and `pg` variables in `InitWindowManager` expires when the function returns. However, you have stored pointers to those variables in `wm->document` and `wm->document->page` and you are using those pointers after the function has returned, resulting in *undefined behavior* (UB). – Ian Abbott Aug 08 '23 at 11:00

1 Answers1

1

The doc and pg local variables of InitWindowManager are being accessed via pointers after the function returns. The lifetime of the variables has already expired by that point, leading to undefined behavior.

To fix the problem, wm->document and wm->document->page can be pointed to dynamically allocated memory as follows:

    Document* doc = malloc(sizeof(*doc));
    Page* pg = malloc(sizeof(*pg));
    RawPoint** stack = (RawPoint**)malloc(sizeof(RawPoint*));
    RawPoint* buffer = (RawPoint*)malloc(SIZE_OF_BUFFER * sizeof(RawPoint));
    *stack = buffer;

    pg->rawStk = stack;
    pg->rawBfrSize = 0;
    pg->rawStkSize = 0;
    doc->page = pg;
    wm->document = doc;
    wm->actBuffer = buffer;
    wm->actPt = buffer;
    wm->actBfrSize = &pg->rawBfrSize;
    wm->actStkSize = &pg->rawStkSize;
Ian Abbott
  • 15,083
  • 19
  • 33