Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
an interseting tutoriel

Thanks to /g/Windows XP friendly thread on 4chan
Thanks to >>77965472 on 4chan
Thanks to @MrBruh discord

  • set system time to 2003-08-01(yyyy-mm-dd) before extraction
  • extract cabs with batch file that comes with it (do not forget to edit x.cmd for the correct extract paths)
  • unset Read Only on NT folder (and subfolders/files)
  • cd to NT directory
  • import tools\driver.pfx (double click and hit next on the import wizard)
  • tools\razzle free offline (or 'tools\razzle offline' for debug)
  • wait for shit, close the notepad that opens
  • run path tools\sp;%path%
  • REM lines 154-160 in tools\sp\package.cmd because some TabletPC stuff missing
  • \NT\base\ntos\ex\exp.h \NT\inetsrv\msmq\src\lib\ex\lib\exinit.c \NT\base\crts\crtw32\time\systime.c replacement down below, replace em!
  • run CheckTestRoot.cmd and CheckTestPCA.cmd
  • perl tools\timebuild.pl -NOCLEANBUILD -NOSYNC -NOSCORCH
  • wait for build ...
  • if any errors in build.err, run build /ZP (race conditions in timebuild might have made stuff build before their dependency, running build /ZP will try the failed stuff again)
  • hopefully now build.err is empty (probably have directui.lib missing error though, either copy from XP or see if there's a built directui.lib and copy to \public\internal\windows\lib\i386)
  • if you copied directui etc run build /ZP again
  • once build.err is empty, copy missing files (winlogon.exe & other missing bins, TBA) into binaries.x86fre
  • then run perl tools\timebuild.pl -NOCLEANBUILD -NOSYNC -NOSCORCH -RESUME
  • do tools\postbuild to start the process of build the iso from bins
  • after all the steps check binaries.x86fre/build_logs/postbuild.err and grab all the missing files mentioned in there from ISO
  • edit tools/postbuildscripts/pbuild.dat and comment out the sxs_make_asms_cabs lines
  • grab asms01.cab from w2k3 ISO and put that into binaries.x86fre, and binaries.x86fre/srv/i386, replacing the one thats there
  • run timebuild one more time and it should sign all the shit for you, now you should have a working setup inside binaries.x86fre/srv/
  • finally use oscdimg to turn that into bootable iso also the oscdimg params are

oscdimg -n -betfsboot.com D:\binaries.x86fre\srv srv.iso assuming etfsboot.com is in your current folder

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
exinit.c
Abstract:
The module contains the the initialization code for the executive
component. It also contains the display string and shutdown system
services.
Author:
Steve Wood (stevewo) 31-Mar-1989
Revision History:
--*/
#include "exp.h"
#include <zwapi.h>
#include <inbv.h>
#include "safeboot.h"
#pragma alloc_text(INIT, ExInitPoolLookasidePointers)
#pragma alloc_text(INIT, ExInitSystem)
#pragma alloc_text(INIT, ExpInitSystemPhase0)
#pragma alloc_text(INIT, ExpInitSystemPhase1)
#pragma alloc_text(INIT, ExComputeTickCountMultiplier)
#pragma alloc_text(PAGE, NtShutdownSystem)
#pragma alloc_text(PAGE, ExSystemExceptionFilter)
#pragma alloc_text(INIT, ExInitializeSystemLookasideList)
//
// Tick count multiplier.
//
ULONG ExpTickCountMultiplier;
ULONG ExpHydraEnabled;
static ULONG ExpSuiteMask;
PVOID ExpControlKey[2];
HANDLE ExpProductTypeKey;
BOOLEAN ExpInTextModeSetup;
BOOLEAN ExpMultiUserTS;
ULONG KdDumpEnableOffset;
PKEY_VALUE_PARTIAL_INFORMATION ExpProductTypeValueInfo;
#define MAX_PRODUCT_TYPE_BYTES 18 // lanmannt, servernt, winnt are only options
extern WCHAR CmSuiteBuffer[128];
extern ULONG CmSuiteBufferLength;
extern ULONG CmSuiteBufferType;
extern POBJECT_TYPE CmpKeyObjectType;
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("INITCONST")
#endif
#define EXP_ST_SETUP 0
#define EXP_ST_SETUP_TYPE 1
#define EXP_ST_SYSTEM_PREFIX 2
#define EXP_ST_PRODUCT_OPTIONS 3
#define EXP_ST_PRODUCT_TYPE 4
#define EXP_ST_LANMANNT 5
#define EXP_ST_SERVERNT 6
#define EXP_ST_WINNT 7
#define EXP_ST_PRODUCT_SUITE 8
#define EXP_ST_LICENSE_INFO 9
#define EXP_ST_CONCURRENT_LIMIT 10
#define EXP_ST_SUITE_SBS 11
#define EXP_ST_SUITE_ENTERPRISE 12
#define EXP_ST_SUITE_COMSRV 13
#define EXP_ST_SUITE_BACKOFFICE 14
#define EXP_ST_SUITE_SBSREST 15
#define EXP_ST_SUITE_TRMSRV 16
#define EXP_ST_SUITE_EMBED 17
#define EXP_ST_SUITE_DTC 18
#define EXP_ST_SUITE_PERSONAL 19
#define EXP_ST_SUITE_BLADE 20
#define EXP_ST_SUITE_EMBEDRES 21
#define EXP_ST_SUITE_SECURITY 22
LPWSTR
static
ExpStrings[23] = {
L"\\Registry\\Machine\\System\\Setup",
L"SetupType",
L"SystemPrefix",
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ProductOptions",
L"ProductType",
L"LanmanNT",
L"ServerNT",
L"WinNT",
L"ProductSuite",
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LicenseInfoSuites",
L"ConcurrentLimit",
L"Small Business",
L"Enterprise",
L"CommunicationServer",
L"BackOffice",
L"Small Business(Restricted)",
L"Terminal Server",
L"EmbeddedNT",
L"DataCenter",
L"Personal",
L"Blade",
L"Embedded(Restricted)",
L"Security Appliance"
};
ULONG
static
ExpSingleStringCheck(
LPWSTR s1
)
{
UNICODE_STRING str;
RtlInitUnicodeString(&str, s1);
return RtlComputeCrc32(0, str.Buffer, str.Length);
}
VOID
static
ExpStringCheck(
LPWSTR s1,
LPWSTR s2,
LPWSTR s3,
LPWSTR s4,
LPWSTR s5,
LPWSTR s6,
LPWSTR s7,
LPWSTR s8,
LPWSTR s9,
LPWSTR s10,
LPWSTR s11,
LPWSTR s12,
LPWSTR s13,
LPWSTR s14,
LPWSTR s15,
LPWSTR s16,
LPWSTR s17,
LPWSTR s18,
LPWSTR s19,
LPWSTR s20,
LPWSTR s21,
LPWSTR s22,
LPWSTR s23
)
{
ULONG Master[23] = {
0xf54d3d83,
0x6d3cbfaf,
0x1418a31c,
0xe7535704,
0x720e8093,
0x1aec49bf,
0x4d8f8978,
0xe00497a3,
0x9788c875,
0x6aa44e66,
0x17d632cf,
0x21bd473b,
0x72d33d9b,
0xdb4f8357,
0xbd7ed200,
0x064f25ee,
0x0c37a2ff,
0xee72022f,
0x52cc749d,
0x88742b75,
0x91e72956,
0x6b09dc7a,
0x21d28371
};
ULONG StringCheckV[23];
ULONG i;
StringCheckV[0] = ExpSingleStringCheck(s1);
StringCheckV[1] = ExpSingleStringCheck(s2);
StringCheckV[2] = ExpSingleStringCheck(s3);
StringCheckV[3] = ExpSingleStringCheck(s4);
StringCheckV[4] = ExpSingleStringCheck(s5);
StringCheckV[5] = ExpSingleStringCheck(s6);
StringCheckV[6] = ExpSingleStringCheck(s7);
StringCheckV[7] = ExpSingleStringCheck(s8);
StringCheckV[8] = ExpSingleStringCheck(s9);
StringCheckV[9] = ExpSingleStringCheck(s10);
StringCheckV[10] = ExpSingleStringCheck(s11);
StringCheckV[11] = ExpSingleStringCheck(s12);
StringCheckV[12] = ExpSingleStringCheck(s13);
StringCheckV[13] = ExpSingleStringCheck(s14);
StringCheckV[14] = ExpSingleStringCheck(s15);
StringCheckV[15] = ExpSingleStringCheck(s16);
StringCheckV[16] = ExpSingleStringCheck(s17);
StringCheckV[17] = ExpSingleStringCheck(s18);
StringCheckV[18] = ExpSingleStringCheck(s19);
StringCheckV[19] = ExpSingleStringCheck(s20);
StringCheckV[20] = ExpSingleStringCheck(s21);
StringCheckV[21] = ExpSingleStringCheck(s22);
StringCheckV[22] = ExpSingleStringCheck(s23);
for ( i=0;i<8;i++ ) {
if ( StringCheckV[i] != Master[i] ) {
KdDumpEnableOffset = 8;
}
}
}
VOID
ExInitPoolLookasidePointers (
VOID
)
/*++
Routine Description:
This function initializes the PRCB lookaside pointers to temporary
values that will be updated during phase 1 initialization.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Index;
PGENERAL_LOOKASIDE Lookaside;
PKPRCB Prcb;
//
// Initialize the paged and nonpaged small pool lookaside list
// pointers in the PRCB to temporarily point to the global pool
// lookaside lists. During phase 1 initialization per processor
// lookaside lists are allocated and the pointer to these lists
// are established in the PRCB of each processor.
//
Prcb = KeGetCurrentPrcb();
for (Index = 0; Index < POOL_SMALL_LISTS; Index += 1) {
Lookaside = &ExpSmallNPagedPoolLookasideLists[Index];
ExInitializeSListHead(&Lookaside->ListHead);
Prcb->PPNPagedLookasideList[Index].P = Lookaside;
Prcb->PPNPagedLookasideList[Index].L = Lookaside;
Lookaside = &ExpSmallPagedPoolLookasideLists[Index];
ExInitializeSListHead(&Lookaside->ListHead);
Prcb->PPPagedLookasideList[Index].P = Lookaside;
Prcb->PPPagedLookasideList[Index].L = Lookaside;
}
return;
}
BOOLEAN
ExInitSystem (
VOID
)
/*++
Routine Description:
This function initializes the executive component of the NT system.
It will perform Phase 0 or Phase 1 initialization as appropriate.
Arguments:
None.
Return Value:
A value of TRUE is returned if the initialization is successful. Otherwise
a value of FALSE is returned.
--*/
{
switch ( InitializationPhase ) {
case 0:
(void) ExpSystemOK(0, FALSE);
return ExpInitSystemPhase0();
case 1:
(void) ExpSystemOK(1, TRUE);
return ExpInitSystemPhase1();
default:
KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL, 3, InitializationPhase, 0, 0);
}
}
BOOLEAN
ExpInitSystemPhase0 (
VOID
)
/*++
Routine Description:
This function performs Phase 0 initialization of the executive component
of the NT system.
Arguments:
None.
Return Value:
A value of TRUE is returned if the initialization is success. Otherwise
a value of FALSE is returned.
--*/
{
ULONG Index;
BOOLEAN Initialized = TRUE;
PGENERAL_LOOKASIDE Lookaside;
//
// Initialize Resource objects, currently required during SE
// Phase 0 initialization.
//
if (ExpResourceInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Resource initialization failed\n"));
}
//
// Initialize query/set environment variable synchronization fast
// mutex.
//
ExInitializeFastMutex(&ExpEnvironmentLock);
//
// Initialize the key manipulation resource.
//
ExInitializeResourceLite(&ExpKeyManipLock);
//
// Initialize the paged and nonpaged small pool lookaside structures,
//
InitializeListHead(&ExPoolLookasideListHead);
for (Index = 0; Index < POOL_SMALL_LISTS; Index += 1) {
Lookaside = &ExpSmallNPagedPoolLookasideLists[Index];
ExInitializeSystemLookasideList(Lookaside,
NonPagedPool,
(Index + 1) * sizeof (POOL_BLOCK),
'looP',
256,
&ExPoolLookasideListHead);
Lookaside = &ExpSmallPagedPoolLookasideLists[Index];
ExInitializeSystemLookasideList(Lookaside,
PagedPool,
(Index + 1) * sizeof (POOL_BLOCK),
'looP',
256,
&ExPoolLookasideListHead);
}
//
// Initialize the nonpaged and paged system lookaside lists.
//
InitializeListHead(&ExNPagedLookasideListHead);
KeInitializeSpinLock(&ExNPagedLookasideLock);
InitializeListHead(&ExPagedLookasideListHead);
KeInitializeSpinLock(&ExPagedLookasideLock);
//
// Initialize the system paged and nonpaged lookaside list.
//
InitializeListHead(&ExSystemLookasideListHead);
return ExpSystemOK(2, Initialized);
}
BOOLEAN
ExpInitSystemPhase1 (
VOID
)
/*++
Routine Description:
This function performs Phase 1 initialization of the executive component
of the NT system.
Arguments:
None.
Return Value:
A value of TRUE is returned if the initialization succeeded. Otherwise
a value of FALSE is returned.
--*/
{
ULONG Index;
BOOLEAN Initialized = TRUE;
ULONG List;
PGENERAL_LOOKASIDE Lookaside;
PKPRCB Prcb;
//
// Initialize the ATOM package
//
RtlInitializeAtomPackage( 'motA' );
//
// Initialize pushlocks.
//
//ExpInitializePushLocks ();
//
// Initialize the worker threads.
//
if (!NT_SUCCESS (ExpWorkerInitialization())) {
Initialized = FALSE;
KdPrint(("Executive: Worker thread initialization failed\n"));
}
//
// Initialize the executive objects.
//
if (ExpEventInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Event initialization failed\n"));
}
if (ExpEventPairInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Event Pair initialization failed\n"));
}
if (ExpMutantInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Mutant initialization failed\n"));
}
if (ExpInitializeCallbacks() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Callback initialization failed\n"));
}
if (ExpSemaphoreInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Semaphore initialization failed\n"));
}
if (ExpTimerInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Timer initialization failed\n"));
}
if (ExpProfileInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Profile initialization failed\n"));
}
if (ExpUuidInitialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Uuid initialization failed\n"));
}
if (!NT_SUCCESS (ExpKeyedEventInitialization ())) {
Initialized = FALSE;
KdPrint(("Executive: Keyed event initialization failed\n"));
}
if (ExpWin32Initialization() == FALSE) {
Initialized = FALSE;
KdPrint(("Executive: Win32 initialization failed\n"));
}
//
// Initialize per processor paged and nonpaged pool lookaside lists.
//
for (Index = 0; Index < (ULONG)KeNumberProcessors; Index += 1) {
Prcb = KiProcessorBlock[Index];
//
// Allocate all of the lookaside list structures at once so they will
// be dense and aligned properly.
//
Lookaside = ExAllocatePoolWithTag(NonPagedPool,
sizeof(GENERAL_LOOKASIDE) * POOL_SMALL_LISTS * 2,
'LooP');
//
// If the allocation succeeded, then initialize and fill in the new
// per processor lookaside structures. Otherwise, use the default
// structures initialized during phase zero.
//
if (Lookaside != NULL) {
for (List = 0; List < POOL_SMALL_LISTS; List += 1) {
ExInitializeSystemLookasideList(Lookaside,
NonPagedPool,
(List + 1) * sizeof (POOL_BLOCK),
'LooP',
256,
&ExPoolLookasideListHead);
Prcb->PPNPagedLookasideList[List].P = Lookaside;
Lookaside += 1;
ExInitializeSystemLookasideList(Lookaside,
PagedPool,
(List + 1) * sizeof (POOL_BLOCK),
'LooP',
256,
&ExPoolLookasideListHead);
Prcb->PPPagedLookasideList[List].P = Lookaside;
Lookaside += 1;
}
}
}
return Initialized;
}
ULONG
ExComputeTickCountMultiplier (
IN ULONG TimeIncrement
)
/*++
Routine Description:
This routine computes the tick count multiplier that is used to
compute a tick count value.
Arguments:
TimeIncrement - Supplies the clock increment value in 100ns units.
Return Value:
A scaled integer/fraction value is returned as the function result.
--*/
{
ULONG FractionPart;
ULONG IntegerPart;
ULONG Index;
ULONG Remainder;
//
// Compute the integer part of the tick count multiplier.
//
// The integer part is the whole number of milliseconds between
// clock interrupts. It is assumed that this value is always less
// than 128.
//
IntegerPart = TimeIncrement / (10 * 1000);
//
// Compute the fraction part of the tick count multiplier.
//
// The fraction part is the fraction milliseconds between clock
// interrupts and is computed to an accuracy of 24 bits.
//
Remainder = TimeIncrement - (IntegerPart * (10 * 1000));
FractionPart = 0;
for (Index = 0; Index < 24; Index += 1) {
FractionPart <<= 1;
Remainder <<= 1;
if (Remainder >= (10 * 1000)) {
Remainder -= (10 * 1000);
FractionPart |= 1;
}
}
//
// The tick count multiplier is equal to the integer part shifted
// left by 24 bits and added to the 24 bit fraction.
//
return (IntegerPart << 24) | FractionPart;
}
NTSTATUS
NtShutdownSystem (
IN SHUTDOWN_ACTION Action
)
/*++
Routine Description:
This service is used to safely shutdown the system.
N.B. The caller must have SeShutdownPrivilege to shut down the
system.
Arguments:
Action - Supplies an action that is to be taken after having shutdown.
Return Value:
!NT_SUCCESS - The operation failed or the caller did not have appropriate
privileges.
--*/
{
POWER_ACTION SystemAction;
NTSTATUS Status;
//
// Convert shutdown action to system action
//
switch (Action) {
case ShutdownNoReboot: SystemAction = PowerActionShutdown; break;
case ShutdownReboot: SystemAction = PowerActionShutdownReset; break;
case ShutdownPowerOff: SystemAction = PowerActionShutdownOff; break;
default:
return STATUS_INVALID_PARAMETER;
}
//
// Bypass policy manager and pass directly to SetSystemPowerState
//
Status = NtSetSystemPowerState (
SystemAction,
PowerSystemSleeping3,
POWER_ACTION_OVERRIDE_APPS | POWER_ACTION_DISABLE_WAKES | POWER_ACTION_CRITICAL
);
return Status;
}
int
ExSystemExceptionFilter( VOID )
{
return( KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
);
}
NTKERNELAPI
KPROCESSOR_MODE
ExGetPreviousMode(
VOID
)
/*++
Routine Description:
Returns previous mode. This routine is exported from the kernel so
that drivers can call it, as they may have to do probing of
embedded pointers to user structures on IOCTL calls that the I/O
system can't probe for them on the FastIo path, which does not pass
previous mode via the FastIo parameters.
Arguments:
None.
Return Value:
return-value - Either KernelMode or UserMode
--*/
{
return KeGetPreviousMode();
}
VOID
ExInitializeSystemLookasideList (
IN PGENERAL_LOOKASIDE Lookaside,
IN POOL_TYPE Type,
IN ULONG Size,
IN ULONG Tag,
IN USHORT Depth,
IN PLIST_ENTRY ListHead
)
/*++
Routine Description:
This function initializes a system lookaside list structure and inserts
the structure in the specified lookaside list.
Arguments:
Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
Type - Supplies the pool type of the lookaside list.
Size - Supplies the size of the lookaside list entries.
Tag - Supplies the pool tag for the lookaside list entries.
Depth - Supplies the maximum depth of the lookaside list.
ListHead - Supplies a pointer to the lookaside list into which the
lookaside list structure is to be inserted.
Return Value:
None.
--*/
{
//
// Initialize pool lookaside list structure and insert the structure
// in the pool lookaside list.
//
ExInitializeSListHead(&Lookaside->ListHead);
Lookaside->Allocate = &ExAllocatePoolWithTag;
Lookaside->Free = &ExFreePool;
Lookaside->Depth = 2;
Lookaside->MaximumDepth = Depth;
Lookaside->TotalAllocates = 0;
Lookaside->AllocateHits = 0;
Lookaside->TotalFrees = 0;
Lookaside->FreeHits = 0;
Lookaside->Type = Type;
Lookaside->Tag = Tag;
Lookaside->Size = Size;
Lookaside->LastTotalAllocates = 0;
Lookaside->LastAllocateHits = 0;
InsertTailList(ListHead, &Lookaside->ListEntry);
return;
}
BOOLEAN
ExVerifySuite(
SUITE_TYPE SuiteType
)
/*++
Routine Description:
This function verifies the given suite type with the system's
assigned suite type.
Arguments:
SuiteType - Suite type to check.
Return Value:
A value of TRUE is returned if the suite matches the system. Otherwise
a value of FALSE is returned.
--*/
{
if (SuiteType <= MaxSuiteType && (SuiteType != TerminalServer || ExpHydraEnabled)) {
//
// Shift the suite type to match the suite mask.
//
if (((1 << SuiteType) & ExpSuiteMask) != 0) {
return TRUE;
}
}
return FALSE;
}
NTSTATUS
NtDisplayString(
IN PUNICODE_STRING String
)
/*++
Routine Description:
This service calls the HAL to display a string on the console.
The caller must have SeTcbPrivilege to display a message.
Arguments:
RebootAfterShutdown - A pointer to the string that is to be displayed.
Return Value:
!NT_SUCCESS - The operation failed or the caller did not have appropriate
privileges.
--*/
{
KPROCESSOR_MODE PreviousMode;
UNICODE_STRING CapturedString;
PCHAR StringBuffer = NULL;
PCHAR AnsiStringBuffer = NULL;
STRING AnsiString;
//
// Check to determine if the caller has the privilege to make this
// call.
//
PreviousMode = KeGetPreviousMode();
if (SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode) == FALSE)
{
return STATUS_PRIVILEGE_NOT_HELD;
}
try
{
//
// If the previous mode was user, then check the input parameters.
//
if (PreviousMode != KernelMode)
{
//
// Probe and capture the input unicode string descriptor.
//
CapturedString = ProbeAndReadUnicodeString(String);
//
// If the captured string descriptor has a length of zero, then
// return success.
//
if ((CapturedString.Buffer == 0) ||
(CapturedString.MaximumLength == 0))
{
return STATUS_SUCCESS;
}
//
// Probe and capture the input string.
//
// N.B. Note the length is in bytes.
//
ProbeForRead(
CapturedString.Buffer,
CapturedString.MaximumLength,
sizeof(UCHAR)
);
//
// Allocate a non-paged string buffer because the buffer passed to
// HalDisplay string must be non-paged.
//
StringBuffer = ExAllocatePoolWithTag(NonPagedPool,
CapturedString.MaximumLength,
'grtS');
if (StringBuffer == NULL)
{
return STATUS_NO_MEMORY;
}
RtlMoveMemory(StringBuffer,
CapturedString.Buffer,
CapturedString.MaximumLength);
CapturedString.Buffer = (PWSTR)StringBuffer;
//
// Allocate a string buffer for the ansi string.
//
AnsiStringBuffer = ExAllocatePoolWithTag(NonPagedPool,
CapturedString.MaximumLength,
'grtS');
if (AnsiStringBuffer == NULL)
{
ExFreePool(StringBuffer);
return STATUS_NO_MEMORY;
}
AnsiString.MaximumLength = CapturedString.MaximumLength;
AnsiString.Length = 0;
AnsiString.Buffer = AnsiStringBuffer;
//
// Transform the string to ANSI until the HAL handles unicode.
//
RtlUnicodeStringToOemString(
&AnsiString,
&CapturedString,
FALSE
);
}
else
{
//
// Allocate a string buffer for the ansi string.
//
AnsiStringBuffer = ExAllocatePoolWithTag(NonPagedPool,
String->MaximumLength,
'grtS');
if (AnsiStringBuffer == NULL)
{
return STATUS_NO_MEMORY;
}
AnsiString.MaximumLength = String->MaximumLength;
AnsiString.Length = 0;
AnsiString.Buffer = AnsiStringBuffer;
//
// We were in kernel mode; just transform the original string.
//
RtlUnicodeStringToOemString(
&AnsiString,
String,
FALSE
);
}
InbvDisplayString((PUCHAR)AnsiString.Buffer);
//
// Free up the memory we used to store the strings.
//
if (PreviousMode != KernelMode) {
ExFreePoolWithTag(StringBuffer, 0);
}
ExFreePoolWithTag(AnsiStringBuffer, 0);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
if (StringBuffer != NULL)
{
ExFreePoolWithTag(StringBuffer, 0);
}
return GetExceptionCode();
}
return STATUS_SUCCESS;
}
BOOLEAN
ExpSystemOK(
IN int safelevel,
IN BOOLEAN evalflag
)
{
if (safelevel == 0)
{
ExpStringCheck(
ExpStrings[EXP_ST_SETUP],
ExpStrings[EXP_ST_SETUP_TYPE],
ExpStrings[EXP_ST_SYSTEM_PREFIX],
ExpStrings[EXP_ST_PRODUCT_OPTIONS],
ExpStrings[EXP_ST_PRODUCT_TYPE],
ExpStrings[EXP_ST_LANMANNT],
ExpStrings[EXP_ST_SERVERNT],
ExpStrings[EXP_ST_WINNT],
ExpStrings[EXP_ST_PRODUCT_SUITE],
ExpStrings[EXP_ST_LICENSE_INFO],
ExpStrings[EXP_ST_CONCURRENT_LIMIT],
ExpStrings[EXP_ST_SUITE_SBS],
ExpStrings[EXP_ST_SUITE_ENTERPRISE],
ExpStrings[EXP_ST_SUITE_COMSRV],
ExpStrings[EXP_ST_SUITE_BACKOFFICE],
ExpStrings[EXP_ST_SUITE_SBSREST],
ExpStrings[EXP_ST_SUITE_TRMSRV],
ExpStrings[EXP_ST_SUITE_EMBED],
ExpStrings[EXP_ST_SUITE_DTC],
ExpStrings[EXP_ST_SUITE_PERSONAL],
ExpStrings[EXP_ST_SUITE_BLADE],
ExpStrings[EXP_ST_SUITE_EMBEDRES],
ExpStrings[EXP_ST_SUITE_SECURITY]
);
return TRUE;
}
else if (safelevel == 2)
{
if (CmSuiteBufferType == 7 && CmSuiteBuffer != NULL)
{
if (wcscmp(CmSuiteBuffer, L"Small Business") == 0)
{
ExpSuiteMask |= 0x1; // TODO: Use a proper definition
}
else if (wcscmp(CmSuiteBuffer, L"Small Business(Restricted)") == 0)
{
ExpSuiteMask |= 0x20;
}
else if (wcscmp(CmSuiteBuffer, L"Enterprise") == 0)
{
ExpSuiteMask |= 0x2;
}
else if (wcscmp(CmSuiteBuffer, L"CommunicationServer") == 0)
{
ExpSuiteMask |= 0x8;
}
else if (wcscmp(CmSuiteBuffer, L"BackOffice") == 0)
{
ExpSuiteMask |= 0x4;
}
else if (wcscmp(CmSuiteBuffer, L"Terminal Server") == 0)
{
ExpSuiteMask |= 0x10;
}
else if (wcscmp(CmSuiteBuffer, L"EmbeddedNT") == 0)
{
ExpSuiteMask |= 0x40;
}
else if (wcscmp(CmSuiteBuffer, L"DataCenter") == 0)
{
ExpSuiteMask |= 0x80;
}
else if (wcscmp(CmSuiteBuffer, L"Personal") == 0)
{
ExpSuiteMask |= 0x200;
}
else if (wcscmp(CmSuiteBuffer, L"Blade") == 0)
{
ExpSuiteMask |= 0x400;
}
else if (wcscmp(CmSuiteBuffer, L"Embedded(Restricted)") == 0)
{
ExpSuiteMask |= 0x800;
}
else if (wcscmp(CmSuiteBuffer, L"Security Appliance") == 0)
{
ExpSuiteMask |= 0x1000;
}
else if (wcscmp(CmSuiteBuffer, L"Storage Server") == 0)
{
ExpSuiteMask |= 0x2000;
}
else if (wcscmp(CmSuiteBuffer, L"Compute Server") == 0)
{
ExpSuiteMask |= 0x4000;
}
}
return evalflag;
}
else
{
return TRUE;
}
}
VOID
ExInitSystemPhase2(
VOID
)
/*++
Routine Description:
This function performs Phase 2 initialisation of the executive component
of the NT system.
Arguments:
None.
Return Value:
None.
--*/
{
UNICODE_STRING KeyName;
UNICODE_STRING KeyValueName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
ULONG DataLength;
ULONG ValueInfoBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 2];
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
PULONG SetupType;
PVOID KeyBody;
//
// Not sure what this does but let's see if it makes any difference
//
SharedUserData->ComPlusPackage = (ULONG)-1;
//
// Load the setup information
//
ExpSystemPrefixValid = FALSE;
ExpSetupModeDetected = FALSE;
SharedUserData->ProductTypeIsValid = TRUE;
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\Setup");
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
&ExpSetupKey,
KEY_READ | KEY_WRITE | KEY_NOTIFY,
&ObjectAttributes
);
if (NT_SUCCESS(Status))
{
Status = ObReferenceObjectByHandle(
ExpSetupKey,
0,
CmpKeyObjectType,
KernelMode,
(PVOID *)(&KeyBody),
NULL
);
if (NT_SUCCESS(Status))
{
ExpControlKey[0] = KeyBody;
}
//
// Query SetupType in the registry and update ExpSetupModeDetected accordingly
//
RtlInitUnicodeString(&KeyValueName, L"SetupType");
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueInfoBuffer;
Status = NtQueryValueKey(
ExpSetupKey,
&KeyValueName,
KeyValuePartialInformation,
ValueInfo,
sizeof(ValueInfoBuffer),
&DataLength
);
if (NT_SUCCESS(Status))
{
SetupType = (PULONG)&ValueInfo->Data;
if (*SetupType == 1 && *SetupType == 4)
{
SharedUserData->ProductTypeIsValid = FALSE;
ExpSetupModeDetected = TRUE;
ObDereferenceObject(ExpControlKey[0]);
ExpControlKey[0] = NULL;
}
}
//
// Query the system prefix data in the registry and update ExpSystemPrefixValid accordingly
//
RtlInitUnicodeString(&KeyValueName, L"SystemPrefix");
ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueInfoBuffer;
Status = NtQueryValueKey(
ExpSetupKey,
&KeyValueName,
KeyValuePartialInformation,
ValueInfo,
sizeof(ValueInfoBuffer),
&DataLength
);
if (NT_SUCCESS(Status))
{
RtlCopyMemory(&ExpSetupSystemPrefix, &ValueInfo->Data, sizeof(LARGE_INTEGER));
if (ExpSetupModeDetected == FALSE)
{
ExpSystemPrefixValid = TRUE;
}
}
}
//
// Load the product options information
//
if (InitIsWinPEMode == FALSE || ExpInTextModeSetup == FALSE)
{
RtlInitUnicodeString(
&KeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ProductOptions"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
&ExpProductTypeKey,
KEY_READ | KEY_NOTIFY | KEY_WRITE,
&ObjectAttributes
);
if (ExpSetupModeDetected == FALSE && ExpInTextModeSetup == FALSE)
{
ASSERT(NT_SUCCESS(Status));
Status = ObReferenceObjectByHandle(
ExpProductTypeKey,
0,
CmpKeyObjectType,
KernelMode,
(PVOID *)(&KeyBody),
NULL
);
if (NT_SUCCESS(Status))
{
ExpControlKey[1] = KeyBody;
}
}
//
// Query the product type in the registry
//
RtlInitUnicodeString(&KeyValueName, L"ProductType");
ExpProductTypeValueInfo = ExAllocatePoolWithTag(
PagedPool,
sizeof(*ExpProductTypeValueInfo) + MAX_PRODUCT_TYPE_BYTES,
' yeK'
);
ASSERT(ExpProductTypeValueInfo != NULL);
Status = NtQueryValueKey(
ExpProductTypeKey,
&KeyValueName,
KeyValuePartialInformation,
ExpProductTypeValueInfo,
sizeof(*ExpProductTypeValueInfo) + MAX_PRODUCT_TYPE_BYTES,
&DataLength
);
ASSERT(NT_SUCCESS(Status));
//
// Modify the suite mask for terminal services
//
if (ExpHydraEnabled == TRUE)
{
ExpSuiteMask |= 0x10;
SharedUserData->SuiteMask = ExpSuiteMask;
if (ExpMultiUserTS == FALSE)
{
SharedUserData->SuiteMask |= 0x100;
}
}
else
{
SharedUserData->SuiteMask = ExpSuiteMask;
}
}
//
// Update the progress bar
//
InbvUpdateProgressBar(25);
}
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
exp.h
Abstract:
This module contains the private (internal) header file for the
executive.
Author:
David N. Cutler (davec) 23-May-1989
Environment:
Kernel mode only.
Revision History:
--*/
#ifndef _EXP_
#define _EXP_
#pragma warning(disable:4214) // bit field types other than int
#pragma warning(disable:4201) // nameless struct/union
#pragma warning(disable:4127) // condition expression is constant
#pragma warning(disable:4115) // named type definition in parentheses
#pragma warning(disable:4206) // translation unit empty
#pragma warning(disable:4706) // assignment within conditional
#pragma warning(disable:4324) // structure was padded
#pragma warning(disable:4328) // greater alignment than needed
#pragma warning(disable:4054) // cast of function pointer to PVOID
#include "ntos.h"
#include "zwapi.h"
#define NOEXTAPI
#include "wdbgexts.h"
#include "ntdbg.h"
#include "ki.h"
#include "stdio.h"
#include "pool.h"
#define COMPLUS_PACKAGE_KEYPATH L"\\Registry\\Machine\\SOFTWARE\\Microsoft\\.NETFramework"
#define COMPLUS_PACKAGE_ENABLE64BIT L"Enable64Bit"
#define COMPLUS_PACKAGE_INVALID (ULONG)-1
//
// Executive information initialization structure
//
typedef struct {
PCALLBACK_OBJECT *CallBackObject;
PWSTR CallbackName;
} EXP_INITIALIZE_GLOBAL_CALLBACKS;
typedef struct _EXP_LICENSE_INFO {
HANDLE RegKey;
ULONG Count;
PWSTR SubKeyName;
WORK_QUEUE_ITEM ExpWatchLicenseInfoWorkItem;
IO_STATUS_BLOCK ExpLicenseInfoIoSb;
ULONG ExpLicenseInfoChangeBuffer;
} EXP_LICENSE_INFO, *PEXP_LICENSE_INFO;
//
// Executive object and other initialization function definitions.
//
NTSTATUS
ExpWorkerInitialization (
VOID
);
BOOLEAN
ExpEventInitialization (
VOID
);
BOOLEAN
ExpEventPairInitialization (
VOID
);
BOOLEAN
ExpMutantInitialization (
VOID
);
BOOLEAN
ExpSemaphoreInitialization (
VOID
);
BOOLEAN
ExpTimerInitialization (
VOID
);
BOOLEAN
ExpWin32Initialization (
VOID
);
BOOLEAN
ExpResourceInitialization (
VOID
);
PVOID
ExpCheckForResource (
IN PVOID p,
IN SIZE_T Size
);
BOOLEAN
ExpInitSystemPhase0 (
VOID
);
BOOLEAN
ExpInitSystemPhase1 (
VOID
);
BOOLEAN
ExpSystemOK(
IN int safelevel,
IN BOOLEAN evalflag
);
BOOLEAN
ExpProfileInitialization (
);
BOOLEAN
ExpUuidInitialization (
);
VOID
ExpProfileDelete (
IN PVOID Object
);
BOOLEAN
ExpInitializeCallbacks (
VOID
);
BOOLEAN
ExpSysEventInitialization(
VOID
);
VOID
ExpCheckSystemInfoWork (
IN PVOID Context
);
VOID
ExInitSystemPhase2 (
VOID
);
NTSTATUS
ExpKeyedEventInitialization (
VOID
);
VOID
ExpCheckSystemInformation (
PVOID Context,
PVOID InformationClass,
PVOID Argument2
);
VOID
ExpTimeZoneWork(
IN PVOID Context
);
VOID
ExpTimeRefreshDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
ExpCenturyDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
ExpTimeRefreshWork(
IN PVOID Context
);
BOOLEAN
ExpRefreshTimeZoneInformation(
IN PLARGE_INTEGER CurrentUniversalTime
);
VOID
ExpTimeZoneDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
ExInitializeTimeRefresh(
VOID
);
VOID
ExpExpirationThread(
IN PVOID StartContext
);
ULONG
ExpComputeTickCountMultiplier(
IN ULONG TimeIncrement
);
BOOLEAN
static
ExpWatchProductTypeInitialization(
VOID
);
VOID
static
ExpWatchProductTypeWork(
IN PVOID Context
);
VOID
static
ExpWatchLicenseInfoWork(
IN PVOID Context
);
VOID
static
ExpWatchSystemPrefixWork(
IN PVOID Context
);
VOID
static
ExpWatchExpirationDataWork(
IN PVOID Context
);
VOID
ExpCheckForWorker(
IN PVOID p,
IN SIZE_T Size
);
VOID
ExpShutdownWorkerThreads(
VOID
);
NTSTATUS
ExpReadComPlusPackage(
VOID
);
NTSTATUS
ExpUpdateComPlusPackage(
IN ULONG ComPlusPackageStatus
);
#if defined(_WIN64)
NTSTATUS
ExpGetSystemEmulationProcessorInformation (
OUT PSYSTEM_PROCESSOR_INFORMATION ProcessorInformation
);
#endif
NTSTATUS
ExApplyCodePatch(
IN PVOID PatchInfoPtr,
IN SIZE_T PatchSize
);
ULONG ExpNtExpirationData[3];
BOOLEAN ExpSetupModeDetected;
LARGE_INTEGER ExpSetupSystemPrefix;
HANDLE ExpSetupKey;
BOOLEAN ExpSystemPrefixValid;
#ifdef _PNP_POWER_
extern WORK_QUEUE_ITEM ExpCheckSystemInfoWorkItem;
extern LONG ExpCheckSystemInfoBusy;
extern const WCHAR ExpWstrSystemInformation[];
extern const WCHAR ExpWstrSystemInformationValue[];
#endif // _PNP_POWER_
extern const WCHAR ExpWstrCallback[];
extern const EXP_INITIALIZE_GLOBAL_CALLBACKS ExpInitializeCallback[];
extern FAST_MUTEX ExpEnvironmentLock;
extern ERESOURCE ExpKeyManipLock;
extern GENERAL_LOOKASIDE ExpSmallPagedPoolLookasideLists[POOL_SMALL_LISTS];
extern GENERAL_LOOKASIDE ExpSmallNPagedPoolLookasideLists[POOL_SMALL_LISTS];
extern LIST_ENTRY ExNPagedLookasideListHead;
extern KSPIN_LOCK ExNPagedLookasideLock;
extern LIST_ENTRY ExPagedLookasideListHead;
extern KSPIN_LOCK ExPagedLookasideLock;
extern LIST_ENTRY ExPoolLookasideListHead;
extern PEPROCESS ExpDefaultErrorPortProcess;
extern HANDLE ExpDefaultErrorPort;
extern HANDLE ExpProductTypeKey;
extern PVOID ExpControlKey[2];
extern BOOLEAN ExpTooLateForErrors;
extern BOOLEAN ExpInTextModeSetup;
#endif // _EXP_
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
systime.c
Abstract:
This module implements the NT system time services.
Author:
Mark Lucovsky (markl) 08-Aug-1989
Revision History:
--*/
#include "exp.h"
//
// Constant Definitions
//
#define EXP_ONE_SECOND (10 * (1000 * 1000))
#define EXP_REFRESH_TIME -3600 // Refresh every hour
#define EXP_DEFAULT_SEPARATION 60
ULONG ExpMaxTimeSeperationBeforeCorrect = EXP_DEFAULT_SEPARATION;
//
// Global Variables
//
RTL_TIME_ZONE_INFORMATION ExpTimeZoneInformation;
LARGE_INTEGER ExpTimeZoneBias;
ULONG ExpCurrentTimeZoneId = 0xffffffff;
LONG ExpLastTimeZoneBias = -1;
LONG ExpAltTimeZoneBias;
ULONG ExpRealTimeIsUniversal;
BOOLEAN ExpSystemIsInCmosMode = TRUE;
BOOLEAN ExCmosClockIsSane = TRUE;
ERESOURCE ExpTimeRefreshLock = {0};
ULONG ExpOkToTimeRefresh;
ULONG ExpOkToTimeZoneRefresh;
ULONG ExpRefreshFailures;
WORK_QUEUE_ITEM ExpTimeRefreshWorkItem;
WORK_QUEUE_ITEM ExpTimeZoneWorkItem;
WORK_QUEUE_ITEM ExpCenturyWorkItem;
LARGE_INTEGER ExpNextSystemCutover;
LARGE_INTEGER ExpLastShutDown;
LARGE_INTEGER ExpTimeRefreshInterval;
KDPC ExpTimeZoneDpc;
KTIMER ExpTimeZoneTimer;
KDPC ExpTimeRefreshDpc;
KTIMER ExpTimeRefreshTimer;
KDPC ExpCenturyDpc;
KTIMER ExpCenturyTimer;
LARGE_INTEGER ExpNextCenturyTime;
TIME_FIELDS ExpNextCenturyTimeFields;
BOOLEAN ExpShuttingDown;
ULONG ExpRefreshCount;
ULONG ExpTimerResolutionCount = 0;
ULONG ExpKernelResolutionCount = 0;
LARGE_INTEGER ExpMaxTimeSeparationBeforeCorrect;
ERESOURCE ExpKeyManipLock;
//
// This is for frankar's evaluation SKU support
// [0] - Setup Date low
// [2] - Setup Date high
// [1] - Evaluation Period in minutes
//
ULONG ExpNtExpirationDataLength = 12;
//extern HANDLE ExpExpirationDataKey;
//
// ALLOC_PRAGMA
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, ExAcquireTimeRefreshLock)
#pragma alloc_text(PAGE, ExReleaseTimeRefreshLock)
#pragma alloc_text(PAGE, ExpRefreshTimeZoneInformation)
#pragma alloc_text(PAGE, ExpTimeZoneWork)
#pragma alloc_text(PAGE, ExpTimeRefreshWork)
#pragma alloc_text(PAGE, NtQuerySystemTime)
#pragma alloc_text(PAGE, ExUpdateSystemTimeFromCmos)
#pragma alloc_text(PAGE, NtSetSystemTime)
#pragma alloc_text(PAGE, NtQueryTimerResolution)
#pragma alloc_text(PAGE, NtSetTimerResolution)
#pragma alloc_text(PAGE, ExShutdownSystem)
#pragma alloc_text(INIT, ExInitializeTimeRefresh)
#endif
//
// Function Implementations
//
VOID
ExpSetSystemTime(
IN BOOLEAN Both,
IN BOOLEAN AdjustInterruptTime,
IN PLARGE_INTEGER NewTime,
OUT PLARGE_INTEGER OldTime
)
{
LARGE_INTEGER NewSystemTime;
TIME_FIELDS TimeFields;
//
// If RTC is supposed to be set to UTC, use the NewTime value supplied; otherwise, convert the
// supplied NewTime value into the local time value since the RTC is required to be set to the
// local time.
//
if (ExpRealTimeIsUniversal == TRUE)
{
NewSystemTime.QuadPart = NewTime->QuadPart;
}
else
{
ExSystemTimeToLocalTime(NewTime, &NewSystemTime);
}
//
// Set the system time
//
KeSetSystemTime(&NewSystemTime, OldTime, AdjustInterruptTime, NULL);
//
// If Both flag is set and the system is not in CMOS mode, update the real time clock
//
if (Both == TRUE)
{
ExpRefreshTimeZoneInformation(&NewSystemTime);
if (ExpRealTimeIsUniversal == FALSE &&
ExpSystemIsInCmosMode == FALSE)
{
ExSystemTimeToLocalTime(NewTime, &NewSystemTime);
RtlTimeToTimeFields(&NewSystemTime, &TimeFields);
ExCmosClockIsSane = HalSetRealTimeClock(&TimeFields);
}
}
//
// Notify other components that the system time has been set
//
PoNotifySystemTimeSet();
}
VOID
ExLocalTimeToSystemTime(
IN PLARGE_INTEGER LocalTime,
OUT PLARGE_INTEGER SystemTime
)
{
//
// SystemTime = LocalTime + TimeZoneBias
//
SystemTime->QuadPart = LocalTime->QuadPart + ExpTimeZoneBias.QuadPart;
}
VOID
ExSystemTimeToLocalTime(
IN PLARGE_INTEGER SystemTime,
OUT PLARGE_INTEGER LocalTime
)
{
//
// LocalTime = SystemTime - TimeZoneBias
//
LocalTime->QuadPart = SystemTime->QuadPart - ExpTimeZoneBias.QuadPart;
}
VOID
ExInitializeTimeRefresh(
VOID
)
{
KeInitializeDpc(&ExpTimeRefreshDpc, ExpTimeRefreshDpcRoutine, NULL);
ExInitializeWorkItem(&ExpTimeRefreshWorkItem, ExpTimeRefreshWork, NULL);
KeInitializeTimer(&ExpTimeRefreshTimer);
ExpTimeRefreshInterval.QuadPart = Int32x32To64(EXP_ONE_SECOND,
EXP_REFRESH_TIME);
KeSetTimer(&ExpTimeRefreshTimer, ExpTimeRefreshInterval, &ExpTimeRefreshDpc);
ExInitializeResourceLite(&ExpTimeRefreshLock);
}
VOID
ExpTimeZoneWork(
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(Context);
PAGED_CODE();
do {
ZwSetSystemTime(NULL, NULL);
} while (ExInterlockedAddUlong(&ExpOkToTimeZoneRefresh, (ULONG)-1, NULL));
}
VOID
ExpTimeZoneDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(DeferredContext);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
if (ExInterlockedAddUlong(&ExpOkToTimeZoneRefresh, 1, NULL) == 1)
{
ExQueueWorkItem(&ExpTimeZoneWorkItem, DelayedWorkQueue);
}
}
BOOLEAN
ExpRefreshTimeZoneInformation(
IN PLARGE_INTEGER CurrentUniversalTime
)
{
NTSTATUS Status;
RTL_TIME_ZONE_INFORMATION tzi;
LARGE_INTEGER NewTimeZoneBias;
LARGE_INTEGER LocalCustomBias;
LARGE_INTEGER StandardTime;
LARGE_INTEGER DaylightTime;
LARGE_INTEGER NextCutover;
LONG ActiveBias;
LARGE_INTEGER CurrentTime;
TIME_FIELDS TimeFields;
PAGED_CODE();
if (ExpTimeZoneWorkItem.WorkerRoutine == NULL)
{
ExInitializeTimeRefresh();
KeInitializeDpc(&ExpTimeZoneDpc, ExpTimeZoneDpcRoutine, &ExpOkToTimeZoneRefresh);
ExInitializeWorkItem(&ExpTimeZoneWorkItem, ExpTimeZoneWork, NULL);
KeInitializeTimer(&ExpTimeZoneTimer);
KeInitializeDpc(&ExpCenturyDpc, ExpCenturyDpcRoutine, NULL);
ExInitializeWorkItem(&ExpCenturyWorkItem, ExpTimeZoneWork, NULL);
KeInitializeTimer(&ExpCenturyTimer);
//
// TODO: Add a macro for initialising TIME_FIELDS later if deemed necessary.
//
ExpNextCenturyTimeFields.Year = 0;
ExpNextCenturyTimeFields.Month = 1;
ExpNextCenturyTimeFields.Day = 1;
ExpNextCenturyTimeFields.Hour = 0;
ExpNextCenturyTimeFields.Minute = 0;
ExpNextCenturyTimeFields.Second = 0;
ExpNextCenturyTimeFields.Milliseconds = 1;
}
//
// Timezone Bias is initially 0
//
Status = RtlQueryTimeZoneInformation(&tzi);
if (NT_SUCCESS(Status) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
//
// Get the new timezone bias
//
NewTimeZoneBias.QuadPart = Int32x32To64(
tzi.Bias * 60, // Bias in seconds
10000000
);
ActiveBias = tzi.Bias;
//
// Now see if we have stored cutover times
//
if (tzi.StandardStart.Month != 0 && tzi.DaylightStart.Month != 0)
{
//
// We have timezone cutover information. Compute the cutover dates
// and compute what our current bias is.
//
if (RtlCutoverTimeToSystemTime(
&tzi.StandardStart,
&StandardTime,
CurrentUniversalTime,
TRUE) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
if (RtlCutoverTimeToSystemTime(
&tzi.DaylightStart,
&DaylightTime,
CurrentUniversalTime,
TRUE) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
//
// If daylight < standard, then time >= daylight and
// less than standard is daylight
//
if ( DaylightTime.QuadPart < StandardTime.QuadPart )
{
//
// If today is >= DaylightTime and < StandardTime, then
// We are in daylight savings time
//
if ((CurrentUniversalTime->QuadPart >= DaylightTime.QuadPart) &&
(CurrentUniversalTime->QuadPart < StandardTime.QuadPart))
{
if (RtlCutoverTimeToSystemTime(
&tzi.StandardStart,
&NextCutover,
CurrentUniversalTime,
FALSE
) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
ExpCurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
SharedUserData->TimeZoneId = ExpCurrentTimeZoneId;
}
else
{
if (RtlCutoverTimeToSystemTime(
&tzi.DaylightStart,
&NextCutover,
CurrentUniversalTime,
FALSE
) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
ExpCurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
SharedUserData->TimeZoneId = ExpCurrentTimeZoneId;
}
}
else
{
//
// If today is >= StandardTime and < DaylightTime, then
// We are in standard time
//
if ((CurrentUniversalTime->QuadPart >= StandardTime.QuadPart) &&
(CurrentUniversalTime->QuadPart < DaylightTime.QuadPart))
{
if (RtlCutoverTimeToSystemTime(
&tzi.DaylightStart,
&NextCutover,
CurrentUniversalTime,
FALSE) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
ExpCurrentTimeZoneId = TIME_ZONE_ID_STANDARD;
SharedUserData->TimeZoneId = ExpCurrentTimeZoneId;
}
else
{
if (RtlCutoverTimeToSystemTime(
&tzi.StandardStart,
&NextCutover,
CurrentUniversalTime,
FALSE) == FALSE)
{
ExpSystemIsInCmosMode = TRUE;
ExpRefreshFailures++;
return FALSE;
}
ExpCurrentTimeZoneId = TIME_ZONE_ID_DAYLIGHT;
SharedUserData->TimeZoneId = ExpCurrentTimeZoneId;
}
}
//
// At this point, we know our current timezone and the
// Universal time of the next cutover.
//
LocalCustomBias.QuadPart =
Int32x32To64(
ExpCurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ? // Bias in seconds
tzi.DaylightBias * 60 :
tzi.StandardBias * 60,
10000000
);
ActiveBias += ExpCurrentTimeZoneId == TIME_ZONE_ID_DAYLIGHT ?
tzi.DaylightBias :
tzi.StandardBias;
ExpTimeZoneBias.QuadPart = NewTimeZoneBias.QuadPart + LocalCustomBias.QuadPart;
#ifdef _ALPHA_
SharedUserData->TimeZoneBias = ExpTimeZoneBias.QuadPart;
#else
SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
#endif
ExpTimeZoneInformation = tzi;
ExpLastTimeZoneBias = ActiveBias;
ExpSystemIsInCmosMode = FALSE;
//
// NextCutover contains date on next transition
//
//
// Convert to universal time and create a DPC to fire at the
// appropriate time
//
ExLocalTimeToSystemTime(&NextCutover, &ExpNextSystemCutover);
KeSetTimer(
&ExpTimeZoneTimer,
ExpNextSystemCutover,
&ExpTimeZoneDpc
);
}
else
{
KeCancelTimer(&ExpTimeZoneTimer);
ExpTimeZoneBias = NewTimeZoneBias;
#ifdef _ALPHA_
SharedUserData->TimeZoneBias = ExpTimeZoneBias.QuadPart;
#else
SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
#endif
ExpCurrentTimeZoneId = TIME_ZONE_ID_UNKNOWN;
SharedUserData->TimeZoneId = ExpCurrentTimeZoneId;
ExpTimeZoneInformation = tzi;
ExpLastTimeZoneBias = ActiveBias;
}
RtlCopyMemory(&CurrentTime, CurrentUniversalTime, sizeof(LARGE_INTEGER));
RtlTimeToTimeFields(&CurrentTime, &TimeFields);
ExpNextCenturyTimeFields.Year = 100 * (TimeFields.Year / 100 + 1);
RtlTimeFieldsToTime(&ExpNextCenturyTimeFields, &CurrentTime);
ExLocalTimeToSystemTime(&CurrentTime, &ExpNextCenturyTime);
KeSetTimer(&ExpCenturyTimer, ExpNextCenturyTime, &ExpCenturyDpc);
//
// If time is stored as local time, update the registry with
// our best guess at the local time bias
//
if (ExpRealTimeIsUniversal == FALSE)
{
RtlSetActiveTimeBias(ExpLastTimeZoneBias);
}
return TRUE;
}
ULONG
ExSetTimerResolution(
IN ULONG DesiredTime,
IN BOOLEAN SetResolution)
{
ULONG NewIncrement;
ULONG NewTime;
PAGED_CODE();
ASSERT(ExpKernelResolutionCount != 0);
ExAcquireTimeRefreshLock(TRUE);
NewIncrement = KeTimeIncrement;
if (SetResolution == TRUE)
{
if (ExpKernelResolutionCount == 0)
++ExpTimerResolutionCount;
++ExpKernelResolutionCount;
NewTime = DesiredTime;
if (NewTime < KeMinimumIncrement)
NewTime = KeMinimumIncrement;
if (NewTime < KeTimeIncrement)
{
KeSetSystemAffinityThread(1);
NewIncrement = HalSetTimeIncrement(NewTime);
KeRevertToUserAffinityThread();
KeTimeIncrement = NewIncrement;
}
}
else if (ExpKernelResolutionCount > 0)
{
if (--ExpKernelResolutionCount > 0)
{
if (--ExpTimerResolutionCount > 0)
{
KeSetSystemAffinityThread(1);
NewIncrement = HalSetTimeIncrement(KeMaximumIncrement);
KeRevertToUserAffinityThread();
KeTimeIncrement = NewIncrement;
}
}
}
ExReleaseTimeRefreshLock();
return NewIncrement;
}
BOOLEAN
ExAcquireTimeRefreshLock(
IN BOOLEAN Wait
)
{
PKTHREAD CurrentThread;
CurrentThread = KeGetCurrentThread();
KeEnterCriticalRegionThread(CurrentThread);
if (ExAcquireResourceExclusiveLite(&ExpTimeRefreshLock, Wait) == FALSE)
{
KeLeaveCriticalRegionThread(CurrentThread);
return FALSE;
}
return TRUE;
}
VOID
ExReleaseTimeRefreshLock(
VOID
)
{
PKTHREAD CurrentThread;
CurrentThread = KeGetCurrentThread();
ExReleaseResourceLite(&ExpTimeRefreshLock);
KeLeaveCriticalRegionThread(CurrentThread);
}
VOID
ExShutdownSystem(
IN ULONG Phase
)
{
UNICODE_STRING KeyName;
UNICODE_STRING KeyValueName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE Key;
//ULONG ValueInfoBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 2];
KEY_VALUE_PARTIAL_INFORMATION ValueInfo;
LARGE_INTEGER SystemPrefix;
LARGE_INTEGER ShutDownTime;
ULONG NumberOfProcessors;
ULONG DataLength;
if (Phase == 0)
{
ExpTooLateForErrors = TRUE;
if (ExpInTextModeSetup == FALSE)
{
ExpShuttingDown = TRUE;
if (ExpSetupModeDetected == TRUE)
{
//
// If we are not in text mode setup, open SetupKey so we can store shutdown time.
//
RtlInitUnicodeString(&KeyName,L"\\Registry\\Machine\\System\\Setup");
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
&Key,
KEY_READ | KEY_WRITE | KEY_NOTIFY,
&ObjectAttributes
);
if (!NT_SUCCESS(Status))
{
return;
}
RtlInitUnicodeString(&KeyValueName, L"SystemPrefix");
Status = NtQueryValueKey(
Key,
&KeyValueName,
KeyValuePartialInformation,
&ValueInfo,
sizeof(ValueInfo),
&DataLength
);
NtClose(Key);
if (!NT_SUCCESS(Status))
{
return;
}
}
else
{
SystemPrefix = ExpSetupSystemPrefix;
}
KeQuerySystemTime(&ShutDownTime);
//
// Clear low 6 bits of time
//
ShutDownTime.LowPart &= ~0x0000003F;
//
// If we have never gone through the refresh count logic, do it now.
//
if (ExpRefreshCount == 0)
{
ExpRefreshCount++;
//
// First time through time refresh. If we are not in setup mode, then make sure
// ShutDownTime is in good shape.
//
if (ExpSetupModeDetected == FALSE && ExpInTextModeSetup == FALSE)
{
if (ExpLastShutDown.QuadPart != 0)
{
NumberOfProcessors = ExpSetupSystemPrefix.LowPart;
NumberOfProcessors = NumberOfProcessors >> 5;
NumberOfProcessors = ~NumberOfProcessors;
NumberOfProcessors = NumberOfProcessors & 0x0000001f;
NumberOfProcessors++;
ExpLastShutDown.LowPart &= 0x3f;
if ((ExpSetupSystemPrefix.HighPart & 0x04000000) != 0)
{
if (((ExpLastShutDown.LowPart >> 1) == NumberOfProcessors) &&
((ExpLastShutDown.LowPart & 1) == 0))
{
ExpLastShutDown.HighPart = 0;
}
else if (ExpLastShutDown.HighPart == 0)
{
ExpLastShutDown.HighPart = 1;
}
}
else
{
if (((ExpLastShutDown.LowPart >> 1) != NumberOfProcessors) ||
((ExpLastShutDown.LowPart & 1) != 0))
{
ExpLastShutDown.HighPart = 0;
}
else if (ExpLastShutDown.HighPart == 0)
{
ExpLastShutDown.HighPart = 1;
}
}
ExpLastShutDown.LowPart |= 0x40;
}
}
else
{
ExpLastShutDown.QuadPart = 0;
}
}
if (ExpLastShutDown.QuadPart != 0 && ExpLastShutDown.HighPart == 0)
{
ShutDownTime.LowPart |= ExpLastShutDown.LowPart;
}
else
{
NumberOfProcessors = ExpSetupSystemPrefix.LowPart;
NumberOfProcessors = NumberOfProcessors >> 5;
NumberOfProcessors = ~NumberOfProcessors;
NumberOfProcessors = NumberOfProcessors & 0x0000001f;
NumberOfProcessors++;
ShutDownTime.LowPart |= (NumberOfProcessors << 1);
if ((ExpSetupSystemPrefix.HighPart & 0x04000000) != 0)
{
ShutDownTime.LowPart |= 1;
}
}
RtlInitUnicodeString(
&KeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
&Key,
KEY_READ | KEY_WRITE | KEY_NOTIFY,
&ObjectAttributes
);
if (!NT_SUCCESS(Status))
{
return;
}
RtlInitUnicodeString(&KeyValueName, L"ShutdownTime");
NtSetValueKey(
Key,
&KeyValueName,
0,
REG_BINARY,
&ShutDownTime,
sizeof(ShutDownTime)
);
NtFlushKey(Key);
NtClose(Key);
}
else
{
//
// If the kernel is running the text mode setup, dereference the kernel objects
// dynamically allocated by the executive.
//
if (ExpDefaultErrorPort != NULL)
{
ObfDereferenceObject(ExpDefaultErrorPort);
ExpDefaultErrorPort = NULL;
}
if (ExpDefaultErrorPortProcess != NULL)
{
ObfDereferenceObject(ExpDefaultErrorPortProcess);
ExpDefaultErrorPortProcess = NULL;
}
ExAcquireResourceExclusiveLite(&ExpKeyManipLock, TRUE);
if (ExpControlKey[0] != NULL)
{
ObfDereferenceObject(ExpControlKey[0]);
ExpControlKey[0] = NULL;
}
if (ExpControlKey[1] != NULL)
{
ObfDereferenceObject(ExpControlKey[1]);
ExpControlKey[1] = NULL;
}
/*if (ExpExpirationDataKey != NULL)
{
ObCloseHandle(ExpExpirationDataKey, FALSE);
ExpExpirationDataKey = NULL;
}*/
/*if (ExpProductTypeKey != NULL)
{
ObCloseHandle(ExpProductTypeKey, FALSE);
ExpProductTypeKey = NULL;
}*/
if (ExpSetupKey != NULL)
{
ObCloseHandle(ExpSetupKey, FALSE);
ExpSetupKey = NULL;
}
ExReleaseResourceLite(&ExpKeyManipLock);
return;
}
}
else if (Phase == 1)
{
if ((PopShutdownCleanly & PO_CLEAN_SHUTDOWN_PAGING) != 0)
{
ExSwapinWorkerThreads(FALSE);
}
}
else
{
ASSERT(Phase == 2);
if ((PopShutdownCleanly & PO_CLEAN_SHUTDOWN_WORKERS) != 0)
{
ExpShutdownWorkerThreads();
}
ExDeleteResourceLite(&ExpKeyManipLock);
}
/*
if (ExpInTextModeSetup == FALSE)
{
ExpShuttingDown = TRUE;
if ( ExpSetupModeDetected )
{
//
// If we are not in text mode setup, open SetupKey so we can store shutdown time.
//
RtlInitUnicodeString(&KeyName,L"\\Registry\\Machine\\System\\Setup");
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
&Key,
KEY_READ | KEY_WRITE | KEY_NOTIFY,
&ObjectAttributes
);
if (NT_SUCCESS(Status) == FALSE)
{
return;
}
//
// Pick up the system prefix data
//
RtlInitUnicodeString(&KeyValueName, L"SystemPrefix");
//ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueInfoBuffer;
Status = NtQueryValueKey(
Key,
&KeyValueName,
KeyValuePartialInformation,
&ValueInfo,
sizeof(ValueInfo),
&DataLength
);
NtClose(Key);
if (NT_SUCCESS(Status) == TRUE)
{
RtlCopyMemory(&SystemPrefix, &ValueInfo.Data, sizeof(LARGE_INTEGER));
}
else
{
return;
}
}
else
{
SystemPrefix = ExpSetupSystemPrefix;
}
KeQuerySystemTime(&ShutDownTime);
//
// Clear low 6 bits of time
//
ShutDownTime.LowPart &= ~0x0000003f;
//
// If we have never gone through the refresh count logic, do it now.
//
if (ExpRefreshCount == 0)
{
ExpRefreshCount++;
//
// First time through time refresh. If we are not in setup mode, then make sure
// ShutDownTime is in good shape.
//
if (ExpSetupModeDetected == FALSE && ExpInTextModeSetup == FALSE)
{
if (ExpLastShutDown.QuadPart != 0)
{
NumberOfProcessors = ExpSetupSystemPrefix.LowPart;
NumberOfProcessors = NumberOfProcessors >> 5;
NumberOfProcessors = ~NumberOfProcessors;
NumberOfProcessors = NumberOfProcessors & 0x0000001f;
NumberOfProcessors++;
ExpLastShutDown.LowPart &= 0x3f;
if ((ExpSetupSystemPrefix.HighPart & 0x04000000) != 0)
{
if (((ExpLastShutDown.LowPart >> 1) == NumberOfProcessors) &&
((ExpLastShutDown.LowPart & 1) == 0))
{
ExpLastShutDown.HighPart = 0;
}
else if (ExpLastShutDown.HighPart == 0)
{
ExpLastShutDown.HighPart = 1;
}
}
else
{
if (((ExpLastShutDown.LowPart >> 1) != NumberOfProcessors) ||
((ExpLastShutDown.LowPart & 1) != 0))
{
ExpLastShutDown.HighPart = 0;
}
else if (ExpLastShutDown.HighPart == 0)
{
ExpLastShutDown.HighPart = 1;
}
}
ExpLastShutDown.LowPart |= 0x40;
}
}
else
{
ExpLastShutDown.QuadPart = 0;
}
}
if (ExpLastShutDown.QuadPart != 0 && ExpLastShutDown.HighPart == 0)
{
ShutDownTime.LowPart |= ExpLastShutDown.LowPart;
}
else
{
NumberOfProcessors = ExpSetupSystemPrefix.LowPart;
NumberOfProcessors = NumberOfProcessors >> 5;
NumberOfProcessors = ~NumberOfProcessors;
NumberOfProcessors = NumberOfProcessors & 0x0000001f;
NumberOfProcessors++;
ShutDownTime.LowPart |= (NumberOfProcessors << 1);
if ((ExpSetupSystemPrefix.HighPart & 0x04000000) != 0)
{
ShutDownTime.LowPart |= 1;
}
}
RtlInitUnicodeString(
&KeyName,
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Windows"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey(
&Key,
KEY_READ | KEY_WRITE | KEY_NOTIFY,
&ObjectAttributes
);
if (NT_SUCCESS(Status) == FALSE)
{
return;
}
RtlInitUnicodeString(&KeyValueName, L"ShutdownTime");
NtSetValueKey(
Key,
&KeyValueName,
0,
REG_BINARY,
&ShutDownTime,
sizeof(ShutDownTime)
);
NtFlushKey(Key);
NtClose(Key);
}
*/
}
VOID
ExpTimeRefreshDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(DeferredContext);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
if (ExInterlockedAddUlong(&ExpOkToTimeRefresh, 1, NULL) == 1)
{
ExQueueWorkItem(&ExpTimeRefreshWorkItem, DelayedWorkQueue);
}
}
VOID
ExpCenturyDpcRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(DeferredContext);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
if (ExInterlockedAddUlong(&ExpOkToTimeZoneRefresh, (ULONG)-1, NULL) == 1)
{
ExQueueWorkItem(&ExpCenturyWorkItem, DelayedWorkQueue);
}
}
VOID
ExpTimeRefreshWork(
IN PVOID Context
)
{
ULONG NumberOfProcessors;
LARGE_INTEGER ShutDownTime;
UNREFERENCED_PARAMETER(Context);
PAGED_CODE();
do
{
if (ExpRefreshCount == 0)
{
//
// First time through time refresh. If we are not in setup mode, then make sure
// ShutDownTime is in good shape.
//
if (ExpSetupModeDetected == FALSE && ExpInTextModeSetup == FALSE)
{
if (ExpLastShutDown.QuadPart != 0 && ExpLastShutDown.HighPart != 0)
{
NumberOfProcessors = ExpSetupSystemPrefix.LowPart;
NumberOfProcessors = NumberOfProcessors >> 5;
NumberOfProcessors = ~NumberOfProcessors;
NumberOfProcessors = NumberOfProcessors & 0x0000001f;
NumberOfProcessors++;
ShutDownTime = ExpLastShutDown;
ShutDownTime.LowPart &= 0x3f;
if ((ExpSetupSystemPrefix.HighPart & 0x04000000) != 0)
{
if (((ShutDownTime.LowPart >> 1) == NumberOfProcessors) &&
((ShutDownTime.LowPart & 1) == 0))
{
ShutDownTime.HighPart = 0;
}
else
{
if (ShutDownTime.HighPart == 0)
{
ShutDownTime.HighPart = 1;
}
}
}
else
{
if (((ShutDownTime.LowPart >> 1) != NumberOfProcessors) ||
((ShutDownTime.LowPart & 1) != 0))
{
ShutDownTime.HighPart = 0;
}
else
{
if (ShutDownTime.HighPart == 0)
{
ShutDownTime.HighPart = 1;
}
}
}
ExpRefreshCount++;
ExpLastShutDown = ShutDownTime;
ExpLastShutDown.LowPart |= 0x40;
}
}
else
{
ExpLastShutDown.QuadPart = 0;
}
}
else if (ExpSetupModeDetected == FALSE && ExpInTextModeSetup == FALSE)
{
ExpRefreshCount++;
}
//
// If enabled, synchronize the system time to the CMOS time. Pay attention to timezone bias.
//
//
// Time zone worker will set just did switchover. This periodic timer will clear this, but
// will also skip all time adjustment work. This will help keep us out of the danger zone
// +/- 1 hour around a switchover.
//
if (KeTimeSynchronization == TRUE)
{
ExAcquireTimeRefreshLock(TRUE);
ExUpdateSystemTimeFromCmos(0, 0);
ExReleaseTimeRefreshLock();
}
} while (ExInterlockedAddUlong(&ExpOkToTimeRefresh, (ULONG)-1, NULL) > 0);
KeSetTimer(
&ExpTimeRefreshTimer,
ExpTimeRefreshInterval,
&ExpTimeRefreshDpc
);
}
VOID
ExUpdateSystemTimeFromCmos(
IN BOOLEAN UpdateInterruptTime,
IN ULONG MaxSepInSeconds
)
{
LARGE_INTEGER SystemTime;
LARGE_INTEGER CmosTime;
LARGE_INTEGER KeTime;
LARGE_INTEGER TimeDiff;
TIME_FIELDS TimeFields;
LARGE_INTEGER MaxSeparation;
MaxSeparation.LowPart = MaxSepInSeconds;
if (MaxSepInSeconds == 0)
{
MaxSeparation.QuadPart = ExpMaxTimeSeparationBeforeCorrect.QuadPart;
}
if (ExCmosClockIsSane)
{
if (HalQueryRealTimeClock(&TimeFields) != FALSE)
{
KeQuerySystemTime(&KeTime);
if (RtlTimeFieldsToTime(&TimeFields, &CmosTime) == TRUE)
{
ExLocalTimeToSystemTime(&CmosTime, &SystemTime);
//
// Only set the SystemTime if the times differ by 1 minute
//
if (SystemTime.QuadPart > KeTime.QuadPart)
{
TimeDiff.QuadPart = SystemTime.QuadPart - KeTime.QuadPart;
}
else
{
TimeDiff.QuadPart = KeTime.QuadPart - SystemTime.QuadPart;
}
if (TimeDiff.QuadPart > MaxSeparation.QuadPart)
{
ExpSetSystemTime(0, UpdateInterruptTime, &SystemTime, &KeTime);
}
}
}
}
}
NTSTATUS
NtQuerySystemTime(
OUT PLARGE_INTEGER SystemTime
)
/*++
Routine Description:
This function returns the absolute system time. The time is in units of
100nsec ticks since the base time which is midnight January 1, 1601.
Arguments:
SystemTime - Supplies the address of a variable that will receive the
current system time.
Return Value:
STATUS_SUCCESS is returned if the service is successfully executed.
STATUS_ACCESS_VIOLATION is returned if the output parameter for the
system time cannot be written.
--*/
{
LARGE_INTEGER CurrentTime;
KPROCESSOR_MODE PreviousMode;
NTSTATUS ReturnValue;
PAGED_CODE();
//
// Establish an exception handler and attempt to write the system time
// to the specified variable. If the write attempt fails, then return
// the exception code as the service status. Otherwise return success
// as the service status.
//
try
{
//
// Get previous processor mode and probe argument if necessary.
//
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode)
{
ProbeForWrite((PVOID)SystemTime, sizeof(LARGE_INTEGER), sizeof(ULONG));
}
//
// Query the current system time and store the result in a local
// variable, then store the local variable in the current time
// variable. This is required so that faults can be prevented from
// happening in the query time routine.
//
KeQuerySystemTime(&CurrentTime);
*SystemTime = CurrentTime;
ReturnValue = STATUS_SUCCESS;
}
except (EXCEPTION_EXECUTE_HANDLER)
{
//
// If an exception occurs during the write of the current system time,
// then always handle the exception and return the exception code as the
// status value.
//
ReturnValue = GetExceptionCode();
}
return ReturnValue;
}
NTSTATUS
NtQueryTimerResolution(
OUT PULONG MaximumTime,
OUT PULONG MinimumTime,
OUT PULONG CurrentTime
)
/*++
Routine Description:
This function returns the maximum, minimum, and current time between
timer interrupts in 100ns units.
Arguments:
MaximumTime - Supplies the address of a variable that receives the
maximum time between interrupts.
MinimumTime - Supplies the address of a variable that receives the
minimum time between interrupts.
CurrentTime - Supplies the address of a variable that receives the
current time between interrupts.
Return Value:
STATUS_SUCCESS is returned if the service is successfully executed.
STATUS_ACCESS_VIOLATION is returned if an output parameter for one
of the times cannot be written.
--*/
{
KPROCESSOR_MODE PreviousMode;
NTSTATUS ReturnValue;
PAGED_CODE();
//
// Establish an exception handler and attempt to write the time increment
// values to the specified variables. If the write fails, then return the
// exception code as the service status. Otherwise, return success as the
// service status.
//
try
{
//
// Get previous processor mode and probe argument if necessary.
//
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode)
{
ProbeForWriteUlong(MaximumTime);
ProbeForWriteUlong(MinimumTime);
ProbeForWriteUlong(CurrentTime);
}
//
// Store the maximum, minimum, and current times in the specified
// variables.
//
*MaximumTime = KeMaximumIncrement;
*MinimumTime = KeMinimumIncrement;
*CurrentTime = KeTimeIncrement;
ReturnValue = STATUS_SUCCESS;
}
except (ExSystemExceptionFilter())
{
//
// If an exception occurs during the write of the time increment values,
// then handle the exception if the previous mode was user, and return
// the exception code as the status value.
//
ReturnValue = GetExceptionCode();
}
return ReturnValue;
}
NTSTATUS
NtSetTimerResolution(
IN ULONG DesiredTime,
IN BOOLEAN SetResolution,
OUT PULONG ActualTime
)
/*++
Routine Description:
This function sets the current time between timer interrupts and
returns the new value.
N.B. The closest value that the host hardware can support is returned
as the actual time.
Arguments:
DesiredTime - Supplies the desired time between timer interrupts in
100ns units.
SetResoluion - Supplies a boolean value that determines whether the timer
resolution is set (TRUE) or reset (FALSE).
ActualTime - Supplies a pointer to a variable that receives the actual
time between timer interrupts.
Return Value:
STATUS_SUCCESS is returned if the service is successfully executed.
STATUS_ACCESS_VIOLATION is returned if the output parameter for the
actual time cannot be written.
--*/
{
ULONG NewResolution;
PEPROCESS Process;
NTSTATUS Status;
PAGED_CODE();
//
// Acquire the time refresh lock
//
ExAcquireTimeRefreshLock(TRUE);
//
// Establish an exception handler and attempt to set the timer resolution
// to the specified value.
//
Process = PsGetCurrentProcess();
try
{
//
// Get previous processor mode and probe argument if necessary.
//
if (KeGetPreviousMode() != KernelMode)
{
ProbeForWriteUlong(ActualTime);
}
//
// Set (SetResolution is TRUE) or reset (SetResolution is FALSE) the
// timer resolution.
//
NewResolution = KeTimeIncrement;
Status = STATUS_SUCCESS;
if (SetResolution == FALSE)
{
//
// If the current process previously set the timer resolution,
// then clear the set timer resolution flag and decrement the
// timer resolution count. Otherwise, return an error.
//
if (Process->SetTimerResolution == FALSE)
{
Status = STATUS_TIMER_RESOLUTION_NOT_SET;
}
else
{
Process->SetTimerResolution = FALSE;
ExpTimerResolutionCount -= 1;
//
// If the timer resolution count is zero, the set the timer
// resolution to the maximum increment value.
//
if (ExpTimerResolutionCount == 0)
{
KeSetSystemAffinityThread(1);
NewResolution = HalSetTimeIncrement(KeMaximumIncrement);
KeRevertToUserAffinityThread();
KeTimeIncrement = NewResolution;
}
}
}
else
{
//
// If the current process has not previously set the timer
// resolution value, then set the set timer resolution flag
// and increment the timer resolution count.
//
if (Process->SetTimerResolution == FALSE)
{
Process->SetTimerResolution = TRUE;
ExpTimerResolutionCount += 1;
}
//
// Compute the desired value as the maximum of the specified
// value and the minimum increment value. If the desired value
// is less than the current timer resolution value, then set
// the timer resolution.
//
if (DesiredTime < KeMinimumIncrement)
{
DesiredTime = KeMinimumIncrement;
}
if (DesiredTime < KeTimeIncrement)
{
KeSetSystemAffinityThread(1);
NewResolution = HalSetTimeIncrement(DesiredTime);
KeRevertToUserAffinityThread();
KeTimeIncrement = NewResolution;
}
}
//
// Attempt to write the new timer resolution. If the write attempt
// fails, then do not report an error. When the caller attempts to
// access the resolution value, and access violation will occur.
//
try
{
*ActualTime = NewResolution;
}
except (ExSystemExceptionFilter())
{
NOTHING;
}
}
except (ExSystemExceptionFilter())
{
//
// If an exception occurs during the write of the actual time increment,
// then handle the exception if the previous mode was user, and return
// the exception code as the status value.
//
Status = GetExceptionCode();
}
//
// Release the time refresh lock
//
ExReleaseTimeRefreshLock();
return Status;
}
NTSTATUS
NtSetSystemTime(
IN PLARGE_INTEGER SystemTime,
OUT PLARGE_INTEGER PreviousTime OPTIONAL
)
/*++
Routine Description:
This function sets the current system time and optionally returns the
previous system time.
Arguments:
SystemTime - Supplies a pointer to the new value for the system time.
PreviousTime - Supplies an optional pointer to a variable that receives
the previous system time.
Return Value:
STATUS_SUCCESS is returned if the service is successfully executed.
STATUS_PRIVILEGE_NOT_HELD is returned if the caller does not have the
privilege to set the system time.
STATUS_ACCESS_VIOLATION is returned if the input parameter for the
system time cannot be read or the output parameter for the system
time cannot be written.
STATUS_INVALID_PARAMETER is returned if the input system time is negative.
--*/
{
LARGE_INTEGER CurrentTime;
LARGE_INTEGER NewTime;
LARGE_INTEGER CmosTime;
KPROCESSOR_MODE PreviousMode;
BOOLEAN HasPrivilege = FALSE;
TIME_FIELDS TimeFields;
BOOLEAN CmosMode;
PAGED_CODE();
//
// If the caller is really trying to set the time, then do it.
// If no time is passed, the caller is simply trying to update
// the system time zone information
//
if (ARGUMENT_PRESENT(SystemTime) == TRUE)
{
//
// Establish an exception handler and attempt to set the new system time.
// If the read attempt for the new system time fails or the write attempt
// for the previous system time fails, then return the exception code as
// the service status. Otherwise return either success or access denied
// as the service status.
//
try
{
//
// Get previous processor mode and probe arguments if necessary.
//
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode)
{
ProbeForRead((PVOID)SystemTime, sizeof(LARGE_INTEGER), sizeof(ULONG));
if (ARGUMENT_PRESENT(PreviousTime) == TRUE)
{
ProbeForWrite((PVOID)PreviousTime, sizeof(LARGE_INTEGER), sizeof(ULONG));
}
}
//
// Check if the current thread has the privilege to set the current
// system time. If the thread does not have the privilege, then return
// access denied.
//
HasPrivilege = SeSinglePrivilegeCheck(
SeSystemtimePrivilege,
PreviousMode
);
if (!HasPrivilege)
{
return STATUS_PRIVILEGE_NOT_HELD;
}
//
// Get the new system time and check to ensure that the value is
// positive and reasonable. If the new system time is negative, then
// return an invalid parameter status.
//
NewTime = *SystemTime;
if ((NewTime.HighPart < 0) || (NewTime.HighPart > 0x20000000))
{
return STATUS_INVALID_PARAMETER;
}
ExAcquireTimeRefreshLock(TRUE);
ExpSetSystemTime(1, 0, SystemTime, &CurrentTime);
ExReleaseTimeRefreshLock();
//
// Audit system time change
//
ExAcquireTimeRefreshLock(TRUE);
ExpSetSystemTime(1, 0, SystemTime, &CurrentTime);
SeAuditSystemTimeChange(CurrentTime, *SystemTime);
ExReleaseTimeRefreshLock();
//
// Anytime we set the system time, x86 systems will also have to set the registry
// to reflect the timezone bias.
//
if (ARGUMENT_PRESENT(PreviousTime) == TRUE)
{
*PreviousTime = CurrentTime;
}
return STATUS_SUCCESS;
}
except (EXCEPTION_EXECUTE_HANDLER)
{
//
// If an exception occurs during the read of the new system time or during
// the write of the previous sytem time, then always handle the exception
// and return the exception code as the status value.
//
return GetExceptionCode();
}
}
else
{
ExAcquireTimeRefreshLock(TRUE);
CmosMode = ExpSystemIsInCmosMode;
if (ExCmosClockIsSane)
{
if (HalQueryRealTimeClock(&TimeFields) != FALSE)
{
RtlTimeFieldsToTime(&TimeFields, &CmosTime);
if (ExpRefreshTimeZoneInformation(&CmosTime))
{
//
// Reset the CMOS time if it is stored in local
// time and we are switching away from CMOS time.
//
if (ExpRealTimeIsUniversal == FALSE)
{
KeQuerySystemTime(&CurrentTime);
if (CmosMode == FALSE)
{
ExSystemTimeToLocalTime(&CurrentTime, &CmosTime);
RtlTimeToTimeFields(&CmosTime, &TimeFields);
ExCmosClockIsSane = HalSetRealTimeClock(&TimeFields);
}
else
{
//
// Now we need to recompute our time base
// because we thought we had UTC but we really
// had local time
//
ExLocalTimeToSystemTime(&CmosTime, &NewTime);
KeSetSystemTime(&NewTime, &CurrentTime, FALSE, NULL);
}
}
PoNotifySystemTimeSet();
}
else
{
return STATUS_INVALID_PARAMETER;
}
}
else
{
return STATUS_INVALID_PARAMETER;
}
}
ExReleaseTimeRefreshLock();
return STATUS_SUCCESS;
}
}
VOID
ExpExpirationThread(
IN PVOID StartContext
)
{
UNREFERENCED_PARAMETER(StartContext);
//
// We do nothing here for the obvious reasons.
//
return;
}
NTSTATUS
NtLockProductActivationKeys(
IN OUT OPTIONAL ULONG *pPrivateVer,
OUT OPTIONAL ULONG *pSafeMode
)
{
UNREFERENCED_PARAMETER(pPrivateVer);
UNREFERENCED_PARAMETER(pSafeMode);
//
// TODO/NOTE: Remove this function if possible. For now, removing this (and in services.tab)
// will cause a BSOD.
//
return STATUS_SUCCESS;
}
@person4268

This comment has been minimized.

Copy link
Owner Author

@person4268 person4268 commented Sep 29, 2020

Evaluation stuff is setup in ./base/ntsetup/hives/mkhives.cmd - you should be able to edit this to remove all time restrictions from your builds.
@person4268

This comment has been minimized.

Copy link
Owner Author

@person4268 person4268 commented Sep 29, 2020

nmake set_builddate set_buildnum set_buildname -f makefil0

@person4268

This comment has been minimized.

Copy link
Owner Author

@person4268 person4268 commented Sep 30, 2020

even more condensed buildguide that works with cleanbuild:

Setup (for Win2003):
>set systime to Aug 1st 2003 before extraction
>extract cabs using x.cmd (edit it first)
>unset Read-Only on NT folder (+ subfolders/files)
>copy public\internal\windows\lib\i386\directui.lib from XP sources into same folder inside NT tree
>copy ThatOpenNTGuy's exinit.c/systime.c/exp.h into NT\base\ntos\ex\, replacing files in there
>import NT\tools\driver.pfx (double click and hit next through the import wizard)

Build:
>open cmd inside NT dir and run
>tools\razzle free offline
>wait for shit, close the notepad that opens
>inside the razzle window run
>perl tools\timebuild.pl -NOSYNC -NOSCORCH -NOPOSTBUILD
>wait for build to finish
>now open 3790src2.cab, extract the following 2 folders into your NT tree, replacing any files inside
>inetcore\outlookexpress\external\
>ds\security\services\ca\tools\certut\obj\
>check build.err, likely some errors there due to race conditions, run build /ZP to clear them

Post-build (builds setup CD etc):
>once build.err is empty, run inside razzle window:
>perl tools\timebuild.pl -NOCLEANBUILD -NOSYNC -NOSCORCH -RESUME
>after that's finished up with some errors, check binaries.x86fre\build_logs\postbuild.err
>should mention lots of missing files, grab those from server2003 RTM ISOs
>(ISO files end with _, eg explorer.ex_, use "expand /r explorer.ex_ C:\destFolder\" to convert them to proper format)
>edit tools\postbuildscripts\pbuild.dat, comment out the sxs_make_asms_cabs lines
>grab asms01.cab from w2k3 ISO and put replace the one inside binaries.x86fre, and binaries.x86fre\srv\i386
>finally run:
>perl tools\timebuild.pl -NOCLEANBUILD -NOSYNC -NOSCORCH -RESUME
>once it's done everything should be signed and ready, should now have a working setup inside binaries.x86fre\srv\
>use oscdimg to turn that into bootable iso:
>oscdimg -n -betfsboot.com D:\binaries.x86fre\srv srv.iso
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment