Holy cow, I wrote a book!
The window manager provides a pointer-sized chunk of storage you can access via the GWLP_USERDATA constant. You pass it to the GetWindowLongPtr function and the SetWindowLongPtr function to read and write that value. Most of the time, all you need to attach to a window is a single pointer value anyway, so the free memory in GWLP_USERDATA is all you need.
GWLP_USERDATA
GetWindowLongPtr
SetWindowLongPtr
Note that this value, like the other window extra bytes and the messages in the WM_USER range, belongs to the window class and not to the code that creates the window.
WM_USER