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.

2130 lines
48 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. graphics.c
  5. Abstract:
  6. Bitmap display support with text mode for
  7. upgrade. This file has implementation for the
  8. three core abstractions i.e. Bitmap,
  9. Animated bitmap and Graphics Progress bar.
  10. In upgrade graphics mode, we have one primary
  11. graphics thread running in the foreground.
  12. This thread paints the background, creates
  13. animated bitmap(s) and updates a single
  14. progress bar. An upgrade specific callback
  15. is registered which calculates the overall
  16. progress.
  17. Although we are in graphics mode during upgrade,
  18. all the regular textmode output is still
  19. written to a buffer. When we hit some error
  20. or require user intervention we switch back
  21. to the actual textmode and copy all the cached
  22. information to actual video memory. One can
  23. switch to textmode from graphics but not
  24. vice-versa.
  25. Note : For each animated bitmap a separate
  26. thread is started while animating. Using lot
  27. of animated bitmaps can slow down the actual
  28. text mode setup thread.
  29. Author:
  30. Vijay Jayaseelan (vijayj) 01 July 2000
  31. Revision History:
  32. None
  33. --*/
  34. #include "spprecmp.h"
  35. #include "ntddser.h"
  36. #include "bootvid.h"
  37. #include "resource.h"
  38. #include <hdlsblk.h>
  39. #include <hdlsterm.h>
  40. #pragma hdrstop
  41. ////////////////////////////////////////////////////////////////
  42. //
  43. // Global data
  44. //
  45. ////////////////////////////////////////////////////////////////
  46. //
  47. // The primary upgrade graphics thread handle
  48. //
  49. HANDLE GraphicsThreadHandle = NULL;
  50. //
  51. // Variable which indicates that upgrade graphics
  52. // thread needs to be stopped or not
  53. //
  54. BOOLEAN StopGraphicsThread = FALSE;
  55. KSPIN_LOCK GraphicsThreadLock;
  56. //
  57. // Upgrade graphics overall progress indication
  58. //
  59. ULONG ProgressPercentage = 0;
  60. KSPIN_LOCK ProgressLock;
  61. //
  62. // For synchronizing access to VGA memory
  63. //
  64. BOOLEAN InVgaDisplay = FALSE;
  65. KSPIN_LOCK VgaDisplayLock;
  66. ////////////////////////////////////////////////////////////////
  67. //
  68. // Atomic operations to stop main graphics thread
  69. //
  70. ////////////////////////////////////////////////////////////////
  71. static
  72. __inline
  73. BOOLEAN
  74. UpgradeGraphicsThreadGetStop(
  75. VOID
  76. )
  77. /*++
  78. Routine Description:
  79. Finds out whether the primary upgrade graphics thread
  80. needs to be stopped
  81. Arguments:
  82. None.
  83. Return Value:
  84. TRUE or FALSE
  85. --*/
  86. {
  87. KIRQL OldIrql;
  88. BOOLEAN Result;
  89. KeAcquireSpinLock(&GraphicsThreadLock, &OldIrql);
  90. Result = StopGraphicsThread;
  91. KeReleaseSpinLock(&GraphicsThreadLock, OldIrql);
  92. return Result;
  93. }
  94. static
  95. VOID
  96. __inline
  97. UpgradeGraphicsThreadSetStop(
  98. BOOLEAN Stop
  99. )
  100. /*++
  101. Routine Description:
  102. Sets the global synchronized state, indicating
  103. whether to stop the primary graphics thread.
  104. Note : Once the thread is stopped, it can be
  105. restarted.
  106. Arguments:
  107. Stop : Indicates whether to stop the primary graphics
  108. thread or not i.e. TRUE or FALSE
  109. Return Value:
  110. None.
  111. --*/
  112. {
  113. KIRQL OldIrql;
  114. KeAcquireSpinLock(&GraphicsThreadLock, &OldIrql);
  115. StopGraphicsThread = Stop;
  116. KeReleaseSpinLock(&GraphicsThreadLock, OldIrql);
  117. }
  118. ////////////////////////////////////////////////////////////////
  119. //
  120. // Atomic progress bar percentage routines
  121. //
  122. ////////////////////////////////////////////////////////////////
  123. static
  124. __inline
  125. ULONG
  126. GetSetupProgress(
  127. VOID
  128. )
  129. /*++
  130. Routine Description:
  131. Gets the overall progress, in terms of percentage,
  132. for the textmode setup. Since multiple threads
  133. are touching the shared overall progress ULONG
  134. its protected.
  135. Arguments:
  136. None.
  137. Return Value:
  138. The overall progress
  139. --*/
  140. {
  141. ULONG PercentageFill;
  142. KIRQL OldIrql;
  143. KeAcquireSpinLock(&ProgressLock, &OldIrql);
  144. PercentageFill = ProgressPercentage;
  145. KeReleaseSpinLock(&ProgressLock, OldIrql);
  146. return PercentageFill;
  147. }
  148. static
  149. __inline
  150. VOID
  151. SetSetupProgress(
  152. ULONG Fill
  153. )
  154. /*++
  155. Routine Description:
  156. Sets the overall progress, in terms of percentage
  157. for the textmode setup. Since multiple threads
  158. are touching the shared overall progress ULONG
  159. its protected.
  160. Arguments:
  161. Fill : The new percentage to set.
  162. Return Value:
  163. None.
  164. --*/
  165. {
  166. KIRQL OldIrql;
  167. KeAcquireSpinLock(&ProgressLock, &OldIrql);
  168. ProgressPercentage = Fill;
  169. KeReleaseSpinLock(&ProgressLock, OldIrql);
  170. }
  171. ////////////////////////////////////////////////////////////////
  172. //
  173. // Graphics progress bar methods
  174. //
  175. ////////////////////////////////////////////////////////////////
  176. TM_GRAPHICS_PRGBAR_HANDLE
  177. TextmodeGraphicsProgBarCreate(
  178. IN ULONG X,
  179. IN ULONG Y,
  180. IN ULONG Length,
  181. IN ULONG Height,
  182. IN ULONG ForegroundColor,
  183. IN ULONG BackgroundColor,
  184. IN ULONG InitialFill
  185. )
  186. /*++
  187. Routine Description:
  188. Creates a graphics progress bar object, with the
  189. specified attributes.
  190. Note : This graphics progress bar will use solid
  191. fill using the current palette, while updating
  192. progress i.e. drawing background and foreground.
  193. Arguments:
  194. X - Top left X coordinate
  195. Y - Top left Y coordinate
  196. Length - Length of the progress bar in pixels
  197. Heigth - Height of the progress bar in pixels
  198. ForegroundColor - Index in palette, indicating
  199. foreground color
  200. BackgroundColor - Index in palette, indicating
  201. background color
  202. IntialFill - Initial percentage that needs to
  203. be filled
  204. Return Value:
  205. Handle to the graphics progress bar object,
  206. if successful otherwise NULL
  207. --*/
  208. {
  209. TM_GRAPHICS_PRGBAR_HANDLE hPrgBar = NULL;
  210. if (Length > Height) {
  211. hPrgBar = (TM_GRAPHICS_PRGBAR_HANDLE)
  212. SpMemAlloc(sizeof(TM_GRAPHICS_PRGBAR));
  213. if (hPrgBar) {
  214. RtlZeroMemory(hPrgBar, sizeof(TM_GRAPHICS_PRGBAR));
  215. hPrgBar->X = X;
  216. hPrgBar->Y = Y;
  217. hPrgBar->Length = Length;
  218. hPrgBar->Height = Height;
  219. hPrgBar->Fill = InitialFill;
  220. hPrgBar->ForegroundColor = ForegroundColor;
  221. hPrgBar->BackgroundColor = BackgroundColor;
  222. }
  223. }
  224. return hPrgBar;
  225. }
  226. TM_GRAPHICS_PRGBAR_HANDLE
  227. TextmodeGraphicsProgBarCreateUsingBmps(
  228. IN ULONG X,
  229. IN ULONG Y,
  230. IN ULONG Length,
  231. IN ULONG Height,
  232. IN ULONG BackgroundId,
  233. IN ULONG ForegroundId,
  234. IN ULONG InitialFill
  235. )
  236. /*++
  237. Routine Description:
  238. Creates a graphics progress bar object, with the
  239. specified attributes.
  240. Note : This graphics progress bar will use the
  241. given bitmaps to update the background and foreground.
  242. Both background and foreground bitmap are assumed
  243. to be 1 pixel wide. Background bitmap's height is
  244. assumed to be "Height" pixels where as foreground
  245. bitmap's height is assumed be to "Height - 2" pixels.
  246. Arguments:
  247. X - Top left X coordinate
  248. Y - Top left Y coordinate
  249. Length - Length of the progress bar in pixels
  250. Heigth - Height of the bakground bitmap, in pixels
  251. BackgroundId - Background bitmap resource ID
  252. ForegroundId - Foreground bitmap resource ID
  253. IntialFill - Initial percentage that needs to
  254. be filled
  255. Note : Its assumed that the foreground and background
  256. bitmaps are in 4bpp i.e. 16 colors format.
  257. Return Value:
  258. Handle to the graphics progress bar object,
  259. if successful otherwise NULL
  260. --*/
  261. {
  262. TM_GRAPHICS_PRGBAR_HANDLE hPrgBar = NULL;
  263. TM_BITMAP_HANDLE hBackground = TextmodeBitmapCreate(BackgroundId);
  264. TM_BITMAP_HANDLE hForeground = TextmodeBitmapCreate(ForegroundId);
  265. if (!hBackground && hForeground) {
  266. TextmodeBitmapDelete(hForeground);
  267. }
  268. if (!hForeground&& hBackground) {
  269. TextmodeBitmapDelete(hBackground);
  270. }
  271. if (hForeground && hBackground) {
  272. hPrgBar = TextmodeGraphicsProgBarCreate(X,
  273. Y,
  274. Length,
  275. Height,
  276. 0,
  277. 0,
  278. InitialFill);
  279. if (hPrgBar) {
  280. hPrgBar->Background = hBackground;
  281. hPrgBar->Foreground = hForeground;
  282. } else {
  283. TextmodeBitmapDelete(hForeground);
  284. TextmodeBitmapDelete(hBackground);
  285. }
  286. }
  287. return hPrgBar;
  288. }
  289. NTSTATUS
  290. TextmodeGraphicsProgBarDelete(
  291. IN TM_GRAPHICS_PRGBAR_HANDLE hPrgBar
  292. )
  293. /*++
  294. Routine Description:
  295. Deletes the graphics progress bar object. Frees
  296. up an any allocated resources.
  297. Arguments:
  298. hPrgBar - Handle to the graphics progress bar object
  299. Return Value:
  300. STATUS_SUCCESS, if successful otherwise appropriate
  301. error code.
  302. --*/
  303. {
  304. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  305. if (hPrgBar) {
  306. SpMemFree(hPrgBar);
  307. Status = STATUS_SUCCESS;
  308. }
  309. return Status;
  310. }
  311. NTSTATUS
  312. TextmodeGraphicsProgBarRefresh(
  313. IN TM_GRAPHICS_PRGBAR_HANDLE hPrgBar,
  314. IN BOOLEAN UpdateBackground
  315. )
  316. /*++
  317. Routine Description:
  318. Repaints the graphics progress bar
  319. Arguments:
  320. hPrgBar - Handle to the graphics progress bar object
  321. UpgradeBackground - Indicates whether the background
  322. also needs to be repainted or not.
  323. Return Value:
  324. STATUS_SUCCESS, if successful, otherwise appropriate
  325. error code
  326. --*/
  327. {
  328. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  329. if (hPrgBar) {
  330. ULONG FillLength = hPrgBar->Fill * (hPrgBar->Length - 2) / 100;
  331. if (hPrgBar->Background && hPrgBar->Foreground) {
  332. //
  333. // Bitmapped progress bar
  334. //
  335. ULONG Index;
  336. if (UpdateBackground) {
  337. for (Index=0; Index < hPrgBar->Length; Index++) {
  338. TextmodeBitmapDisplay(hPrgBar->Background,
  339. hPrgBar->X + Index,
  340. hPrgBar->Y);
  341. }
  342. }
  343. if (FillLength) {
  344. ULONG Count = FillLength;
  345. for (Index=1; Index <= Count; Index++) {
  346. TextmodeBitmapDisplay(hPrgBar->Foreground,
  347. hPrgBar->X + Index,
  348. hPrgBar->Y + 1);
  349. }
  350. }
  351. } else {
  352. //
  353. // Solid fill progress bar
  354. //
  355. if (UpdateBackground) {
  356. VgaGraphicsSolidColorFill(hPrgBar->X, hPrgBar->Y,
  357. hPrgBar->X + hPrgBar->Length, hPrgBar->Y + hPrgBar->Height,
  358. hPrgBar->BackgroundColor);
  359. }
  360. if (FillLength) {
  361. VgaGraphicsSolidColorFill(hPrgBar->X + 1, hPrgBar->Y + 1,
  362. hPrgBar->X + FillLength, hPrgBar->Y + hPrgBar->Height - 1,
  363. hPrgBar->ForegroundColor);
  364. }
  365. }
  366. Status = STATUS_SUCCESS;
  367. }
  368. return Status;
  369. }
  370. NTSTATUS
  371. TextmodeGraphicsProgBarUpdate(
  372. IN TM_GRAPHICS_PRGBAR_HANDLE hPrgBar,
  373. IN ULONG Fill
  374. )
  375. /*++
  376. Routine Description:
  377. Updates the progress bar fill percentage, and repaints
  378. if needed.
  379. Note : The percentage can be increasing or decreasing
  380. w.r.t to previous fill percentage
  381. Arguments:
  382. hPrgBar - Handle to the graphics progress bar object
  383. Fill - The new fill percentage.
  384. Return Value:
  385. STATUS_SUCCESS, if successful, otherwise appropriate
  386. error code
  387. --*/
  388. {
  389. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  390. if (Fill > 100) {
  391. Fill = 100;
  392. }
  393. if (hPrgBar && (hPrgBar->Fill != Fill)) {
  394. //
  395. // Note : Make sure we leave one pixel at the start and end
  396. // in the background to emulate a bounding rectangle
  397. // around the current fill
  398. //
  399. ULONG OldFillLength = hPrgBar->Fill * (hPrgBar->Length - 2) / 100;
  400. ULONG NewFillLength = Fill * (hPrgBar->Length - 2) / 100;
  401. ULONG Index;
  402. if (OldFillLength != NewFillLength) {
  403. if (OldFillLength < NewFillLength) {
  404. //
  405. // increasing
  406. //
  407. if (hPrgBar->Foreground && hPrgBar->Background) {
  408. for (Index = OldFillLength; Index < NewFillLength; Index++) {
  409. TextmodeBitmapDisplay(hPrgBar->Foreground,
  410. hPrgBar->X + Index + 1,
  411. hPrgBar->Y + 1);
  412. }
  413. } else {
  414. VgaGraphicsSolidColorFill(hPrgBar->X + OldFillLength + 1, hPrgBar->Y + 1,
  415. hPrgBar->X + NewFillLength, hPrgBar->Y + hPrgBar->Height - 1,
  416. hPrgBar->ForegroundColor);
  417. }
  418. } else {
  419. //
  420. // decreasing
  421. //
  422. if (hPrgBar->Foreground && hPrgBar->Background) {
  423. for (Index = NewFillLength; Index <= OldFillLength; Index++) {
  424. TextmodeBitmapDisplay(hPrgBar->Background,
  425. hPrgBar->X + Index,
  426. hPrgBar->Y);
  427. }
  428. } else {
  429. VgaGraphicsSolidColorFill(hPrgBar->X + NewFillLength, hPrgBar->Y + 1,
  430. hPrgBar->X + OldFillLength, hPrgBar->Y + hPrgBar->Height - 1,
  431. hPrgBar->BackgroundColor);
  432. }
  433. }
  434. hPrgBar->Fill = Fill;
  435. }
  436. Status = STATUS_SUCCESS;
  437. }
  438. return Status;
  439. }
  440. ////////////////////////////////////////////////////////////////
  441. //
  442. // Bitmap methods
  443. //
  444. ////////////////////////////////////////////////////////////////
  445. TM_BITMAP_HANDLE
  446. TextmodeBitmapCreate(
  447. IN ULONG BitmapResourceId
  448. )
  449. /*++
  450. Routine Description:
  451. Creates a bitmap object using the given resource Id.
  452. Note : The resource is currently assumed to be present
  453. in usetup.exe module. The bitmap is assumed to be in
  454. 4bpp or 16 colors format.
  455. Arguments:
  456. BitmapResourceId - the bitmap resource Id.
  457. Return Value:
  458. Handle to the new bitmap object, if successful,
  459. otherwise NULL
  460. --*/
  461. {
  462. TM_BITMAP_HANDLE hBitmap = NULL;
  463. ULONG_PTR ResourceIdPath[3];
  464. PUCHAR Bitmap = NULL;
  465. NTSTATUS Status;
  466. PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry = NULL;
  467. if (BitmapResourceId) {
  468. ResourceIdPath[0] = 2;
  469. ResourceIdPath[1] = BitmapResourceId;
  470. ResourceIdPath[2] = 0;
  471. Status = LdrFindResource_U(ResourceImageBase,
  472. ResourceIdPath,
  473. 3,
  474. &ResourceDataEntry);
  475. if (NT_SUCCESS(Status)) {
  476. Status = LdrAccessResource(ResourceImageBase,
  477. ResourceDataEntry,
  478. &Bitmap,
  479. NULL);
  480. if (NT_SUCCESS(Status)) {
  481. hBitmap = (TM_BITMAP_HANDLE)SpMemAlloc(sizeof(TM_BITMAP));
  482. if (hBitmap) {
  483. RtlZeroMemory(hBitmap, sizeof(TM_BITMAP));
  484. //
  485. // All we have and need is actual bitmap data
  486. //
  487. hBitmap->Data = (PVOID)Bitmap;
  488. }
  489. }
  490. }
  491. }
  492. return hBitmap;
  493. }
  494. TM_BITMAP_HANDLE
  495. TextmodeBitmapCreateFromFile(
  496. IN PWSTR FileName
  497. )
  498. /*++
  499. Routine Description:
  500. Creates a bitmap object using the given fully qualified
  501. NT pathname for the bitmap file.
  502. Note : The bitmap is assumed to be in 4bpp or 16 color
  503. format
  504. Arguments:
  505. FileName - Fully qualified NT pathname for
  506. the bitmap file
  507. Return Value:
  508. Handle to the new bitmap object if successful,
  509. otherwise NULL.
  510. --*/
  511. {
  512. TM_BITMAP_HANDLE hBitmap = NULL;
  513. HANDLE FileHandle = NULL, SectionHandle = NULL;
  514. PVOID ViewBase = NULL;
  515. ULONG FileSize = 0;
  516. if (FileName && *FileName &&
  517. NT_SUCCESS(SpOpenAndMapFile(FileName,
  518. &FileHandle,
  519. &SectionHandle,
  520. &ViewBase,
  521. &FileSize,
  522. FALSE))) {
  523. hBitmap = (TM_BITMAP_HANDLE)SpMemAlloc(sizeof(TM_BITMAP));
  524. if (hBitmap) {
  525. RtlZeroMemory(hBitmap, sizeof(TM_BITMAP));
  526. wcscpy(hBitmap->FileName, FileName);
  527. hBitmap->ViewBase = ViewBase;
  528. hBitmap->Data = ((PCHAR)ViewBase) + sizeof(BITMAPFILEHEADER);
  529. hBitmap->FileHandle = FileHandle;
  530. hBitmap->SectionHandle = SectionHandle;
  531. }
  532. }
  533. return hBitmap;
  534. }
  535. NTSTATUS
  536. TextmodeBitmapDelete(
  537. IN TM_BITMAP_HANDLE hBitmap
  538. )
  539. /*++
  540. Routine Description:
  541. Delete the bitmap object and frees up any allocated
  542. resources.
  543. Arguments:
  544. hBitmap - Handle to the bitmap object
  545. Return Value:
  546. STATUS_SUCCESS, if successful, otherwise appropriate
  547. error code.
  548. --*/
  549. {
  550. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  551. if (hBitmap) {
  552. if (hBitmap->SectionHandle != NULL) {
  553. SpUnmapFile(hBitmap->SectionHandle, hBitmap->ViewBase);
  554. }
  555. if (hBitmap->FileHandle != NULL) {
  556. Status = ZwClose(hBitmap->FileHandle);
  557. } else {
  558. Status = STATUS_SUCCESS;
  559. }
  560. SpMemFree(hBitmap);
  561. }
  562. return Status;
  563. }
  564. NTSTATUS
  565. TextmodeBitmapDisplay(
  566. IN TM_BITMAP_HANDLE hBitmap,
  567. IN ULONG X,
  568. IN ULONG Y
  569. )
  570. /*++
  571. Routine Description:
  572. Displays the given bitmap at the specified
  573. coordinates.
  574. Arguments:
  575. hBitmap - Handle to the bitmap object
  576. X - Top left X coordinate
  577. Y - Top left Y coordinate
  578. Return Value:
  579. STATUS_SUCCESS, if successful, otherwise
  580. appropriate error code.
  581. --*/
  582. {
  583. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  584. if (hBitmap) {
  585. VgaGraphicsBitBlt(hBitmap->Data, X, Y);
  586. Status = STATUS_SUCCESS;
  587. }
  588. return Status;
  589. }
  590. ////////////////////////////////////////////////////////////////
  591. //
  592. // Animated bitmap methods
  593. //
  594. ////////////////////////////////////////////////////////////////
  595. __inline
  596. NTSTATUS
  597. TextmodeAnimatedBitmapSetStopAnimating(
  598. IN TM_ANIMATED_BITMAP_HANDLE hBitmap,
  599. IN BOOLEAN StopAnimating
  600. )
  601. /*++
  602. Routine Description:
  603. Sets the (shared) attribute which indicates
  604. whether the animation for the animated bitmap
  605. needs to be stopped or not.
  606. Arguments:
  607. hBitmap - Handle to the animated bitmap object
  608. StopAnimating - Whether to stop the animation or not
  609. Return Value:
  610. STATUS_SUCCESS, if successful, otherwise appropriate
  611. error code.
  612. --*/
  613. {
  614. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  615. if (hBitmap) {
  616. InterlockedExchange(&(hBitmap->StopAnimating), (LONG)StopAnimating);
  617. Status = STATUS_SUCCESS;
  618. }
  619. return Status;
  620. }
  621. __inline
  622. NTSTATUS
  623. TextmodeAnimatedBitmapGetStopAnimating(
  624. IN TM_ANIMATED_BITMAP_HANDLE hBitmap,
  625. IN PBOOLEAN StopAnimating
  626. )
  627. /*++
  628. Routine Description:
  629. Gets the (shared) attribute which indicates whether the
  630. animated bitmap is currently being animated or not.
  631. Arguments:
  632. hBitmap - Handle to the animated bitmap object
  633. StopAnimating - Place holder for boolean value indicating
  634. whether animation is in progress or not.
  635. Return Value:
  636. STATUS_SUCCESS, if successful, otherwise appropriate
  637. error code.
  638. --*/
  639. {
  640. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  641. if (hBitmap && StopAnimating) {
  642. *StopAnimating = (BOOLEAN)InterlockedExchange(&(hBitmap->StopAnimating),
  643. hBitmap->StopAnimating);
  644. Status = STATUS_SUCCESS;
  645. }
  646. return Status;
  647. }
  648. TM_ANIMATED_BITMAP_HANDLE
  649. TextmodeAnimatedBitmapCreate(
  650. IN ULONG *ResourceIds
  651. )
  652. /*++
  653. Routine Description:
  654. Creates a animated bitmap, given the list of resource
  655. ids each bitmaps, in sequence.
  656. Note : The bitmap format needs to adhere to 4bpp or
  657. 16 colors. The resource is assumed to be
  658. present in usetup.exe
  659. Arguments:
  660. ResourceIds - Array of resource ids for the bitmaps
  661. to be animated, in sequence. A "0" id
  662. indicates the termination for array.
  663. Return Value:
  664. Handle to the newly created animated bitmap object, if
  665. successful, otherwise NULL.
  666. --*/
  667. {
  668. TM_ANIMATED_BITMAP_HANDLE hAnimatedBitmap = NULL;
  669. ULONG Count = 0;
  670. ULONG Index;
  671. if (ResourceIds) {
  672. for (Index = 0; ResourceIds[Index]; Index++) {
  673. Count++;
  674. }
  675. }
  676. if (Count) {
  677. ULONG BitmapsLoaded = 0;
  678. TM_BITMAP_HANDLE hBitmap;
  679. hAnimatedBitmap = (TM_ANIMATED_BITMAP_HANDLE)
  680. SpMemAlloc(sizeof(TM_ANIMATED_BITMAP));
  681. if (hAnimatedBitmap) {
  682. RtlZeroMemory(hAnimatedBitmap, sizeof(TM_ANIMATED_BITMAP));
  683. hAnimatedBitmap->StopAnimating = FALSE;
  684. for (Index = 0; Index < Count; Index++) {
  685. hBitmap = TextmodeBitmapCreate(ResourceIds[Index]);
  686. if (hBitmap) {
  687. hAnimatedBitmap->Bitmaps[BitmapsLoaded++] = hBitmap;
  688. }
  689. }
  690. if (!BitmapsLoaded) {
  691. SpMemFree(hAnimatedBitmap);
  692. hAnimatedBitmap = NULL;
  693. } else {
  694. hAnimatedBitmap->CurrentBitmap = 0; // the first bitmap
  695. }
  696. }
  697. }
  698. return hAnimatedBitmap;
  699. }
  700. TM_ANIMATED_BITMAP_HANDLE
  701. TextmodeAnimatedBitmapCreateFromFiles(
  702. IN WCHAR *FileNames[]
  703. )
  704. /*++
  705. Routine Description:
  706. Creates a animated bitmap, given the list of bitmap
  707. filenames, in sequence.
  708. Note : The bitmap format needs to adhere to 4bpp or
  709. 16 colors.
  710. Arguments:
  711. FileNames - Null terminated array of filenames for
  712. the bitmaps to be animated, in sequence.
  713. Return Value:
  714. Handle to the newly created animated bitmap object, if
  715. successful, otherwise NULL.
  716. --*/
  717. {
  718. TM_ANIMATED_BITMAP_HANDLE hAnimatedBitmap = NULL;
  719. ULONG FileCount = 0;
  720. ULONG Index;
  721. if (FileNames) {
  722. for (Index = 0; FileNames[Index]; Index++) {
  723. FileCount++;
  724. }
  725. }
  726. if (FileCount) {
  727. ULONG BitmapsLoaded = 0;
  728. TM_BITMAP_HANDLE hBitmap;
  729. hAnimatedBitmap = (TM_ANIMATED_BITMAP_HANDLE)
  730. SpMemAlloc(sizeof(TM_ANIMATED_BITMAP));
  731. if (hAnimatedBitmap) {
  732. RtlZeroMemory(hAnimatedBitmap, sizeof(TM_ANIMATED_BITMAP));
  733. hAnimatedBitmap->StopAnimating = FALSE;
  734. for (Index = 0; Index < FileCount; Index++) {
  735. hBitmap = TextmodeBitmapCreateFromFile(FileNames[Index]);
  736. if (hBitmap) {
  737. hAnimatedBitmap->Bitmaps[BitmapsLoaded++] = hBitmap;
  738. }
  739. }
  740. if (!BitmapsLoaded) {
  741. SpMemFree(hAnimatedBitmap);
  742. hAnimatedBitmap = NULL;
  743. } else {
  744. hAnimatedBitmap->CurrentBitmap = 0; // the first bitmap
  745. }
  746. }
  747. }
  748. return hAnimatedBitmap;
  749. }
  750. NTSTATUS
  751. TextmodeAnimatedBitmapDelete(
  752. IN TM_ANIMATED_BITMAP_HANDLE hAnimatedBitmap
  753. )
  754. /*++
  755. Routine Description:
  756. Delete the given animated bitmap object and frees
  757. up an resource associated with the object.
  758. Note : This will stop the animation thread, if
  759. required.
  760. Arguments:
  761. hAnimatedBitmap - Handle to the animated bitmap object
  762. Return Value:
  763. STATUS_SUCCESS, if successful, otherwise appropriate
  764. error code.
  765. --*/
  766. {
  767. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  768. if (hAnimatedBitmap) {
  769. ULONG Index;
  770. //
  771. // First, try to terminate the thread
  772. //
  773. TextmodeAnimatedBitmapSetStopAnimating(hAnimatedBitmap, TRUE);
  774. //
  775. // Wait, till the animator thread stops
  776. //
  777. Status = ZwWaitForSingleObject(hAnimatedBitmap->ThreadHandle, FALSE, NULL);
  778. if (!NT_SUCCESS(Status)) {
  779. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  780. "SETUP: DeleteTextmodeAnimatedBitmap() : Wait filed for %lX with %lX\n",
  781. hAnimatedBitmap->ThreadHandle,
  782. Status));
  783. }
  784. Status = STATUS_SUCCESS;
  785. //
  786. // Delete each bitmap
  787. //
  788. for (Index=0;
  789. (hAnimatedBitmap->Bitmaps[Index] && (Index < MAX_ANIMATED_BITMAPS));
  790. Index++) {
  791. if (NT_SUCCESS(Status)) {
  792. Status = TextmodeBitmapDelete(hAnimatedBitmap->Bitmaps[Index]);
  793. }
  794. }
  795. //
  796. // Free the animated bitmap
  797. //
  798. SpMemFree(hAnimatedBitmap);
  799. }
  800. return Status;
  801. }
  802. NTSTATUS
  803. TextmodeAnimateBitmapAnimateNext(
  804. IN TM_ANIMATED_BITMAP_HANDLE hBitmap
  805. )
  806. /*++
  807. Routine Description:
  808. Animates rather draws the next bitmap in the sequence.
  809. Arguments:
  810. hBitmap - Handle to the animated bitmap object
  811. Return Value:
  812. STATUS_SUCCESS, if successful, otherwise appropriate
  813. error code.
  814. --*/
  815. {
  816. TM_BITMAP_HANDLE hCurrBitmap;
  817. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  818. if (hBitmap) {
  819. hCurrBitmap = hBitmap->Bitmaps[hBitmap->CurrentBitmap];
  820. Status = TextmodeBitmapDisplay( hCurrBitmap, hBitmap->X, hBitmap->Y);
  821. hBitmap->CurrentBitmap++;
  822. if ((hBitmap->CurrentBitmap >= MAX_ANIMATED_BITMAPS) ||
  823. (hBitmap->Bitmaps[hBitmap->CurrentBitmap] == NULL)) {
  824. hBitmap->CurrentBitmap = 0; // start over again
  825. }
  826. }
  827. return Status;
  828. }
  829. NTSTATUS
  830. TextmodeAnimatedBitmapAnimate(
  831. IN TM_ANIMATED_BITMAP_HANDLE hBitmap,
  832. IN ULONG X,
  833. IN ULONG Y,
  834. IN ULONG Speed
  835. )
  836. /*++
  837. Routine Description:
  838. Starts the animation for the given animated bitmap by
  839. drawing the bitmaps in sequence at the specified
  840. coordinates.
  841. Note : This call would create a separate system
  842. thread for actually animating the bitmap and would return
  843. immediately.
  844. Arguments:
  845. hBitmap - Handle to the animated bitmap object
  846. X - Top left X coordinate for the animation space
  847. Y - Top left Y coordinate for the animation space
  848. Speed - Time interval between changing of bitmaps
  849. in animation sequence, in milliseconds.
  850. Return Value:
  851. STATUS_SUCCESS, if successful, otherwise appropriate
  852. error code.
  853. --*/
  854. {
  855. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  856. if (hBitmap) {
  857. hBitmap->FlipTime = Speed;
  858. hBitmap->X = X;
  859. hBitmap->Y = Y;
  860. Status = PsCreateSystemThread(&(hBitmap->ThreadHandle),
  861. THREAD_ALL_ACCESS,
  862. NULL,
  863. NtCurrentProcess(),
  864. NULL,
  865. TextmodeAnimatedBitmapAnimator,
  866. hBitmap);
  867. }
  868. return Status;
  869. }
  870. VOID
  871. TextmodeAnimatedBitmapAnimator(
  872. IN PVOID Context
  873. )
  874. /*++
  875. Routine Description:
  876. The worker routine which runs as a separate thread doing
  877. the actual animation for a animated bitmap.
  878. Arguments:
  879. Context - Handle to the animated bitmap object type cast
  880. into PVOID type.
  881. Return Value:
  882. None.
  883. --*/
  884. {
  885. LARGE_INTEGER DelayTime;
  886. TM_ANIMATED_BITMAP_HANDLE hBitmap = (TM_ANIMATED_BITMAP_HANDLE)Context;
  887. TM_BITMAP_HANDLE hCurrBitmap = NULL;
  888. if (Context) {
  889. BOOLEAN StopAnimating = FALSE;
  890. NTSTATUS Status;
  891. DelayTime.HighPart = -1; // relative time
  892. DelayTime.LowPart = (ULONG)(-10000 * hBitmap->FlipTime); // secs in 100ns interval
  893. Status = TextmodeAnimatedBitmapGetStopAnimating(hBitmap, &StopAnimating);
  894. while (NT_SUCCESS(Status) && !StopAnimating) {
  895. hCurrBitmap = hBitmap->Bitmaps[hBitmap->CurrentBitmap];
  896. TextmodeBitmapDisplay(hCurrBitmap, hBitmap->X, hBitmap->Y);
  897. KeDelayExecutionThread(KernelMode, FALSE, &DelayTime);
  898. hBitmap->CurrentBitmap++;
  899. if ((hBitmap->CurrentBitmap >= MAX_ANIMATED_BITMAPS) ||
  900. (hBitmap->Bitmaps[hBitmap->CurrentBitmap] == NULL)) {
  901. hBitmap->CurrentBitmap = 0; // start over again
  902. }
  903. Status = TextmodeAnimatedBitmapGetStopAnimating(hBitmap, &StopAnimating);
  904. }
  905. }
  906. PsTerminateSystemThread(STATUS_SUCCESS);
  907. }
  908. ////////////////////////////////////////////////////////////////
  909. //
  910. // VGA graphics methods
  911. //
  912. // Note : VgaXXXX rountines are defined basically
  913. // to segregate the video memory update routines
  914. // from the other abstractions. Right now most of
  915. // these routine delegate the actual work to the
  916. // real implementation in bootvid.dll, but in
  917. // future if bootvid.dll goes away, all we need
  918. // to do is implement this interface.
  919. // Also note that, these routine synchronize the
  920. // access, so that only one thread at a time
  921. // updates the video memory.
  922. //
  923. ////////////////////////////////////////////////////////////////
  924. __inline
  925. VOID
  926. VgaDisplayAcquireLock(
  927. VOID
  928. )
  929. /*++
  930. Routine Description:
  931. Acquires the lock to the video memory, so that
  932. only one thread a time writes to the video memory.
  933. Note : If the lock is already held by another thread,
  934. then the calling thread is put to sleep. The calling
  935. thread wakes up after every 100 millisecond and
  936. checks for the lock. It falls out of sleep based on
  937. whether the lock is already held or not.
  938. Arguments:
  939. None.
  940. Return Value:
  941. None.
  942. --*/
  943. {
  944. KIRQL OldIrql;
  945. KeAcquireSpinLock(&VgaDisplayLock, &OldIrql);
  946. while (InVgaDisplay) {
  947. LARGE_INTEGER DelayTime;
  948. DelayTime.HighPart = -1; // relative time
  949. DelayTime.LowPart = (ULONG)(-10000 * 100); // 100ms interval
  950. KeReleaseSpinLock(&VgaDisplayLock, OldIrql);
  951. KeDelayExecutionThread(KernelMode, FALSE, &DelayTime);
  952. KeAcquireSpinLock(&VgaDisplayLock, &OldIrql);
  953. }
  954. InVgaDisplay = TRUE;
  955. KeReleaseSpinLock(&VgaDisplayLock, OldIrql);
  956. }
  957. __inline
  958. VOID
  959. VgaDisplayReleaseLock(
  960. VOID
  961. )
  962. /*++
  963. Routine Description:
  964. Release the video memory lock which was held.
  965. Arguments:
  966. None.
  967. Return Value:
  968. None.
  969. --*/
  970. {
  971. KIRQL OldIrql;
  972. KeAcquireSpinLock(&VgaDisplayLock, &OldIrql);
  973. InVgaDisplay = FALSE;
  974. KeReleaseSpinLock(&VgaDisplayLock, OldIrql);
  975. }
  976. NTSTATUS
  977. VgaGraphicsInit(
  978. PSP_VIDEO_VARS VideoVars
  979. )
  980. /*++
  981. Routine Description:
  982. Initializes the video card and switches it into
  983. 640 * 480 * 16 colors mode.
  984. Arguments:
  985. VideoVars - Pointer to SP_VIDEO_VARS containing
  986. graphics mode index and handle to the
  987. display.
  988. Return Value:
  989. Appropriate NTSTATUS value.
  990. --*/
  991. {
  992. NTSTATUS Status;
  993. IO_STATUS_BLOCK IoStatusBlock;
  994. VIDEO_MODE VideoMode;
  995. VgaDisplayAcquireLock();
  996. //
  997. // Set the desired graphics mode.
  998. //
  999. VideoMode.RequestedMode = VideoVars->GraphicsModeInfo.ModeIndex;
  1000. Status = ZwDeviceIoControlFile(VideoVars->hDisplay,
  1001. NULL,
  1002. NULL,
  1003. NULL,
  1004. &IoStatusBlock,
  1005. IOCTL_VIDEO_SET_CURRENT_MODE,
  1006. &VideoMode,
  1007. sizeof(VideoMode),
  1008. NULL,
  1009. 0);
  1010. if(NT_SUCCESS(Status)) {
  1011. VidInitialize(FALSE);
  1012. VidResetDisplay(FALSE);
  1013. }
  1014. VgaDisplayReleaseLock();
  1015. return Status;
  1016. }
  1017. NTSTATUS
  1018. VgaGraphicsTerminate(
  1019. PSP_VIDEO_VARS VideoVars
  1020. )
  1021. /*++
  1022. Routine Description:
  1023. Terminates the 640 * 480 * 16 color mode & switches
  1024. it back to regular text mode. Also clears the display.
  1025. Arguments:
  1026. VideoVars - Pointer to SP_VIDEO_VARS containing
  1027. text mode index and handle to the
  1028. display.
  1029. Return Value:
  1030. Appropriate NTSTATUS value.
  1031. --*/
  1032. {
  1033. NTSTATUS Status;
  1034. IO_STATUS_BLOCK IoStatusBlock;
  1035. VIDEO_MODE VideoMode;
  1036. VgaDisplayAcquireLock();
  1037. VidResetDisplay(FALSE);
  1038. //
  1039. // Switch the adapter to textmode again.
  1040. //
  1041. VideoMode.RequestedMode = VideoVars->VideoModeInfo.ModeIndex;
  1042. Status = ZwDeviceIoControlFile(VideoVars->hDisplay,
  1043. NULL,
  1044. NULL,
  1045. NULL,
  1046. &IoStatusBlock,
  1047. IOCTL_VIDEO_SET_CURRENT_MODE,
  1048. &VideoMode,
  1049. sizeof(VideoMode),
  1050. NULL,
  1051. 0);
  1052. VgaDisplayReleaseLock();
  1053. return Status;
  1054. }
  1055. __inline
  1056. VOID
  1057. VgaGraphicsSolidColorFill(
  1058. IN ULONG x1,
  1059. IN ULONG y1,
  1060. IN ULONG x2,
  1061. IN ULONG y2,
  1062. IN ULONG Color
  1063. )
  1064. /*++
  1065. Routine Description:
  1066. Fills the given rectangle with the specified
  1067. color.
  1068. Arguments:
  1069. x1 - Top left x coordinate
  1070. y1 - Top left y coordinate
  1071. x2 - Bottom right x coordinate
  1072. y2 - Bottom right y coordinate
  1073. Color - Index into the current palette table
  1074. indicating the color to be filled inside
  1075. the rectangle.
  1076. Return Value:
  1077. None.
  1078. --*/
  1079. {
  1080. VgaDisplayAcquireLock();
  1081. VidSolidColorFill(x1, y1, x2, y2, Color);
  1082. VgaDisplayReleaseLock();
  1083. }
  1084. __inline
  1085. VOID
  1086. VgaGraphicsBitBlt(
  1087. IN PUCHAR Buffer,
  1088. IN ULONG x,
  1089. IN ULONG y
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. BitBlts the given bitmap at the specified
  1094. coordinates.
  1095. Arguments:
  1096. Buffer - The actual bitmap date (i.e. starting
  1097. with the color table information)
  1098. x - Top left x coordinate
  1099. y - Top left y coordinate
  1100. Return Value:
  1101. None.
  1102. --*/
  1103. {
  1104. VgaDisplayAcquireLock();
  1105. VidBitBlt(Buffer, x, y);
  1106. VgaDisplayReleaseLock();
  1107. }
  1108. ////////////////////////////////////////////////////////////////
  1109. //
  1110. // Upgrade graphics routines
  1111. //
  1112. ////////////////////////////////////////////////////////////////
  1113. __inline
  1114. BOOLEAN
  1115. QuitGraphicsThread(
  1116. VOID
  1117. )
  1118. /*++
  1119. Routine Description:
  1120. Indiates whether the primary upgrade graphics thread
  1121. needs to be stopped or not based on user input
  1122. (ESC key).
  1123. Note : This feature is only enable in pre-release
  1124. builds.
  1125. Arguments:
  1126. None.
  1127. Return Value:
  1128. TRUE if the upgrade graphics thread needs to be stopped
  1129. else FALSE.
  1130. --*/
  1131. {
  1132. BOOLEAN Result = FALSE;
  1133. /*
  1134. #ifdef PRERELEASE
  1135. Result = SpInputIsKeyWaiting() && (SpInputGetKeypress() == ASCI_ESC);
  1136. #endif
  1137. */
  1138. return Result;
  1139. }
  1140. NTSTATUS
  1141. UpgradeGraphicsInit(
  1142. VOID
  1143. )
  1144. /*++
  1145. Routine Description:
  1146. Does the needed global initialization for the
  1147. upgrade graphics mode.
  1148. Arguments:
  1149. None.
  1150. Return Value:
  1151. STATUS_SUCCESS, if successful with initialzation,
  1152. otherwise appropriate error code
  1153. --*/
  1154. {
  1155. NTSTATUS Status = STATUS_SUCCESS;
  1156. //
  1157. // Initialize global spin locks
  1158. //
  1159. KeInitializeSpinLock(&VgaDisplayLock);
  1160. KeInitializeSpinLock(&ProgressLock);
  1161. KeInitializeSpinLock(&GraphicsThreadLock);
  1162. return Status;
  1163. }
  1164. NTSTATUS
  1165. UpgradeGraphicsStart(
  1166. VOID
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. Starts of the upgrade graphics
  1171. Arguments:
  1172. None.
  1173. Return Value:
  1174. STATUS_SUCCESS, if the upgrade graphics was started,
  1175. else appropriate error code.
  1176. --*/
  1177. {
  1178. NTSTATUS Status;
  1179. Status = PsCreateSystemThread(&GraphicsThreadHandle,
  1180. THREAD_ALL_ACCESS,
  1181. NULL,
  1182. NtCurrentProcess(),
  1183. NULL,
  1184. UpgradeGraphicsThread,
  1185. NULL);
  1186. #ifdef _GRAPHICS_TESTING_
  1187. Status = ZwWaitForSingleObject(GraphicsThreadHandle, FALSE, NULL);
  1188. #endif
  1189. return Status;
  1190. }
  1191. VOID
  1192. UpgradeGraphicsThread(
  1193. IN PVOID Context
  1194. )
  1195. /*++
  1196. Routine Description:
  1197. The primary upgrade graphics worker thread, which
  1198. paints the background, updates the progress bar
  1199. and starts the animation.
  1200. Arguments:
  1201. Context - Ignored
  1202. Return Value:
  1203. None.
  1204. --*/
  1205. {
  1206. BOOLEAN Stop = FALSE;
  1207. TM_GRAPHICS_PRGBAR_HANDLE hProgBar;
  1208. TM_ANIMATED_BITMAP_HANDLE hAnimation = NULL;
  1209. TM_BITMAP_HANDLE hBitmap = NULL;
  1210. LARGE_INTEGER DelayTime;
  1211. NTSTATUS Status;
  1212. WCHAR Buffer[MAX_PATH];
  1213. ULONG BitmapIds[] = {
  1214. IDB_WORKING1, IDB_WORKING2,
  1215. IDB_WORKING3, IDB_WORKING4,
  1216. IDB_WORKING5, IDB_WORKING6,
  1217. IDB_WORKING7, IDB_WORKING8,
  1218. IDB_WORKING9, IDB_WORKING10,
  1219. IDB_WORKING11, IDB_WORKING12,
  1220. IDB_WORKING13, IDB_WORKING14,
  1221. IDB_WORKING15, IDB_WORKING16,
  1222. IDB_WORKING17, IDB_WORKING18,
  1223. IDB_WORKING19, IDB_WORKING20,
  1224. 0 };
  1225. //
  1226. // Initialize graphics mode
  1227. //
  1228. Status = VgaGraphicsInit(&VideoVars);
  1229. if (NT_SUCCESS(Status)) {
  1230. //
  1231. // Create the background bitmap
  1232. //
  1233. if (Win9xRollback) {
  1234. hBitmap = TextmodeBitmapCreate(IDB_RESTORE_BK);
  1235. } else {
  1236. hBitmap = TextmodeBitmapCreate(IDB_BACKGROUND1);
  1237. }
  1238. if (hBitmap) {
  1239. //
  1240. // Create the animated bitmap
  1241. //
  1242. hAnimation = TextmodeAnimatedBitmapCreate(BitmapIds);
  1243. if (hAnimation) {
  1244. //
  1245. // Create the bitmapped graphics progress bar
  1246. //
  1247. hProgBar = TextmodeGraphicsProgBarCreateUsingBmps(28, 352,
  1248. 123, 14,
  1249. IDB_BACKCELL, IDB_FORECELL, 0);
  1250. if (hProgBar) {
  1251. BOOLEAN Refreshed = FALSE;
  1252. ULONG Fill = 0;
  1253. BOOLEAN Increase = TRUE;
  1254. //
  1255. // Render background
  1256. //
  1257. TextmodeBitmapDisplay(hBitmap, 0, 0);
  1258. //
  1259. // Start the animation
  1260. //
  1261. Status = TextmodeAnimatedBitmapAnimate(hAnimation, 542, 460, 100);
  1262. //
  1263. // Note : Failure to start the animation is not a critical
  1264. // error
  1265. //
  1266. if (!NT_SUCCESS(Status)) {
  1267. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1268. "SETUP:Upgrade graphics thread failed to "
  1269. "animate : %lx error code\r\n",
  1270. Status));
  1271. }
  1272. DelayTime.HighPart = -1; // relative time
  1273. DelayTime.LowPart = (ULONG)(-10000 * 500); // 1000 msec interval
  1274. //
  1275. // Render graphics progress bar
  1276. //
  1277. TextmodeGraphicsProgBarRefresh(hProgBar, TRUE);
  1278. Fill = GetSetupProgress();
  1279. Stop = UpgradeGraphicsThreadGetStop();
  1280. //
  1281. // Continue on till user asks us to stop, or the main
  1282. // textmode thread encounters an error and stops us
  1283. //
  1284. while (!Stop && !QuitGraphicsThread()) {
  1285. //
  1286. // Update the graphics progress bar
  1287. //
  1288. TextmodeGraphicsProgBarUpdate(hProgBar, Fill);
  1289. //
  1290. // Sleep for 0.5 secs
  1291. //
  1292. KeDelayExecutionThread(KernelMode, FALSE, &DelayTime);
  1293. Fill = GetSetupProgress();
  1294. Stop = UpgradeGraphicsThreadGetStop();
  1295. #ifdef _GRAPHICS_TESTING_
  1296. if (Increase) {
  1297. if (Fill < 100) {
  1298. Fill++;
  1299. SetSetupProgress(Fill);
  1300. } else {
  1301. Increase = FALSE;
  1302. }
  1303. }
  1304. if (!Increase) {
  1305. if (Fill <= 0) {
  1306. Increase = TRUE;
  1307. } else {
  1308. Fill--;
  1309. SetSetupProgress(Fill);
  1310. }
  1311. }
  1312. #endif _GRAPHICS_TESTING_
  1313. }
  1314. //
  1315. // Was graphics thread stopped by the main
  1316. // textmode setup, then most probably we
  1317. // encountered an error or user intervention
  1318. // is required
  1319. //
  1320. Stop = UpgradeGraphicsThreadGetStop();
  1321. //
  1322. // Delete the graphics progress bar
  1323. //
  1324. TextmodeGraphicsProgBarDelete(hProgBar);
  1325. }
  1326. //
  1327. // Stop the animation, and delete the animated
  1328. // bitmap object
  1329. //
  1330. TextmodeAnimatedBitmapDelete(hAnimation);
  1331. }
  1332. //
  1333. // Delete the background bitmap object
  1334. //
  1335. TextmodeBitmapDelete(hBitmap);
  1336. }
  1337. }
  1338. //
  1339. // If graphics thread was stopped by user intervention
  1340. // then we need to switch to textmode
  1341. //
  1342. if (!Stop) {
  1343. spvidSpecificReInitialize();
  1344. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  1345. }
  1346. PsTerminateSystemThread(Status);
  1347. }
  1348. VOID
  1349. GraphicsModeProgressUpdate(
  1350. IN TM_SETUP_MAJOR_EVENT MajorEvent,
  1351. IN TM_SETUP_MINOR_EVENT MinorEvent,
  1352. IN PVOID Context,
  1353. IN PVOID EventData
  1354. )
  1355. /*++
  1356. Routine Description:
  1357. Callback which updates the over all progress during
  1358. upgrade graphics mode.
  1359. Note : The single progress bar in upgrade graphics mode
  1360. is used in place of all the various different
  1361. progress bars which are used through out the
  1362. textmode.
  1363. The single progress bar is divided into ranges
  1364. as shown below for the various major events
  1365. across the textmode setup:
  1366. ------------------------------------------
  1367. Range(%) MajorEvent
  1368. ------------------------------------------
  1369. 00-05 InitializationEvent
  1370. 05-20 PartitioningEvent
  1371. (Includes chkdsk)
  1372. 20-40 Backup (if enabled)
  1373. 20-40 Uninstall (if enabled)
  1374. 20/40-90 FileCopyEvent
  1375. (Actual file copying)
  1376. 90-98 SavingSettingsEvent
  1377. 98-100 SetupCompleted
  1378. ------------------------------------------
  1379. Arguments:
  1380. MajorEvent - Indicates the major type of the event
  1381. which happened.
  1382. MinorEvent - Indicates the minor type of the event
  1383. which happened.
  1384. Context - Context data which was registered when
  1385. we register for callback.
  1386. EventData - More detailed event specific data
  1387. Return Value:
  1388. None.
  1389. --*/
  1390. {
  1391. static BOOLEAN Add = TRUE;
  1392. static ULONG LastPercentage = 0;
  1393. static ULONG BackupAllocation = 0;
  1394. BOOLEAN SkipSpew = FALSE;
  1395. ULONG Delta = 0;
  1396. ULONG PercentageFill = 0;
  1397. PercentageFill = GetSetupProgress();
  1398. switch (MajorEvent) {
  1399. case InitializationEvent:
  1400. switch (MinorEvent) {
  1401. case InitializationStartEvent:
  1402. PercentageFill = 2;
  1403. break;
  1404. case InitializationEndEvent:
  1405. PercentageFill = 5;
  1406. break;
  1407. default:
  1408. break;
  1409. }
  1410. break;
  1411. case PartitioningEvent:
  1412. switch (MinorEvent) {
  1413. case ValidatePartitionEvent:
  1414. Delta = (15 * (*(PULONG)EventData)) / 200;
  1415. PercentageFill = 5 + Delta;
  1416. break;
  1417. case FormatPartitionEvent:
  1418. //
  1419. // In cases of upgrade (we won't be formatting)
  1420. //
  1421. break;
  1422. default:
  1423. break;
  1424. }
  1425. break;
  1426. case FileCopyEvent:
  1427. switch (MinorEvent) {
  1428. case FileCopyStartEvent:
  1429. LastPercentage = PercentageFill = 20 + BackupAllocation;
  1430. break;
  1431. case OneFileCopyEvent:
  1432. Delta = ((70 - BackupAllocation) * (*(PULONG)EventData)) / 100;
  1433. PercentageFill = 20 + Delta + BackupAllocation;
  1434. if ((PercentageFill - LastPercentage) > 5) {
  1435. LastPercentage = PercentageFill;
  1436. } else {
  1437. SkipSpew = TRUE;
  1438. }
  1439. break;
  1440. case FileCopyEndEvent:
  1441. PercentageFill = 90;
  1442. break;
  1443. default:
  1444. break;
  1445. }
  1446. break;
  1447. case BackupEvent:
  1448. switch (MinorEvent) {
  1449. case BackupStartEvent:
  1450. LastPercentage = PercentageFill = 20;
  1451. BackupAllocation = 20;
  1452. break;
  1453. case OneFileBackedUpEvent:
  1454. Delta = (20 * (*(PULONG)EventData)) / 100;
  1455. PercentageFill = 20 + Delta;
  1456. if ((PercentageFill - LastPercentage) > 5) {
  1457. LastPercentage = PercentageFill;
  1458. } else {
  1459. SkipSpew = TRUE;
  1460. }
  1461. break;
  1462. case BackupEndEvent:
  1463. PercentageFill = 40;
  1464. break;
  1465. }
  1466. break;
  1467. case UninstallEvent:
  1468. switch (MinorEvent) {
  1469. case UninstallStartEvent:
  1470. LastPercentage = PercentageFill = 20;
  1471. break;
  1472. case UninstallUpdateEvent:
  1473. Delta = (70 * (*(PULONG)EventData)) / 100;
  1474. PercentageFill = 20 + Delta;
  1475. if ((PercentageFill - LastPercentage) > 5) {
  1476. LastPercentage = PercentageFill;
  1477. } else {
  1478. SkipSpew = TRUE;
  1479. }
  1480. break;
  1481. case UninstallEndEvent:
  1482. PercentageFill = 90;
  1483. break;
  1484. default:
  1485. break;
  1486. }
  1487. break;
  1488. case SavingSettingsEvent:
  1489. switch (MinorEvent) {
  1490. case SavingSettingsStartEvent:
  1491. PercentageFill = 90;
  1492. break;
  1493. case SaveHiveEvent:
  1494. if (PercentageFill < 98) {
  1495. if (Add) {
  1496. PercentageFill += 1;
  1497. Add = FALSE;
  1498. } else {
  1499. Add = TRUE;
  1500. }
  1501. }
  1502. break;
  1503. case SavingSettingsEndEvent:
  1504. if (PercentageFill < 98) {
  1505. PercentageFill = 98;
  1506. }
  1507. break;
  1508. default:
  1509. break;
  1510. }
  1511. break;
  1512. case SetupCompletedEvent:
  1513. PercentageFill = 100;
  1514. break;
  1515. default:
  1516. break;
  1517. }
  1518. if (!SkipSpew) {
  1519. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1520. "Setup Event : %ld, %ld, %ld, [%ld], (%ld)\n",
  1521. MajorEvent,
  1522. MinorEvent,
  1523. EventData ? *(PULONG)EventData : 0,
  1524. Delta,
  1525. PercentageFill
  1526. ));
  1527. }
  1528. SetSetupProgress(PercentageFill);
  1529. }
  1530. NTSTATUS
  1531. SpvidSwitchToTextmode(
  1532. VOID
  1533. )
  1534. /*++
  1535. Routine Description:
  1536. Switches from upgrade graphics mode to the regular
  1537. textmode.
  1538. Note : The actual work of switching the graphics
  1539. back to the regular VGA textmode happens
  1540. as a method in video specific reinitialize
  1541. method.
  1542. Arguments:
  1543. None.
  1544. Return Value:
  1545. STATUS_SUCCESS, if successful, otherwise appropirate
  1546. error code
  1547. --*/
  1548. {
  1549. NTSTATUS Status = STATUS_SUCCESS;
  1550. if (SP_IS_UPGRADE_GRAPHICS_MODE() && GraphicsThreadHandle) {
  1551. //
  1552. // Stop the primary upgrade graphics thread
  1553. //
  1554. UpgradeGraphicsThreadSetStop(TRUE);
  1555. //
  1556. // Wait for the graphics thread to terminate
  1557. //
  1558. Status = ZwWaitForSingleObject(GraphicsThreadHandle, FALSE, NULL);
  1559. //
  1560. // Switch back to textmode
  1561. //
  1562. spvidSpecificReInitialize();
  1563. }
  1564. return Status;
  1565. }