информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Атака на InternetSpanning Tree Protocol: недокументированное применениеГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 700 с лишним git-серверов пострадало... 
 От повторного пришествия Шаи-Хулуда... 
 Крупный сбой Azure и других сервисов... 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[Win32] Виндос программеры - рассудите спор 13.02.02 17:55  
Автор: PS <PS> Статус: Elderman
Отредактировано 13.02.02 17:55  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
С коллегами спор возник.
Есть алгоритм:
1.Создаем окно
2.Запоминаем его hwnd
3.тра ля ля
4.закрываем окно по запомненому hwnd

Они утверждают, что алгоритм валиден. Я же говорю, что во время тра ла ла пользователь может закрыть окно, открыть какое нибудь другое и (внимание!) виндос даст новому окну тот же hwnd ! И тогда в п.4 мы закроем совсем не то окно какое следует.

Кто прав ?
[Win32] Обратимся к истокам 16.02.02 12:42  
Автор: 1blin Статус: Незарегистрированный пользователь
<"чистая" ссылка> <обсуждение закрыто>
Platform SDK: Windows User Interface
IsWindow:

Remarks
An application 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.
[Win32] А алгоритм тем не менее валиден (в рамках области процесса)... 16.02.02 20:40  
Автор: LiNX Статус: Незарегистрированный пользователь
<"чистая" ссылка> <обсуждение закрыто>
А по русски ? 17.02.02 22:35  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
В смысле в чем валидность ?
Этажем выше сказано было как раз то на чам я настаивал, - повторяться будут - закроем другое. Нет, зря я на пиво не спорил :)
резюме всего 17.02.02 22:57  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
рассмотрим два понимания ВАЛИДНОСТИ: теоретическую и практическую
теоретически алгоритм ИНВАЛИДЕН в принципе
чтобы не тратить попусту время приведу тестовую прожку,
доказывающую теоретическую ИНВАЛИДНОСТЬ алгоритма
--------------------------------- test.cpp ------------------------------
#include <windows.h>
#include <stdio.h>
#include "test.h"

HINSTANCE Instance;

HWND MainWindow;

HWND TestCreateWindow(void); // форвард
HWND CreateAnotherWindow(void); // форвард

char TestWNDCLASSName [] = "Test WNDCLASS name";
WNDCLASS TestWNDCLASS;
char TestWindowTitle [] = "Test window";

char AnotherWNDCLASSName [] = "Some WNDCLASS name";
WNDCLASS AnotherWNDCLASS;
char AnotherWindowTitle [] = "Some another window";

long WINAPI CALLBACK MainWindowProc
(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
HWND HWNDSavedByCoder;
switch (msg)
{
case WM_COMMAND:
{
switch (wParam)
{
case MWM_FILE_EXIT:
{
PostQuitMessage(0);
return 0;
}
case MWM_ACTION_TEST1_CREATEWINDOW:
{
// 1.Создаем окно
HWNDSavedByCoder = TestCreateWindow();
// 2.Запоминаем его hwnd
if (NULL != HWNDSavedByCoder)
{
// 3.тра ля ля
MessageBox(hWnd, "Please close manually [TEST WINDOW] and press OK to continue", "Your action here", MB_OK);
FILE* file = fopen("test.log", "wb");
fprintf(file,"HWNDSavedByCoder = %x\n", HWNDSavedByCoder);
for (;;)
{
HWND tempHWND = CreateAnotherWindow();
fprintf(file,"tempHWND = %x\n", tempHWND);
if (HWNDSavedByCoder == tempHWND)
{
MessageBox(tempHWND, "This really innocent window will now be destroyed", "look!", MB_OK);
break;
}
fflush(file);
}
// 4.закрываем окно по запомненому hwnd
DestroyWindow(HWNDSavedByCoder);
fclose(file);
Sleep(1000);
for(;;)
{
HWND tempHWND = GetForegroundWindow();
if (tempHWND == MainWindow) break;
DestroyWindow(tempHWND);
}
}
break;
}
case MWM_ACTION_TEST2_CREATEWINDOW:
{
// 1.Создаем окно
HWNDSavedByCoder = TestCreateWindow();
// 2.Запоминаем его hwnd
if (NULL != HWNDSavedByCoder)
{
// 3.тра ля ля
MessageBox(hWnd, "Please close manually [TEST WINDOW] and press OK to continue", "Your action here", MB_OK);
FILE* file = fopen("test.log", "wb");
fprintf(file,"HWNDSavedByCoder = %x\n", HWNDSavedByCoder);
for (;;)
{
HWND tempHWND = CreateAnotherWindow();
fprintf(file,"tempHWND = %x\n", tempHWND);
if (HWNDSavedByCoder == tempHWND)
{
MessageBox(tempHWND, "This really innocent window will now be destroyed", "look!", MB_OK);
break;
}
DestroyWindow(tempHWND);
fflush(file);
}
// 4.закрываем окно по запомненому hwnd
DestroyWindow(HWNDSavedByCoder);
fclose(file);
}
break;
}
case MWM_HELP_ABOUT:
{
MessageBox(hWnd, "www.BugTraq.ru/forum\ntest proggy by [z0]", "About", MB_OK);
break;
}
}
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}

long WINAPI CALLBACK DummyWindowProc
(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain
(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
Instance = hInstance;

char SomeWNDCLASSName [] = "Main WNDCLASS name";
WNDCLASS SomeWNDCLASS;

char MainWindowTitle [] = "Main window";

SomeWNDCLASS.style = CS_HREDRAW | CS_VREDRAW;
SomeWNDCLASS.lpfnWndProc = MainWindowProc;
SomeWNDCLASS.cbClsExtra = 0;
SomeWNDCLASS.cbWndExtra = 0;
SomeWNDCLASS.hInstance = Instance;
SomeWNDCLASS.hIcon = NULL;
SomeWNDCLASS.hCursor = NULL;
SomeWNDCLASS.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
SomeWNDCLASS.lpszMenuName = "MainWindowMenu";
SomeWNDCLASS.lpszClassName = SomeWNDCLASSName;

if ( !RegisterClass(&SomeWNDCLASS) )
{
MessageBox(NULL, "RegisterClass(&SomeWNDCLASS) failed", "Error!", MB_OK);
return FALSE;
}

TestWNDCLASS.style = CS_HREDRAW | CS_VREDRAW;
TestWNDCLASS.lpfnWndProc = DummyWindowProc;
TestWNDCLASS.cbClsExtra = 0;
TestWNDCLASS.cbWndExtra = 0;
TestWNDCLASS.hInstance = Instance;
TestWNDCLASS.hIcon = NULL;
TestWNDCLASS.hCursor = NULL;
TestWNDCLASS.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
TestWNDCLASS.lpszMenuName = NULL;
TestWNDCLASS.lpszClassName = TestWNDCLASSName;

if ( !RegisterClass(&TestWNDCLASS) )
{
MessageBox(NULL, "RegisterClass(&TestWNDCLASS) failed", "Error!", MB_OK);
return FALSE;
}

AnotherWNDCLASS.style = CS_HREDRAW | CS_VREDRAW;
AnotherWNDCLASS.lpfnWndProc = DummyWindowProc;
AnotherWNDCLASS.cbClsExtra = 0;
AnotherWNDCLASS.cbWndExtra = 0;
AnotherWNDCLASS.hInstance = Instance;
AnotherWNDCLASS.hIcon = NULL;
AnotherWNDCLASS.hCursor = NULL;
AnotherWNDCLASS.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
AnotherWNDCLASS.lpszMenuName = NULL;
AnotherWNDCLASS.lpszClassName = AnotherWNDCLASSName;

if ( !RegisterClass(&AnotherWNDCLASS) )
{
MessageBox(NULL, "RegisterClass(&AnotherWNDCLASS) failed", "Error!", MB_OK);
return FALSE;
}

MainWindow = CreateWindow
(
SomeWNDCLASSName,
MainWindowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
Instance,
0
);
if ( !MainWindow )
{
MessageBox(NULL, "CreateWindow() failed", "Error!", MB_OK);
return FALSE;
}

ShowWindow(MainWindow, nCmdShow);
UpdateWindow(MainWindow);

MSG msg;
while ( GetMessage(&msg, 0, 0, 0) )
{
DispatchMessage(&msg);
}

return TRUE;
}

HWND TestCreateWindow(void)
{
HWND TestWindow = CreateWindow
(
TestWNDCLASSName,
TestWindowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
Instance,
0
);
if ( !TestWindow )
{
return NULL;
}

ShowWindow(TestWindow, SW_SHOWNORMAL);
UpdateWindow(TestWindow);

return TestWindow;
}

HWND CreateAnotherWindow(void)
{
HWND AnotherWindow = CreateWindow
(
AnotherWNDCLASSName,
AnotherWindowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
Instance,
0
);
if ( !AnotherWindow )
{
return NULL;
}

ShowWindow(AnotherWindow, SW_SHOWNORMAL);
UpdateWindow(AnotherWindow);

return AnotherWindow;
}
---------------------------------- test.rc ----------------------------
#include <windows.h>
#include "test.h"

MainWindowMenu MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit" MWM_FILE_EXIT
END
POPUP "&Action"
BEGIN
MENUITEM "Test CreateWindow() &1" MWM_ACTION_TEST1_CREATEWINDOW
MENUITEM "Test CreateWindow() &2" MWM_ACTION_TEST2_CREATEWINDOW
END
POPUP "&Help"
BEGIN
MENUITEM "&About" MWM_HELP_ABOUT
END
END
------------------------------------ test.h -----------------------------
#define MWM_FILE_EXIT 0x0301
#define MWM_ACTION_TEST1_CREATEWINDOW 0x0401
#define MWM_ACTION_TEST2_CREATEWINDOW 0x0402
#define MWM_HELP_ABOUT 0x0501
-------------------------------------------------------------------------

результат работы данной прожки можно считать резюмой топика:
1) для win9x оба теста дают быстрый предсказанный результат -
повторяется использование хендла и закрывается НЕ ТО окно
2) при разработке NT-шной USER32.DLL эта ошибка видимо была учтена
добавлением случайного числа в старшее слово HWND и учете значения
этого слова при дальнейшей работе с HWND
я не дождался завала под NT4 - видимо практическая валидность под
этой системой высока

конкретную практическую валидность считайте для себя сами

зы: можно еще вспомнить такую штуку как PID - тоже ведь recycled и
reused и не где-нибудь а в хороших юниксах типа netBSD, Solaris etc.
программеры конечное же исходят из практической валидности числа
но надо только правильно ее оценивать
[Win32] Виндос программеры - рассудите спор 15.02.02 14:43  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
> С коллегами спор возник.
> Есть алгоритм:
> 1.Создаем окно
> 2.Запоминаем его hwnd
> 3.тра ля ля
> 4.закрываем окно по запомненому hwnd
>
> Они утверждают, что алгоритм валиден. Я же говорю, что во
> время тра ла ла пользователь может закрыть окно, открыть
> какое нибудь другое и (внимание!) виндос даст новому окну
> тот же hwnd ! И тогда в п.4 мы закроем совсем не то окно
> какое следует.
>
> Кто прав ?

нет не копались твои коллеги в виндах не понимают их специфики
линейные алгоритмы при работе с виндовс апи надо исключить напрочь
и кстати сами винды даже в ядре работают не по линейным а по спагетти-алгоритмам
в любой книжонке по программированию на первом же "хелло винды" видно как надо это делать:
1.создаем окно и прочую инициализацию проводим
2.входим в цикл обработки сообщений
и дальше все равно кто и как окно закроет - мышою, альт-ф4 или closewindow
там только написано что-то типа "смотрите как теперь удобно и просто стало" а надо было так сказать - "и попробуйте только по-другому..."

забавно что чем проще вещь тем труднее доходит
а вот отход от этого способа уже не забавен - действительно ведь не то окно совсем закроется

зы: ну конечно это не везде так - файловые операции например подчиняются линейности и хендлы там локальные
но в большинстве... все же это оболочка дешевая...
[Win32] Виндос программеры - рассудите спор 14.02.02 00:23  
Автор: ih8u <i hate you> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
када приходит @#$%ец окну - HWND тоже приходит @#$%ец!
если такое случилось, то нихуя работать не будет,
чего тут не ясного!!
[Win32] Виндос программеры - рассудите спор 15.02.02 14:52  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
> када приходит @#$%ец окну - HWND тоже приходит @#$%ец!
> если такое случилось, то нихуя работать не будет,
> чего тут не ясного!!

ну @#$%ец окну это допустим еще можно понять
а вот @#$%ец номеру записи в таблице окошек - честно скажу - не ясно
объяснишь?
[Win32] Виндос программеры - рассудите спор 17.02.02 12:45  
Автор: ih8u <i hate you> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
мля, когда окно умирает, HWND не будет принадлежать к какому либо окну, соответсвенно ты не сможешь его использовать, например, в SendMessage
[Win32] Виндос программеры - рассудите спор 13.02.02 22:24  
Автор: + <Mikhail> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> С коллегами спор возник.
> Есть алгоритм:
> 1.Создаем окно
> 2.Запоминаем его hwnd
> 3.тра ля ля
> 4.закрываем окно по запомненому hwnd
>
> Они утверждают, что алгоритм валиден. Я же говорю, что во
> время тра ла ла пользователь может закрыть окно, открыть
> какое нибудь другое и (внимание!) виндос даст новому окну
> тот же hwnd ! И тогда в п.4 мы закроем совсем не то окно
> какое следует.
>
> Кто прав ?
I dumau chto kollegi pravy:
Tak kak window handle global , to kogda okno destroyed eta handle invalid i tolko odin sposob dlia drugogo processa uznat` valid ili ne valid handle ispolzua IsWindow(hwnd). i esli pri sozdanii drugogo window mozhet ispolzovat`sia starai handle togda teriaetsia integriti WIndows.
Predstav` situaciu neskolko raznyh threads rabotaut s odnoi i toi zhe window, i esli Windows bydut recycle window handle togda bolshaia veroiatnost` chto chasto windows bydut putatsia, chego ne proishodit (mozhesh napisat` test application chtoby ubeditsia)
Я не в чем не ошибся ? 14.02.02 00:14  
Автор: PS <PS> Статус: Elderman
Отредактировано 14.02.02 00:15  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> I dumau chto kollegi pravy:
> Tak kak window handle global , to kogda okno destroyed eta
> handle invalid i tolko odin sposob dlia drugogo processa
> uznat` valid ili ne valid handle ispolzua IsWindow(hwnd).
> i esli pri sozdanii drugogo window mozhet ispolzovat`sia
> starai handle togda teriaetsia integriti WIndows.
> Predstav` situaciu neskolko raznyh threads rabotaut s odnoi
> i toi zhe window, i esli Windows bydut recycle window
> handle togda bolshaia veroiatnost` chto chasto windows
> bydut putatsia, chego ne proishodit (mozhesh napisat` test
> application chtoby ubeditsia)

Допустим одно окно создается за секунду. Тогда ((2^32)/60)/60 = 1193046 часов, Это 138 лет. Уменьшим создания окна с секунды. до 10мс, Тогда что бы выбрать все hwnd нам потребуется всего лишь год. Т.е. через год hwnd начнут повторяться... что-то многова-то...
Мда... вот что значит спорить не на трезвую голову. Хорошо хоть не на пиво.... :)
Windows 9X: The system can support a maximum of 16,364 window handles. 15.02.02 15:23  
Автор: z0 <z0> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Там не 2^32, а много меньше 14.02.02 11:10  
Автор: ukv Статус: Незарегистрированный пользователь
<"чистая" ссылка> <обсуждение закрыто>
> Допустим одно окно создается за секунду. Тогда
> ((2^32)/60)/60 = 1193046 часов, Это 138 лет. Уменьшим
> создания окна с секунды. до 10мс, Тогда что бы выбрать все
> hwnd нам потребуется всего лишь год.

Не помню точно, но на 2^16 по-моему расчитывать можно, а больше - зависит от системы. Но 2^32 - и близко не будет.
Правильное решение - поставить hook на это окно и отслеживать его закрытие. Еще проще было бы получить нотификацию при закрытии окна, но по-моему нотификации идут только в parent.
2^16 14.02.02 11:56  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Это 18 минут... значит я был прав. А правильно уже не сделаешь... Это огромный проект - фиг перепишишь. Остаеться только плеваться.
А по-моему хендёл у окна пожизненный 15.02.02 04:20  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
Во первых: тот же Spy идентифицирует окна хендлами и я еще не замечал, чтобы в процессе жизни они менялись.
Во вторых: цикл обработки сообщений идентифицирует окна-адресаты по хендлам, и эти хендлы - СТАТИК.
В третьих: я где - то (чуть ли не у Питтрека) читал, что 2^16 хендлов - это мало, и я сам, похоже сталкивался с такой ситуацией: если какой-нит сайт начинает сыпать новые окна, как из пулемета - винда падает.
Я не в чем не ошибся ? 14.02.02 01:35  
Автор: Sandy <Alexander Stepanov> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> Допустим одно окно создается за секунду. Тогда
> ((2^32)/60)/60 = 1193046 часов, Это 138 лет. Уменьшим
> создания окна с секунды. до 10мс, Тогда что бы выбрать все
> hwnd нам потребуется всего лишь год. Т.е. через год hwnd
> начнут повторяться... что-то многова-то...
> Мда... вот что значит спорить не на трезвую голову. Хорошо
> хоть не на пиво.... :)

Насколько я помню, хэндл (любой) - это смещение. Т.е., хэндл окна - смещение в таблице, описывающей ВСЕ имеющиеся окна в системе. На мой взгляд, нет ничего невозможного в ситуации, когда РАЗНЫМ окнам, существующим в РАЗНОЕ время, присваивается один и тот же хэндл.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2025 Dmitry Leonov   Page build time: 1 s   Design: Vadim Derkach