674 lines
14 KiB
C++
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;
|
||
|
}
|
||
|
|
||
|
|