News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Dialog box programming considerations

Started by kkurkiewicz, October 23, 2023, 02:18:34 AM

Previous topic - Next topic

Vortex

#30
Hi NoCforMe,

Quoteand no need to lock memory or other such nonsense:

QuoteIf SetClipboardData succeeds, the system owns the object identified by the hMem parameter. The application may not write to or free the data once ownership has been transferred to the system, but it can lock and read from the data until the CloseClipboard function is called. (The memory must be unlocked before the Clipboard is closed.) If the hMem parameter identifies a memory object, the object must have been allocated using the function with the GMEM_MOVEABLE flag.

https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclipboarddata

https://learn.microsoft.com/en-us/windows/win32/dataxchg/using-the-clipboard


NoCforMe

Look, all I can tell you is that my method has been working fine for me for years and has no ill effects on the operation of the clipboard at all. We all know that Micro$oft documentation is notoriously confused, deficient and, in some case, just plain wrong.

Like I said, try it and see what your results are. I'd be curious to hear what you find.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on October 27, 2023, 07:40:05 AMtry it and see what your results are

To test that, you would need a setup where one program uses your method fifty-thousand times, while another program clears the clipboard immediately after. Of course, you will have no problems if you do that only a few times...

You are touching a global resource here. Yes, GlobalAlloc uses eventually the heap, but it does some tricks there. I don't know the details, but probably the OS keeps a global table where it stores the heap handles. By using GlobalFree for a heapalloc'ed block, you are bypassing that global table. Maybe it will be full after a while, who knows?

Vortex

#33
Locking the memory portion has a meaning, it protects the data and makes it consistent. The official example of MS :

// Allocate a global memory object for the text.
 
        hglbCopy = GlobalAlloc(GMEM_MOVEABLE,
            (cch + 1) * sizeof(TCHAR));
        if (hglbCopy == NULL)
        {
            CloseClipboard();
            return FALSE;
        }
 
        // Lock the handle and copy the text to the buffer.
 
        lptstrCopy = GlobalLock(hglbCopy);
        memcpy(lptstrCopy, &pbox->atchLabel[ich1],
            cch * sizeof(TCHAR));
        lptstrCopy[cch] = (TCHAR) 0;    // null character
        GlobalUnlock(hglbCopy);
 
        // Place the handle on the clipboard.
 
        SetClipboardData(CF_TEXT, hglbCopy);

https://learn.microsoft.com/en-us/windows/win32/dataxchg/using-the-clipboard

You can ask ChatCPT.

me :

QuoteIn windows programming, why do I need a locked memory area while dealing with clipboard functions?

ChatGPT :

QuoteIn Windows programming, when working with clipboard functions, you may need to use locked memory for a couple of reasons:

Data Transfer Between Processes: The Windows Clipboard is used for transferring data between different processes or applications. When you copy data to the clipboard in one application and paste it into another, the data needs to be accessible to both processes. Locked memory ensures that the data remains in a consistent memory location so that it can be shared and accessed by both processes.

Data Format Stability: When you place data on the clipboard, it needs to remain in a stable format until it's pasted. This means that the data should not be moved or altered in any way. Locking the memory prevents the operating system or other processes from moving or modifying the data while it's on the clipboard. This ensures that the pasted data retains its integrity and format.

To accomplish these goals, Windows provides functions like GlobalAlloc, GlobalLock, GlobalUnlock, and related functions to allocate and lock memory for clipboard data. These functions allocate memory from the global heap and lock it in place, making it accessible and stable for clipboard operations.

Here's a typical sequence of steps for using locked memory with clipboard functions in Windows:

Allocate memory using GlobalAlloc or another appropriate function.
Lock the allocated memory with GlobalLock.
Copy or write your data into the locked memory.
Place the locked memory on the clipboard using clipboard functions like SetClipboardData.
When you're done with the clipboard data, unlock the memory using GlobalUnlock.
By following this process, you ensure that the data is locked in a stable memory area, making it safe and consistent for clipboard operations between different processes and across the clipboard's various data formats.

NoCforMe

Quote from: jj2007 on October 27, 2023, 07:43:57 AM
Quote from: NoCforMe on October 27, 2023, 07:40:05 AMtry it and see what your results are

To test that, you would need a setup where one program uses your method fifty-thousand times, while another program clears the clipboard immediately after.

Well, Jochen, nobody's stopping you from doing just that. I know with your super-duper IDE you could probably whip up a test like that in a short time. Might vindicate me, or might reveal that I'm slowly corrupting the OS by playing fast and loose with global memory ...
Assembly language programming should be fun. That's why I do it.

Vortex

Hi NoCforMe,

Nobody is trying to vindicate or hurt you. Jochen is trying to explain the importance of respecting the documentation provided by the OS manufacturer. M$ may be not perfect and the documentation may be not perfect too. They write millions line of code and probably there are reasons why to follow the documentation. It's all simple, the text tells that you must provide secure and reliable data while manipulating the clipboard.

NoCforMe

Don't worry, no hurt feelings here either way. What I do works for me, so I ain't worrying about it. (I probably wouldn't suggest that anyone use my code in their production application.) I'd be mildly curious to see if such a test would vindicate me or not, but beyond that I'm not losing any sleep over this.
Assembly language programming should be fun. That's why I do it.

Greenhorn

#37
Read the manual, it's as simple as that.

https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalalloc

QuoteNote  The global functions have greater overhead and provide fewer features than other memory management functions. New applications should use the heap functions unless documentation states that a global function should be used. For more information, see Global and Local Functions.

Quote[...]
The movable-memory flags GHND and GMEM_MOVABLE add unnecessary overhead and require locking to be used safely. They should be avoided unless documentation specifically states that they should be used.

New applications should use the heap functions to allocate and manage memory unless the documentation specifically states that a global function should be used. For example, the global functions are still used with Dynamic Data Exchange (DDE), the clipboard functions, and OLE data objects.
[...]
Kole Feut un Nordenwind gift en krusen Büdel un en lütten Pint.

zedd

Be nice, guys... this IS the Campus.  :smiley:
NoCforMe, I sent you a PM.

adeyblue

It'll work competely fine in NT windows until such time as HeapHandle is not GetProcessHeap, then it'll crash.

NoCforMe

Can you please clarify that a bit? Not sure what you're saying here.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: adeyblue on October 27, 2023, 02:30:03 PMIt'll work competely fine in NT windows until such time as HeapHandle is not GetProcessHeap, then it'll crash.

Hi adeyblue, nice to see you :thumbsup:
I recently re-discovered your zip post - great stuff.

Here is a little test:
include \masm32\include\masm32rt.inc

.code
start:
  xor ebx, ebx
  .Repeat
    inc ebx
    print str$(ebx), " "
    invoke HeapAlloc, rv(GetProcessHeap), 0, 100000
    invoke GlobalFree, eax
    .if rv(GetLastError)
        print " error", 13, 10
    .endif
  .Until ebx>99
  MsgBox 0, "ok", "Hi", MB_OK
  exit
end start

That works fine, so the OS has no problems to free heap memory using GlobalFree. However, as mentioned above, there might be a global table (pun intended) where it keeps track of GlobalAlloc memory. So, if you do the trick a Million times, it's not clear what can happen. And of course, it's not documented :cool:

Quote from: jj2007 on October 27, 2023, 07:43:57 AMyou would need a setup where one program uses your method fifty-thousand times, while another program clears the clipboard immediately after. Of course, you will have no problems if you do that only a few times...

You are touching a global resource here. Yes, GlobalAlloc uses eventually the heap, but it does some tricks there. I don't know the details, but probably the OS keeps a global table where it stores the heap handles. By using GlobalFree for a heapalloc'ed block, you are bypassing that global table. Maybe it will be full after a while, who knows?

jj2007

Quote from: NoCforMe on October 27, 2023, 03:11:30 PMCan you please clarify that a bit? Not sure what you're saying here.

QuoteMore on the Global Heap Manager
      To allocate memory directly from the global heap, Windows 3.0-based programs called the GlobalAlloc API. GlobalAlloc still exists in Win32, but only to ease porting of Win16 code. Under the hood, GlobalAlloc is just a layer over the same heap manager used by HeapAlloc, which allocates memory visible only to the calling process. Thus, GlobalAlloc memory in Win32 is local to its allocating process, and not really global.

NoCforMe

So if I read that last part correctly, doesn't that make what I'm doing (using HeapAlloc() ) OK? No matter what else they (MS) say you need to do to use the clipboard?
Assembly language programming should be fun. That's why I do it.

jj2007

The only thing that is clear is that nothing is clear: it's not documented. The clipboard is information exchanged between processes, not within one process. So it must use some global resource (same for SendMessage to other processes btw).