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.

519 lines
11 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. arc.c
  5. Abstract:
  6. Routines relating to boot.ini.
  7. Author:
  8. Ted Miller (tedm) 4-Apr-1995
  9. Revision History:
  10. --*/
  11. #include "setupp.h"
  12. #pragma hdrstop
  13. PWSTR
  14. ArcDevicePathToNtPath(
  15. IN PCWSTR ArcPath
  16. )
  17. /*++
  18. Routine Description:
  19. Convert an ARC path (device only) to an NT path.
  20. Arguments:
  21. ArcPath - supplies path to be converted.
  22. Return Value:
  23. Converted path. Caller must free with MyFree().
  24. --*/
  25. {
  26. NTSTATUS Status;
  27. HANDLE ObjectHandle;
  28. OBJECT_ATTRIBUTES Obja;
  29. UNICODE_STRING UnicodeString;
  30. UCHAR Buffer[1024];
  31. PWSTR arcPath;
  32. PWSTR ntPath;
  33. //
  34. // Assume failure
  35. //
  36. ntPath = NULL;
  37. arcPath = MyMalloc(((lstrlen(ArcPath)+1)*sizeof(WCHAR)) + sizeof(L"\\ArcName"));
  38. if( !arcPath ) {
  39. return NULL;
  40. }
  41. lstrcpy(arcPath,L"\\ArcName\\");
  42. lstrcat(arcPath,ArcPath);
  43. RtlInitUnicodeString(&UnicodeString,arcPath);
  44. InitializeObjectAttributes(
  45. &Obja,
  46. &UnicodeString,
  47. OBJ_CASE_INSENSITIVE,
  48. NULL,
  49. NULL
  50. );
  51. Status = NtOpenSymbolicLinkObject(
  52. &ObjectHandle,
  53. READ_CONTROL | SYMBOLIC_LINK_QUERY,
  54. &Obja
  55. );
  56. if(NT_SUCCESS(Status)) {
  57. //
  58. // Query the object to get the link target.
  59. //
  60. UnicodeString.Buffer = (PWSTR)Buffer;
  61. UnicodeString.Length = 0;
  62. UnicodeString.MaximumLength = sizeof(Buffer);
  63. Status = NtQuerySymbolicLinkObject(ObjectHandle,&UnicodeString,NULL);
  64. if(NT_SUCCESS(Status)) {
  65. ntPath = MyMalloc(UnicodeString.Length+sizeof(WCHAR));
  66. if( ntPath ) {
  67. CopyMemory(ntPath,UnicodeString.Buffer,UnicodeString.Length);
  68. ntPath[UnicodeString.Length/sizeof(WCHAR)] = 0;
  69. }
  70. }
  71. NtClose(ObjectHandle);
  72. }
  73. MyFree(arcPath);
  74. return(ntPath);
  75. }
  76. PWSTR
  77. NtFullPathToDosPath(
  78. IN PCWSTR NtPath
  79. )
  80. {
  81. OBJECT_ATTRIBUTES Attributes;
  82. UNICODE_STRING UnicodeString;
  83. NTSTATUS Status;
  84. HANDLE DosDevicesDir;
  85. HANDLE DosDevicesObj;
  86. PWSTR dosPath;
  87. PWSTR currentDosPath;
  88. ULONG Context;
  89. ULONG Length;
  90. BOOLEAN RestartScan;
  91. CHAR Buffer[1024];
  92. WCHAR LinkSource[2*MAX_PATH];
  93. WCHAR LinkTarget[2*MAX_PATH];
  94. POBJECT_DIRECTORY_INFORMATION DirInfo;
  95. UINT PrefixLength;
  96. UINT NtPathLength;
  97. WCHAR canonNtPath[MAX_PATH];
  98. OBJECT_ATTRIBUTES Obja;
  99. HANDLE ObjectHandle;
  100. PWSTR ntPath;
  101. //
  102. // Canonicalize the NT path by following the symbolic link.
  103. //
  104. ntPath = (PWSTR) NtPath;
  105. dosPath = NULL;
  106. RtlInitUnicodeString(&UnicodeString,ntPath);
  107. InitializeObjectAttributes(
  108. &Obja,
  109. &UnicodeString,
  110. OBJ_CASE_INSENSITIVE,
  111. NULL,
  112. NULL
  113. );
  114. NtPathLength = UnicodeString.Length/sizeof(WCHAR);
  115. PrefixLength = UnicodeString.Length/sizeof(WCHAR);
  116. for (;;) {
  117. Status = NtOpenSymbolicLinkObject(
  118. &ObjectHandle,
  119. READ_CONTROL | SYMBOLIC_LINK_QUERY,
  120. &Obja
  121. );
  122. if (NT_SUCCESS(Status)) {
  123. UnicodeString.Buffer = canonNtPath;
  124. UnicodeString.Length = 0;
  125. UnicodeString.MaximumLength = sizeof(WCHAR)*MAX_PATH;
  126. RtlZeroMemory(canonNtPath, UnicodeString.MaximumLength);
  127. Status = NtQuerySymbolicLinkObject(ObjectHandle,&UnicodeString,NULL);
  128. if(NT_SUCCESS(Status)) {
  129. if (NtPathLength > PrefixLength) {
  130. RtlCopyMemory((PCHAR) canonNtPath + UnicodeString.Length,
  131. ntPath + PrefixLength,
  132. (NtPathLength - PrefixLength)*sizeof(WCHAR));
  133. }
  134. ntPath = canonNtPath;
  135. }
  136. NtClose(ObjectHandle);
  137. break;
  138. }
  139. RtlInitUnicodeString(&UnicodeString,ntPath);
  140. PrefixLength--;
  141. while (PrefixLength > 0) {
  142. if (ntPath[PrefixLength] == '\\') {
  143. break;
  144. }
  145. PrefixLength--;
  146. }
  147. if (!PrefixLength) {
  148. break;
  149. }
  150. UnicodeString.Length = (USHORT)(PrefixLength*sizeof(WCHAR));
  151. InitializeObjectAttributes(
  152. &Obja,
  153. &UnicodeString,
  154. OBJ_CASE_INSENSITIVE,
  155. NULL,
  156. NULL
  157. );
  158. }
  159. NtPathLength = lstrlen(ntPath);
  160. //
  161. // Open \DosDevices directory.
  162. //
  163. RtlInitUnicodeString(&UnicodeString,L"\\DosDevices");
  164. InitializeObjectAttributes(&Attributes,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
  165. Status = NtOpenDirectoryObject(&DosDevicesDir,DIRECTORY_QUERY,&Attributes);
  166. if(!NT_SUCCESS(Status)) {
  167. return(NULL);
  168. }
  169. //
  170. // Iterate each object in that directory.
  171. //
  172. Context = 0;
  173. RestartScan = TRUE;
  174. Status = NtQueryDirectoryObject(
  175. DosDevicesDir,
  176. Buffer,
  177. sizeof(Buffer),
  178. TRUE,
  179. RestartScan,
  180. &Context,
  181. &Length
  182. );
  183. RestartScan = FALSE;
  184. DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
  185. while(NT_SUCCESS(Status)) {
  186. DirInfo->Name.Buffer[DirInfo->Name.Length/sizeof(WCHAR)] = 0;
  187. DirInfo->TypeName.Buffer[DirInfo->TypeName.Length/sizeof(WCHAR)] = 0;
  188. //
  189. // Skip this entry if it's not a symbolic link.
  190. //
  191. if(DirInfo->Name.Length && !lstrcmpi(DirInfo->TypeName.Buffer,L"SymbolicLink")) {
  192. //
  193. // Get this \DosDevices object's link target.
  194. //
  195. UnicodeString.Buffer = LinkSource;
  196. UnicodeString.Length = sizeof(L"\\DosDevices\\") - sizeof(WCHAR);
  197. UnicodeString.MaximumLength = sizeof(LinkSource);
  198. lstrcpy(LinkSource,L"\\DosDevices\\");
  199. RtlAppendUnicodeStringToString(&UnicodeString,&DirInfo->Name);
  200. InitializeObjectAttributes(&Attributes,&UnicodeString,OBJ_CASE_INSENSITIVE,NULL,NULL);
  201. Status = NtOpenSymbolicLinkObject(
  202. &DosDevicesObj,
  203. READ_CONTROL|SYMBOLIC_LINK_QUERY,
  204. &Attributes
  205. );
  206. if(NT_SUCCESS(Status)) {
  207. UnicodeString.Buffer = LinkTarget;
  208. UnicodeString.Length = 0;
  209. UnicodeString.MaximumLength = sizeof(LinkTarget);
  210. Status = NtQuerySymbolicLinkObject(DosDevicesObj,&UnicodeString,NULL);
  211. CloseHandle(DosDevicesObj);
  212. if(NT_SUCCESS(Status)) {
  213. //
  214. // Make sure LinkTarget is nul-terminated.
  215. //
  216. PrefixLength = UnicodeString.Length/sizeof(WCHAR);
  217. UnicodeString.Buffer[PrefixLength] = 0;
  218. //
  219. // See if it's a prefix of the path we're converting,
  220. //
  221. if(!_wcsnicmp(ntPath,LinkTarget,PrefixLength)) {
  222. //
  223. // Got a match.
  224. //
  225. currentDosPath = dosPath;
  226. if(dosPath = MyMalloc(DirInfo->Name.Length + ((NtPathLength - PrefixLength + 1)*sizeof(WCHAR)))) {
  227. lstrcpy(dosPath,DirInfo->Name.Buffer);
  228. lstrcat(dosPath,ntPath + PrefixLength);
  229. }
  230. if (currentDosPath) {
  231. if (lstrlen(currentDosPath) < lstrlen(dosPath)) {
  232. MyFree(dosPath);
  233. dosPath = currentDosPath;
  234. } else {
  235. MyFree(currentDosPath);
  236. }
  237. }
  238. }
  239. }
  240. }
  241. }
  242. //
  243. // Go on to next object.
  244. //
  245. Status = NtQueryDirectoryObject(
  246. DosDevicesDir,
  247. Buffer,
  248. sizeof(Buffer),
  249. TRUE,
  250. RestartScan,
  251. &Context,
  252. &Length
  253. );
  254. }
  255. CloseHandle(DosDevicesDir);
  256. return dosPath;
  257. }
  258. BOOL
  259. SetNvRamVariable(
  260. IN PCWSTR VarName,
  261. IN PCWSTR VarValue
  262. )
  263. {
  264. UNICODE_STRING VarNameU,VarValueU;
  265. NTSTATUS Status;
  266. //
  267. // Set up unicode strings.
  268. //
  269. RtlInitUnicodeString(&VarNameU ,VarName );
  270. RtlInitUnicodeString(&VarValueU,VarValue);
  271. pSetupEnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE);
  272. Status = NtSetSystemEnvironmentValue(&VarNameU,&VarValueU);
  273. return(NT_SUCCESS(Status));
  274. }
  275. BOOL
  276. ChangeBootTimeoutNvram(
  277. IN UINT Timeout
  278. )
  279. /*++
  280. Routine Description:
  281. Changes the boot countdown value in nv-ram.
  282. The non-ARC version (which operates on boot.ini) is in i386\bootini.c.
  283. Arguments:
  284. Timeout - supplies new timeout value, in seconds.
  285. Return Value:
  286. None.
  287. --*/
  288. {
  289. WCHAR TimeoutValue[24];
  290. wsprintf(TimeoutValue,L"%u",Timeout);
  291. if(!SetNvRamVariable(L"COUNTDOWN",TimeoutValue)) {
  292. return(FALSE);
  293. }
  294. return(SetNvRamVariable(L"AUTOLOAD",L"YES"));
  295. }
  296. #if defined(EFI_NVRAM_ENABLED)
  297. BOOL
  298. ChangeBootTimeoutEfiNvram(
  299. IN UINT Timeout
  300. )
  301. /*++
  302. Routine Description:
  303. Changes the boot countdown value in EFI nv-ram.
  304. Arguments:
  305. Timeout - supplies new timeout value, in seconds.
  306. Return Value:
  307. None.
  308. --*/
  309. {
  310. NTSTATUS Status;
  311. BOOT_OPTIONS BootOptions;
  312. ASSERT(IsEfi());
  313. BootOptions.Version = BOOT_OPTIONS_VERSION;
  314. BootOptions.Length = sizeof(BootOptions);
  315. BootOptions.Timeout = Timeout;
  316. pSetupEnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE);
  317. Status = NtSetBootOptions(&BootOptions, BOOT_OPTIONS_FIELD_TIMEOUT);
  318. return(NT_SUCCESS(Status));
  319. }
  320. #endif // defined(EFI_NVRAM_ENABLED)
  321. #if defined(_X86_)
  322. BOOL
  323. IsArc(
  324. VOID
  325. )
  326. /*++
  327. Routine Description:
  328. Run time check to determine if this is an Arc system. We attempt to read an
  329. Arc variable using the Hal. This will fail for Bios based systems.
  330. Arguments:
  331. None
  332. Return Value:
  333. True = This is an Arc system.
  334. --*/
  335. {
  336. UNICODE_STRING UnicodeString;
  337. NTSTATUS Status;
  338. WCHAR Buffer[4096];
  339. if(!pSetupEnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE))
  340. return(FALSE); // need better error handling?
  341. //
  342. // Get the env var into the temp buffer.
  343. //
  344. RtlInitUnicodeString(&UnicodeString, L"OSLOADER");
  345. Status = NtQuerySystemEnvironmentValue(
  346. &UnicodeString,
  347. Buffer,
  348. sizeof(Buffer)/sizeof(WCHAR),
  349. NULL
  350. );
  351. return(NT_SUCCESS(Status) ? TRUE: FALSE);
  352. }
  353. #endif
  354. BOOL
  355. ChangeBootTimeout(
  356. IN UINT Timeout
  357. )
  358. /*++
  359. Routine Description:
  360. Changes the boot countdown value; decides whether
  361. to use ARC or non-ARC version.
  362. Arguments:
  363. Timeout - supplies new timeout value, in seconds.
  364. Return Value:
  365. None.
  366. --*/
  367. {
  368. #if defined(EFI_NVRAM_ENABLED)
  369. if (IsEfi()) {
  370. return ChangeBootTimeoutEfiNvram(Timeout);
  371. }
  372. #endif
  373. if (IsArc()) {
  374. return ChangeBootTimeoutNvram(Timeout);
  375. }
  376. #if defined(_X86_)
  377. return ChangeBootTimeoutBootIni(Timeout);
  378. #else
  379. return FALSE;
  380. #endif
  381. }