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.

2850 lines
71 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.0\r\n";
  54. WCHAR OsLoaderVersionW[] = L"OS Chooser V5.0\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 AllowFlip = TRUE; // can we be flipped to another server
  71. BOOLEAN LoggedIn = FALSE; // have we successfully logged in
  72. UCHAR NextBootfile[128];
  73. UCHAR SifFile[128];
  74. BOOLEAN DoSoftReboot = FALSE;
  75. BOOLEAN BlUsePae;
  76. //
  77. // the following globals are for detecting the hal
  78. //
  79. UCHAR HalType[8+1+3+1];
  80. UCHAR HalDescription[128];
  81. PVOID InfFile;
  82. PVOID WinntSifHandle;
  83. PCHAR WinntSifFile;
  84. ULONG WinntSifFileLength;
  85. BOOLEAN DisableACPI = FALSE;
  86. #if 0 && DBG
  87. #define _TRACE_FUNC_
  88. #endif
  89. #ifdef _TRACE_FUNC_
  90. #define TraceFunc( _func) { \
  91. CHAR FileLine[80]; \
  92. sprintf( FileLine, "%s(%u)", __FILE__, __LINE__ ); \
  93. DPRINT( OSC, ( "%-55s: %s", FileLine, _func )); \
  94. }
  95. #else
  96. #define TraceFunc( _func )
  97. #endif
  98. //
  99. // This removes macro redefinitions which appear because we define __RPC_DOS__,
  100. // but rpc.h defines __RPC_WIN32__
  101. //
  102. #pragma warning(disable:4005)
  103. //
  104. // As of 12/17/98, SECURITY_DOS is *not* defined - adamba
  105. //
  106. #if defined(SECURITY_DOS)
  107. //
  108. // These appear because we defined SECURITY_DOS
  109. //
  110. #define __far
  111. #define __pascal
  112. #define __loadds
  113. #endif
  114. #include <security.h>
  115. #include <rpc.h>
  116. #include <spseal.h>
  117. #if defined(SECURITY_DOS)
  118. //
  119. // PSECURITY_STRING is not supposed to be used when SECURITY_DOS is
  120. // defined -- it should be a WCHAR*. Unfortunately ntlmsp.h breaks
  121. // this rule and even uses the SECURITY_STRING structure, which there
  122. // is really no equivalent for in 16-bit mode.
  123. //
  124. typedef SEC_WCHAR * SECURITY_STRING; // more-or-less the intention where it is used
  125. typedef SEC_WCHAR * PSECURITY_STRING;
  126. #endif
  127. #include <ntlmsp.h>
  128. //
  129. // Packet structure definitions.
  130. //
  131. #include "oscpkt.h"
  132. #if DBG
  133. VOID
  134. DumpBuffer(
  135. PVOID Buffer,
  136. ULONG BufferSize
  137. )
  138. /*++
  139. Routine Description:
  140. Dumps the buffer content on to the debugger output.
  141. Arguments:
  142. Buffer: buffer pointer.
  143. BufferSize: size of the buffer.
  144. Return Value:
  145. none
  146. --*/
  147. {
  148. #define NUM_CHARS 16
  149. ULONG i, limit;
  150. CHAR TextBuffer[NUM_CHARS + 1];
  151. PUCHAR BufferPtr = Buffer;
  152. KdPrint(("------------------------------------\n"));
  153. //
  154. // Hex dump of the bytes
  155. //
  156. limit = ((BufferSize - 1) / NUM_CHARS + 1) * NUM_CHARS;
  157. for (i = 0; i < limit; i++) {
  158. if (i < BufferSize) {
  159. KdPrint(("%02x ", (UCHAR)BufferPtr[i]));
  160. if (BufferPtr[i] < 31 ) {
  161. TextBuffer[i % NUM_CHARS] = '.';
  162. } else if (BufferPtr[i] == '\0') {
  163. TextBuffer[i % NUM_CHARS] = ' ';
  164. } else {
  165. TextBuffer[i % NUM_CHARS] = (CHAR) BufferPtr[i];
  166. }
  167. } else {
  168. KdPrint((" "));
  169. TextBuffer[i % NUM_CHARS] = ' ';
  170. }
  171. if ((i + 1) % NUM_CHARS == 0) {
  172. TextBuffer[NUM_CHARS] = 0;
  173. KdPrint((" %s\n", TextBuffer));
  174. }
  175. }
  176. KdPrint(("------------------------------------\n"));
  177. }
  178. VOID
  179. PrintTime(
  180. LPSTR Comment,
  181. TimeStamp ConvertTime
  182. )
  183. /*++
  184. Routine Description:
  185. Print the specified time
  186. Arguments:
  187. Comment - Comment to print in front of the time
  188. Time - Local time to print
  189. Return Value:
  190. None
  191. --*/
  192. {
  193. KdPrint(( "%s", Comment ));
  194. //
  195. // If the time is infinite,
  196. // just say so.
  197. //
  198. if ( ConvertTime.LowPart == 0x7FFFFFFF ) {
  199. KdPrint(( "Infinite\n" ));
  200. //
  201. // Otherwise print it more clearly
  202. //
  203. } else {
  204. KdPrint(("%lx %lx\n", ConvertTime.HighPart, ConvertTime.LowPart));
  205. }
  206. }
  207. #endif // DBG
  208. //
  209. // Define transfer entry of loaded image.
  210. //
  211. typedef
  212. VOID
  213. (*PTRANSFER_ROUTINE) (
  214. PLOADER_PARAMETER_BLOCK LoaderBlock
  215. );
  216. BOOLEAN
  217. BlGetDriveSignature(
  218. IN PCHAR Name,
  219. OUT PULONG Signature
  220. );
  221. PVOID
  222. BlLoadDataFile(
  223. IN ULONG DeviceId,
  224. IN PCHAR LoadDevice,
  225. IN PCHAR SystemPath,
  226. IN PUNICODE_STRING Filename,
  227. IN MEMORY_TYPE MemoryType,
  228. OUT PULONG FileSize
  229. );
  230. #if defined(REMOTE_BOOT)
  231. BOOLEAN
  232. BlIsDiskless(
  233. VOID
  234. );
  235. #endif // defined(REMOTE_BOOT)
  236. //
  237. // Define local static data.
  238. //
  239. PCHAR ArcStatusCodeMessages[] = {
  240. "operation was success",
  241. "E2BIG",
  242. "EACCES",
  243. "EAGAIN",
  244. "EBADF",
  245. "EBUSY",
  246. "EFAULT",
  247. "EINVAL",
  248. "EIO",
  249. "EISDIR",
  250. "EMFILE",
  251. "EMLINK",
  252. "ENAMETOOLONG",
  253. "ENODEV",
  254. "ENOENT",
  255. "ENOEXEC",
  256. "ENOMEM",
  257. "ENOSPC",
  258. "ENOTDIR",
  259. "ENOTTY",
  260. "ENXIO",
  261. "EROFS",
  262. };
  263. //
  264. // Diagnostic load messages
  265. //
  266. VOID
  267. BlFatalError(
  268. IN ULONG ClassMessage,
  269. IN ULONG DetailMessage,
  270. IN ULONG ActionMessage
  271. );
  272. VOID
  273. BlBadFileMessage(
  274. IN PCHAR BadFileName
  275. );
  276. VOID
  277. BlpSetInverseMode(
  278. IN BOOLEAN InverseOn
  279. );
  280. VOID
  281. BlpSendEscape(
  282. PCHAR Escape
  283. );
  284. ULONG
  285. BlGetUserResponse(
  286. IN ULONG XLocation,
  287. IN ULONG YLocation,
  288. IN BOOLEAN Hidden,
  289. IN ULONG MaximumLength,
  290. OUT PCHAR Response
  291. );
  292. ULONG
  293. BlGetKeyWithBlink(
  294. IN ULONG XLocation,
  295. IN ULONG YLocation
  296. );
  297. ULONG
  298. BlDoLogin ( );
  299. VOID
  300. BlDoLogoff(
  301. VOID
  302. );
  303. //
  304. // Define external static data.
  305. //
  306. BOOLEAN BlConsoleInitialized = FALSE;
  307. ULONG BlConsoleOutDeviceId = 0;
  308. ULONG BlConsoleInDeviceId = 0;
  309. ULONG BlDcacheFillSize = 32;
  310. extern BOOLEAN BlOutputDots;
  311. ULONGLONG NetRebootParameter = (ULONGLONG)0;
  312. UCHAR NetRebootFile[128];
  313. BOOLEAN BlRebootSystem = FALSE;
  314. ULONG BlVirtualBias = 0;
  315. CHAR KernelFileName[8+1+3+1]="ntoskrnl.exe";
  316. CHAR HalFileName[8+1+3+1]="hal.dll";
  317. //
  318. // Globals used during login. Mostly because it would be too many
  319. // parameters to pass to BlDoLogin().
  320. //
  321. #define OUTGOING_MESSAGE_LENGTH 1024
  322. #define INCOMING_MESSAGE_LENGTH 8192
  323. #define TEMP_INCOMING_MESSAGE_LENGTH 1500
  324. #define RECEIVE_TIMEOUT 5
  325. #define RECEIVE_RETRIES 24
  326. CHAR OutgoingMessageBuffer[OUTGOING_MESSAGE_LENGTH];
  327. SIGNED_PACKET UNALIGNED * OutgoingSignedMessage;
  328. CHAR IncomingMessageBuffer[INCOMING_MESSAGE_LENGTH];
  329. SIGNED_PACKET UNALIGNED * IncomingSignedMessage;
  330. CHAR TempIncomingMessage[TEMP_INCOMING_MESSAGE_LENGTH]; // used for reassembly
  331. CredHandle CredentialHandle;
  332. BOOLEAN CredentialHandleValid = FALSE;
  333. CtxtHandle ClientContextHandle;
  334. BOOLEAN ClientContextHandleValid = FALSE;
  335. PSecPkgInfoA PackageInfo = NULL;
  336. ARC_STATUS
  337. BlInitStdio (
  338. IN ULONG Argc,
  339. IN PCHAR Argv[]
  340. )
  341. {
  342. PCHAR ConsoleOutDevice;
  343. PCHAR ConsoleInDevice;
  344. ULONG Status;
  345. if (BlConsoleInitialized) {
  346. return ESUCCESS;
  347. }
  348. //
  349. // Get the name of the console output device and open the device for
  350. // write access.
  351. //
  352. ConsoleOutDevice = BlGetArgumentValue(Argc, Argv, "consoleout");
  353. if (ConsoleOutDevice == NULL) {
  354. return ENODEV;
  355. }
  356. Status = ArcOpen(ConsoleOutDevice, ArcOpenWriteOnly, &BlConsoleOutDeviceId);
  357. if (Status != ESUCCESS) {
  358. return Status;
  359. }
  360. //
  361. // Get the name of the console input device and open the device for
  362. // read access.
  363. //
  364. ConsoleInDevice = BlGetArgumentValue(Argc, Argv, "consolein");
  365. if (ConsoleInDevice == NULL) {
  366. return ENODEV;
  367. }
  368. Status = ArcOpen(ConsoleInDevice, ArcOpenReadOnly, &BlConsoleInDeviceId);
  369. if (Status != ESUCCESS) {
  370. return Status;
  371. }
  372. BlConsoleInitialized = TRUE;
  373. return ESUCCESS;
  374. }
  375. extern BOOLEAN NetBoot;
  376. NTSTATUS
  377. UdpSendAndReceive(
  378. IN PVOID SendBuffer,
  379. IN ULONG SendBufferLength,
  380. IN ULONG SendRemoteHost,
  381. IN USHORT SendRemotePort,
  382. IN ULONG SendRetryCount,
  383. IN PVOID ReceiveBuffer,
  384. IN ULONG ReceiveBufferLength,
  385. OUT PULONG ReceiveRemoteHost,
  386. OUT PUSHORT ReceiveRemotePort,
  387. IN ULONG ReceiveTimeout,
  388. IN ULONG ReceiveSignatureCount,
  389. IN PCHAR ReceiveSignatures[],
  390. IN ULONG ReceiveSequenceNumber
  391. )
  392. {
  393. ULONG i, j;
  394. ULONG length;
  395. SIGNED_PACKET UNALIGNED * ReceiveHeader =
  396. (SIGNED_PACKET UNALIGNED *)ReceiveBuffer;
  397. #ifdef _TRACE_FUNC_
  398. TraceFunc("UdpSendAndReceive( ");
  399. DPRINT( OSC, ("ReceiveSequenceNumber=%u )\n", ReceiveSequenceNumber) );
  400. #endif
  401. //
  402. // Try sending the packet SendRetryCount times, until we receive
  403. // a response with the right signature, waiting ReceiveTimeout
  404. // each time.
  405. //
  406. for (i = 0; i < SendRetryCount; i++) {
  407. length = UdpSend(
  408. SendBuffer,
  409. SendBufferLength,
  410. SendRemoteHost,
  411. SendRemotePort);
  412. if ( length != SendBufferLength ) {
  413. DPRINT( ERROR, ("UdpSend only sent %d bytes, not %d\n", length, SendBufferLength) );
  414. return STATUS_UNEXPECTED_NETWORK_ERROR;
  415. }
  416. ReReceive:
  417. //
  418. // NULL out the first 12 bytes in case we get shorter data.
  419. //
  420. memset(ReceiveBuffer, 0x0, 12);
  421. length = UdpReceive(
  422. ReceiveBuffer,
  423. ReceiveBufferLength,
  424. ReceiveRemoteHost,
  425. ReceiveRemotePort,
  426. ReceiveTimeout);
  427. if ( length == 0 ) {
  428. DPRINT( ERROR, ("UdpReceive timed out\n") );
  429. continue;
  430. }
  431. //
  432. // Make sure the signature is one of the ones we expect.
  433. //
  434. for (j = 0; j < ReceiveSignatureCount; j++) {
  435. if (memcmp(ReceiveBuffer, ReceiveSignatures[j], 4) == 0) {
  436. //
  437. // Now make sure that the sequence number is correct,
  438. // if asked to check (0 means don't check).
  439. //
  440. if ((ReceiveSequenceNumber == 0) ||
  441. (ReceiveSequenceNumber == ReceiveHeader->SequenceNumber)) {
  442. return STATUS_SUCCESS;
  443. } else {
  444. DPRINT( ERROR, ("UdpReceive expected seq %d, got %d\n",
  445. ReceiveSequenceNumber, ReceiveHeader->SequenceNumber) );
  446. }
  447. }
  448. }
  449. DPRINT( ERROR, ("UdpReceive got wrong signature\n") );
  450. //
  451. // Don't UdpSend again just because we got a bad signature. Still need
  452. // to respect the original ReceiveTimeout however!
  453. //
  454. goto ReReceive;
  455. }
  456. //
  457. // We timed out.
  458. //
  459. return STATUS_IO_TIMEOUT;
  460. }
  461. //
  462. // This routine signs and sends a message, waits for a response, and
  463. // then verifies the signature on the response.
  464. //
  465. // It returns a positive number on success, 0 on a timeout, -1 if
  466. // the server did not recognize the client, and -2 on other errors
  467. // (which should be fixable by having the client re-login and
  468. // re-transmit the request).
  469. //
  470. // NOTE: The data is sent as a UDP datagram. This requires a UDP header
  471. // which the SendBuffer is assumed to have room for. In addition, we
  472. // use 32 bytes for the "REQS", the total length, the sequence number,
  473. // the sign length, and the sign itself (which is 16 bytes).
  474. //
  475. // For similar reasons, ReceiveBuffer is assumed to have 32 bytes of
  476. // room at the beginning.
  477. //
  478. // Return values:
  479. //
  480. // 0 - nothing was received
  481. // -1 - a timeout occurred
  482. // -2 - unexpected network error, such as a sign/seal error
  483. // -3 - receive buffer overflow
  484. // positive number - the number of data bytes received
  485. //
  486. #define SIGN_HEADER_SIZE SIGNED_PACKET_DATA_OFFSET
  487. ULONG CorruptionCounter = 1;
  488. ULONG
  489. SignSendAndReceive(
  490. IN PVOID SendBuffer,
  491. IN ULONG SendBufferLength,
  492. IN ULONG SendRemoteHost,
  493. IN USHORT SendRemotePort,
  494. IN ULONG SendRetryCount,
  495. IN ULONG SendSequenceNumber,
  496. CtxtHandle ClientContextHandle,
  497. IN PVOID ReceiveBuffer,
  498. IN ULONG ReceiveBufferLength,
  499. OUT PULONG ReceiveRemoteHost,
  500. OUT PUSHORT ReceiveRemotePort,
  501. IN ULONG ReceiveTimeout
  502. )
  503. {
  504. SECURITY_STATUS SecStatus;
  505. ULONG Status;
  506. ULONG length;
  507. SecBufferDesc SignMessage;
  508. SecBuffer SigBuffers[2];
  509. SIGNED_PACKET UNALIGNED * SendHeader =
  510. (SIGNED_PACKET UNALIGNED *)((PCHAR)SendBuffer - SIGN_HEADER_SIZE);
  511. SIGNED_PACKET UNALIGNED * ReceiveHeader =
  512. (SIGNED_PACKET UNALIGNED *)((PCHAR)ReceiveBuffer - SIGN_HEADER_SIZE);
  513. PCHAR ResultSigs[3];
  514. USHORT FragmentNumber;
  515. USHORT FragmentTotal;
  516. FRAGMENT_PACKET UNALIGNED * TempFragment = (FRAGMENT_PACKET UNALIGNED *)TempIncomingMessage;
  517. ULONG ResendCount = 0;
  518. ULONG ReceivedDataBytes;
  519. TraceFunc("SignSendAndReceive( )\n");
  520. if ( LoggedIn )
  521. {
  522. SigBuffers[1].pvBuffer = SendHeader->Sign;
  523. SigBuffers[1].cbBuffer = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  524. SigBuffers[1].BufferType = SECBUFFER_TOKEN;
  525. SigBuffers[0].pvBuffer = SendBuffer;
  526. SigBuffers[0].cbBuffer = SendBufferLength;
  527. SigBuffers[0].BufferType = SECBUFFER_DATA;
  528. SignMessage.pBuffers = SigBuffers;
  529. SignMessage.cBuffers = 2;
  530. SignMessage.ulVersion = 0;
  531. //
  532. // Sign/seal a message
  533. //
  534. #ifndef ONLY_SIGN_MESSAGES
  535. SecStatus = SealMessage(
  536. &ClientContextHandle,
  537. 0,
  538. &SignMessage,
  539. 0 );
  540. if ( SecStatus != SEC_E_OK ) {
  541. DPRINT( OSC, ("SealMessage: %lx\n", SecStatus) );
  542. return (ULONG)-2;
  543. }
  544. #else
  545. SecStatus = MakeSignature(
  546. &ClientContextHandle,
  547. 0,
  548. &SignMessage,
  549. 0 );
  550. if ( SecStatus != SEC_E_OK ) {
  551. DPRINT( OSC, ("MakeSignature: %lx\n", SecStatus) );
  552. return (ULONG)-2;
  553. }
  554. #endif
  555. #if 0
  556. //
  557. // Corrupt every fifth message.
  558. //
  559. if ((CorruptionCounter % 5) == 0) {
  560. DPRINT( ERROR, ("INTENTIONALLY CORRUPTING A PACKET\n") );
  561. ((PCHAR)SendBuffer)[0] = '\0';
  562. }
  563. ++CorruptionCounter;
  564. #endif
  565. memcpy(SendHeader->Signature, RequestSignedSignature, 4);
  566. SendHeader->SignLength = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  567. ResultSigs[0] = ResponseSignedSignature;
  568. }
  569. else
  570. {
  571. memcpy(SendHeader->Signature, RequestUnsignedSignature, 4);
  572. SendHeader->SignLength = 0;
  573. ResultSigs[0] = ResponseUnsignedSignature;
  574. }
  575. ResultSigs[1] = ErrorSignedSignature;
  576. ResultSigs[2] = UnrecognizedClientSignature;
  577. //
  578. // Fill in our header before the SendBuffer. The sign has already been
  579. // written in because we set up SigBuffers to point to the right place.
  580. //
  581. SendHeader->Length = SendBufferLength + SIGNED_PACKET_EMPTY_LENGTH;
  582. SendHeader->SequenceNumber = SendSequenceNumber;
  583. SendHeader->FragmentNumber = 1;
  584. SendHeader->FragmentTotal = 1;
  585. //
  586. // Do an exchange with the server.
  587. //
  588. ReSend:
  589. Status = UdpSendAndReceive(
  590. SendHeader,
  591. SendBufferLength + SIGN_HEADER_SIZE,
  592. SendRemoteHost,
  593. SendRemotePort,
  594. SendRetryCount,
  595. ReceiveHeader,
  596. INCOMING_MESSAGE_LENGTH,
  597. ReceiveRemoteHost,
  598. ReceiveRemotePort,
  599. ReceiveTimeout,
  600. 3, // signature count
  601. ResultSigs, // signatures we look for
  602. SendSequenceNumber); // response should have the same one
  603. if (!NT_SUCCESS(Status)) {
  604. if (Status == STATUS_IO_TIMEOUT) {
  605. return (ULONG)-1;
  606. } else {
  607. return (ULONG)-2;
  608. }
  609. }
  610. //
  611. // Was it an error?
  612. //
  613. if (memcmp(ReceiveHeader->Signature, ErrorSignedSignature, 4) == 0) {
  614. DPRINT( ERROR, ("SignSendAndReceive: got ERR response\n") );
  615. return (ULONG)-2;
  616. }
  617. //
  618. // Was the client not recognized by the server?
  619. //
  620. if (memcmp(ReceiveHeader->Signature, UnrecognizedClientSignature, 4) == 0) {
  621. DPRINT( ERROR, ("SignSendAndReceive: got UNR response\n") );
  622. return (ULONG)-1;
  623. }
  624. if (ReceiveHeader->Length < (ULONG)SIGNED_PACKET_EMPTY_LENGTH) {
  625. DPRINT( ERROR, ("SignSendAndReceive: response is only %d bytes!\n", ReceiveHeader->Length) );
  626. ++ResendCount;
  627. if (ResendCount > SendRetryCount) {
  628. return (ULONG)-2;
  629. }
  630. goto ReSend;
  631. }
  632. //
  633. // If there are fragments, then try to receive the rest of them.
  634. //
  635. if (ReceiveHeader->FragmentTotal != 1) {
  636. //
  637. // Make sure this is fragment 1 -- otherwise the first one
  638. // was probably dropped and we should re-request it.
  639. //
  640. if (ReceiveHeader->FragmentNumber != 1) {
  641. DPRINT( ERROR, ("UdpReceive got non-first fragment\n") );
  642. ++ResendCount;
  643. if (ResendCount > SendRetryCount) {
  644. return (ULONG)-1;
  645. }
  646. goto ReSend; // redoes the whole exchange.
  647. }
  648. FragmentTotal = ReceiveHeader->FragmentTotal;
  649. ReceivedDataBytes = ReceiveHeader->Length - SIGNED_PACKET_EMPTY_LENGTH;
  650. for (FragmentNumber = 1; FragmentNumber < FragmentTotal; FragmentNumber ++) {
  651. ReReceive:
  652. //
  653. // NULL out the start of the receive buffer.
  654. //
  655. memset(TempFragment, 0x0, sizeof(FRAGMENT_PACKET));
  656. length = UdpReceive(
  657. TempFragment,
  658. TEMP_INCOMING_MESSAGE_LENGTH,
  659. ReceiveRemoteHost,
  660. ReceiveRemotePort,
  661. ReceiveTimeout);
  662. if ( length == 0 ) {
  663. DPRINT( ERROR, ("UdpReceive timed out\n") );
  664. ++ResendCount;
  665. if (ResendCount > SendRetryCount) {
  666. return (ULONG)-1;
  667. }
  668. goto ReSend; // redoes the whole exchange.
  669. }
  670. //
  671. // Make sure the signature is one of the ones we expect -- only
  672. // worry about the ResultSignature because we won't get an
  673. // error response on any fragment besides the first.
  674. //
  675. // Also make sure that the
  676. // sequence number is correct, if asked to check (0 means don't
  677. // check). If it's not, then go back and wait for another packet.
  678. //
  679. if ((TempFragment->Length < (ULONG)FRAGMENT_PACKET_EMPTY_LENGTH) ||
  680. (memcmp(TempFragment->Signature, ResultSigs[0], 4) != 0) ||
  681. ((SendSequenceNumber != 0) &&
  682. (SendSequenceNumber != TempFragment->SequenceNumber))) {
  683. DPRINT( ERROR, ("UdpReceive got wrong signature or sequence number\n") );
  684. goto ReReceive;
  685. }
  686. //
  687. // Check that the fragment number is also correct.
  688. //
  689. if (TempFragment->FragmentNumber != FragmentNumber+1) {
  690. DPRINT( ERROR, ("UdpReceive got wrong fragment number\n") );
  691. goto ReReceive;
  692. }
  693. //
  694. // Make sure that this fragment won't overflow the buffer.
  695. //
  696. if (ReceivedDataBytes + (TempFragment->Length - FRAGMENT_PACKET_EMPTY_LENGTH) >
  697. ReceiveBufferLength) {
  698. return (ULONG)-3;
  699. }
  700. //
  701. // This is the correct fragment, so copy it over and loop
  702. // to the next fragment.
  703. //
  704. memcpy(
  705. &ReceiveHeader->Data[ReceivedDataBytes],
  706. TempFragment->Data,
  707. TempFragment->Length - FRAGMENT_PACKET_EMPTY_LENGTH);
  708. ReceivedDataBytes += TempFragment->Length - FRAGMENT_PACKET_EMPTY_LENGTH;
  709. }
  710. //
  711. // When we are done getting everything, modify the length in the
  712. // incoming packet to match the total length (currently it will
  713. // just have the length of the first fragment.
  714. //
  715. ReceiveHeader->Length = ReceivedDataBytes + SIGNED_PACKET_EMPTY_LENGTH;
  716. DPRINT( OSC, ("Got packet with %d fragments, total length %d\n",
  717. FragmentTotal, ReceiveHeader->Length) );
  718. }
  719. //
  720. // Make sure the sign is the length we expect!!
  721. //
  722. if (LoggedIn == TRUE &&
  723. ReceiveHeader->SignLength != NTLMSSP_MESSAGE_SIGNATURE_SIZE)
  724. {
  725. DPRINT( ERROR, ("SignSendAndReceive: signature length is %d bytes!\n", ReceiveHeader->SignLength) );
  726. ++ResendCount;
  727. if (ResendCount > SendRetryCount) {
  728. return (ULONG)-2;
  729. }
  730. goto ReSend;
  731. }
  732. else if ( LoggedIn == FALSE &&
  733. ReceiveHeader->SignLength != 0 )
  734. {
  735. DPRINT( ERROR, ("SignSendAndReceive: signature length is not 0 bytes (=%u)!\n", ReceiveHeader->SignLength) );
  736. ++ResendCount;
  737. if (ResendCount > SendRetryCount) {
  738. return (ULONG)-2;
  739. }
  740. goto ReSend;
  741. }
  742. if ( LoggedIn )
  743. {
  744. SigBuffers[1].pvBuffer = ReceiveHeader->Sign;
  745. SigBuffers[1].cbBuffer = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  746. SigBuffers[1].BufferType = SECBUFFER_TOKEN;
  747. SigBuffers[0].pvBuffer = ReceiveBuffer;
  748. SigBuffers[0].cbBuffer = ReceiveHeader->Length - SIGNED_PACKET_EMPTY_LENGTH;
  749. SigBuffers[0].BufferType = SECBUFFER_DATA;
  750. SignMessage.pBuffers = SigBuffers;
  751. SignMessage.cBuffers = 2;
  752. SignMessage.ulVersion = 0;
  753. #ifndef ONLY_SIGN_MESSAGES
  754. SecStatus = UnsealMessage(
  755. &ClientContextHandle,
  756. &SignMessage,
  757. 0,
  758. 0 );
  759. if ( SecStatus != SEC_E_OK ) {
  760. DPRINT( ERROR, ("UnsealMessage: %lx\n", SecStatus) );
  761. return (ULONG)-2;
  762. }
  763. #else
  764. SecStatus = VerifySignature(
  765. &ClientContextHandle,
  766. &SignMessage,
  767. 0,
  768. 0 );
  769. if ( SecStatus != SEC_E_OK ) {
  770. DPRINT( ERROR, ("VerifySignature: %lx\n", SecStatus) );
  771. return (ULONG)-2;
  772. }
  773. #endif
  774. }
  775. //
  776. // Sucess, so return.
  777. //
  778. return (ReceiveHeader->Length - SIGNED_PACKET_EMPTY_LENGTH);
  779. }
  780. #if defined(REMOTE_BOOT)
  781. //
  782. // write secret based on the CREATE_DATA structure
  783. //
  784. VOID
  785. BlWriteSecretFromCreateData(
  786. PCREATE_DATA CreateData
  787. )
  788. {
  789. ULONG FileId;
  790. RI_SECRET Secret;
  791. ARC_STATUS ArcStatus;
  792. UNICODE_STRING TmpNtPassword;
  793. CHAR TmpLmOwfPassword[LM_OWF_PASSWORD_SIZE];
  794. CHAR TmpNtOwfPassword[NT_OWF_PASSWORD_SIZE];
  795. TraceFunc("BlWriteSecretFromCreateData( )\n");
  796. //
  797. // Write the secret. This is the secret for the machine account
  798. // created by BINL, not for the user that logged on.
  799. //
  800. if (BlOpenRawDisk(&FileId) == ESUCCESS) {
  801. if (BlCheckForFreeSectors(FileId) == ESUCCESS) {
  802. TmpNtPassword.Length = (USHORT)CreateData->UnicodePasswordLength;
  803. TmpNtPassword.MaximumLength = sizeof(CreateData->UnicodePassword);
  804. TmpNtPassword.Buffer = CreateData->UnicodePassword;
  805. BlOwfPassword(
  806. CreateData->Password,
  807. &TmpNtPassword,
  808. TmpLmOwfPassword,
  809. TmpNtOwfPassword);
  810. BlInitializeSecret(
  811. CreateData->Domain,
  812. CreateData->Name,
  813. TmpLmOwfPassword,
  814. TmpNtOwfPassword,
  815. NULL, // no password 2
  816. NULL, // no password 2
  817. CreateData->Sid,
  818. &Secret);
  819. //
  820. // Copy the cleartext UnicodePassword into the reserved
  821. // section. The reserved section has the length followed
  822. // by the data (up to 32 WCHARs).
  823. //
  824. (*(ULONG UNALIGNED *)(Secret.Reserved)) = CreateData->UnicodePasswordLength;
  825. RtlCopyMemory(
  826. Secret.Reserved + sizeof(ULONG),
  827. CreateData->UnicodePassword,
  828. CreateData->UnicodePasswordLength);
  829. ArcStatus = BlWriteSecret(FileId, &Secret);
  830. if (ArcStatus != ESUCCESS) {
  831. DPRINT( ERROR, ("BlWriteSecret: status is %d\n", ArcStatus) );
  832. }
  833. }
  834. BlCloseRawDisk(FileId);
  835. }
  836. }
  837. #endif // defined(REMOTE_BOOT)
  838. //
  839. // Retrieve next screen
  840. //
  841. BOOL
  842. BlRetrieveScreen(
  843. ULONG *SequenceNumber,
  844. PCHAR OutMessage,
  845. PCHAR InMessage
  846. )
  847. {
  848. ARC_STATUS Status;
  849. ULONG OutMessageLength = strlen( OutMessage );
  850. ULONG InMessageLength;
  851. PCREATE_DATA CreateData;
  852. TraceFunc("BlRetrieveScreen( )\n");
  853. // make sure we don't over flow the output buffer
  854. if ( OutMessageLength > 1023 ) {
  855. OutMessageLength = 1023;
  856. OutMessage[OutMessageLength] = '\0';
  857. }
  858. ++(*SequenceNumber);
  859. if ( *SequenceNumber > 0x2000 )
  860. {
  861. *SequenceNumber = 1;
  862. }
  863. if (!LoggedIn)
  864. {
  865. #ifdef _TRACE_FUNC_
  866. TraceFunc( "Sending RQU ");
  867. DPRINT( OSC, ("(%u)...\n", *SequenceNumber) );
  868. #endif
  869. memcpy( OutgoingSignedMessage->Data, OutMessage, OutMessageLength );
  870. Status = SignSendAndReceive(
  871. OutgoingSignedMessage->Data,
  872. OutMessageLength,
  873. NetServerIpAddress,
  874. BINL_PORT,
  875. RECEIVE_RETRIES,
  876. *SequenceNumber,
  877. ClientContextHandle,
  878. IncomingSignedMessage->Data,
  879. INCOMING_MESSAGE_LENGTH - SIGN_HEADER_SIZE,
  880. &RemoteHost,
  881. &RemotePort,
  882. RECEIVE_TIMEOUT);
  883. }
  884. else
  885. {
  886. #ifdef _TRACE_FUNC_
  887. TraceFunc( "Sending Seal/Signed REQS " );
  888. DPRINT( OSC, ("(%u)...\n", *SequenceNumber) );
  889. #endif
  890. while (TRUE)
  891. {
  892. memcpy( OutgoingSignedMessage->Data, OutMessage, OutMessageLength );
  893. Status = SignSendAndReceive(
  894. OutgoingSignedMessage->Data,
  895. OutMessageLength,
  896. NetServerIpAddress,
  897. BINL_PORT,
  898. RECEIVE_RETRIES,
  899. *SequenceNumber,
  900. ClientContextHandle,
  901. IncomingSignedMessage->Data,
  902. INCOMING_MESSAGE_LENGTH - SIGN_HEADER_SIZE,
  903. &RemoteHost,
  904. &RemotePort,
  905. RECEIVE_TIMEOUT);
  906. if ((Status == 0) || (Status == (ULONG)-2))
  907. {
  908. DPRINT( OSC, ("Attempting to re-login\n") );
  909. //
  910. // We assume that the server has dropped the current login
  911. // and don't bother calling BlDoLogoff();
  912. //
  913. LoggedIn = FALSE;
  914. Status = BlDoLogin( );
  915. *SequenceNumber = 1;
  916. if (Status == STATUS_SUCCESS)
  917. {
  918. DPRINT( ERROR, ("Successfully re-logged in\n") );
  919. memcpy(OutgoingSignedMessage->Data, OutMessage, OutMessageLength);
  920. LoggedIn = TRUE;
  921. continue;
  922. }
  923. else
  924. {
  925. DPRINT( ERROR, ("ERROR - could not re-login, %x\n", Status) );
  926. //DbgBreakPoint();
  927. //
  928. // Call ourselves again, but request the LoginErr screen which
  929. // is 00004e28.
  930. //
  931. strcpy( OutMessage, "00004e28\n" );
  932. return BlRetrieveScreen( SequenceNumber, OutMessage, InMessage );
  933. }
  934. }
  935. else if (Status == (ULONG)-1)
  936. {
  937. DPRINT( ERROR, ("Unrecognized, requested TIMEOUT screen\n") );
  938. //
  939. // We assume that the server has dropped the current login
  940. //
  941. LoggedIn = FALSE;
  942. //
  943. // Increase the sequence number for the new screen request,
  944. // don't worry about wrapping since the session will die soon.
  945. //
  946. ++(*SequenceNumber);
  947. //
  948. // Call ourselves again, but request the TIMEOUT screen.
  949. //
  950. strcpy( OutMessage, "00004E2A\n" );
  951. return BlRetrieveScreen( SequenceNumber, OutMessage, InMessage );
  952. }
  953. else if (Status == (ULONG)-3)
  954. {
  955. DPRINT( ERROR, ("Unrecognized, requested TOO LONG screen\n") );
  956. //
  957. // This screen is a fatal error, so don't worry about
  958. // staying logged in.
  959. //
  960. LoggedIn = FALSE;
  961. //
  962. // Increase the sequence number for the new screen request,
  963. // don't worry about wrapping since the session will die soon.
  964. //
  965. ++(*SequenceNumber);
  966. //
  967. // Call ourselves again, but request the TIMEOUT screen.
  968. //
  969. strcpy( OutMessage, "00004E53\n" );
  970. return BlRetrieveScreen( SequenceNumber, OutMessage, InMessage );
  971. }
  972. else
  973. {
  974. break;
  975. }
  976. }
  977. }
  978. //
  979. // NULL-terminate it.
  980. //
  981. IncomingSignedMessage->Data[IncomingSignedMessage->Length - SIGNED_PACKET_EMPTY_LENGTH] = '\0';
  982. strcpy( InMessage, IncomingSignedMessage->Data );
  983. InMessageLength = strlen(InMessage);
  984. // DumpBuffer( InMessage, strlen(InMessage) );
  985. //
  986. // If we got an just an ACCT response, with no screen data, that means a
  987. // restart is happening.
  988. //
  989. if (memcmp(InMessage, "ACCT", 4) == 0)
  990. {
  991. CreateData = (PCREATE_DATA) IncomingSignedMessage->Data;
  992. #if defined(REMOTE_BOOT)
  993. //
  994. // If doing remote BOOT (as opposed to install) enable this.
  995. //
  996. BlWriteSecretFromCreateData( CreateData );
  997. #endif // defined(REMOTE_BOOT)
  998. DPRINT( OSC, ("Trying to reboot to <%s>\n", CreateData->NextBootfile) );
  999. strcpy(NextBootfile, CreateData->NextBootfile);
  1000. strcpy(SifFile, CreateData->SifFile);
  1001. DoSoftReboot = TRUE;
  1002. return FALSE; // exit message loop
  1003. }
  1004. //
  1005. // If we got a screen with an ACCT response after the screen data,
  1006. // should write the secret and do a soft reboot. In this situation
  1007. // InMessageLength will only include the screen data itself, but
  1008. // IncomingSignedMessage->Length will include the whole thing.
  1009. //
  1010. if ((IncomingSignedMessage->Length - SIGNED_PACKET_EMPTY_LENGTH) ==
  1011. (InMessageLength + 1 + sizeof(CREATE_DATA))) {
  1012. CreateData = (PCREATE_DATA) (InMessage + InMessageLength + 1);
  1013. if (memcmp(CreateData->Id, "ACCT", 4) == 0) {
  1014. #if defined(REMOTE_BOOT)
  1015. //
  1016. // If doing remote BOOT (as opposed to install) enable this.
  1017. //
  1018. BlWriteSecretFromCreateData( CreateData );
  1019. #endif // defined(REMOTE_BOOT)
  1020. DPRINT( OSC, ("INSTALL packet setting up reboot to <%s>\n", CreateData->NextBootfile) );
  1021. strcpy(NextBootfile, CreateData->NextBootfile);
  1022. strcpy(SifFile, CreateData->SifFile);
  1023. DoSoftReboot = TRUE;
  1024. //
  1025. // Don't return FALSE, because we still want to show the INSTALL
  1026. // screen. NextBootFile/SifFile/DoSoftReboot won't be modified by
  1027. // that so we will do a proper soft reboot when the time comes.
  1028. //
  1029. }
  1030. }
  1031. // Special-case server tells us to LAUNCH a file
  1032. if (memcmp(InMessage, "LAUNCH", 6) == 0) {
  1033. CreateData = (PCREATE_DATA) (IncomingSignedMessage->Data + 7);
  1034. DPRINT( OSC, ("Trying to launch <%s>\n", CreateData->NextBootfile) );
  1035. strcpy(NextBootfile, CreateData->NextBootfile);
  1036. strcpy(SifFile, CreateData->SifFile);
  1037. if (CreateData->RebootParameter == OSC_REBOOT_COMMAND_CONSOLE_ONLY) {
  1038. NetRebootParameter = NET_REBOOT_COMMAND_CONSOLE_ONLY;
  1039. } else if (CreateData->RebootParameter == OSC_REBOOT_ASR) {
  1040. NetRebootParameter = NET_REBOOT_ASR;
  1041. }
  1042. DoSoftReboot = TRUE;
  1043. return FALSE; // exit message loop
  1044. }
  1045. // Special-case REBOOT - server told us to reboot.
  1046. if (memcmp(InMessage, "REBOOT", 6) == 0)
  1047. {
  1048. return FALSE; // exit message loop
  1049. }
  1050. #if defined(REMOTE_BOOT)
  1051. // Special-case GETCREATE - should reboot after we get this
  1052. if (memcmp(InMessage, "GETCREATE", 9) == 0) {
  1053. CreateData = (PCREATE_DATA) (IncomingSignedMessage->Data + 10);
  1054. BlWriteSecretFromCreateData( CreateData );
  1055. //
  1056. // We were soft rebooted to, and it told us where to go back to
  1057. // in NetRebootFile.
  1058. //
  1059. NetRebootParameter = NET_REBOOT_SECRET_VALID;
  1060. strcpy(NextBootfile, NetRebootFile);
  1061. SifFile[0] = '\0';
  1062. DoSoftReboot = TRUE;
  1063. return FALSE; // exit message loop
  1064. }
  1065. // Special-case REPLDONE - write the secret, then do normal processing.
  1066. // The secret is sent as binary data immediately after the screen.
  1067. //
  1068. // This check for "NAME REPLDONE" is obsolete now that we use OSCML.
  1069. //
  1070. if (memcmp(InMessage, "NAME REPLDONE", 13) == 0) {
  1071. CreateData = (PCREATE_DATA) (InMessage + strlen(InMessage) + 1);
  1072. BlWriteSecretFromCreateData( CreateData );
  1073. //
  1074. // Set this so the user won't be sent back to us to logon for
  1075. // te disk having changed.
  1076. //
  1077. NetRebootParameter = NET_REBOOT_SECRET_VALID;
  1078. strcpy(NextBootfile, CreateData->NextBootfile);
  1079. SifFile[0] = '\0';
  1080. DoSoftReboot = TRUE;
  1081. }
  1082. #endif // defined(REMOTE_BOOT)
  1083. return TRUE; // stay in message loop
  1084. }
  1085. ARC_STATUS
  1086. BlOsLoader (
  1087. IN ULONG Argc,
  1088. IN PCHAR Argv[],
  1089. IN PCHAR Envp[]
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. This is the main routine that controls the loading of the NT operating
  1094. system on an ARC compliant system. It opens the system partition,
  1095. the boot partition, the console input device, and the console output
  1096. device. The NT operating system and all its DLLs are loaded and bound
  1097. together. Control is then transfered to the loaded system.
  1098. Arguments:
  1099. Argc - Supplies the number of arguments that were provided on the
  1100. command that invoked this program.
  1101. Argv - Supplies a pointer to a vector of pointers to null terminated
  1102. argument strings.
  1103. Envp - Supplies a pointer to a vector of pointers to null terminated
  1104. environment variables.
  1105. Return Value:
  1106. EBADF is returned if the specified OS image cannot be loaded.
  1107. --*/
  1108. {
  1109. CHAR OutputBuffer[256];
  1110. ULONG Count;
  1111. ARC_STATUS Status;
  1112. SECURITY_STATUS SecStatus; // NOTE: This is a SHORT, so not an NTSTATUS failure on error
  1113. ULONG PackageCount;
  1114. PVOID LoaderBase;
  1115. //
  1116. // Initialize the OS loader console input and output.
  1117. //
  1118. Status = BlInitStdio(Argc, Argv);
  1119. if (Status != ESUCCESS) {
  1120. return Status;
  1121. }
  1122. //
  1123. // Initialize the boot debugger for platforms that directly load the
  1124. // OS Loader.
  1125. //
  1126. // N.B. This must occur after the console input and output have been
  1127. // initialized so debug messages can be printed on the console
  1128. // output device.
  1129. //
  1130. #if defined(_ALPHA_) || defined(ARCI386) || defined(_IA64_)
  1131. //
  1132. // If the program memory descriptor was found, then compute the base
  1133. // address of the OS Loader for use by the debugger.
  1134. //
  1135. LoaderBase = &__ImageBase;
  1136. BlPrint(TEXT("about to init debugger...\r\n"));
  1137. //
  1138. // Initialize traps and the boot debugger.
  1139. //
  1140. #if defined(ENABLE_LOADER_DEBUG)
  1141. #if defined(_ALPHA_)
  1142. BdInitializeTraps();
  1143. #endif
  1144. BdInitDebugger("oschoice.exe", LoaderBase, ENABLE_LOADER_DEBUG);
  1145. #else
  1146. BdInitDebugger("oschoice.exe", LoaderBase, NULL);
  1147. #endif
  1148. #endif
  1149. BlPrint(TEXT("back from initializing debugger...\r\n"));
  1150. #if DBG
  1151. // NetDebugFlag |= 0x147;
  1152. #endif
  1153. TraceFunc("BlOsLoader( )\n");
  1154. //
  1155. // Announce OS Loader.
  1156. //
  1157. BlpClearScreen();
  1158. #if 1
  1159. #ifdef UNICODE
  1160. BlPrint(OsLoaderVersionW);
  1161. #else
  1162. BlPrint(OsLoaderVersion);
  1163. #endif
  1164. #else
  1165. strcpy(&OutputBuffer[0], OsLoaderVersion);
  1166. ArcWrite(BlConsoleOutDeviceId,
  1167. &OutputBuffer[0],
  1168. strlen(&OutputBuffer[0]),
  1169. &Count);
  1170. #endif
  1171. //
  1172. // Initialize the memory descriptor list, the OS loader heap, and the
  1173. // OS loader parameter block.
  1174. //
  1175. #if 0
  1176. //
  1177. // bugbug: we already do this in SuMain()
  1178. //
  1179. BlPrint(TEXT("about to BlMemoryInitialize...\r\n"));
  1180. Status = BlMemoryInitialize();
  1181. if (Status != ESUCCESS) {
  1182. BlFatalError(LOAD_HW_MEM_CLASS,
  1183. DIAG_BL_MEMORY_INIT,
  1184. LOAD_HW_MEM_ACT);
  1185. goto LoadFailed;
  1186. }
  1187. #endif
  1188. //
  1189. // Initialize the network.
  1190. //
  1191. NetGetRebootParameters(&NetRebootParameter, NetRebootFile, NULL, NULL, NULL, NULL, NULL, TRUE);
  1192. DPRINT( OSC, ("Initializing the network\n") );
  1193. Status = NetInitialize();
  1194. if (Status != ESUCCESS) {
  1195. return Status;
  1196. }
  1197. #ifndef EFI
  1198. //
  1199. // Get ourselves a UDP port.
  1200. //
  1201. LocalPort = UdpAssignUnicastPort();
  1202. DPRINT( OSC, ("Using port %x\n", LocalPort) );
  1203. #endif
  1204. //
  1205. // Initialize the security package.
  1206. //
  1207. DPRINT( OSC, ("Initializing security package\n") );
  1208. SecStatus = EnumerateSecurityPackagesA( &PackageCount, &PackageInfo );
  1209. if (SecStatus == SEC_E_OK) {
  1210. DPRINT( OSC, ("NTLMSSP: PackageCount: %ld\n", PackageCount) );
  1211. DPRINT( OSC, ("Name: %s Comment: %s\n", PackageInfo->Name, PackageInfo->Comment) );
  1212. DPRINT( OSC, ("Cap: %ld Version: %ld RPCid: %ld MaxToken: %ld\n\n",
  1213. PackageInfo->fCapabilities,
  1214. PackageInfo->wVersion,
  1215. PackageInfo->wRPCID,
  1216. PackageInfo->cbMaxToken) );
  1217. } else {
  1218. DPRINT( ERROR, ("NTLMSSP: Enumerate failed, %d\n", SecStatus) );
  1219. }
  1220. //
  1221. // Get info about the security packages.
  1222. //
  1223. SecStatus = QuerySecurityPackageInfoA( NTLMSP_NAME_A, &PackageInfo );
  1224. if ( SecStatus != SEC_E_OK ) {
  1225. DPRINT( ERROR, ("QuerySecurityPackageInfo failed %d", SecStatus) );
  1226. return SecStatus;
  1227. }
  1228. //
  1229. // Detect the Hal type
  1230. //
  1231. if (!BlDetectHal()) {
  1232. //
  1233. // just fall through if it fails, it's not the end of the world
  1234. //
  1235. HalType[0] = '\0';
  1236. HalDescription[0] = '\0';
  1237. DPRINT( ERROR, ("BlDetectHal failed.\n") );
  1238. }
  1239. //
  1240. // Process screens, loggons, etc... we come back after a "REBOOT"
  1241. // was indicated.
  1242. //
  1243. BlMainLoop( );
  1244. //
  1245. // Inform boot debugger that the boot phase is complete.
  1246. //
  1247. // N.B. This is x86 only for now.
  1248. //
  1249. #if defined(_X86_)
  1250. DbgUnLoadImageSymbols(NULL, (PVOID)-1, 0);
  1251. #endif
  1252. #ifdef EFI
  1253. BlEfiSetAttribute( DEFATT );
  1254. #else
  1255. BlpSendEscape(";0;37;40m");
  1256. #endif
  1257. BlpSetInverseMode( FALSE );
  1258. BlpClearScreen();
  1259. BlPrint(TEXT("Waiting for reboot...\n"));
  1260. #ifndef EFI
  1261. HW_CURSOR(1,0);
  1262. #endif
  1263. if (DoSoftReboot) {
  1264. Status = NetSoftReboot(
  1265. NextBootfile,
  1266. NetRebootParameter,
  1267. NULL, // reboot file
  1268. SifFile,
  1269. UserName,
  1270. DomainName,
  1271. Password,
  1272. AdministratorPassword); // this only returns on an error
  1273. } else {
  1274. DPRINT( OSC, ("calling ArcRestart()\n") );
  1275. ArcRestart();
  1276. }
  1277. BlPrint(TEXT("Reboot failed... Press ALT+CTL+DEL to reboot.\n"));
  1278. //LoadFailed:
  1279. return Status;
  1280. }
  1281. //
  1282. //
  1283. //
  1284. ARC_STATUS
  1285. BlProcessLogin(
  1286. PCHAR OutgoingMessage )
  1287. {
  1288. //
  1289. // If this is the login screen, remember some of the inputs
  1290. // ourselves.
  1291. //
  1292. ARC_STATUS Status;
  1293. UNICODE_STRING TmpNtPassword;
  1294. PCHAR AtSign;
  1295. int i;
  1296. TraceFunc("BlProcessLogin( )\n");
  1297. //
  1298. // We could be trying to log another person in so log off the
  1299. // current user.
  1300. //
  1301. if ( LoggedIn == TRUE )
  1302. {
  1303. BlDoLogoff();
  1304. LoggedIn = FALSE;
  1305. }
  1306. DPRINT( OSC, ("Login info: Domain <%s>, User <%s>, Password<%s>\n", DomainName, UserName, "*") );
  1307. //
  1308. // Do a quick conversion of the password to Unicode.
  1309. //
  1310. TmpNtPassword.Length = strlen(Password) * sizeof(WCHAR);
  1311. TmpNtPassword.MaximumLength = sizeof(UnicodePassword);
  1312. TmpNtPassword.Buffer = UnicodePassword;
  1313. for (i = 0; i < sizeof(Password); i++) {
  1314. UnicodePassword[i] = (WCHAR)(Password[i]);
  1315. }
  1316. BlOwfPassword(Password, &TmpNtPassword, LmOwfPassword, NtOwfPassword);
  1317. Status = BlDoLogin( );
  1318. DPRINT( OSC, ("Login returned: %x\n", Status) );
  1319. return Status;
  1320. }
  1321. //
  1322. //
  1323. //
  1324. VOID
  1325. BlMainLoop(
  1326. )
  1327. {
  1328. ULONG SequenceNumber;
  1329. int len;
  1330. PUCHAR psz;
  1331. PUCHAR pch;
  1332. UCHAR OutgoingMessage[1024];
  1333. PUCHAR IncomingMessage;
  1334. TraceFunc("BlMainLoop( )\n");
  1335. //
  1336. // These all point into our single outgoing and incoming buffers.
  1337. //
  1338. OutgoingSignedMessage = (SIGNED_PACKET UNALIGNED *)OutgoingMessageBuffer;
  1339. IncomingSignedMessage = (SIGNED_PACKET UNALIGNED *)IncomingMessageBuffer;
  1340. DomainName[0] = '\0';
  1341. UserName[0] = '\0';
  1342. Password[0] = '\0';
  1343. SequenceNumber = 0;
  1344. //
  1345. // Ask the server for the initial screen
  1346. //
  1347. #if defined(REMOTE_BOOT)
  1348. if (NetRebootParameter == NET_REBOOT_WRITE_SECRET_ONLY) {
  1349. strcpy( OutgoingMessage, "LOGIN\n" ); // first screen is logon.
  1350. } else
  1351. #endif // defined(REMOTE_BOOT)
  1352. {
  1353. strcpy( OutgoingMessage, "\n" ); // first screen name is <blank>.
  1354. }
  1355. IncomingMessage = IncomingSignedMessage->Data;
  1356. SpecialAction = ACTION_NOP;
  1357. while ( SpecialAction != ACTION_REBOOT )
  1358. {
  1359. CHAR LastKey;
  1360. //
  1361. // Retrieve next screen
  1362. //
  1363. #if 0
  1364. IF_DEBUG(OSC) {
  1365. DPRINT( OSC, ("Dumping OutgoingingMessage buffer:\r\n" ) );
  1366. DumpBuffer( (PVOID)OutgoingMessage, 256 );
  1367. }
  1368. #endif
  1369. if (!BlRetrieveScreen( &SequenceNumber, OutgoingMessage, IncomingMessage ) )
  1370. break;
  1371. //
  1372. // Process the screen and get user input
  1373. //
  1374. LastKey = BlProcessScreen( IncomingMessage, OutgoingMessage );
  1375. DPRINT( OSC, ("LastKey = 0x%02x\nAction = %u\nResults:\n%s<EOM>\n",
  1376. LastKey, SpecialAction, OutgoingMessage) );
  1377. switch ( SpecialAction )
  1378. {
  1379. case ACTION_LOGIN:
  1380. DPRINT( OSC, ("[SpecialAction] Logging in\n") );
  1381. if ( STATUS_SUCCESS == BlProcessLogin( OutgoingMessage ) )
  1382. {
  1383. #if defined(REMOTE_BOOT)
  1384. //
  1385. // If we are only logging on for machine replacement, then request
  1386. // the GETCREATE screen -- we will reboot once we get the
  1387. // response.
  1388. //
  1389. if (NetRebootParameter == NET_REBOOT_WRITE_SECRET_ONLY) {
  1390. //
  1391. // Find the current screen name (probably "CHOICE") and
  1392. // replace it with "GETCREATE").
  1393. //
  1394. ULONG OriginalLen = strlen(OutgoingMessage) + 1; // include the '\0'
  1395. ULONG CurrentScreenLen = (strchr(OutgoingMessage, '\n') - OutgoingMessage);
  1396. ULONG GetCreateLen = strlen("GETCREATE");
  1397. if (CurrentScreenLen != GetCreateLen) {
  1398. memmove(OutgoingMessage + GetCreateLen,
  1399. OutgoingMessage + CurrentScreenLen,
  1400. OriginalLen - CurrentScreenLen);
  1401. }
  1402. memcpy(OutgoingMessage, "GETCREATE", GetCreateLen);
  1403. }
  1404. #endif // defined(REMOTE_BOOT)
  1405. DPRINT( OSC, ("Validate Results are still the same:\n%s<EOM>\n",
  1406. OutgoingMessage) );
  1407. LoggedIn = TRUE;
  1408. SequenceNumber = 0;
  1409. //
  1410. // If the welcome screen was processed, then add some extra
  1411. // outgoing predetermined variables.
  1412. //
  1413. // Add NIC address
  1414. //
  1415. // Convert NIC address 0x00a0c968041c to a string
  1416. //
  1417. //
  1418. // Make sure the outgoing has a \n after the screen name
  1419. //
  1420. if ( OutgoingMessage[ strlen(OutgoingMessage) - 1 ] != '\n' )
  1421. {
  1422. strcat( OutgoingMessage, "\n" );
  1423. }
  1424. strcat( OutgoingMessage, "MAC=" );
  1425. len = 6;
  1426. psz = &OutgoingMessage[ strlen( OutgoingMessage ) ];
  1427. pch = (PCHAR) NetLocalHardwareAddress;
  1428. while (len--) {
  1429. UCHAR c = *(pch++);
  1430. *(psz++) = rghex [(c >> 4) & 0x0F] ;
  1431. *(psz++) = rghex [c & 0x0F];
  1432. }
  1433. *psz = '\0'; // terminate
  1434. //
  1435. // Add the Guid
  1436. //
  1437. pch = NULL;
  1438. len = 0;
  1439. GetGuid(&pch, &len);
  1440. if ((len != 0) && (pch!=NULL)) {
  1441. strcat( OutgoingMessage, "\nGUID=" );
  1442. psz = &OutgoingMessage[ strlen( OutgoingMessage ) ];
  1443. while (len--) {
  1444. UCHAR c = *(pch++);
  1445. *(psz++) = rghex [(c >> 4) & 0x0F] ;
  1446. *(psz++) = rghex [c & 0x0F];
  1447. }
  1448. *psz = '\0'; // terminate
  1449. }
  1450. //
  1451. // if we detected the HAL, specify it here
  1452. //
  1453. if (HalType[0] != '\0') {
  1454. strcat( OutgoingMessage, "\nHALTYPE=" );
  1455. strcat( OutgoingMessage, HalType );
  1456. if (HalDescription[0] != '\0') {
  1457. strcat( OutgoingMessage, "\nHALTYPEDESCRIPTION=" );
  1458. strcat( OutgoingMessage, HalDescription );
  1459. }
  1460. }
  1461. //
  1462. // Add the machine type
  1463. //
  1464. #if defined(_ALPHA_)
  1465. strcat( OutgoingMessage, "\nMACHINETYPE=Alpha\n" ); // add machinetype
  1466. #else
  1467. #if defined(_IA64_)
  1468. strcat( OutgoingMessage, "\nMACHINETYPE=ia64\n" ); // add machinetype
  1469. #else // INTEL
  1470. strcat( OutgoingMessage, "\nMACHINETYPE=i386\n" ); // add machinetype
  1471. #endif // _IA64_
  1472. #endif
  1473. #if defined(REMOTE_BOOT)
  1474. //
  1475. // If we are diskless, tell BINL.
  1476. //
  1477. if (BlIsDiskless()) {
  1478. strcat( OutgoingMessage, "DISKLESS=1\n" );
  1479. }
  1480. #endif // defined(REMOTE_BOOT)
  1481. //
  1482. // Tell BINL to verify the domain, because otherwise
  1483. // the SSPI package on the server will allow the login
  1484. // to succeed with an invalid domain. BINL will delete
  1485. // this variable from the client state on the server
  1486. // once it does the domain check.
  1487. //
  1488. strcat( OutgoingMessage, "CHECKDOMAIN=1\n" );
  1489. }
  1490. else
  1491. {
  1492. //
  1493. // Goto the Login Error Screen which is
  1494. // 00004e28.
  1495. //
  1496. strcpy( OutgoingMessage, "00004e28\n" );
  1497. LoggedIn = FALSE;
  1498. }
  1499. break;
  1500. }
  1501. }
  1502. //
  1503. // If we logged on successfully, then log off.
  1504. //
  1505. if (LoggedIn)
  1506. {
  1507. BlDoLogoff();
  1508. }
  1509. }
  1510. //
  1511. //
  1512. //
  1513. ULONG
  1514. BlDoLogin ( )
  1515. {
  1516. ARC_STATUS Status;
  1517. SECURITY_STATUS SecStatus;
  1518. SecBufferDesc NegotiateDesc;
  1519. SecBuffer NegotiateBuffer;
  1520. SecBufferDesc ChallengeDesc;
  1521. SecBuffer ChallengeBuffer;
  1522. SecBufferDesc AuthenticateDesc;
  1523. SecBuffer AuthenticateBuffer;
  1524. ULONG ContextAttributes;
  1525. SEC_WINNT_AUTH_IDENTITY_A AuthIdentity;
  1526. TimeStamp Lifetime;
  1527. PCHAR ResultSigs[2];
  1528. UCHAR FlipServerList[MAX_FLIP_SERVER_COUNT * 4];
  1529. ULONG FlipServerCount;
  1530. ULONG CurFlipServer;
  1531. UCHAR OwfPasswords[LM_OWF_PASSWORD_SIZE + NT_OWF_PASSWORD_SIZE];
  1532. PLOGIN_PACKET OutgoingLoginMessage;
  1533. PLOGIN_PACKET IncomingLoginMessage;
  1534. OutgoingLoginMessage = (LOGIN_PACKET *) OutgoingMessageBuffer;
  1535. IncomingLoginMessage = (LOGIN_PACKET *) IncomingMessageBuffer;
  1536. TraceFunc("BlDoLogin( )\n");
  1537. //
  1538. // Delete both contexts if needed.
  1539. //
  1540. if (ClientContextHandleValid) {
  1541. SecStatus = DeleteSecurityContext( &ClientContextHandle );
  1542. ClientContextHandleValid = FALSE;
  1543. }
  1544. if (CredentialHandleValid) {
  1545. SecStatus = FreeCredentialsHandle( &CredentialHandle );
  1546. CredentialHandleValid = FALSE;
  1547. }
  1548. //
  1549. // Acquire a credential handle for the client side. The password
  1550. // we supply is the LM OWF password and the NT OWF password
  1551. // concatenated together.
  1552. //
  1553. memcpy( OwfPasswords, LmOwfPassword, LM_OWF_PASSWORD_SIZE );
  1554. memcpy( OwfPasswords+LM_OWF_PASSWORD_SIZE, NtOwfPassword, NT_OWF_PASSWORD_SIZE );
  1555. RtlZeroMemory( &AuthIdentity, sizeof(AuthIdentity) );
  1556. AuthIdentity.Domain = DomainName;
  1557. AuthIdentity.User = UserName;
  1558. AuthIdentity.Password = OwfPasswords;
  1559. #if 0
  1560. IF_DEBUG(OSC) {
  1561. DPRINT( OSC, ("Dumping OwfPasswords:\r\n") );
  1562. DumpBuffer( AuthIdentity.Password, LM_OWF_PASSWORD_SIZE+NT_OWF_PASSWORD_SIZE );
  1563. }
  1564. #endif
  1565. DPRINT( OSC, ("About to AcquireCredentialsHandle\n") );
  1566. SecStatus = AcquireCredentialsHandleA(
  1567. NULL, // New principal
  1568. NTLMSP_NAME_A, // Package Name
  1569. SECPKG_CRED_OUTBOUND | SECPKG_CRED_OWF_PASSWORD,
  1570. NULL,
  1571. &AuthIdentity,
  1572. NULL,
  1573. NULL,
  1574. &CredentialHandle,
  1575. &Lifetime );
  1576. if ( SecStatus != SEC_E_OK ) {
  1577. DPRINT( ERROR, ("AcquireCredentialsHandle failed: %s ", SecStatus) );
  1578. return SecStatus;
  1579. }
  1580. DPRINT( OSC, ("CredentialHandle: 0x%lx 0x%lx ",
  1581. CredentialHandle.dwLower, CredentialHandle.dwUpper) );
  1582. CredentialHandleValid = TRUE;
  1583. //
  1584. // Get the NegotiateMessage (ClientSide)
  1585. //
  1586. NegotiateDesc.ulVersion = 0;
  1587. NegotiateDesc.cBuffers = 1;
  1588. NegotiateDesc.pBuffers = &NegotiateBuffer;
  1589. NegotiateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1590. NegotiateBuffer.BufferType = SECBUFFER_TOKEN;
  1591. NegotiateBuffer.pvBuffer = OutgoingLoginMessage->Data;
  1592. SecStatus = InitializeSecurityContextA(
  1593. &CredentialHandle,
  1594. NULL, // No Client context yet
  1595. NULL, // No target name needed
  1596. ISC_REQ_SEQUENCE_DETECT,
  1597. 0, // Reserved 1
  1598. SECURITY_NATIVE_DREP,
  1599. NULL, // No initial input token
  1600. 0, // Reserved 2
  1601. &ClientContextHandle,
  1602. &NegotiateDesc,
  1603. &ContextAttributes,
  1604. &Lifetime );
  1605. if ( (SecStatus != SEC_E_OK) && (SecStatus != SEC_I_CONTINUE_NEEDED) ) {
  1606. DPRINT( ERROR, ("InitializeSecurityContext (negotiate): %d" , SecStatus) );
  1607. return SecStatus;
  1608. }
  1609. ClientContextHandleValid = TRUE;
  1610. #if 0
  1611. IF_DEBUG(OSC) {
  1612. KdPrint(( "\n\nNegotiate Message:\n" ));
  1613. KdPrint(( "ClientContextHandle: 0x%lx 0x%lx Attributes: 0x%lx ",
  1614. ClientContextHandle.dwLower, ClientContextHandle.dwUpper,
  1615. ContextAttributes ));
  1616. PrintTime( "Lifetime: ", Lifetime );
  1617. DumpBuffer( NegotiateBuffer.pvBuffer, NegotiateBuffer.cbBuffer );
  1618. }
  1619. #endif
  1620. //
  1621. // Send the negotiate buffer to the server and wait for a response.
  1622. //
  1623. memcpy(OutgoingLoginMessage->Signature, NegotiateSignature, 4);
  1624. OutgoingLoginMessage->Length = NegotiateBuffer.cbBuffer;
  1625. TraceFunc("");
  1626. DPRINT( OSC, ("Sending NEG...\n") );
  1627. ResultSigs[0] = ChallengeSignature;
  1628. ResultSigs[1] = NegativeAckSignature;
  1629. #if 0
  1630. IF_DEBUG(OSC) {
  1631. KdPrint(( "\n\nNegotiate Message Outgoing Packet:\n" ));
  1632. DumpBuffer( OutgoingLoginMessage, NegotiateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET );
  1633. }
  1634. #endif
  1635. Status = UdpSendAndReceive(
  1636. OutgoingLoginMessage,
  1637. NegotiateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET,
  1638. NetServerIpAddress,
  1639. BINL_PORT,
  1640. 5, // retry count
  1641. IncomingLoginMessage,
  1642. INCOMING_MESSAGE_LENGTH,
  1643. &RemoteHost,
  1644. &RemotePort,
  1645. 2, // receive timeout
  1646. 2, // number of signatures
  1647. ResultSigs, // signature we are looking for
  1648. 0); // sequence number (0 means don't check)
  1649. if ( !NT_SUCCESS(Status) ) {
  1650. DPRINT( ERROR, ("UdpSendAndReceive status is %x\n", Status) );
  1651. return Status;
  1652. }
  1653. //
  1654. // If the response was a NAK, then fail immediately.
  1655. //
  1656. if (memcmp(IncomingLoginMessage->Signature, NegativeAckSignature, 4) == 0) {
  1657. DPRINT( ERROR, ("Received NAK from server\n") );
  1658. return STATUS_LOGON_FAILURE;
  1659. }
  1660. #if 0
  1661. IF_DEBUG(OSC) {
  1662. KdPrint(( "\n\nNegotiate Message Incoming Packet: %d %d %d %d\n",
  1663. IncomingLoginMessage->Data,
  1664. IncomingLoginMessage->Length,
  1665. IncomingLoginMessage->Signature,
  1666. IncomingLoginMessage->Status ));
  1667. DumpBuffer( IncomingLoginMessage->Data, IncomingLoginMessage->Length );
  1668. }
  1669. #endif
  1670. //
  1671. // Get the AuthenticateMessage (ClientSide)
  1672. //
  1673. AuthenticateDesc.ulVersion = 0;
  1674. AuthenticateDesc.cBuffers = 1;
  1675. AuthenticateDesc.pBuffers = &AuthenticateBuffer;
  1676. AuthenticateBuffer.cbBuffer = PackageInfo->cbMaxToken;
  1677. AuthenticateBuffer.BufferType = SECBUFFER_TOKEN;
  1678. AuthenticateBuffer.pvBuffer = OutgoingLoginMessage->Data;
  1679. ChallengeDesc.ulVersion = 0;
  1680. ChallengeDesc.cBuffers = 1;
  1681. ChallengeDesc.pBuffers = &ChallengeBuffer;
  1682. ChallengeBuffer.cbBuffer = IncomingLoginMessage->Length;
  1683. ChallengeBuffer.BufferType = SECBUFFER_TOKEN | SECBUFFER_READONLY;
  1684. ChallengeBuffer.pvBuffer = IncomingLoginMessage->Data;
  1685. DPRINT( OSC, ("About to call InitializeSecurityContext\n") );
  1686. SecStatus = InitializeSecurityContextA(
  1687. NULL,
  1688. &ClientContextHandle,
  1689. NULL, // No target name needed
  1690. 0,
  1691. 0, // Reserved 1
  1692. SECURITY_NATIVE_DREP,
  1693. &ChallengeDesc,
  1694. 0, // Reserved 2
  1695. &ClientContextHandle,
  1696. &AuthenticateDesc,
  1697. &ContextAttributes,
  1698. &Lifetime );
  1699. if ( (SecStatus != SEC_E_OK) ) {
  1700. DPRINT( OSC, ("InitializeSecurityContext (Authenticate): %d\n", SecStatus) );
  1701. return SecStatus;
  1702. }
  1703. //
  1704. // Send the authenticate buffer to the server and wait for the response.
  1705. //
  1706. if (AllowFlip) {
  1707. memcpy(OutgoingLoginMessage->Signature, AuthenticateSignature, 4);
  1708. } else {
  1709. memcpy(OutgoingLoginMessage->Signature, AuthenticateFlippedSignature, 4);
  1710. }
  1711. OutgoingLoginMessage->Length = AuthenticateBuffer.cbBuffer;
  1712. TraceFunc("");
  1713. DPRINT( OSC, ("Sending AUTH...\n") );
  1714. #if 0
  1715. IF_DEBUG(OSC) {
  1716. KdPrint(( "\n\nAuth Message Outgoing Packet:\n" ));
  1717. DumpBuffer( OutgoingLoginMessage, AuthenticateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET );
  1718. }
  1719. #endif
  1720. ResultSigs[0] = ResultSignature;
  1721. Status = UdpSendAndReceive(
  1722. OutgoingLoginMessage,
  1723. AuthenticateBuffer.cbBuffer + LOGIN_PACKET_DATA_OFFSET,
  1724. NetServerIpAddress,
  1725. BINL_PORT,
  1726. 10, // retry count
  1727. IncomingLoginMessage,
  1728. INCOMING_MESSAGE_LENGTH,
  1729. &RemoteHost,
  1730. &RemotePort,
  1731. 5, // receive timeout
  1732. 1, // number of signatures we are looking for
  1733. ResultSigs, // signatures we look for
  1734. 0); // sequence number (0 means don't check)
  1735. if ( !NT_SUCCESS(Status) ) {
  1736. DPRINT( ERROR, ("UdpSendAndReceive status is %x\n", Status) );
  1737. return Status;
  1738. }
  1739. #if 0
  1740. IF_DEBUG(OSC) {
  1741. KdPrint(( "\n\nAuthenticateBuffer Message Incoming Packet: %d %d %d %d\n",
  1742. IncomingLoginMessage->Data,
  1743. IncomingLoginMessage->Length,
  1744. IncomingLoginMessage->Signature,
  1745. IncomingLoginMessage->Status ));
  1746. DumpBuffer( IncomingLoginMessage->Data, IncomingLoginMessage->Length );
  1747. }
  1748. #endif
  1749. if (memcmp(IncomingLoginMessage->Signature, ResultSignature, 4) == 0) {
  1750. //
  1751. // Login has completed/failed, check status.
  1752. //
  1753. if ( IncomingLoginMessage->Status == STATUS_SUCCESS) {
  1754. TraceFunc("Login successful\n");
  1755. //
  1756. // If we are allowed to be flipped, then check if there is a
  1757. // flip list in the response, and if so try to log in to each one
  1758. // until we succeed at one.
  1759. //
  1760. if (AllowFlip) {
  1761. AllowFlip = FALSE; // once we have been flipped, don't do it again
  1762. if (IncomingLoginMessage->Length > 4) {
  1763. FlipServerCount = (IncomingLoginMessage->Length - 4) / 4;
  1764. if (FlipServerCount > MAX_FLIP_SERVER_COUNT) {
  1765. FlipServerCount = MAX_FLIP_SERVER_COUNT;
  1766. }
  1767. memcpy(
  1768. FlipServerList,
  1769. (PUCHAR)(&IncomingLoginMessage->Status) + sizeof(ULONG),
  1770. FlipServerCount * 4
  1771. );
  1772. //
  1773. // If the first server in the list is our current server,
  1774. // then don't flip.
  1775. //
  1776. if (*(ULONG *)FlipServerList == NetServerIpAddress) {
  1777. DPRINT( OSC, ("Not flipping, first server is the same\n") );
  1778. return STATUS_SUCCESS;
  1779. }
  1780. DPRINT( OSC, ("Trying %d flip servers\n", FlipServerCount) );
  1781. for (CurFlipServer = 0; CurFlipServer < FlipServerCount; ++CurFlipServer) {
  1782. //
  1783. // Logoff the previous server connection.
  1784. //
  1785. BlDoLogoff();
  1786. //
  1787. // Now connect to the new server.
  1788. //
  1789. NetServerIpAddress = *(ULONG *)(&FlipServerList[CurFlipServer*4]);
  1790. DPRINT( OSC, ("Trying to flip to server %lx\n", NetServerIpAddress) );
  1791. //
  1792. // We will only recurse once because *AllowFlip is now FALSE.
  1793. //
  1794. Status = BlDoLogin( );
  1795. DPRINT( OSC, ("Flip server login returned %lx\n", Status) );
  1796. if (Status == STATUS_SUCCESS) {
  1797. return Status;
  1798. }
  1799. }
  1800. //
  1801. // We have tried each flip server in turn and failed!
  1802. //
  1803. TraceFunc("ERROR - We have tried each flip server in turn and failed!\n");
  1804. return STATUS_NO_LOGON_SERVERS;
  1805. }
  1806. }
  1807. } else {
  1808. DPRINT( ERROR, ("ERROR - could not login, %x\n", IncomingLoginMessage->Status) );
  1809. }
  1810. return IncomingLoginMessage->Status;
  1811. } else {
  1812. //
  1813. // Shouldn't get this because we check signatures!!
  1814. //
  1815. DPRINT( ERROR, ("Got wrong message, expecting success or failure\n") );
  1816. return STATUS_UNEXPECTED_NETWORK_ERROR;
  1817. }
  1818. }
  1819. VOID
  1820. BlDoLogoff (
  1821. VOID
  1822. )
  1823. {
  1824. ARC_STATUS Status;
  1825. TraceFunc("BlDoLogoff( )\n");
  1826. //
  1827. // Send a logoff message to the server -- for the moment this is
  1828. // just sent once and not acked, since if it is lost the server
  1829. // will eventually timeout.
  1830. //
  1831. memcpy(OutgoingSignedMessage->Signature, LogoffSignature, 4);
  1832. OutgoingSignedMessage->Length = 0;
  1833. Status = UdpSend(
  1834. OutgoingSignedMessage,
  1835. SIGNED_PACKET_DATA_OFFSET,
  1836. NetServerIpAddress,
  1837. BINL_PORT);
  1838. if ( !NT_SUCCESS(Status) ) {
  1839. DPRINT( ERROR, ("UdpSend status is %x\n", Status) );
  1840. }
  1841. }
  1842. VOID
  1843. BlOutputLoadMessage (
  1844. IN PCHAR DeviceName,
  1845. IN PCHAR FileName,
  1846. IN PTCHAR FileDescription OPTIONAL
  1847. )
  1848. /*++
  1849. Routine Description:
  1850. This routine outputs a loading message to the console output device.
  1851. Arguments:
  1852. DeviceName - Supplies a pointer to a zero terminated device name.
  1853. FileName - Supplies a pointer to a zero terminated file name.
  1854. FileDescription - Friendly name of the file in question.
  1855. Return Value:
  1856. None.
  1857. --*/
  1858. {
  1859. ULONG Count;
  1860. CHAR OutputBuffer[256];
  1861. PTCHAR pOutputBuffer;
  1862. #ifdef UNICODE
  1863. WCHAR OutputBufferW[256];
  1864. UNICODE_STRING uString;
  1865. ANSI_STRING aString;
  1866. pOutputBuffer = OutputBufferW;
  1867. #else
  1868. pOutputBuffer = OutputBuffer;
  1869. #endif
  1870. UNREFERENCED_PARAMETER( FileDescription );
  1871. //
  1872. // Construct and output loading file message.
  1873. //
  1874. if (!BlOutputDots) {
  1875. strcpy(&OutputBuffer[0], " ");
  1876. strcat(&OutputBuffer[0], DeviceName);
  1877. strcat(&OutputBuffer[0], FileName);
  1878. strcat(&OutputBuffer[0], "\r\n");
  1879. } else {
  1880. strcpy(&OutputBuffer[0],".");
  1881. }
  1882. #if 0
  1883. BlLog((LOG_LOGFILE,OutputBuffer));
  1884. #endif
  1885. #ifdef UNICODE
  1886. RtlInitAnsiString( &aString, OutputBuffer);
  1887. uString.MaximumLength = sizeof(OutputBufferW);
  1888. uString.Buffer = OutputBufferW;
  1889. RtlAnsiStringToUnicodeString( &uString, &aString, FALSE );
  1890. #endif
  1891. ArcWrite(BlConsoleOutDeviceId,
  1892. pOutputBuffer,
  1893. _tcslen(pOutputBuffer),
  1894. &Count);
  1895. return;
  1896. }
  1897. BOOLEAN
  1898. BlGetDriveSignature(
  1899. IN PCHAR Name,
  1900. OUT PULONG Signature
  1901. )
  1902. /*++
  1903. Routine Description:
  1904. This routine gets the NTFT disk signature for a specified partition or
  1905. path.
  1906. Arguments:
  1907. Name - Supplies the arcname of the partition or drive.
  1908. Signature - Returns the NTFT disk signature for the drive.
  1909. Return Value:
  1910. TRUE - success, Signature will be filled in.
  1911. FALSE - failed, Signature will not be filled in.
  1912. --*/
  1913. {
  1914. UCHAR SectorBuffer[512+256];
  1915. CHAR DiskName[256];
  1916. ULONG DiskId;
  1917. PCHAR p;
  1918. ARC_STATUS Status;
  1919. ULONG Count;
  1920. LARGE_INTEGER SeekValue;
  1921. //
  1922. // Generate the arcname ("...partition(0)") for the raw disk device
  1923. // where the boot partition is, so we can read the MBR.
  1924. //
  1925. strcpy(DiskName, Name);
  1926. p=DiskName;
  1927. while (*p != '\0') {
  1928. if (_strnicmp(p, "partition(",10) == 0) {
  1929. break;
  1930. }
  1931. ++p;
  1932. }
  1933. if (*p != '\0') {
  1934. strcpy(p,"partition(0)");
  1935. }
  1936. Status = ArcOpen(DiskName,ArcOpenReadOnly, &DiskId);
  1937. if (Status!=ESUCCESS) {
  1938. return(FALSE);
  1939. }
  1940. //
  1941. // Read the first sector of the physical drive
  1942. //
  1943. SeekValue.QuadPart = 0;
  1944. Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
  1945. if (Status==ESUCCESS) {
  1946. Status = ArcRead(DiskId,
  1947. ALIGN_BUFFER(SectorBuffer),
  1948. 512,
  1949. &Count);
  1950. }
  1951. ArcClose(DiskId);
  1952. if (Status!=ESUCCESS) {
  1953. return(FALSE);
  1954. }
  1955. //
  1956. // copy NTFT signature.
  1957. //
  1958. *Signature = ((PULONG)SectorBuffer)[PARTITION_TABLE_OFFSET/2-1];
  1959. return(TRUE);
  1960. }
  1961. #ifndef EFI
  1962. VOID
  1963. BlBadFileMessage(
  1964. IN PCHAR BadFileName
  1965. )
  1966. /*++
  1967. Routine Description:
  1968. This function displays the error message for a missing or incorrect
  1969. critical file.
  1970. Arguments:
  1971. BadFileName - Supplies the name of the file that is missing or
  1972. corrupt.
  1973. Return Value:
  1974. None.
  1975. --*/
  1976. {
  1977. ULONG Count;
  1978. PCHAR Text;
  1979. ArcWrite(BlConsoleOutDeviceId,
  1980. "\r\n",
  1981. strlen("\r\n"),
  1982. &Count);
  1983. Text = BlFindMessage(LOAD_SW_MIS_FILE_CLASS);
  1984. if (Text != NULL) {
  1985. ArcWrite(BlConsoleOutDeviceId,
  1986. Text,
  1987. strlen(Text),
  1988. &Count);
  1989. }
  1990. ArcWrite(BlConsoleOutDeviceId,
  1991. BadFileName,
  1992. strlen(BadFileName),
  1993. &Count);
  1994. ArcWrite(BlConsoleOutDeviceId,
  1995. "\r\n\r\n",
  1996. strlen("\r\n\r\n"),
  1997. &Count);
  1998. Text = BlFindMessage(LOAD_SW_FILE_REST_ACT);
  1999. if (Text != NULL) {
  2000. ArcWrite(BlConsoleOutDeviceId,
  2001. Text,
  2002. strlen(Text),
  2003. &Count);
  2004. }
  2005. }
  2006. VOID
  2007. BlFatalError(
  2008. IN ULONG ClassMessage,
  2009. IN ULONG DetailMessage,
  2010. IN ULONG ActionMessage
  2011. )
  2012. /*++
  2013. Routine Description:
  2014. This function looks up messages to display at a error condition.
  2015. It attempts to locate the string in the resource section of the
  2016. osloader. If that fails, it prints a numerical error code.
  2017. The only time it should print a numerical error code is if the
  2018. resource section could not be located. This will only happen
  2019. on ARC machines where boot fails before the osloader.exe file
  2020. can be opened.
  2021. Arguments:
  2022. ClassMessage - General message that describes the class of
  2023. problem.
  2024. DetailMessage - Detailed description of what caused problem
  2025. ActionMessage - Message that describes a course of action
  2026. for user to take.
  2027. Return Value:
  2028. none
  2029. --*/
  2030. {
  2031. PCHAR Text;
  2032. CHAR Buffer[40];
  2033. ULONG Count;
  2034. ArcWrite(BlConsoleOutDeviceId,
  2035. "\r\n",
  2036. strlen("\r\n"),
  2037. &Count);
  2038. //
  2039. // Remove any remains from the last known good message.
  2040. //
  2041. BlClearToEndOfScreen();
  2042. Text = BlFindMessage(ClassMessage);
  2043. if (Text == NULL) {
  2044. sprintf(Buffer,"%08lx\r\n",ClassMessage);
  2045. Text = Buffer;
  2046. }
  2047. ArcWrite(BlConsoleOutDeviceId,
  2048. Text,
  2049. strlen(Text),
  2050. &Count);
  2051. Text = BlFindMessage(DetailMessage);
  2052. if (Text == NULL) {
  2053. sprintf(Buffer,"%08lx\r\n",DetailMessage);
  2054. Text = Buffer;
  2055. }
  2056. ArcWrite(BlConsoleOutDeviceId,
  2057. Text,
  2058. strlen(Text),
  2059. &Count);
  2060. Text = BlFindMessage(ActionMessage);
  2061. if (Text == NULL) {
  2062. sprintf(Buffer,"%08lx\r\n",ActionMessage);
  2063. Text = Buffer;
  2064. }
  2065. ArcWrite(BlConsoleOutDeviceId,
  2066. Text,
  2067. strlen(Text),
  2068. &Count);
  2069. return;
  2070. }
  2071. #endif
  2072. #if defined(REMOTE_BOOT)
  2073. BOOLEAN
  2074. BlIsDiskless(
  2075. VOID
  2076. )
  2077. /*++
  2078. Routine Description:
  2079. This function returns TRUE if a machine is diskless.
  2080. Arguments:
  2081. None.
  2082. Return Value:
  2083. TRUE if the machine is diskless, FALSE otherwise.
  2084. --*/
  2085. {
  2086. ULONG FileId;
  2087. if (BlOpenRawDisk(&FileId) == ESUCCESS) {
  2088. BlCloseRawDisk(FileId);
  2089. return FALSE;
  2090. } else {
  2091. return TRUE;
  2092. }
  2093. }
  2094. #endif // defined(REMOTE_BOOT)
  2095. BOOLEAN
  2096. BlDetectHal(
  2097. VOID
  2098. )
  2099. /*++
  2100. Routine Description:
  2101. This function tries to determine the Hal type for this system.
  2102. It fills in the global "HalType" with the type.
  2103. Arguments:
  2104. None.
  2105. Return Value:
  2106. TRUE if the function successfully detects the hal type.
  2107. --*/
  2108. {
  2109. BOOLEAN Status = FALSE;
  2110. PSTR MachineName,HalName;
  2111. CHAR FileName[128];
  2112. ARC_STATUS AStatus;
  2113. ULONG DontCare;
  2114. //
  2115. // detecting the hal requires that you open up a copy of winnt.sif
  2116. //
  2117. strcpy(FileName, NetBootPath);
  2118. strcat(FileName, "winnt.sif" );
  2119. AStatus = SlInitIniFile( NULL,
  2120. NET_DEVICE_ID,
  2121. FileName,
  2122. &InfFile,
  2123. &WinntSifFile,
  2124. &WinntSifFileLength,
  2125. &DontCare );
  2126. //
  2127. // if it opens successfully, then search for the HAL.
  2128. //
  2129. if (AStatus == ESUCCESS) {
  2130. //
  2131. // do the search for the HAL.
  2132. //
  2133. MachineName = SlDetectHal();
  2134. if (MachineName) {
  2135. //
  2136. // OK, got the hal type, now look in the SIF file for the actual
  2137. // hal name.
  2138. //
  2139. HalName = SlGetIniValue(
  2140. InfFile,
  2141. "Hal",
  2142. MachineName,
  2143. NULL);
  2144. if (HalName) {
  2145. strcpy(HalType, HalName );
  2146. //
  2147. // also get the hal description, which is a "pretty print" version
  2148. // of the hal name
  2149. //
  2150. HalName = SlGetIniValue(
  2151. InfFile,
  2152. "Computer",
  2153. MachineName,
  2154. NULL );
  2155. if (HalName) {
  2156. strcpy(HalDescription, HalName);
  2157. Status = TRUE;
  2158. }
  2159. }
  2160. }
  2161. SpFreeINFBuffer( InfFile );
  2162. }
  2163. return(Status);
  2164. }
  2165. //
  2166. // note well: We stub out these setup functions in oschoice.exe, which are
  2167. // needed so that the hal detection routines can run properly. None of these
  2168. // routines should actually be called.
  2169. //
  2170. VOID
  2171. SlErrorBox(
  2172. IN ULONG MessageId,
  2173. IN ULONG Line,
  2174. IN PCHAR File
  2175. )
  2176. {
  2177. NOTHING;
  2178. }
  2179. VOID
  2180. SlFatalError(
  2181. IN ULONG MessageId,
  2182. ...
  2183. )
  2184. {
  2185. //while(1) {
  2186. NOTHING;
  2187. //};
  2188. }
  2189. VOID
  2190. SlFriendlyError(
  2191. IN ULONG uStatus,
  2192. IN PCHAR pchBadFile,
  2193. IN ULONG uLine,
  2194. IN PCHAR pchCodeFile
  2195. )
  2196. {
  2197. NOTHING;
  2198. }
  2199. VOID
  2200. SlNoMemError(
  2201. IN ULONG Line,
  2202. IN PCHAR File
  2203. )
  2204. {
  2205. SlFatalError(0,Line,File);
  2206. }
  2207. VOID
  2208. SlBadInfLineError(
  2209. IN ULONG Line,
  2210. IN PCHAR INFFile
  2211. )
  2212. {
  2213. SlFatalError(0,Line,INFFile);
  2214. }
  2215. #define SL_KEY_F3 0x03000000
  2216. ULONG
  2217. SlGetChar(
  2218. VOID
  2219. )
  2220. {
  2221. return(SL_KEY_F3);
  2222. }
  2223. VOID
  2224. SlPrint(
  2225. IN PTCHAR FormatString,
  2226. ...
  2227. )
  2228. {
  2229. NOTHING;
  2230. }