Article ID: 246689
Article Last Modified on 2/22/2007
APPLIES TO
- Microsoft Windows 2000 Server
- Microsoft Windows 2000 Advanced Server
- Microsoft Windows 2000 Professional Edition
- Microsoft Windows 98 Standard Edition
This article was previously published under Q246689
SUMMARY
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; else { // 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 return(FALSE); } 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); return(FALSE); } } } // 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()); return(FALSE); } // 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); } return(FALSE); } pQos = (QOS *)pBuf;
Keywords: kbdswnet2003swept kbapi kbgqos kbhowto kbnetwork KB246689