Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!


На бытовые приборы, к которым относится и оборудование для детей, этот список распространяться не должен.
А депутаты и прочие гос. служащие, допущенные к гостайне, должны иметь четкую инструкцию, какие устройства могут быть у них в доме.

И еще вопрос — а тот ли исходный код используется для сборки образов той же винды, который показывают нашим чекистам? Или у них свои, сляпаные из этих исходников, сборки винды? :)Если все бекдоры вырежут, это будет хороший подарок чекистам, так взять и слить бекдоры в стоковой винде. Потому как скомпиленные бинари переводятся в графы исполнения, и если дифф показывает, что вырезана ветка кода или вызов функции, место внимательно изучается.
//
// The following macro initializes thread local variables for the wait
// for multiple objects kernel service while context switching is disabled.
//
// N.B. IRQL must be raised to DPC level prior to the invocation of this
// macro.
//
// N.B. Initialization is done in this manner so this code does not get
// executed inside the dispatcher lock.
//
#define InitializeWaitMultiple() \
Thread->WaitBlockList = WaitBlockArray; \
Index = 0; \
do { \
WaitBlock = &WaitBlockArray[Index]; \
WaitBlock->Object = Object[Index]; \
WaitBlock->WaitKey = (CSHORT)(Index); \
WaitBlock->WaitType = WaitType; \
WaitBlock->Thread = Thread; \
WaitBlock->NextWaitBlock = &WaitBlockArray[Index + 1]; \
Index += 1; \
} while (Index < Count); \
WaitBlock->NextWaitBlock = &WaitBlockArray[0]; \
Thread->WaitStatus = 0; \
if (ARGUMENT_PRESENT(Timeout)) { \
WaitTimer->NextWaitBlock = &WaitBlockArray[0]; \
KiSetDueTime(Timer, *Timeout, &Hand); \
DueTime.QuadPart = Timer->DueTime.QuadPart; \
InitializeListHead(&Timer->Header.WaitListHead); \
} \
Thread->Alertable = Alertable; \
Thread->WaitMode = WaitMode; \
Thread->WaitReason = (UCHAR)WaitReason; \
Thread->WaitListEntry.Flink = NULL; \
StackSwappable = KiIsKernelStackSwappable(WaitMode, Thread); \
Thread->WaitTime = KiQueryLowTickCount()
NTSTATUS
KeWaitForMultipleObjects (
__in ULONG Count,
__in_ecount(Count) PVOID Object[],
__in WAIT_TYPE WaitType,
__in KWAIT_REASON WaitReason,
__in KPROCESSOR_MODE WaitMode,
__in BOOLEAN Alertable,
__in_opt PLARGE_INTEGER Timeout,
__out_opt PKWAIT_BLOCK WaitBlockArray
)
/*++
Routine Description:
This function waits until the specified objects attain a state of
Signaled. The wait can be specified to wait until all of the objects
attain a state of Signaled or until one of the objects attains a state
of Signaled. An optional timeout can also be specified. If a timeout
is not specified, then the wait will not be satisfied until the objects
attain a state of Signaled. If a timeout is specified, and the objects
have not attained a state of Signaled when the timeout expires, then
the wait is automatically satisfied. If an explicit timeout value of
zero is specified, then no wait will occur if the wait cannot be satisfied
immediately. The wait can also be specified as alertable.
Arguments:
Count - Supplies a count of the number of objects that are to be waited
on.
Object[] - Supplies an array of pointers to dispatcher objects.
WaitType - Supplies the type of wait to perform (WaitAll, WaitAny).
WaitReason - Supplies the reason for the wait.
WaitMode - Supplies the processor mode in which the wait is to occur.
Alertable - Supplies a boolean value that specifies whether the wait is
alertable.
Timeout - Supplies a pointer to an optional absolute of relative time over
which the wait is to occur.
WaitBlockArray - Supplies an optional pointer to an array of wait blocks
that are to used to describe the wait operation.
Return Value:
The wait completion status. A value of STATUS_TIMEOUT is returned if a
timeout occurred. The index of the object (zero based) in the object
pointer array is returned if an object satisfied the wait. A value of
STATUS_ALERTED is returned if the wait was aborted to deliver an alert
to the current thread. A value of STATUS_USER_APC is returned if the
wait was aborted to deliver a user APC to the current thread.
--*/
{
PKPRCB CurrentPrcb;
LARGE_INTEGER DueTime;
ULONG Hand;
ULONG_PTR Index;
LARGE_INTEGER NewTime;
PKMUTANT Objectx;
PLARGE_INTEGER OriginalTime;
PRKQUEUE Queue;
LOGICAL StackSwappable;
PRKTHREAD Thread;
PRKTIMER Timer;
PRKWAIT_BLOCK WaitBlock;
NTSTATUS WaitStatus;
PKWAIT_BLOCK WaitTimer;
//
// Set constant variables.
//
Hand = 0;
Thread = KeGetCurrentThread();
OriginalTime = Timeout;
Timer = &Thread->Timer;
WaitTimer = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
//
// If a wait block array has been specified, then the maximum number of
// objects that can be waited on is specified by MAXIMUM_WAIT_OBJECTS.
// Otherwise the builtin wait blocks in the thread object are used and
// the maximum number of objects that can be waited on is specified by
// THREAD_WAIT_OBJECTS. If the specified number of objects is not within
// limits, then bugcheck.
//
if (ARGUMENT_PRESENT(WaitBlockArray)) {
if (Count > MAXIMUM_WAIT_OBJECTS) {
KeBugCheck(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
}
} else {
if (Count > THREAD_WAIT_OBJECTS) {
KeBugCheck(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
}
WaitBlockArray = &Thread->WaitBlock[0];
}
ASSERT(Count != 0);
//
// If the dispatcher database is already held, then initialize the thread
// local variables. Otherwise, raise IRQL to DPC level, initialize the
// thread local variables, and lock the dispatcher database.
//
if (ReadForWriteAccess(&Thread->WaitNext) == FALSE) {
goto WaitStart;
}
Thread->WaitNext = FALSE;
InitializeWaitMultiple();
//
// Start of wait loop.
//
// Note this loop is repeated if a kernel APC is delivered in the middle
// of the wait or a kernel APC is pending on the first attempt through
// the loop.
//
do {
//
// Test to determine if a kernel APC is pending.
//
// If a kernel APC is pending, the special APC disable count is zero,
// and the previous IRQL was less than APC_LEVEL, then a kernel APC
// was queued by another processor just after IRQL was raised to
// DISPATCH_LEVEL, but before the dispatcher database was locked.
//
// N.B. This can only happen in a multiprocessor system.
//
Thread->Preempted = FALSE;
if (Thread->ApcState.KernelApcPending &&
(Thread->SpecialApcDisable == 0) &&
(Thread->WaitIrql < APC_LEVEL)) {
//
// Unlock the dispatcher database and lower IRQL to its previous
// value. An APC interrupt will immediately occur which will result
// in the delivery of the kernel APC if possible.
//
KiUnlockDispatcherDatabase(Thread->WaitIrql);
} else {
//
// Construct wait blocks and check to determine if the wait is
// already satisfied. If the wait is satisfied, then perform
// wait completion and return. Else put current thread in a wait
// state if an explicit timeout value of zero is not specified.
//
Index = 0;
if (WaitType == WaitAny) {
do {
//
// Test if wait can be satisfied immediately.
//
Objectx = (PKMUTANT)Object[Index];
ASSERT(Objectx->Header.Type != QueueObject);
//
// If the object is a mutant object and the mutant object
// has been recursively acquired MINLONG times, then raise
// an exception. Otherwise if the signal state of the mutant
// object is greater than zero, or the current thread is
// the owner of the mutant object, then satisfy the wait.
//
if (Objectx->Header.Type == MutantObject) {
if ((Objectx->Header.SignalState > 0) ||
(Thread == Objectx->OwnerThread)) {
if (Objectx->Header.SignalState != MINLONG) {
KiWaitSatisfyMutant(Objectx, Thread);
WaitStatus = (NTSTATUS)(Index | Thread->WaitStatus);
goto NoWait;
} else {
KiUnlockDispatcherDatabase(Thread->WaitIrql);
ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
}
}
//
// If the signal state is greater than zero, then satisfy
// the wait.
//
} else if (Objectx->Header.SignalState > 0) {
KiWaitSatisfyOther(Objectx);
WaitStatus = (NTSTATUS)(Index);
goto NoWait;
}
Index += 1;
} while(Index < Count);
} else {
do {
//
// Test if wait can be satisfied.
//
Objectx = (PKMUTANT)Object[Index];
ASSERT(Objectx->Header.Type != QueueObject);
//
// If the object is a mutant object and the mutant object
// has been recursively acquired MINLONG times, then raise
// an exception. Otherwise if the signal state of the mutant
// object is less than or equal to zero and the current
// thread is not the owner of the mutant object, then the
// wait cannot be satisfied.
//
if (Objectx->Header.Type == MutantObject) {
if ((Thread == Objectx->OwnerThread) &&
(Objectx->Header.SignalState == MINLONG)) {
KiUnlockDispatcherDatabase(Thread->WaitIrql);
ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
} else if ((Objectx->Header.SignalState <= 0) &&
(Thread != Objectx->OwnerThread)) {
break;
}
//
// If the signal state is less than or equal to zero, then
// the wait cannot be satisfied.
//
} else if (Objectx->Header.SignalState <= 0) {
break;
}
Index += 1;
} while(Index < Count);
//
// If all objects have been scanned, then satisfy the wait.
//
if (Index == Count) {
WaitBlock = &WaitBlockArray[0];
do {
Objectx = (PKMUTANT)WaitBlock->Object;
KiWaitSatisfyAny(Objectx, Thread);
WaitBlock = WaitBlock->NextWaitBlock;
} while (WaitBlock != &WaitBlockArray[0]);
WaitStatus = (NTSTATUS)Thread->WaitStatus;
goto NoWait;
}
}
//
// Test for alert pending.
//
TestForAlertPending(Alertable);
//
// Check to determine if a timeout value is specified.
//
if (ARGUMENT_PRESENT(Timeout)) {
//
// Check if the timer has already expired.
//
// N.B. The constant fields of the timer wait block are
// initialized when the thread is initialized. The
// constant fields include the wait object, wait key,
// wait type, and the wait list entry link pointers.
//
if (KiCheckDueTime(Timer) == FALSE) {
WaitStatus = (NTSTATUS)STATUS_TIMEOUT;
goto NoWait;
}
WaitBlock->NextWaitBlock = WaitTimer;
}
//
// Insert wait blocks in object wait lists.
//
WaitBlock = &WaitBlockArray[0];
do {
Objectx = (PKMUTANT)WaitBlock->Object;
InsertTailList(&Objectx->Header.WaitListHead, &WaitBlock->WaitListEntry);
WaitBlock = WaitBlock->NextWaitBlock;
} while (WaitBlock != &WaitBlockArray[0]);
//
// If the current thread is processing a queue entry, then attempt
// to activate another thread that is blocked on the queue object.
//
Queue = Thread->Queue;
if (Queue != NULL) {
KiActivateWaiterQueue(Queue);
}
//
// Set the thread wait parameters, set the thread dispatcher state
// to Waiting, and insert the thread in the wait list.
//
CurrentPrcb = KeGetCurrentPrcb();
Thread->State = Waiting;
if (StackSwappable != FALSE) {
InsertTailList(&CurrentPrcb->WaitListHead, &Thread->WaitListEntry);
}
//
// Set swap busy for the current thread, unlock the dispatcher
// database, and switch to a new thread.
//
// Control is returned at the original IRQL.
//
ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);
KiSetContextSwapBusy(Thread);
if (ARGUMENT_PRESENT(Timeout)) {
KiInsertOrSignalTimer(Timer, Hand);
} else {
KiUnlockDispatcherDatabaseFromSynchLevel();
}
WaitStatus = (NTSTATUS)KiSwapThread(Thread, CurrentPrcb);
//
// If the thread was not awakened to deliver a kernel mode APC,
// then return the wait status.
//
if (WaitStatus != STATUS_KERNEL_APC) {
return WaitStatus;
}
if (ARGUMENT_PRESENT(Timeout)) {
//
// Reduce the amount of time remaining before timeout occurs.
//
Timeout = KiComputeWaitInterval(OriginalTime,
&DueTime,
&NewTime);
}
}
//
// Raise IRQL to SYNCH level, initialize the thread local variables,
// and lock the dispatcher database.
//
WaitStart:
Thread->WaitIrql = KeRaiseIrqlToSynchLevel();
InitializeWaitMultiple();
KiLockDispatcherDatabaseAtSynchLevel();
} while (TRUE);
//
// The thread is alerted or a user APC should be delivered. Unlock the
// dispatcher database, lower IRQL to its previous value, and return
// the wait status.
//
KiUnlockDispatcherDatabase(Thread->WaitIrql);
return WaitStatus;
//
// The wait has been satisfied without actually waiting.
//
// Unlock the dispatcher database and remain at SYNCH level.
//
NoWait:
KiUnlockDispatcherDatabaseFromSynchLevel();
//
// Adjust the thread quantum, exit the scheduler, and return the wait
// completion status.
//
KiAdjustQuantumThread(Thread);
return WaitStatus;
}// magic number, местами построчно и с ASCII-графикой расписанный алгоритм балансировки дерева (с припиской, что Кнут говорит, что это просто)
Глава Минкомсвязи предложил Apple и SAP раскрыть свои исходные коды российским специалистам