2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-19 14:22:10 +00:00

Merge dialog box closing fixes

[SVN r34537]
This commit is contained in:
Vladimir Prus
2006-07-15 05:56:54 +00:00
parent a5eef8bde8
commit 956a67940b

View File

@@ -1002,6 +1002,8 @@ int is_parent_child(DWORD parent, DWORD child)
{
HANDLE process_snapshot_h = INVALID_HANDLE_VALUE;
if (!child)
return 0;
if (parent == child)
return 1;
@@ -1016,8 +1018,37 @@ int is_parent_child(DWORD parent, DWORD child)
ok == TRUE;
ok = Process32Next(process_snapshot_h, &pinfo) )
{
if (pinfo.th32ProcessID == child && pinfo.th32ParentProcessID)
if (pinfo.th32ProcessID == child)
{
CloseHandle(process_snapshot_h);
if (!stricmp(pinfo.szExeFile, "explorer.exe"))
{
/* explorer.exe is orphaned and process_id of its parent may
accidentally match process_id of process we are after. We must not
close dialog boxes displayed by children of explorer.exe even
though (thanks to its parent process id) it might appear to be
our child. This is not very reliable - there might be more
orphaned processes or shell might be something else than
explorer.exe, but this is most common and important scenario */
return 0;
}
if (!stricmp(pinfo.szExeFile, "csrss.exe"))
{
/* csrss.exe may display message box like following:
xyz.exe - Unable To Locate Component
This application has failed to start because boost_foo-bar.dll
was not found. Re-installing the application may fix the problem
This actually happens when starting test process that depends on
dynamic library which failed to build. We want to automatically
close these message boxes even though csrss.exe is not our
child process. We may depend on the fact that (in all current
versions of Windows) csrss.exe is indirectly child of System which
always has process id == 4 */
if (is_parent_child(4, pinfo.th32ParentProcessID))
return 1;
}
return is_parent_child(parent, pinfo.th32ParentProcessID);
}
}
CloseHandle(process_snapshot_h);
@@ -1026,28 +1057,44 @@ int is_parent_child(DWORD parent, DWORD child)
return 0;
}
int related(HANDLE h, DWORD p)
int related(DWORD d, DWORD p)
{
return is_parent_child(get_process_id(h), p);
return is_parent_child(d, p);
}
typedef struct PROCESS_HANDLE_ID {HANDLE h; DWORD pid;} PROCESS_HANDLE_ID;
BOOL CALLBACK window_enum(HWND hwnd, LPARAM lParam)
{
char buf[10] = {0};
HANDLE h = *((HANDLE*) (lParam));
char buf[7] = {0};
PROCESS_HANDLE_ID p = *((PROCESS_HANDLE_ID*) (lParam));
DWORD pid = 0;
DWORD tid = 0;
if (!GetClassNameA(hwnd, buf, 10))
return TRUE; // failed to read class name
if (!IsWindowVisible(hwnd))
return TRUE;
if (!GetClassNameA(hwnd, buf, 7))
return TRUE; /* failed to read class name; presume it's not a dialog */
if (strcmp(buf, "#32770"))
return TRUE; // not a dialog
return TRUE; /* not a dialog */
GetWindowThreadProcessId(hwnd, &pid);
if (related(h, pid))
tid = GetWindowThreadProcessId(hwnd, &pid);
if (tid && related(p.pid, pid))
{
PostMessage(hwnd, WM_QUIT, 0, 0);
// just one window at a time
/* ask really nice */
PostMessageA(hwnd, WM_CLOSE, 0, 0);
/* now wait and see if it worked. If not, insist */
if (WaitForSingleObject(p.h, 200) == WAIT_TIMEOUT)
{
PostThreadMessageA(tid, WM_QUIT, 0, 0);
if (WaitForSingleObject(p.h, 500) == WAIT_TIMEOUT)
{
PostThreadMessageA(tid, WM_QUIT, 0, 0);
WaitForSingleObject(p.h, 500);
}
}
return FALSE;
}
@@ -1056,7 +1103,13 @@ BOOL CALLBACK window_enum(HWND hwnd, LPARAM lParam)
void close_alert(HANDLE process)
{
EnumWindows(&window_enum, (LPARAM) &process);
DWORD pid = get_process_id(process);
/* If process already exited or we just cannot get its process id, do not go any further */
if (pid)
{
PROCESS_HANDLE_ID p = {process, pid};
EnumWindows(&window_enum, (LPARAM) &p);
}
}
static int
@@ -1094,9 +1147,10 @@ my_wait( int *status )
if ( globs.timeout > 0 )
{
unsigned int alert_wait = 1;
/* with a timeout we wait for a finish or a timeout, we check every second
to see if something timed out */
for (waitcode = WAIT_TIMEOUT; waitcode == WAIT_TIMEOUT;)
for (waitcode = WAIT_TIMEOUT; waitcode == WAIT_TIMEOUT; ++alert_wait)
{
waitcode = WaitForMultipleObjects( num_active, active_handles, FALSE, 1*1000 /* 1 second */ );
if ( waitcode == WAIT_TIMEOUT )
@@ -1105,10 +1159,15 @@ my_wait( int *status )
for ( i = 0; i < num_active; ++i )
{
double t = running_time(active_handles[i]);
/* periodically (each 5 secs) review and close alert dialogs hanging around */
if ((alert_wait % ((unsigned int) 5)) == 0)
close_alert(active_handles[i]);
if ( t > (double)globs.timeout )
{
/* the job may have left an alert dialog around,
try and get rid of it before killing */
try and get rid of it before killing */
close_alert(active_handles[i]);
/* we have a "runaway" job, kill it */
kill_all(0,active_handles[i]);