/* Copyright (c) 1995, Microsoft Corporation, all rights reserved ** ** popupdlg.c ** UI helper library ** Popup dialog routines ** Listed alphabetically ** ** 08/25/95 Steve Cobb */ #include // NT declarations #include // NT general runtime-library #include // NT user-mode runtime-library #include // Win32 root #include // LAN Manager errors #include // LAN Manager constants #include // To stop va_list argument warning only #include // RAS API definitions #include // Win32 RAS error codes #include // Trace/assert library #include // No-HWND utilities #include // Our public header /*---------------------------------------------------------------------------- ** Error popup **---------------------------------------------------------------------------- */ int ErrorDlgUtil( IN HWND hwndOwner, IN DWORD dwOperation, IN DWORD dwError, IN OUT ERRORARGS* pargs, IN HINSTANCE hInstance, IN DWORD dwTitle, IN DWORD dwFormat ) /* Pops up a modal error dialog centered on 'hwndOwner'. 'DwOperation' is ** the string resource ID of the string describing the operation underway ** when the error occurred. 'DwError' is the code of the system or RAS ** error that occurred. 'Pargs' is a extended formatting arguments or ** NULL if none. 'hInstance' is the application/module handle where ** string resources are located. 'DwTitle' is the string ID of the dialog ** title. 'DwFormat' is the string ID of the error format title. ** ** Returns MessageBox-style code. */ { TCHAR* pszUnformatted; TCHAR* pszOp; TCHAR szErrorNum[ 50 ]; TCHAR* pszError; TCHAR* pszResult; TCHAR* pszNotFound; int nResult; TRACE("ErrorDlgUtil"); /* A placeholder for missing strings components. */ pszNotFound = TEXT(""); /* Build the error number string. */ if (dwError > 0x7FFFFFFF) wsprintf( szErrorNum, TEXT("0x%X"), dwError ); else wsprintf( szErrorNum, TEXT("%u"), dwError ); /* Build the error text string. */ if (!GetErrorText( dwError, &pszError )) pszError = pszNotFound; /* Build the operation string. */ pszUnformatted = PszFromId( hInstance, dwOperation ); pszOp = pszNotFound; if (pszUnformatted) { FormatMessage( FORMAT_MESSAGE_FROM_STRING + FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_ARGUMENT_ARRAY, pszUnformatted, 0, 0, (LPTSTR )&pszOp, 1, (va_list* )((pargs) ? pargs->apszOpArgs : NULL) ); Free( pszUnformatted ); } /* Call MsgDlgUtil with the standard arguments plus any auxillary format ** arguments. */ pszUnformatted = PszFromId( hInstance, dwFormat ); pszResult = pszNotFound; if (pszUnformatted) { MSGARGS msgargs; ZeroMemory( &msgargs, sizeof(msgargs) ); msgargs.dwFlags = MB_ICONEXCLAMATION + MB_OK + MB_SETFOREGROUND; msgargs.pszString = pszUnformatted; msgargs.apszArgs[ 0 ] = pszOp; msgargs.apszArgs[ 1 ] = szErrorNum; msgargs.apszArgs[ 2 ] = pszError; if (pargs) { msgargs.fStringOutput = pargs->fStringOutput; CopyMemory( &msgargs.apszArgs[ 3 ], pargs->apszAuxFmtArgs, 3 * sizeof(TCHAR) ); } nResult = MsgDlgUtil( hwndOwner, 0, &msgargs, hInstance, dwTitle ); Free( pszUnformatted ); if (pargs && pargs->fStringOutput) pargs->pszOutput = msgargs.pszOutput; } if (pszOp != pszNotFound) LocalFree( pszOp ); if (pszError != pszNotFound) LocalFree( pszError ); return nResult; } BOOL GetErrorText( DWORD dwError, TCHAR** ppszError ) /* Fill caller's '*ppszError' with the address of a LocalAlloc'ed heap ** block containing the error text associated with error 'dwError'. It is ** caller's responsibility to LocalFree the returned string. ** ** Returns true if successful, false otherwise. */ { #define MAXRASERRORLEN 256 TCHAR szBuf[ MAXRASERRORLEN + 1 ]; DWORD dwFlags; HANDLE hmodule; DWORD cch; /* Don't panic if the RAS API address is not loaded. Caller may be trying ** and get an error up during LoadRas. */ if ((Rasapi32DllLoaded() || RasRpcDllLoaded()) && g_pRasGetErrorString && g_pRasGetErrorString( (UINT )dwError, (LPTSTR )szBuf, MAXRASERRORLEN ) == 0) { /* It's a RAS error. */ *ppszError = LocalAlloc( LPTR, (lstrlen( szBuf ) + 1) * sizeof(TCHAR) ); if (!*ppszError) return FALSE; lstrcpy( *ppszError, szBuf ); return TRUE; } /* The rest adapted from BLT's LoadSystem routine. */ dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_IGNORE_INSERTS; if (dwError >= MIN_LANMAN_MESSAGE_ID && dwError <= MAX_LANMAN_MESSAGE_ID) { /* It's a net error. */ dwFlags += FORMAT_MESSAGE_FROM_HMODULE; hmodule = GetModuleHandle( TEXT("NETMSG.DLL") ); } else { /* It must be a system error. */ dwFlags += FORMAT_MESSAGE_FROM_SYSTEM; hmodule = NULL; } /* Whistler bug: 389111 VPN connection returns unacceptable error message ** when smart card is not available */ dwFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; /* This is an NTSTATUS error msg. */ if (NT_ERROR(dwError)) { dwError = RtlNtStatusToDosError( dwError ); } cch = FormatMessage( dwFlags, hmodule, dwError, 0, (LPTSTR )ppszError, 1, NULL ); /* FormatMessage failed so we are going to get a generic one from RAS. */ if (!cch || !*ppszError) { Free0( *ppszError ); dwError = ERROR_UNKNOWN; if ((Rasapi32DllLoaded() || RasRpcDllLoaded()) && g_pRasGetErrorString && g_pRasGetErrorString( (UINT )dwError, (LPTSTR )szBuf, MAXRASERRORLEN ) == 0) { *ppszError = LocalAlloc( LPTR, (lstrlen( szBuf ) + 1) * sizeof(TCHAR) ); if (!*ppszError) return FALSE; lstrcpy( *ppszError, szBuf ); return TRUE; } } return (cch > 0); } /*---------------------------------------------------------------------------- ** Message popup **---------------------------------------------------------------------------- */ int MsgDlgUtil( IN HWND hwndOwner, IN DWORD dwMsg, IN OUT MSGARGS* pargs, IN HINSTANCE hInstance, IN DWORD dwTitle ) /* Pops up a message dialog centered on 'hwndOwner'. 'DwMsg' is the ** string resource ID of the message text. 'Pargs' is a extended ** formatting arguments or NULL if none. 'hInstance' is the ** application/module handle where string resources are located. ** 'DwTitle' is the string ID of the dialog title. ** ** Returns MessageBox-style code. */ { TCHAR* pszUnformatted; TCHAR* pszResult; TCHAR* pszNotFound; int nResult; TRACE("MsgDlgUtil"); /* A placeholder for missing strings components. */ pszNotFound = TEXT(""); /* Build the message string. */ pszResult = pszNotFound; if (pargs && pargs->pszString) { FormatMessage( FORMAT_MESSAGE_FROM_STRING + FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_ARGUMENT_ARRAY, pargs->pszString, 0, 0, (LPTSTR )&pszResult, 1, (va_list* )pargs->apszArgs ); } else { pszUnformatted = PszFromId( hInstance, dwMsg ); if (pszUnformatted) { FormatMessage( FORMAT_MESSAGE_FROM_STRING + FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_ARGUMENT_ARRAY, pszUnformatted, 0, 0, (LPTSTR )&pszResult, 1, (va_list* )((pargs) ? pargs->apszArgs : NULL) ); Free( pszUnformatted ); } } if (!pargs || !pargs->fStringOutput) { TCHAR* pszTitle; DWORD dwFlags; HHOOK hhook; if (pargs && pargs->dwFlags != 0) dwFlags = pargs->dwFlags; else dwFlags = MB_ICONINFORMATION + MB_OK + MB_SETFOREGROUND; pszTitle = PszFromId( hInstance, dwTitle ); if (hwndOwner) { /* Install hook that will get the message box centered on the ** owner window. */ hhook = SetWindowsHookEx( WH_CALLWNDPROC, CenterDlgOnOwnerCallWndProc, hInstance, GetCurrentThreadId() ); } else hhook = NULL; if (pszResult) { nResult = MessageBox( hwndOwner, pszResult, pszTitle, dwFlags ); } if (hhook) UnhookWindowsHookEx( hhook ); Free0( pszTitle ); if (pszResult != pszNotFound) LocalFree( pszResult ); } else { /* Caller wants the string without doing the popup. */ pargs->pszOutput = (pszResult != pszNotFound) ? pszResult : NULL; nResult = IDOK; } return nResult; } LRESULT CALLBACK CenterDlgOnOwnerCallWndProc( int code, WPARAM wparam, LPARAM lparam ) /* Standard Win32 CallWndProc hook callback that looks for the next dialog ** started and centers it on it's owner window. */ { /* Arrive here when any window procedure associated with our thread is ** called. */ if (!wparam) { CWPSTRUCT* p = (CWPSTRUCT* )lparam; /* The message is from outside our process. Look for the MessageBox ** dialog initialization message and take that opportunity to center ** the dialog on it's owner's window. */ if (p->message == WM_INITDIALOG) CenterWindow( p->hwnd, GetParent( p->hwnd ) ); } return 0; }