2020-09-30 17:12:29 +02:00

2002 lines
45 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Winmsd.c
Abstract:
Author:
David J. Gilman (davegi) 12-Nov-1992
Gregg R. Acheson (GreggA) 7-Sep-1993
Environment:
User Mode
--*/
#include "resource.h"
#include "dialogs.h"
#include "drives.h"
#include "environ.h"
#include "hardware.h"
#include "network.h"
#include "mem.h"
#include "msg.h"
#include "osver.h"
#include "resource.h"
#include "resprint.h"
#include "service.h"
#include "strresid.h"
#include "winmsd.h"
#include "computer.h"
#include "report.h"
#include "video.h"
#include <commctrl.h>
#include <commdlg.h>
#include <shellapi.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <windowsx.h>
//
// External Global Variables.
//
TCHAR _lpszSelectedComputer [ COMPUTERNAME_LENGTH ];
HKEY _hKeyLocalMachine = HKEY_LOCAL_MACHINE;
HKEY _hKeyUsers = HKEY_USERS;
BOOL _fIsRemote;
//
// Module handle.
//
HANDLE _hModule;
//
// Application's icon handle.
//
HANDLE _hIcon;
//
// Main window handle.
//
HANDLE _hWndMain;
//
// Application's global ImageLists
//
HIMAGELIST _h16x16Imagelist; // 16x16 images
HIMAGELIST _h32x32Imagelist; // 32x32 images
HIMAGELIST _hSystemImage; // single image of system.bmp
//
// Internal Global Variables.
//
TCHAR g_szRunApp[MAX_PATH]; // command line for the app selected in run dlg
//
// Application's accelerator table handle.
//
HANDLE _hAccel;
//
// Internal function prototypes.
//
VOID Usage(
VOID
);
BOOL
InitializeApplication(
INT argc,
CHAR *argv[]
);
void
InitImageLists( void );
BOOL
DoRunApplication( IN HWND hWnd );
BOOL
GetRunCommand (HWND hDlg,
LPWSTR pszCommand,
INT nMaxLen
);
BOOL
GetRunHistoryCommand (HWND hDlg,
LPWSTR pszCommand,
INT nMaxLen
);
BOOL
InitHistoryList (HWND hDlg);
BOOL
ReviseHistoryList (LPWSTR pszCommand);
BOOL StartProcess (LPWSTR pszApplication,
LPWSTR pszParameters);
BOOL
MakeTabs(
IN HWND hWnd,
IN HWND hMainTabControl
);
BOOL
GetTabClientRect( IN HWND hWndTab,
IN LPRECT lpRect
);
DLGTEMPLATE * WINAPI
DoLockDlgRes(LPWSTR lpszResName);
VOID
FixupNulls(LPWSTR p);
//
// Structure for the Run Application dialog
//
struct {
UINT iDisplayName;
TCHAR szExecutableName[MAX_PATH];
} Tools[ ] = {
{IDS_EVENTVWR, TEXT( "eventvwr.exe" ) },
{IDS_REGEDT32, TEXT( "regedt32.exe" ) },
{IDS_WINDISK, TEXT( "windisk.exe" ) },
{IDS_TASKMGR, TEXT( "taskmgr.exe" ) },
{IDS_PERFMON, TEXT( "perfmon.exe" ) },
{IDS_CONTROLP, TEXT( "control.exe" ) },
{IDS_NOTEPAD, TEXT( "notepad.exe" ) },
{IDS_AUTOEXEC_NT, TEXT( "notepad.exe %systemroot%\\system32\\autoexec.nt" ) },
{IDS_CONFIG_NT, TEXT( "notepad.exe %systemroot%\\system32\\config.nt" ) },
{IDS_EXPLORER, TEXT( "explorer.exe" ) },
{IDS_SYSTEDIT, TEXT( "sysedit.exe" ) }
};
//
// Begin Code
//
VOID Usage(
VOID
)
{
TCHAR szBuffer[1024];
WFormatMessage(szBuffer, sizeof( szBuffer ), IDS_FORMAT_COMMAND_LINE_HELP);
MessageBox( _hWndMain, szBuffer, GetString(IDS_APPLICATION_FULLNAME), MB_OK );
}
int
_CRTAPI1
main(
INT argc,
CHAR *argv[]
)
/*++
Routine Description:
Main is the entry point for Winmsd. It initializes the application and
manages the message pump. When the message pump quits, main performs some
global cleanup.
Arguments:
None.
Return Value:
int - Returns the result of the PostQuitMessgae API or -1 if
initialization failed.
--*/
{
MSG msg;
DLGHDR *pHdr;
BOOL bHandled;
TCHAR buffer[MAX_PATH];
if( InitializeApplication( argc, argv )) {
pHdr = (DLGHDR *) GetWindowLong( _hWndMain, GWL_USERDATA );
while( GetMessage( &msg, NULL, 0, 0 )) {
bHandled = FALSE;
bHandled = TranslateAccelerator( _hWndMain, _hAccel, &msg );
if (FALSE == bHandled)
{
if (pHdr->hwndDisplay)
{
bHandled = TranslateAccelerator(pHdr->hwndDisplay, _hAccel, &msg);
}
if (FALSE == bHandled && FALSE == IsDialogMessage(_hWndMain, &msg))
{
TranslateMessage(&msg); // Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window
}
}
}
return msg.wParam;
}
//
// Initialization failed.
//
return -1;
}
BOOL
InitializeApplication(
INT argc,
CHAR *argv[]
)
/*++
Routine Description:
InitializeApplication does just what its name implies. It initializes
global varaibles, sets up global state (e.g. 3D-Controls), registers window
classes and creates and shows the application's main window.
Arguments:
None.
Return Value:
BOOL - Returns TRUE if the application succesfully initialized.
--*/
{
WNDCLASS Wc;
ATOM Window;
OSVERSIONINFO vi;
TCHAR szBuffer[MAX_PATH];
INT nArg = 1;
CHAR *pch;
BOOL Success;
DWORD dwNumChars;
INT nDestination = 0;
INT nDetailLevel = 0;
//
// Make sure we are running NT 4.0 or greater
//
vi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &vi );
if ((vi.dwMajorVersion < 4) ||
(vi.dwPlatformId != VER_PLATFORM_WIN32_NT)) {
lstrcpy(szBuffer, GetString( IDS_NT_REQUIRED ) );
MessageBox( NULL, szBuffer, GetString( IDS_APPLICATION_FULLNAME ), MB_ICONSTOP | MB_OK );
return(FALSE);
}
//
// Set the current machine name.
//
dwNumChars = sizeof(szBuffer);
GetComputerName(szBuffer, &dwNumChars);
wsprintf( _lpszSelectedComputer, L"\\\\%s", szBuffer);
//
// Collect the command line options, if any.
//
while( nArg < argc ){
pch = argv[nArg];
if ( *pch == '-' || *pch == '/') {
pch++;
switch( toupper( *pch ) ) {
case 'S':
nDetailLevel = IDC_SUMMARY_REPORT;
break;
case 'A':
nDetailLevel = IDC_COMPLETE_REPORT;
break;
case 'P':
nDestination = IDC_SEND_TO_PRINTER;
break;
case 'F':
nDestination = IDC_SEND_TO_FILE;
break;
default:
Usage();
return(FALSE);
}
pch++;
} else {
if ( *pch == '\\') {
MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pch,
-1,
_lpszSelectedComputer,
sizeof(_lpszSelectedComputer)
);
//
// If the workstation service is not started, fail this attempt
//
if (NERR_WkstaNotStarted == NetWkstaGetInfo( L"", 100L,(LPBYTE *) szBuffer ))
{
//bugbug: we should throw up a messagebox here.
return FALSE;
}
Success = VerifyComputer( _lpszSelectedComputer );
if (!Success) {
return(FALSE);
}
}
}
nArg++;
}
//
// Get the application's module (instance) handle.
//
_hModule = GetModuleHandle( NULL );
DbgHandleAssert( _hModule );
if( _hModule == NULL ) {
return FALSE;
}
//
// Load the application's main icon resource.
//
_hIcon = LoadIcon( _hModule, MAKEINTRESOURCE( IDI_WINMSD ));
DbgHandleAssert( _hIcon );
if( _hIcon == NULL ) {
return FALSE;
}
//
// Initialize the applications global image lists (helper.c)
//
InitImageLists();
//
// Load the application's accelerator table.
//
_hAccel = LoadAccelerators( _hModule, MAKEINTRESOURCE( IDA_WINMSD ));
DbgHandleAssert( _hAccel );
if( _hAccel == NULL ) {
return FALSE;
}
//
// Register the window class for the application.
//
Wc.style = CS_HREDRAW
| CS_OWNDC
| CS_SAVEBITS
| CS_VREDRAW;
Wc.lpfnWndProc = MainWndProc;
Wc.cbClsExtra = 0;
Wc.cbWndExtra = DLGWINDOWEXTRA;
Wc.hInstance = _hModule;
Wc.hIcon = _hIcon;
Wc.hCursor = LoadCursor( NULL, IDC_ARROW );
Wc.hbrBackground = ( HBRUSH ) ( COLOR_BTNFACE + 1 );
Wc.lpszMenuName = NULL;
Wc.lpszClassName = L"Diagnostics";
Window = RegisterClass( &Wc );
DbgAssert( Window != 0 );
if( Window == 0 ) {
return FALSE;
}
//
// Create the main window.
//
_hWndMain = CreateDialog(
_hModule,
MAKEINTRESOURCE( IDD_WINMSD ),
NULL,
MainWndProc
);
DbgHandleAssert( _hWndMain );
if( _hWndMain == NULL ) {
return FALSE;
}
//
// Set the window title.
//
wsprintf(szBuffer, L"%s - %s",
GetString( IDS_APPLICATION_FULLNAME ),
_lpszSelectedComputer);
SetWindowText(_hWndMain, szBuffer);
//
// if we have been given a detail level or a destination on the
// cmd line, then generate a report now, and terminate.
//
if( nDestination || nDetailLevel ){
//
// Make sure we have a destination
//
if ( !nDestination ) {
nDestination = IDC_SEND_TO_FILE;
}
//
// Make sure we have a detail level
//
if ( !nDetailLevel ) {
nDetailLevel = IDC_SUMMARY_REPORT;
}
Success = GenerateReport ( _hWndMain, nDestination, IDC_ALL_TABS, nDetailLevel, TRUE );
if(!Success){
lstrcpy( szBuffer, GetString(IDS_REPORT_FAILED) );
MessageBox(_hWndMain, szBuffer, GetString(IDS_APPLICATION_FULLNAME), MB_OK | MB_ICONSTOP );
}
return(FALSE);
}
//
// Show the main window
//
ShowWindow( _hWndMain, SW_SHOW );
return TRUE;
}
void
InitImageLists( void )
/*++
Routine Description:
InitImageLists - create the image lists used by application
Arguments:
none
Return Value:
none
--*/
{
// Create the 16 x 16 Image List
_h16x16Imagelist = ImageList_LoadBitmap( _hModule,
L"IDB_16x16",
16,
0,
0x00808000);
DbgHandleAssert( _h16x16Imagelist );
// Create the 32 x 32 Image List
_h32x32Imagelist = ImageList_LoadBitmap( _hModule,
L"IDB_32x32",
32,
0,
0x00808000);
DbgHandleAssert( _h32x32Imagelist );
// system image list (one item)
_hSystemImage = ImageList_LoadBitmap( _hModule,
L"IDB_SYSTEM",
114,
0,
0x00FF00FF);
DbgHandleAssert( _hSystemImage );
}
LRESULT
MainWndProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
MainWndProc processes messages for Winmsd's main window. This entails
handling of messages from the menu bar.
Arguments:
Standard WNDPROC entry.
Return Value:
LRESULT - Depending on input message and processing options.
--*/
{
BOOL Success;
PRINTDLG PrtDlg;
TCHAR szBuffer[MAX_PATH];
static
HWND hMainTabControl;
static
int nCurrentTab;
DLGHDR *pHdr;
switch( message ) {
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
//
// Don't waste our time if we're minimized
//
if (FALSE == IsIconic(hWnd))
{
BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc);
//
// Draw an edge just below menu bar
//
DrawEdge(ps.hdc, &rc, EDGE_ETCHED, BF_TOP);
EndPaint(hWnd, &ps);
}
break;
}
case WM_CREATE:
{
DWORD cb;
BOOL Success;
HKEY hKey;
WINDOWPLACEMENT wp;
DWORD dwSize;
DWORD dwType;
int fDefault = TRUE;
//
// Read the window location in from the registry
//
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
SZ_WINMSD_KEY,
0,
KEY_READ,
&hKey))
{
fDefault = FALSE;
dwSize = sizeof(wp);
if (ERROR_SUCCESS != RegQueryValueEx(hKey,
L"Preferences",
0,
&dwType,
(LPBYTE) &wp,
&dwSize)
// Validate type and size of options info we got from the registry
|| dwType != REG_BINARY
|| dwSize != sizeof(wp)
// Validate points
|| wp.rcNormalPosition.left > GetSystemMetrics(SM_CXMAXIMIZED)
|| wp.rcNormalPosition.top > GetSystemMetrics(SM_CYMAXIMIZED) )
{
fDefault = TRUE;
}
RegCloseKey( hKey );
}
if (fDefault)
{
//
// use default values
//
wp.rcNormalPosition.left = GetSystemMetrics( SM_CXSCREEN ) / 2 ;
wp.rcNormalPosition.top = GetSystemMetrics( SM_CYSCREEN ) / 2;
//
// Make it look good on my dual screen, I just hate
// it being centered across two monitors. This centers
// it on the first monitor.
//
if (wp.rcNormalPosition.left > 1600) {
wp.rcNormalPosition.left = wp.rcNormalPosition.left / 2;
}
if (wp.rcNormalPosition.top > 1280) {
wp.rcNormalPosition.top = wp.rcNormalPosition.top / 2;
}
wp.rcNormalPosition.left = wp.rcNormalPosition.left - (((( LPCREATESTRUCT ) lParam )->cx ) / 2);
wp.rcNormalPosition.top = wp.rcNormalPosition.top - (((( LPCREATESTRUCT ) lParam )->cy ) / 2);
}
Success = SetWindowPos(
hWnd,
NULL,
wp.rcNormalPosition.left,
wp.rcNormalPosition.top,
0,
0,
SWP_NOSIZE
| SWP_NOREDRAW
| SWP_NOZORDER
);
DbgAssert( Success );
return 0;
}
case WM_INITDIALOG:
{
//
// Check for aliases
//
TCHAR szMessage[MAX_PATH];
DWORD dwNumChars = MAX_PATH;
if ( GetServerPrimaryName(&_lpszSelectedComputer[2], szBuffer, dwNumChars ) )
{
wsprintf(szMessage, GetString(IDS_ALIAS_NAME), _lpszSelectedComputer, szBuffer);
MessageBox( hWnd, szMessage, GetString( IDS_APPLICATION_FULLNAME ), MB_OK | MB_ICONINFORMATION );
lstrcpy(&_lpszSelectedComputer[2], szBuffer);
}
//
// Get the handle of the tab control
//
hMainTabControl = GetDlgItem( hWnd, IDC_MAIN_TAB );
//
// Fill out tab control with appropriate tabs
//
MakeTabs( hWnd, hMainTabControl );
// Set Tab control to first tab
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
pHdr->hwndDisplay = CreateDialogIndirect( _hModule,
pHdr->apRes[ 0 ], hWnd, pHdr->ChildTabProc[ 0 ] );
return( TRUE );
}
case WM_INITMENU:
{
// Call SHRestricted, @100 in shell32.dll
HMODULE hModule = GetModuleHandle(L"Shell32");
FARPROC SHRestricted = GetProcAddress( hModule, (LPCSTR) MAKEWORD(100,0));
HMENU hMenu = GetMenu(_hWndMain);
//
// Remove restriced items from the menu
//
if (SHRestricted(0x00000001))
{
DeleteMenu(hMenu, IDM_RUN_APPLICATION, MF_BYCOMMAND);
}
//
// Remove restriced items from the menu
//
if (SHRestricted(0x00000080))
{
DeleteMenu(hMenu, IDM_FILE_FIND_FILE, MF_BYCOMMAND);
}
//
// Enable/Disable the "View Local" menu, based on whether we are
// local or not
//
EnableMenuItem(hMenu, IDM_VIEW_LOCAL, !_fIsRemote);
//
// If the workstation service is not started, grey the Select Computer Menu
//
if (NERR_WkstaNotStarted == NetWkstaGetInfo( L"", 100L,(LPBYTE *) szBuffer ))
{
EnableMenuItem(hMenu, IDM_SELECT_COMPUTER, MF_GRAYED);
}
DrawMenuBar(_hWndMain);
break;
}
case WM_NOTIFY:
{
static
int nPreviousTab = 1;
// switch on notification code
switch ( ((LPNMHDR)lParam)->code ) {
case TCN_SELCHANGE:
{
TC_ITEM tci;
int iSel;
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
iSel = TabCtrl_GetCurSel( pHdr->hwndTab );
//
//get the proper index to the appropriate procs
//that were set in MakeTabs
//
tci.mask = TCIF_PARAM;
TabCtrl_GetItem(pHdr->hwndTab, iSel, &tci);
// Destroy the current child dialog box, if any.
if (pHdr->hwndDisplay != NULL)
DestroyWindow(pHdr->hwndDisplay);
// Create the new child dialog box.
pHdr->hwndDisplay = CreateDialogIndirect(
_hModule,
pHdr->apRes[ tci.lParam ],
hWnd,
pHdr->ChildTabProc[ tci.lParam ]
);
return(TRUE);
}
case TTN_NEEDTEXT:
{
LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lParam;
int idCtrl = GetDlgCtrlID((HWND) ((LPNMHDR) lParam)->idFrom);
lpttt->lpszText = (unsigned short *) IDS_APPLICATION_FULLNAME;
lpttt->hinst = _hModule;
return(TRUE);
}
}
break;
}
case WM_COMMAND:
{
switch (LOWORD( wParam)) {
// pass these messages on to the TabProc
case IDC_PUSH_PROPERTIES:
case IDC_PUSH_REFRESH:
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
PostMessage(pHdr->hwndDisplay,
message,
wParam,
lParam
);
return TRUE;
case IDM_COPY_TAB:
if (GetKeyState(VK_SHIFT) & 0x8000) {
GenerateReport ( hWnd, IDC_CLIPBOARD, IDC_CURRENT_TAB, IDC_COMPLETE_REPORT, FALSE );
} else {
GenerateReport ( hWnd, IDC_CLIPBOARD, IDC_CURRENT_TAB, IDC_SUMMARY_REPORT, FALSE );
}
break;
case IDM_NEXTTAB:
case IDM_PREVTAB:
{
int iSel;
NMHDR nmhdr;
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
iSel = TabCtrl_GetCurSel( pHdr->hwndTab );
// set the new tab
iSel += (LOWORD( wParam) == IDM_NEXTTAB) ? 1 : -1;
// make sure we are not tabbing past legal limits
if (iSel == TabCtrl_GetItemCount(pHdr->hwndTab))
{
iSel = 0;
}
else if (iSel < 0)
{
iSel = (TabCtrl_GetItemCount(pHdr->hwndTab)) - 1;
}
TabCtrl_SetCurSel(pHdr->hwndTab, iSel);
// SetCurSel doesn't do the page change (that would make too much
// sense), so we have to fake up a TCN_SELCHANGE notification
nmhdr.hwndFrom = GetDlgItem(_hWndMain, IDC_MAIN_TAB);
nmhdr.idFrom = IDC_MAIN_TAB;
nmhdr.code = TCN_SELCHANGE;
SendMessage( hWnd, WM_NOTIFY, (WPARAM) IDC_MAIN_TAB, (LPARAM) &nmhdr);
break;
}
case IDM_FILE_FIND_FILE:
{
// Call SHFindFile, @90 in shell32.dll
HMODULE hModule = GetModuleHandle(L"Shell32");
FARPROC pfn = GetProcAddress( hModule, (LPCSTR) MAKEWORD(90,0));
if(pfn)
{
pfn( NULL, NULL);
}
break;
}
case IDM_RUN_APPLICATION:
Success = DoRunApplication( hWnd );
break;
case IDM_WHATS_THIS:
PostMessage(hWnd, WM_SYSCOMMAND, SC_CONTEXTHELP, 0);
break;
case IDC_PUSH_PRINT:
case IDM_FILE_PRINT:
case IDM_FILE_SAVE:
//
// Call the create report setup dialog.
//
DialogBoxParam(
_hModule,
MAKEINTRESOURCE( IDD_REPORT ),
hWnd,
ReportDlgProc,
LOWORD( wParam )
);
break;
case IDOK:
case IDM_FILE_EXIT:
PostMessage(hWnd, WM_CLOSE, 0, 0L);
break;
case IDM_FILE_PRINT_SETUP:
//
// Call the Printer setup common dialog.
//
PrtDlg.lStructSize = sizeof(PRINTDLG);
PrtDlg.hwndOwner = hWnd;
PrtDlg.hDevMode = NULL;
PrtDlg.hDevNames = NULL;
PrtDlg.hDC = NULL;
PrtDlg.Flags = PD_PRINTSETUP;
PrintDlg ( &PrtDlg ) ;
return TRUE;
case IDM_SELECT_COMPUTER:
{
TC_ITEM tci;
TCHAR szBuffer[MAX_PATH];
int iSel;
//
// Select Computer.
//
if( SelectComputer( hWnd, _lpszSelectedComputer ) )
{
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
//
// Recreate the tab control for the new machine
//
MakeTabs( hWnd, hMainTabControl );
// Set Tab control to first tab
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
pHdr->hwndDisplay = CreateDialogIndirect( _hModule,
pHdr->apRes[ 0 ], hWnd, pHdr->ChildTabProc[ 0 ] );
return(TRUE);
}
return(FALSE);
}
case IDM_VIEW_LOCAL:
{
DWORD cb;
//
// View local machine.
//
//
// Reset the pointer to HKEY_LOCAL_MACHINE and the fIsRemote flag
//
_fIsRemote = FALSE;
RegCloseKey( _hKeyLocalMachine );
_hKeyLocalMachine = HKEY_LOCAL_MACHINE;
RegCloseKey( _hKeyUsers );
_hKeyUsers = HKEY_USERS;
//
// Reset the window title
//
cb = sizeof(_lpszSelectedComputer);
GetComputerName(_lpszSelectedComputer, &cb);
wsprintf(szBuffer, L"Windows NT %s - \\\\%s",
GetString( IDS_APPLICATION_NAME ),
_lpszSelectedComputer);
Success = SetWindowText(hWnd, szBuffer);
DbgAssert( Success );
//
// Recreate the tab control for the new machine
//
MakeTabs( hWnd, hMainTabControl );
// Set Tab control to first tab
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
pHdr->hwndDisplay = CreateDialogIndirect(
_hModule,
pHdr->apRes[ 0 ],
hWnd,
pHdr->ChildTabProc[ 0 ]
);
return TRUE;
}
case IDM_HELP_ABOUT:
//
// Display the About dialog.
//
ShellAbout(
hWnd,
( LPWSTR ) GetString( IDS_APPLICATION_NAME ),
INTERNAL_VERSION,
_hIcon
);
return TRUE;
}
break;
}
case WM_CLOSE:
{
DWORD dwDisposition;
HKEY hKey;
WINDOWPLACEMENT wp;
//
// Do some clean up
//
pHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
//
// Save the window position to the registry
//
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hWnd, &wp);
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER,
SZ_WINMSD_KEY,
0,
TEXT("REG_BINARY"),
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisposition))
{
RegSetValueEx(hKey,
L"Preferences",
0,
REG_BINARY,
(LPBYTE) &wp,
sizeof(wp));
RegCloseKey(hKey);
}
//
// Close the registry keys
//
RegCloseKey(_hKeyLocalMachine);
RegCloseKey(_hKeyUsers);
//
// Destroy Current tab
//
DestroyWindow(pHdr->hwndDisplay);
//
// Free memory associated with Tab structure
//
LocalFree( pHdr );
//
// Commit suicide
//
DestroyWindow( hWnd );
break;
}
case WM_DESTROY:
//
// Destroy the application.
//
PostQuitMessage( 0 );
return 0;
}
//
// Handle unhandled messages.
//
return DefWindowProc( hWnd, message, wParam, lParam );
}
BOOL
GetTabClientRect( IN HWND hWndTab,
IN LPRECT lpRect
)
/*++
Routine Description:
GetTabClientRect calculates the client area of the Tab control relative
to the main window
Arguments:
HWND hWndTab -- handle of tab control
LPRECT lpRect -- pointer to RECT structure that will recieve the data
Return Value:
BOOL - TRUE if successful
--*/
{
UINT fSuccess = TRUE;
// first get the size of the tab control
if (GetWindowRect( hWndTab, lpRect ) == FALSE)
fSuccess = FALSE;
// adjust it to compensate for the tabs
TabCtrl_AdjustRect( hWndTab, FALSE , lpRect);
// convert the screen coordinates to client coordinates
MapWindowPoints( HWND_DESKTOP, GetParent(hWndTab), (LPPOINT) lpRect, 2);
return(fSuccess);
}
BOOL
MakeTabs(
IN HWND hWnd,
IN HWND hMainTabControl
)
/*++
Routine Description:
MakeTabs fills out the Main Tab Control with appropriate tabs
Arguments:
HWND hWnd - handle of main window
HWND hMainTabControl - handle to the tab control
Return Value:
BOOL - Returns TRUE if successful.
--*/
{
DLGHDR *pHdr = (DLGHDR *) LocalAlloc(LPTR, sizeof(DLGHDR));
DLGHDR *pOldHdr = (DLGHDR *) GetWindowLong( hWnd, GWL_USERDATA );
TC_ITEM tci;
TCHAR pszTabText[30];
int i;
DWORD Tab[C_PAGES] = {IDD_VERSION_TAB,
IDD_HARDWARE_TAB,
IDD_VIDEO_TAB,
IDD_DRIVES_TAB,
IDD_MEMORY_TAB,
//IDD_INSTALLATION_TAB,
IDD_DRIVERS_SERVICES_TAB,
IDD_IRQ_PORT_DMA_MEM_TAB,
IDD_ENVIRONMENT_TAB,
//IDD_PRINTING_TAB,
IDD_NETWORK_TAB
};
//
// If the old pointer is valid, remove all tabs free
// the structure, then save a pointer to the new DLGHDR structure.
//
if (pOldHdr)
{
// Destroy the current child dialog box, if any.
if (pOldHdr->hwndDisplay != NULL)
{
DestroyWindow(pOldHdr->hwndDisplay);
}
TabCtrl_DeleteAllItems(hMainTabControl);
LocalFree(pOldHdr);
}
SetWindowLong(hWnd, GWL_USERDATA, (LONG) pHdr);
//
// Save pointers to the tab procs
//
pHdr->ChildTabProc[0] = VersionTabProc;
pHdr->ChildTabProc[1] = HardwareTabProc;
pHdr->ChildTabProc[2] = VideoTabProc;
pHdr->ChildTabProc[3] = DrivesTabProc;
pHdr->ChildTabProc[4] = MemoryTabProc;
pHdr->ChildTabProc[5] = DevicesAndServicesTabProc;
pHdr->ChildTabProc[6] = DeviceDlgProc;
pHdr->ChildTabProc[7] = EnvironmentTabProc;
pHdr->ChildTabProc[8] = NetworkDlgProc;
//
// Save pointers to the print procs
//
pHdr->TabPrintProc[0] = BuildOsVerReport;
pHdr->TabPrintProc[1] = BuildHardwareReport;
pHdr->TabPrintProc[2] = BuildVideoReport;
pHdr->TabPrintProc[3] = BuildDrivesReport;
pHdr->TabPrintProc[4] = BuildMemoryReport;
pHdr->TabPrintProc[5] = BuildServicesReport;
pHdr->TabPrintProc[6] = BuildResourceReport;
pHdr->TabPrintProc[7] = BuildEnvironmentReport;
pHdr->TabPrintProc[8] = BuildNetworkReport;
// Save the handle to the main tab control.
pHdr->hwndTab = hMainTabControl;
//
// Assume we will be displaying the tab
//
for (i = 0; i < C_PAGES; i++)
{
pHdr->fActiveTab[i] = TRUE;
}
// Check to see if the network is running
// if it is not, do not display the network tab
if (NERR_WkstaNotStarted == NetWkstaGetInfo( L"", 100L,(LPBYTE *) pszTabText ))
{
pHdr->fActiveTab[8] = FALSE;
}
// If we are remote, disable the Drives and Memory tabs
if (_fIsRemote)
{
pHdr->fActiveTab[3] = FALSE;
pHdr->fActiveTab[4] = FALSE;
}
//
// For the Active tabs, insert them in the control
//
tci.mask = TCIF_TEXT | TCIF_PARAM;
tci.pszText = pszTabText;
tci.cchTextMax = sizeof( pszTabText );
for (i = 0; i < C_PAGES; i++) {
if ( pHdr->fActiveTab[i] )
{
// Get the Tab title, the current index + the strind ID
tci.pszText = (LPTSTR) GetString( i + IDS_FIRST_TAB);
// store the index to the procs
tci.lParam = i;
// insert the tab
TabCtrl_InsertItem( hMainTabControl, i + 1, &tci );
// lock the resources for the dialog
pHdr->apRes[i] = DoLockDlgRes( MAKEINTRESOURCE( Tab[i] ) );
}
}
// Save the size of the tab control's client area
GetTabClientRect( pHdr->hwndTab , &pHdr->rcDisplay );
return(TRUE);
}
DLGTEMPLATE * WINAPI
DoLockDlgRes(LPWSTR lpszResName)
/*++
Routine Description:
DoLockDlgRes - loads and locks a dialog template resource.
Arguments:
lpszResName - name of the resource
Return Value:
Returns a pointer to the locked resource.
--*/
{
HRSRC hrsrc = FindResource(NULL, lpszResName, RT_DIALOG);
HGLOBAL hglb = LoadResource(_hModule, hrsrc);
return (DLGTEMPLATE *) LockResource(hglb);
}
BOOL
DoRunApplication( IN HWND hWnd )
/*++
Routine Description:
DoRunApplication
Invoke the run application dialog box. Afterwards, execute the command
that the user entered. [Borrowed from MSINFO32]
Arguments:
hWnd - handle of main window
Return Value:
TRUE is successful
--*/
{
BOOL bOK = FALSE;
//
// Call the dialog
//
BOOL fRun = DialogBox(_hModule,
MAKEINTRESOURCE(IDD_RUN_APPLICATION),
hWnd,
(DLGPROC) RunDlgProc);
//
// Execute the command line
//
if (fRun)
{
HCURSOR hcurPrev = SetCursor(LoadCursor(NULL, IDC_WAIT));
StartProcess(NULL, g_szRunApp);
SetCursor(hcurPrev);
bOK = TRUE;
}
return (bOK);
}
LRESULT
RunDlgProc(
HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
/*++
Routine Description:
RunDlgProc "Run System Applications" dialog box procedure.
Arguments:
Standard WNDPROC entry.
Return Value:
LRESULT - Depending on input message and processing options.
--*/
{
OPENFILENAME ofn;
switch (message)
{
case WM_INITDIALOG:
{
HWND hWndRunList = GetDlgItem(hDlg, didlbxProgs);
int i;
//
// Initialize applications listbox w/ existing applications
//
for (i = 0; i < NumberOfEntries( Tools ); i++){
ListBox_AddString( hWndRunList, GetString( Tools[i].iDisplayName) );
}
//
// Set the initial selection to null and disable the OK button
//
ListBox_SetCurSel(hWndRunList, -1);
EnableControl(hDlg, IDOK, FALSE);
//
// Setup the history list
//
InitHistoryList(hDlg);
return(TRUE);
}
case WM_COMMAND:
{
HWND hWndRunList = GetDlgItem(hDlg, didlbxProgs);
WORD wID = LOWORD(wParam);
WORD wNotifyCode = HIWORD(wParam);
BOOL bValid;
if ((wID == IDOK) || (wID == IDCANCEL))
{
if (wID == IDCANCEL)
{
g_szRunApp[0] = UNICODE_NULL;
}
else
{
GetRunCommand(hDlg, g_szRunApp, sizeof(g_szRunApp));
}
EndDialog(hDlg, (wID == IDOK));
return(TRUE);
}
// If the run history list is clicked, remove any highlight from run list
// and enable OK if command is nonblank
else if (wID == didcbxRunHistory)
{
if ((wNotifyCode == CBN_EDITCHANGE) ||
(wNotifyCode == CBN_SELCHANGE) ||
(wNotifyCode == CBN_SETFOCUS))
{
ListBox_SetCurSel(hWndRunList, -1);
bValid = GetRunHistoryCommand(hDlg, g_szRunApp, sizeof(g_szRunApp));
EnableControl(hDlg, IDOK, bValid);
}
break;
}
else if (wID == didbtnBrowse)
{
TCHAR szFilters[MAX_PATH];
TCHAR szTitle[64];
TCHAR szDir[MAX_PATH];
TCHAR szPath[MAX_PATH];
// get filters and fix nulls
lstrcpy(szFilters, GetString (IDS_PROGRAMFILTERS) );
FixupNulls(szFilters);
//get title
lstrcpy(szTitle, GetString( IDS_BROWSE ) );
// On NT, we like to start apps in the HOMEPATH directory. This
// should be the current directory for the current process.
GetEnvironmentVariable(TEXT("HOMEDRIVE"), szDir, sizeof(szDir));
GetEnvironmentVariable(TEXT("HOMEPATH"), szPath, sizeof(szPath));
lstrcat(szDir, L"\\");
lstrcat(szDir, szPath);
// reuse szPath for filename
szPath[0] = UNICODE_NULL;
// Setup info for comm dialog.
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilters;
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 1;
ofn.nMaxCustFilter = 0;
ofn.lpstrFile = szPath;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = szDir;
ofn.lpstrTitle = szTitle;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
ofn.lpfnHook = NULL;
ofn.lpstrDefExt = NULL;
ofn.lpstrFileTitle = NULL;
// Call it.
if (GetOpenFileName(&ofn)){
//if there is a space in the path, quote the string
if(wcschr(ofn.lpstrFile, L' ')){
wsprintf(szDir, L"\"%s\"", ofn.lpstrFile);
SetDlgItemText( hDlg, didcbxRunHistory, szDir);
}
else{
SetDlgItemText( hDlg, didcbxRunHistory, ofn.lpstrFile);
}
EnableControl(hDlg, IDOK, TRUE);
SetFocus( GetDlgItem( hDlg, IDOK ) );
}
return(TRUE);
}
else if (wID == didlbxProgs)
{
INT nCurSel = ListBox_GetCurSel(hWndRunList);
BOOL bValidSelection = (nCurSel != LB_ERR);
if (wNotifyCode == LBN_DBLCLK)
{
if (bValidSelection)
{
GetRunCommand(hDlg, g_szRunApp, lstrlen(g_szRunApp));
EndDialog(hDlg, TRUE);
return (TRUE);
}
}
EnableControl(hDlg, IDOK, bValidSelection);
}
break;
}
}
return(FALSE);
}
BOOL
GetRunCommand (HWND hDlg,
LPWSTR pszCommand,
INT nMaxLen
)
/*++
Routine Description:
GetRunCommand Copies the command line for the selected application (to be run)
into the specified buffer.
--*/
{
BOOL bOK = TRUE;
HWND hWndRunList = GetDlgItem(hDlg, didlbxProgs);
INT nAppPos = ListBox_GetCurSel(hWndRunList);
if (nAppPos == -1)
{
BOOL bValid = GetRunHistoryCommand(hDlg, pszCommand, nMaxLen);
if (bValid)
{
ReviseHistoryList(pszCommand);
}
else
{
bOK = FALSE;
pszCommand[0] = UNICODE_NULL;
}
}
else
{
TCHAR ExpandedPath[MAX_PATH];
ExpandEnvironmentStrings(Tools[nAppPos].szExecutableName, ExpandedPath, MAX_PATH);
lstrcpy(pszCommand, ExpandedPath);
}
return (bOK);
}
BOOL
GetRunHistoryCommand (HWND hDlg,
LPWSTR pszCommand,
INT nMaxLen
)
/*++
Routine Description:
GetRunHistoryCommand -- Gets the current command in the run history list
--*/
{
HWND hWndRunHistory = GetDlgItem(hDlg, didcbxRunHistory);
INT nCommandLen = GetDlgItemText(hDlg, didcbxRunHistory, (LPTSTR) pszCommand, nMaxLen);
LPWSTR pszStart = NULL;
BOOL bOK = 0;
if (nCommandLen == 0)
{
INT nCurSel = ComboBox_GetCurSel(hWndRunHistory);
if (nCurSel != CB_ERR)
{
nCommandLen = ComboBox_GetLBText(hWndRunHistory, nCurSel, pszCommand);
DbgAssert((nCommandLen != LB_ERR) && (nCommandLen <= nMaxLen));
}
}
pszStart = pszCommand;
//BUGBUG: the following line is intended to skip initial spaces, but does not work
// while( lstrcmp(pszStart++, L" ") == 0 );
bOK = ((nCommandLen > 0) && (*pszStart != UNICODE_NULL));
return (bOK);
}
BOOL
InitHistoryList (HWND hDlg)
/*++
Routine Description:
InitHistoryList -- Initialize the history list for the previous commands exectued
--*/
{
HWND hWndRunHistory = GetDlgItem(hDlg, didcbxRunHistory);
LPTSTR pszRunHistory = NULL;
LPWSTR pszPos = NULL;
LPWSTR pszEnd = NULL;
DWORD cb;
BOOL Success;
HKEY hKey;
// Allocate a buffer for the history list
cb = MAX_HISTORY * MAX_PATH * sizeof(TCHAR);
pszRunHistory = (LPTSTR) LocalAlloc(LPTR, cb);
if( pszRunHistory == NULL )
return(FALSE);
//
// Open the winmsd key in the registry
//
Success = RegCreateKeyEx( HKEY_CURRENT_USER,
SZ_WINMSD_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&cb);
if(Success != ERROR_SUCCESS){
LocalFree(pszRunHistory);
return( FALSE );
}
//
// Read the history value
//
cb = LocalSize( pszRunHistory );
Success = RegQueryValueEx( hKey,
(LPWSTR) GetString(IDS_HISTORY),
0,
NULL,
(LPBYTE) pszRunHistory,
&cb);
if(Success != ERROR_SUCCESS){
LocalFree(pszRunHistory);
return( FALSE );
}
RegCloseKey(hKey);
pszPos = pszRunHistory;
pszEnd = pszRunHistory + cb;
while (*pszPos && (pszPos < pszEnd))
{
ComboBox_AddString(hWndRunHistory, pszPos);
pszPos += 1 + lstrlen(pszPos);
}
LocalFree(pszRunHistory);
return (TRUE);
}
BOOL
ReviseHistoryList (LPWSTR pszCommand)
/*++
Routine Description:
ReviseHistoryList -- Add the command to the front of the history list,
removing any existing occurrence(s).
--*/
{
LPWSTR pszNewHistory = NULL;
DWORD cbMax = MAX_HISTORY * MAX_PATH * sizeof(TCHAR);
DWORD dwDisposition;
UINT pos;
DWORD cbRemainingBytes;
BOOL Success;
HKEY hKey;
// Allocate a buffer for the new history list + 1 MAX_PATH for new command
pszNewHistory = (LPWSTR) LocalAlloc(LPTR, cbMax + (MAX_PATH * sizeof(TCHAR)));
// make sure we have a buffer
if(pszNewHistory == NULL){
DbgAssert(pszNewHistory);
return(FALSE);
}
// Put the command at the front of the history list, obtained from registry
lstrcpy(pszNewHistory, pszCommand);
//set the pos to the next available char
pos = lstrlen(pszNewHistory) + 1;
//
// Open the winmsd key in the registry
//
Success = RegCreateKeyEx( HKEY_CURRENT_USER,
SZ_WINMSD_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisposition);
if((Success == ERROR_SUCCESS) && (dwDisposition == REG_OPENED_EXISTING_KEY)){
//
// We opened an existing key so read the value for the old run history
//
cbRemainingBytes = cbMax - pos;
Success = RegQueryValueEx( hKey,
GetString(IDS_HISTORY),
0,
NULL,
(LPBYTE) &pszNewHistory[pos],
&cbRemainingBytes);
if((Success == ERROR_SUCCESS) && cbRemainingBytes){
// make sure the list is double NULL terminated
cbMax = cbRemainingBytes + pos;
pszNewHistory[cbMax + 1] = UNICODE_NULL;
pszNewHistory[cbMax + 2] = UNICODE_NULL;
while ((pszNewHistory[pos] != UNICODE_NULL)){
//Stop if the current element matches the text completely
if (lstrcmpi(pszNewHistory, &pszNewHistory[pos]) == 0){
// move the rest of the string up, and exit the while loop.
cbMax -= (lstrlen( &pszNewHistory[pos] ) + 1);
MoveMemory(&pszNewHistory[pos],
&pszNewHistory[pos + (lstrlen( &pszNewHistory[pos] ) + 1)],
cbRemainingBytes);
break;
}
pos += lstrlen( &pszNewHistory[pos] ) + 1;
cbRemainingBytes = cbMax - pos;
}
}
}
//
// Write the history value back to the registry
//
Success = RegSetValueEx( hKey,
GetString(IDS_HISTORY),
0,
REG_MULTI_SZ,
(LPBYTE) pszNewHistory,
cbMax);
RegCloseKey(hKey);
LocalFree(pszNewHistory);
return (TRUE);
}
BOOL StartProcess (LPWSTR pszApplication, LPWSTR pszParameters)
/*++
Routine Description:
StartProcess -- Starts the command line specified by pszApplication
--*/
{
BOOL bOK = TRUE;
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
bOK = CreateProcess(pszApplication, // module name
(LPWSTR)pszParameters, // command line
NULL, // process security attributes
NULL, // thread security attributes
FALSE, // new process inherits handles
NORMAL_PRIORITY_CLASS, // creation flags
NULL, // new environment block
NULL, // current directory name
&si, // STARTUPINFO
&pi); // PROCESS_INFORMATION
if (!bOK)
{
// WORKITEM: handle failure with a msg
}
return (bOK);
}
VOID
FixupNulls(LPWSTR p)
/*++
Routine Description:
FixupNulls -- since LoadString() only reads up to a null we have to mark
special characters where we want nulls then convert them
after loading.
--*/
{
LPTSTR pT;
while (*p) {
if (*p == L'#') {
pT = p;
p = CharNext(p);
*pT = UNICODE_NULL;
}
else
p = CharNext(p);
}
}
//
// debug support
//
#if DBG
#define DEBUG 1
#endif
#ifdef DEBUG
int dprintf(LPCTSTR szFormat, ...)
{
TCHAR szBuffer[4096];
TCHAR szPrefix[MAX_PATH];
va_list vaList;
va_start(vaList, szFormat);
wvsprintf(szBuffer, szFormat, vaList);
wsprintf(szPrefix, L"WinMSD: %s", szBuffer);
OutputDebugString(szPrefix);
va_end (vaList);
return TRUE;
}
#else
int dprintf(LPCTSTR szFormat, ...)
{
return FALSE;
}
#endif