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.

176 lines
3.6 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. gdtsup.c
  5. Abstract:
  6. This module implements interfaces that support manipulation of i386 GDTs.
  7. These entry points only exist on i386 machines.
  8. Author:
  9. Dave Hastings (daveh) 28 May 1991
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGELK, KeI386SetGdtSelector)
  17. #pragma alloc_text(PAGE, Ke386GetGdtEntryThread)
  18. #endif
  19. VOID
  20. Ke386GetGdtEntryThread(
  21. IN PKTHREAD Thread,
  22. IN ULONG Offset,
  23. IN PKGDTENTRY Descriptor
  24. )
  25. /*++
  26. Routine Description:
  27. This routine returns the contents of an entry in the GDT. If the
  28. entry is thread specific, the entry for the specified thread is
  29. created and returned (KGDT_LDT, and KGDT_R3_TEB). If the selector
  30. is processor dependent, the entry for the current processor is
  31. returned (KGDT_R0_PCR).
  32. Arguments:
  33. Thread -- Supplies a pointer to the thread to return the entry for.
  34. Offset -- Supplies the offset in the Gdt. This value must be 0
  35. mod 8.
  36. Descriptor -- Returns the contents of the Gdt descriptor
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. PKGDTENTRY Gdt;
  42. PKPROCESS Process;
  43. //
  44. // If the entry is out of range, don't return anything
  45. //
  46. if (Offset >= KGDT_NUMBER * sizeof(KGDTENTRY)) {
  47. return ;
  48. }
  49. if (Offset == KGDT_LDT) {
  50. //
  51. // Materialize Ldt selector
  52. //
  53. Process = Thread->Process;
  54. RtlCopyMemory( Descriptor,
  55. &(Process->LdtDescriptor),
  56. sizeof(KGDTENTRY)
  57. );
  58. } else {
  59. //
  60. // Copy Selector from Ldt
  61. //
  62. // N.B. We will change the base later, if it is KGDT_R3_TEB
  63. //
  64. Gdt = KiPcr()->GDT;
  65. RtlCopyMemory(Descriptor, (PCHAR)Gdt + Offset, sizeof(KGDTENTRY));
  66. //
  67. // if it is the TEB selector, fix the base
  68. //
  69. if (Offset == KGDT_R3_TEB) {
  70. Descriptor->BaseLow = (USHORT)((ULONG)(Thread->Teb) & 0xFFFF);
  71. Descriptor->HighWord.Bytes.BaseMid =
  72. (UCHAR) ( ( (ULONG)(Thread->Teb) & 0xFF0000L) >> 16);
  73. Descriptor->HighWord.Bytes.BaseHi =
  74. (CHAR) ( ( (ULONG)(Thread->Teb) & 0xFF000000L) >> 24);
  75. }
  76. }
  77. return ;
  78. }
  79. NTSTATUS
  80. KeI386SetGdtSelector (
  81. ULONG Selector,
  82. PKGDTENTRY GdtValue
  83. )
  84. /*++
  85. Routine Description:
  86. Sets a GDT entry obtained via KeI386AllocateGdtSelectors to the supplied
  87. GdtValue.
  88. Arguments:
  89. Selector - Which GDT to set
  90. GdtValue - GDT value to set into GDT
  91. Return Value:
  92. status code
  93. --*/
  94. {
  95. KAFFINITY TargetSet;
  96. PKPRCB Prcb;
  97. PKPCR Pcr;
  98. PKGDTENTRY GdtEntry;
  99. ULONG GdtIndex, BitNumber;
  100. PAGED_CODE ();
  101. //
  102. // Verify GDT entry passed, and it's above the kernel GDT values
  103. //
  104. GdtIndex = Selector >> 3;
  105. if ((Selector & 0x7) != 0 || GdtIndex < KGDT_NUMBER) {
  106. return STATUS_UNSUCCESSFUL;
  107. }
  108. //
  109. // Set GDT entry in each processor's GDT
  110. //
  111. TargetSet = KeActiveProcessors;
  112. while (TargetSet != 0) {
  113. KeFindFirstSetLeftAffinity(TargetSet, &BitNumber);
  114. ClearMember(BitNumber, TargetSet);
  115. Prcb = KiProcessorBlock[BitNumber];
  116. Pcr = CONTAINING_RECORD (Prcb, KPCR, PrcbData);
  117. GdtEntry = Pcr->GDT + GdtIndex;
  118. // set it
  119. *GdtEntry = *GdtValue;
  120. }
  121. return STATUS_SUCCESS;
  122. }