In Windows 7, VS2012 compiler
PostQueuedCompletionStatus(hCompletionPort, 0, (DWORD) pContext, &pOverlap->m_ol);
the above API call is working fine.
But on Windows 10 and VS2017 compiler, member variables in structure of pContext are not accessible.
When we change from DWORD to ULONG_PTR, it is working fine in Windows 10
PostQueuedCompletionStatus(hCompletionPort, 0, (ULONG_PTR) pContext, &pOverlap->m_ol);
What is reason for this behaviour?
Most probably the new build differs not only in Windows version, but you are also compiling for 64 bit, while previously you were compiling for 32 bit.
Update: OP has clarified that both builds are 64 bit, but this is easily explained; see below.
That cast to DWORD is conceptually wrong even on Windows 7/32 bit. Indeed, the API definition requires a ULONG_PTR, which is an unsigned integer type big enough to hold a pointer with no loss of data. As such, it's a 32 bit type when compiling for 32 bit, 64 bit when compiling for 64 bit.
Instead, you are casting your pointer to a DWORD; DWORD is always a 32 bit unsigned type, so when building for 32 bit Windows everything goes smoothly (pointers need no more than 32 bit to arrive intact on the other side), but on 64 bit Windows you are losing the top 32 bit of your pointer.
Now, this happens to work even on 64 bit Windows 7; why?
As explained in the comments, this pointer comes from the heap, and by default on Windows 7 the heap starts providing memory from the "low" portion of the 64 bit address space; hence, unless you are consuming lots of memory, you are going to get always addresses with the top 32 bits to zero, so they are going to survive even with the top 32 bits chopped off.
This changed since Windows 8, as ASLR (enabled by default by the linker when building 64 bit executables) randomizes the position of the heap in the virtual address space, which means that you are going to get pointers with non-zero upper 32 bits, that are going to be maimed badly by the cast to DWORD.
Long story short: fix your cast1 and everything will work fine. Also, in future be always wary of casts from a pointer to an integral type that doesn't end with _ptr or _PTR - there are good chances that you are doing a mistake.
Notes
void * for these casts to work correctly, i.e. the roundtrip through uintptr_t is guaranteed only for void * (and maybe char *? I'll have to check the standard), so it should be (ULONG_PTR)(LPVOID)pContext, if pContext isn't a void * already. However, this being Win32 I'm pretty sure it's guaranteed to work even without the extra cast. If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With