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.

1067 lines
32 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. efinvram.cpp
  5. Abstract:
  6. Tool that allows you to edit/view EFI
  7. nvram entries.
  8. Author:
  9. Vijay Jayaseelan (vijayj) 02-Feb-2001
  10. Revision History:
  11. None
  12. --*/
  13. extern "C" {
  14. #include <efisbent.h>
  15. #include <setupapi.h>
  16. }
  17. #include <iostream>
  18. #include <string>
  19. #include <exception>
  20. #include <windows.h>
  21. #include <tchar.h>
  22. #include <locale>
  23. #include "msg.h"
  24. #include <libmsg.h>
  25. #define DEFAULT_NAME L"Windows"
  26. #define DEFAULT_TIMEOUT 30
  27. //
  28. // Global variables used to get formatted message for this program.
  29. //
  30. HMODULE ThisModule = NULL;
  31. WCHAR Message[4096];
  32. //
  33. // function prototypes
  34. //
  35. NTSTATUS
  36. QueryCanonicalName(
  37. IN PCWSTR Name,
  38. IN ULONG MaxDepth,
  39. OUT PWSTR CanonicalName,
  40. IN ULONG SizeOfBufferInBytes
  41. );
  42. VOID
  43. GetFriendlyName(
  44. IN const std::wstring &InfFileName,
  45. OUT std::wstring &Buffer
  46. );
  47. void
  48. DeriveNtPathAndSrcPath(
  49. IN const std::wstring &FullPath,
  50. OUT std::wstring &DrvDevicePath,
  51. OUT std::wstring &DrvSrcPath
  52. );
  53. //
  54. // Helper dump operators
  55. //
  56. std::ostream& operator<<(std::ostream &os, const std::wstring &str) {
  57. FILE *OutStream = (&os == &std::cerr) ? stderr : stdout;
  58. fwprintf(OutStream, (PWSTR)str.c_str());
  59. return os;
  60. }
  61. //
  62. // Helper dump operators
  63. //
  64. std::ostream& operator<<(std::ostream &os, WCHAR *Str) {
  65. std::wstring WStr = Str;
  66. os << WStr;
  67. return os;
  68. }
  69. PWSTR GetOptionKey(ULONG MsgId) {
  70. Message[0] = TEXT('\0');
  71. GetFormattedMessage(ThisModule,
  72. FALSE,
  73. Message,
  74. sizeof(Message)/sizeof(Message[0]),
  75. MsgId);
  76. return Message;
  77. }
  78. //
  79. // Exceptions
  80. //
  81. struct ProgramException : public std::exception {
  82. virtual void Dump(std::ostream &os) = 0;
  83. };
  84. //
  85. // Abstracts a Win32 error
  86. //
  87. struct W32Error : public ProgramException {
  88. DWORD ErrorCode;
  89. W32Error(DWORD ErrCode = GetLastError()) : ErrorCode(ErrCode){}
  90. void Dump(std::ostream &os) {
  91. WCHAR MsgBuffer[4096];
  92. MsgBuffer[0] = UNICODE_NULL;
  93. if (GetFormattedMessage(ThisModule,
  94. TRUE,
  95. MsgBuffer,
  96. sizeof(MsgBuffer)/sizeof(MsgBuffer[0]),
  97. ErrorCode)){
  98. std::wstring Msg(MsgBuffer);
  99. os << Msg;
  100. } else {
  101. os << std::hex << ErrorCode;
  102. }
  103. }
  104. };
  105. //
  106. // Invalid arguments
  107. //
  108. struct InvalidArguments : public ProgramException {
  109. const char *what() const throw() {
  110. return "Invalid Arguments";
  111. }
  112. void Dump(std::ostream &os) {
  113. os << what() << std::endl;
  114. }
  115. };
  116. //
  117. // Invalid arguments
  118. //
  119. struct ProgramUsage : public ProgramException {
  120. std::wstring PrgUsage;
  121. ProgramUsage(const std::wstring &Usg) : PrgUsage(Usg) {}
  122. const char *what() const throw() {
  123. return "Program Usage exception";
  124. }
  125. void Dump(std::ostream &os) {
  126. os << PrgUsage << std::endl;
  127. }
  128. };
  129. //
  130. // Program Arguments abstraction
  131. //
  132. struct ProgramArguments {
  133. bool ShowUsage;
  134. bool ListEntries;
  135. bool AddNewEntry;
  136. bool DeleteBootEntry;
  137. bool QuiteMode;
  138. bool SetActive;
  139. bool SetOsLoadOptions;
  140. bool SetTimeout;
  141. bool ListDrvEntries;
  142. bool AddDrvEntry;
  143. bool DelDrvEntry;
  144. std::wstring LoaderVolumeName;
  145. std::wstring LoaderPath;
  146. std::wstring BootVolumeName;
  147. std::wstring BootPath;
  148. std::wstring LoadOptions;
  149. std::wstring FriendlyName;
  150. std::wstring OsLoadOptions;
  151. std::wstring AddOptionKey;
  152. std::wstring DeleteOptionKey;
  153. std::wstring ListOptionKey;
  154. std::wstring OptionsOptionKey;
  155. std::wstring SetActiveOptionKey;
  156. std::wstring TimeoutOptionKey;
  157. ULONG Timeout;
  158. ULONG EntryId;
  159. std::wstring DrvDevicePath;
  160. std::wstring FullPath;
  161. std::wstring DrvSrcPath;
  162. std::wstring DrvFriendlyName;
  163. std::wstring ListDrvOptionKey;
  164. std::wstring AddDrvOptionKey;
  165. std::wstring DelDrvOptionKey;
  166. ULONG DrvId;
  167. ProgramArguments(INT Argc, WCHAR *Argv[]) {
  168. ShowUsage = false;
  169. QuiteMode = false;
  170. ListEntries = AddNewEntry = DeleteBootEntry = false;
  171. ListDrvEntries = AddDrvEntry = DelDrvEntry = false;
  172. SetActive = false;
  173. EntryId = -1;
  174. Timeout = DEFAULT_TIMEOUT;
  175. SetTimeout = false;
  176. //
  177. // get all the options
  178. //
  179. ListOptionKey = GetOptionKey(MSG_LIST_OPTION);
  180. AddOptionKey = GetOptionKey(MSG_ADD_OPTION);
  181. DeleteOptionKey = GetOptionKey(MSG_DELETE_OPTION);
  182. OptionsOptionKey = GetOptionKey(MSG_OPTIONS_OPTION);
  183. SetActiveOptionKey = GetOptionKey(MSG_SETACTIVE_OPTION);
  184. TimeoutOptionKey = GetOptionKey(MSG_TIMEOUT_OPTION);
  185. ListDrvOptionKey = GetOptionKey(MSG_LISTDRV_OPTION);
  186. AddDrvOptionKey = GetOptionKey(MSG_ADDDRV_OPTION);
  187. DelDrvOptionKey = GetOptionKey(MSG_DELDRV_OPTION);
  188. //
  189. // parse the arguments
  190. //
  191. for (ULONG Index=1; !ShowUsage && (Index < Argc); Index++) {
  192. if (!_wcsicmp(Argv[Index], L"/q")) {
  193. QuiteMode = true;
  194. } else if (!_wcsicmp(Argv[Index], AddOptionKey.c_str())) {
  195. std::wstring LoaderName;
  196. std::wstring BootVolName;
  197. AddNewEntry = true;
  198. ShowUsage = true;
  199. if (Argc > 3) {
  200. Index++;
  201. LoaderName = Argv[Index++];
  202. BootVolName = Argv[Index++];
  203. ShowUsage = false;
  204. for ( ; (Index < Argc) && (false == ShowUsage); Index++) {
  205. if (!_wcsicmp(Argv[Index], SetActiveOptionKey.c_str())) {
  206. SetActive = true;
  207. } else if (!_wcsicmp(Argv[Index], OptionsOptionKey.c_str())) {
  208. SetOsLoadOptions = true;
  209. Index++;
  210. if (Index < Argc) {
  211. OsLoadOptions = Argv[Index];
  212. } else {
  213. ShowUsage = true;
  214. }
  215. } else if (!_wcsicmp(Argv[Index], TimeoutOptionKey.c_str())) {
  216. SetTimeout = true;
  217. Index++;
  218. if (Index < Argc) {
  219. PWSTR EndChar = NULL;
  220. Timeout = wcstoul(Argv[Index], &EndChar, 10);
  221. if (errno) {
  222. ShowUsage = true;
  223. }
  224. }
  225. } else {
  226. ShowUsage = true;
  227. }
  228. }
  229. //
  230. // Verify the arguments
  231. //
  232. if (!ShowUsage) {
  233. NTSTATUS Status;
  234. if (_waccess(LoaderName.c_str(), 0) ||
  235. _waccess(BootVolName.c_str(), 0)) {
  236. throw new W32Error(::GetLastError());
  237. }
  238. //
  239. // Get the fully qualified NT name for
  240. // the the loader volume and boot volume
  241. // name
  242. //
  243. DeriveNtPathAndSrcPath(LoaderName,
  244. LoaderVolumeName,
  245. LoaderPath);
  246. DeriveNtPathAndSrcPath(BootVolName,
  247. BootVolumeName,
  248. BootPath);
  249. if (BootVolName[BootVolName.length() - 1] != L'\\') {
  250. BootVolName += L"\\";
  251. }
  252. std::wstring LayoutInf = BootVolName + L"inf\\layout.inf";
  253. //
  254. // Verify the inf file path
  255. //
  256. if (_waccess(LayoutInf.c_str(), 0)) {
  257. throw new W32Error(::GetLastError());
  258. }
  259. //
  260. // Extract the product friendly name for the inf file
  261. //
  262. GetFriendlyName(LayoutInf, FriendlyName);
  263. }
  264. }
  265. break;
  266. } else if (!_wcsicmp(Argv[Index], ListOptionKey.c_str())) {
  267. ListEntries = true;
  268. break;
  269. } else if (!_wcsicmp(Argv[Index], DeleteOptionKey.c_str())) {
  270. DeleteBootEntry = true;
  271. Index++;
  272. if (Index < Argc) {
  273. PWSTR EndChar = NULL;
  274. EntryId = wcstoul(Argv[Index], &EndChar, 10);
  275. }
  276. break;
  277. } else if (!_wcsicmp(Argv[Index], L"/?") ||
  278. !_wcsicmp(Argv[Index], L"-?") ||
  279. !_wcsicmp(Argv[Index], L"?") ||
  280. !_wcsicmp(Argv[Index], L"/h") ||
  281. !_wcsicmp(Argv[Index], L"-h")) {
  282. ShowUsage = true;
  283. } else if (!_wcsicmp(Argv[Index], OptionsOptionKey.c_str())) {
  284. Index++;
  285. SetOsLoadOptions = true;
  286. if (Index < Argc) {
  287. OsLoadOptions = Argv[Index];
  288. Index++;
  289. if (Index < Argc) {
  290. PWSTR EndChar = NULL;
  291. EntryId = wcstoul(Argv[Index], &EndChar, 10);
  292. }
  293. }
  294. break;
  295. } else if (!_wcsicmp(Argv[Index], SetActiveOptionKey.c_str())) {
  296. Index++;
  297. SetActive = true;
  298. if (Index < Argc) {
  299. PWSTR EndChar = NULL;
  300. EntryId = wcstoul(Argv[Index], &EndChar, 10);
  301. if (errno) {
  302. ShowUsage = true;
  303. }
  304. } else {
  305. ShowUsage = true;
  306. }
  307. break;
  308. } else if (!_wcsicmp(Argv[Index], TimeoutOptionKey.c_str())) {
  309. Index++;
  310. SetTimeout = true;
  311. if (Index < Argc) {
  312. PWSTR EndChar = NULL;
  313. Timeout = wcstoul(Argv[Index], &EndChar, 10);
  314. if (errno) {
  315. ShowUsage = true;
  316. }
  317. } else {
  318. ShowUsage = true;
  319. }
  320. } else if (!_wcsicmp(Argv[Index], ListDrvOptionKey.c_str())){
  321. ListDrvEntries = true;
  322. } else if (!_wcsicmp(Argv[Index], AddDrvOptionKey.c_str())){
  323. if (Index + 2 < Argc){
  324. FullPath = Argv[++Index];
  325. if (_waccess(FullPath.c_str(), 0)) {
  326. throw new W32Error(::GetLastError());
  327. }
  328. DeriveNtPathAndSrcPath(FullPath,
  329. DrvDevicePath,
  330. DrvSrcPath);
  331. DrvFriendlyName = Argv[++Index];
  332. ShowUsage = false;
  333. AddDrvEntry = true;
  334. }
  335. break;
  336. } else if (!_wcsicmp(Argv[Index], DelDrvOptionKey.c_str())){
  337. if (Index + 1 < Argc){
  338. PWSTR EndChar = NULL;
  339. DrvId = wcstoul(Argv[++Index], &EndChar, 10);
  340. ShowUsage = false;
  341. DelDrvEntry = true;
  342. }
  343. break;
  344. } else {
  345. ShowUsage = true;
  346. }
  347. }
  348. if (!ShowUsage) {
  349. ShowUsage = (!ListEntries && !AddNewEntry && !SetActive &&
  350. !DeleteBootEntry && !SetOsLoadOptions && !SetTimeout &&
  351. !ListDrvEntries && !AddDrvEntry && !DelDrvEntry);
  352. }
  353. if (ShowUsage) {
  354. throw new ProgramUsage(GetFormattedMessage( ThisModule,
  355. FALSE,
  356. Message,
  357. sizeof(Message)/sizeof(Message[0]),
  358. MSG_PGM_USAGE));
  359. }
  360. }
  361. friend std::ostream& operator<<(std::ostream &os, ProgramArguments &Args) {
  362. os << "List Entries : " << Args.ListEntries << std::endl;
  363. os << "Add Entry : " << Args.AddNewEntry << std::endl;
  364. os << "Delete Entry : " << Args.DeleteBootEntry << std::endl;
  365. os << "QuiteMode : " << Args.QuiteMode << std::endl;
  366. os << "Loader Vol : " << Args.LoaderVolumeName << std::endl;
  367. os << "Loader Path : " << Args.LoaderPath << std::endl;
  368. os << "Boot Vol : " << Args.BootVolumeName << std::endl;
  369. os << "Boot Path : " << Args.BootPath << std::endl;
  370. os << "Friendly Name: " << Args.FriendlyName << std::endl;
  371. os << "Load Options : " << Args.OsLoadOptions << std::endl;
  372. os << "Timeout : " << std::dec << Args.Timeout << " Secs" << std::endl;
  373. return os;
  374. }
  375. };
  376. void
  377. DeriveNtPathAndSrcPath(
  378. IN const std::wstring &FullPath,
  379. OUT std::wstring &DrvDevicePath,
  380. OUT std::wstring &DrvSrcPath
  381. )
  382. {
  383. WCHAR CanonicalName[MAX_PATH];
  384. std::wstring NtName;
  385. std::wstring DosDevices = L"\\DosDevices\\";
  386. std::wstring::size_type ColonPos = FullPath.find(L':');
  387. if (ColonPos != FullPath.npos) {
  388. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  389. NtName = DosDevices + FullPath.substr(0, ColonPos + 1);
  390. Status = QueryCanonicalName(NtName.c_str(),
  391. -1,
  392. CanonicalName,
  393. sizeof(CanonicalName));
  394. if (NT_SUCCESS(Status)) {
  395. DrvDevicePath = CanonicalName;
  396. DrvSrcPath = FullPath.substr(ColonPos + 1);
  397. } else {
  398. throw new W32Error(RtlNtStatusToDosError(Status));
  399. }
  400. } else {
  401. throw new W32Error(ERROR_PATH_NOT_FOUND);
  402. }
  403. }
  404. VOID
  405. DumpOsBootEntry(
  406. IN POS_BOOT_ENTRY Entry
  407. )
  408. {
  409. if (Entry) {
  410. wprintf(GetFormattedMessage( ThisModule,
  411. FALSE,
  412. Message,
  413. sizeof(Message)/sizeof(Message[0]),
  414. MSG_BOOT_ENTRY,
  415. OSBEGetId(Entry),
  416. OSBEGetFriendlyName(Entry),
  417. OSBEGetOsLoaderVolumeName(Entry),
  418. OSBEGetOsLoaderPath(Entry),
  419. OSBEGetBootVolumeName(Entry),
  420. OSBEGetBootPath(Entry),
  421. OSBEGetOsLoadOptions(Entry)));
  422. }
  423. }
  424. VOID
  425. DumpOsBootOptions(
  426. IN POS_BOOT_OPTIONS Options
  427. )
  428. {
  429. if (Options) {
  430. ULONG Index;
  431. wprintf(GetFormattedMessage( ThisModule,
  432. FALSE,
  433. Message,
  434. sizeof(Message)/sizeof(Message[0]),
  435. MSG_TIMEOUT_AND_BOOT_ORDER,
  436. OSBOGetTimeOut(Options)));
  437. for (Index=0;
  438. Index < OSBOGetOrderedBootEntryCount(Options);
  439. Index++) {
  440. wprintf(GetFormattedMessage( ThisModule,
  441. FALSE,
  442. Message,
  443. sizeof(Message)/sizeof(Message[0]),
  444. MSG_ORDERED_BOOT_ENTRIES,
  445. OSBOGetBootEntryIdByOrder(Options, Index)));
  446. }
  447. wprintf(GetFormattedMessage( ThisModule,
  448. FALSE,
  449. Message,
  450. sizeof(Message)/sizeof(Message[0]),
  451. MSG_BOOT_ENTRIES));
  452. POS_BOOT_ENTRY Entry = OSBOGetFirstBootEntry(Options, &Index);
  453. while (Entry) {
  454. DumpOsBootEntry(Entry);
  455. Entry = OSBOGetNextBootEntry(Options, &Index);
  456. }
  457. wprintf(GetFormattedMessage( ThisModule,
  458. FALSE,
  459. Message,
  460. sizeof(Message)/sizeof(Message[0]),
  461. MSG_ACTIVE_ENTRY));
  462. DumpOsBootEntry(OSBOGetActiveBootEntry(Options));
  463. }
  464. }
  465. DWORD
  466. ListDriverEntry(
  467. IN POS_BOOT_OPTIONS OsOptions
  468. )
  469. {
  470. DWORD Result = ERROR_INVALID_PARAMETER;
  471. if (OsOptions){
  472. PDRIVER_ENTRY DrvEntry ;
  473. for (DrvEntry = OSBOGetFirstDriverEntry(OsOptions);
  474. DrvEntry != NULL;
  475. DrvEntry = OSBOGetNextDriverEntry(OsOptions,DrvEntry)){
  476. wprintf(GetFormattedMessage( ThisModule,
  477. FALSE,
  478. Message,
  479. sizeof(Message)/sizeof(Message[0]),
  480. MSG_DRIVER_ENTRY,
  481. OSDriverGetId(DrvEntry),
  482. OSDriverGetFriendlyName(DrvEntry),
  483. OSDriverGetFileName(DrvEntry),
  484. OSDriverGetDevicePath(DrvEntry),
  485. OSDriverGetFilePath(DrvEntry)));
  486. }
  487. Result = ERROR_SUCCESS;
  488. }
  489. return Result;
  490. }
  491. DWORD
  492. ListEntries(
  493. IN POS_BOOT_OPTIONS OsOptions
  494. )
  495. {
  496. DWORD Result = ERROR_INVALID_PARAMETER;
  497. if (OsOptions) {
  498. DumpOsBootOptions(OsOptions);
  499. Result = ERROR_SUCCESS;
  500. }
  501. return Result;
  502. }
  503. DWORD
  504. AddNewDriverEntry(
  505. IN POS_BOOT_OPTIONS OsOptions,
  506. IN ProgramArguments &Args
  507. )
  508. {
  509. DWORD Result = ERROR_INVALID_PARAMETER;
  510. if (OsOptions){
  511. PDRIVER_ENTRY NewDrvEntry =NULL;
  512. BOOLEAN Status = FALSE;
  513. NewDrvEntry = OSBOAddNewDriverEntry(OsOptions,
  514. Args.DrvFriendlyName.c_str(),
  515. Args.DrvDevicePath.c_str(),
  516. Args.DrvSrcPath.c_str());
  517. if (NewDrvEntry) {
  518. Status = OSBOFlush(OsOptions);
  519. }
  520. if (Status){
  521. Result = ERROR_SUCCESS;
  522. } else {
  523. Result = ERROR_CAN_NOT_COMPLETE;
  524. }
  525. }
  526. return Result;
  527. }
  528. DWORD
  529. AddNewEntry(
  530. IN POS_BOOT_OPTIONS OsOptions,
  531. IN ProgramArguments &Args
  532. )
  533. {
  534. DWORD Result = ERROR_INVALID_PARAMETER;
  535. if (OsOptions) {
  536. POS_BOOT_ENTRY NewEntry;
  537. BOOLEAN Status = TRUE;
  538. NewEntry = OSBOAddNewBootEntry(OsOptions,
  539. Args.FriendlyName.c_str(),
  540. Args.LoaderVolumeName.c_str(),
  541. Args.LoaderPath.c_str(),
  542. Args.BootVolumeName.c_str(),
  543. Args.BootPath.c_str(),
  544. Args.OsLoadOptions.c_str());
  545. if (NewEntry) {
  546. if (Args.SetActive) {
  547. Status = (OSBOSetActiveBootEntry(OsOptions,
  548. NewEntry) != NULL);
  549. }
  550. if (Status && Args.SetTimeout) {
  551. OSBOSetTimeOut(OsOptions, Args.Timeout);
  552. }
  553. if (Status) {
  554. Status = OSBOFlush(OsOptions);
  555. }
  556. } else {
  557. Status = FALSE;
  558. }
  559. if (Status) {
  560. Result = ERROR_SUCCESS;
  561. } else {
  562. Result = ERROR_CAN_NOT_COMPLETE;
  563. }
  564. }
  565. return Result;
  566. }
  567. DWORD
  568. SetBootEntryOptions(
  569. IN POS_BOOT_OPTIONS OsOptions,
  570. IN const ProgramArguments &Args
  571. )
  572. {
  573. DWORD ErrorCode = ERROR_INVALID_PARAMETER;
  574. if (OsOptions) {
  575. POS_BOOT_ENTRY BootEntry;
  576. BOOLEAN Status = FALSE;
  577. if (Args.EntryId != -1) {
  578. BootEntry = OSBOFindBootEntry(OsOptions,
  579. Args.EntryId);
  580. } else {
  581. BootEntry = OSBOGetActiveBootEntry(OsOptions);
  582. }
  583. if (BootEntry) {
  584. Status = (OSBESetOsLoadOptions(BootEntry,
  585. Args.OsLoadOptions.c_str()) != NULL);
  586. if (Status) {
  587. Status = OSBOFlush(OsOptions);
  588. }
  589. }
  590. if (Status) {
  591. ErrorCode = ERROR_SUCCESS;
  592. } else {
  593. ErrorCode = ERROR_CAN_NOT_COMPLETE;
  594. }
  595. }
  596. return ErrorCode;
  597. }
  598. DWORD
  599. SetBootEntryActive(
  600. IN POS_BOOT_OPTIONS OsOptions,
  601. IN ProgramArguments &Args
  602. )
  603. {
  604. DWORD ErrorCode = ERROR_INVALID_PARAMETER;
  605. if (OsOptions && (Args.EntryId != -1)) {
  606. POS_BOOT_ENTRY BootEntry;
  607. BOOLEAN Status = FALSE;
  608. BootEntry = OSBOFindBootEntry(OsOptions,
  609. Args.EntryId);
  610. if (BootEntry) {
  611. Status = (OSBOSetActiveBootEntry(OsOptions,
  612. BootEntry) != NULL);
  613. if (Status) {
  614. Status = OSBOFlush(OsOptions);
  615. }
  616. }
  617. if (Status) {
  618. ErrorCode = ERROR_SUCCESS;
  619. } else {
  620. ErrorCode = ERROR_CAN_NOT_COMPLETE;
  621. }
  622. }
  623. return ErrorCode;
  624. }
  625. DWORD
  626. DelDriverEntry(
  627. IN POS_BOOT_OPTIONS OsOptions,
  628. IN ProgramArguments &Args
  629. )
  630. {
  631. DWORD ErrorCode = ERROR_INVALID_PARAMETER;
  632. if (OsOptions){
  633. BOOLEAN Status = FALSE;
  634. Status = OSBODeleteDriverEntry(OsOptions, Args.DrvId);
  635. if (Status){
  636. Status = OSBOFlush(OsOptions);
  637. }
  638. if (Status){
  639. ErrorCode = ERROR_SUCCESS;
  640. } else {
  641. ErrorCode = ERROR_CAN_NOT_COMPLETE;
  642. }
  643. }
  644. return ErrorCode;
  645. }
  646. DWORD
  647. DeleteBootEntry(
  648. IN POS_BOOT_OPTIONS OsOptions,
  649. IN ProgramArguments &Args
  650. )
  651. {
  652. DWORD ErrorCode = ERROR_INVALID_PARAMETER;
  653. if (OsOptions) {
  654. POS_BOOT_ENTRY BootEntry;
  655. BOOLEAN Status = FALSE;
  656. if (Args.EntryId != -1) {
  657. BootEntry = OSBOFindBootEntry(OsOptions,
  658. Args.EntryId);
  659. } else {
  660. BootEntry = OSBOGetActiveBootEntry(OsOptions);
  661. }
  662. if (BootEntry) {
  663. Status = OSBODeleteBootEntry(OsOptions, BootEntry);
  664. if (Status) {
  665. Status = OSBOFlush(OsOptions);
  666. }
  667. }
  668. if (Status) {
  669. ErrorCode = ERROR_SUCCESS;
  670. } else {
  671. ErrorCode = ERROR_CAN_NOT_COMPLETE;
  672. }
  673. }
  674. return ErrorCode;
  675. }
  676. DWORD
  677. SetTimeout(
  678. IN POS_BOOT_OPTIONS OsOptions,
  679. IN const ProgramArguments &Args
  680. )
  681. {
  682. DWORD ErrorCode = ERROR_INVALID_PARAMETER;
  683. if (OsOptions && Args.SetTimeout) {
  684. OSBOSetTimeOut(OsOptions, Args.Timeout);
  685. ErrorCode = OSBOFlush(OsOptions) ? ERROR_SUCCESS : ERROR_CAN_NOT_COMPLETE;
  686. }
  687. return ErrorCode;
  688. }
  689. //
  690. // main() entry point
  691. //
  692. int
  693. __cdecl
  694. wmain(
  695. int Argc,
  696. wchar_t *Argv[]
  697. )
  698. {
  699. int Result = 0;
  700. ThisModule = GetModuleHandle(NULL);
  701. try {
  702. DWORD ErrorCode = ERROR_INVALID_PARAMETER;
  703. ProgramArguments Args(Argc, Argv);
  704. POS_BOOT_OPTIONS BootOptions = NULL;
  705. //
  706. // Initialize the library
  707. //
  708. if (OSBOLibraryInit((SBEMemAllocateRoutine)malloc, (SBEMemFreeRoutine)free)) {
  709. BootOptions = EFIOSBOCreate();
  710. }
  711. if (!BootOptions) {
  712. std::cout << GetFormattedMessage( ThisModule,
  713. FALSE,
  714. Message,
  715. sizeof(Message)/sizeof(Message[0]),
  716. MSG_ERROR_READING_BOOT_ENTRIES) << std::endl;
  717. Result = 1;
  718. } else {
  719. if (Args.ListEntries) {
  720. ErrorCode = ListEntries(BootOptions);
  721. } else if (Args.AddNewEntry) {
  722. ErrorCode = AddNewEntry(BootOptions, Args);
  723. } else if (Args.DeleteBootEntry) {
  724. ErrorCode = DeleteBootEntry(BootOptions, Args);
  725. } else if (Args.SetOsLoadOptions) {
  726. ErrorCode = SetBootEntryOptions(BootOptions, Args);
  727. } else if (Args.SetActive) {
  728. ErrorCode = SetBootEntryActive(BootOptions, Args);
  729. } else if (Args.SetTimeout) {
  730. ErrorCode = SetTimeout(BootOptions, Args);
  731. } else if (Args.ListDrvEntries){
  732. ErrorCode = ListDriverEntry(BootOptions);
  733. } else if (Args.AddDrvEntry){
  734. ErrorCode = AddNewDriverEntry(BootOptions, Args);
  735. } else if (Args.DelDrvEntry){
  736. ErrorCode = DelDriverEntry(BootOptions, Args);
  737. }
  738. OSBODelete(BootOptions);
  739. }
  740. if (ErrorCode != ERROR_SUCCESS) {
  741. throw new W32Error(ErrorCode);
  742. }
  743. }
  744. catch(ProgramArguments *pArgs) {
  745. Result = 1;
  746. std::cout << GetFormattedMessage( ThisModule,
  747. FALSE,
  748. Message,
  749. sizeof(Message)/sizeof(Message[0]),
  750. MSG_PGM_USAGE) << std::endl;
  751. if (pArgs) {
  752. delete pArgs;
  753. }
  754. }
  755. catch(W32Error *W32Err) {
  756. if (W32Err) { // to make prefix happy :(
  757. W32Err->Dump(std::cout);
  758. std::cout << GetFormattedMessage( ThisModule,
  759. FALSE,
  760. Message,
  761. sizeof(Message)/sizeof(Message[0]),
  762. MSG_PGM_USAGE) << std::endl;
  763. delete W32Err;
  764. }
  765. Result = 1;
  766. }
  767. catch(ProgramException *PrgExp) {
  768. Result = 1;
  769. PrgExp->Dump(std::cout);
  770. delete PrgExp;
  771. } catch (exception *Exp) {
  772. Result = 1;
  773. std::cout << Exp->what() << std::endl;
  774. }
  775. return Result;
  776. }
  777. NTSTATUS
  778. QueryCanonicalName(
  779. IN PCWSTR Name,
  780. IN ULONG MaxDepth,
  781. OUT PWSTR CanonicalName,
  782. IN ULONG SizeOfBufferInBytes
  783. )
  784. /*++
  785. Routine Description:
  786. Resolves the symbolic name to the specified depth. To resolve
  787. a symbolic name completely specify the MaxDepth as -1
  788. Arguments:
  789. Name - Symbolic name to be resolved
  790. MaxDepth - The depth till which the resolution needs to
  791. be carried out
  792. CanonicalName - The fully resolved name
  793. SizeOfBufferInBytes - The size of the CanonicalName buffer in
  794. bytes
  795. Return Value:
  796. Appropriate NT status code
  797. --*/
  798. {
  799. UNICODE_STRING name, canonName;
  800. OBJECT_ATTRIBUTES oa;
  801. NTSTATUS status;
  802. HANDLE handle;
  803. ULONG CurrentDepth;
  804. RtlInitUnicodeString(&name, Name);
  805. canonName.MaximumLength = (USHORT) (SizeOfBufferInBytes - sizeof(WCHAR));
  806. canonName.Length = 0;
  807. canonName.Buffer = CanonicalName;
  808. if (name.Length >= canonName.MaximumLength) {
  809. return STATUS_BUFFER_TOO_SMALL;
  810. }
  811. RtlCopyMemory(canonName.Buffer, name.Buffer, name.Length);
  812. canonName.Length = name.Length;
  813. canonName.Buffer[canonName.Length/sizeof(WCHAR)] = 0;
  814. for (CurrentDepth = 0; CurrentDepth < MaxDepth; CurrentDepth++) {
  815. InitializeObjectAttributes(&oa, &canonName, OBJ_CASE_INSENSITIVE, 0, 0);
  816. status = NtOpenSymbolicLinkObject(&handle,
  817. READ_CONTROL | SYMBOLIC_LINK_QUERY,
  818. &oa);
  819. if (!NT_SUCCESS(status)) {
  820. break;
  821. }
  822. status = NtQuerySymbolicLinkObject(handle, &canonName, NULL);
  823. NtClose(handle);
  824. if (!NT_SUCCESS(status)) {
  825. return status;
  826. }
  827. canonName.Buffer[canonName.Length/sizeof(WCHAR)] = 0;
  828. }
  829. return STATUS_SUCCESS;
  830. }
  831. #define PRODUCT_NAME_KEY TEXT("productname")
  832. VOID
  833. GetFriendlyName(
  834. IN const std::wstring &InfFileName,
  835. OUT std::wstring &FriendlyName
  836. )
  837. {
  838. UINT ErrorLine = 0;
  839. BOOL Status = FALSE;
  840. HINF InfHandle = ::SetupOpenInfFile(InfFileName.c_str(),
  841. NULL,
  842. INF_STYLE_WIN4,
  843. &ErrorLine);
  844. if (InfHandle != INVALID_HANDLE_VALUE) {
  845. INFCONTEXT InfContext = {0};
  846. WCHAR Buffer[MAX_PATH] = {0};
  847. //
  848. // get the key
  849. //
  850. Status = SetupFindFirstLine(InfHandle,
  851. TEXT("Strings"),
  852. PRODUCT_NAME_KEY,
  853. &InfContext);
  854. if (Status) {
  855. //
  856. // If we found the key extract the description
  857. //
  858. Status = SetupGetStringField(&InfContext,
  859. 1,
  860. Buffer,
  861. ARRAY_SIZE(Buffer),
  862. NULL);
  863. if (Status) {
  864. FriendlyName = Buffer;
  865. }
  866. }
  867. SetupCloseInfFile(InfHandle);
  868. }
  869. //
  870. // If we didn't find the description use default description
  871. //
  872. if (!Status) {
  873. FriendlyName = DEFAULT_NAME;
  874. }
  875. }