HRESULT STDMETHODCALLTYPE CHelloWorldService::FilterNextFrame()

in HelloWorld/Cpp/dll/_HelloWorldService.cpp [10:97]


HRESULT STDMETHODCALLTYPE CHelloWorldService::FilterNextFrame(
    DkmStackContext* pStackContext,
    DkmStackWalkFrame* pInput,
    DkmArray<DkmStackWalkFrame*>* pResult
    )
{
    HRESULT hr;

    // The HelloWorld sample is a very simple debugger component which modified the call stack
    // so that there is a '[Hello World]' frame at the top of the call stack. All the frames
    // below this are left the same.

    if (pInput == NULL) // NULL input frame indicates the end of the call stack. This sample does nothing on end-of-stack.
        return S_OK; 
    
    // Get the CHelloWorldDataItem which is associated with this stack walk. This
    // lets us keep data associated with this stack walk.
    CComPtr<CHelloWorldDataItem> pDataItem;
    hr = CHelloWorldDataItem::GetInstance(pStackContext, &pDataItem);
    if (FAILED(hr))
        return hr;

    // Now use this data item to see if we are looking at the first (top-most) frame
    if (pDataItem->CurrentState() == State::Initial)
    {
        // On the top most frame, we want to return back two different frames. First 
        // we place the '[Hello World]' frame, and under that we put the input frame.

        // Allocate an array with two elements. Store it in a CAutoDkmArray so that
        // if anything fails, the memory will be automatically freed.
        CAutoDkmArray<DkmStackWalkFrame*> result;
        hr = DkmAllocArray(2, &result);
        if (FAILED(hr))
        {
            return hr;
        }

        // Create a string object for 'hello world'
        CComPtr<DkmString> pDescription;
        hr = DkmString::Create(L"[Hello World]", &pDescription);
        if (FAILED(hr))
        {
            return hr;
        }

        // Create the hello world frame object, and stick it in the array
        hr = DkmStackWalkFrame::Create(
            pStackContext->Thread(),
            NULL,                           // Annotated frame, so no instruction address
            pInput->FrameBase(),            // Use the same frame base as the input frame
            0,                              // annoted frame uses zero bytes
            DkmStackWalkFrameFlags::None,
            pDescription,
            NULL,                           // Annotated frame, so no registers
            NULL,
            &result.Members[0]
            );
        if (FAILED(hr))
        {
            return hr;
        }

        // Add the input frame into the array as well
        result.Members[1] = pInput;
        result.Members[1]->AddRef();

        // Array succesfully created, so return the value in the out param, and update our
        // state so that on the next frame we know not to add '[Hello World]' again.
        *pResult = result.Detach();
        pDataItem->SetState(State::HelloWorldFrameAdded);
    }
    else
    {
        // We have already added '[Hello World]' to this call stack, so just return
        // the input frame.

        hr = DkmAllocArray(1, pResult);
        if (FAILED(hr))
        {
            return hr;
        }

        pResult->Members[0] = pInput;
        pResult->Members[0]->AddRef();
    }

    return S_OK;
}