void GetMetadata()

in IMDSSample-windows.cpp [13:172]


void GetMetadata(LPCWSTR serverName, WORD port, LPCWSTR url)
{
    LPSTR pszOutBuffer = NULL;
    HINTERNET  hSession = NULL, hConnect = NULL, hRequest = NULL;

    try
    {
        // ========================================================================================
        // Setup connection
        // ========================================================================================
        hSession = WinHttpOpen(L"WinHTTP connection from WS to IMDS",
                               WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                               WINHTTP_NO_PROXY_NAME,
                               WINHTTP_NO_PROXY_BYPASS,
                               /* dwFlags */ 0);
        if (hSession == NULL)
            throw L"Failed to create session";

        hConnect = WinHttpConnect(hSession, serverName, port, /* dwReserved */ 0);
        if(!hConnect)
        {
            throw L"Failed to connect";
        }

        hRequest = WinHttpOpenRequest(hConnect, L"GET", url,
                                      NULL, WINHTTP_NO_REFERER,
                                      WINHTTP_DEFAULT_ACCEPT_TYPES,
                                      0);

        if(!hRequest) throw L"Failed to open request";
      
        if(!WinHttpAddRequestHeaders(hRequest, MetadataRequiredHeader, -1L, WINHTTP_ADDREQ_FLAG_ADD))
            throw L" Failed in WinHttpAddRequestHeaders";

        if(!WinHttpSendRequest(hRequest,
                               WINHTTP_NO_ADDITIONAL_HEADERS, /* dwHeadersLength */ 0,
                               WINHTTP_NO_REQUEST_DATA, /* dwOptionalLength */ 0,
                               /* dwTotalLength */ 0, /* dwContext */ 0))
            throw L"Failed in WinHttpSendRequest";
        
        // ========================================================================================
        // Receive response and headers
        // ========================================================================================
        DWORD httpStatusCode = 0;
        DWORD httpStatusSize = sizeof(httpStatusCode);
        if(!WinHttpReceiveResponse(hRequest, /* lpReserved */ NULL))
        {
            throw L"Failed in WinHttpReceiveReponse";
        }

        if(!WinHttpQueryHeaders(hRequest,
                                WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
                                WINHTTP_HEADER_NAME_BY_INDEX,
                                &httpStatusCode, &httpStatusSize, WINHTTP_NO_HEADER_INDEX))
        {
            throw L"Failed in WinHttpQueryHeaders";
        }
        
        std::wcout << L"Status code: " << httpStatusCode << std::endl;

        wchar_t contentType[256];
        DWORD headerLength = sizeof(contentType);
        if(!WinHttpQueryHeaders(hRequest,
                                WINHTTP_QUERY_CONTENT_TYPE,
                                NULL,
                                contentType,
                                &headerLength,
                                WINHTTP_NO_HEADER_INDEX))
        {
            throw L"Failed inWinHttpQueryHeaders";
        }

        
        DWORD dwSize;
        WinHttpQueryHeaders(hRequest, 
                            WINHTTP_QUERY_RAW_HEADERS_CRLF,
                            WINHTTP_HEADER_NAME_BY_INDEX, NULL, 
                            &dwSize, WINHTTP_NO_HEADER_INDEX);
        if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        {
            auto lpOutBuffer = new wchar_t[dwSize/sizeof(wchar_t)];

            // Now, use WinHttpQueryHeaders to retrieve the header.
            if(!WinHttpQueryHeaders(hRequest,
                                    WINHTTP_QUERY_RAW_HEADERS_CRLF,
                                    WINHTTP_HEADER_NAME_BY_INDEX,
                                    lpOutBuffer, &dwSize,
                                    WINHTTP_NO_HEADER_INDEX))
            {
                throw L"Failed in WinHttpQueryHeaders - All Headers";
            }

            std::wcout << L"=============================================================" << std::endl;
            std::wcout << lpOutBuffer;
            std::wcout << L"=============================================================" << std::endl;

            delete []  lpOutBuffer;
        }

        // ========================================================================================
        // Receive data from server and print
        // ========================================================================================
        // Keep checking for data until there is nothing left.
        dwSize = 0;
        do
        {
            // Check for available data.
            if(!WinHttpQueryDataAvailable(hRequest, &dwSize))
            {
                throw L"Failed in WinHttpQueryDataAvailable";
            }

            // Allocate space for the buffer.
            pszOutBuffer = new char[dwSize + 1];
            if(pszOutBuffer == NULL)
            {
                throw L"Failed to allocate memory for pszOutBuffer.";
            }

            // Read the data.
            ZeroMemory(pszOutBuffer, dwSize + 1);
    
            DWORD dwDownloaded = 0;
            if(!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
            {
                throw L"Failed in WinHttpReadData";
            }

            // this is a simple client and we don't parse content-type to find charset
            // we assume IMDS always returns utf-8
            int wchars_num = ::MultiByteToWideChar(CP_UTF8 , 0 , pszOutBuffer, -1, NULL , 0 );
            wchar_t* wstr = new wchar_t[wchars_num];
            ::MultiByteToWideChar( CP_UTF8 , 0 , pszOutBuffer, -1, wstr , wchars_num );
            
            std::wcout << wstr;

            // Free the memory allocated to the buffer.
            delete[] wstr;
            delete[] pszOutBuffer;
            pszOutBuffer = NULL;

        } while (dwSize > 0);
    }
    catch(LPCWSTR msg)
    {
        std::wcout << L"ERROR!! " << msg;
    }
    
    if (hRequest)
        WinHttpCloseHandle(hRequest);
        
    if (hConnect)
        WinHttpCloseHandle(hConnect);
        
    if (hSession)
        WinHttpCloseHandle(hSession);
        
    if (pszOutBuffer != NULL)
        delete[] pszOutBuffer;
}