CMyQueue::OnCreateFile(
    _In_ IWDFIoQueue* pWdfQueue,
    _In_ IWDFIoRequest* pWdfRequest,
    _In_ IWDFFile* pWdfFileObject
    )

/*++

Routine Description:

    Create callback from the framework for this default parallel queue 
    
    The create request will create a socket connection , create a file i/o target associated 
    with the socket handle for this connection and store in the file object context.

Aruments:
    
    pWdfQueue - Framework Queue instance
    pWdfRequest - Framework Request  instance
    pWdfFileObject - WDF file object for this create

 Return Value:

    VOID

--*/
{
    Trace(
        TRACE_LEVEL_INFORMATION, 
        "%!FUNC!"
        );
    
    HRESULT hr = S_OK;

    CComPtr<IWDFFileHandleTargetFactory> spFileHandleTargetFactory;

    CComPtr<IWDFIoTarget> pFileTarget;

    CComPtr<IWDFDevice> pDevice;

    HANDLE SocketHandle = NULL; 

    pWdfQueue->GetDevice(&pDevice);

    FileContext *pContext = NULL;

    //
    // Create new connection object 
    //
    
    CConnection *pConnection = new CConnection();

    if (NULL == pConnection )
    {
        hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
        Trace(
              TRACE_LEVEL_ERROR,
               L"ERROR: Could not create connection object %!hresult!",
               hr
               );
          goto Exit;
    }

    //
    // Connect to the socket server 
    //

    hr = pConnection->Connect(pDevice);

    if (FAILED(hr))
    {
        Trace(
              TRACE_LEVEL_ERROR,
               L"ERROR: Could not connect %!hresult!",
               hr
               );

        goto Exit;       

    }

    //
    // If that succeeds, get socket handle for the connection 
    //

    if ( NULL  ==  (SocketHandle = pConnection->GetSocketHandle()) ) 
    {
        hr = E_FAIL; 
        Trace(
              TRACE_LEVEL_ERROR,
               L"ERROR: Unable to obtain valid Socket Handle %!hresult!",
               hr
               );
          goto Exit;
    }

    //
    // Create file context for this file object 
    //

    pContext  = new  FileContext; 

    if (NULL == pContext)
    {
        hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
        Trace(
              TRACE_LEVEL_ERROR,
               L"ERROR: Could not create file context %!hresult!",
               hr
               );
          goto Exit;        

    }

    //
    // QI for IWDFFileHandleTargetFactory from the framework device object. 
    // Note UmdfDispatcher in Wdf Section in the Inf
    //

    hr = pDevice->QueryInterface(IID_PPV_ARGS(&spFileHandleTargetFactory));
    
    if (FAILED(hr))
    {
        Trace(
            TRACE_LEVEL_ERROR,
            L"ERROR: Unable to obtain target factory for creating FileHandle based I/O target %!hresult!",
            hr
            );
        goto Exit;
    }

    //
    // If that succeeds, Create a File Handle I/O Target and associate the socket handle with this target 
    //
    
    hr = spFileHandleTargetFactory->CreateFileHandleTarget(SocketHandle ,&pFileTarget);
 
    if (FAILED(hr))
    {
        Trace(
            TRACE_LEVEL_ERROR,
            L"ERROR: Unable to create framework I/O target %!hresult!",
            hr
            );
        goto Exit;
    }


    pContext->pFileTarget  = pFileTarget;

    pContext->pConnection = pConnection; 
     
    hr = pWdfFileObject->AssignContext(NULL,(void*)pContext);

    if (FAILED(hr))
    {
        Trace(
            TRACE_LEVEL_ERROR,
            L"ERROR: Unable to Assign Context to this File Object %!hresult!",
            hr
            );
        goto Exit;
    }

    

Exit:

    if (FAILED(hr))
    {

        if ( pFileTarget )
        {
            pFileTarget->DeleteWdfObject();
        }

        if (pConnection != NULL)
        {
            delete pConnection;            
            pConnection = NULL;
        }
        
        if (pContext != NULL)
        {
            delete pContext;            
            pContext = NULL;
        }

    }
    
    pWdfRequest->Complete(hr);

}