windows-nt/Source/XPSP1/NT/base/remoteboot/riprep/callback.cpp

1230 lines
32 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/****************************************************************************
Copyright (c) Microsoft Corporation 1998
All rights reserved
File: CALLBACK.CPP
***************************************************************************/
#include "pch.h"
#include "utils.h"
#include "tasks.h"
#include "setup.h"
#include "callback.h"
#include "logging.h"
#include "userenv.h"
// Must have this...
extern "C" {
#include <sysprep_.h>
//
// SYSPREP globals
//
extern BOOL NoSidGen;
extern BOOL PnP;
}
DEFINE_MODULE("RIPREP")
DWORD g_WorkerThreadId = 0;
HANDLE g_WorkerThreadHandle = INVALID_HANDLE_VALUE;
HWND g_hMainWindow = NULL;
HWND g_hTasksDialog = NULL;
DWORD g_NeedDlg = NULL;
#define NCOLORSHADES 32
//
// Spin( )
//
DWORD
Spin( )
{
TraceFunc( "Spin( )\n" );
DWORD dwResult;
MSG Msg;
// We will spin in here until the end
while ( WAIT_TIMEOUT == (dwResult = WaitForSingleObject( g_WorkerThreadHandle, 50 )) )
{
while ( PeekMessage( &Msg, NULL, NULL, NULL, PM_REMOVE ) )
{
if (Msg.message == WM_SYSKEYUP)
continue; // ignore
if (Msg.message == WM_KEYDOWN)
continue; // ignore
if (Msg.message == WM_KEYUP)
continue; // ignore
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
}
RETURN(dwResult);
}
//
// WorkerThreadProc( )
//
DWORD
WorkerThreadProc(
LPVOID lParam )
{
// Place in the log all the gathered information for the wizard
// as well as system APIs.
LogMsg( L"Server : %s\r\n", g_ServerName );
LogMsg( L"Image Dir : %s\r\n", g_MirrorDir );
LogMsg( L"Language : %s\r\n", g_Language );
LogMsg( L"Architecture: %s\r\n", g_Architecture );
LogMsg( L"Description : %s\r\n", g_Description );
LogMsg( L"HelpText : %s\r\n", g_HelpText );
LogMsg( L"SystemRoot : %s\r\n", g_SystemRoot );
LogMsg( L"Winnt Dir : %s\r\n", g_WinntDirectory );
// Start the IMIRROR task list
DWORD dw = ProcessToDoItems( );
DebugMsg( "ProcessToDoItems( ) completed: 0x%08x\n", dw );
return dw;
}
HWND g_hParent = NULL;
//
// MainWindowProc ( )
//
LRESULT CALLBACK
MainWindowProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
static WCHAR szTitle[ 256 ];
static DWORD dwTitleLength;
static HFONT BigBoldFont = NULL;
switch(uMsg)
{
case WM_NCCREATE:
return TRUE; // keep going
case WM_CREATE:
{
DWORD dw;
dw = LoadString( g_hinstance, IDS_APPNAME, szTitle, ARRAYSIZE(szTitle));
Assert(dw);
dwTitleLength = wcslen( szTitle );
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
LOGBRUSH brush;
HBRUSH hBrush;
HBRUSH hOldBrush;
HFONT hFont;
INT n = 0;
BeginPaint( hDlg, &ps );
rc.left = 0;
rc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
rc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
INT yDelta= max(rc.bottom/NCOLORSHADES,1); // height of one shade band
rc.top = rc.bottom - yDelta;
// Shade the background
while (rc.top >= 0)
{
brush.lbColor = RGB(0, 0, (256*n)/NCOLORSHADES);
brush.lbStyle = BS_SOLID;
hBrush = (HBRUSH) CreateBrushIndirect( &brush );
hOldBrush = (HBRUSH) SelectObject(ps.hdc, hBrush);
FillRect( ps.hdc, &rc, hBrush );
SelectObject(ps.hdc, hOldBrush);
DeleteObject(hBrush);
rc.top -= yDelta;
rc.bottom -= yDelta;
n++;
}
if ( !BigBoldFont )
{
HFONT Font;
LOGFONT LogFont;
WCHAR FontSizeString[24];
INT FontSize;
Font = (HFONT) GetStockObject( SYSTEM_FONT );
if ( (Font ) && GetObject( Font, sizeof(LOGFONT), &LogFont) )
{
DWORD dw = LoadString( g_hinstance,
IDS_LARGEFONTNAME,
LogFont.lfFaceName,
LF_FACESIZE);
Assert( dw );
LogFont.lfWeight = 700;
FontSize = yDelta;
LogFont.lfHeight = 0 - (GetDeviceCaps(ps.hdc,LOGPIXELSY) * FontSize / 72);
LogFont.lfWidth = 0;
BigBoldFont = CreateFontIndirect(&LogFont);
}
}
// Redraw the title
SetBkMode( ps.hdc, TRANSPARENT );
SelectObject( ps.hdc, BigBoldFont );
SetTextColor( ps.hdc, RGB( 255, 255, 255 ) );
TextOut(ps.hdc, yDelta, yDelta, szTitle, dwTitleLength );
EndPaint( hDlg, &ps );
}
break;
case WM_CHAR:
case WM_KEYDOWN:
case WM_KEYUP:
case WM_MOUSEACTIVATE:
case WM_MOUSEMOVE:
case WM_MOUSEWHEEL:
break; // ignore
case WM_DESTROY:
if ( BigBoldFont )
DeleteObject( BigBoldFont );
break;
case WM_ERASEBKGND:
// Don't waste time erasing
return TRUE; // non-zero
default:
return DefWindowProc( hDlg, uMsg, wParam, lParam );
}
return FALSE;
}
//
// BeginProcess( )
//
HRESULT
BeginProcess(
HWND hParent)
{
TraceFunc( "BeginProcess( )\n" );
MSG Msg;
WNDCLASSEX wndClass;
ATOM atom;
RECT rc;
HWND hwndDesktop = GetDesktopWindow( );
DWORD dwExStyle;
GetWindowRect( hwndDesktop, &rc );
// Create our window class
ZeroMemory( &wndClass, sizeof(wndClass) );
wndClass.cbSize = sizeof(wndClass);
wndClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
wndClass.hInstance = g_hinstance;
wndClass.lpfnWndProc = (WNDPROC) &MainWindowProc;
wndClass.lpszClassName = L"MondoWindow";
wndClass.style = CS_CLASSDC | CS_NOCLOSE;
atom = RegisterClassEx( &wndClass );
Assert( atom );
g_hParent = hParent;
#ifdef DEBUG
dwExStyle = ( g_dwTraceFlags ? 0 : WS_EX_TOPMOST );
#else
dwExStyle = WS_EX_TOPMOST;
#endif
g_hMainWindow = CreateWindowEx( dwExStyle,
L"MondoWindow",
L"",
WS_POPUP | WS_VISIBLE,
GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN),
NULL,
NULL,
g_hinstance,
NULL );
Assert( g_hMainWindow );
g_hTasksDialog = CreateDialog(g_hinstance, MAKEINTRESOURCE(IDD_TASKS), g_hMainWindow, TasksDlgProc );
if ( g_hTasksDialog )
{
g_WorkerThreadHandle = CreateThread( NULL, NULL, WorkerThreadProc, NULL, 0, &g_WorkerThreadId );
Spin( );
SendMessage( g_hTasksDialog, WM_DESTROY, 0, 0 );
}
HRETURN(S_OK);
}
//
// IsFileInExclusionList()
//
BOOLEAN
IsFileInExclusionList(
IN PCWSTR FileName
)
/*++
Description:
This routine searches the exclusion list in our INF file.
Parameters:
FileName : File to search the INF for.
Return Value:
TRUE - The file does exist in the INF
FALSE - The file does not exist in the INF
++*/
{
#define SKIPFLAG_DIRECTORY 1
#define SKIPFLAG_FILTEREXTENSION 2
PWSTR FullPath = NULL;
PWSTR DirectoryName = NULL;
INFCONTEXT Context;
INT Flags = 0;
WCHAR FilterExtension[10];
BOOLEAN ReturnValue = FALSE;
//
// Make sure we have our INF.
//
if( g_hCompatibilityInf == INVALID_HANDLE_VALUE ) {
//
// Probably hasn't been initialized yet. Assume the
// file isn't in the INF.
//
return FALSE;
}
if( FileName == NULL ) {
return FALSE;
}
//
// Get a local copy of the filename so we can operate on it
// without worry of corrupting the caller's data.
//
if( wcsncmp(FileName, L"\\\\?\\", 4) == 0 ) {
FullPath = (PWSTR)TraceStrDup( FileName+4 );
} else {
FullPath = (PWSTR)TraceStrDup( FileName );
}
if( FullPath == NULL ) {
DebugMsg( "IsFileInExclusionList: Odd pathname %s.\n",
FileName );
return FALSE;
}
//
// See if it's explicitly listed in the INF
//
if (SetupFindFirstLine( g_hCompatibilityInf,
L"FilesToSkipCopy",
FullPath,
&Context)) {
DebugMsg( "IsFileInExclusionList: Found file %s in the INF exclusion list.\n",
FullPath );
ReturnValue = TRUE;
goto Cleanup;
}
//
// The file isn't specifically listed in the INF. See if
// the directory this file is in is listed.
//
// Start whacking file/directory names off the end of the
// path to see if the result is in our exclusion list.
//
//
// Remember the filename.
//
FileName = wcsrchr(FullPath, L'\\');
if( FileName == NULL ) {
DebugMsg( "IsFileInExclusionList: File isn't in exclusion list and has no directory path.\n" );
ReturnValue = FALSE;
goto Cleanup;
}
FileName++;
while( DirectoryName = wcsrchr(FullPath, L'\\') ) {
*DirectoryName = NULL;
if( SetupFindFirstLine( g_hCompatibilityInf,
L"FilesToSkipCopy",
FullPath,
&Context)) {
//
// The directory name *IS* in there. See if we need to
// skip all files in this directory, or only some.
//
Flags = 0;
if( SetupGetIntField( &Context, 1, &Flags) &&
((Flags & SKIPFLAG_FILTEREXTENSION) == 0)) {
//
// We don't have the filter flag, so we will just
// skip all files in this directory.
//
DebugMsg( "IsFileInExclusionList: Found file %s in %s in the exclusion list (based on the name of his directory).\n",
FileName,
FullPath );
ReturnValue = TRUE;
goto Cleanup;
}
//
// See if we should skip files with a specified extension.
//
if( SetupGetStringField( &Context,
2,
FilterExtension,
ARRAYSIZE(FilterExtension),
NULL )) {
PCWSTR q = wcsrchr( FileName, L'.' );
if (q) {
q++;
if (_wcsicmp(q, FilterExtension) == 0) {
DebugMsg( "IsFileInExclusionList: Found file %s in %s with extension %s in the exclusion list (based on the directory and extension of the file).\n",
FileName,
FullPath,
q );
ReturnValue = TRUE;
goto Cleanup;
}
}
}
}
}
Cleanup:
if( FullPath ) {
DebugMemoryDelete( FullPath );
}
return ReturnValue;
}
//
// ConvTestErrorFn()
//
NTSTATUS
ConvTestErrorFn(
IN PVOID Context,
IN NTSTATUS Status,
IN IMIRROR_TODO IMirrorFunctionId
)
{
TraceFunc( "ConvTestErrorFn( ... )\n" );
WCHAR szMessage[ 256 ];
DWORD dw;
LBITEMDATA item;
if ( Status != ERROR_SUCCESS )
{
DebugMsg("ERROR REPORTED! : Context 0x%x, Status 0x%x, In Func 0x%x\n", Context, Status, IMirrorFunctionId );
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = (IMirrorFunctionId == CheckPartitions) ? NULL : (LPWSTR)Context;
item.uState = Status; // used as input and output
item.todo = IMirrorFunctionId;
BOOL b = (BOOL)SendMessage( g_hTasksDialog, WM_ERROR, 0, (LPARAM) &item );
if ( !b )
{
Status = ERROR_REQUEST_ABORTED;
}
else
{
Status = item.uState;
}
if ( Status == ERROR_SUCCESS )
{
dw = LoadString( g_hinstance, IDS_ERROR_IGNORED, szMessage, ARRAYSIZE( szMessage ));
Assert( dw );
}
else if ( Status == STATUS_RETRY )
{
dw = LoadString( g_hinstance, IDS_STATUS_RETRY, szMessage, ARRAYSIZE( szMessage ));
Assert( dw );
}
else // other should be abort
{
Assert( Status == ERROR_REQUEST_ABORTED );
dw = LoadString( g_hinstance, IDS_OPERATION_ABORTED, szMessage, ARRAYSIZE( szMessage ));
Assert( dw );
ClearAllToDoItems(FALSE);
}
Assert( dw );
LogMsg( szMessage );
}
RETURN(Status);
}
NTSTATUS
ConvTestNowDoingFn(
IN PVOID Context,
IN IMIRROR_TODO Function,
IN PWSTR String
)
{
TraceFunc( "ConvTestNowDoingFn( )\n" );
LPWSTR pszMessage;
WCHAR szMessage[ 256 ];
LPWSTR pszString;
HWND hwnd = GetDlgItem( g_hTasksDialog, IDC_L_TASKS );
INT uCount;
DWORD dw;
LPLBITEMDATA pitem = NULL;
NTSTATUS Status = ERROR_SUCCESS;
static lastToDo = IMirrorNone;
static BOOL fAlreadyAdjusted = FALSE;
if ( String ) {
pszString = (LPWSTR)TraceStrDup( String );
// DebugMsg( "Received: %s\n", String );
} else {
pszString = NULL;
}
// if we are onto another task, mark the previous one done
// and mark this one as started.
if ( lastToDo != Function )
{
uCount = ListBox_GetCount( hwnd );
while (uCount>=0)
{
LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
uCount--;
if ( lResult == LB_ERR )
continue;
pitem = (LPLBITEMDATA) lResult;
pitem->fSeen = TRUE;
if ( pitem->todo == Function )
{
if ( pitem->uState == STATE_NOTSTARTED )
{
pitem->uState = STATE_STARTED;
InvalidateRect( hwnd, NULL, TRUE ); // force redraw
}
}
else
{
if ( pitem->uState == STATE_STARTED )
{
pitem->uState = STATE_DONE;
InvalidateRect( hwnd, NULL, TRUE ); // force redraw
}
}
}
lastToDo = Function;
}
switch (Function) {
case IMirrorInitialize:
dw = LoadString( g_hinstance, IDS_INITIALIZING, szMessage, ARRAYSIZE(szMessage) );
Assert(dw);
break;
case VerifySystemIsNt5:
dw = LoadString( g_hinstance, IDS_VERIFYING_WINDOWS_VERSION, szMessage, ARRAYSIZE(szMessage) );
Assert(dw);
break;
case CheckPartitions:
dw = LoadString( g_hinstance, IDS_ANALYZING_PARTITIONS, szMessage, ARRAYSIZE(szMessage) );
Assert(dw);
break;
case CopyPartitions:
dw = LoadString( g_hinstance, IDS_COPYING_PARTITIONS, szMessage, ARRAYSIZE(szMessage) );
Assert(dw);
break;
case CopyFiles:
if ( pszString == NULL )
{ // Only need to do this once.
WCHAR ProfilesDirectory[MAX_PATH];
OSVERSIONINFO OsVersion;
//
// Begin SYSPREP ops
//
if( !NoSidGen && !IsSetupClPresent() )
{
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"SETUPCL.EXE";
item.uState = ERROR_FILE_NOT_FOUND;
item.todo = Function;
SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
Status = STATUS_REQUEST_ABORTED;
}
//
// Prepare to run Setupcl. This will also call into
// RunExternalUniqueness which gives others a chance to save
// any info that needs to be copied to the server.
//
if (!NoSidGen && !PrepForSidGen())
{
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"Preparing SIDs error";
item.uState = ERROR_FILE_NOT_FOUND;
item.todo = Function;
SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
Status = STATUS_REQUEST_ABORTED;
}
//
// Syprep cleanup which updates files that are required to be copied
// over to the server.
//
if (!AdjustFiles())
{
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"Adjusting files error";
item.uState = ERROR_FILE_NOT_FOUND;
item.todo = Function;
SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
Status = STATUS_REQUEST_ABORTED;
}
#ifndef _IA64_
//
// Make sure we're on something reasonably current before
// we attempt to ReArm the license. The APIs just didn't
// exist on win2k.
//
OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if( (GetVersionEx(&OsVersion)) &&
(OsVersion.dwMajorVersion >= 5) &&
(OsVersion.dwMinorVersion >= 1) ) {
dw = ReArm();
if( dw != ERROR_SUCCESS ) {
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"Rearming";
item.uState = dw;
item.todo = Function;
SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
Status = STATUS_REQUEST_ABORTED;
}
}
#endif
//
// We need to assign a DirectoryID to the directory containing
// the user profiles. There is no hardcoded DirID for this, so
// we'll make one up and tell Setupapi about it.
//
dw = MAX_PATH;
if( !GetProfilesDirectory( ProfilesDirectory,
&dw ) ) {
//
// We should never get here, but just in case.
//
wcscpy( ProfilesDirectory, L"C:\\Documents and Settings" );
}
if (g_hCompatibilityInf != INVALID_HANDLE_VALUE) {
if( !SetupSetDirectoryId( g_hCompatibilityInf,
PROFILES_DIRID,
ProfilesDirectory ) ) {
ASSERT( FALSE && L"Unable to SetupSetDirectoryId for user profiles" );
}
}
//
// End SYSPREP ops
//
}
else // if ( pszString )
{
if( IsFileInExclusionList(pszString) ) {
//
// It's in the exclusion list.
//
DebugMsg( "ConvTestNowDoingFn: Skipping file %s because it's in the INF exclusion list.\n",
pszString );
RETURN(E_FAIL);
}
}
dw = LoadString( g_hinstance, IDS_COPYING_FILES, szMessage, ARRAYSIZE(szMessage) );
Assert(dw);
break;
case CopyRegistry:
//
// Begin SYSPREP ops
//
Status = ERROR_SUCCESS;
if ( IsDomainMember( ) )
{
RetryUnjoin:
Status = NetUnjoinDomain( NULL, NULL, NULL, 0 );
if ( Status != NERR_Success )
{
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"Remove from Domain Error";
item.uState = Status;
item.todo = Function;
SendMessage( g_hTasksDialog, WM_ERROR, 0, (LPARAM) &item );
if ( Status == ERROR_SUCCESS )
{
dw = LoadString( g_hinstance, IDS_ERROR_IGNORED, szMessage, ARRAYSIZE( szMessage ));
}
else if ( Status == STATUS_RETRY )
{
dw = LoadString( g_hinstance, IDS_STATUS_RETRY, szMessage, ARRAYSIZE( szMessage ));
}
else // other should be abort
{
Assert( Status == ERROR_REQUEST_ABORTED );
dw = LoadString( g_hinstance, IDS_OPERATION_ABORTED, szMessage, ARRAYSIZE( szMessage ));
}
Assert( dw );
LogMsg( szMessage );
if ( Status == STATUS_RETRY )
{
goto RetryUnjoin;
}
}
}
if( !fAlreadyAdjusted )
{
WCHAR szSrcPath[MAX_PATH];
fAlreadyAdjusted = TRUE;
wsprintf( szSrcPath, L"%s\\ristndrd.sif", g_ImageName );
//
// We are going to munge some system values. Prevent us for bailing
// without a reboot.
//
g_fRebootOnExit = TRUE;
if ( Status != ERROR_SUCCESS
|| !RemoveNetworkSettings(szSrcPath)
|| !AdjustRegistry( FALSE /* no, do not remove networking*/) )
{
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"Registry Error";
item.uState = GetLastError( );
item.todo = Function;
SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
Status = STATUS_REQUEST_ABORTED;
}
}
if ( Status == ERROR_SUCCESS )
{
NukeMruList();
}
else
{
ClearAllToDoItems(FALSE);
}
//
// End SYSPREP ops
//
dw = LoadString( g_hinstance, IDS_COPYING_REGISTRY, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case PatchDSEntries:
dw = LoadString( g_hinstance, IDS_UPDATING_DS_ENTRIES, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case RebootSystem:
dw = LoadString( g_hinstance, IDS_REBOOTING_SYSTEM, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
default:
dw = LoadString( g_hinstance, IDS_DOING_UNKNOWN_TASK, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
}
pszMessage = (LPWSTR) TraceStrDup( szMessage );
if ( !pszMessage )
RETURN(E_OUTOFMEMORY);
PostMessage( g_hTasksDialog, WM_UPDATE, (WPARAM)pszMessage, (LPARAM)pszString );
// These were handed off to another thread. Don't track them anymore in
// this thread.
DebugMemoryDelete( pszMessage );
if (pszString) {
DebugMemoryDelete( pszString );
}
if ( Status != NO_ERROR )
{
if( pitem ) {
pitem->uState = STATE_ERROR;
}
InvalidateRect( hwnd, NULL, TRUE ); // force redraw
ClearAllToDoItems(FALSE);
}
RETURN(Status);
}
NTSTATUS
ConvTestGetServerFn(
IN PVOID Context,
OUT PWSTR Server,
IN OUT PULONG Length
)
{
TraceFunc( "ConvTestGetServerFn( )\n" );
StrCpy( Server, g_ServerName );
*Length = (wcslen(Server) + 1) * sizeof(WCHAR);
DebugMsg( "Sending: %s\n", Server );
RETURN((*Length == sizeof(WCHAR)) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS);
}
NTSTATUS
ConvTestGetMirrorDirFn(
IN PVOID Context,
OUT PWSTR Mirror,
IN OUT PULONG Length
)
{
TraceFunc( "ConvTestGetMirrorDirFn( )\n" );
wsprintf( Mirror,
L"\\\\%s\\REMINST\\Setup\\%s\\%s\\%s",
g_ServerName,
g_Language,
REMOTE_INSTALL_IMAGE_DIR_W,
g_MirrorDir );
CreateDirectory( Mirror, NULL );
wsprintf( Mirror,
L"\\\\%s\\REMINST\\Setup\\%s\\%s\\%s\\%s",
g_ServerName,
g_Language,
REMOTE_INSTALL_IMAGE_DIR_W,
g_MirrorDir,
g_Architecture );
CreateDirectory( Mirror, NULL );
*Length = (wcslen(Mirror) + 1) * sizeof(WCHAR);
DebugMsg( "Sending: %s\n", Mirror );
RETURN((*Length == sizeof(WCHAR)) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS);
}
NTSTATUS
ConvTestFileCreateFn(
IN PVOID Context,
IN PWSTR FileName,
IN ULONG FileAction,
IN ULONG Status
)
{
TraceFunc( "ConvTestFileCreateFn( )\n" );
if (Status != 0) {
if( IsFileInExclusionList( FileName ) ) {
//
// It's in the exclusion list.
//
DebugMsg( "ConvTestFileCreateFn: Skipping file %s because it's in the INF exclusion list.\n",
FileName );
Status = 0;
}
if (Status != 0) {
Status = ConvTestErrorFn( FileName, Status, CopyFiles );
}
} else {
DebugMsg("created %ws\n", FileName);
}
RETURN(Status);
}
NTSTATUS
ConvTestReinitFn(
IN PVOID Context
)
{
TraceFunc( "ConvTestReinitFn()\n" );
WCHAR Tmp[256] = L"c";
if (Tmp[0] != 'c') {
ClearAllToDoItems(FALSE);
InitToDo();
}
RETURN(STATUS_SUCCESS);
}
NTSTATUS
ConvTestGetSetupFn(
IN PVOID Context,
IN PWSTR Server,
OUT PWSTR SetupPath,
IN OUT PULONG Length
)
{
TraceFunc( "ConvTestGetSetupFn()\n" );
wcscpy( SetupPath, g_ImageName );
*Length = wcslen( SetupPath );
DebugMsg( "Sending: %s\n", SetupPath );
RETURN(STATUS_SUCCESS);
}
NTSTATUS
ConvTestSetSystemFn(
IN PVOID Context,
IN PWSTR SystemPath,
IN ULONG Length
)
{
NTSTATUS err;
TraceFunc( "ConvTestSetSystemFn()\n" );
if (Length <= ARRAYSIZE(g_SystemRoot)) {
wcscpy( g_SystemRoot, SystemPath );
err = STATUS_SUCCESS;
} else {
err = ERROR_BAD_LENGTH;
}
RETURN(err);
}
NTSTATUS
ConvAddToDoItemFn(
IN PVOID Context,
IN IMIRROR_TODO Function,
IN PWSTR String,
IN ULONG Length
)
{
LPLBITEMDATA pitem;
HWND hwnd = GetDlgItem( g_hTasksDialog, IDC_L_TASKS );
WCHAR szMessage[ 256 ];
DWORD dw;
INT uCount;
TraceFunc( "ConvAddToDoItemFn()\n" );
pitem = (LPLBITEMDATA) TraceAlloc( LMEM_FIXED, sizeof(LBITEMDATA));
if ( !pitem)
RETURN(E_OUTOFMEMORY);
switch (Function) {
case IMirrorInitialize:
dw = LoadString( g_hinstance, IDS_INITIALIZE, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case VerifySystemIsNt5:
dw = LoadString( g_hinstance, IDS_VERIFY_WINDOWS_VERSION, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case CheckPartitions:
dw = LoadString( g_hinstance, IDS_ANALYZE_PARTITIONS, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case CopyPartitions:
dw = LoadString( g_hinstance, IDS_COPY_PARTITIONS, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case CopyFiles:
dw = LoadString( g_hinstance, IDS_COPY_FILES, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case CopyRegistry:
dw = LoadString( g_hinstance, IDS_COPY_REGISTRY, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case PatchDSEntries:
dw = LoadString( g_hinstance, IDS_PATH_DS_ENTRIES, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
case RebootSystem:
dw = LoadString( g_hinstance, IDS_REBOOT_SYSTEM, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
break;
default:
dw = LoadString( g_hinstance, IDS_UNKNOWN_TASK, szMessage, ARRAYSIZE( szMessage ));
Assert(dw);
}
pitem->pszText = (LPWSTR) TraceStrDup( szMessage );
pitem->uState = STATE_NOTSTARTED;
pitem->todo = Function;
pitem->fSeen = FALSE;
if ( !pitem->pszText )
{
TraceFree( pitem );
RETURN(E_OUTOFMEMORY);
}
// skip the "done" items
uCount = 0;
while (uCount>=0)
{
LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
if ( lResult == LB_ERR )
break;
LPLBITEMDATA panitem = (LPLBITEMDATA) lResult;
if ( panitem->uState == STATE_STARTED )
{
uCount++;
break;
}
if ( panitem->uState != STATE_DONE )
break;
uCount++;
}
// go to end of the "unseen" items
while (uCount>=0)
{
LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
if ( lResult == LB_ERR )
break;
LPLBITEMDATA panitem = (LPLBITEMDATA) lResult;
uCount++;
if ( panitem->fSeen )
{
uCount--;
break;
}
}
ListBox_InsertString( hwnd, uCount, pitem );
InvalidateRect( hwnd, NULL, TRUE ); // force redraw
DebugMsg( "Added ToDo Item (%d): %s\n", uCount, pitem->pszText );
RETURN(STATUS_SUCCESS);
}
NTSTATUS
ConvRemoveToDoItemFn(
IN PVOID Context,
IN IMIRROR_TODO Function,
IN PWSTR String,
IN ULONG Length
)
{
LPLBITEMDATA pitem;
HWND hwnd = GetDlgItem( g_hTasksDialog, IDC_L_TASKS );
INT uCount;
TraceFunc( "ConvRemoveToDoItemFn()\n" );
uCount = ListBox_GetCount( hwnd );
while (uCount>=0)
{
LRESULT lResult = ListBox_GetItemData( hwnd, uCount );
uCount--;
if ( lResult == LB_ERR )
continue;
pitem = (LPLBITEMDATA) lResult;
if ( pitem->todo == Function )
{
pitem->uState = STATE_STARTED;
break;
}
}
RETURN(STATUS_SUCCESS);
}
NTSTATUS
ConvRebootFn(
IN PVOID Context
)
{
DWORD Error;
// do the last minute things
EndProcess( g_hTasksDialog );
#ifdef DEBUG
// if Debugging, don't reboot
if ( !g_dwTraceFlags )
{
#endif
if (!DoShutdown(FALSE)) {
LBITEMDATA item;
// Error will be logged in TASKS.CPP
item.fSeen = FALSE;
item.pszText = L"Shutdown Error";
item.uState = GetLastError( );
item.todo = RebootSystem;
SendMessage( g_hTasksDialog, WM_ERROR_OK, 0, (LPARAM) &item );
return item.uState;
}
//
// Prevent the error log from being displayed twice. Since
// we are set to reboot/shutdown now, this flag can be
// safely reset.
//
g_fRebootOnExit = FALSE;
#ifdef DEBUG
}
#endif
return STATUS_SUCCESS;
}
BOOL
DoShutdown(
IN BOOL Restart
)
{
NTSTATUS Status;
BOOLEAN WasEnabled;
Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
(BOOLEAN)TRUE,
TRUE,
&WasEnabled
);
if (Status == STATUS_NO_TOKEN) {
//
// No thread token, use the process token
//
Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
(BOOLEAN)TRUE,
FALSE,
&WasEnabled
);
}
if (Restart) {
return ExitWindowsEx( EWX_REBOOT | EWX_FORCEIFHUNG, 0 );
} else {
return InitiateSystemShutdown(NULL, NULL, 0, TRUE, FALSE);
}
}