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.

2425 lines
63 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. osloader.c
  5. Abstract:
  6. This module contains the code that implements the OS chooser.
  7. Author:
  8. Adam Barr (adamba) 15-May-1997
  9. Revision History:
  10. --*/
  11. #ifdef i386
  12. #include "bldrx86.h"
  13. #endif
  14. #if defined(_IA64_)
  15. #include "bldria64.h"
  16. #endif
  17. #include "netboot.h" // for network functionality
  18. #include "netfs.h" // for network functionality
  19. #include "stdio.h"
  20. #include "msg.h"
  21. #include <pxe_cmn.h>
  22. #include <pxe_api.h>
  23. #include <tftp_api.h>
  24. #include "parse.h"
  25. #include "stdlib.h"
  26. #include "parseini.h"
  27. #include "haldtect.h"
  28. #ifdef EFI
  29. #define BINL_PORT 0x0FAB // 4011 (decimal) in little-endian
  30. #else
  31. #define BINL_PORT 0xAB0F // 4011 (decimal) in big-endian
  32. #endif
  33. #if defined(_WIN64) && defined(_M_IA64)
  34. #pragma section(".base", long, read, write)
  35. __declspec(allocate(".base"))
  36. extern
  37. PVOID __ImageBase;
  38. #else
  39. extern
  40. PVOID __ImageBase;
  41. #endif
  42. VOID
  43. BlpClearScreen(
  44. VOID
  45. );
  46. BOOLEAN
  47. BlDetectHal(
  48. VOID
  49. );
  50. VOID
  51. BlMainLoop(
  52. );
  53. UCHAR OsLoaderVersion[] = "OS Chooser V5.2\r\n";
  54. WCHAR OsLoaderVersionW[] = L"OS Chooser V5.2\r\n";
  55. UCHAR OsLoaderName[] = "oschoice.exe";
  56. const CHAR rghex[] = "0123456789ABCDEF";
  57. typedef BOOLEAN BOOL;
  58. BOOLEAN isOSCHOICE=TRUE;
  59. ULONG RemoteHost;
  60. USHORT RemotePort;
  61. USHORT LocalPort;
  62. CHAR DomainName[256];
  63. CHAR UserName[256];
  64. CHAR Password[128];
  65. CHAR AdministratorPassword[OSC_ADMIN_PASSWORD_LEN+1];
  66. CHAR AdministratorPasswordConfirm[OSC_ADMIN_PASSWORD_LEN+1];
  67. WCHAR UnicodePassword[128];
  68. CHAR LmOwfPassword[LM_OWF_PASSWORD_SIZE];
  69. CHAR NtOwfPassword[NT_OWF_PASSWORD_SIZE];
  70. BOOLEAN LoggedIn = FALSE; // have we successfully logged in
  71. UCHAR NextBootfile[128];
  72. UCHAR SifFile[128];
  73. BOOLEAN DoSoftReboot = FALSE;
  74. BOOLEAN BlUsePae;
  75. //
  76. // the following globals are for detecting the hal
  77. //
  78. UCHAR HalType[8+1+3+1];
  79. UCHAR HalDescription[128];
  80. PVOID InfFile;
  81. PVOID WinntSifHandle;
  82. PCHAR WinntSifFile;
  83. ULONG WinntSifFileLength;
  84. BOOLEAN DisableACPI = FALSE;
  85. #if 0 && DBG
  86. #define _TRACE_FUNC_
  87. #endif
  88. #ifdef _TRACE_FUNC_
  89. #define TraceFunc( _func) { \
  90. CHAR FileLine[80]; \
  91. sprintf( FileLine, "%s(%u)", __FILE__, __LINE__ ); \
  92. DPRINT( OSC, ( "%-55s: %s", FileLine, _func )); \
  93. }
  94. #else
  95. #define TraceFunc( _func )
  96. #endif
  97. //
  98. // This removes macro redefinitions which appear because we define __RPC_DOS__,
  99. // but rpc.h defines __RPC_WIN32__
  100. //
  101. #pragma warning(disable:4005)
  102. //
  103. // As of 12/17/98, SECURITY_DOS is *not* defined - adamba
  104. //
  105. #if defined(SECURITY_DOS)
  106. //
  107. // These appear because we defined SECURITY_DOS
  108. //
  109. #define __far
  110. #define __pascal
  111. #define __loadds
  112. #endif
  113. #include <security.h>
  114. #include <rpc.h>
  115. #include <spseal.h>
  116. #if defined(SECURITY_DOS)
  117. //
  118. // PSECURITY_STRING is not supposed to be used when SECURITY_DOS is
  119. // defined -- it should be a WCHAR*. Unfortunately ntlmsp.h breaks
  120. // this rule and even uses the SECURITY_STRING structure, which there
  121. // is really no equivalent for in 16-bit mode.
  122. //
  123. typedef SEC_WCHAR * SECURITY_STRING; // more-or-less the intention where it is used
  124. typedef SEC_WCHAR * PSECURITY_STRING;
  125. #endif
  126. #include <ntlmsp.h>
  127. //
  128. // Packet structure definitions.
  129. //
  130. #include "oscpkt.h"
  131. VOID
  132. BlpSetInverseMode(
  133. IN BOOLEAN InverseOn
  134. );
  135. VOID
  136. BlpSendEscape(
  137. PCHAR Escape
  138. );
  139. ULONG
  140. BlDoLogin(
  141. VOID
  142. );
  143. VOID
  144. BlDoLogoff(
  145. VOID
  146. );
  147. //
  148. // Define external static data.
  149. //
  150. BOOLEAN BlConsoleInitialized = FALSE;
  151. ULONG BlConsoleOutDeviceId = 0;
  152. ULONG BlConsoleInDeviceId = 0;
  153. ULONG BlDcacheFillSize = 32;
  154. extern BOOLEAN BlOutputDots;
  155. ULONGLONG NetRebootParameter = (ULONGLONG)0;
  156. UCHAR NetRebootFile[128];
  157. BOOLEAN BlRebootSystem = FALSE;
  158. ULONG BlVirtualBias = 0;
  159. CHAR KernelFileName[8+1+3+1]="ntoskrnl.exe";
  160. CHAR HalFileName[8+1+3+1]="hal.dll";
  161. //
  162. // Globals used during login. Mostly because it would be too many
  163. // parameters to pass to BlDoLogin().
  164. //
  165. #define OUTGOING_MESSAGE_LENGTH 1024
  166. #define INCOMING_MESSAGE_LENGTH 8192
  167. #define TEMP_INCOMING_MESSAGE_LENGTH 1500
  168. #define RECEIVE_TIMEOUT 5
  169. #define RECEIVE_RETRIES 24
  170. PCHAR OutgoingMessageBuffer = NULL;
  171. SIGNED_PACKET UNALIGNED * OutgoingSignedMessage;
  172. PCHAR IncomingMessageBuffer = NULL;
  173. SIGNED_PACKET UNALIGNED * IncomingSignedMessage;
  174. PCHAR TempIncomingMessage = NULL;
  175. CredHandle CredentialHandle;
  176. BOOLEAN CredentialHandleValid = FALSE;
  177. CtxtHandle ClientContextHandle;
  178. BOOLEAN ClientContextHandleValid = FALSE;
  179. PSecPkgInfoA PackageInfo = NULL;
  180. #if DBG
  181. VOID
  182. DumpBuffer(
  183. PVOID Buffer,
  184. ULONG BufferSize
  185. )
  186. /*++
  187. Routine Description:
  188. Dumps the buffer content on to the debugger output.
  189. Arguments:
  190. Buffer: buffer pointer.
  191. BufferSize: size of the buffer.
  192. Return Value:
  193. none
  194. --*/
  195. {
  196. #define NUM_CHARS 16
  197. ULONG i, limit;
  198. CHAR TextBuffer[NUM_CHARS + 1];
  199. PUCHAR BufferPtr = Buffer;
  200. KdPrint(("------------------------------------\n"));
  201. //
  202. // Hex dump of the bytes
  203. //
  204. limit = ((BufferSize - 1) / NUM_CHARS + 1) * NUM_CHARS;
  205. for (i = 0; i < limit; i++) {
  206. if (i < BufferSize) {
  207. KdPrint(("%02x ", (UCHAR)BufferPtr[i]));
  208. if (BufferPtr[i] < 31 ) {
  209. TextBuffer[i % NUM_CHARS] = '.';
  210. } else if (BufferPtr[i] == '\0') {
  211. TextBuffer[i % NUM_CHARS] = ' ';
  212. } else {
  213. TextBuffer[i % NUM_CHARS] = (CHAR) BufferPtr[i];
  214. }
  215. } else {
  216. KdPrint((" "));
  217. TextBuffer[i % NUM_CHARS] = ' ';
  218. }
  219. if ((i + 1) % NUM_CHARS == 0) {
  220. TextBuffer[NUM_CHARS] = 0;
  221. KdPrint((" %s\n", TextBuffer));
  222. }
  223. }
  224. KdPrint(("------------------------------------\n"));
  225. }
  226. VOID
  227. PrintTime(
  228. LPSTR Comment,
  229. TimeStamp ConvertTime
  230. )
  231. /*++
  232. Routine Description:
  233. Print the specified time
  234. Arguments:
  235. Comment - Comment to print in front of the time
  236. Time - Local time to print
  237. Return Value:
  238. None
  239. --*/
  240. {
  241. KdPrint(( "%s", Comment ));
  242. //
  243. // If the time is infinite,
  244. // just say so.
  245. //
  246. if ( ConvertTime.LowPart == 0x7FFFFFFF ) {
  247. KdPrint(( "Infinite\n" ));
  248. //
  249. // Otherwise print it more clearly
  250. //
  251. } else {
  252. KdPrint(("%lx %lx\n", ConvertTime.HighPart, ConvertTime.LowPart));
  253. }
  254. }
  255. #endif // DBG
  256. ARC_STATUS
  257. BlInitStdio (
  258. IN ULONG Argc,
  259. IN PCHAR Argv[]
  260. )
  261. {
  262. PCHAR ConsoleOutDevice;
  263. PCHAR ConsoleInDevice;
  264. ULONG Status;
  265. if (BlConsoleInitialized) {
  266. return ESUCCESS;
  267. }
  268. //
  269. // Allocate some memory for our UDP reads/writes. These *must*
  270. // be virtual addresses, so we need to allocate them rather than
  271. // just using static arrays because if we have lots of memory
  272. // (greater than >9Gig) on a machine and oschoice gets loaded high, we
  273. // may end up with a bogus address when we convert these addresses to
  274. // physical addresses just before we UdpWrite/UdpRead.
  275. //
  276. OutgoingMessageBuffer = BlAllocateHeap(OUTGOING_MESSAGE_LENGTH);
  277. IncomingMessageBuffer = BlAllocateHeap(INCOMING_MESSAGE_LENGTH);
  278. TempIncomingMessage = BlAllocateHeap(TEMP_INCOMING_MESSAGE_LENGTH);
  279. //
  280. // Get the name of the console output device and open the device for
  281. // write access.
  282. //
  283. ConsoleOutDevice = BlGetArgumentValue(Argc, Argv, "consoleout");
  284. if (ConsoleOutDevice == NULL) {
  285. return ENODEV;
  286. }
  287. Status = ArcOpen(ConsoleOutDevice, ArcOpenWriteOnly, &BlConsoleOutDeviceId);
  288. if (Status != ESUCCESS) {
  289. return Status;
  290. }
  291. //
  292. // Get the name of the console input device and open the device for
  293. // read access.
  294. //
  295. ConsoleInDevice = BlGetArgumentValue(Argc, Argv, "consolein");
  296. if (ConsoleInDevice == NULL) {
  297. return ENODEV;
  298. }
  299. Status = ArcOpen(ConsoleInDevice, ArcOpenReadOnly, &BlConsoleInDeviceId);
  300. if (Status != ESUCCESS) {
  301. return Status;
  302. }
  303. BlConsoleInitialized = TRUE;
  304. return ESUCCESS;
  305. }
  306. extern BOOLEAN NetBoot;
  307. NTSTATUS
  308. UdpSendAndReceive(
  309. IN PVOID SendBuffer,
  310. IN ULONG SendBufferLength,
  311. IN ULONG SendRemoteHost,
  312. IN USHORT SendRemotePort,
  313. IN ULONG SendRetryCount,
  314. IN PVOID ReceiveBuffer,
  315. IN ULONG ReceiveBufferLength,
  316. OUT PULONG ReceiveRemoteHost,
  317. OUT PUSHORT ReceiveRemotePort,
  318. IN ULONG ReceiveTimeout,
  319. IN ULONG ReceiveSignatureCount,
  320. IN PCHAR ReceiveSignatures[],
  321. IN ULONG ReceiveSequenceNumber
  322. )
  323. {
  324. ULONG i, j;
  325. ULONG length;
  326. SIGNED_PACKET UNALIGNED * ReceiveHeader =
  327. (SIGNED_PACKET UNALIGNED *)ReceiveBuffer;
  328. #ifdef _TRACE_FUNC_
  329. TraceFunc("UdpSendAndReceive( ");
  330. DPRINT( OSC, ("ReceiveSequenceNumber=%u )\n", ReceiveSequenceNumber) );
  331. #endif
  332. //
  333. // Try sending the packet SendRetryCount times, until we receive
  334. // a response with the right signature, waiting ReceiveTimeout
  335. // each time.
  336. //
  337. for (i = 0; i < SendRetryCount; i++) {
  338. length = UdpSend(
  339. SendBuffer,
  340. SendBufferLength,
  341. SendRemoteHost,
  342. SendRemotePort);
  343. if ( length != SendBufferLength ) {
  344. DPRINT( ERROR, ("UdpSend only sent %d bytes, not %d\n", length, SendBufferLength) );
  345. return STATUS_UNEXPECTED_NETWORK_ERROR;
  346. }
  347. ReReceive:
  348. //
  349. // NULL out the first 12 bytes in case we get shorter data.
  350. //
  351. memset(ReceiveBuffer, 0x0, 12);
  352. length = UdpReceive(
  353. ReceiveBuffer,
  354. ReceiveBufferLength,
  355. ReceiveRemoteHost,
  356. ReceiveRemotePort,
  357. ReceiveTimeout);
  358. if ( length == 0 ) {
  359. DPRINT( ERROR, ("UdpReceive timed out\n") );
  360. continue;
  361. }
  362. //
  363. // Make sure the signature is one of the ones we expect.
  364. //
  365. for (j = 0; j < ReceiveSignatureCount; j++) {
  366. if (memcmp(ReceiveBuffer, ReceiveSignatures[j], 4) == 0) {
  367. //
  368. // Now make sure that the sequence number is correct,
  369. // if asked to check (0 means don't check).
  370. //
  371. if ((ReceiveSequenceNumber == 0) ||
  372. (ReceiveSequenceNumber == ReceiveHeader->SequenceNumber)) {
  373. return STATUS_SUCCESS;
  374. } else {
  375. DPRINT( ERROR, ("UdpReceive expected seq %d, got %d\n",
  376. ReceiveSequenceNumber, ReceiveHeader->SequenceNumber) );
  377. }
  378. }
  379. }
  380. DPRINT( ERROR, ("UdpReceive got wrong signature\n") );
  381. //
  382. // Don't UdpSend again just because we got a bad signature. Still need
  383. // to respect the original ReceiveTimeout however!
  384. //
  385. goto ReReceive;
  386. }
  387. //
  388. // We timed out.
  389. //
  390. return STATUS_IO_TIMEOUT;
  391. }
  392. //
  393. // This routine signs and sends a message, waits for a response, and
  394. // then verifies the signature on the response.
  395. //
  396. // It returns a positive number on success, 0 on a timeout, -1 if
  397. // the server did not recognize the client, and -2 on other errors
  398. // (which should be fixable by having the client re-login and
  399. // re-transmit the request).
  400. //
  401. // NOTE: The data is sent as a UDP datagram. This requires a UDP header
  402. // which the SendBuffer is assumed to have room for. In addition, we
  403. // use 32 bytes for the "REQS", the total length, the sequence number,
  404. // the sign length, and the sign itself (which is 16 bytes).
  405. //
  406. // For similar reasons, ReceiveBuffer is assumed to have 32 bytes of
  407. // room at the beginning.
  408. //
  409. // Return values:
  410. //
  411. // 0 - nothing was received
  412. // -1 - a timeout occurred
  413. // -2 - unexpected network error, such as a sign/seal error
  414. // -3 - receive buffer overflow
  415. // positive number - the number of data bytes received
  416. //
  417. #define SIGN_HEADER_SIZE SIGNED_PACKET_DATA_OFFSET
  418. ULONG CorruptionCounter = 1;
  419. ULONG
  420. SignSendAndReceive(
  421. IN PVOID SendBuffer,
  422. IN ULONG SendBufferLength,
  423. IN ULONG SendRemoteHost,
  424. IN USHORT SendRemotePort,
  425. IN ULONG SendRetryCount,
  426. IN ULONG SendSequenceNumber,
  427. CtxtHandle ClientContextHandle,
  428. IN PVOID ReceiveBuffer,
  429. IN ULONG ReceiveBufferLength,
  430. OUT PULONG ReceiveRemoteHost,
  431. OUT PUSHORT ReceiveRemotePort,
  432. IN ULONG ReceiveTimeout
  433. )
  434. {
  435. SECURITY_STATUS SecStatus;
  436. ULONG Status;
  437. ULONG length;
  438. SecBufferDesc SignMessage;
  439. SecBuffer SigBuffers[2];
  440. SIGNED_PACKET UNALIGNED * SendHeader =
  441. (SIGNED_PACKET UNALIGNED *)((PCHAR)SendBuffer - SIGN_HEADER_SIZE);
  442. SIGNED_PACKET UNALIGNED * ReceiveHeader =
  443. (SIGNED_PACKET UNALIGNED *)((PCHAR)ReceiveBuffer - SIGN_HEADER_SIZE);
  444. PCHAR ResultSigs[3];
  445. USHORT FragmentNumber;
  446. USHORT FragmentTotal;
  447. FRAGMENT_PACKET UNALIGNED * TempFragment = (FRAGMENT_PACKET UNALIGNED *)TempIncomingMessage;
  448. ULONG ResendCount = 0;
  449. ULONG ReceivedDataBytes;
  450. TraceFunc("SignSendAndReceive( )\n");
  451. if ( LoggedIn )
  452. {
  453. SigBuffers[1].pvBuffer = SendHeader->Sign;
  454. SigBuffers[1].cbBuffer = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  455. SigBuffers[1].BufferType = SECBUFFER_TOKEN;
  456. SigBuffers[0].pvBuffer = SendBuffer;
  457. SigBuffers[0].cbBuffer = SendBufferLength;
  458. SigBuffers[0].BufferType = SECBUFFER_DATA;
  459. SignMessage.pBuffers = SigBuffers;
  460. SignMessage.cBuffers = 2;
  461. SignMessage.ulVersion = 0;
  462. //
  463. // Sign/seal a message
  464. //
  465. #ifndef ONLY_SIGN_MESSAGES
  466. SecStatus = SealMessage(
  467. &ClientContextHandle,
  468. 0,
  469. &SignMessage,
  470. 0 );
  471. if ( SecStatus != SEC_E_OK ) {
  472. DPRINT( OSC, ("SealMessage: %lx\n", SecStatus) );
  473. return (ULONG)-2;
  474. }
  475. #else
  476. SecStatus = MakeSignature(
  477. &ClientContextHandle,
  478. 0,
  479. &SignMessage,
  480. 0 );
  481. if ( SecStatus != SEC_E_OK ) {
  482. DPRINT( OSC, ("MakeSignature: %lx\n", SecStatus) );
  483. return (ULONG)-2;
  484. }
  485. #endif
  486. #if 0
  487. //
  488. // Corrupt every fifth message.
  489. //
  490. if ((CorruptionCounter % 5) == 0) {
  491. DPRINT( ERROR, ("INTENTIONALLY CORRUPTING A PACKET\n") );
  492. ((PCHAR)SendBuffer)[0] = '\0';
  493. }
  494. ++CorruptionCounter;
  495. #endif
  496. memcpy(SendHeader->Signature, RequestSignedSignature, 4);
  497. SendHeader->SignLength = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  498. ResultSigs[0] = ResponseSignedSignature;
  499. }
  500. else
  501. {
  502. memcpy(SendHeader->Signature, RequestUnsignedSignature, 4);
  503. SendHeader->SignLength = 0;
  504. ResultSigs[0] = ResponseUnsignedSignature;
  505. }
  506. ResultSigs[1] = ErrorSignedSignature;
  507. ResultSigs[2] = UnrecognizedClientSignature;
  508. //
  509. // Fill in our header before the SendBuffer. The sign has already been
  510. // written in because we set up SigBuffers to point to the right place.
  511. //
  512. SendHeader->Length = SendBufferLength + SIGNED_PACKET_EMPTY_LENGTH;
  513. SendHeader->SequenceNumber = SendSequenceNumber;
  514. SendHeader->FragmentNumber = 1;
  515. SendHeader->FragmentTotal = 1;
  516. //
  517. // Do an exchange with the server.
  518. //
  519. ReSend:
  520. Status = UdpSendAndReceive(
  521. SendHeader,
  522. SendBufferLength + SIGN_HEADER_SIZE,
  523. SendRemoteHost,
  524. SendRemotePort,
  525. SendRetryCount,
  526. ReceiveHeader,
  527. INCOMING_MESSAGE_LENGTH,
  528. ReceiveRemoteHost,
  529. ReceiveRemotePort,
  530. ReceiveTimeout,
  531. 3, // signature count
  532. ResultSigs, // signatures we look for
  533. SendSequenceNumber); // response should have the same one
  534. if (!NT_SUCCESS(Status)) {
  535. if (Status == STATUS_IO_TIMEOUT) {
  536. return (ULONG)-1;
  537. } else {
  538. return (ULONG)-2;
  539. }
  540. }
  541. //
  542. // Was it an error?
  543. //
  544. if (memcmp(ReceiveHeader->Signature, ErrorSignedSignature, 4) == 0) {
  545. DPRINT( ERROR, ("SignSendAndReceive: got ERR response\n") );
  546. return (ULONG)-2;
  547. }
  548. //
  549. // Was the client not recognized by the server?
  550. //
  551. if (memcmp(ReceiveHeader->Signature, UnrecognizedClientSignature, 4) == 0) {
  552. DPRINT( ERROR, ("SignSendAndReceive: got UNR response\n") );
  553. return (ULONG)-1;
  554. }
  555. if (ReceiveHeader->Length < (ULONG)SIGNED_PACKET_EMPTY_LENGTH) {
  556. DPRINT( ERROR, ("SignSendAndReceive: response is only %d bytes!\n", ReceiveHeader->Length) );
  557. ++ResendCount;
  558. if (ResendCount > SendRetryCount) {
  559. return (ULONG)-2;
  560. }
  561. goto ReSend;
  562. }
  563. //
  564. // If there are fragments, then try to receive the rest of them.
  565. //
  566. if (ReceiveHeader->FragmentTotal != 1) {
  567. //
  568. // Make sure this is fragment 1 -- otherwise the first one
  569. // was probably dropped and we should re-request it.
  570. //
  571. if (ReceiveHeader->FragmentNumber != 1) {
  572. DPRINT( ERROR, ("UdpReceive got non-first fragment\n") );
  573. ++ResendCount;
  574. if (ResendCount > SendRetryCount) {
  575. return (ULONG)-1;
  576. }
  577. goto ReSend; // redoes the whole exchange.
  578. }
  579. FragmentTotal = ReceiveHeader->FragmentTotal;
  580. ReceivedDataBytes = ReceiveHeader->Length - SIGNED_PACKET_EMPTY_LENGTH;
  581. for (FragmentNumber = 1; FragmentNumber < FragmentTotal; FragmentNumber ++) {
  582. ReReceive:
  583. //
  584. // NULL out the start of the receive buffer.
  585. //
  586. memset(TempFragment, 0x0, sizeof(FRAGMENT_PACKET));
  587. length = UdpReceive(
  588. TempFragment,
  589. TEMP_INCOMING_MESSAGE_LENGTH,
  590. ReceiveRemoteHost,
  591. ReceiveRemotePort,
  592. ReceiveTimeout);
  593. if ( length == 0 ) {
  594. DPRINT( ERROR, ("UdpReceive timed out\n") );
  595. ++ResendCount;
  596. if (ResendCount > SendRetryCount) {
  597. return (ULONG)-1;
  598. }
  599. goto ReSend; // redoes the whole exchange.
  600. }
  601. //
  602. // Make sure the signature is one of the ones we expect -- only
  603. // worry about the ResultSignature because we won't get an
  604. // error response on any fragment besides the first.
  605. //
  606. // Also make sure that the
  607. // sequence number is correct, if asked to check (0 means don't
  608. // check). If it's not, then go back and wait for another packet.
  609. //
  610. if ((TempFragment->Length < (ULONG)FRAGMENT_PACKET_EMPTY_LENGTH) ||
  611. (memcmp(TempFragment->Signature, ResultSigs[0], 4) != 0) ||
  612. ((SendSequenceNumber != 0) &&
  613. (SendSequenceNumber != TempFragment->SequenceNumber))) {
  614. DPRINT( ERROR, ("UdpReceive got wrong signature or sequence number\n") );
  615. goto ReReceive;
  616. }
  617. //
  618. // Check that the fragment number is also correct.
  619. //
  620. if (TempFragment->FragmentNumber != FragmentNumber+1) {
  621. DPRINT( ERROR, ("UdpReceive got wrong fragment number\n") );
  622. goto ReReceive;
  623. }
  624. //
  625. // Make sure that this fragment won't overflow the buffer.
  626. //
  627. if (ReceivedDataBytes + (TempFragment->Length - FRAGMENT_PACKET_EMPTY_LENGTH) >
  628. ReceiveBufferLength) {
  629. return (ULONG)-3;
  630. }
  631. //
  632. // This is the correct fragment, so copy it over and loop
  633. // to the next fragment.
  634. //
  635. memcpy(
  636. &ReceiveHeader->Data[ReceivedDataBytes],
  637. TempFragment->Data,
  638. TempFragment->Length - FRAGMENT_PACKET_EMPTY_LENGTH);
  639. ReceivedDataBytes += TempFragment->Length - FRAGMENT_PACKET_EMPTY_LENGTH;
  640. }
  641. //
  642. // When we are done getting everything, modify the length in the
  643. // incoming packet to match the total length (currently it will
  644. // just have the length of the first fragment.
  645. //
  646. ReceiveHeader->Length = ReceivedDataBytes + SIGNED_PACKET_EMPTY_LENGTH;
  647. DPRINT( OSC, ("Got packet with %d fragments, total length %d\n",
  648. FragmentTotal, ReceiveHeader->Length) );
  649. }
  650. //
  651. // Make sure the sign is the length we expect!!
  652. //
  653. if (LoggedIn == TRUE &&
  654. ReceiveHeader->SignLength != NTLMSSP_MESSAGE_SIGNATURE_SIZE)
  655. {
  656. DPRINT( ERROR, ("SignSendAndReceive: signature length is %d bytes!\n", ReceiveHeader->SignLength) );
  657. ++ResendCount;
  658. if (ResendCount > SendRetryCount) {
  659. return (ULONG)-2;
  660. }
  661. goto ReSend;
  662. }
  663. else if ( LoggedIn == FALSE &&
  664. ReceiveHeader->SignLength != 0 )
  665. {
  666. DPRINT( ERROR, ("SignSendAndReceive: signature length is not 0 bytes (=%u)!\n", ReceiveHeader->SignLength) );
  667. ++ResendCount;
  668. if (ResendCount > SendRetryCount) {
  669. return (ULONG)-2;
  670. }
  671. goto ReSend;
  672. }
  673. if ( LoggedIn )
  674. {
  675. SigBuffers[1].pvBuffer = ReceiveHeader->Sign;
  676. SigBuffers[1].cbBuffer = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  677. SigBuffers[1].BufferType = SECBUFFER_TOKEN;
  678. SigBuffers[0].pvBuffer = ReceiveBuffer;
  679. SigBuffers[0].cbBuffer = ReceiveHeader->Length - SIGNED_PACKET_EMPTY_LENGTH;
  680. SigBuffers[0].BufferType = SECBUFFER_DATA;
  681. SignMessage.pBuffers = SigBuffers;
  682. SignMessage.cBuffers = 2;
  683. SignMessage.ulVersion = 0;
  684. #ifndef ONLY_SIGN_MESSAGES
  685. SecStatus = UnsealMessage(
  686. &ClientContextHandle,
  687. &SignMessage,
  688. 0,
  689. 0 );
  690. if ( SecStatus != SEC_E_OK ) {
  691. DPRINT( ERROR, ("UnsealMessage: %lx\n", SecStatus) );
  692. return (ULONG)-2;
  693. }
  694. #else
  695. SecStatus = VerifySignature(
  696. &ClientContextHandle,
  697. &SignMessage,
  698. 0,
  699. 0 );
  700. if ( SecStatus != SEC_E_OK ) {
  701. DPRINT( ERROR, ("VerifySignature: %lx\n", SecStatus) );
  702. return (ULONG)-2;
  703. }
  704. #endif
  705. }
  706. //
  707. // Sucess, so return.
  708. //
  709. return (ReceiveHeader->Length - SIGNED_PACKET_EMPTY_LENGTH);
  710. }
  711. //
  712. // Retrieve next screen
  713. //
  714. BOOL
  715. BlRetrieveScreen(
  716. ULONG *SequenceNumber,
  717. PCHAR OutMessage,
  718. PCHAR InMessage
  719. )
  720. {
  721. ARC_STATUS Status;
  722. ULONG OutMessageLength = strlen( OutMessage );
  723. ULONG InMessageLength;
  724. PCREATE_DATA CreateData;
  725. TraceFunc("BlRetrieveScreen( )\n");
  726. // make sure we don't over flow the output buffer
  727. if ( OutMessageLength > 1023 ) {
  728. OutMessageLength = 1023;
  729. OutMessage[OutMessageLength] = '\0';
  730. }
  731. ++(*SequenceNumber);
  732. if ( *SequenceNumber > 0x2000 )
  733. {
  734. *SequenceNumber = 1;
  735. }
  736. if (!LoggedIn)
  737. {
  738. #ifdef _TRACE_FUNC_
  739. TraceFunc( "Sending RQU ");
  740. DPRINT( OSC, ("(%u)...\n", *SequenceNumber) );
  741. #endif
  742. memcpy( OutgoingSignedMessage->Data, OutMessage, OutMessageLength );
  743. Status = SignSendAndReceive(
  744. OutgoingSignedMessage->Data,
  745. OutMessageLength,
  746. NetServerIpAddress,
  747. BINL_PORT,
  748. RECEIVE_RETRIES,
  749. *SequenceNumber,
  750. ClientContextHandle,
  751. IncomingSignedMessage->Data,
  752. INCOMING_MESSAGE_LENGTH - SIGN_HEADER_SIZE,
  753. &RemoteHost,
  754. &RemotePort,
  755. RECEIVE_TIMEOUT);
  756. }
  757. else
  758. {
  759. #ifdef _TRACE_FUNC_
  760. TraceFunc( "Sending Seal/Signed REQS " );
  761. DPRINT( OSC, ("(%u)...\n", *SequenceNumber) );
  762. #endif
  763. while (TRUE)
  764. {
  765. memcpy( OutgoingSignedMessage->Data, OutMessage, OutMessageLength );
  766. Status = SignSendAndReceive(
  767. OutgoingSignedMessage->Data,
  768. OutMessageLength,
  769. NetServerIpAddress,
  770. BINL_PORT,
  771. RECEIVE_RETRIES,
  772. *SequenceNumber,
  773. ClientContextHandle,
  774. IncomingSignedMessage->Data,
  775. INCOMING_MESSAGE_LENGTH - SIGN_HEADER_SIZE,
  776. &RemoteHost,
  777. &RemotePort,
  778. RECEIVE_TIMEOUT);
  779. if ((Status == 0) || (Status == (ULONG)-2))
  780. {
  781. DPRINT( OSC, ("Attempting to re-login\n") );
  782. //
  783. // We assume that the server has dropped the current login
  784. // and don't bother calling BlDoLogoff();
  785. //
  786. LoggedIn = FALSE;
  787. Status = BlDoLogin( );
  788. *SequenceNumber = 1;
  789. if (Status == STATUS_SUCCESS)
  790. {
  791. DPRINT( ERROR, ("Successfully re-logged in\n") );
  792. memcpy(OutgoingSignedMessage->Data, OutMessage, OutMessageLength);
  793. LoggedIn = TRUE;
  794. continue;
  795. }
  796. else
  797. {
  798. DPRINT( ERROR, ("ERROR - could not re-login, %x\n", Status) );
  799. //DbgBreakPoint();
  800. //
  801. // Call ourselves again, but request the LoginErr screen which
  802. // is 00004e28.
  803. //
  804. strcpy( OutMessage, "00004e28\n" );
  805. return BlRetrieveScreen( SequenceNumber, OutMessage, InMessage );
  806. }
  807. }
  808. else if (Status == (ULONG)-1)
  809. {
  810. DPRINT( ERROR, ("Unrecognized, requested TIMEOUT screen\n") );
  811. //
  812. // We assume that the server has dropped the current login
  813. //
  814. LoggedIn = FALSE;
  815. //
  816. // Increase the sequence number for the new screen request,
  817. // don't worry about wrapping since the session will die soon.
  818. //
  819. ++(*SequenceNumber);
  820. //
  821. // Call ourselves again, but request the TIMEOUT screen.
  822. //
  823. strcpy( OutMessage, "00004E2A\n" );
  824. return BlRetrieveScreen( SequenceNumber, OutMessage, InMessage );
  825. }
  826. else if (Status == (ULONG)-3)
  827. {
  828. DPRINT( ERROR, ("Unrecognized, requested TOO LONG screen\n") );
  829. //
  830. // This screen is a fatal error, so don't worry about
  831. // staying logged in.
  832. //
  833. LoggedIn = FALSE;
  834. //
  835. // Increase the sequence number for the new screen request,
  836. // don't worry about wrapping since the session will die soon.
  837. //
  838. ++(*SequenceNumber);
  839. //
  840. // Call ourselves again, but request the TIMEOUT screen.
  841. //
  842. strcpy( OutMessage, "00004E53\n" );
  843. return BlRetrieveScreen( SequenceNumber, OutMessage, InMessage );
  844. }
  845. else
  846. {
  847. break;
  848. }
  849. }
  850. }
  851. //
  852. // NULL-terminate it.
  853. //
  854. IncomingSignedMessage->Data[IncomingSignedMessage->Length - SIGNED_PACKET_EMPTY_LENGTH] = '\0';
  855. strcpy( InMessage, IncomingSignedMessage->Data );
  856. InMessageLength = strlen(InMessage);
  857. // DumpBuffer( InMessage, strlen(InMessage) );
  858. //
  859. // If we got an just an ACCT response, with no screen data, that means a
  860. // restart is happening.
  861. //
  862. if (memcmp(InMessage, "ACCT", 4) == 0)
  863. {
  864. CreateData = (PCREATE_DATA) IncomingSignedMessage->Data;
  865. DPRINT( OSC, ("Trying to reboot to <%s>\n", CreateData->NextBootfile) );
  866. strcpy(NextBootfile, CreateData->NextBootfile);
  867. strcpy(SifFile, CreateData->SifFile);
  868. DoSoftReboot = TRUE;
  869. return FALSE; // exit message loop
  870. }
  871. //
  872. // If we got a screen with an ACCT response after the screen data,
  873. // should write the secret and do a soft reboot. In this situation
  874. // InMessageLength will only include the screen data itself, but
  875. // IncomingSignedMessage->Length will include the whole thing.
  876. //
  877. if ((IncomingSignedMessage->Length - SIGNED_PACKET_EMPTY_LENGTH) ==
  878. (InMessageLength + 1 + sizeof(CREATE_DATA))) {
  879. CreateData = (PCREATE_DATA) (InMessage + InMessageLength + 1);
  880. if (memcmp(CreateData->Id, "ACCT", 4) == 0) {
  881. DPRINT( OSC, ("INSTALL packet setting up reboot to <%s>\n", CreateData->NextBootfile) );
  882. strcpy(NextBootfile, CreateData->NextBootfile);
  883. strcpy(SifFile, CreateData->SifFile);
  884. DoSoftReboot = TRUE;
  885. //
  886. // Don't return FALSE, because we still want to show the INSTALL
  887. // screen. NextBootFile/SifFile/DoSoftReboot won't be modified by
  888. // that so we will do a proper soft reboot when the time comes.
  889. //
  890. }
  891. }
  892. // Special-case server tells us to LAUNCH a file
  893. if (memcmp(InMessage, "LAUNCH", 6) == 0) {
  894. CreateData = (PCREATE_DATA) (IncomingSignedMessage->Data + 7);
  895. DPRINT( OSC, ("Trying to launch <%s>\n", CreateData->NextBootfile) );
  896. strcpy(NextBootfile, CreateData->NextBootfile);
  897. strcpy(SifFile, CreateData->SifFile);
  898. if (CreateData->RebootParameter == OSC_REBOOT_COMMAND_CONSOLE_ONLY) {
  899. NetRebootParameter = NET_REBOOT_COMMAND_CONSOLE_ONLY;
  900. } else if (CreateData->RebootParameter == OSC_REBOOT_ASR) {
  901. NetRebootParameter = NET_REBOOT_ASR;
  902. }
  903. DoSoftReboot = TRUE;
  904. return FALSE; // exit message loop
  905. }
  906. // Special-case REBOOT - server told us to reboot.
  907. if (memcmp(InMessage, "REBOOT", 6) == 0)
  908. {
  909. return FALSE; // exit message loop
  910. }
  911. return TRUE; // stay in message loop
  912. }
  913. ARC_STATUS
  914. BlOsLoader (
  915. IN ULONG Argc,
  916. IN PCHAR Argv[],
  917. IN PCHAR Envp[]
  918. )
  919. /*++
  920. Routine Description:
  921. This is the main routine that controls the loading of the NT operating
  922. system on an ARC compliant system. It opens the system partition,
  923. the boot partition, the console input device, and the console output
  924. device. The NT operating system and all its DLLs are loaded and bound
  925. together. Control is then transfered to the loaded system.
  926. Arguments:
  927. Argc - Supplies the number of arguments that were provided on the
  928. command that invoked this program.
  929. Argv - Supplies a pointer to a vector of pointers to null terminated
  930. argument strings.
  931. Envp - Supplies a pointer to a vector of pointers to null terminated
  932. environment variables.
  933. Return Value:
  934. EBADF is returned if the specified OS image cannot be loaded.
  935. --*/
  936. {
  937. CHAR OutputBuffer[256];
  938. ULONG Count;
  939. ARC_STATUS Status;
  940. SECURITY_STATUS SecStatus; // NOTE: This is a SHORT, so not an NTSTATUS failure on error
  941. ULONG PackageCount;
  942. PVOID LoaderBase;
  943. #ifdef EFI
  944. //
  945. // set the efi watchdog timer to 20 minutes. the boot manager sets it to 5, but
  946. // the loader could take longer than this, especially if installing over the
  947. // network
  948. //
  949. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  950. #endif
  951. //
  952. // Initialize the OS loader console input and output.
  953. //
  954. Status = BlInitStdio(Argc, Argv);
  955. if (Status != ESUCCESS) {
  956. return Status;
  957. }
  958. //
  959. // Initialize the boot debugger for platforms that directly load the
  960. // OS Loader.
  961. //
  962. // N.B. This must occur after the console input and output have been
  963. // initialized so debug messages can be printed on the console
  964. // output device.
  965. //
  966. #if defined(_ALPHA_) || defined(ARCI386) || defined(_IA64_)
  967. //
  968. // If the program memory descriptor was found, then compute the base
  969. // address of the OS Loader for use by the debugger.
  970. //
  971. LoaderBase = &__ImageBase;
  972. BlPrint(TEXT("about to init debugger...\r\n"));
  973. //
  974. // Initialize traps and the boot debugger.
  975. //
  976. #if defined(ENABLE_LOADER_DEBUG)
  977. #if defined(_ALPHA_)
  978. BdInitializeTraps();
  979. #endif
  980. BdInitDebugger("oschoice.exe", LoaderBase, ENABLE_LOADER_DEBUG);
  981. #else
  982. BdInitDebugger("oschoice.exe", LoaderBase, NULL);
  983. #endif
  984. #endif
  985. BlPrint(TEXT("back from initializing debugger...\r\n"));
  986. #if DBG
  987. // NetDebugFlag |= 0x147;
  988. #endif
  989. TraceFunc("BlOsLoader( )\n");
  990. //
  991. // Announce OS Loader.
  992. //
  993. BlpClearScreen();
  994. #if 1
  995. #ifdef UNICODE
  996. BlPrint(OsLoaderVersionW);
  997. #else
  998. BlPrint(OsLoaderVersion);
  999. #endif
  1000. #else
  1001. strcpy(&OutputBuffer[0], OsLoaderVersion);
  1002. ArcWrite(BlConsoleOutDeviceId,
  1003. &OutputBuffer[0],
  1004. strlen(&OutputBuffer[0]),
  1005. &Count);
  1006. #endif
  1007. //
  1008. // Initialize the network.
  1009. //
  1010. NetGetRebootParameters(&NetRebootParameter, NetRebootFile, NULL, NULL, NULL, NULL, NULL, TRUE);
  1011. DPRINT( OSC, ("Initializing the network\n") );
  1012. Status = NetInitialize();
  1013. if (Status != ESUCCESS) {
  1014. return Status;
  1015. }
  1016. #ifndef EFI
  1017. //
  1018. // Get ourselves a UDP port.
  1019. //
  1020. LocalPort = UdpAssignUnicastPort();
  1021. DPRINT( OSC, ("Using port %x\n", LocalPort) );
  1022. #endif
  1023. //
  1024. // Initialize the security package.
  1025. //
  1026. DPRINT( OSC, ("Initializing security package\n") );
  1027. SecStatus = EnumerateSecurityPackagesA( &PackageCount, &PackageInfo );
  1028. if (SecStatus == SEC_E_OK) {
  1029. DPRINT( OSC, ("NTLMSSP: PackageCount: %ld\n", PackageCount) );
  1030. DPRINT( OSC, ("Name: %s Comment: %s\n", PackageInfo->Name, PackageInfo->Comment) );
  1031. DPRINT( OSC, ("Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
  1032. PackageInfo->fCapabilities,
  1033. PackageInfo->wVersion,
  1034. PackageInfo->wRPCID,
  1035. PackageInfo->cbMaxToken) );
  1036. } else {
  1037. DPRINT( ERROR, ("NTLMSSP: Enumerate failed, %d\n", SecStatus) );
  1038. }
  1039. //
  1040. // Get info about the security packages.
  1041. //
  1042. SecStatus = QuerySecurityPackageInfoA( NTLMSP_NAME_A, &PackageInfo );
  1043. if ( SecStatus != SEC_E_OK ) {
  1044. DPRINT( ERROR, ("QuerySecurityPackageInfo failed %d", SecStatus) );
  1045. return SecStatus;
  1046. }
  1047. //
  1048. // Detect the Hal type
  1049. //
  1050. if (!BlDetectHal()) {
  1051. //
  1052. // just fall through if it fails, it's not the end of the world
  1053. //
  1054. HalType[0] = '\0';
  1055. HalDescription[0] = '\0';
  1056. DPRINT( ERROR, ("BlDetectHal failed.\n") );
  1057. }
  1058. //
  1059. // Process screens, loggons, etc... we come back after a "REBOOT"
  1060. // was indicated.
  1061. //
  1062. BlMainLoop( );
  1063. //
  1064. // Inform boot debugger that the boot phase is complete.
  1065. //
  1066. // N.B. This is x86 only for now.
  1067. //
  1068. #if defined(_X86_)
  1069. DbgUnLoadImageSymbols(NULL, (PVOID)-1, 0);
  1070. #endif
  1071. #ifdef EFI
  1072. BlEfiSetAttribute( DEFATT );
  1073. #else
  1074. BlpSendEscape(";0;37;40m");
  1075. #endif
  1076. BlpSetInverseMode( FALSE );
  1077. BlpClearScreen();
  1078. BlPrint(TEXT("Waiting for reboot...\r\n"));
  1079. #ifndef EFI
  1080. HW_CURSOR(1,0);
  1081. #endif
  1082. if (DoSoftReboot) {
  1083. Status = NetSoftReboot(
  1084. NextBootfile,
  1085. NetRebootParameter,
  1086. NULL, // reboot file
  1087. SifFile,
  1088. UserName,
  1089. DomainName,
  1090. Password,
  1091. AdministratorPassword); // this only returns on an error
  1092. } else {
  1093. DPRINT( OSC, ("calling ArcRestart()\n") );
  1094. ArcRestart();
  1095. }
  1096. BlPrint(TEXT("Reboot failed... Press ALT+CTL+DEL to reboot.\n"));
  1097. //LoadFailed:
  1098. return Status;
  1099. }
  1100. //
  1101. //
  1102. //
  1103. ARC_STATUS
  1104. BlProcessLogin(
  1105. PCHAR OutgoingMessage )
  1106. {
  1107. //
  1108. // If this is the login screen, remember some of the inputs
  1109. // ourselves.
  1110. //
  1111. ARC_STATUS Status;
  1112. UNICODE_STRING TmpNtPassword;
  1113. PCHAR AtSign;
  1114. int i;
  1115. TraceFunc("BlProcessLogin( )\n");
  1116. //
  1117. // We could be trying to log another person in so log off the
  1118. // current user.
  1119. //
  1120. if ( LoggedIn == TRUE )
  1121. {
  1122. BlDoLogoff();
  1123. LoggedIn = FALSE;
  1124. }
  1125. DPRINT( OSC, ("Login info: Domain <%s>, User <%s>, Password<%s>\n", DomainName, UserName, "*") );
  1126. //
  1127. // Do a quick conversion of the password to Unicode.
  1128. //
  1129. TmpNtPassword.Length = strlen(Password) * sizeof(WCHAR);
  1130. TmpNtPassword.MaximumLength = sizeof(UnicodePassword);
  1131. TmpNtPassword.Buffer = UnicodePassword;
  1132. for (i = 0; i < sizeof(Password); i++) {
  1133. UnicodePassword[i] = (WCHAR)(Password[i]);
  1134. }
  1135. BlOwfPassword(Password, &TmpNtPassword, LmOwfPassword, NtOwfPassword);
  1136. Status = BlDoLogin( );
  1137. DPRINT( OSC, ("Login returned: %x\n", Status) );
  1138. return Status;
  1139. }
  1140. //
  1141. //
  1142. //
  1143. VOID
  1144. BlMainLoop(
  1145. )
  1146. {
  1147. ULONG SequenceNumber;
  1148. int len;
  1149. PUCHAR psz;
  1150. PUCHAR pch;
  1151. UCHAR OutgoingMessage[1024];
  1152. PUCHAR IncomingMessage;
  1153. TraceFunc("BlMainLoop( )\n");
  1154. //
  1155. // These all point into our single outgoing and incoming buffers.
  1156. //
  1157. OutgoingSignedMessage = (SIGNED_PACKET UNALIGNED *)OutgoingMessageBuffer;
  1158. IncomingSignedMessage = (SIGNED_PACKET UNALIGNED *)IncomingMessageBuffer;
  1159. DomainName[0] = '\0';
  1160. UserName[0] = '\0';
  1161. Password[0] = '\0';
  1162. SequenceNumber = 0;
  1163. //
  1164. // Ask the server for the initial screen
  1165. //
  1166. strcpy( OutgoingMessage, "\n" ); // first screen name is <blank>.
  1167. IncomingMessage = IncomingSignedMessage->Data;
  1168. SpecialAction = ACTION_NOP;
  1169. while ( SpecialAction != ACTION_REBOOT )
  1170. {
  1171. CHAR LastKey;
  1172. //
  1173. // Retrieve next screen
  1174. //
  1175. #if 0
  1176. IF_DEBUG(OSC) {
  1177. DPRINT( OSC, ("Dumping OutgoingingMessage buffer:\r\n" ) );
  1178. DumpBuffer( (PVOID)OutgoingMessage, 256 );
  1179. }
  1180. #endif
  1181. if (!BlRetrieveScreen( &SequenceNumber, OutgoingMessage, IncomingMessage ) )
  1182. break;
  1183. //
  1184. // Process the screen and get user input
  1185. //
  1186. LastKey = BlProcessScreen( IncomingMessage, OutgoingMessage );
  1187. DPRINT( OSC, ("LastKey = 0x%02x\nAction = %u\nResults:\n%s<EOM>\n",
  1188. LastKey, SpecialAction, OutgoingMessage) );
  1189. switch ( SpecialAction )
  1190. {
  1191. case ACTION_LOGIN:
  1192. DPRINT( OSC, ("[SpecialAction] Logging in\n") );
  1193. if ( STATUS_SUCCESS == BlProcessLogin( OutgoingMessage ) )
  1194. {
  1195. DPRINT( OSC, ("Validate Results are still the same:\n%s<EOM>\n",
  1196. OutgoingMessage) );
  1197. LoggedIn = TRUE;
  1198. SequenceNumber = 0;
  1199. //
  1200. // If the welcome screen was processed, then add some extra
  1201. // outgoing predetermined variables.
  1202. //
  1203. // Add NIC address
  1204. //
  1205. // Convert NIC address 0x00a0c968041c to a string
  1206. //
  1207. //
  1208. // Make sure the outgoing has a \n after the screen name
  1209. //
  1210. if ( OutgoingMessage[ strlen(OutgoingMessage) - 1 ] != '\n' )
  1211. {
  1212. strcat( OutgoingMessage, "\n" );
  1213. }
  1214. strcat( OutgoingMessage, "MAC=" );
  1215. len = 6;
  1216. psz = &OutgoingMessage[ strlen( OutgoingMessage ) ];
  1217. pch = (PCHAR) NetLocalHardwareAddress;
  1218. while (len--) {
  1219. UCHAR c = *(pch++);
  1220. *(psz++) = rghex [(c >> 4) & 0x0F] ;
  1221. *(psz++) = rghex [c & 0x0F];
  1222. }
  1223. *psz = '\0'; // terminate
  1224. //
  1225. // Add the Guid
  1226. //
  1227. pch = NULL;
  1228. len = 0;
  1229. GetGuid(&pch, &len);
  1230. if ((len != 0) && (pch!=NULL)) {
  1231. strcat( OutgoingMessage, "\nGUID=" );
  1232. psz = &OutgoingMessage[ strlen( OutgoingMessage ) ];
  1233. while (len--) {
  1234. UCHAR c = *(pch++);
  1235. *(psz++) = rghex [(c >> 4) & 0x0F] ;
  1236. *(psz++) = rghex [c & 0x0F];
  1237. }
  1238. *psz = '\0'; // terminate
  1239. }
  1240. //
  1241. // if we detected the HAL, specify it here
  1242. //
  1243. if (HalType[0] != '\0') {
  1244. strcat( OutgoingMessage, "\nHALTYPE=" );
  1245. strcat( OutgoingMessage, HalType );
  1246. if (HalDescription[0] != '\0') {
  1247. strcat( OutgoingMessage, "\nHALTYPEDESCRIPTION=" );
  1248. strcat( OutgoingMessage, HalDescription );
  1249. }
  1250. }
  1251. //
  1252. // Add the machine type
  1253. //
  1254. #if defined(_ALPHA_)
  1255. strcat( OutgoingMessage, "\nMACHINETYPE=Alpha\n" ); // add machinetype
  1256. #else
  1257. #if defined(_IA64_)
  1258. strcat( OutgoingMessage, "\nMACHINETYPE=ia64\n" ); // add machinetype
  1259. #else // INTEL
  1260. strcat( OutgoingMessage, "\nMACHINETYPE=i386\n" ); // add machinetype
  1261. #endif // _IA64_
  1262. #endif
  1263. //
  1264. // Tell BINL to verify the domain, because otherwise
  1265. // the SSPI package on the server will allow the login
  1266. // to succeed with an invalid domain. BINL will delete
  1267. // this variable from the client state on the server
  1268. // once it does the domain check.
  1269. //
  1270. strcat( OutgoingMessage, "CHECKDOMAIN=1\n" );
  1271. }
  1272. else
  1273. {
  1274. //
  1275. // Goto the Login Error Screen which is
  1276. // 00004e28.
  1277. //
  1278. strcpy( OutgoingMessage, "00004e28\n" );
  1279. LoggedIn = FALSE;
  1280. }
  1281. break;
  1282. }
  1283. }
  1284. //
  1285. // If we logged on successfully, then log off.
  1286. //
  1287. if (LoggedIn)
  1288. {
  1289. BlDoLogoff();
  1290. }
  1291. }
  1292. //
  1293. //
  1294. //
  1295. ULONG
  1296. BlDoLogin ( )
  1297. {
  1298. ARC_STATUS Status;
  1299. SECURITY_STATUS SecStatus;
  1300. SecBufferDesc NegotiateDesc;
  1301. SecBuffer NegotiateBuffer;
  1302. SecBufferDesc ChallengeDesc;
  1303. SecBuffer ChallengeBuffer;
  1304. SecBufferDesc AuthenticateDesc;
  1305. SecBuffer AuthenticateBuffer;
  1306. ULONG ContextAttributes;
  1307. SEC_WINNT_AUTH_IDENTITY_A AuthIdentity;
  1308. TimeStamp Lifetime;
  1309. PCHAR ResultSigs[2];
  1310. UCHAR OwfPasswords[LM_OWF_PASSWORD_SIZE + NT_OWF_PASSWORD_SIZE];
  1311. PLOGIN_PACKET OutgoingLoginMessage;
  1312. PLOGIN_PACKET IncomingLoginMessage;
  1313. OutgoingLoginMessage = (LOGIN_PACKET *) OutgoingMessageBuffer;
  1314. IncomingLoginMessage = (LOGIN_PACKET *) IncomingMessageBuffer;
  1315. TraceFunc("BlDoLogin( )\n");
  1316. //
  1317. // Delete both contexts if needed.
  1318. //
  1319. if (ClientContextHandleValid) {
  1320. SecStatus = DeleteSecurityContext( &ClientContextHandle );
  1321. ClientContextHandleValid = FALSE;
  1322. }
  1323. if (CredentialHandleValid) {
  1324. SecStatus = FreeCredentialsHandle( &CredentialHandle );
  1325. CredentialHandleValid = FALSE;
  1326. }
  1327. //
  1328. // Acquire a credential handle for the client side. The password
  1329. // we supply is the LM OWF password and the NT OWF password
  1330. // concatenated together.
  1331. //
  1332. memcpy( OwfPasswords, LmOwfPassword, LM_OWF_PASSWORD_SIZE );
  1333. memcpy( OwfPasswords+LM_OWF_PASSWORD_SIZE, NtOwfPassword, NT_OWF_PASSWORD_SIZE );
  1334. RtlZeroMemory( &AuthIdentity, sizeof(AuthIdentity) );
  1335. AuthIdentity.Domain = DomainName;
  1336. AuthIdentity.User = UserName;
  1337. AuthIdentity.Password = OwfPasswords;
  1338. #if 0
  1339. IF_DEBUG(OSC) {
  1340. DPRINT( OSC, ("Dumping OwfPasswords:\r\n") );
  1341. DumpBuffer( AuthIdentity.Password, LM_OWF_PASSWORD_SIZE+NT_OWF_PASSWORD_SIZE );
  1342. }
  1343. #endif
  1344. DPRINT( OSC, ("About to AcquireCredentialsHandle\n") );
  1345. SecStatus = AcquireCredentialsHandleA(
  1346. NULL, // New principal
  1347. NTLMSP_NAME_A, // Package Name
  1348. SECPKG_CRED_OUTBOUND | SECPKG_CRED_OWF_PASSWORD,
  1349. NULL,
  1350. &AuthIdentity,
  1351. NULL,
  1352. NULL,
  1353. &CredentialHandle,
  1354. &Lifetime );
  1355. if ( SecStatus != SEC_E_OK ) {
  1356. DPRINT( ERROR, ("AcquireCredentialsHandle failed: %s ", SecStatus) );
  1357. return SecStatus;
  1358. }
  1359. DPRINT( OSC, ("CredentialHandle: 0x%lx 0x%lx ",
  1360. CredentialHandle.dwLower, CredentialHandle.dwUpper) );
  1361. CredentialHandleValid = TRUE;
  1362. //
  1363. // Get the NegotiateMessage (ClientSide)
  1364. //
  1365. NegotiateDesc.ulVersion = 0;
  1366. NegotiateDesc.cBuffers = 1;
  1367. NegotiateDesc.pBuffers = &NegotiateBuffer;
  1368. NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1369. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  1370. NegotiateBuffer.pvBuffer = OutgoingLoginMessage->Data;
  1371. SecStatus = InitializeSecurityContextA(
  1372. &CredentialHandle,
  1373. NULL, // No Client context yet
  1374. NULL, // No target name needed
  1375. ISC_REQ_SEQUENCE_DETECT,
  1376. 0, // Reserved 1
  1377. SECURITY_NATIVE_DREP,
  1378. NULL, // No initial input token
  1379. 0, // Reserved 2
  1380. &ClientContextHandle,
  1381. &NegotiateDesc,
  1382. &ContextAttributes,
  1383. &Lifetime );
  1384. if ( (SecStatus != SEC_E_OK) && (SecStatus != SEC_I_CONTINUE_NEEDED) ) {
  1385. DPRINT( ERROR, ("InitializeSecurityContext (negotiate): %d" , SecStatus) );
  1386. return SecStatus;
  1387. }
  1388. ClientContextHandleValid = TRUE;
  1389. #if 0
  1390. IF_DEBUG(OSC) {
  1391. KdPrint(( "\n\nNegotiate Message:\n" ));
  1392. KdPrint(( "ClientContextHandle: 0x%lx 0x%lx Attributes: 0x%lx ",
  1393. ClientContextHandle.dwLower, ClientContextHandle.dwUpper,
  1394. ContextAttributes ));
  1395. PrintTime( "Lifetime: ", Lifetime );
  1396. DumpBuffer( NegotiateBuffer.pvBuffer, NegotiateBuffer.cbBuffer );
  1397. }
  1398. #endif
  1399. //
  1400. // Send the negotiate buffer to the server and wait for a response.
  1401. //
  1402. memcpy(OutgoingLoginMessage->Signature, NegotiateSignature, 4);
  1403. OutgoingLoginMessage->Length = NegotiateBuffer.cbBuffer;
  1404. TraceFunc("");
  1405. DPRINT( OSC, ("Sending NEG...\n") );
  1406. ResultSigs[0] = ChallengeSignature;
  1407. ResultSigs[1] = NegativeAckSignature;
  1408. #if 0
  1409. IF_DEBUG(OSC) {
  1410. KdPrint(( "\n\nNegotiate Message Outgoing Packet:\n" ));
  1411. DumpBuffer( OutgoingLoginMessage, NegotiateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET );
  1412. }
  1413. #endif
  1414. Status = UdpSendAndReceive(
  1415. OutgoingLoginMessage,
  1416. NegotiateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET,
  1417. NetServerIpAddress,
  1418. BINL_PORT,
  1419. 5, // retry count
  1420. IncomingLoginMessage,
  1421. INCOMING_MESSAGE_LENGTH,
  1422. &RemoteHost,
  1423. &RemotePort,
  1424. 2, // receive timeout
  1425. 2, // number of signatures
  1426. ResultSigs, // signature we are looking for
  1427. 0); // sequence number (0 means don't check)
  1428. if ( !NT_SUCCESS(Status) ) {
  1429. DPRINT( ERROR, ("UdpSendAndReceive status is %x\n", Status) );
  1430. return Status;
  1431. }
  1432. //
  1433. // If the response was a NAK, then fail immediately.
  1434. //
  1435. if (memcmp(IncomingLoginMessage->Signature, NegativeAckSignature, 4) == 0) {
  1436. DPRINT( ERROR, ("Received NAK from server\n") );
  1437. return STATUS_LOGON_FAILURE;
  1438. }
  1439. #if 0
  1440. IF_DEBUG(OSC) {
  1441. KdPrint(( "\n\nNegotiate Message Incoming Packet: %d %d %d %d\n",
  1442. IncomingLoginMessage->Data,
  1443. IncomingLoginMessage->Length,
  1444. IncomingLoginMessage->Signature,
  1445. IncomingLoginMessage->Status ));
  1446. DumpBuffer( IncomingLoginMessage->Data, IncomingLoginMessage->Length );
  1447. }
  1448. #endif
  1449. //
  1450. // Get the AuthenticateMessage (ClientSide)
  1451. //
  1452. AuthenticateDesc.ulVersion = 0;
  1453. AuthenticateDesc.cBuffers = 1;
  1454. AuthenticateDesc.pBuffers = &AuthenticateBuffer;
  1455. AuthenticateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1456. AuthenticateBuffer.BufferType = SECBUFFER_TOKEN;
  1457. AuthenticateBuffer.pvBuffer = OutgoingLoginMessage->Data;
  1458. ChallengeDesc.ulVersion = 0;
  1459. ChallengeDesc.cBuffers = 1;
  1460. ChallengeDesc.pBuffers = &ChallengeBuffer;
  1461. ChallengeBuffer.cbBuffer = IncomingLoginMessage->Length;
  1462. ChallengeBuffer.BufferType = SECBUFFER_TOKEN | SECBUFFER_READONLY;
  1463. ChallengeBuffer.pvBuffer = IncomingLoginMessage->Data;
  1464. DPRINT( OSC, ("About to call InitializeSecurityContext\n") );
  1465. SecStatus = InitializeSecurityContextA(
  1466. NULL,
  1467. &ClientContextHandle,
  1468. NULL, // No target name needed
  1469. 0,
  1470. 0, // Reserved 1
  1471. SECURITY_NATIVE_DREP,
  1472. &ChallengeDesc,
  1473. 0, // Reserved 2
  1474. &ClientContextHandle,
  1475. &AuthenticateDesc,
  1476. &ContextAttributes,
  1477. &Lifetime );
  1478. if ( (SecStatus != SEC_E_OK) ) {
  1479. DPRINT( OSC, ("InitializeSecurityContext (Authenticate): %d\n", SecStatus) );
  1480. return SecStatus;
  1481. }
  1482. //
  1483. // Send the authenticate buffer to the server and wait for the response.
  1484. //
  1485. memcpy(OutgoingLoginMessage->Signature, AuthenticateSignature, 4);
  1486. OutgoingLoginMessage->Length = AuthenticateBuffer.cbBuffer;
  1487. TraceFunc("");
  1488. DPRINT( OSC, ("Sending AUTH...\n") );
  1489. #if 0
  1490. IF_DEBUG(OSC) {
  1491. KdPrint(( "\n\nAuth Message Outgoing Packet:\n" ));
  1492. DumpBuffer( OutgoingLoginMessage, AuthenticateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET );
  1493. }
  1494. #endif
  1495. ResultSigs[0] = ResultSignature;
  1496. Status = UdpSendAndReceive(
  1497. OutgoingLoginMessage,
  1498. AuthenticateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET,
  1499. NetServerIpAddress,
  1500. BINL_PORT,
  1501. 10, // retry count
  1502. IncomingLoginMessage,
  1503. INCOMING_MESSAGE_LENGTH,
  1504. &RemoteHost,
  1505. &RemotePort,
  1506. 5, // receive timeout
  1507. 1, // number of signatures we are looking for
  1508. ResultSigs, // signatures we look for
  1509. 0); // sequence number (0 means don't check)
  1510. if ( !NT_SUCCESS(Status) ) {
  1511. DPRINT( ERROR, ("UdpSendAndReceive status is %x\n", Status) );
  1512. return Status;
  1513. }
  1514. #if 0
  1515. IF_DEBUG(OSC) {
  1516. KdPrint(( "\n\nAuthenticateBuffer Message Incoming Packet: %d %d %d %d\n",
  1517. IncomingLoginMessage->Data,
  1518. IncomingLoginMessage->Length,
  1519. IncomingLoginMessage->Signature,
  1520. IncomingLoginMessage->Status ));
  1521. DumpBuffer( IncomingLoginMessage->Data, IncomingLoginMessage->Length );
  1522. }
  1523. #endif
  1524. if (memcmp(IncomingLoginMessage->Signature, ResultSignature, 4) == 0) {
  1525. //
  1526. // Login has completed/failed, check status.
  1527. //
  1528. if ( IncomingLoginMessage->Status == STATUS_SUCCESS) {
  1529. TraceFunc("Login successful\n");
  1530. } else {
  1531. DPRINT( ERROR, ("ERROR - could not login, %x\n", IncomingLoginMessage->Status) );
  1532. }
  1533. return IncomingLoginMessage->Status;
  1534. } else {
  1535. //
  1536. // Shouldn't get this because we check signatures!!
  1537. //
  1538. DPRINT( ERROR, ("Got wrong message, expecting success or failure\n") );
  1539. return STATUS_UNEXPECTED_NETWORK_ERROR;
  1540. }
  1541. }
  1542. FILETIME GlobalFileTime = { 0 };
  1543. TIME_FIELDS ArcTimeForUTCTime = { 0 };
  1544. NTSTATUS
  1545. SetFileTimeFromTimeString(
  1546. IN PSTR TimeString,
  1547. OUT PFILETIME FileTime,
  1548. OUT TIME_FIELDS *ArcTime
  1549. )
  1550. {
  1551. TIME_FIELDS *pArcTime;
  1552. NTSTATUS Status = STATUS_SUCCESS;
  1553. PSTR p,q;
  1554. if (!TimeString) {
  1555. Status = STATUS_INVALID_PARAMETER;
  1556. goto exit;
  1557. }
  1558. q = p = TimeString;
  1559. //
  1560. // go until we either run out of space or hit a semi-colon. The
  1561. // semi-colon delimits the two fields of the filetime string.
  1562. //
  1563. while(*q != '\0' && *q != ';') {
  1564. q++;
  1565. }
  1566. //
  1567. // make sure we didn't have a bad input
  1568. //
  1569. if (*q == '\0') {
  1570. Status = STATUS_INVALID_PARAMETER;
  1571. goto exit;
  1572. }
  1573. *q = '\0';
  1574. q += 1;
  1575. //
  1576. // convert from string into binary format.
  1577. //
  1578. FileTime->dwHighDateTime = atoi(p);
  1579. FileTime->dwLowDateTime = atoi(q);
  1580. //
  1581. // now save off the arc time that we did the conversion so that
  1582. // we can calculate a delta later on.
  1583. //
  1584. pArcTime = ArcGetTime();
  1585. RtlCopyMemory(ArcTime,pArcTime,sizeof(TIME_FIELDS));
  1586. exit:
  1587. return(Status);
  1588. }
  1589. #if 0
  1590. NTSTATUS
  1591. GetFileTimeFromTimeFields(
  1592. IN PTIME_FIELDS TimeFields,
  1593. OUT FILETIME *Time
  1594. )
  1595. {
  1596. if (!TimeFields) {
  1597. return(STATUS_UNSUCCESSFUL);
  1598. }
  1599. return(RtlTimeFieldsToTime(TimeFields,(LARGE_INTEGER *)Time) == TRUE
  1600. ? STATUS_SUCCESS
  1601. : STATUS_UNSUCCESSFUL );
  1602. }
  1603. #endif
  1604. NTSTATUS
  1605. BlGetSystemTimeAsFileTime(
  1606. FILETIME *pSystemTimeAsFileTime
  1607. )
  1608. /*++
  1609. Routine Description:
  1610. Return the current UTC system time in file time format.
  1611. This routine requires that a network agent has let us know what the
  1612. UTC time of the system currently is. If not, we will try to use the
  1613. less accurate system bios time.
  1614. Arguments:
  1615. pSystemTimeAsFileTime - receives the current time.
  1616. Return Value:
  1617. NTSTATUS code indicating outcome.
  1618. --*/
  1619. {
  1620. NTSTATUS Status;
  1621. LARGE_INTEGER OriginalTime,CurrentTime,Delta,LIFileTime;
  1622. #if 0
  1623. //
  1624. // check if we've gotten the system time from the network. if not, then
  1625. // we will try to use the time from the bios.
  1626. //
  1627. if (GlobalFileTime.dwLowDateTime == 0 && GlobalFileTime.dwHighDateTime == 0) {
  1628. Status = GetFileTimeFromTimeFields(ArcGetTime(),pSystemTimeAsFileTime);
  1629. return(Status);
  1630. }
  1631. //
  1632. // Get the delta time from when we got the original time.
  1633. //
  1634. if (RtlTimeFieldsToTime(&ArcTimeForUTCTime,&OriginalTime) &&
  1635. RtlTimeFieldsToTime(ArcGetTime(), &CurrentTime)) {
  1636. Delta.QuadPart = CurrentTime.QuadPart - OriginalTime.QuadPart;
  1637. //
  1638. // Add that delta into the current time.
  1639. // do this math in large integer format cause it handles
  1640. // overflow from one DWORD to the next.
  1641. //
  1642. RtlCopyMemory(&LIFileTime,&GlobalFileTime,sizeof(FILETIME));
  1643. LIFileTime.QuadPart += Delta.QuadPart;
  1644. RtlCopyMemory(&GlobalFileTime,&LIFileTime,sizeof(FILETIME));
  1645. }
  1646. #endif
  1647. RtlCopyMemory(pSystemTimeAsFileTime,&GlobalFileTime,sizeof(FILETIME));
  1648. return(STATUS_SUCCESS);
  1649. }
  1650. VOID
  1651. BlDoLogoff (
  1652. VOID
  1653. )
  1654. {
  1655. ARC_STATUS Status;
  1656. TraceFunc("BlDoLogoff( )\n");
  1657. //
  1658. // Send a logoff message to the server -- for the moment this is
  1659. // just sent once and not acked, since if it is lost the server
  1660. // will eventually timeout.
  1661. //
  1662. memcpy(OutgoingSignedMessage->Signature, LogoffSignature, 4);
  1663. OutgoingSignedMessage->Length = 0;
  1664. Status = UdpSend(
  1665. OutgoingSignedMessage,
  1666. SIGNED_PACKET_DATA_OFFSET,
  1667. NetServerIpAddress,
  1668. BINL_PORT);
  1669. if ( !NT_SUCCESS(Status) ) {
  1670. DPRINT( ERROR, ("UdpSend status is %x\n", Status) );
  1671. }
  1672. }
  1673. VOID
  1674. BlOutputLoadMessage (
  1675. IN PCHAR DeviceName,
  1676. IN PCHAR FileName,
  1677. IN PTCHAR FileDescription OPTIONAL
  1678. )
  1679. /*++
  1680. Routine Description:
  1681. This routine outputs a loading message to the console output device.
  1682. Arguments:
  1683. DeviceName - Supplies a pointer to a zero terminated device name.
  1684. FileName - Supplies a pointer to a zero terminated file name.
  1685. FileDescription - Friendly name of the file in question.
  1686. Return Value:
  1687. None.
  1688. --*/
  1689. {
  1690. ULONG Count;
  1691. CHAR OutputBuffer[256];
  1692. PTCHAR pOutputBuffer;
  1693. #ifdef UNICODE
  1694. WCHAR OutputBufferW[256];
  1695. UNICODE_STRING uString;
  1696. ANSI_STRING aString;
  1697. pOutputBuffer = OutputBufferW;
  1698. #else
  1699. pOutputBuffer = OutputBuffer;
  1700. #endif
  1701. UNREFERENCED_PARAMETER( FileDescription );
  1702. //
  1703. // Construct and output loading file message.
  1704. //
  1705. if (!BlOutputDots) {
  1706. strcpy(&OutputBuffer[0], " ");
  1707. strcat(&OutputBuffer[0], DeviceName);
  1708. strcat(&OutputBuffer[0], FileName);
  1709. strcat(&OutputBuffer[0], "\r\n");
  1710. } else {
  1711. strcpy(&OutputBuffer[0],".");
  1712. }
  1713. #if 0
  1714. BlLog((LOG_LOGFILE,OutputBuffer));
  1715. #endif
  1716. #ifdef UNICODE
  1717. RtlInitAnsiString( &aString, OutputBuffer);
  1718. uString.MaximumLength = sizeof(OutputBufferW);
  1719. uString.Buffer = OutputBufferW;
  1720. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  1721. #endif
  1722. ArcWrite(BlConsoleOutDeviceId,
  1723. pOutputBuffer,
  1724. _tcslen(pOutputBuffer),
  1725. &Count);
  1726. return;
  1727. }
  1728. #ifndef EFI
  1729. BOOLEAN
  1730. BlDetectHal(
  1731. VOID
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. This function tries to determine the Hal type for this system.
  1736. It fills in the global "HalType" with the type.
  1737. Arguments:
  1738. None.
  1739. Return Value:
  1740. TRUE if the function successfully detects the hal type.
  1741. --*/
  1742. {
  1743. BOOLEAN Status = FALSE;
  1744. PSTR MachineName,HalName;
  1745. CHAR FileName[128];
  1746. ARC_STATUS AStatus;
  1747. ULONG DontCare;
  1748. //
  1749. // detecting the hal requires that you open up a copy of winnt.sif
  1750. //
  1751. strncpy(FileName, NetBootPath, sizeof(FileName));
  1752. FileName[sizeof(FileName)-1] = '\0';
  1753. strncat(FileName, "winnt.sif", sizeof(FileName) - strlen(FileName) );
  1754. FileName[sizeof(FileName)-1] = '\0';
  1755. AStatus = SlInitIniFile( NULL,
  1756. NET_DEVICE_ID,
  1757. FileName,
  1758. &InfFile,
  1759. &WinntSifFile,
  1760. &WinntSifFileLength,
  1761. &DontCare );
  1762. //
  1763. // if it opens successfully, then search for the HAL.
  1764. //
  1765. if (AStatus == ESUCCESS) {
  1766. //
  1767. // do the search for the HAL.
  1768. //
  1769. MachineName = SlDetectHal();
  1770. if (MachineName) {
  1771. //
  1772. // OK, got the hal type, now look in the SIF file for the actual
  1773. // hal name.
  1774. //
  1775. HalName = SlGetIniValue(
  1776. InfFile,
  1777. "Hal",
  1778. MachineName,
  1779. NULL);
  1780. if (HalName) {
  1781. strcpy(HalType, HalName );
  1782. //
  1783. // also get the hal description, which is a "pretty print" version
  1784. // of the hal name
  1785. //
  1786. HalName = SlGetIniValue(
  1787. InfFile,
  1788. "Computer",
  1789. MachineName,
  1790. NULL );
  1791. if (HalName) {
  1792. strcpy(HalDescription, HalName);
  1793. Status = TRUE;
  1794. }
  1795. }
  1796. }
  1797. SpFreeINFBuffer( InfFile );
  1798. }
  1799. return(Status);
  1800. }
  1801. #else
  1802. BOOLEAN
  1803. BlDetectHal(
  1804. VOID
  1805. )
  1806. /*++
  1807. Routine Description:
  1808. This function tries to determine the Hal type for this system.
  1809. It fills in the global "HalType" with the type.
  1810. NOTE WELL: EFI machines are always "ACPI" machines so there is
  1811. only one hal type.
  1812. Arguments:
  1813. None.
  1814. Return Value:
  1815. TRUE if the function successfully detects the hal type.
  1816. --*/
  1817. {
  1818. strcpy(HalType, "hal.dll" );
  1819. strcpy(HalDescription,"ACPI PC");
  1820. return(TRUE);
  1821. }
  1822. #endif
  1823. //
  1824. // note well: We stub out these setup functions in oschoice.exe, which are
  1825. // needed so that the hal detection routines can run properly. None of these
  1826. // routines should actually be called.
  1827. //
  1828. VOID
  1829. SlErrorBox(
  1830. IN ULONG MessageId,
  1831. IN ULONG Line,
  1832. IN PCHAR File
  1833. )
  1834. {
  1835. NOTHING;
  1836. }
  1837. VOID
  1838. SlFatalError(
  1839. IN ULONG MessageId,
  1840. ...
  1841. )
  1842. {
  1843. //while(1) {
  1844. NOTHING;
  1845. //};
  1846. }
  1847. VOID
  1848. SlFriendlyError(
  1849. IN ULONG uStatus,
  1850. IN PCHAR pchBadFile,
  1851. IN ULONG uLine,
  1852. IN PCHAR pchCodeFile
  1853. )
  1854. {
  1855. NOTHING;
  1856. }
  1857. VOID
  1858. SlNoMemError(
  1859. IN ULONG Line,
  1860. IN PCHAR File
  1861. )
  1862. {
  1863. SlFatalError(0,Line,File);
  1864. }
  1865. VOID
  1866. SlBadInfLineError(
  1867. IN ULONG Line,
  1868. IN PCHAR INFFile
  1869. )
  1870. {
  1871. SlFatalError(0,Line,INFFile);
  1872. }
  1873. #define SL_KEY_F3 0x03000000
  1874. ULONG
  1875. SlGetChar(
  1876. VOID
  1877. )
  1878. {
  1879. return(SL_KEY_F3);
  1880. }
  1881. VOID
  1882. SlPrint(
  1883. IN PTCHAR FormatString,
  1884. ...
  1885. )
  1886. {
  1887. NOTHING;
  1888. }