Leaked source code of windows server 2003
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.

673 lines
15 KiB

  1. #include "component.h"
  2. #include <wchar.h>
  3. #include <tchar.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. //////////////////////////////////////////////////////////////////
  9. // Implementation of the Component Class
  10. //////////////////////////////////////////////////////////////////
  11. // Constructor
  12. Component::Component(){
  13. tszComponentId[0] = 0;
  14. tszParentId[0] = 0;
  15. prlNeedList = new RelationList;
  16. prlExcludeList = new RelationList;
  17. prlChildrenList = new RelationList;
  18. }
  19. // Another constructor
  20. Component::Component(TCHAR *tszId){
  21. _tcscpy(tszComponentId, tszId);
  22. tszParentId[0] = 0;
  23. prlNeedList = new RelationList;
  24. prlExcludeList = new RelationList;
  25. prlChildrenList = new RelationList;
  26. }
  27. // Destructor
  28. Component::~Component(){
  29. if (prlNeedList) {
  30. delete prlNeedList;
  31. }
  32. if (prlExcludeList) {
  33. delete prlExcludeList;
  34. }
  35. if (prlChildrenList) {
  36. delete prlChildrenList;
  37. }
  38. }
  39. // Copy constructor
  40. Component::Component(const Component& source){
  41. _tcscpy(tszComponentId, source.tszComponentId);
  42. _tcscpy(tszParentId, source.tszParentId);
  43. prlNeedList = source.prlNeedList;
  44. prlExcludeList = source.prlExcludeList;
  45. prlChildrenList = source.prlChildrenList;
  46. }
  47. // Assignment operator
  48. const Component& Component::operator=(const Component& source){
  49. _tcscpy(tszComponentId, source.tszComponentId);
  50. _tcscpy(tszComponentId, source.tszParentId);
  51. if (prlNeedList) {
  52. delete prlNeedList;
  53. }
  54. if (prlExcludeList) {
  55. delete prlExcludeList;
  56. }
  57. if (prlChildrenList) {
  58. delete prlChildrenList;
  59. }
  60. prlNeedList = source.prlNeedList;
  61. prlExcludeList = source.prlExcludeList;
  62. prlChildrenList = source.prlChildrenList;
  63. return *this;
  64. }
  65. // Find the parent of this component
  66. // by searching a component list
  67. Component* Component::GetParent(ComponentList *pclHead){
  68. Component *pcTemp = pclHead->pcCurrent;
  69. pclHead->ResetList();
  70. while (!pclHead->Done()) {
  71. if (pclHead->GetNext()->IsParent(this)){
  72. pclHead->pcCurrent = pcTemp;
  73. return (pclHead->GetNext());
  74. }
  75. }
  76. pclHead->pcCurrent = pcTemp;
  77. return NULL;
  78. }
  79. // If this component is the parent of the parameter
  80. BOOL Component::IsParent(Component* pcChild){
  81. if (_tcscmp(pcChild->tszParentId, this->tszComponentId) == 0) {
  82. if (_tcscmp(pcChild->tszComponentId, pcChild->tszParentId) == 0) {
  83. // the parameter is a top-level component
  84. return FALSE;
  85. }
  86. return TRUE;
  87. }
  88. return FALSE;
  89. }
  90. // If this component is the child of the parameter
  91. BOOL Component::IsChild(Component* pcParent){
  92. if (_tcscmp(this->tszParentId, pcParent->tszComponentId) == 0) {
  93. if (_tcscmp(this->tszParentId, this->tszComponentId) == 0 ) {
  94. // This is a top-level component
  95. return FALSE;
  96. }
  97. return TRUE;
  98. }
  99. return FALSE;
  100. }
  101. // Check if this component is needed by the parameter
  102. BOOL Component::IsNeededBy(Component *pcComponent){
  103. pcComponent->prlNeedList->ResetList();
  104. while (!pcComponent->prlNeedList->Done()) {
  105. if (_tcscmp(pcComponent->prlNeedList->GetNext()->tszComponentId,
  106. this->tszComponentId) == 0){
  107. return TRUE;
  108. }
  109. }
  110. return FALSE;
  111. }
  112. // Check if this component is excluded by the parameter
  113. BOOL Component::IsExcludeBy(Component *pcComponent){
  114. pcComponent->prlExcludeList->ResetList();
  115. while (!pcComponent->prlExcludeList->Done()) {
  116. if (_tcscmp(pcComponent->prlNeedList->GetNext()->tszComponentId,
  117. this->tszComponentId) == 0) {
  118. return TRUE;
  119. }
  120. }
  121. return FALSE;
  122. }
  123. // Get this component's parent id from INF file
  124. BOOL Component::GetParentIdFromINF(HINF hinfHandle){
  125. INFCONTEXT infContext;
  126. BOOL bSuccess;
  127. bSuccess = SetupFindFirstLine(hinfHandle,
  128. tszComponentId,
  129. TEXT("Parent"),
  130. &infContext);
  131. if (bSuccess) {
  132. // Find the line
  133. bSuccess = SetupGetStringField(&infContext,
  134. 1,
  135. tszParentId,
  136. MaxBufferSize,
  137. NULL);
  138. if (bSuccess) {
  139. return TRUE;
  140. }
  141. else{
  142. MessageBox(NULL,
  143. TEXT("Unexpected error happened"),
  144. TEXT("GetParentIdFromINF"),
  145. MB_ICONERROR | MB_OK);
  146. return FALSE;
  147. }
  148. }
  149. else{
  150. // This is a top-level component
  151. _tcscpy(tszParentId, tszComponentId);
  152. return TRUE;
  153. }
  154. }
  155. // Check if this component is a toplevel compoent
  156. // Toplevel component means no parent
  157. BOOL Component::IsTopLevelComponent(){
  158. if (_tcscmp(tszComponentId, tszParentId) == 0) {
  159. return TRUE;
  160. }
  161. return FALSE;
  162. }
  163. // Check if this component is a bottomlevel component
  164. // bottom level component doesn't have any child
  165. BOOL Component::IsBottomComponent(){
  166. if (prlChildrenList == NULL ||
  167. prlChildrenList->prHead == NULL) {
  168. return TRUE;
  169. }
  170. return FALSE;
  171. }
  172. // Check if this component is needed by others
  173. BOOL Component::IsNeededByOthers(ComponentList *pclList){
  174. Component *pcTemp = pclList->pcCurrent;
  175. pclList->ResetList();
  176. while (!pclList->Done()) {
  177. if (IsNeededBy(pclList->GetNext())){
  178. pclList->pcCurrent = pcTemp;
  179. return TRUE;
  180. }
  181. }
  182. pclList->pcCurrent = pcTemp;
  183. return FALSE;
  184. }
  185. // Check if this component is excluded by others
  186. BOOL Component::IsExcludedByOthers(ComponentList *pclList){
  187. Component *pcTemp = pclList->pcCurrent;
  188. pclList->ResetList();
  189. while (!pclList->Done()) {
  190. if (IsExcludeBy(pclList->GetNext())){
  191. pclList->pcCurrent = pcTemp;
  192. return TRUE;
  193. }
  194. }
  195. pclList->pcCurrent = pcTemp;
  196. return FALSE;
  197. }
  198. // Check if this component is parent of other components
  199. BOOL Component::IsParentOfOthers(){
  200. if (prlChildrenList != NULL &&
  201. prlChildrenList->prHead != NULL) {
  202. return TRUE;
  203. }
  204. return FALSE;
  205. }
  206. // Build the children list for this component
  207. BOOL Component::BuildChildrenList(ComponentList *pclList){
  208. // We can't use the enumerate facility of pclList here
  209. Component *pcComponent = pclList->pcHead;
  210. while (pcComponent) {
  211. if (IsParent(pcComponent)) {
  212. if (!prlChildrenList) {
  213. prlChildrenList = new RelationList;
  214. }
  215. prlChildrenList->AddRelation(pcComponent->tszComponentId);
  216. }
  217. pcComponent = pcComponent->Next;
  218. }
  219. return TRUE;
  220. }
  221. // Check if this component has a need and exclude relation with other
  222. // component at the same time
  223. BOOL Component::NeedAndExcludeAtSameTime(ComponentList *pclList){
  224. TCHAR tszMsg[MaxStringSize];
  225. Component *pcComponent;
  226. const PTSTR tszFunctionName = TEXT("Component::NeedAndExcludeAtSameTime");
  227. // Go through the list of component it excludes
  228. // check if any of them needs this one
  229. prlExcludeList->ResetList();
  230. while (!prlExcludeList->Done()){
  231. pcComponent = pclList->LookupComponent(prlExcludeList->GetNext()->GetComponentId());
  232. // Check if this needs pcComponent
  233. if (pcComponent->IsNeededBy(this)){
  234. _stprintf(tszMsg,
  235. TEXT("%s is needed and excluded by the same component"),
  236. this->tszComponentId);
  237. LogError(tszMsg, SEV2, tszFunctionName);
  238. return TRUE;
  239. }
  240. // Check if pcComponent needs this
  241. if (this->IsNeededBy(pcComponent)){
  242. _stprintf(tszMsg,
  243. TEXT("%s is needed and excluded by the same component"),
  244. this->tszComponentId);
  245. LogError(tszMsg, SEV2, tszFunctionName);
  246. return TRUE;
  247. }
  248. }
  249. return FALSE;
  250. }
  251. // Check if this component needs other components
  252. BOOL Component::NeedOthers(){
  253. if (prlNeedList != NULL && prlNeedList->prHead != NULL) {
  254. return TRUE;
  255. }
  256. return FALSE;
  257. }
  258. // Check if this component excludes other components
  259. BOOL Component::ExcludeOthers(){
  260. if (prlExcludeList != NULL && prlExcludeList->prHead != NULL) {
  261. return TRUE;
  262. }
  263. return FALSE;
  264. }
  265. // Check if there is another component with the same
  266. // id as this component
  267. BOOL Component::IsThereSameId(ComponentList *pclList){
  268. Component *pcCur;
  269. TCHAR tszMsg[MaxStringSize];
  270. const PTSTR tszFunctionName = TEXT("Component::IsThereSameId");
  271. pcCur = pclList->pcHead;
  272. while (pcCur) {
  273. if (pcCur != this) {
  274. if (_tcscmp(pcCur->tszComponentId, this->tszComponentId) == 0) {
  275. _stprintf(tszMsg,
  276. TEXT("There are two component with the same ID %s"),
  277. this->tszComponentId);
  278. LogError(tszMsg, SEV2, tszFunctionName);
  279. }
  280. }
  281. pcCur = pcCur->Next;
  282. }
  283. return TRUE;
  284. }
  285. // Not implemented yet
  286. UINT Component::GetDiskSpaceRequirement(HINF hinfHandle){
  287. // Not implemented yet.
  288. return 0;
  289. }
  290. // Check if this another component with the same description
  291. BOOL Component::IsThereSameDesc(ComponentList *pclList){
  292. const PTSTR tszFunctionName = TEXT("Component::IsThereSameDesc");
  293. TCHAR tszMsg[MaxStringSize];
  294. Component *pcCur = pclList->pcHead;
  295. while (pcCur) {
  296. if (pcCur != this) {
  297. if (_tcscmp(pcCur->pDescAndTip->tszDesc,
  298. this->pDescAndTip->tszDesc) == 0) {
  299. if ((this->IsTopLevelComponent() &&
  300. pcCur->IsTopLevelComponent()) ||
  301. this->HasSameParentWith(pcCur)) {
  302. // ahha, found one
  303. _stprintf(tszMsg,
  304. TEXT("Two components with the same description %s"),
  305. pDescAndTip->tszDesc);
  306. LogError(tszMsg, SEV2, tszFunctionName);
  307. }
  308. }
  309. }
  310. pcCur = pcCur->Next;
  311. }
  312. return TRUE;
  313. }
  314. // Check if this component has the same parent as the parameter
  315. BOOL Component::HasSameParentWith(Component *pcComponent){
  316. if (_tcscmp(tszParentId, pcComponent->tszParentId) == 0) {
  317. return TRUE;
  318. }
  319. else{
  320. return FALSE;
  321. }
  322. }
  323. /////////////////////////////////////////////////////////////////////
  324. // Implementation of the ComponentList class
  325. /////////////////////////////////////////////////////////////////////
  326. // Constructor
  327. ComponentList::ComponentList(){
  328. pcHead = NULL;
  329. pcCurrent = NULL;
  330. }
  331. // destructor
  332. ComponentList::~ComponentList(){
  333. // Go through the list and delete each component
  334. Component *pcComponent;
  335. if (pcHead == NULL) {
  336. // Empty list
  337. return;
  338. }
  339. while(pcHead != NULL){
  340. pcComponent = pcHead->Next;
  341. delete pcHead;
  342. pcHead = pcComponent;
  343. }
  344. }
  345. // List iteration facility
  346. // reset the iterator
  347. void ComponentList::ResetList(){
  348. pcCurrent = pcHead;
  349. }
  350. // Check if the iterator has reached the end
  351. BOOL ComponentList::Done(){
  352. return (pcCurrent == NULL);
  353. }
  354. // Get the next node in the list
  355. Component* ComponentList::GetNext(){
  356. Component *pcReturn;
  357. pcReturn = pcCurrent;
  358. if (pcCurrent != NULL) {
  359. pcCurrent = pcReturn->Next;
  360. return pcReturn;
  361. }
  362. else{
  363. MessageBox(NULL,
  364. TEXT("Something is seriously wrong"),
  365. TEXT("ComponentList.GetNext()"),
  366. MB_ICONERROR | MB_OK);
  367. return NULL;
  368. }
  369. }
  370. // Add a component into the list
  371. Component* ComponentList::AddComponent(TCHAR *tszId){
  372. if (tszId == NULL) {
  373. return NULL;
  374. }
  375. Component *pcNewComponent = new Component(tszId);
  376. if (!pcHead) {
  377. pcHead = pcNewComponent;
  378. pcNewComponent->Next = NULL;
  379. return pcNewComponent;
  380. }
  381. pcNewComponent->Next = pcHead;
  382. pcHead = pcNewComponent;
  383. return pcNewComponent;
  384. }
  385. // Remove a component from the list according to the id given
  386. BOOL ComponentList::RemoveComponent(TCHAR *tszId){
  387. if (tszId == NULL) {
  388. return NULL;
  389. }
  390. // Find the component in the list
  391. Component *pcPrev = pcHead;
  392. Component *pcCur = pcHead;
  393. while (pcCur) {
  394. if (_tcscmp(pcCur->tszComponentId, tszId) == 0) {
  395. // Found the node to delete
  396. pcPrev->Next = pcCur->Next;
  397. delete pcCur;
  398. return TRUE;
  399. }
  400. pcPrev = pcCur;
  401. pcCur = pcCur->Next;
  402. }
  403. return FALSE;
  404. }
  405. // Find a component from the list
  406. Component* ComponentList::LookupComponent(TCHAR *tszId){
  407. if (tszId == NULL) {
  408. return NULL;
  409. }
  410. Component *pcCur = pcHead;
  411. while (pcCur) {
  412. if (_tcscmp(pcCur->tszComponentId, tszId) == 0) {
  413. return pcCur;
  414. }
  415. pcCur = pcCur->Next;
  416. }
  417. return NULL;
  418. }
  419. //////////////////////////////////////////////////////////////////////
  420. // Implementation of RelationList
  421. //////////////////////////////////////////////////////////////////////
  422. // Constructor
  423. RelationList::RelationList(){
  424. prHead = NULL;
  425. prCurrent = NULL;
  426. }
  427. // destructor
  428. RelationList::~RelationList(){
  429. // deallocate all the memory
  430. Relation *prNext;
  431. if (prHead == NULL) {
  432. // The list is empty
  433. return;
  434. }
  435. while (prNext = prHead->Next) {
  436. delete prHead;
  437. prHead = prNext;
  438. }
  439. }
  440. // List iteration facility
  441. // reset the iterator
  442. void RelationList::ResetList(){
  443. prCurrent = prHead;
  444. }
  445. // Check if the iterator has reached the end of the list
  446. BOOL RelationList::Done(){
  447. if (prCurrent == NULL) {
  448. return TRUE;
  449. }
  450. else{
  451. return FALSE;
  452. }
  453. }
  454. // Get the next node in the list
  455. Relation* RelationList::GetNext(){
  456. Relation *prReturn = prCurrent;
  457. if (prCurrent != NULL) {
  458. prCurrent = prCurrent->Next;
  459. return prReturn;
  460. }
  461. else{
  462. MessageBox(NULL,
  463. TEXT("Something is seriously wrong"),
  464. TEXT("RelationList::GetNext()"),
  465. MB_ICONERROR | MB_OK);
  466. return NULL;
  467. }
  468. }
  469. // Add a node to the list
  470. Relation* RelationList::AddRelation(TCHAR *tszId){
  471. Relation *newRelation = new Relation;
  472. _tcscpy(newRelation->tszComponentId, tszId);
  473. if (!prHead) {
  474. prHead = newRelation;
  475. newRelation->Next = NULL;
  476. return newRelation;
  477. }
  478. newRelation->Next = prHead;
  479. prHead = newRelation;
  480. return newRelation;
  481. }
  482. // Remove a node from the list
  483. BOOL RelationList::RemoveRelation(TCHAR *tszId){
  484. // First find the node from the list
  485. Relation *prPrev = prHead;
  486. prCurrent = prHead;
  487. while (prCurrent) {
  488. if (_tcscmp(prCurrent->tszComponentId, tszId) == 0) {
  489. prPrev->Next = prCurrent->Next;
  490. delete prCurrent;
  491. return TRUE;
  492. }
  493. prPrev = prCurrent;
  494. prCurrent = prCurrent->Next;
  495. }
  496. return FALSE;
  497. }