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.

1212 lines
34 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. setupapi.hpp
  5. Abstract:
  6. Wrapper class library for setup api
  7. Author:
  8. Vijay Jayaseelan (vijayj) 04 Aug 2000
  9. Revision History:
  10. None
  11. --*/
  12. #pragma once
  13. //
  14. // Disable the compiler warning for long names
  15. //
  16. #pragma warning( disable : 4786 )
  17. extern "C" {
  18. #include <windows.h>
  19. #include <setupapi.h>
  20. #include <spapip.h>
  21. }
  22. #include <iostream>
  23. #include <vector>
  24. #include <map>
  25. #include <string>
  26. //
  27. // Wide string output routine
  28. //
  29. std::string&
  30. ToAnsiString(std::string &lhs, const std::wstring &rhs);
  31. std::ostream&
  32. operator<<(std::ostream &lhs, const std::basic_string<WCHAR> &rhs);
  33. std::ostream&
  34. operator<<(std::ostream &lhs, PCWSTR rhs);
  35. //
  36. // Exception classes
  37. //
  38. template<class T>
  39. class BaseException {
  40. public:
  41. BaseException(){}
  42. BaseException(const std::basic_string<T> &Info)
  43. : ExceptionInfo(Info) {}
  44. virtual ~BaseException(){}
  45. virtual void Dump(std::ostream &os) = 0;
  46. protected:
  47. std::basic_string<T> ExceptionInfo;
  48. };
  49. template<class T>
  50. class InvalidValueIndex : public BaseException<T>{
  51. public:
  52. InvalidValueIndex(unsigned int Idx) : Index(Idx){}
  53. void Dump(std::ostream &os) {
  54. os << "Invalid value index : (" << std::dec
  55. << Index << ")" << std::endl;
  56. }
  57. private:
  58. unsigned int Index;
  59. };
  60. template<class T>
  61. class InvalidValueKey : public BaseException<T>{
  62. public:
  63. InvalidValueKey(const std::basic_string<T> &SecName,
  64. const std::basic_string<T> &Key) : SectionName(SecName), KeyName(Key){}
  65. void Dump(std::ostream &os) {
  66. os << "Invalid value key name (" << KeyName << ")"
  67. << " in " << SectionName << " section." << std::endl;
  68. }
  69. private:
  70. std::basic_string<T> SectionName, KeyName;
  71. };
  72. //
  73. // Abstracts a Win32 error
  74. //
  75. template <class T>
  76. class W32Exception : public BaseException<T> {
  77. public:
  78. W32Exception(DWORD ErrCode = GetLastError()) : ErrorCode(ErrCode){}
  79. void Dump(std::ostream &os) {
  80. T MsgBuffer[4096];
  81. MsgBuffer[0] = NULL;
  82. DWORD CharCount;
  83. if (sizeof(T) == sizeof(WCHAR)) {
  84. CharCount = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
  85. NULL,
  86. ErrorCode,
  87. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  88. (PWSTR)MsgBuffer,
  89. sizeof(MsgBuffer)/sizeof(WCHAR),
  90. NULL);
  91. if (CharCount) {
  92. std::wstring Msg((PWSTR)MsgBuffer);
  93. os << Msg;
  94. } else {
  95. os << std::hex << ErrorCode;
  96. }
  97. } else {
  98. CharCount = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
  99. NULL,
  100. ErrorCode,
  101. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  102. (PSTR)MsgBuffer,
  103. sizeof(MsgBuffer)/sizeof(CHAR),
  104. NULL);
  105. if (CharCount) {
  106. std::string Msg((PCSTR)MsgBuffer);
  107. os << Msg;
  108. } else {
  109. os << std::hex << ErrorCode;
  110. }
  111. }
  112. }
  113. DWORD GetErrorCode() const { return ErrorCode; }
  114. protected:
  115. DWORD ErrorCode;
  116. };
  117. template<class T>
  118. class Section;
  119. template<class T>
  120. class SectionValues {
  121. public:
  122. SectionValues(Section<T> &Sec, ULONG LineIdx, bool New = false);
  123. SectionValues(Section<T> &Sec, const std::basic_string<T> &Key,
  124. ULONG LineIdx, bool New = false);
  125. void PutValue(ULONG Index, const std::basic_string<T> &Val) {
  126. Values[Index] = Val;
  127. GetContainer().GetContainer().SetDirty();
  128. }
  129. const std::basic_string<T>& GetValue(ULONG Index) const {
  130. return Values[Index];
  131. }
  132. void AppendValue(const std::basic_string<T> &Val) {
  133. Values.push_back(Val);
  134. GetContainer().GetContainer().SetDirty();
  135. }
  136. void ClearValues() {
  137. Values.clear();
  138. GetContainer().GetContainer().SetDirty();
  139. }
  140. ULONG Count() const {
  141. return Values.size();
  142. }
  143. Section<T>& GetContainer() { return Container; }
  144. const std::basic_string<T>& GetName() const { return Name; }
  145. ULONG GetIndex() const { return Index; }
  146. friend std::ostream& operator<<(std::ostream &os, SectionValues<T> &rhs) {
  147. os << rhs.GetName() << " = ";
  148. std::vector< std::basic_string<T> >::iterator Iter = rhs.Values.begin();
  149. while (Iter != rhs.Values.end()) {
  150. os << *Iter << ", ";
  151. Iter++;
  152. }
  153. os << std::endl;
  154. return os;
  155. }
  156. protected:
  157. //
  158. // data members
  159. //
  160. ULONG Index;
  161. std::basic_string<T> Name;
  162. std::vector< std::basic_string<T> > Values;
  163. Section<T> &Container;
  164. };
  165. template<class T>
  166. struct InvalidInfSection : public BaseException<T> {
  167. public:
  168. InvalidInfSection(const std::basic_string<T> &SecName,
  169. const std::basic_string<T> &InfName)
  170. : Name(SecName), FileName(InfName){}
  171. std::basic_string<T> Name;
  172. std::basic_string<T> FileName;
  173. void Dump(std::ostream &os) {
  174. os << "InvalidInfSection : " << Name << " in "
  175. << FileName << std::endl;
  176. }
  177. };
  178. //
  179. // forward declaration
  180. //
  181. template<class T>
  182. class InfFile;
  183. template<class T>
  184. class Section {
  185. public:
  186. Section(InfFile<T> &file, const std::basic_string<T> &name);
  187. Section(InfFile<T> &file, const std::basic_string<T> &name, bool NoKey) :
  188. File(file), Name(name), Keyless(NoKey) {}
  189. ~Section(){}
  190. const std::basic_string<T>& GetName() const{
  191. return Name;
  192. }
  193. SectionValues<T>& GetValue(const std::basic_string<T> &Key) {
  194. std::vector< SectionValues<T> *>::iterator Iter = Lines.begin();
  195. SectionValues<T> *Values = NULL;
  196. while (Iter != Lines.end()) {
  197. Values = (*Iter);
  198. if (sizeof(T) == sizeof(CHAR)) {
  199. if (!_stricmp((PCSTR)Values->GetName().c_str(),
  200. (PCSTR)Key.c_str())) {
  201. break;
  202. }
  203. } else {
  204. if (!_wcsicmp((PCWSTR)Values->GetName().c_str(),
  205. (PCWSTR)Key.c_str())) {
  206. break;
  207. }
  208. }
  209. Iter++;
  210. }
  211. if (Iter == Lines.end()) {
  212. throw new InvalidValueKey<T>(Name, Key);
  213. }
  214. return *Values;
  215. }
  216. //
  217. // Note : For the following scenario
  218. //
  219. // [Section]
  220. // a
  221. // b,c
  222. //
  223. // a & b are treated as Keys i.e. for keyless sections
  224. // the first value is treated as a key
  225. //
  226. bool IsKeyPresent(const std::basic_string<T> &Key) const {
  227. bool Result = false;
  228. if (!IsKeyless()) {
  229. std::vector< SectionValues<T> *>::const_iterator Iter = Lines.begin();
  230. SectionValues<T> *Values = NULL;
  231. while (Iter != Lines.end()) {
  232. Values = (*Iter);
  233. if (sizeof(T) == sizeof(CHAR)) {
  234. if (!_stricmp((PCSTR)Values->GetName().c_str(),
  235. (PCSTR)Key.c_str())) {
  236. break;
  237. }
  238. } else {
  239. if (!_wcsicmp((PCWSTR)Values->GetName().c_str(),
  240. (PCWSTR)Key.c_str())) {
  241. break;
  242. }
  243. }
  244. Iter++;
  245. }
  246. Result = (Iter != Lines.end());
  247. } else {
  248. std::vector< SectionValues<T> *>::const_iterator Iter = KeylessLines.begin();
  249. SectionValues<T> *Values = NULL;
  250. while (Iter != KeylessLines.end()) {
  251. Values = (*Iter);
  252. if (sizeof(T) == sizeof(CHAR)) {
  253. if (!_stricmp((PCSTR)Values->GetValue(0).c_str(),
  254. (PCSTR)Key.c_str())) {
  255. break;
  256. }
  257. } else {
  258. if (!_wcsicmp((PCWSTR)Values->GetValue(0).c_str(),
  259. (PCWSTR)Key.c_str())) {
  260. break;
  261. }
  262. }
  263. Iter++;
  264. }
  265. Result = (Iter != KeylessLines.end());
  266. }
  267. return Result;
  268. }
  269. SectionValues<T>& GetValue(ULONG Index) {
  270. return *(KeylessLines[Index]);
  271. }
  272. InfFile<T>& GetContainer() { return File; }
  273. bool IsKeyless() const { return Keyless; }
  274. Section<T>& operator+=(Section<T> &rhs) {
  275. if (IsKeyless() == rhs.IsKeyless()) {
  276. //
  277. // add entries with key
  278. //
  279. std::vector< SectionValues<T> *>::iterator Iter = rhs.Lines.begin();
  280. while (Iter != rhs.Lines.end()) {
  281. Lines.push_back(*Iter);
  282. Iter++;
  283. }
  284. //
  285. // add entries without key
  286. //
  287. std::vector< SectionValues<T> *>::iterator KlIter = rhs.KeylessLines.begin();
  288. while (KlIter != rhs.KeylessLines.end()) {
  289. KeylessLines.push_back(*KlIter);
  290. KlIter++;
  291. }
  292. } else {
  293. throw new InvalidInfSection<T>(File.GetName(), rhs.GetName());
  294. }
  295. return *this;
  296. }
  297. SectionValues<T>* AddLine(const std::basic_string<T> &Key) {
  298. SectionValues<T> *Value = NULL;
  299. if (Key.length() && !IsKeyless()) {
  300. Value = new SectionValues<T>(*this, Key, 0, true);
  301. if (Value) {
  302. Lines.push_back(Value);
  303. }
  304. } else {
  305. Value = new SectionValues<T>(*this, KeylessLines.size(), true);
  306. if (Value) {
  307. KeylessLines.push_back(Value);
  308. }
  309. }
  310. File.SetDirty();
  311. return Value;
  312. }
  313. friend std::ostream& operator<<(std::ostream &os, Section<T> &rhs) {
  314. os << "[" << rhs.GetName() << "]" << std::endl;
  315. Section<T>::Iterator Iter = rhs.begin();
  316. SectionValues<T> *Values;
  317. while (!Iter.end()) {
  318. Values = *Iter;
  319. if (Values) {
  320. os << *Values;
  321. }
  322. Iter++;
  323. }
  324. return os;
  325. }
  326. //
  327. // Callback function pointer for
  328. // working on each section element
  329. //
  330. typedef void (*ELEMENT_WORKER)(
  331. SectionValues<T> &Values,
  332. void *ContextData
  333. );
  334. void DoForEach(ELEMENT_WORKER Worker, void *ContextData);
  335. //
  336. // Iterator
  337. //
  338. class Iterator{
  339. public:
  340. Iterator(std::vector< SectionValues<T> *> *Collect = NULL) {
  341. Collection = Collect;
  342. if (Collection) {
  343. Iter = (*Collection).begin();
  344. }
  345. }
  346. Iterator& begin() {
  347. if (Collection) {
  348. Iter = Collection->begin();
  349. }
  350. return *this;
  351. }
  352. bool end() {
  353. return Collection? (Iter == Collection->end()) : true;
  354. }
  355. Iterator& operator++(int) {
  356. if (Collection) {
  357. Iter++;
  358. }
  359. return *this;
  360. }
  361. friend SectionValues<T> * operator*(Iterator &lhs) {
  362. return lhs.Collection ? *(lhs.Iter): NULL;
  363. }
  364. friend Section<T>;
  365. protected:
  366. void Init(std::vector< SectionValues<T> *> *Collect) {
  367. Collection = Collect;
  368. Iter = (*Collection).begin();
  369. }
  370. private:
  371. //
  372. // data members
  373. //
  374. typename std::vector< SectionValues<T> * >::iterator Iter;
  375. std::vector< SectionValues<T> *> *Collection;
  376. };
  377. Iterator begin(void) {
  378. Iterator Iter;
  379. if (IsKeyless()) {
  380. if (KeylessLines.size()) {
  381. Iter.Init(&KeylessLines);
  382. }
  383. } else {
  384. if (Lines.size()) {
  385. Iter.Init(&Lines);
  386. }
  387. }
  388. return Iter;
  389. }
  390. protected:
  391. //
  392. // data members
  393. //
  394. InfFile<T> &File;
  395. std::basic_string<T> Name;
  396. std::vector< SectionValues<T> *> Lines;
  397. std::vector< SectionValues<T> *> KeylessLines;
  398. bool Keyless;
  399. };
  400. template<class T>
  401. class InvalidInfFile : public BaseException<T> {
  402. public:
  403. InvalidInfFile() : ErrorCode(0){}
  404. InvalidInfFile(const std::basic_string<T> &Name) :
  405. FileName(Name), ErrorCode(0) {}
  406. InvalidInfFile(const std::basic_string<T> &Name, DWORD ErrCode) :
  407. FileName(Name), ErrorCode(ErrCode) {}
  408. void Dump(std::ostream &os) {
  409. os << "Invalid INF file " << FileName;
  410. if (ErrorCode) {
  411. os << " (" << std::dec << ErrorCode << ") ";
  412. }
  413. os << std::endl;
  414. }
  415. protected:
  416. std::basic_string<T> FileName;
  417. DWORD ErrorCode;
  418. };
  419. template<class T>
  420. class InvalidInfFormat : public InvalidInfFile<T> {
  421. public:
  422. InvalidInfFormat(const std::basic_string<T> &Name, UINT Line) :
  423. InvalidInfFile<T>(Name), ErrorLine(Line) {}
  424. void Dump(std::ostream &os) {
  425. os << "Invalid INF format at " << std::dec
  426. << ErrorLine << " line of " << FileName << std::endl;
  427. }
  428. UINT ErrorLine;
  429. };
  430. //
  431. // Inf file abstraction
  432. //
  433. template <class T>
  434. class InfFile {
  435. public:
  436. InfFile(const std::basic_string<T> &name);
  437. virtual ~InfFile() {
  438. if (InfHandle && (InfHandle != INVALID_HANDLE_VALUE)) {
  439. SetupCloseInfFile(InfHandle);
  440. }
  441. if (Dirty) {
  442. //CommitChanges();
  443. }
  444. SetupApiUseCount--;
  445. if (!SetupApiUseCount) {
  446. FreeLibrary(SetupApiModuleHandle);
  447. GetInfSections = NULL;
  448. }
  449. }
  450. const std::basic_string<T>& GetName() const {
  451. return Name;
  452. }
  453. friend bool operator==(const InfFile<T> &lhs, const InfFile<T> &rhs) {
  454. return lhs.GetName() == rhs.GetName();
  455. }
  456. friend bool operator!=(const InfFile<T> &lhs, const InfFile<T> &rhs) {
  457. return !(lhs == rhs);
  458. }
  459. void GetLines(Section<T> &Sec,
  460. std::vector< SectionValues<T> *> &Lines,
  461. std::vector< SectionValues<T> *> &KeylessLines);
  462. void GetValues(Section<T> &Sec,
  463. SectionValues<T> &SecValues,
  464. std::vector< std::basic_string<T> > &Values);
  465. friend std::ostream& operator<<(std::ostream &os, InfFile<T> &rhs) {
  466. InfFile<T>::Iterator Iter = rhs.begin();
  467. while (!Iter.end()) {
  468. os << **Iter << std::endl;
  469. Iter++;
  470. }
  471. return os;
  472. }
  473. Section<T>* AddSection(const std::basic_string<T> &SecName, bool Keyless) {
  474. Section<T> *NewSection = NULL;
  475. try {
  476. NewSection = GetSection(SecName);
  477. } catch(...) {
  478. }
  479. if (!NewSection) {
  480. Sections[SecName] = NewSection =
  481. new Section<T>(*this, SecName, Keyless);
  482. SetDirty();
  483. }
  484. return NewSection;
  485. }
  486. Section<T>* GetSection(const std::basic_string<T> &SecName) {
  487. std::map< std::basic_string<T>, Section<T> *>::iterator Iter = Sections.find(SecName);
  488. Section<T>* Sec = NULL;
  489. if (Iter != Sections.end()) {
  490. Sec = (*Iter).second;
  491. }
  492. return Sec;
  493. }
  494. void GetSections(std::map< std::basic_string<T>, Section<T> *> &Secs) {
  495. Secs = Sections;
  496. }
  497. void SetDirty() { Dirty = true; }
  498. const HINF GetInfHandle() const { return InfHandle; }
  499. //
  500. // Callback function pointer for
  501. // working on each section
  502. //
  503. typedef void (*ELEMENT_WORKER)(
  504. Section<T> &Section,
  505. void *ContextData
  506. );
  507. void DoForEach(ELEMENT_WORKER Worker, void *ContextData);
  508. //
  509. // Iterator
  510. //
  511. class Iterator{
  512. public:
  513. Iterator(std::map< std::basic_string<T>, Section<T> *> *Collect = NULL) {
  514. Collection = Collect;
  515. if (Collection) {
  516. Iter = (*Collection).begin();
  517. }
  518. }
  519. Iterator& begin() {
  520. if (Collection) {
  521. Iter = Collection->begin();
  522. }
  523. return *this;
  524. }
  525. bool end() {
  526. return Collection? (Iter == Collection->end()) : true;
  527. }
  528. Iterator& operator++(int) {
  529. if (Collection) {
  530. Iter++;
  531. }
  532. return *this;
  533. }
  534. friend Section<T> * operator*(Iterator &lhs) {
  535. return lhs.Collection ? (*(lhs.Iter)).second: NULL;
  536. }
  537. friend Section<T>;
  538. protected:
  539. void Init(std::map< std::basic_string<T>, Section<T> *> *Collect) {
  540. Collection = Collect;
  541. Iter = (*Collection).begin();
  542. }
  543. private:
  544. //
  545. // data members
  546. //
  547. typename std::map< std::basic_string<T>, Section<T> *>::iterator Iter;
  548. std::map< std::basic_string<T>, Section<T> *> *Collection;
  549. };
  550. Iterator begin(void) {
  551. return Iterator(&(this->Sections));
  552. }
  553. protected:
  554. HINF OpenFile() {
  555. HINF InfHandle = NULL;
  556. UINT ErrorLine = 0;
  557. if (sizeof(T) == sizeof(CHAR)) {
  558. InfHandle = SetupOpenInfFileA((const CHAR*)(GetName().c_str()),
  559. NULL,
  560. INF_STYLE_WIN4,
  561. &ErrorLine);
  562. } else {
  563. InfHandle = SetupOpenInfFileW((const WCHAR*)(GetName().c_str()),
  564. NULL,
  565. INF_STYLE_WIN4,
  566. &ErrorLine);
  567. }
  568. if (InfHandle == INVALID_HANDLE_VALUE) {
  569. DWORD ErrorCode = ::GetLastError();
  570. if (ErrorLine) {
  571. throw new InvalidInfFormat<T>(GetName(), ErrorLine);
  572. } else {
  573. throw new InvalidInfFile<T>(GetName(), ErrorCode);
  574. }
  575. }
  576. return InfHandle;
  577. }
  578. typedef BOOL (* GetInfSectionsRoutine)(HINF, T*, UINT, UINT *);
  579. //
  580. // data members
  581. //
  582. std::basic_string<T> Name;
  583. HINF InfHandle;
  584. bool Dirty;
  585. static GetInfSectionsRoutine GetInfSections;
  586. static HMODULE SetupApiModuleHandle;
  587. static ULONG SetupApiUseCount;
  588. std::map< std::basic_string<T>, Section<T> *> Sections;
  589. };
  590. template <class T>
  591. SectionValues<T>::SectionValues(Section<T> &Sec,
  592. const std::basic_string<T> &Key, ULONG LineIdx, bool New)
  593. : Container(Sec), Name(Key), Index(LineIdx) {
  594. if (!New) {
  595. GetContainer().GetContainer().GetValues(Sec, *this, Values);
  596. }
  597. }
  598. template <class T>
  599. SectionValues<T>::SectionValues(Section<T> &Sec, ULONG LineIdx, bool New)
  600. : Container(Sec), Index(LineIdx) {
  601. BYTE Buffer[64] = {0};
  602. if (sizeof(T) == sizeof(CHAR)) {
  603. Name = std::basic_string<T>((const T*)_ltoa(Index, (char *)Buffer, 10));
  604. } else {
  605. Name = std::basic_string<T>((const T*)_ltow(Index, (wchar_t*)Buffer, 10));
  606. }
  607. if (!New) {
  608. GetContainer().GetContainer().GetValues(Sec, *this, Values);
  609. }
  610. }
  611. template <class T>
  612. Section<T>::Section(InfFile<T> &file, const std::basic_string<T> &name)
  613. : Name(name), File(file), Keyless(false) {
  614. INFCONTEXT InfContext;
  615. BOOL Result;
  616. const HINF InfHandle = GetContainer().GetInfHandle();
  617. if (sizeof(T) == sizeof(CHAR)) {
  618. Result = SetupFindFirstLineA((HINF)InfHandle,
  619. (PCSTR)GetName().c_str(),
  620. NULL,
  621. &InfContext);
  622. } else {
  623. Result = SetupFindFirstLineW((HINF)InfHandle,
  624. (PCWSTR)GetName().c_str(),
  625. NULL,
  626. &InfContext);
  627. }
  628. //std::cout << Name << " is " << Keyless << std::endl;
  629. if (Result) {
  630. BYTE Buffer[4096], Buffer1[4096];
  631. bool KeyPresent = false;
  632. //
  633. // NOTE : singular values in section are treated as keys
  634. // by setupapi so take care of such cases correctly
  635. // as keyless entries
  636. //
  637. // ISSUE : because of the way we are trying to determine
  638. // keyless section a sections with first entry a = a will
  639. // be treated as keyless section wrongly.
  640. //
  641. if (sizeof(T) == sizeof(CHAR)) {
  642. *((PSTR)Buffer) = '\0';
  643. *((PSTR)Buffer1) = '\0';
  644. if (SetupGetStringFieldA(&InfContext,
  645. 0,
  646. (PSTR)Buffer,
  647. sizeof(Buffer) / sizeof(T),
  648. NULL) &&
  649. SetupGetStringFieldA(&InfContext,
  650. 1,
  651. (PSTR)Buffer1,
  652. sizeof(Buffer1) / sizeof(T),
  653. NULL)) {
  654. KeyPresent = (_stricmp((PCSTR)Buffer, (PCSTR)Buffer1) != 0);
  655. }
  656. } else {
  657. *((PWSTR)Buffer) = L'\0';
  658. *((PWSTR)Buffer1) = L'\0';
  659. if (SetupGetStringFieldW(&InfContext,
  660. 0,
  661. (PWSTR)Buffer,
  662. sizeof(Buffer) / sizeof(T),
  663. NULL) &&
  664. SetupGetStringFieldW(&InfContext,
  665. 1,
  666. (PWSTR)Buffer1,
  667. sizeof(Buffer1) / sizeof(T),
  668. NULL)) {
  669. KeyPresent = (_wcsicmp((PCWSTR)Buffer, (PCWSTR)Buffer1) != 0);
  670. }
  671. }
  672. // If we cannot read 0th value, then we
  673. // assume that the whole section is
  674. // doesnot have entries with key
  675. //
  676. Keyless = !KeyPresent;
  677. }
  678. GetContainer().GetLines(*this, Lines, KeylessLines);
  679. //std::cout << Name << " is " << Keyless << std::endl;
  680. }
  681. template<class T>
  682. void
  683. Section<T>::DoForEach(typename Section<T>::ELEMENT_WORKER Worker,
  684. void *ContextData) {
  685. if (IsKeyless()) {
  686. std::vector< SectionValues<T> * >::iterator Iter = KeylessLines.begin();
  687. SectionValues<T> *Value;
  688. while (Iter != KeylessLines.end()) {
  689. Value = *Iter;
  690. if (Value) {
  691. Worker(*Value, ContextData);
  692. }
  693. Iter++;
  694. }
  695. } else {
  696. std::vector< SectionValues<T> *>::iterator Iter = Lines.begin();
  697. SectionValues<T> *Value;
  698. while (Iter != Lines.end()) {
  699. Value = *Iter;
  700. if (Value) {
  701. Worker(*Value, ContextData);
  702. }
  703. Iter++;
  704. }
  705. }
  706. }
  707. template <class T>
  708. InfFile<T>::InfFile(const std::basic_string<T> &name) : Name(name) {
  709. Dirty = false;
  710. InfHandle = OpenFile();
  711. if (!GetInfSections) {
  712. SetupApiModuleHandle = LoadLibrary(TEXT("setupapi.dll"));
  713. if (SetupApiModuleHandle) {
  714. GetInfSections = (GetInfSectionsRoutine)(GetProcAddress(SetupApiModuleHandle,
  715. "pSetupGetInfSections"));
  716. if (!GetInfSections) {
  717. GetInfSections = (GetInfSectionsRoutine)(GetProcAddress(SetupApiModuleHandle,
  718. "SetupGetInfSections"));
  719. }
  720. }
  721. if (!GetInfSections) {
  722. throw new W32Exception<T>();
  723. }
  724. }
  725. SetupApiUseCount++;
  726. //
  727. // get hold of all the sections
  728. //
  729. UINT CurrSize = 4096;
  730. UINT SizeNeeded = 0;
  731. DWORD LastError = 0;
  732. WCHAR *Buffer = new WCHAR[CurrSize];
  733. memset(Buffer, 0, CurrSize);
  734. BOOL Result = GetInfSections(InfHandle, Buffer, CurrSize, &SizeNeeded);
  735. if (!Result && (SizeNeeded > CurrSize)) {
  736. delete []Buffer;
  737. Buffer = new WCHAR[SizeNeeded];
  738. memset(Buffer, 0, SizeNeeded);
  739. CurrSize = SizeNeeded;
  740. Result = GetInfSections(InfHandle, Buffer, CurrSize, &SizeNeeded);
  741. }
  742. std::vector<std::basic_string<T> > SectionNames;
  743. if (Result) {
  744. while (Buffer && *Buffer) {
  745. std::basic_string<WCHAR> WNextSection((const WCHAR*)Buffer);
  746. if (sizeof(T) == sizeof(CHAR)) {
  747. std::basic_string<T> NextSection;
  748. ToAnsiString((std::basic_string<char> &)NextSection, WNextSection);
  749. SectionNames.push_back(NextSection);
  750. } else {
  751. std::basic_string<T> NextSection((const T *)WNextSection.c_str());
  752. SectionNames.push_back(NextSection);
  753. }
  754. Buffer += (WNextSection.length() + 1);
  755. }
  756. } else {
  757. LastError = ::GetLastError();
  758. }
  759. if (Result && SectionNames.size()) {
  760. std::vector<std::basic_string<T> >::iterator NameIter = SectionNames.begin();
  761. while (NameIter != SectionNames.end()) {
  762. // std::cout << *NameIter << std::endl;
  763. Sections[*NameIter] = new Section<T>(*this, *NameIter);
  764. NameIter++;
  765. }
  766. }
  767. if (!Result) {
  768. throw new InvalidInfFile<T>(GetName(), LastError);
  769. }
  770. }
  771. template<class T>
  772. void
  773. InfFile<T>::DoForEach(
  774. typename InfFile<T>::ELEMENT_WORKER Worker,
  775. void *ContextData
  776. )
  777. {
  778. std::map< std::basic_string<T>, Section<T> *>::iterator
  779. Iter = Sections.begin();
  780. while (Iter != Sections.end()) {
  781. Worker(*(*Iter).second, ContextData);
  782. Iter++;
  783. }
  784. }
  785. template <class T>
  786. void
  787. InfFile<T>::GetLines(
  788. Section<T> &Sec,
  789. std::vector< SectionValues<T> *> &Values,
  790. std::vector< SectionValues<T> *> &KeylessValues
  791. )
  792. {
  793. std::vector< SectionValues<T>* >::iterator MapIter = Values.begin();
  794. //
  795. // delete the old values (if any)
  796. //
  797. while (MapIter != Values.end()) {
  798. if (*MapIter) {
  799. delete (*MapIter);
  800. }
  801. MapIter++;
  802. }
  803. Values.clear();
  804. std::vector< SectionValues<T>* >::iterator KeylessIter = KeylessValues.begin();
  805. //
  806. // delete the old values (if any)
  807. //
  808. while (KeylessIter != KeylessValues.end()) {
  809. if (*KeylessIter) {
  810. delete (*KeylessIter);
  811. }
  812. KeylessIter++;
  813. }
  814. KeylessValues.clear();
  815. //
  816. // locate the first line
  817. //
  818. INFCONTEXT InfContext;
  819. BOOL Result;
  820. DWORD LineCount;
  821. if (sizeof(T) == sizeof(CHAR)) {
  822. LineCount = SetupGetLineCountA(InfHandle,
  823. (PCSTR)Sec.GetName().c_str());
  824. } else {
  825. LineCount = SetupGetLineCountW(InfHandle,
  826. (PCWSTR)Sec.GetName().c_str());
  827. }
  828. if (LineCount) {
  829. if (sizeof(T) == sizeof(CHAR)) {
  830. Result = SetupFindFirstLineA(InfHandle,
  831. (PCSTR)Sec.GetName().c_str(),
  832. NULL,
  833. &InfContext);
  834. } else {
  835. Result = SetupFindFirstLineW(InfHandle,
  836. (PCWSTR)Sec.GetName().c_str(),
  837. NULL,
  838. &InfContext);
  839. }
  840. if (Result) {
  841. BYTE Buffer[4096];
  842. bool Read = false;
  843. BOOL NextLine = TRUE;
  844. DWORD Index = 0;
  845. bool Keyless = Sec.IsKeyless();
  846. for (Index=0; (NextLine && (Index < LineCount)); Index++) {
  847. Buffer[0] = Buffer[1] = 0;
  848. Read = false;
  849. if (!Keyless) {
  850. if (sizeof(T) == sizeof(CHAR)) {
  851. if (SetupGetStringFieldA(&InfContext,
  852. 0,
  853. (PSTR)Buffer,
  854. sizeof(Buffer) / sizeof(T),
  855. NULL)) {
  856. Read = true;
  857. }
  858. } else {
  859. if (SetupGetStringFieldW(&InfContext,
  860. 0,
  861. (PWSTR)Buffer,
  862. sizeof(Buffer) / sizeof(T),
  863. NULL)) {
  864. Read = true;
  865. }
  866. }
  867. }
  868. if (Read) {
  869. std::basic_string<T> Key((const T *)Buffer);
  870. //std::cout << Key << std::endl;
  871. Values.push_back(new SectionValues<T>(Sec, Key, Index));
  872. } else {
  873. KeylessValues.push_back(new SectionValues<T>(Sec, Index));
  874. }
  875. NextLine = SetupFindNextLine(&InfContext, &InfContext);
  876. }
  877. if (!NextLine && (Index < LineCount)) {
  878. throw new InvalidInfSection<T>(Sec.GetName(), GetName());
  879. }
  880. } else {
  881. throw new InvalidInfSection<T>(Sec.GetName(), GetName());
  882. }
  883. }
  884. }
  885. template <class T>
  886. void
  887. InfFile<T>::GetValues(
  888. Section<T> &Sec,
  889. SectionValues<T> &SecValues,
  890. std::vector<std::basic_string<T> > &Values
  891. )
  892. {
  893. const std::basic_string<T> &SecName = Sec.GetName();
  894. const std::basic_string<T> &Key = SecValues.GetName();
  895. INFCONTEXT InfContext;
  896. BOOL Result = TRUE;
  897. ULONG Lines = 0;
  898. Values.clear();
  899. if (sizeof(T) == sizeof(CHAR)) {
  900. Lines = SetupGetLineCountA(InfHandle,
  901. (PCSTR)SecName.c_str());
  902. } else {
  903. Lines = SetupGetLineCountW(InfHandle,
  904. (PCWSTR)SecName.c_str());
  905. }
  906. if (Lines) {
  907. if (sizeof(T) == sizeof(CHAR)) {
  908. Result = SetupGetLineByIndexA(InfHandle,
  909. (PCSTR)SecName.c_str(),
  910. SecValues.GetIndex(),
  911. &InfContext);
  912. } else {
  913. Result = SetupGetLineByIndexW(InfHandle,
  914. (PCWSTR)SecName.c_str(),
  915. SecValues.GetIndex(),
  916. &InfContext);
  917. }
  918. if (Result) {
  919. DWORD FieldCount = SetupGetFieldCount(&InfContext);
  920. BYTE Buffer[2048];
  921. for (DWORD Index=0; Index < FieldCount; Index++) {
  922. Buffer[0] = Buffer[1] = 0;
  923. if (sizeof(T) == sizeof(CHAR)) {
  924. if (SetupGetStringFieldA(&InfContext,
  925. Index + 1,
  926. (PSTR)Buffer,
  927. sizeof(Buffer) / sizeof(T),
  928. NULL)) {
  929. Values.push_back((const T *)Buffer);
  930. }
  931. } else {
  932. if (SetupGetStringFieldW(&InfContext,
  933. Index + 1,
  934. (PWSTR)Buffer,
  935. sizeof(Buffer) / sizeof(T),
  936. NULL)) {
  937. Values.push_back((const T *)Buffer);
  938. }
  939. }
  940. }
  941. } else {
  942. throw new InvalidInfSection<T>(SecName, GetName());
  943. }
  944. }
  945. }
  946. typedef InfFile<CHAR> InfFileA;
  947. typedef InfFile<WCHAR> InfFileW;