Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2163 lines
52 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. if (hAnimatedBitmap->ThreadHandle){
  786. ZwClose(hAnimatedBitmap->ThreadHandle);
  787. }
  788. //
  789. // Delete each bitmap
  790. //
  791. for (Index=0;
  792. ((Index < MAX_ANIMATED_BITMAPS) && hAnimatedBitmap->Bitmaps[Index]);
  793. Index++) {
  794. if (NT_SUCCESS(Status)) {
  795. Status = TextmodeBitmapDelete(hAnimatedBitmap->Bitmaps[Index]);
  796. }
  797. }
  798. //
  799. // Free the animated bitmap
  800. //
  801. SpMemFree(hAnimatedBitmap);
  802. }
  803. return Status;
  804. }
  805. NTSTATUS
  806. TextmodeAnimateBitmapAnimateNext(
  807. IN TM_ANIMATED_BITMAP_HANDLE hBitmap
  808. )
  809. /*++
  810. Routine Description:
  811. Animates rather draws the next bitmap in the sequence.
  812. Arguments:
  813. hBitmap - Handle to the animated bitmap object
  814. Return Value:
  815. STATUS_SUCCESS, if successful, otherwise appropriate
  816. error code.
  817. --*/
  818. {
  819. TM_BITMAP_HANDLE hCurrBitmap;
  820. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  821. if (hBitmap) {
  822. hCurrBitmap = hBitmap->Bitmaps[hBitmap->CurrentBitmap];
  823. Status = TextmodeBitmapDisplay( hCurrBitmap, hBitmap->X, hBitmap->Y);
  824. hBitmap->CurrentBitmap++;
  825. if ((hBitmap->CurrentBitmap >= MAX_ANIMATED_BITMAPS) ||
  826. (hBitmap->Bitmaps[hBitmap->CurrentBitmap] == NULL)) {
  827. hBitmap->CurrentBitmap = 0; // start over again
  828. }
  829. }
  830. return Status;
  831. }
  832. NTSTATUS
  833. TextmodeAnimatedBitmapAnimate(
  834. IN TM_ANIMATED_BITMAP_HANDLE hBitmap,
  835. IN ULONG X,
  836. IN ULONG Y,
  837. IN ULONG Speed
  838. )
  839. /*++
  840. Routine Description:
  841. Starts the animation for the given animated bitmap by
  842. drawing the bitmaps in sequence at the specified
  843. coordinates.
  844. Note : This call would create a separate system
  845. thread for actually animating the bitmap and would return
  846. immediately.
  847. Arguments:
  848. hBitmap - Handle to the animated bitmap object
  849. X - Top left X coordinate for the animation space
  850. Y - Top left Y coordinate for the animation space
  851. Speed - Time interval between changing of bitmaps
  852. in animation sequence, in milliseconds.
  853. Return Value:
  854. STATUS_SUCCESS, if successful, otherwise appropriate
  855. error code.
  856. --*/
  857. {
  858. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  859. if (hBitmap) {
  860. hBitmap->FlipTime = Speed;
  861. hBitmap->X = X;
  862. hBitmap->Y = Y;
  863. Status = PsCreateSystemThread(&(hBitmap->ThreadHandle),
  864. THREAD_ALL_ACCESS,
  865. NULL,
  866. NtCurrentProcess(),
  867. NULL,
  868. TextmodeAnimatedBitmapAnimator,
  869. hBitmap);
  870. }
  871. return Status;
  872. }
  873. VOID
  874. TextmodeAnimatedBitmapAnimator(
  875. IN PVOID Context
  876. )
  877. /*++
  878. Routine Description:
  879. The worker routine which runs as a separate thread doing
  880. the actual animation for a animated bitmap.
  881. Arguments:
  882. Context - Handle to the animated bitmap object type cast
  883. into PVOID type.
  884. Return Value:
  885. None.
  886. --*/
  887. {
  888. LARGE_INTEGER DelayTime;
  889. TM_ANIMATED_BITMAP_HANDLE hBitmap = (TM_ANIMATED_BITMAP_HANDLE)Context;
  890. TM_BITMAP_HANDLE hCurrBitmap = NULL;
  891. if (Context) {
  892. BOOLEAN StopAnimating = FALSE;
  893. NTSTATUS Status;
  894. DelayTime.HighPart = -1; // relative time
  895. DelayTime.LowPart = (ULONG)(-10000 * hBitmap->FlipTime); // secs in 100ns interval
  896. Status = TextmodeAnimatedBitmapGetStopAnimating(hBitmap, &StopAnimating);
  897. while (NT_SUCCESS(Status) && !StopAnimating) {
  898. hCurrBitmap = hBitmap->Bitmaps[hBitmap->CurrentBitmap];
  899. TextmodeBitmapDisplay(hCurrBitmap, hBitmap->X, hBitmap->Y);
  900. KeDelayExecutionThread(KernelMode, FALSE, &DelayTime);
  901. hBitmap->CurrentBitmap++;
  902. if ((hBitmap->CurrentBitmap >= MAX_ANIMATED_BITMAPS) ||
  903. (hBitmap->Bitmaps[hBitmap->CurrentBitmap] == NULL)) {
  904. hBitmap->CurrentBitmap = 0; // start over again
  905. }
  906. Status = TextmodeAnimatedBitmapGetStopAnimating(hBitmap, &StopAnimating);
  907. }
  908. }
  909. PsTerminateSystemThread(STATUS_SUCCESS);
  910. }
  911. ////////////////////////////////////////////////////////////////
  912. //
  913. // VGA graphics methods
  914. //
  915. // Note : VgaXXXX rountines are defined basically
  916. // to segregate the video memory update routines
  917. // from the other abstractions. Right now most of
  918. // these routine delegate the actual work to the
  919. // real implementation in bootvid.dll, but in
  920. // future if bootvid.dll goes away, all we need
  921. // to do is implement this interface.
  922. // Also note that, these routine synchronize the
  923. // access, so that only one thread at a time
  924. // updates the video memory.
  925. //
  926. ////////////////////////////////////////////////////////////////
  927. __inline
  928. VOID
  929. VgaDisplayAcquireLock(
  930. VOID
  931. )
  932. /*++
  933. Routine Description:
  934. Acquires the lock to the video memory, so that
  935. only one thread a time writes to the video memory.
  936. Note : If the lock is already held by another thread,
  937. then the calling thread is put to sleep. The calling
  938. thread wakes up after every 100 millisecond and
  939. checks for the lock. It falls out of sleep based on
  940. whether the lock is already held or not.
  941. Arguments:
  942. None.
  943. Return Value:
  944. None.
  945. --*/
  946. {
  947. KIRQL OldIrql;
  948. KeAcquireSpinLock(&VgaDisplayLock, &OldIrql);
  949. while (InVgaDisplay) {
  950. LARGE_INTEGER DelayTime;
  951. DelayTime.HighPart = -1; // relative time
  952. DelayTime.LowPart = (ULONG)(-10000 * 100); // 100ms interval
  953. KeReleaseSpinLock(&VgaDisplayLock, OldIrql);
  954. KeDelayExecutionThread(KernelMode, FALSE, &DelayTime);
  955. KeAcquireSpinLock(&VgaDisplayLock, &OldIrql);
  956. }
  957. InVgaDisplay = TRUE;
  958. KeReleaseSpinLock(&VgaDisplayLock, OldIrql);
  959. }
  960. __inline
  961. VOID
  962. VgaDisplayReleaseLock(
  963. VOID
  964. )
  965. /*++
  966. Routine Description:
  967. Release the video memory lock which was held.
  968. Arguments:
  969. None.
  970. Return Value:
  971. None.
  972. --*/
  973. {
  974. KIRQL OldIrql;
  975. KeAcquireSpinLock(&VgaDisplayLock, &OldIrql);
  976. InVgaDisplay = FALSE;
  977. KeReleaseSpinLock(&VgaDisplayLock, OldIrql);
  978. }
  979. NTSTATUS
  980. VgaGraphicsInit(
  981. PSP_VIDEO_VARS VideoVars
  982. )
  983. /*++
  984. Routine Description:
  985. Initializes the video card and switches it into
  986. 640 * 480 * 16 colors mode.
  987. Arguments:
  988. VideoVars - Pointer to SP_VIDEO_VARS containing
  989. graphics mode index and handle to the
  990. display.
  991. Return Value:
  992. Appropriate NTSTATUS value.
  993. --*/
  994. {
  995. NTSTATUS Status;
  996. IO_STATUS_BLOCK IoStatusBlock;
  997. VIDEO_MODE VideoMode;
  998. VgaDisplayAcquireLock();
  999. //
  1000. // Set the desired graphics mode.
  1001. //
  1002. VideoMode.RequestedMode = VideoVars->GraphicsModeInfo.ModeIndex;
  1003. Status = ZwDeviceIoControlFile(VideoVars->hDisplay,
  1004. NULL,
  1005. NULL,
  1006. NULL,
  1007. &IoStatusBlock,
  1008. IOCTL_VIDEO_SET_CURRENT_MODE,
  1009. &VideoMode,
  1010. sizeof(VideoMode),
  1011. NULL,
  1012. 0);
  1013. if(NT_SUCCESS(Status)) {
  1014. VidInitialize(FALSE);
  1015. VidResetDisplay(FALSE);
  1016. }
  1017. VgaDisplayReleaseLock();
  1018. return Status;
  1019. }
  1020. NTSTATUS
  1021. VgaGraphicsTerminate(
  1022. PSP_VIDEO_VARS VideoVars
  1023. )
  1024. /*++
  1025. Routine Description:
  1026. Terminates the 640 * 480 * 16 color mode & switches
  1027. it back to regular text mode. Also clears the display.
  1028. Arguments:
  1029. VideoVars - Pointer to SP_VIDEO_VARS containing
  1030. text mode index and handle to the
  1031. display.
  1032. Return Value:
  1033. Appropriate NTSTATUS value.
  1034. --*/
  1035. {
  1036. NTSTATUS Status;
  1037. IO_STATUS_BLOCK IoStatusBlock;
  1038. VIDEO_MODE VideoMode;
  1039. VgaDisplayAcquireLock();
  1040. VidResetDisplay(FALSE);
  1041. //
  1042. // Switch the adapter to textmode again.
  1043. //
  1044. VideoMode.RequestedMode = VideoVars->VideoModeInfo.ModeIndex;
  1045. Status = ZwDeviceIoControlFile(VideoVars->hDisplay,
  1046. NULL,
  1047. NULL,
  1048. NULL,
  1049. &IoStatusBlock,
  1050. IOCTL_VIDEO_SET_CURRENT_MODE,
  1051. &VideoMode,
  1052. sizeof(VideoMode),
  1053. NULL,
  1054. 0);
  1055. VgaDisplayReleaseLock();
  1056. return Status;
  1057. }
  1058. __inline
  1059. VOID
  1060. VgaGraphicsSolidColorFill(
  1061. IN ULONG x1,
  1062. IN ULONG y1,
  1063. IN ULONG x2,
  1064. IN ULONG y2,
  1065. IN ULONG Color
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. Fills the given rectangle with the specified
  1070. color.
  1071. Arguments:
  1072. x1 - Top left x coordinate
  1073. y1 - Top left y coordinate
  1074. x2 - Bottom right x coordinate
  1075. y2 - Bottom right y coordinate
  1076. Color - Index into the current palette table
  1077. indicating the color to be filled inside
  1078. the rectangle.
  1079. Return Value:
  1080. None.
  1081. --*/
  1082. {
  1083. VgaDisplayAcquireLock();
  1084. VidSolidColorFill(x1, y1, x2, y2, Color);
  1085. VgaDisplayReleaseLock();
  1086. }
  1087. __inline
  1088. VOID
  1089. VgaGraphicsBitBlt(
  1090. IN PUCHAR Buffer,
  1091. IN ULONG x,
  1092. IN ULONG y
  1093. )
  1094. /*++
  1095. Routine Description:
  1096. BitBlts the given bitmap at the specified
  1097. coordinates.
  1098. Arguments:
  1099. Buffer - The actual bitmap date (i.e. starting
  1100. with the color table information)
  1101. x - Top left x coordinate
  1102. y - Top left y coordinate
  1103. Return Value:
  1104. None.
  1105. --*/
  1106. {
  1107. VgaDisplayAcquireLock();
  1108. VidBitBlt(Buffer, x, y);
  1109. VgaDisplayReleaseLock();
  1110. }
  1111. ////////////////////////////////////////////////////////////////
  1112. //
  1113. // Upgrade graphics routines
  1114. //
  1115. ////////////////////////////////////////////////////////////////
  1116. __inline
  1117. BOOLEAN
  1118. QuitGraphicsThread(
  1119. VOID
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. Indiates whether the primary upgrade graphics thread
  1124. needs to be stopped or not based on user input
  1125. (ESC key).
  1126. Note : This feature is only enable in pre-release
  1127. builds.
  1128. Arguments:
  1129. None.
  1130. Return Value:
  1131. TRUE if the upgrade graphics thread needs to be stopped
  1132. else FALSE.
  1133. --*/
  1134. {
  1135. BOOLEAN Result = FALSE;
  1136. /*
  1137. #ifdef PRERELEASE
  1138. Result = SpInputIsKeyWaiting() && (SpInputGetKeypress() == ASCI_ESC);
  1139. #endif
  1140. */
  1141. return Result;
  1142. }
  1143. NTSTATUS
  1144. UpgradeGraphicsInit(
  1145. VOID
  1146. )
  1147. /*++
  1148. Routine Description:
  1149. Does the needed global initialization for the
  1150. upgrade graphics mode.
  1151. Arguments:
  1152. None.
  1153. Return Value:
  1154. STATUS_SUCCESS, if successful with initialzation,
  1155. otherwise appropriate error code
  1156. --*/
  1157. {
  1158. NTSTATUS Status = STATUS_SUCCESS;
  1159. //
  1160. // Initialize global spin locks
  1161. //
  1162. KeInitializeSpinLock(&VgaDisplayLock);
  1163. KeInitializeSpinLock(&ProgressLock);
  1164. KeInitializeSpinLock(&GraphicsThreadLock);
  1165. return Status;
  1166. }
  1167. NTSTATUS
  1168. UpgradeGraphicsStart(
  1169. VOID
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. Starts of the upgrade graphics
  1174. Arguments:
  1175. None.
  1176. Return Value:
  1177. STATUS_SUCCESS, if the upgrade graphics was started,
  1178. else appropriate error code.
  1179. --*/
  1180. {
  1181. NTSTATUS Status;
  1182. Status = PsCreateSystemThread(&GraphicsThreadHandle,
  1183. THREAD_ALL_ACCESS,
  1184. NULL,
  1185. NtCurrentProcess(),
  1186. NULL,
  1187. UpgradeGraphicsThread,
  1188. NULL);
  1189. #ifdef _GRAPHICS_TESTING_
  1190. Status = ZwWaitForSingleObject(GraphicsThreadHandle, FALSE, NULL);
  1191. #endif
  1192. return Status;
  1193. }
  1194. VOID
  1195. UpgradeGraphicsThread(
  1196. IN PVOID Context
  1197. )
  1198. /*++
  1199. Routine Description:
  1200. The primary upgrade graphics worker thread, which
  1201. paints the background, updates the progress bar
  1202. and starts the animation.
  1203. Arguments:
  1204. Context - Ignored
  1205. Return Value:
  1206. None.
  1207. --*/
  1208. {
  1209. BOOLEAN Stop = FALSE;
  1210. TM_GRAPHICS_PRGBAR_HANDLE hProgBar;
  1211. TM_ANIMATED_BITMAP_HANDLE hAnimation = NULL;
  1212. TM_BITMAP_HANDLE hBitmap = NULL;
  1213. LARGE_INTEGER DelayTime;
  1214. NTSTATUS Status;
  1215. WCHAR Buffer[MAX_PATH];
  1216. ULONG BitmapIds[] = {
  1217. IDB_WORKING1, IDB_WORKING2,
  1218. IDB_WORKING3, IDB_WORKING4,
  1219. IDB_WORKING5, IDB_WORKING6,
  1220. IDB_WORKING7, IDB_WORKING8,
  1221. IDB_WORKING9, IDB_WORKING10,
  1222. IDB_WORKING11, IDB_WORKING12,
  1223. IDB_WORKING13, IDB_WORKING14,
  1224. IDB_WORKING15, IDB_WORKING16,
  1225. IDB_WORKING17, IDB_WORKING18,
  1226. IDB_WORKING19, IDB_WORKING20,
  1227. 0 };
  1228. ULONG SrvBitmapIds[] = {
  1229. IDB_SRV_WORKING1, IDB_SRV_WORKING2,
  1230. IDB_SRV_WORKING3, IDB_SRV_WORKING4,
  1231. IDB_SRV_WORKING5, IDB_SRV_WORKING6,
  1232. IDB_SRV_WORKING7, IDB_SRV_WORKING8,
  1233. IDB_SRV_WORKING9, IDB_SRV_WORKING10,
  1234. IDB_SRV_WORKING11, IDB_SRV_WORKING12,
  1235. IDB_SRV_WORKING13, IDB_SRV_WORKING14,
  1236. IDB_SRV_WORKING15, IDB_SRV_WORKING16,
  1237. IDB_SRV_WORKING17, IDB_SRV_WORKING18,
  1238. IDB_SRV_WORKING19, IDB_SRV_WORKING20,
  1239. 0 };
  1240. //
  1241. // Initialize graphics mode
  1242. //
  1243. Status = VgaGraphicsInit(&VideoVars);
  1244. if (NT_SUCCESS(Status)) {
  1245. //
  1246. // Create the background bitmap
  1247. //
  1248. if (Win9xRollback) {
  1249. hBitmap = TextmodeBitmapCreate(IDB_RESTORE_BK);
  1250. } else {
  1251. if (!AdvancedServer)
  1252. {
  1253. hBitmap = TextmodeBitmapCreate(IDB_BACKGROUND1);
  1254. }
  1255. else
  1256. {
  1257. hBitmap = TextmodeBitmapCreate(IDB_BACKGROUND2);
  1258. }
  1259. }
  1260. if (hBitmap) {
  1261. //
  1262. // Create the animated bitmap
  1263. //
  1264. if (!AdvancedServer)
  1265. {
  1266. hAnimation = TextmodeAnimatedBitmapCreate(BitmapIds);
  1267. }
  1268. else
  1269. {
  1270. hAnimation = TextmodeAnimatedBitmapCreate(SrvBitmapIds);
  1271. }
  1272. if (hAnimation) {
  1273. //
  1274. // Create the bitmapped graphics progress bar
  1275. //
  1276. hProgBar = TextmodeGraphicsProgBarCreateUsingBmps(28, 352,
  1277. 123, 14,
  1278. IDB_BACKCELL, IDB_FORECELL, 0);
  1279. if (hProgBar) {
  1280. BOOLEAN Refreshed = FALSE;
  1281. ULONG Fill = 0;
  1282. BOOLEAN Increase = TRUE;
  1283. //
  1284. // Render background
  1285. //
  1286. TextmodeBitmapDisplay(hBitmap, 0, 0);
  1287. //
  1288. // Start the animation
  1289. //
  1290. Status = TextmodeAnimatedBitmapAnimate(hAnimation, 542, 460, 100);
  1291. //
  1292. // Note : Failure to start the animation is not a critical
  1293. // error
  1294. //
  1295. if (!NT_SUCCESS(Status)) {
  1296. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL,
  1297. "SETUP:Upgrade graphics thread failed to "
  1298. "animate : %lx error code\r\n",
  1299. Status));
  1300. }
  1301. DelayTime.HighPart = -1; // relative time
  1302. DelayTime.LowPart = (ULONG)(-10000 * 500); // 1000 msec interval
  1303. //
  1304. // Render graphics progress bar
  1305. //
  1306. TextmodeGraphicsProgBarRefresh(hProgBar, TRUE);
  1307. Fill = GetSetupProgress();
  1308. Stop = UpgradeGraphicsThreadGetStop();
  1309. //
  1310. // Continue on till user asks us to stop, or the main
  1311. // textmode thread encounters an error and stops us
  1312. //
  1313. while (!Stop && !QuitGraphicsThread()) {
  1314. //
  1315. // Update the graphics progress bar
  1316. //
  1317. TextmodeGraphicsProgBarUpdate(hProgBar, Fill);
  1318. //
  1319. // Sleep for 0.5 secs
  1320. //
  1321. KeDelayExecutionThread(KernelMode, FALSE, &DelayTime);
  1322. Fill = GetSetupProgress();
  1323. Stop = UpgradeGraphicsThreadGetStop();
  1324. #ifdef _GRAPHICS_TESTING_
  1325. if (Increase) {
  1326. if (Fill < 100) {
  1327. Fill++;
  1328. SetSetupProgress(Fill);
  1329. } else {
  1330. Increase = FALSE;
  1331. }
  1332. }
  1333. if (!Increase) {
  1334. if (Fill <= 0) {
  1335. Increase = TRUE;
  1336. } else {
  1337. Fill--;
  1338. SetSetupProgress(Fill);
  1339. }
  1340. }
  1341. #endif _GRAPHICS_TESTING_
  1342. }
  1343. //
  1344. // Was graphics thread stopped by the main
  1345. // textmode setup, then most probably we
  1346. // encountered an error or user intervention
  1347. // is required
  1348. //
  1349. Stop = UpgradeGraphicsThreadGetStop();
  1350. //
  1351. // Delete the graphics progress bar
  1352. //
  1353. TextmodeGraphicsProgBarDelete(hProgBar);
  1354. }
  1355. //
  1356. // Stop the animation, and delete the animated
  1357. // bitmap object
  1358. //
  1359. TextmodeAnimatedBitmapDelete(hAnimation);
  1360. }
  1361. //
  1362. // Delete the background bitmap object
  1363. //
  1364. TextmodeBitmapDelete(hBitmap);
  1365. }
  1366. }
  1367. //
  1368. // If graphics thread was stopped by user intervention
  1369. // then we need to switch to textmode
  1370. //
  1371. if (!Stop) {
  1372. spvidSpecificReInitialize();
  1373. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  1374. }
  1375. PsTerminateSystemThread(Status);
  1376. }
  1377. VOID
  1378. GraphicsModeProgressUpdate(
  1379. IN TM_SETUP_MAJOR_EVENT MajorEvent,
  1380. IN TM_SETUP_MINOR_EVENT MinorEvent,
  1381. IN PVOID Context,
  1382. IN PVOID EventData
  1383. )
  1384. /*++
  1385. Routine Description:
  1386. Callback which updates the over all progress during
  1387. upgrade graphics mode.
  1388. Note : The single progress bar in upgrade graphics mode
  1389. is used in place of all the various different
  1390. progress bars which are used through out the
  1391. textmode.
  1392. The single progress bar is divided into ranges
  1393. as shown below for the various major events
  1394. across the textmode setup:
  1395. ------------------------------------------
  1396. Range(%) MajorEvent
  1397. ------------------------------------------
  1398. 00-05 InitializationEvent
  1399. 05-20 PartitioningEvent
  1400. (Includes chkdsk)
  1401. 20-40 Backup (if enabled)
  1402. 20-40 Uninstall (if enabled)
  1403. 20/40-90 FileCopyEvent
  1404. (Actual file copying)
  1405. 90-98 SavingSettingsEvent
  1406. 98-100 SetupCompleted
  1407. ------------------------------------------
  1408. Arguments:
  1409. MajorEvent - Indicates the major type of the event
  1410. which happened.
  1411. MinorEvent - Indicates the minor type of the event
  1412. which happened.
  1413. Context - Context data which was registered when
  1414. we register for callback.
  1415. EventData - More detailed event specific data
  1416. Return Value:
  1417. None.
  1418. --*/
  1419. {
  1420. static BOOLEAN Add = TRUE;
  1421. static ULONG LastPercentage = 0;
  1422. static ULONG BackupAllocation = 0;
  1423. BOOLEAN SkipSpew = FALSE;
  1424. ULONG Delta = 0;
  1425. ULONG PercentageFill = 0;
  1426. PercentageFill = GetSetupProgress();
  1427. switch (MajorEvent) {
  1428. case InitializationEvent:
  1429. switch (MinorEvent) {
  1430. case InitializationStartEvent:
  1431. PercentageFill = 2;
  1432. break;
  1433. case InitializationEndEvent:
  1434. PercentageFill = 5;
  1435. break;
  1436. default:
  1437. break;
  1438. }
  1439. break;
  1440. case PartitioningEvent:
  1441. switch (MinorEvent) {
  1442. case ValidatePartitionEvent:
  1443. Delta = (15 * (*(PULONG)EventData)) / 200;
  1444. PercentageFill = 5 + Delta;
  1445. break;
  1446. case FormatPartitionEvent:
  1447. //
  1448. // In cases of upgrade (we won't be formatting)
  1449. //
  1450. break;
  1451. default:
  1452. break;
  1453. }
  1454. break;
  1455. case FileCopyEvent:
  1456. switch (MinorEvent) {
  1457. case FileCopyStartEvent:
  1458. LastPercentage = PercentageFill = 20 + BackupAllocation;
  1459. break;
  1460. case OneFileCopyEvent:
  1461. Delta = ((70 - BackupAllocation) * (*(PULONG)EventData)) / 100;
  1462. PercentageFill = 20 + Delta + BackupAllocation;
  1463. if ((PercentageFill - LastPercentage) > 5) {
  1464. LastPercentage = PercentageFill;
  1465. } else {
  1466. SkipSpew = TRUE;
  1467. }
  1468. break;
  1469. case FileCopyEndEvent:
  1470. PercentageFill = 90;
  1471. break;
  1472. default:
  1473. break;
  1474. }
  1475. break;
  1476. case BackupEvent:
  1477. switch (MinorEvent) {
  1478. case BackupStartEvent:
  1479. LastPercentage = PercentageFill = 20;
  1480. BackupAllocation = 20;
  1481. break;
  1482. case OneFileBackedUpEvent:
  1483. Delta = (20 * (*(PULONG)EventData)) / 100;
  1484. PercentageFill = 20 + Delta;
  1485. if ((PercentageFill - LastPercentage) > 5) {
  1486. LastPercentage = PercentageFill;
  1487. } else {
  1488. SkipSpew = TRUE;
  1489. }
  1490. break;
  1491. case BackupEndEvent:
  1492. PercentageFill = 40;
  1493. break;
  1494. }
  1495. break;
  1496. case UninstallEvent:
  1497. switch (MinorEvent) {
  1498. case UninstallStartEvent:
  1499. LastPercentage = PercentageFill = 20;
  1500. break;
  1501. case UninstallUpdateEvent:
  1502. Delta = (70 * (*(PULONG)EventData)) / 100;
  1503. PercentageFill = 20 + Delta;
  1504. if ((PercentageFill - LastPercentage) > 5) {
  1505. LastPercentage = PercentageFill;
  1506. } else {
  1507. SkipSpew = TRUE;
  1508. }
  1509. break;
  1510. case UninstallEndEvent:
  1511. PercentageFill = 90;
  1512. break;
  1513. default:
  1514. break;
  1515. }
  1516. break;
  1517. case SavingSettingsEvent:
  1518. switch (MinorEvent) {
  1519. case SavingSettingsStartEvent:
  1520. PercentageFill = 90;
  1521. break;
  1522. case SaveHiveEvent:
  1523. if (PercentageFill < 98) {
  1524. if (Add) {
  1525. PercentageFill += 1;
  1526. Add = FALSE;
  1527. } else {
  1528. Add = TRUE;
  1529. }
  1530. }
  1531. break;
  1532. case SavingSettingsEndEvent:
  1533. if (PercentageFill < 98) {
  1534. PercentageFill = 98;
  1535. }
  1536. break;
  1537. default:
  1538. break;
  1539. }
  1540. break;
  1541. case SetupCompletedEvent:
  1542. PercentageFill = 100;
  1543. break;
  1544. default:
  1545. break;
  1546. }
  1547. if (!SkipSpew) {
  1548. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL,
  1549. "Setup Event : %ld, %ld, %ld, [%ld], (%ld)\n",
  1550. MajorEvent,
  1551. MinorEvent,
  1552. EventData ? *(PULONG)EventData : 0,
  1553. Delta,
  1554. PercentageFill
  1555. ));
  1556. }
  1557. SetSetupProgress(PercentageFill);
  1558. }
  1559. NTSTATUS
  1560. SpvidSwitchToTextmode(
  1561. VOID
  1562. )
  1563. /*++
  1564. Routine Description:
  1565. Switches from upgrade graphics mode to the regular
  1566. textmode.
  1567. Note : The actual work of switching the graphics
  1568. back to the regular VGA textmode happens
  1569. as a method in video specific reinitialize
  1570. method.
  1571. Arguments:
  1572. None.
  1573. Return Value:
  1574. STATUS_SUCCESS, if successful, otherwise appropirate
  1575. error code
  1576. --*/
  1577. {
  1578. NTSTATUS Status = STATUS_SUCCESS;
  1579. if (SP_IS_UPGRADE_GRAPHICS_MODE()) {
  1580. if (GraphicsThreadHandle){
  1581. //
  1582. // Stop the primary upgrade graphics thread
  1583. //
  1584. UpgradeGraphicsThreadSetStop(TRUE);
  1585. //
  1586. // Wait for the graphics thread to terminate
  1587. //
  1588. Status = ZwWaitForSingleObject(GraphicsThreadHandle, FALSE, NULL);
  1589. ZwClose(GraphicsThreadHandle);
  1590. }
  1591. //
  1592. // Switch back to textmode
  1593. //
  1594. spvidSpecificReInitialize();
  1595. }
  1596. return Status;
  1597. }