Reputation: 177
I am thinking if there are handles of the same value ?
To clarify my question, let's say I open Notepad, type in some text, save it and then close Notepad. If I repeat this a thousand times (or even more), will I ever have a chance to see the same window handle (HWND) value being used for the Notepad main window that was used the first time? If so, why?
Upvotes: 10
Views: 6108
Reputation: 569
One of the easiest ways to confirm the answer to this question is to write a program and actually test it. I wrote a program that continuously creates and destroys windows, records the used HWND values, and finally outputs the number of times it takes to obtain repeated HWND values.
104871
323720
65535
110979
65535
65535
65535
96496
65535
65535
120943
65535
65535
65535
65535
65535
105174
71404
65535
203978
67363
106052
211456
159880
103437
114832
94049
65535
244838
In conclusion:
After 65534 windows are created and destroyed, you will have a chance to get duplicate HWND values
The following is my test code. I compiled my program to 32-bit because in 64-bit, for unknown reasons, I sometimes get HWND with high-order dword not being zreo (such as 0xffffffff80230918, 0xffffffff80000e68, 0xffffffff802d0918)
#include <Windows.h>
#include <iostream>
#include <vector>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int main() {
WNDCLASSW wc{
NULL,
WindowProc,
0,
0,
NULL,
NULL,
NULL,
NULL,
NULL,
L"MessageWindowClass"
};
RegisterClassW(&wc);
std::vector<bool> hwndused(0x7FFFFFFF);
std::vector<bool> hwndused2(0x7FFFFFFF);
for (long long count = 1;; ++count) {
HWND hwnd = CreateWindowW(
L"MessageWindowClass",
L"WindowName",
NULL,
NULL,
NULL,
NULL,
NULL,
HWND_MESSAGE,
NULL,
NULL,
NULL
);
if (hwnd == NULL) {
std::cerr << "CreateWindow failed!";
return -1;
}
if ((size_t)hwnd > 0x7FFFFFFF) {
if (hwndused2[(size_t)hwnd - 0x7FFFFFFF]) {
std::cout << count << '\t' << hwnd;
return 0;
}
else {
hwndused2[(size_t)hwnd - 0x7FFFFFFF] = true;
}
}
else {
if (hwndused[(size_t)hwnd]) {
std::cout << count << '\t' << hwnd;
return 0;
}
else {
hwndused[(size_t)hwnd] = true;
}
}
PostMessage(hwnd, WM_CLOSE, NULL, NULL);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
Upvotes: 1
Reputation: 33784
theoretically yes. in practice - the probability of this (in contrast to process and thread id, which is frequently reused) is almost zero.
in current implementation low 16 bits of HWND
used as index in windows handle table - so currently maximum 64K windows can be created. the next 16 bits used as reuse index. when a cell is used for the first time this index is 1.when this cell is reused, the index is increased by 1. and so on. as result for get the same HWND
on window need how minimum 64k windows must be created and destroyed. but this is only in case all this windows will be used the same cell. but we have 64k cells. so real minimum much more higher for this. not exactly 2^32 but big enough.
and even if implementation will changed, i not think that new implementation will make HWND
less unique than current.
Upvotes: 5
Reputation: 72539
By the pigeonhole principal, yes, they can't be unique.
Due to the compatibility with 32-bit processes (WoW64), handles cannot use the entire 64-bits even on 64-bit OS -- think of a 64-bit process passing a handle to a 32-bit child, or getting a handle to a window opened by a 32-bit process. This makes their true space pretty small, and thus reuse very likely.
Upvotes: 2
Reputation: 11878
Yes, window handles are reused.
Documentation to IsWindow
function says:
A thread should not use
IsWindow
for a window that it did not create because the window could be destroyed after this function was called. Further, because window handles are recycled the handle could even point to a different window.
Upvotes: 3
Reputation: 84815
I would advise you to make absolutely no assumptions about handle values.
You shouldn't have to think about concrete handle values for all practical purposes. A handle should be considered an opaque placeholder for something else. You can pass the handle around to refer to something (e.g. a window) without having a reference to the real thing, but you shouldn't ever have to look at the handle itself. The fact that it is a numeric value should be considered an implementation detail, ie. not important (unless maybe you do some kind of low-level systems programming).
That being said, I'd support @jalf's answer: Handle values could get reused. If I had to make any assumption at all about that, I would assume that a handle value could get reused anytime.
Upvotes: 1
Reputation: 248219
Yes. There are only a finite number of values a handle can be represented by, so Windows has to reuse them eventually.
Once a handle is closed, it is gone, you can't do anything with it, it doesn't exist, and you shouldn't even look at it.
And if you subsequently open another handle, then it is possible that Windows will reuse the handle value.
Upvotes: 7