mirror of https://github.com/lianthony/NT4.0
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.
602 lines
17 KiB
602 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fileq6.c
|
|
|
|
Abstract:
|
|
|
|
Copy list scanning functions.
|
|
|
|
Author:
|
|
|
|
Ted Miller (tedm) 24-Feb-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "setupntp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Define mask that isolates the action to be performed on the file queue.
|
|
//
|
|
#define SPQ_ACTION_MASK (SPQ_SCAN_FILE_PRESENCE | SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_USE_CALLBACK)
|
|
|
|
BOOL
|
|
pScanCheckValidity(
|
|
IN PCTSTR FileName
|
|
);
|
|
|
|
|
|
BOOL
|
|
_SetupScanFileQueue(
|
|
IN HSPFILEQ FileQueue,
|
|
IN DWORD Flags,
|
|
IN HWND Window, OPTIONAL
|
|
IN PVOID CallbackRoutine, OPTIONAL
|
|
IN PVOID CallbackContext, OPTIONAL
|
|
OUT PDWORD Result,
|
|
IN BOOL IsUnicodeCallback
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation for SetupScanFileQueue, handles ANSI and Unicode
|
|
callback functions.
|
|
|
|
Arguments:
|
|
|
|
Same as SetupScanFileQueue().
|
|
|
|
IsUnicodeCallBack - supplies flag indicating whether callback routine is
|
|
expecting unicode params. Meaningful only in UNICODE version of DLL.
|
|
|
|
Return Value:
|
|
|
|
Same as SetupScanFileQueue().
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Action;
|
|
PSP_FILE_QUEUE Queue;
|
|
PSP_FILE_QUEUE_NODE QueueNode;
|
|
PSP_FILE_QUEUE_NODE TempNode;
|
|
PSOURCE_MEDIA_INFO SourceMedia;
|
|
BOOL Continue;
|
|
TCHAR TargetPath[MAX_PATH];
|
|
BOOL Err;
|
|
int i;
|
|
PTSTR Message;
|
|
DWORD flags;
|
|
|
|
Queue = (PSP_FILE_QUEUE)FileQueue;
|
|
|
|
//
|
|
// Validate arguments. Exactly one action flag must be specified.
|
|
//
|
|
if(Result) {
|
|
*Result = 0;
|
|
} else {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return(FALSE);
|
|
}
|
|
switch(Action = (Flags & SPQ_ACTION_MASK)) {
|
|
case SPQ_SCAN_FILE_PRESENCE:
|
|
case SPQ_SCAN_FILE_VALIDITY:
|
|
break;
|
|
case SPQ_SCAN_USE_CALLBACK:
|
|
if(CallbackRoutine) {
|
|
break;
|
|
}
|
|
// else fall through to invalid arg case
|
|
default:
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Process all nodes in the copy queue.
|
|
//
|
|
Err = FALSE;
|
|
Continue = TRUE;
|
|
for(SourceMedia=Queue->SourceMediaList; Continue && SourceMedia; SourceMedia=SourceMedia->Next) {
|
|
for(QueueNode=SourceMedia->CopyQueue; Continue && QueueNode; QueueNode=QueueNode->Next) {
|
|
|
|
//
|
|
// Form target path.
|
|
//
|
|
lstrcpyn(
|
|
TargetPath,
|
|
StringTableStringFromId(Queue->StringTable,QueueNode->TargetDirectory),
|
|
MAX_PATH
|
|
);
|
|
|
|
ConcatenatePaths(
|
|
TargetPath,
|
|
StringTableStringFromId(Queue->StringTable,QueueNode->TargetFilename),
|
|
MAX_PATH,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Perform check on file.
|
|
//
|
|
switch(Action) {
|
|
|
|
case SPQ_SCAN_FILE_PRESENCE:
|
|
|
|
Continue = FileExists(TargetPath,NULL);
|
|
break;
|
|
|
|
case SPQ_SCAN_FILE_VALIDITY:
|
|
|
|
Continue = pScanCheckValidity(TargetPath);
|
|
break;
|
|
|
|
case SPQ_SCAN_USE_CALLBACK:
|
|
|
|
flags = (QueueNode->InternalFlags & (INUSE_INF_WANTS_REBOOT | INUSE_IN_USE))
|
|
? SPQ_DELAYED_COPY
|
|
: 0;
|
|
|
|
*Result = (DWORD)pSetupCallMsgHandler(
|
|
CallbackRoutine,
|
|
IsUnicodeCallback,
|
|
CallbackContext,
|
|
SPFILENOTIFY_QUEUESCAN,
|
|
(UINT)TargetPath,
|
|
flags
|
|
);
|
|
|
|
Err = (*Result != NO_ERROR);
|
|
Continue = !Err;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the case of SPQ_SCAN_USE_CALLBACK, *Result is already set up
|
|
// when we get here. If Continue is TRUE then we visited all nodes
|
|
// and the presence/validity check passed on all of them. Note that
|
|
// if Continue is TRUE then Err must be FALSE.
|
|
//
|
|
if((Action == SPQ_SCAN_FILE_PRESENCE) || (Action == SPQ_SCAN_FILE_VALIDITY)) {
|
|
if(Continue) {
|
|
//
|
|
// Need to set up Result.
|
|
//
|
|
if((Flags & SPQ_SCAN_INFORM_USER) && Queue->CopyNodeCount
|
|
&& (Message = RetreiveAndFormatMessage(MSG_NO_NEED_TO_COPY))) {
|
|
|
|
//
|
|
// Overload TargetPath for use as the caption string.
|
|
//
|
|
GetWindowText(Window,TargetPath,sizeof(TargetPath)/sizeof(TargetPath[0]));
|
|
|
|
i = MessageBox(
|
|
Window,
|
|
Message,
|
|
TargetPath,
|
|
MB_APPLMODAL | MB_YESNO | MB_ICONINFORMATION
|
|
);
|
|
|
|
MyFree(Message);
|
|
|
|
if(i == IDYES) {
|
|
//
|
|
// User wants to skip copying.
|
|
//
|
|
*Result = (Queue->DeleteNodeCount || Queue->RenameNodeCount) ? 2 : 1;
|
|
} else {
|
|
//
|
|
// User wants to perform copy.
|
|
//
|
|
*Result = 0;
|
|
}
|
|
} else {
|
|
//
|
|
// Don't want to ask user. Set up Result based on whether
|
|
// there are items in the delete or rename queues.
|
|
//
|
|
*Result = (Queue->DeleteNodeCount || Queue->RenameNodeCount) ? 2 : 1;
|
|
}
|
|
} else {
|
|
//
|
|
// Presence/validity check failed.
|
|
//
|
|
*Result = 0;
|
|
}
|
|
|
|
//
|
|
// Empty the copy queue if necessary.
|
|
//
|
|
if(*Result) {
|
|
for(SourceMedia=Queue->SourceMediaList; Continue && SourceMedia; SourceMedia=SourceMedia->Next) {
|
|
for(QueueNode=SourceMedia->CopyQueue; QueueNode; QueueNode=TempNode) {
|
|
TempNode = QueueNode->Next;
|
|
MyFree(QueueNode);
|
|
}
|
|
Queue->CopyNodeCount -= SourceMedia->CopyNodeCount;
|
|
SourceMedia->CopyQueue = NULL;
|
|
SourceMedia->CopyNodeCount = 0;
|
|
}
|
|
//
|
|
// We think we just removed all files in all copy queues.
|
|
// The 2 counts we maintain should be in sync -- meaning that
|
|
// the total copy node count should now be 0.
|
|
//
|
|
MYASSERT(Queue->CopyNodeCount == 0);
|
|
}
|
|
}
|
|
|
|
return(!Err);
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
//
|
|
// ANSI version. Also need undecorated (Unicode) version for apps that were linked
|
|
// before we had ANSI and Unicode versions.
|
|
//
|
|
BOOL
|
|
SetupScanFileQueueA(
|
|
IN HSPFILEQ FileQueue,
|
|
IN DWORD Flags,
|
|
IN HWND Window, OPTIONAL
|
|
IN PSP_FILE_CALLBACK_A CallbackRoutine, OPTIONAL
|
|
IN PVOID CallbackContext, OPTIONAL
|
|
OUT PDWORD Result
|
|
)
|
|
{
|
|
BOOL b;
|
|
|
|
b = _SetupScanFileQueue(
|
|
FileQueue,
|
|
Flags,
|
|
Window,
|
|
CallbackRoutine,
|
|
CallbackContext,
|
|
Result,
|
|
FALSE
|
|
);
|
|
|
|
return(b);
|
|
}
|
|
|
|
#undef SetupScanFileQueue
|
|
BOOL
|
|
SetupScanFileQueue(
|
|
IN HSPFILEQ FileQueue,
|
|
IN DWORD Flags,
|
|
IN HWND Window, OPTIONAL
|
|
IN PSP_FILE_CALLBACK_W CallbackRoutine, OPTIONAL
|
|
IN PVOID CallbackContext, OPTIONAL
|
|
OUT PDWORD Result
|
|
)
|
|
{
|
|
BOOL b;
|
|
|
|
b = _SetupScanFileQueue(
|
|
FileQueue,
|
|
Flags,
|
|
Window,
|
|
CallbackRoutine,
|
|
CallbackContext,
|
|
Result,
|
|
TRUE
|
|
);
|
|
|
|
return(b);
|
|
}
|
|
#else
|
|
//
|
|
// ANSI version. Also need undecorated (ANSI) version for apps that were linked
|
|
// before we had ANSI and Unicode versions.
|
|
//
|
|
BOOL
|
|
SetupScanFileQueueW(
|
|
IN HSPFILEQ FileQueue,
|
|
IN DWORD Flags,
|
|
IN HWND Window, OPTIONAL
|
|
IN PSP_FILE_CALLBACK_W CallbackRoutine, OPTIONAL
|
|
IN PVOID CallbackContext, OPTIONAL
|
|
OUT PDWORD Result
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(FileQueue);
|
|
UNREFERENCED_PARAMETER(Flags);
|
|
UNREFERENCED_PARAMETER(Window);
|
|
UNREFERENCED_PARAMETER(CallbackRoutine);
|
|
UNREFERENCED_PARAMETER(CallbackContext);
|
|
UNREFERENCED_PARAMETER(Result);
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return(FALSE);
|
|
}
|
|
|
|
#undef SetupScanFileQueue
|
|
BOOL
|
|
SetupScanFileQueue(
|
|
IN HSPFILEQ FileQueue,
|
|
IN DWORD Flags,
|
|
IN HWND Window, OPTIONAL
|
|
IN PSP_FILE_CALLBACK_A CallbackRoutine, OPTIONAL
|
|
IN PVOID CallbackContext, OPTIONAL
|
|
OUT PDWORD Result
|
|
)
|
|
{
|
|
BOOL b;
|
|
|
|
b = _SetupScanFileQueue(
|
|
FileQueue,
|
|
Flags,
|
|
Window,
|
|
CallbackRoutine,
|
|
CallbackContext,
|
|
Result,
|
|
FALSE
|
|
);
|
|
|
|
return(b);
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
#ifdef UNICODE
|
|
SetupScanFileQueueW(
|
|
#else
|
|
SetupScanFileQueueA(
|
|
#endif
|
|
IN HSPFILEQ FileQueue,
|
|
IN DWORD Flags,
|
|
IN HWND Window, OPTIONAL
|
|
IN PSP_FILE_CALLBACK CallbackRoutine, OPTIONAL
|
|
IN PVOID CallbackContext, OPTIONAL
|
|
OUT PDWORD Result
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine scans a setup file queue, performing an operation on each
|
|
node in its copy list. The operation is specified by a set of flags.
|
|
|
|
A caller can use this API to determine whether all files that have been
|
|
enqueued for copy already exist on the target, and if so, to inform the
|
|
user, who may elect to skip the file copying. This can spare the user from
|
|
having to furnish Setup media in many cases.
|
|
|
|
Arguments:
|
|
|
|
FileQueue - supplies handle to Setup file queue whose copy list is to
|
|
be scanned/iterated.
|
|
|
|
Flags - supplies a set of values that control operation of the API. A
|
|
combination of the following values:
|
|
|
|
SPQ_SCAN_FILE_PRESENCE - determine whether all target files in the
|
|
copy queue are already present on the target.
|
|
|
|
SPQ_SCAN_FILE_VALIDITY - determine whether all target files in the
|
|
copy queue are already present on the target, and perform a
|
|
validity check on them.
|
|
(For now this flag is equivalent to SPQ_SCAN_FILE_PRESENCE.)
|
|
|
|
SPQ_SCAN_USE_CALLBACK - for each node in the queue, call the
|
|
callback routine. If the callback routine returns non-0 then
|
|
queue processing is stopped and this routine returns FALSE
|
|
immediately.
|
|
|
|
Exactly one of SPQ_SCAN_FILE_PRESENCE, SPQ_SCAN_FILE_VALIDITY, or
|
|
SPQ_SCAN_USE_CALLBACK must be specified.
|
|
|
|
SPQ_SCAN_INFORM_USER - if specified and all files in the queue
|
|
pass the presence/validity check, then this routine will inform
|
|
the user that the operation he is attempting requires files but
|
|
that we believe all files are already present. Ignored if
|
|
SPQ_SCAN_FILE_PRESENCE or SPQ_SCAN_FILE_VALIDITY is not specified.
|
|
|
|
Window - specifies the window to own any dialogs, etc, that may be
|
|
presented. Unused if Flags does not contain one of
|
|
SPQ_SCAN_FILE_PRESENCE or SPQ_SCAN_FILE_VALIDITY, or if Flags does not
|
|
contain SPQ_SCAN_INFORM_USER.
|
|
|
|
CallbackRoutine - required if Flags includes SPQ_SCAN_USE_CALLBACK.
|
|
Specifies a callback function to be called on each node in
|
|
the copy queue. The notification code passed to the callback is
|
|
SPFILENOTIFY_QUEUESCAN.
|
|
|
|
CallbackContext - caller-defined data to be passed to CallbackRoutine.
|
|
|
|
Result - receives result of routine. See below.
|
|
|
|
Return Value:
|
|
|
|
If FALSE, then an error occurred or the callback function returned non-0.
|
|
Check Result -- if it is non-0, then it is the value returned by
|
|
the callback function which stopped queue processing.
|
|
If Result is 0, then extended error information is available from
|
|
GetLastError().
|
|
|
|
If TRUE, then all nodes were processed. Result is 0 if SPQ_SCAN_USE_CALLBACK
|
|
was specified. If SPQ_SCAN_USE_CALLBACK was not specified, then Result
|
|
indicates whether the queue passed the presence/validity check:
|
|
|
|
Result = 0: queue failed the check, or the queue passed the
|
|
check but SPQ_SCAN_INFORM_USER was specified and the user indicated
|
|
that he wants new copies of the files.
|
|
|
|
Result = 1: queue passed the check, and, if SPQ_SCAN_INFORM_USER was
|
|
specified, the user indicated that no copying is required. If Result is 1,
|
|
the copy queue has been emptied, and there are no elements on the
|
|
delete or rename queues, so the caller may skip queue commit.
|
|
|
|
Result = 2: queue passed the check, and, if SPQ_SCAN_INFORM_USER was
|
|
specified, the user indicated that no copying is required. In this case,
|
|
the copy queue has been emptied, however there are elements on the
|
|
delete or rename queues, so the caller may not skip queue commit.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL b;
|
|
|
|
b = _SetupScanFileQueue(
|
|
FileQueue,
|
|
Flags,
|
|
Window,
|
|
CallbackRoutine,
|
|
CallbackContext,
|
|
Result,
|
|
TRUE
|
|
);
|
|
|
|
return(b);
|
|
}
|
|
|
|
|
|
BOOL
|
|
pScanCheckValidity(
|
|
IN PCTSTR FileName
|
|
)
|
|
{
|
|
//
|
|
// For now, validity check means that the file exists.
|
|
//
|
|
return(FileExists(FileName,NULL));
|
|
}
|
|
|
|
|
|
INT
|
|
SetupPromptReboot(
|
|
IN HSPFILEQ FileQueue, OPTIONAL
|
|
IN HWND Owner,
|
|
IN BOOL ScanOnly
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine asks the user whether he wants to reboot the system,
|
|
optionally dependent on whether any files in a committed file queue
|
|
were in use (and are thus now pending operations via MoveFileEx()).
|
|
|
|
If the user answers yes to the prompt, shutdown is initiated
|
|
before this routine returns.
|
|
|
|
Arguments:
|
|
|
|
FileQueue - if specified, supplies a file queue upon which
|
|
to base the decision about whether shutdown is necessary.
|
|
If not specified, then this routine assumes shutdown is
|
|
necessary and asks the user what to do.
|
|
|
|
Owner - supplies window handle for parent window to own windows
|
|
created by this routine.
|
|
|
|
ScanOnly - if TRUE, then the user is never asked whether he wants
|
|
to reboot and no shutdown is initiated. In this case FileQueue
|
|
must be specified. If FALSE then this routine functions as
|
|
described above.
|
|
|
|
This flags is used when the caller wants to determine whether
|
|
shutdown is necessary separately from actually performing
|
|
the shutdown.
|
|
|
|
Return Value:
|
|
|
|
A combination of the following flags or -1 if an error occured:
|
|
|
|
SPFILEQ_FILE_IN_USE: at least one file was in use and thus there are
|
|
delayed file operations pending. This flag will never be set
|
|
when FileQueue is not specified.
|
|
|
|
SPFILEQ_REBOOT_RECOMMENDED: it is recommended that the system
|
|
be rebooted. Depending on other flags and user response to
|
|
the shutdown query, shutdown may already be happening.
|
|
|
|
SPFILEQ_REBOOT_IN_PROGRESS: shutdown is in progress.
|
|
|
|
--*/
|
|
|
|
{
|
|
PSP_FILE_QUEUE Queue;
|
|
PSP_FILE_QUEUE_NODE QueueNode;
|
|
PSOURCE_MEDIA_INFO SourceMedia;
|
|
INT Flags;
|
|
int i;
|
|
|
|
//
|
|
// If only scanning, there must be a FileQueue to scan!
|
|
//
|
|
if(ScanOnly && !FileQueue) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return(-1);
|
|
}
|
|
|
|
Queue = (PSP_FILE_QUEUE)FileQueue;
|
|
Flags = 0;
|
|
|
|
//
|
|
// Scan file queue if the caller so desires.
|
|
//
|
|
if(FileQueue) {
|
|
try {
|
|
//
|
|
// Check delete queue for in-use files.
|
|
//
|
|
for(QueueNode=Queue->DeleteQueue; QueueNode; QueueNode=QueueNode->Next) {
|
|
|
|
if(QueueNode->InternalFlags & INUSE_INF_WANTS_REBOOT) {
|
|
Flags |= SPFILEQ_REBOOT_RECOMMENDED;
|
|
}
|
|
|
|
if(QueueNode->InternalFlags & INUSE_IN_USE) {
|
|
Flags |= SPFILEQ_FILE_IN_USE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check copy queues for in-use files.
|
|
//
|
|
for(SourceMedia=Queue->SourceMediaList; SourceMedia; SourceMedia=SourceMedia->Next) {
|
|
for(QueueNode=SourceMedia->CopyQueue; QueueNode; QueueNode=QueueNode->Next) {
|
|
|
|
if(QueueNode->InternalFlags & INUSE_INF_WANTS_REBOOT) {
|
|
Flags |= SPFILEQ_REBOOT_RECOMMENDED;
|
|
}
|
|
|
|
if(QueueNode->InternalFlags & INUSE_IN_USE) {
|
|
Flags |= SPFILEQ_FILE_IN_USE;
|
|
}
|
|
}
|
|
}
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
Flags = -1;
|
|
}
|
|
} else {
|
|
Flags = SPFILEQ_REBOOT_RECOMMENDED;
|
|
}
|
|
|
|
//
|
|
// Ask the user if he wants to shut down, if necessary.
|
|
//
|
|
if(!ScanOnly && (Flags & SPFILEQ_REBOOT_RECOMMENDED) && (Flags != -1)) {
|
|
|
|
if(RestartDialog(Owner,NULL,EWX_REBOOT) == IDYES) {
|
|
Flags |= SPFILEQ_REBOOT_IN_PROGRESS;
|
|
}
|
|
}
|
|
|
|
return(Flags);
|
|
}
|