|
|
/****************************************************************************
Copyright (c) Microsoft Corporation 1998 All rights reserved
File: SERVERDLG.CPP
***************************************************************************/
#include "pch.h"
#include "callback.h"
#include "utils.h"
#include <winver.h>
#include <sputils.h>
DEFINE_MODULE( "RIPREP" )
BOOLEAN GetInstalledProductType( OUT PDWORD ProductType, OUT PDWORD ProductSuite ) /*++
Routine Description:
retrieves the product type and suite from a running system
Arguments:
ProductType - receives a VER_NT_* constant. ProductSuite - receives a VER_SUITE_* mask for the system. Return Value:
TRUE indicates success
--*/ { OSVERSIONINFOEX VersionInfo;
VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
if (GetVersionEx((OSVERSIONINFO *)&VersionInfo)) { //
// make domain controllers and servers look the same
//
*ProductType = (VersionInfo.wProductType == VER_NT_DOMAIN_CONTROLLER) ? VER_NT_SERVER : VersionInfo.wProductType; //
// we only care about suites that have a SKU associated with them.
//
*ProductSuite = (VersionInfo.wSuiteMask & (VER_SUITE_ENTERPRISE | VER_SUITE_DATACENTER | VER_SUITE_PERSONAL)) ;
return(TRUE); }
return(FALSE);
}
BOOL pSetupEnablePrivilegeW( IN PCWSTR PrivilegeName, IN BOOL Enable )
/*++
Routine Description:
Enable or disable a given named privilege.
Arguments:
PrivilegeName - supplies the name of a system privilege.
Enable - flag indicating whether to enable or disable the privilege.
Return Value:
Boolean value indicating whether the operation was successful.
--*/
{ HANDLE Token; BOOL b; TOKEN_PRIVILEGES NewPrivileges; LUID Luid;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&Token)) { return(FALSE); }
if(!LookupPrivilegeValue(NULL,PrivilegeName,&Luid)) { CloseHandle(Token); return(FALSE); }
NewPrivileges.PrivilegeCount = 1; NewPrivileges.Privileges[0].Luid = Luid; NewPrivileges.Privileges[0].Attributes = Enable ? SE_PRIVILEGE_ENABLED : 0;
b = AdjustTokenPrivileges( Token, FALSE, &NewPrivileges, 0, NULL, NULL );
CloseHandle(Token);
return(b); }
GetSuiteMaskFromPath( IN PCWSTR PathToSearch, OUT PDWORD SuiteMask ) { #define HIVENAME L"riprepsetupreg"
TCHAR lpszSetupReg[MAX_PATH] = HIVENAME L"\\ControlSet001\\Services\\setupdd";
WCHAR Path[MAX_PATH]; WCHAR DestPath[MAX_PATH]; LONG rslt; HKEY hKey; DWORD Type; DWORD Buffer[4]; DWORD BufferSize = sizeof(Buffer); BOOLEAN RetVal = FALSE;
GetTempPath(ARRAYSIZE(Path),Path); GetTempFileName( Path, L"ripr", 0, DestPath);
if (-1 == _snwprintf( Path, MAX_PATH, L"%ws\\setupreg.hiv", PathToSearch)) { goto e0; } TERMINATE_BUFFER(Path);
if (!CopyFile(Path,DestPath,FALSE)) { goto e0; }
SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL);
//
// need SE_RESTORE_NAME priviledge to call this API!
//
pSetupEnablePrivilegeW( SE_RESTORE_NAME, TRUE );
//
// try to unload this first in case we faulted or something and the key is still loaded
//
RegUnLoadKey( HKEY_LOCAL_MACHINE, HIVENAME );
rslt = RegLoadKey( HKEY_LOCAL_MACHINE, HIVENAME, DestPath ); if (rslt != ERROR_SUCCESS) { goto e1; } rslt = RegOpenKey(HKEY_LOCAL_MACHINE,lpszSetupReg,&hKey); if (rslt != ERROR_SUCCESS) { goto e2; }
rslt = RegQueryValueEx(hKey, NULL, NULL, &Type, (LPBYTE) Buffer, &BufferSize); if (rslt != ERROR_SUCCESS || Type != REG_BINARY) { goto e3; } *SuiteMask=Buffer[3]; RetVal = TRUE;
e3: RegCloseKey( hKey ); e2: RegUnLoadKey( HKEY_LOCAL_MACHINE, HIVENAME );
e1: if (GetFileAttributes(DestPath) != 0xFFFFFFFF) { SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL); DeleteFile(DestPath); wcscat(DestPath, L".LOG"); SetFileAttributes(DestPath,FILE_ATTRIBUTE_NORMAL); DeleteFile(DestPath); }
pSetupEnablePrivilegeW( SE_RESTORE_NAME, FALSE ); e0: return(RetVal); }
BOOLEAN GetProductTypeFromPath( OUT PDWORD ProductType, OUT PDWORD ProductSuite, IN PCWSTR PathToSearch ) /*++
Routine Description:
retrieves the product type and suite by looking in txtsetup.sif
Arguments:
ProductType - receives a VER_NT_* constant. ProductSuite - receives a VER_SUITE_* mask for the system. PathToSearch - specifies the path to the txtsetup.sif to be searched Return Value:
TRUE indicates success
--*/ { WCHAR Path[MAX_PATH]; UINT DontCare; HINF hInf; WCHAR Type[20]; BOOLEAN RetVal = TRUE; INFCONTEXT Context;
if (-1 == _snwprintf( Path, MAX_PATH, L"%ws\\txtsetup.sif", PathToSearch)) { RetVal = FALSE; goto e0; } TERMINATE_BUFFER(Path);
hInf = SetupOpenInfFile( Path, NULL, INF_STYLE_WIN4, &DontCare ); if (hInf == INVALID_HANDLE_VALUE) { RetVal = FALSE; goto e0; } if (SetupFindFirstLine( hInf, L"SetupData", L"ProductType", &Context) && SetupGetStringField( &Context, 1, Type, ARRAYSIZE(Type), NULL)) { switch (Type[0]) { case L'0': *ProductType = VER_NT_WORKSTATION; *ProductSuite = 0; break; case L'1': *ProductType = VER_NT_SERVER; //
// HACK alert: we have to call this API because txtsetup.sif
// didn't have the correct product type in it in win2k.
// So we do it the hard way.
//
if (!GetSuiteMaskFromPath( PathToSearch, ProductSuite)) { *ProductSuite = 0; } break; case L'2': *ProductType = VER_NT_SERVER; *ProductSuite = VER_SUITE_ENTERPRISE; break; case L'3': *ProductType = VER_NT_SERVER; *ProductSuite = VER_SUITE_ENTERPRISE | VER_SUITE_DATACENTER; break; case L'4': *ProductType = VER_NT_WORKSTATION; *ProductSuite = VER_SUITE_PERSONAL; break; default: ASSERT( FALSE && L"Unknown type in txtsetup.sif ProductType" ); RetVal = FALSE; break; }
}
SetupCloseInfFile(hInf); e0: return(RetVal);
}
//
// GetNtVersionInfo( )
//
// Retrieves the build version from the kernel
//
BOOLEAN GetNtVersionInfo( PULONGLONG Version, PWCHAR SearchDir ) { DWORD FileVersionInfoSize; DWORD VersionHandle; ULARGE_INTEGER TmpVersion; PVOID VersionInfo; VS_FIXEDFILEINFO * FixedFileInfo; UINT FixedFileInfoLength; WCHAR Path[MAX_PATH]; BOOLEAN fResult = FALSE;
TraceFunc("GetNtVersionInfo( )\n");
// Resulting string should be something like:
// "\\server\reminst\Setup\English\Images\nt50.wks\i386\ntoskrnl.exe"
if (!SearchDir) { goto e0; } lstrcpyn(Path, SearchDir, ARRAYSIZE(Path)); wcsncat(Path, L"\\ntoskrnl.exe", ARRAYSIZE(Path) - lstrlen(Path)); TERMINATE_BUFFER(Path);
FileVersionInfoSize = GetFileVersionInfoSize(Path, &VersionHandle); if (FileVersionInfoSize == 0) goto e0;
VersionInfo = LocalAlloc( LPTR, FileVersionInfoSize ); if (VersionInfo == NULL) goto e0;
if (!GetFileVersionInfo( Path, VersionHandle, FileVersionInfoSize, VersionInfo)) { goto e1; }
if (!VerQueryValue( VersionInfo, L"\\", (LPVOID*)&FixedFileInfo, &FixedFileInfoLength)) { goto e1; }
TmpVersion.HighPart = FixedFileInfo->dwFileVersionMS; TmpVersion.LowPart = FixedFileInfo->dwFileVersionLS;
//
// We need to whack the low 16 bits of the .LowPart so that
// we ignore the service pack value. For example, WindowsXP has a
// version number of 5.1.2600.0. XP-ServicePack1 has a version
// number of 5.1.2600.1038. We'd like those to match, so just whack
// the servicepack number portion.
//
TmpVersion.LowPart &= 0xFFFF0000;
*Version = TmpVersion.QuadPart;
fResult = TRUE;
e1: LocalFree( VersionInfo ); e0: RETURN(fResult); }
//
// VerifyMatchingFlatImage( )
//
BOOLEAN VerifyMatchingFlatImage( PULONGLONG VersionNeeded OPTIONAL ) { TraceFunc( "VerifyMatchingFlatImage( )\n" );
BOOLEAN fResult = FALSE; // assume failure
DWORD dwLen; WCHAR szPath[ MAX_PATH ]; WIN32_FIND_DATA fd; HANDLE hFind; ULONGLONG OurVersion; DWORD OurProductType = 0, OurProductSuiteMask = 0;
GetSystemDirectory( szPath, ARRAYSIZE( szPath )); GetNtVersionInfo( &OurVersion, szPath );
GetInstalledProductType( &OurProductType, &OurProductSuiteMask );
if (VersionNeeded) { *VersionNeeded = OurVersion; }
DebugMsg( "Our NTOSKRNL verion: %u.%u:%u.%u Type: %d Suite: %d\n", HIWORD(((PULARGE_INTEGER)&OurVersion)->HighPart), LOWORD(((PULARGE_INTEGER)&OurVersion)->HighPart), HIWORD(((PULARGE_INTEGER)&OurVersion)->LowPart), LOWORD(((PULARGE_INTEGER)&OurVersion)->LowPart), OurProductType, OurProductSuiteMask);
_snwprintf( szPath, ARRAYSIZE(szPath), L"\\\\%s\\REMINST\\Setup\\%s\\%s\\", g_ServerName, g_Language, REMOTE_INSTALL_IMAGE_DIR_W ); TERMINATE_BUFFER(szPath);
dwLen = wcslen( szPath );
wcsncat(szPath, L"*", ARRAYSIZE(szPath) - lstrlen(szPath)); TERMINATE_BUFFER(szPath);
hFind = FindFirstFile( szPath, &fd ); if ( hFind != INVALID_HANDLE_VALUE ) { do { if ( (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && StrCmp( fd.cFileName, L"." ) != 0 && StrCmp( fd.cFileName, L".." ) != 0 ) { ULONGLONG Version; DWORD ProductType = 0, ProductSuiteMask = 0; _snwprintf( &szPath[dwLen], ARRAYSIZE(szPath) - dwLen, L"%s\\%s", fd.cFileName, g_Architecture ); TERMINATE_BUFFER(szPath);
if ( GetNtVersionInfo( &Version, szPath ) && GetProductTypeFromPath( &ProductType, &ProductSuiteMask, szPath )) { DebugMsg( "%s's verion: %u.%u:%u.%u Type: %d Suite: %d\n", fd.cFileName, HIWORD(((PULARGE_INTEGER)&Version)->HighPart), LOWORD(((PULARGE_INTEGER)&Version)->HighPart), HIWORD(((PULARGE_INTEGER)&Version)->LowPart), LOWORD(((PULARGE_INTEGER)&Version)->LowPart), ProductType, ProductSuiteMask); if ( OurVersion == Version && OurProductType == ProductType && OurProductSuiteMask == ProductSuiteMask ) { wcscpy( g_ImageName, szPath ); fResult = TRUE; break; } } } } while ( FindNextFile( hFind, &fd ) ); }
FindClose( hFind );
RETURN(fResult); }
//
// VerifyServerName( )
//
// Check to see if the server is a Remote Installation Server by
// checking for the existance of the "REMINST" share.
//
DWORD VerifyServerName( ) { TraceFunc( "VerifyServerName( )\n" );
NET_API_STATUS netStatus; SHARE_INFO_0 * psi;
HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
netStatus = NetShareGetInfo( g_ServerName, L"REMINST", 0, (LPBYTE *) &psi ); if ( netStatus == NERR_Success ) { NetApiBufferFree( psi ); }
SetCursor( oldCursor );
RETURN(netStatus); }
BOOL VerifyServerAccess( PCWSTR ServerShareName, PCWSTR ServerLanguage ) /*++
Routine Description:
Checks permissions on the RIPREP server machine by trying to create a file on the server. The temp file is then deleted.
Arguments:
ServerShareName - path that we want to check permissions on. ServerLanguage - indicates the language subdirectory to check for access in.
Return value:
TRUE if the user has access to the server, FALSE otherwise.
--*/ { TraceFunc( "VerifyServerAccess( )\n" );
WCHAR FileName[MAX_PATH]; WCHAR FilePath[MAX_PATH]; BOOL RetVal; HCURSOR oldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
_snwprintf(FilePath, ARRAYSIZE(FilePath), L"\\\\%s\\reminst\\Setup\\%s\\Images", ServerShareName, ServerLanguage ); TERMINATE_BUFFER(FilePath);
RetVal = GetTempFileName( FilePath , L"ACC", 0, FileName ); if (RetVal) { //
// delete the file, we don't want to leave turds on the server
//
DeleteFile(FileName); RetVal = TRUE; } else if (GetLastError() == ERROR_ACCESS_DENIED) { RetVal = FALSE; } else { //
// GetTempFileName failed, but not because of an access problem, so
// return success
//
RetVal = TRUE; } SetCursor( oldCursor );
RETURN(RetVal); }
//
// ServerDlgCheckNextButtonActivation( )
//
VOID ServerDlgCheckNextButtonActivation( HWND hDlg ) { TraceFunc( "ServerDlgCheckNextButtonActivation( )\n" ); WCHAR szName[ MAX_PATH ]; GetDlgItemText( hDlg, IDC_E_SERVER, szName, ARRAYSIZE(szName)); PropSheet_SetWizButtons( GetParent( hDlg ), PSWIZB_BACK | (wcslen(szName) ? PSWIZB_NEXT : 0 ) ); TraceFuncExit( ); }
//
// ServerDlgProc()
//
INT_PTR CALLBACK ServerDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { ULARGE_INTEGER ImageVersion; WCHAR szTemp[ 1024 ]; WCHAR szCaption[ 1024 ]; WCHAR ErrorText[ 1024 ]; DWORD dw;
switch (uMsg) { default: return FALSE;
case WM_INITDIALOG: CenterDialog( GetParent( hDlg ) ); return FALSE;
case WM_COMMAND: switch ( LOWORD( wParam ) ) { case IDC_E_SERVER: if ( HIWORD( wParam ) == EN_CHANGE ) { ServerDlgCheckNextButtonActivation( hDlg ); } break; } break;
case WM_NOTIFY: SetWindowLongPtr( hDlg, DWLP_MSGRESULT, FALSE ); LPNMHDR lpnmhdr = (LPNMHDR) lParam; switch ( lpnmhdr->code ) { case PSN_WIZNEXT: { GetDlgItemText( hDlg, IDC_E_SERVER, g_ServerName, ARRAYSIZE(g_ServerName) );
//remove the wackwack if found
if ( g_ServerName[0] == L'\\' && g_ServerName[1] == L'\\' ) { wcscpy( g_ServerName, &g_ServerName[2] ); }
Assert( wcslen( g_ServerName ) ); DWORD dwErr = VerifyServerName( ); if ( dwErr != ERROR_SUCCESS ) { switch (dwErr) { case NERR_NetNameNotFound: MessageBoxFromStrings( hDlg, IDS_NOT_A_BINL_SERVER_TITLE, IDS_NOT_A_BINL_SERVER_TEXT, MB_OK ); break;
default: dw = LoadString( g_hinstance, IDS_FAILED_TO_CONTACT_SERVER_TITLE, szTemp, ARRAYSIZE(szTemp) ); Assert( dw ); MessageBoxFromError( hDlg, szTemp, dwErr, NULL, MB_OK ); break; } SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
break; }
BOOL fFoundMatchingFlatImage = VerifyMatchingFlatImage( (PULONGLONG)&ImageVersion ); if ( !fFoundMatchingFlatImage ) { dw = LoadString( g_hinstance, IDS_MISSING_BACKING_FLAT_IMAGE_TEXT, szTemp, ARRAYSIZE(szTemp) ); ASSERT(dw);
dw = LoadString( g_hinstance, IDS_MISSING_BACKING_FLAT_IMAGE_TITLE, szCaption, ARRAYSIZE(szCaption) ); ASSERT(dw);
_snwprintf( ErrorText, ARRAYSIZE(ErrorText), szTemp, HIWORD(ImageVersion.HighPart), LOWORD(ImageVersion.HighPart), HIWORD(ImageVersion.LowPart), g_Language ); TERMINATE_BUFFER(ErrorText);
MessageBox( hDlg, ErrorText, szCaption, MB_OK ); SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
break; }
if (!VerifyServerAccess(g_ServerName,g_Language)) { dw = LoadString( g_hinstance, IDS_SERVER_ACCESS_DESC, ErrorText, ARRAYSIZE(ErrorText) ); ASSERT(dw);
dw = LoadString( g_hinstance, IDS_SERVER_ACCESS, szCaption, ARRAYSIZE(szCaption) ); ASSERT(dw);
MessageBox( hDlg, ErrorText, szCaption, MB_OK ); SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 ); // don't go on
break; } } break;
case PSN_QUERYCANCEL: return VerifyCancel( hDlg );
case PSN_SETACTIVE: SetDlgItemText( hDlg, IDC_E_SERVER, g_ServerName ); ServerDlgCheckNextButtonActivation( hDlg ); ClearMessageQueue( ); break; } break; }
return TRUE; }
|