/*++

Copyright (c) 2000  Microsoft Corporation

Module Name:

    vfstack.c

Abstract:

    This module contains code required to verify drivers don't improperly use
    thread stacks.

Author:

    Adrian J. Oney (adriao) 09-May-1998

Environment:

    Kernel mode.

--*/

#include "vfdef.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGEVRFY, VfStackSeedStack)
#endif

VOID
FASTCALL
VfStackSeedStack(
    IN  ULONG   Seed
    )
/*++

  Description:

    This routine "seeds" the stack so that uninitialized variables are
    more easily ferreted out.

    Note if the thread subsequently does a usermode wait, the memory
    manager throws out the filled pages on stack swapout and on swapin
    replaces them with randomly filled ones.

  Arguments:

      Seed - Value to seed stack with.

  Return Value:
  
      None.

--*/
{
#if !defined(_WIN64)
    KIRQL oldIrql;
    PKTHREAD Thread;
    PULONG StartingAddress;
    PULONG StackPointer;

    if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SEEDSTACK)) {
        return;
    }

    Thread = KeGetCurrentThread ();
    StartingAddress = (PULONG) Thread->StackLimit;

    //
    // We are going below the stack pointer.  Make sure no interrupt can occur.
    //

    KeRaiseIrql (HIGH_LEVEL, &oldIrql);

    _asm {
        mov StackPointer, esp
    }

    // 
    // Check the stack bounds and don't fill if some caller is whacking the
    // stack pointer.
    //

    if ((StackPointer <= StartingAddress) || (StackPointer >= (PULONG)Thread->StackBase)) {
        KeLowerIrql (oldIrql);
        return;
    }

    // 
    // We use the return value 0xFFFFFFFF, as it is an illegal return value. We
    // are trying to catch people who don't initialize NTSTATUS, and it's also
    // a good pointer trap too.
    //
    // Note RtlFillMemoryUlong is not used because calling it would use
    // additional stack which we don't want to have to account for in our
    // calculations.
    //

    while (StartingAddress < StackPointer) {
        *StartingAddress = Seed;
        StartingAddress += 1;
    }

    KeLowerIrql (oldIrql);
#else
    UNREFERENCED_PARAMETER (Seed);
#endif
}