/*++ Copyright (c) 1995 Microsoft Corporation Module Name: fileq3.c Abstract: Setup file queue routines for enqueing delete and rename operations. Author: Ted Miller (tedm) 15-Feb-1995 Revision History: --*/ #include "setupntp.h" #pragma hdrstop BOOL _SetupQueueDelete( IN HSPFILEQ QueueHandle, IN PCTSTR PathPart1, IN PCTSTR PathPart2, OPTIONAL IN UINT Flags ) /*++ Routine Description: Place a delete operation on a setup file queue. Note that delete operations are assumed to be on fixed media. No prompting will be performed for delete operations when the queue is committed. Arguments: QueueHandle - supplies a handle to a setup file queue, as returned by SetupOpenFileQueue. PathPart1 - Supplies the first part of the path of the file to be deleted. If PathPart2 is not specified, then this is the full path of the file to be deleted. PathPart2 - if specified, supplies the second part of the path of the file to be deleted. This is concatenated to PathPart1 to form the full pathname. Flags - specified flags controlling delete operation. DELFLG_IN_USE - if the file is in use, queue it for delayed delete, on next reboot. Otherwise in-use files are not deleted. DELFLG_IN_USE1 - same as DELFLG_IN_USE Return Value: Boolean value indicating outcome. If FALSE, GetLastError() returns extended error information. --*/ { PSP_FILE_QUEUE Queue; PSP_FILE_QUEUE_NODE QueueNode,TempNode; Queue = (PSP_FILE_QUEUE)QueueHandle; // // Allocate a queue structure. // QueueNode = MyMalloc(sizeof(SP_FILE_QUEUE_NODE)); if(!QueueNode) { goto clean0; } // // Operation is delete. // QueueNode->Operation = FILEOP_DELETE; // // Initialize unused fields. // QueueNode->SourceRootPath = -1; QueueNode->SourcePath = -1; QueueNode->SourceFilename = -1; QueueNode->StyleFlags = 0; QueueNode->SourceMediaInfo = NULL; QueueNode->InternalFlags = (Flags & (DELFLG_IN_USE|DELFLG_IN_USE1)) ? IQF_DELAYED_DELETE_OK : 0; // // NOTE: When adding the following strings to the string table, we cast away // their CONST-ness to avoid a compiler warning. Since we are adding them // case-sensitively, we are guaranteed they will not be modified. // // // Set up the target directory. // QueueNode->TargetDirectory = StringTableAddString(Queue->StringTable, (PTSTR)PathPart1, STRTAB_CASE_SENSITIVE ); if(QueueNode->TargetDirectory == -1) { goto clean1; } // // Set up the target filename. // if(PathPart2) { QueueNode->TargetFilename = StringTableAddString(Queue->StringTable, (PTSTR)PathPart2, STRTAB_CASE_SENSITIVE ); if(QueueNode->TargetFilename == -1) { goto clean1; } } else { QueueNode->TargetFilename = -1; } // // Link the node onto the end of the delete queue. // QueueNode->Next = NULL; if(Queue->DeleteQueue) { for(TempNode=Queue->DeleteQueue; TempNode->Next; TempNode=TempNode->Next) ; TempNode->Next = QueueNode; } else { Queue->DeleteQueue = QueueNode; } Queue->DeleteNodeCount++; return(TRUE); clean1: MyFree(QueueNode); clean0: SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } #ifdef UNICODE // // ANSI version // BOOL SetupQueueDeleteA( IN HSPFILEQ QueueHandle, IN PCSTR PathPart1, IN PCSTR PathPart2 OPTIONAL ) { PWSTR p1,p2; DWORD d; BOOL b; b = FALSE; d = CaptureAndConvertAnsiArg(PathPart1,&p1); if(d == NO_ERROR) { if(PathPart2) { d = CaptureAndConvertAnsiArg(PathPart2,&p2); } else { p2 = NULL; } if(d == NO_ERROR) { b = _SetupQueueDelete(QueueHandle,p1,p2,0); d = GetLastError(); if(p2) { MyFree(p2); } } MyFree(p1); } SetLastError(d); return(b); } #else // // Unicode stub // BOOL SetupQueueDeleteW( IN HSPFILEQ QueueHandle, IN PCWSTR PathPart1, IN PCWSTR PathPart2 OPTIONAL ) { UNREFERENCED_PARAMETER(QueueHandle); UNREFERENCED_PARAMETER(PathPart1); UNREFERENCED_PARAMETER(PathPart2); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return(FALSE); } #endif BOOL SetupQueueDelete( IN HSPFILEQ QueueHandle, IN PCTSTR PathPart1, IN PCTSTR PathPart2 OPTIONAL ) /*++ Routine Description: Place a delete operation on a setup file queue. Note that delete operations are assumed to be on fixed media. No prompting will be performed for delete operations when the queue is committed. Arguments: QueueHandle - supplies a handle to a setup file queue, as returned by SetupOpenFileQueue. PathPart1 - Supplies the first part of the path of the file to be deleted. If PathPart2 is not specified, then this is the full path of the file to be deleted. PathPart2 - if specified, supplies the second part of the path of the file to be deleted. This is concatenated to PathPart1 to form the full pathname. Return Value: Boolean value indicating outcome. If FALSE, GetLastError() returns extended error information. --*/ { PTSTR p1,p2; DWORD d; BOOL b; b = FALSE; d = CaptureStringArg(PathPart1,&p1); if(d == NO_ERROR) { if(PathPart2) { d = CaptureStringArg(PathPart2,&p2); } else { p2 = NULL; } if(d == NO_ERROR) { b = _SetupQueueDelete(QueueHandle,p1,p2,0); d = GetLastError(); if(p2) { MyFree(p2); } } MyFree(p1); } SetLastError(d); return(b); } #ifdef UNICODE // // ANSI version // BOOL SetupQueueDeleteSectionA( IN HSPFILEQ QueueHandle, IN HINF InfHandle, IN HINF ListInfHandle, OPTIONAL IN PCSTR Section ) { PWSTR section; DWORD d; BOOL b; d = CaptureAndConvertAnsiArg(Section,§ion); if(d == NO_ERROR) { b = SetupQueueDeleteSectionW(QueueHandle,InfHandle,ListInfHandle,section); d = GetLastError(); MyFree(section); } else { b = FALSE; } SetLastError(d); return(b); } #else // // Unicode stub // BOOL SetupQueueDeleteSectionW( IN HSPFILEQ QueueHandle, IN HINF InfHandle, IN HINF ListInfHandle, OPTIONAL IN PCWSTR Section ) { UNREFERENCED_PARAMETER(QueueHandle); UNREFERENCED_PARAMETER(InfHandle); UNREFERENCED_PARAMETER(ListInfHandle); UNREFERENCED_PARAMETER(Section); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return(FALSE); } #endif BOOL SetupQueueDeleteSection( IN HSPFILEQ QueueHandle, IN HINF InfHandle, IN HINF ListInfHandle, OPTIONAL IN PCTSTR Section ) /*++ Routine Description: Queue an entire section in an inf file for delete. The section must be in delete-section format and the inf file must contain [DestinationDirs]. Arguments: QueueHandle - supplies a handle to a setup file queue, as returned by SetupOpenFileQueue. InfHandle - supplies a handle to an open inf file, that contains the [DestinationDirs] section. ListInfHandle - if specified, supplies a handle to the open inf file containing the section named by Section. If not specified this section is assumed to be in InfHandle. Section - supplies the name of the section to be queued for delete. Return Value: Boolean value indicating outcome. If FALSE, GetLastError() returns extended error information. Some files may have been queued successfully. --*/ { BOOL b; PTSTR TargetDirectory; PCTSTR TargetFilename; INFCONTEXT LineContext; DWORD SizeRequired; DWORD rc; UINT Flags; if(!ListInfHandle) { ListInfHandle = InfHandle; } // // The section has to exist and there sas to be at least one line in it. // b = SetupFindFirstLine(ListInfHandle,Section,NULL,&LineContext); if(!b) { SetLastError(ERROR_SECTION_NOT_FOUND); return(FALSE); } // // Iterate every line in the section. // do { // // Get the target filename out of the line. // TargetFilename = pSetupFilenameFromLine(&LineContext,FALSE); if(!TargetFilename) { SetLastError(ERROR_INVALID_DATA); return(FALSE); } // // Determine the target path for the file. // b = SetupGetTargetPath(InfHandle,&LineContext,NULL,NULL,0,&SizeRequired); if(!b) { return(FALSE); } TargetDirectory = MyMalloc(SizeRequired*sizeof(TCHAR)); if(!TargetDirectory) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } SetupGetTargetPath(InfHandle,&LineContext,NULL,TargetDirectory,SizeRequired,NULL); // // If present flags are field 4 // if(!SetupGetIntField(&LineContext,4,(PINT)&Flags)) { Flags = 0; } // // Add to queue. // b = _SetupQueueDelete(QueueHandle,TargetDirectory,TargetFilename,Flags); rc = GetLastError(); MyFree(TargetDirectory); if(!b) { SetLastError(rc); return(FALSE); } } while(SetupFindNextLine(&LineContext,&LineContext)); return(TRUE); } #ifdef UNICODE // // ANSI version // BOOL SetupQueueRenameA( IN HSPFILEQ QueueHandle, IN PCSTR SourcePath, IN PCSTR SourceFilename, OPTIONAL IN PCSTR TargetPath, OPTIONAL IN PCSTR TargetFilename ) { PWSTR sourcepath = NULL; PWSTR sourcefilename = NULL; PWSTR targetpath = NULL; PWSTR targetfilename = NULL; DWORD d; BOOL b; b = FALSE; d = CaptureAndConvertAnsiArg(SourcePath,&sourcepath); if((d == NO_ERROR) && SourceFilename) { d = CaptureAndConvertAnsiArg(SourceFilename,&sourcefilename); } if((d == NO_ERROR) && TargetPath) { d = CaptureAndConvertAnsiArg(TargetPath,&targetpath); } if(d == NO_ERROR) { d = CaptureAndConvertAnsiArg(TargetFilename,&targetfilename); } if(d == NO_ERROR) { b = SetupQueueRenameW(QueueHandle,sourcepath,sourcefilename,targetpath,targetfilename); d = GetLastError(); } if(sourcepath) { MyFree(sourcepath); } if(sourcefilename) { MyFree(sourcefilename); } if(targetpath) { MyFree(targetpath); } if(targetfilename) { MyFree(targetfilename); } SetLastError(d); return(b); } #else // // Unicode stub // BOOL SetupQueueRenameW( IN HSPFILEQ QueueHandle, IN PCWSTR SourcePath, IN PCWSTR SourceFilename, OPTIONAL IN PCWSTR TargetPath, OPTIONAL IN PCWSTR TargetFilename ) { UNREFERENCED_PARAMETER(QueueHandle); UNREFERENCED_PARAMETER(SourcePath); UNREFERENCED_PARAMETER(SourceFilename); UNREFERENCED_PARAMETER(TargetPath); UNREFERENCED_PARAMETER(TargetFilename); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return(FALSE); } #endif BOOL SetupQueueRename( IN HSPFILEQ QueueHandle, IN PCTSTR SourcePath, IN PCTSTR SourceFilename, OPTIONAL IN PCTSTR TargetPath, OPTIONAL IN PCTSTR TargetFilename ) /*++ Routine Description: Place a rename operation on a setup file queue. Note that rename operations are assumed to be on fixed media. No prompting will be performed for rename operations when the queue is committed. Arguments: QueueHandle - supplies a handle to a setup file queue, as returned by SetupOpenFileQueue. SourcePath - Supplies the source path of the file to be renamed. If SourceFilename is specified, this is the part part only. If SourceFilename is not specified, this is the fully-qualified path. SourceFilename - if specified, supplies the filename part of the file to be renamed. If not specified, SourcePath is the fully- qualified path of the file to be renamed. TargetPath - if specified, supplies the target directory, and the rename is actually a move operation. If not specified, then the rename takes place without moving the file. TargetFilename - supplies the new name (no path) of the file. Return Value: Boolean value indicating outcome. If FALSE, GetLastError() returns extended error information. --*/ { PSP_FILE_QUEUE Queue; PSP_FILE_QUEUE_NODE QueueNode,TempNode; Queue = (PSP_FILE_QUEUE)QueueHandle; // // Allocate a queue structure. // QueueNode = MyMalloc(sizeof(SP_FILE_QUEUE_NODE)); if(!QueueNode) { goto clean0; } // // Operation is rename. // QueueNode->Operation = FILEOP_RENAME; // // Initialize unused fields. // QueueNode->SourceRootPath = -1; QueueNode->StyleFlags = 0; QueueNode->InternalFlags = 0; // // NOTE: When adding the following strings to the string table, we cast away // their CONST-ness to avoid a compiler warning. Since we are adding them // case-sensitively, we are guaranteed they will not be modified. // // // Set up the source path. // QueueNode->SourcePath = StringTableAddString(Queue->StringTable, (PTSTR)SourcePath, STRTAB_CASE_SENSITIVE ); if(QueueNode->SourcePath == -1) { goto clean1; } // // Set up the source filename. // if(SourceFilename) { QueueNode->SourceFilename = StringTableAddString(Queue->StringTable, (PTSTR)SourceFilename, STRTAB_CASE_SENSITIVE ); if(QueueNode->SourceFilename == -1) { goto clean1; } } else { QueueNode->SourceFilename = -1; } // // Set up the target directory. // if(TargetPath) { QueueNode->TargetDirectory = StringTableAddString(Queue->StringTable, (PTSTR)TargetPath, STRTAB_CASE_SENSITIVE ); if(QueueNode->TargetDirectory == -1) { goto clean1; } } else { QueueNode->TargetDirectory = -1; } // // Set up the target filename. // QueueNode->TargetFilename = StringTableAddString(Queue->StringTable, (PTSTR)TargetFilename, STRTAB_CASE_SENSITIVE ); if(QueueNode->TargetFilename == -1) { goto clean1; } // // Link the node onto the end of the copy queue. // QueueNode->Next = NULL; if(Queue->RenameQueue) { for(TempNode=Queue->RenameQueue; TempNode->Next; TempNode=TempNode->Next) ; TempNode->Next = QueueNode; } else { Queue->RenameQueue = QueueNode; } Queue->RenameNodeCount++; return(TRUE); clean1: MyFree(QueueNode); clean0: SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } #ifdef UNICODE // // ANSI version // BOOL SetupQueueRenameSectionA( IN HSPFILEQ QueueHandle, IN HINF InfHandle, IN HINF ListInfHandle, OPTIONAL IN PCSTR Section ) { PWSTR section; DWORD d; BOOL b; d = CaptureAndConvertAnsiArg(Section,§ion); if(d == NO_ERROR) { b = SetupQueueRenameSectionW(QueueHandle,InfHandle,ListInfHandle,section); d = GetLastError(); MyFree(section); } else { b = FALSE; } SetLastError(d); return(b); } #else // // Unicode stub // BOOL SetupQueueRenameSectionW( IN HSPFILEQ QueueHandle, IN HINF InfHandle, IN HINF ListInfHandle, OPTIONAL IN PCWSTR Section ) { UNREFERENCED_PARAMETER(QueueHandle); UNREFERENCED_PARAMETER(InfHandle); UNREFERENCED_PARAMETER(ListInfHandle); UNREFERENCED_PARAMETER(Section); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return(FALSE); } #endif BOOL SetupQueueRenameSection( IN HSPFILEQ QueueHandle, IN HINF InfHandle, IN HINF ListInfHandle, OPTIONAL IN PCTSTR Section ) /*++ Routine Description: Queue an entire section in an inf file for delete. The section must be in delete-section format and the inf file must contain [DestinationDirs]. The format of a rename list section dictates that only renames within the same directory is supported (ie, you cannot queue file moves with this API). Arguments: QueueHandle - supplies a handle to a setup file queue, as returned by SetupOpenFileQueue. InfHandle - supplies a handle to an open inf file, that contains the [DestinationDirs] section. ListInfHandle - if specified, supplies a handle to the open inf file containing the section named by Section. If not specified this section is assumed to be in InfHandle. Section - supplies the name of the section to be queued for delete. Return Value: Boolean value indicating outcome. If FALSE, GetLastError() returns extended error information. --*/ { BOOL b; INFCONTEXT LineContext; PCTSTR TargetFilename; PCTSTR SourceFilename; PTSTR Directory; DWORD SizeRequired; DWORD rc; if(!ListInfHandle) { ListInfHandle = InfHandle; } // // The section has to exist and there has to be at least one line in it. // b = SetupFindFirstLine(ListInfHandle,Section,NULL,&LineContext); if(!b) { SetLastError(ERROR_SECTION_NOT_FOUND); return(FALSE); } // // Iterate every line in the section. // do { // // Get the target filename out of the line. // TargetFilename = pSetupFilenameFromLine(&LineContext,FALSE); if(!TargetFilename) { SetLastError(ERROR_INVALID_DATA); return(FALSE); } // // Get source filename out of the line. // SourceFilename = pSetupFilenameFromLine(&LineContext,TRUE); if(!SourceFilename || (*SourceFilename == 0)) { SetLastError(ERROR_INVALID_DATA); return(FALSE); } // // Determine the path of the file. // b = SetupGetTargetPath(InfHandle,&LineContext,NULL,NULL,0,&SizeRequired); if(!b) { return(FALSE); } Directory = MyMalloc(SizeRequired*sizeof(TCHAR)); if(!Directory) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } SetupGetTargetPath(InfHandle,&LineContext,NULL,Directory,SizeRequired,NULL); // // Add to queue. // b = SetupQueueRename( QueueHandle, Directory, SourceFilename, NULL, TargetFilename ); rc = GetLastError(); MyFree(Directory); if(!b) { SetLastError(rc); return(FALSE); } } while(SetupFindNextLine(&LineContext,&LineContext)); return(TRUE); }