Thursday, March 28, 2013

WinDBG: dt vs ??

dt

The dt command stands for display type.

usage:
dt var

dt address

??

The ?? command is for evaluating a C++ expression.  You can use it like dt, but you can use it to do even more.  I personally like to just use it most of the time because C are more accessible to me often than trying to remember which switches I need to use with dt.

usage:
?? sizeof(var)

?? this

?? this->m_member_obj

?? array[25].member_ptr->val

?? g_some_global

Thursday, March 21, 2013

Checking an Event's Signaled State in KM w/ WinDBG

I've talked about debugging events in the past in UM in simple terms.  !handle works great, and although is use is slightly different in UM vs KM it provides a lot of good information, but lets say you are in KD and want to know if your event is signaled or not.  !handle will not tell you that.  This is how you do it.  Note: you need to have a KD to look at the kernel's objects.

1. Find the index of handle


1: kd> dt g_hMyEvent
my_bin!g_hMyEvent
0x00001218
Void



2. Use !handle to get the address of the event object.

1: kd> !handle 0x00001218 f -1 Event

Searching for handles of type Event

PROCESS 845f4b40  SessionId: 0  Cid: 040c    Peb: 7fbb4000  ParentCid: 023c
    DirBase: 7ffea200  ObjectTable: a194d280  HandleCount: 1071.
    Image: svchost.exe

Handle table at a194d280 with 1071 entries in use

1218: Object: aa934288  GrantedAccess: 001f0003 Entry: bb591430
Object: aa934288  Type: (845692b8) Event
    ObjectHeader: aa934270 (new version)
        HandleCount: 1  PointerCount: 62

3. Cast that pointer to the dispatch header it is
1: kd> ?? (PDISPATCHER_HEADER)0xaa934288
PDISPATCHER_HEADER 0xaa934288
   +0x000 Type             : 0 ''
   +0x001 TimerControlFlags : 0 ''
   +0x001 Absolute         : 0y0
   +0x001 Wake             : 0y0
   +0x001 EncodedTolerableDelay : 0y000000 (0)
   +0x001 Abandoned        : 0 ''
   +0x001 Signalling       : 0 ''
   +0x002 ThreadControlFlags : 0x4 ''
   +0x002 CycleProfiling   : 0y0
   +0x002 CounterProfiling : 0y0
   +0x002 GroupScheduling  : 0y1
   +0x002 AffinitySet      : 0y0
   +0x002 Reserved         : 0y0000
   +0x002 Hand             : 0x4 ''
   +0x002 Size             : 0x4 ''
   +0x003 TimerMiscFlags   : 0 ''
   +0x003 Index            : 0y0
   +0x003 Processor        : 0y00000 (0)
   +0x003 Inserted         : 0y0
   +0x003 Expired          : 0y0
   +0x003 DebugActive      : 0 ''
   +0x003 DpcActive        : 0 ''
   +0x000 Lock             : 0n262144
   +0x000 LockNV           : 0n262144
   +0x004 SignalState      : 0n1
   +0x008 WaitListHead     : _LIST_ENTRY [ 0xaa934290 - 0xaa934290 ]

There you go, you can see this event is in a signaled state.

By the way, the member Type 0 means event notification.  Other common values:

    EventNotificationObject = 0,
    EventSynchronizationObject = 1,
    MutantObject = 2,
    ProcessObject = 3,
    QueueObject = 4,
    SemaphoreObject = 5,
    ThreadObject = 6,




Tuesday, March 5, 2013

Setting FILETIME Timeout for SetThreadpoolWait

Using Window's new (since Vista) Threadpool is great.  You can read up on it here.  If you want some sample code on usage patterns, message me, and I can do a post on it later.

The threadpool has a generic wait on an handle (eg. event, process, etc.) mechanism.  It even has a timeout so say you want to wait either for an event or a timeout, but the timeout is in FILETIME format.  How do you convert a specified amount say in ms of time into a FILETIME?


HRESULT DoWaitWithTimeout(
    __in DWORD Timeout) // in ms
{
    HRESULT hr = S_OK;
    PMY_CONTEXT pContext = NULL;
    FILETIME timeout = {0};

    pContext = (PMY_CONTEXT)my_alloc(sizeof(MY_CONTEXT));

    if (!pContext) {
        hr = E_OUTOFMEMORY;
        goto Exit;
    }

    ZeroMemory(pContext, sizeof(MY_CONTEXT));
    pContext->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (!pContext->hEvent) {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    pContext->hWait = CreateThreadpoolWait(
            MyWaitCallback,
            pContext,
            NULL);

    if (!pContext->hWait) {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }

    if (Timeout) {
        ULARGE_INTEGER ulTimeout = {0};

        // Timeout in ms, FILETIME is in 100 ns increments
        ulTimeout.QuadPart = Timeout * -10000; 
        timeout.dwHighDateTime = ulTimeout.HighPart;
        timeout.dwLowDateTime = ulTimeout.LowPart;
    }
  
    SetThreadpoolWait(
            pContext->hWait,
            pContext->hEvent,
            &timeout);
// ...