Clipboard Handle Safety

⚠️ WARNING! This document contains critical technical knowledge about safe clipboard handling in Windows C applications. Incorrect assumptions (e.g., that GetClipboardData(CF_TEXT) returns an HGLOBAL) lead to crashes and memory leaks. This content is not suitable for beginners – it requires knowledge of Windows API and handle types. Please read the entire document carefully. All statements are documented and citable.

The following statements are derived from official Microsoft documentation and are essential for developing safe, correct C programs on Windows.

Microsoft Guidelines – Heap vs. Global Functions

“New applications should use heap functions, unless the documentation explicitly states that a global function is required.”

This means:

What does this mean for clipboard reading?

Statement Meaning
Higher Overhead GlobalAlloc and GlobalLock are system-level functions with higher system overhead and are not optimized for all use cases.
Fewer Features Global functions offer fewer features and are less suitable for modern C applications.
New applications → Heap functions Use HeapAlloc / HeapFree for buffer management – this is the recommended approach.

GetClipboardData(CF_TEXT) returns a HANDLE, not an HGLOBAL!

Important correction: The function GetClipboardData(CF_TEXT) returns a HANDLEnot an HGLOBAL!

Official documentation makes no statement about the type of handle returned:

“The GetClipboardData function returns a handle to the data in the clipboard.” → This is a generic handle (e.g., for windows, files, processes). → There is no guarantee that it is an HGLOBAL.

❌ Incorrect assumption: “GetClipboardData(CF_TEXT) always returns an HGLOBAL.” → This is incorrect and dangerous – leads to crashes when applied to invalid handles.

Safe Approach: Validate with GlobalLock

The only safe method to read the clipboard is to attempt GlobalLock and check its return value.

If GlobalLock(hData) returns NULL → the handle is invalid or not suitable for GlobalLock → error.

Final, Safe C Function


char* ReadClipboardText() {
    HANDLE hData = GetClipboardData(CF_TEXT);
    if (!hData) {
        return NULL;
    }

    void* p = GlobalLock(hData);
    if (!p) {
        return NULL;
    }

    char* text = (char*)p;
    DWORD len = strlen(text);
    if (len == 0) {
        GlobalUnlock(hData);
        return NULL;
    }

    HANDLE hHeap = GetProcessHeap();
    void* pBuf = HeapAlloc(hHeap, 0, len + 1);
    if (!pBuf) {
        GlobalUnlock(hData);
        return NULL;
    }

    char* buf = (char*)pBuf;
    memcpy(buf, text, len + 1);

    GlobalUnlock(hData);
    return buf;
}

Conclusion – Clear and Precise

Although new applications should use heap functions, GlobalLock is required to read the clipboard – and Microsoft documentation explicitly supports this case.

Why?

📝 Summary in one sentence: GetClipboardData(CF_TEXT) returns a HANDLE – not automatically an HGLOBAL. There is no guarantee it is a valid global memory handle. The only safe method is to attempt GlobalLock and check for NULL – if it fails, the handle is invalid or not suitable for GlobalLock.”
Source: Microsoft Learn – GetClipboardData