You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
362 lines
8.5 KiB
362 lines
8.5 KiB
/* Copyright (c) 1996, Microsoft Corporation, all rights reserved
|
|
**
|
|
** wait.c
|
|
** Waiting for services popup
|
|
** Listed alphabetically
|
|
**
|
|
** 02/17/96 Steve Cobb
|
|
*/
|
|
|
|
#include <windows.h> // Win32 root
|
|
#include <debug.h> // Trace and assert
|
|
#include <nouiutil.h> // No-HWND utilities
|
|
#include <uiutil.h> // Our public header
|
|
#include <wait.rch> // Our resource constants
|
|
|
|
/* Set when RasLoad has completed successfully in this process context.
|
|
*/
|
|
BOOL g_fRasLoaded = FALSE;
|
|
|
|
|
|
/* Waiting for services thread argument block.
|
|
*/
|
|
#define WSARGS struct tagWSARGS
|
|
WSARGS
|
|
{
|
|
HINSTANCE hInst;
|
|
HWND hwndOwner;
|
|
HANDLE hEventUp;
|
|
HANDLE hEventDie;
|
|
};
|
|
|
|
/* Waiting for services thread context.
|
|
*/
|
|
#define WSINFO struct tagWSINFO
|
|
WSINFO
|
|
{
|
|
HANDLE hEventDie;
|
|
DWORD dwThreadId;
|
|
HICON hIcon;
|
|
};
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** Local prototypes
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
VOID
|
|
StartWaitingForServices(
|
|
HINSTANCE hInst,
|
|
HWND hwndOwner,
|
|
WSINFO* pInfo );
|
|
|
|
VOID
|
|
StopWaitingForServices(
|
|
IN WSINFO* pInfo );
|
|
|
|
DWORD
|
|
WsThread(
|
|
LPVOID pArg );
|
|
|
|
INT_PTR CALLBACK
|
|
WsDlgProc(
|
|
HWND hwnd,
|
|
UINT unMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam );
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** Routines
|
|
**----------------------------------------------------------------------------
|
|
*/
|
|
|
|
DWORD
|
|
LoadRas(
|
|
IN HINSTANCE hInst,
|
|
IN HWND hwnd )
|
|
|
|
/* Starts the RASMAN service and loads the RASMAN and RASAPI32 entrypoint
|
|
** addresses. The "waiting for services" popup is displayed, if
|
|
** indicated. 'HInst' and 'hwnd' are the owning instance and window.
|
|
**
|
|
** Returns 0 if successful or an error code.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
WSINFO info;
|
|
|
|
TRACE("LoadRas");
|
|
|
|
ZeroMemory(&info, sizeof(WSINFO));
|
|
if (g_fRasLoaded)
|
|
dwErr = 0;
|
|
else
|
|
{
|
|
if (IsRasmanServiceRunning())
|
|
info.hEventDie = NULL;
|
|
else
|
|
StartWaitingForServices( hInst, hwnd, &info );
|
|
|
|
dwErr = LoadRasapi32Dll();
|
|
if (dwErr == 0)
|
|
{
|
|
dwErr = LoadRasmanDll();
|
|
if (dwErr == 0)
|
|
{
|
|
ASSERT(g_pRasInitialize);
|
|
TRACE("RasInitialize");
|
|
dwErr = g_pRasInitialize();
|
|
TRACE1("RasInitialize=%d",dwErr);
|
|
}
|
|
}
|
|
|
|
StopWaitingForServices( &info );
|
|
|
|
if (dwErr == 0)
|
|
g_fRasLoaded = TRUE;
|
|
}
|
|
|
|
TRACE1("LoadRas=%d",dwErr);
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
VOID
|
|
StartWaitingForServices(
|
|
HINSTANCE hInst,
|
|
HWND hwndOwner,
|
|
WSINFO* pInfo )
|
|
|
|
/* Popup the "waiting for services" dialog in another thread. 'HInst' and
|
|
** 'hwnd' are the owning instance and window. Fills caller's 'pInfo' with
|
|
** context to pass to StopWaitingForServices.
|
|
*/
|
|
{
|
|
#ifndef NT4STUFF
|
|
|
|
// Set the hourglass cursor
|
|
pInfo->hIcon = SetCursor (LoadCursor (NULL, IDC_WAIT));
|
|
ShowCursor (TRUE);
|
|
|
|
#else
|
|
|
|
WSARGS* pArgs;
|
|
HANDLE hThread;
|
|
HANDLE hEventUp;
|
|
|
|
pInfo->hEventDie = NULL;
|
|
|
|
pArgs = (WSARGS* )Malloc( sizeof(*pArgs) );
|
|
if (!pArgs)
|
|
return;
|
|
|
|
ZeroMemory( pArgs, sizeof(*pArgs) );
|
|
pArgs->hInst = hInst;
|
|
pArgs->hwndOwner = hwndOwner;
|
|
|
|
hEventUp = pArgs->hEventUp =
|
|
CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
if (!hEventUp)
|
|
{
|
|
Free( pArgs );
|
|
return;
|
|
}
|
|
|
|
pInfo->hEventDie = pArgs->hEventDie =
|
|
CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
if (!pInfo->hEventDie)
|
|
{
|
|
Free( pArgs );
|
|
CloseHandle( hEventUp );
|
|
return;
|
|
}
|
|
|
|
/* Create a thread so paint messages for the popup get processed. The
|
|
** current thread is going to be tied up starting RAS Manager.
|
|
*/
|
|
hThread = CreateThread( NULL, 0, WsThread, pArgs, 0, &pInfo->dwThreadId );
|
|
if (hThread)
|
|
{
|
|
/* Don't begin churning on RASMAN until the popup has displayed
|
|
** itself.
|
|
*/
|
|
SetThreadPriority( hThread, THREAD_PRIORITY_HIGHEST );
|
|
WaitForSingleObject( hEventUp, INFINITE );
|
|
CloseHandle( hThread );
|
|
}
|
|
else
|
|
{
|
|
/* Thread was DOA.
|
|
*/
|
|
CloseHandle( pInfo->hEventDie );
|
|
pInfo->hEventDie = NULL;
|
|
Free( pArgs );
|
|
}
|
|
|
|
CloseHandle( hEventUp );
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
StopWaitingForServices(
|
|
IN WSINFO* pInfo )
|
|
|
|
/* Terminate the "waiting for services" popup. 'PInfo' is the context
|
|
** from StartWaitingForServices.
|
|
*/
|
|
{
|
|
TRACE("StopWaitingForServices");
|
|
|
|
|
|
#ifndef NT4STUFF
|
|
|
|
if (pInfo->hIcon == NULL)
|
|
pInfo->hIcon = LoadCursor (NULL, IDC_ARROW);
|
|
|
|
SetCursor (pInfo->hIcon);
|
|
ShowCursor (TRUE);
|
|
|
|
#else
|
|
|
|
if (pInfo->hEventDie)
|
|
{
|
|
/* The post triggers the message loop to action, but you can't rely on
|
|
** the posted message arriving in the thread message loop. For
|
|
** example, if user holds the mouse down on the window caption, the
|
|
** message never appears, presumably because it's flushed by some
|
|
** sub-loop during "move window" processing. Set the event to make
|
|
** sure the popup knows to quit the next time it processes a message.
|
|
*/
|
|
SetEvent( pInfo->hEventDie );
|
|
PostThreadMessage( pInfo->dwThreadId, WM_CLOSE, 0, 0 );
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
DWORD
|
|
WsThread(
|
|
LPVOID pArg )
|
|
|
|
/* Waiting for services thread main.
|
|
*/
|
|
{
|
|
WSARGS* pArgs;
|
|
HWND hwnd;
|
|
MSG msg;
|
|
|
|
TRACE("WsThread running");
|
|
|
|
pArgs = (WSARGS* )pArg;
|
|
hwnd = CreateDialog( pArgs->hInst,
|
|
MAKEINTRESOURCE( DID_WS_WaitingForServices ),
|
|
NULL, WsDlgProc );
|
|
if (hwnd)
|
|
{
|
|
LONG lStyle;
|
|
|
|
/* Make ourselves topmost if the owner window is, otherwise we may not
|
|
** be visible under the topmost window, such as the winlogin window.
|
|
** Note that if you actally create the dialog with an owner you have
|
|
** all kinds of thread related problems. In retrospect, should have
|
|
** written this such that the "waiting" dialog happened in the main
|
|
** thread and the LoadLibraries and RasInitialize happened in the
|
|
** created thread which would automatically avoid this kind of
|
|
** problem, but this works too.
|
|
*/
|
|
lStyle = GetWindowLong( pArgs->hwndOwner, GWL_EXSTYLE );
|
|
if (lStyle & WS_EX_TOPMOST)
|
|
{
|
|
TRACE("TOPMOST");
|
|
SetWindowPos( hwnd, HWND_TOPMOST,
|
|
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
|
}
|
|
|
|
CenterWindow( hwnd, pArgs->hwndOwner );
|
|
ShowWindow( hwnd, SW_SHOW );
|
|
UpdateWindow( hwnd );
|
|
SetForegroundWindow( hwnd );
|
|
}
|
|
|
|
/* Tell other thread to go on.
|
|
*/
|
|
SetEvent( pArgs->hEventUp );
|
|
|
|
if (hwnd)
|
|
{
|
|
TRACE("WsThread msg-loop running");
|
|
|
|
while (GetMessage( &msg, NULL, 0, 0 ))
|
|
{
|
|
if (WaitForSingleObject( pArgs->hEventDie, 0 ) == WAIT_OBJECT_0)
|
|
{
|
|
/* Normal termination.
|
|
*/
|
|
DestroyWindow( hwnd );
|
|
break;
|
|
}
|
|
|
|
if (!IsDialogMessage( hwnd, &msg ))
|
|
{
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
}
|
|
|
|
if (pArgs->hwndOwner)
|
|
SetForegroundWindow( pArgs->hwndOwner );
|
|
}
|
|
|
|
CloseHandle( pArgs->hEventDie );
|
|
Free( pArgs );
|
|
TRACE("WsThread terminating");
|
|
return 0;
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK
|
|
WsDlgProc(
|
|
HWND hwnd,
|
|
UINT unMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
|
|
/* Standard Win32 dialog procedure.
|
|
*/
|
|
{
|
|
if (unMsg == WM_INITDIALOG)
|
|
{
|
|
HMENU hmenu;
|
|
|
|
/* Remove Close from the system menu since some people think it kills
|
|
** the app and not just the popup.
|
|
*/
|
|
hmenu = GetSystemMenu( hwnd, FALSE );
|
|
if (hmenu && DeleteMenu( hmenu, SC_CLOSE, MF_BYCOMMAND ))
|
|
DrawMenuBar( hwnd );
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
VOID
|
|
UnloadRas(
|
|
void )
|
|
|
|
/* Unload the DLLs loaded by LoadRas().
|
|
*/
|
|
{
|
|
if (g_fRasLoaded)
|
|
{
|
|
g_fRasLoaded = FALSE;
|
|
UnloadRasmanDll();
|
|
UnloadRasapi32Dll();
|
|
}
|
|
}
|