Source code of Windows XP (NT5)
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.

379 lines
9.7 KiB

  1. /*++
  2. Copyright (c) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. sbentry.c
  5. Abstract:
  6. Contains the OS boot entry and boot options
  7. abstraction implementation.
  8. Author:
  9. Vijay Jayaseelan (vijayj@microsoft.com) 14 Feb 2001
  10. Revision History:
  11. None.
  12. --*/
  13. #include <sbentry.h>
  14. #include <stdio.h>
  15. SBEMemAllocateRoutine AllocRoutine = NULL;
  16. SBEMemFreeRoutine FreeRoutine = NULL;
  17. //
  18. // OS_BOOT_ENTRY Methods
  19. //
  20. PCTSTR
  21. OSBEAddOsLoadOption(
  22. IN POS_BOOT_ENTRY This,
  23. IN PCTSTR BootOption
  24. )
  25. {
  26. PTSTR Option = NULL;
  27. TCHAR Buffer[MAX_PATH];
  28. if (This && BootOption) {
  29. ULONG Length;
  30. _tcscpy(Buffer, BootOption);
  31. _tcsupr(Buffer);
  32. Length = _tcslen(Buffer);
  33. if (Length) {
  34. //
  35. // Add a space at the end if required
  36. //
  37. if ((Length < ARRAY_SIZE(Buffer)) && (Buffer[Length - 1] != L' ')) {
  38. Buffer[Length] = L' ';
  39. Buffer[Length + 1] = UNICODE_NULL;
  40. Length++;
  41. }
  42. if ((!_tcsstr(This->OsLoadOptions, Buffer)) &&
  43. ((_tcslen(This->OsLoadOptions) + Length) < MAX_PATH)) {
  44. _tcscat(This->OsLoadOptions, Buffer);
  45. Option = This->OsLoadOptions;
  46. }
  47. OSBE_SET_DIRTY(This);
  48. OSBO_SET_DIRTY(This->BootOptions);
  49. }
  50. }
  51. return Option;
  52. }
  53. PCTSTR
  54. OSBERemoveOsLoadOption(
  55. IN POS_BOOT_ENTRY This,
  56. IN PCTSTR BootOption
  57. )
  58. {
  59. PTSTR Option = NULL;
  60. TCHAR Buffer[MAX_PATH];
  61. if (This && BootOption) {
  62. ULONG Length;
  63. _tcscpy(Buffer, BootOption);
  64. _tcsupr(Buffer);
  65. Length = _tcslen(Buffer);
  66. if (Length) {
  67. PTSTR OldOption;
  68. if ((Length < ARRAY_SIZE(Buffer)) && (Buffer[Length - 1] != L' ')) {
  69. Buffer[Length] = L' ';
  70. Buffer[Length + 1] = UNICODE_NULL;
  71. Length++;
  72. }
  73. OldOption = _tcsstr(This->OsLoadOptions, Buffer);
  74. if (OldOption) {
  75. PTSTR NextToken = _tcschr(OldOption + 1, L'/');
  76. if (NextToken) {
  77. _tcscpy(OldOption, NextToken);
  78. } else {
  79. *OldOption = UNICODE_NULL;
  80. }
  81. Option = This->OsLoadOptions;
  82. OSBE_SET_DIRTY(This);
  83. OSBO_SET_DIRTY(This->BootOptions);
  84. }
  85. }
  86. }
  87. return Option;
  88. }
  89. BOOLEAN
  90. OSBEIsOsLoadOptionPresent(
  91. IN POS_BOOT_ENTRY This,
  92. IN PCTSTR BootOption
  93. )
  94. {
  95. BOOLEAN Result = FALSE;
  96. TCHAR Buffer[MAX_PATH];
  97. if (This && BootOption) {
  98. ULONG Length;
  99. _tcscpy(Buffer, BootOption);
  100. _tcsupr(Buffer);
  101. Length = _tcslen(Buffer);
  102. if (Length) {
  103. if ((Length < ARRAY_SIZE(Buffer)) && (Buffer[Length - 1] != L' ')) {
  104. Buffer[Length] = L' ';
  105. Buffer[Length + 1] = UNICODE_NULL;
  106. Length++;
  107. }
  108. Result = _tcsstr(This->OsLoadOptions, Buffer) ? TRUE : FALSE;
  109. }
  110. }
  111. return Result;
  112. }
  113. //
  114. // OS_BOOT_OPTIONS Methods
  115. //
  116. POS_BOOT_ENTRY
  117. OSBOFindBootEntry(
  118. IN POS_BOOT_OPTIONS This,
  119. IN ULONG Id
  120. )
  121. {
  122. POS_BOOT_ENTRY Entry = NULL;
  123. if (This) {
  124. for (Entry = This->BootEntries; Entry; Entry = Entry->NextEntry) {
  125. if (Entry->Id == Id) {
  126. break; // found the required entry
  127. }
  128. }
  129. }
  130. return Entry;
  131. }
  132. ULONG
  133. OSBOFindBootEntryOrder(
  134. IN POS_BOOT_OPTIONS This,
  135. IN ULONG Id
  136. )
  137. {
  138. ULONG Index = -1;
  139. if (This) {
  140. ULONG EntryIndex;
  141. for (EntryIndex = 0;
  142. EntryIndex < OSBOGetOrderedBootEntryCount(This);
  143. EntryIndex++) {
  144. if (This->BootOrder[EntryIndex] == Id) {
  145. Index = EntryIndex;
  146. break; // found the required entry
  147. }
  148. }
  149. }
  150. return Index;
  151. }
  152. BOOLEAN
  153. OSBODeleteBootEntry(
  154. IN POS_BOOT_OPTIONS This,
  155. IN POS_BOOT_ENTRY BootEntry
  156. )
  157. {
  158. BOOLEAN Result = FALSE;
  159. if (This && BootEntry) {
  160. POS_BOOT_ENTRY CurrEntry = NULL;
  161. POS_BOOT_ENTRY PrevEntry = NULL;
  162. for (CurrEntry = This->BootEntries;
  163. CurrEntry != BootEntry;
  164. PrevEntry = CurrEntry, CurrEntry = CurrEntry->NextEntry) {
  165. // do nothing
  166. }
  167. if (CurrEntry) {
  168. ULONG Order;
  169. POS_BOOT_ENTRY OrderedEntry;
  170. //
  171. // Set the required attributes
  172. //
  173. OSBE_SET_DELETED(BootEntry);
  174. OSBE_SET_DIRTY(BootEntry);
  175. OSBO_SET_DIRTY(This);
  176. //
  177. // Flush the changes
  178. //
  179. Result = OSBEFlush(BootEntry);
  180. if (Result) {
  181. //
  182. // Remove references to the entries
  183. //
  184. if (PrevEntry) {
  185. PrevEntry->NextEntry = BootEntry->NextEntry;
  186. } else {
  187. This->BootEntries = BootEntry->NextEntry;
  188. }
  189. if (This->EntryCount) {
  190. This->EntryCount--;
  191. }
  192. //
  193. // if this entry was ordered then remove
  194. // reference from the order too
  195. //
  196. Order = OSBOFindBootEntryOrder(This, OSBEGetId(BootEntry));
  197. if (Order != (-1)) {
  198. ULONG OrderCount = OSBOGetOrderedBootEntryCount(This);
  199. OrderCount--;
  200. if (OrderCount) {
  201. PULONG NewOrder = SBE_MALLOC(OrderCount * sizeof(ULONG));
  202. if (NewOrder) {
  203. //
  204. // copy entries before the current entry
  205. //
  206. memcpy(NewOrder, This->BootOrder, Order * sizeof(ULONG));
  207. //
  208. // copy entries after the current entry
  209. //
  210. memcpy(NewOrder + Order, This->BootOrder + Order + 1,
  211. (OrderCount - Order) * sizeof(ULONG));
  212. SBE_FREE(This->BootOrder);
  213. This->BootOrder = NewOrder;
  214. This->BootOrderCount = OrderCount;
  215. Result = TRUE;
  216. } else {
  217. Result = FALSE;
  218. }
  219. } else {
  220. SBE_FREE(This->BootOrder);
  221. This->BootOrder = NULL;
  222. This->BootOrderCount = 0;
  223. }
  224. }
  225. if (BootEntry == OSBOGetActiveBootEntry(This)) {
  226. ULONG Index;
  227. //
  228. // Update the active boot entry and the next boot entry
  229. //
  230. This->CurrentEntry = NULL;
  231. Index = OSBOGetBootEntryIdByOrder(This, 0);
  232. if (Index != (-1)) {
  233. This->CurrentEntry = OSBOFindBootEntry(This, Index);
  234. }
  235. }
  236. //
  237. // Since we updated some state mark it dirty
  238. //
  239. OSBO_SET_DIRTY(This);
  240. OSBEDelete(BootEntry);
  241. }
  242. }
  243. }
  244. return Result;
  245. }
  246. POS_BOOT_ENTRY
  247. OSBOSetActiveBootEntry(
  248. IN POS_BOOT_OPTIONS This,
  249. IN POS_BOOT_ENTRY BootEntry
  250. )
  251. {
  252. POS_BOOT_ENTRY OldActiveEntry = NULL;
  253. if (This && BootEntry) {
  254. ULONG OrderCount = OSBOGetOrderedBootEntryCount(This);
  255. OldActiveEntry = OSBOGetActiveBootEntry(This);
  256. if ((OrderCount > 0) && (OldActiveEntry != BootEntry)) {
  257. ULONG Index;
  258. ULONG ActiveIndex = OSBOFindBootEntryOrder(This,
  259. OSBEGetId(BootEntry));
  260. //
  261. // If the entry is already present in the boot order
  262. // and move it to the start of the list
  263. //
  264. if (ActiveIndex != (-1)) {
  265. for (Index = ActiveIndex; Index; Index--) {
  266. This->BootOrder[Index] = This->BootOrder[Index - 1];
  267. }
  268. This->BootOrder[0] = BootEntry->Id;
  269. } else {
  270. //
  271. // This is a new entry in ordered list. Grow the ordered boot
  272. // entry list with this new entry at the start
  273. //
  274. PULONG NewBootOrder = (PULONG)SBE_MALLOC((OrderCount + 1) * sizeof(ULONG));
  275. memcpy(NewBootOrder + 1, This->BootOrder, sizeof(ULONG) * OrderCount);
  276. NewBootOrder[0] = BootEntry->Id;
  277. SBE_FREE(This->BootOrder);
  278. This->BootOrder = NewBootOrder;
  279. }
  280. //
  281. // Update the active boot entry and the next boot entry
  282. //
  283. This->CurrentEntry = NULL;
  284. Index = OSBOGetBootEntryIdByOrder(This, 0);
  285. if (Index != (-1)) {
  286. This->CurrentEntry = OSBOFindBootEntry(This, Index);
  287. }
  288. //
  289. // Since we updated some state mark it dirty
  290. //
  291. OSBO_SET_DIRTY(This);
  292. }
  293. }
  294. return OldActiveEntry;
  295. }