How To Use WSAIoctl with SIO_GET_QOS

Article translations Article translations
Article ID: 246689 - View products that this article applies to.
This article was previously published under Q246689
This article has been archived. It is offered "as is" and will no longer be updated.
Expand all | Collapse all


The version of the GQoS on Windows 2000 is version 4 (GQoSv4). The version of the GQoS on Windows 98 and Microsoft Windows 98 Second Edition is version 1 (GQoSv1). The WSAEnumProtocols function can be used to determine the version of the GQoS.

Using WSAIoctl with the SIO_GET_QOS control code can be different because GQoSv4 and GQoSv1 differ in how the API can and must be called. The differences are as follows:
  • GQoSv4 allows you to query the system to determine how large an output buffer you need in order to retrieve the QOS structure(s) whereas with GQoSv1 you must pass in a large enough buffer.
  • GQoSv4 requires the output buffer to be contiguous whereas GQoSv1 does not.
  • GQoSv4 requires that the supplied output buffer be large enough to contain all the Quality of Service (QOS) data (specifically the variable length provider-specific data in addition to the fixed size flowspec data); otherwise, none of the information will be returned, whereas GQoSv1 returns the portion of the provider-specific data (complete provider-specific QOS objects only) that can fit in the supplied provider-specific buffer.
  • GQoSv1 requires that the output buffer be initialized so that the provider-specific pointer in the QOS structure points to valid memory, whereas GQoSv4 treats the buffer strictly as an output-only parameter (as it should).
As background, the WSAIoctl function is called with the SIO_GET_QOS control code to retrieve one or more QOS structures from the system. Typically this is done in response to the receipt of an FD_QOS as a result of using either the WSAAsyncSelect or WSAEventSelect function. A high performance server application that utilizes Quality of Service most likely would not call either WSAAsyncSelect or WSAEventSelect but would instead call WSAIoctl(SIO_GET_QOS) in an overlapped manner, perhaps even by using I/O Completion Ports (IOCP).

More information

The following code snippet demonstrates a technique that can be used to call WSAIoctl with the SIO_GET_QOS control code on either GQoSv1 or GQoSv4, and takes into account the differences outlined earlier:
    DWORD   dwBytesReturned=0;
    DWORD   status;
    DWORD   dwBufferLen;
    CHAR    *pBuf = NULL;
    QOS     *pTempQos = NULL;
    QOS     *pQos = NULL;

    if (GQOSv1)
        // For GQOSv1 we must pick a buffer size
        dwBufferLen = 2048;
        // For GQOSv4 we can query the system to determine
        // how large a buffer we need to pass in.
        dwBufferLen = 0;
        status = WSAIoctl(sd, SIO_GET_QOS, NULL, 0,
                    &dwBufferLen, sizeof(dwBufferLen),
                    &dwBytesReturned, NULL, NULL);
        if (SOCKET_ERROR == status)
            DWORD dwErr = WSAGetLastError();
            if (WSAEWOULDBLOCK == dwErr)
                // nothing to do
            else if (WSAENOBUFS != dwErr)
                // some sort of error not related to passing a
                // large enough buffer
                printf("WSAIoctl(SIO_GET_QOS)-query: %d\n",dwErr);

    // For Windows 98 dwBufferLen has been set above, for
    // Windows 2000 we queried the OS for the proper buffer size
    printf("dwBufferlen for pQos = %d\n", dwBufferLen);
    if (!(pBuf = (CHAR *)malloc(dwBufferLen)))
        printf("malloc: %d\n", GetLastError());

    // GQOSv1 workaround - not needed for GQOSv4, but doesn't
    // hurt.  GQOSv1 needs the provider specific buffer to point 
    // to valid memory, whereas GQOSv4 simply needs a contiguous   
    // block of memory. Therefore we allocate a contiguous block of
    // memory cast it to a QOS structure and then set the provider
    // specific buffer pointer to just beyond the QOS structure
    // proper.  GQOSv1 needs this whereas GQOSv4 ignores this. 
    // GQOSv1 should not care, because this is strictly an output
    // buffer, GQOSv4 corrects this problem. 
    pTempQos = (QOS *)pBuf;
    pTempQos->ProviderSpecific.buf = pBuf + sizeof(QOS);
    pTempQos->ProviderSpecific.len = dwBufferLen - sizeof(QOS);
    // end GQOSv1 workaround

    status = WSAIoctl(sd, SIO_GET_QOS, NULL, 0,
                   pBuf, dwBufferLen, &dwBytesReturned,
                   NULL, NULL);
    if (SOCKET_ERROR == status)
        DWORD dwErr = WSAGetLastError();
        free((char *)pBuf);
        if (WSAEWOULDBLOCK != dwErr)
            printf("WSAIoctl(SIO_GET_QOS) %d\n", dwErr);
    pQos = (QOS *)pBuf;


Article ID: 246689 - Last Review: October 26, 2013 - Revision: 4.0
Applies to
  • Microsoft Windows 2000 Server
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional Edition
kbnosurvey kbarchive kbdswnet2003swept kbapi kbgqos kbhowto kbnetwork KB246689

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from