A recent developer update for Windows 10 violated my application code, which uses the Win32 API GetWindowLong ().
Prior to Windows 10 Creator Update, one process (for example, process A) was able to call the GetWindowWord () / GetWindowLong () API in another handle to the process window (for example, process B), even if process B (main thread) was blocked in which Either a system call (for example, waiting for a mutex to exit). In this way, process A was able to request the reserved memory of the window belonging to process B, using these APIs successfully, despite blocking process B.
However, when using the Updater Creator used in Windows 10, process A is blocked when these APIs are called in a window belonging to process B when process B (main thread) is blocked.
I simulated this scenario by creating 2 standalone Win32 applications representing process A and process B. On Windows 10 with Creators Update, the Hanging process is applied when it calls GetWindowLong () / GetWindowWord () in a window belonging to process B, while how process B (main thread) expected a mutex. In other words, calls to GetWindowLong () / GetWindowWord () never returned, causing the process to hang.
However, when I test the same scenario with my stand-alone applications on a Windows 10 system without updating for authors or an earlier version such as Windows 7, the GetWindowLong () / GetWindowWord () API calls in process A return successfully, even when the process B is awaiting the release of the mutex.
To demonstrate the above problem, here is the code for process A and process B. To see the problem, start process A and process B. Then find the window handle to the window of Process B (for example, using Spy ++), and then paste it into the edit box process windows. Then click OK. A message box is displayed displaying the LONG value set in the extra memory of process window B (using SetWindowLong ()). So far, so good. Now go to the process window B and fix it by clicking the "Block" button. This will cause process “B” (the main GUI thread) to wait on the mutex, which will never be released, and therefore process B will hang.
NOW, go back to the process window and click OK again (assuming the edit box still has the same handle to the process window B that you pasted).
NOW, here is the difference in behavior:
In Windows 10 WITHOUT updating for authors and in earlier versions of Windows, such as Windows 7, as before (i.e., when process B did not hang), a message box displaying the LONG value set in the additional memory of window B (with using SetWindowLong ()).
On Windows 10 with the Creators update, process A hangs because the SetWindowLong () call created using the window handle to process B never returns process A to hang.
Pls offers me how to get around this behavior change in Windows 10 Creators Update so that my application does not freeze. Any ideas / help would be greatly appreciated.
Here is the code for process A.
#include <windows.h> #include <stdio.h> #include <commctrl.h> int count = 0; int count1 = 0; TCHAR str[1000]; LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM); HWND g_hwndEdit, g_hwndButton; #define ID_EDIT (3456) #define ID_OK (3457) TCHAR szWinName[] = TEXT("MyWin"); HINSTANCE g_hInst = NULL; int WINAPI WinMain(HINSTANCE hThisInst,HINSTANCE hPrevInst,LPSTR lpszArgs,int nWinMode) { HWND hwnd; MSG msg; WNDCLASSEX wcl; g_hInst = hThisInst; wcl.cbSize = sizeof(WNDCLASSEX); wcl.hInstance = hThisInst; wcl.lpszClassName = szWinName; wcl.lpfnWndProc = WindowFunc; wcl.style = CS_HREDRAW|CS_VREDRAW; wcl.hIcon = LoadIcon(NULL,IDI_APPLICATION); wcl.hIconSm = NULL; wcl.hCursor = LoadCursor(NULL,IDC_ARROW); wcl.lpszMenuName = NULL; wcl.cbClsExtra = 0; wcl.cbWndExtra = 44; wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); if(!RegisterClassEx(&wcl)) return 0; hwnd = CreateWindowEx( WS_EX_WINDOWEDGE, szWinName, "Process A", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, hThisInst, NULL ); ShowWindow(hwnd,nWinMode); UpdateWindow(hwnd); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WindowFunc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { LONG l; HWND hwndOther = hwnd; char s[] = "Paste the window handle (in HEX) of Process B window on which you wish to call GetWindowLong() in the edit field and click on OK."; HDC hdc; PAINTSTRUCT ps; static int cxClient = 0, cyClient = 0; char btnText[1001]; switch(message){ case WM_CREATE: g_hwndEdit = CreateWindow ("edit", NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | ES_LEFT, 200, 200, 200, 200, hwnd, (HMENU)ID_EDIT, g_hInst, NULL) ; g_hwndButton = CreateWindow( "Button", "OK", WS_CHILD|WS_VISIBLE, 500, 200, 150, 50, hwnd, (HMENU)ID_OK, g_hInst, NULL ); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); TextOut(hdc, 10, 100, s, strlen(s)); EndPaint(hwnd, &ps); return 0; case WM_COMMAND: { if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == ID_OK) { GetWindowText(g_hwndEdit, btnText, 1000); sscanf(btnText, "%x", &hwndOther); l = GetWindowLong(hwndOther, 24); sprintf(str, "The LONG value at offset 24 of the window with handle 0x%x is %d.", hwndOther, l); MessageBox(hwnd, str, "", 0); } } break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wParam,lParam); }
And here is the code for process B: