windows-nt/Source/XPSP1/NT/base/ntsetup/ocmanage/testoc/checkinf/component.cpp
2020-09-26 16:20:57 +08:00

674 lines
14 KiB
C++

#include "component.h"
#include <wchar.h>
#include <tchar.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
//////////////////////////////////////////////////////////////////
// Implementation of the Component Class
//////////////////////////////////////////////////////////////////
// Constructor
Component::Component(){
tszComponentId[0] = 0;
tszParentId[0] = 0;
prlNeedList = new RelationList;
prlExcludeList = new RelationList;
prlChildrenList = new RelationList;
}
// Another constructor
Component::Component(TCHAR *tszId){
_tcscpy(tszComponentId, tszId);
tszParentId[0] = 0;
prlNeedList = new RelationList;
prlExcludeList = new RelationList;
prlChildrenList = new RelationList;
}
// Destructor
Component::~Component(){
if (prlNeedList) {
delete prlNeedList;
}
if (prlExcludeList) {
delete prlExcludeList;
}
if (prlChildrenList) {
delete prlChildrenList;
}
}
// Copy constructor
Component::Component(const Component& source){
_tcscpy(tszComponentId, source.tszComponentId);
_tcscpy(tszParentId, source.tszParentId);
prlNeedList = source.prlNeedList;
prlExcludeList = source.prlExcludeList;
prlChildrenList = source.prlChildrenList;
}
// Assignment operator
const Component& Component::operator=(const Component& source){
_tcscpy(tszComponentId, source.tszComponentId);
_tcscpy(tszComponentId, source.tszParentId);
if (prlNeedList) {
delete prlNeedList;
}
if (prlExcludeList) {
delete prlExcludeList;
}
if (prlChildrenList) {
delete prlChildrenList;
}
prlNeedList = source.prlNeedList;
prlExcludeList = source.prlExcludeList;
prlChildrenList = source.prlChildrenList;
return *this;
}
// Find the parent of this component
// by searching a component list
Component* Component::GetParent(ComponentList *pclHead){
Component *pcTemp = pclHead->pcCurrent;
pclHead->ResetList();
while (!pclHead->Done()) {
if (pclHead->GetNext()->IsParent(this)){
pclHead->pcCurrent = pcTemp;
return (pclHead->GetNext());
}
}
pclHead->pcCurrent = pcTemp;
return NULL;
}
// If this component is the parent of the parameter
BOOL Component::IsParent(Component* pcChild){
if (_tcscmp(pcChild->tszParentId, this->tszComponentId) == 0) {
if (_tcscmp(pcChild->tszComponentId, pcChild->tszParentId) == 0) {
// the parameter is a top-level component
return FALSE;
}
return TRUE;
}
return FALSE;
}
// If this component is the child of the parameter
BOOL Component::IsChild(Component* pcParent){
if (_tcscmp(this->tszParentId, pcParent->tszComponentId) == 0) {
if (_tcscmp(this->tszParentId, this->tszComponentId) == 0 ) {
// This is a top-level component
return FALSE;
}
return TRUE;
}
return FALSE;
}
// Check if this component is needed by the parameter
BOOL Component::IsNeededBy(Component *pcComponent){
pcComponent->prlNeedList->ResetList();
while (!pcComponent->prlNeedList->Done()) {
if (_tcscmp(pcComponent->prlNeedList->GetNext()->tszComponentId,
this->tszComponentId) == 0){
return TRUE;
}
}
return FALSE;
}
// Check if this component is excluded by the parameter
BOOL Component::IsExcludeBy(Component *pcComponent){
pcComponent->prlExcludeList->ResetList();
while (!pcComponent->prlExcludeList->Done()) {
if (_tcscmp(pcComponent->prlNeedList->GetNext()->tszComponentId,
this->tszComponentId) == 0) {
return TRUE;
}
}
return FALSE;
}
// Get this component's parent id from INF file
BOOL Component::GetParentIdFromINF(HINF hinfHandle){
INFCONTEXT infContext;
BOOL bSuccess;
bSuccess = SetupFindFirstLine(hinfHandle,
tszComponentId,
TEXT("Parent"),
&infContext);
if (bSuccess) {
// Find the line
bSuccess = SetupGetStringField(&infContext,
1,
tszParentId,
MaxBufferSize,
NULL);
if (bSuccess) {
return TRUE;
}
else{
MessageBox(NULL,
TEXT("Unexpected error happened"),
TEXT("GetParentIdFromINF"),
MB_ICONERROR | MB_OK);
return FALSE;
}
}
else{
// This is a top-level component
_tcscpy(tszParentId, tszComponentId);
return TRUE;
}
}
// Check if this component is a toplevel compoent
// Toplevel component means no parent
BOOL Component::IsTopLevelComponent(){
if (_tcscmp(tszComponentId, tszParentId) == 0) {
return TRUE;
}
return FALSE;
}
// Check if this component is a bottomlevel component
// bottom level component doesn't have any child
BOOL Component::IsBottomComponent(){
if (prlChildrenList == NULL ||
prlChildrenList->prHead == NULL) {
return TRUE;
}
return FALSE;
}
// Check if this component is needed by others
BOOL Component::IsNeededByOthers(ComponentList *pclList){
Component *pcTemp = pclList->pcCurrent;
pclList->ResetList();
while (!pclList->Done()) {
if (IsNeededBy(pclList->GetNext())){
pclList->pcCurrent = pcTemp;
return TRUE;
}
}
pclList->pcCurrent = pcTemp;
return FALSE;
}
// Check if this component is excluded by others
BOOL Component::IsExcludedByOthers(ComponentList *pclList){
Component *pcTemp = pclList->pcCurrent;
pclList->ResetList();
while (!pclList->Done()) {
if (IsExcludeBy(pclList->GetNext())){
pclList->pcCurrent = pcTemp;
return TRUE;
}
}
pclList->pcCurrent = pcTemp;
return FALSE;
}
// Check if this component is parent of other components
BOOL Component::IsParentOfOthers(){
if (prlChildrenList != NULL &&
prlChildrenList->prHead != NULL) {
return TRUE;
}
return FALSE;
}
// Build the children list for this component
BOOL Component::BuildChildrenList(ComponentList *pclList){
// We can't use the enumerate facility of pclList here
Component *pcComponent = pclList->pcHead;
while (pcComponent) {
if (IsParent(pcComponent)) {
if (!prlChildrenList) {
prlChildrenList = new RelationList;
}
prlChildrenList->AddRelation(pcComponent->tszComponentId);
}
pcComponent = pcComponent->Next;
}
return TRUE;
}
// Check if this component has a need and exclude relation with other
// component at the same time
BOOL Component::NeedAndExcludeAtSameTime(ComponentList *pclList){
TCHAR tszMsg[MaxStringSize];
Component *pcComponent;
const PTSTR tszFunctionName = TEXT("Component::NeedAndExcludeAtSameTime");
// Go through the list of component it excludes
// check if any of them needs this one
prlExcludeList->ResetList();
while (!prlExcludeList->Done()){
pcComponent = pclList->LookupComponent(prlExcludeList->GetNext()->GetComponentId());
// Check if this needs pcComponent
if (pcComponent->IsNeededBy(this)){
_stprintf(tszMsg,
TEXT("%s is needed and excluded by the same component"),
this->tszComponentId);
LogError(tszMsg, SEV2, tszFunctionName);
return TRUE;
}
// Check if pcComponent needs this
if (this->IsNeededBy(pcComponent)){
_stprintf(tszMsg,
TEXT("%s is needed and excluded by the same component"),
this->tszComponentId);
LogError(tszMsg, SEV2, tszFunctionName);
return TRUE;
}
}
return FALSE;
}
// Check if this component needs other components
BOOL Component::NeedOthers(){
if (prlNeedList != NULL && prlNeedList->prHead != NULL) {
return TRUE;
}
return FALSE;
}
// Check if this component excludes other components
BOOL Component::ExcludeOthers(){
if (prlExcludeList != NULL && prlExcludeList->prHead != NULL) {
return TRUE;
}
return FALSE;
}
// Check if there is another component with the same
// id as this component
BOOL Component::IsThereSameId(ComponentList *pclList){
Component *pcCur;
TCHAR tszMsg[MaxStringSize];
const PTSTR tszFunctionName = TEXT("Component::IsThereSameId");
pcCur = pclList->pcHead;
while (pcCur) {
if (pcCur != this) {
if (_tcscmp(pcCur->tszComponentId, this->tszComponentId) == 0) {
_stprintf(tszMsg,
TEXT("There are two component with the same ID %s"),
this->tszComponentId);
LogError(tszMsg, SEV2, tszFunctionName);
}
}
pcCur = pcCur->Next;
}
return TRUE;
}
// Not implemented yet
UINT Component::GetDiskSpaceRequirement(HINF hinfHandle){
// Not implemented yet.
return 0;
}
// Check if this another component with the same description
BOOL Component::IsThereSameDesc(ComponentList *pclList){
const PTSTR tszFunctionName = TEXT("Component::IsThereSameDesc");
TCHAR tszMsg[MaxStringSize];
Component *pcCur = pclList->pcHead;
while (pcCur) {
if (pcCur != this) {
if (_tcscmp(pcCur->pDescAndTip->tszDesc,
this->pDescAndTip->tszDesc) == 0) {
if ((this->IsTopLevelComponent() &&
pcCur->IsTopLevelComponent()) ||
this->HasSameParentWith(pcCur)) {
// ahha, found one
_stprintf(tszMsg,
TEXT("Two components with the same description %s"),
pDescAndTip->tszDesc);
LogError(tszMsg, SEV2, tszFunctionName);
}
}
}
pcCur = pcCur->Next;
}
return TRUE;
}
// Check if this component has the same parent as the parameter
BOOL Component::HasSameParentWith(Component *pcComponent){
if (_tcscmp(tszParentId, pcComponent->tszParentId) == 0) {
return TRUE;
}
else{
return FALSE;
}
}
/////////////////////////////////////////////////////////////////////
// Implementation of the ComponentList class
/////////////////////////////////////////////////////////////////////
// Constructor
ComponentList::ComponentList(){
pcHead = NULL;
pcCurrent = NULL;
}
// destructor
ComponentList::~ComponentList(){
// Go through the list and delete each component
Component *pcComponent;
if (pcHead == NULL) {
// Empty list
return;
}
while(pcHead != NULL){
pcComponent = pcHead->Next;
delete pcHead;
pcHead = pcComponent;
}
}
// List iteration facility
// reset the iterator
void ComponentList::ResetList(){
pcCurrent = pcHead;
}
// Check if the iterator has reached the end
BOOL ComponentList::Done(){
return (pcCurrent == NULL);
}
// Get the next node in the list
Component* ComponentList::GetNext(){
Component *pcReturn;
pcReturn = pcCurrent;
if (pcCurrent != NULL) {
pcCurrent = pcReturn->Next;
return pcReturn;
}
else{
MessageBox(NULL,
TEXT("Something is seriously wrong"),
TEXT("ComponentList.GetNext()"),
MB_ICONERROR | MB_OK);
return NULL;
}
}
// Add a component into the list
Component* ComponentList::AddComponent(TCHAR *tszId){
if (tszId == NULL) {
return NULL;
}
Component *pcNewComponent = new Component(tszId);
if (!pcHead) {
pcHead = pcNewComponent;
pcNewComponent->Next = NULL;
return pcNewComponent;
}
pcNewComponent->Next = pcHead;
pcHead = pcNewComponent;
return pcNewComponent;
}
// Remove a component from the list according to the id given
BOOL ComponentList::RemoveComponent(TCHAR *tszId){
if (tszId == NULL) {
return NULL;
}
// Find the component in the list
Component *pcPrev = pcHead;
Component *pcCur = pcHead;
while (pcCur) {
if (_tcscmp(pcCur->tszComponentId, tszId) == 0) {
// Found the node to delete
pcPrev->Next = pcCur->Next;
delete pcCur;
return TRUE;
}
pcPrev = pcCur;
pcCur = pcCur->Next;
}
return FALSE;
}
// Find a component from the list
Component* ComponentList::LookupComponent(TCHAR *tszId){
if (tszId == NULL) {
return NULL;
}
Component *pcCur = pcHead;
while (pcCur) {
if (_tcscmp(pcCur->tszComponentId, tszId) == 0) {
return pcCur;
}
pcCur = pcCur->Next;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////
// Implementation of RelationList
//////////////////////////////////////////////////////////////////////
// Constructor
RelationList::RelationList(){
prHead = NULL;
prCurrent = NULL;
}
// destructor
RelationList::~RelationList(){
// deallocate all the memory
Relation *prNext;
if (prHead == NULL) {
// The list is empty
return;
}
while (prNext = prHead->Next) {
delete prHead;
prHead = prNext;
}
}
// List iteration facility
// reset the iterator
void RelationList::ResetList(){
prCurrent = prHead;
}
// Check if the iterator has reached the end of the list
BOOL RelationList::Done(){
if (prCurrent == NULL) {
return TRUE;
}
else{
return FALSE;
}
}
// Get the next node in the list
Relation* RelationList::GetNext(){
Relation *prReturn = prCurrent;
if (prCurrent != NULL) {
prCurrent = prCurrent->Next;
return prReturn;
}
else{
MessageBox(NULL,
TEXT("Something is seriously wrong"),
TEXT("RelationList::GetNext()"),
MB_ICONERROR | MB_OK);
return NULL;
}
}
// Add a node to the list
Relation* RelationList::AddRelation(TCHAR *tszId){
Relation *newRelation = new Relation;
_tcscpy(newRelation->tszComponentId, tszId);
if (!prHead) {
prHead = newRelation;
newRelation->Next = NULL;
return newRelation;
}
newRelation->Next = prHead;
prHead = newRelation;
return newRelation;
}
// Remove a node from the list
BOOL RelationList::RemoveRelation(TCHAR *tszId){
// First find the node from the list
Relation *prPrev = prHead;
prCurrent = prHead;
while (prCurrent) {
if (_tcscmp(prCurrent->tszComponentId, tszId) == 0) {
prPrev->Next = prCurrent->Next;
delete prCurrent;
return TRUE;
}
prPrev = prCurrent;
prCurrent = prCurrent->Next;
}
return FALSE;
}