Microsoft KB Archive/250461

From BetaArchive Wiki
Knowledge Base


Article ID: 250461

Article Last Modified on 2/28/2007



APPLIES TO

  • Microsoft Windows 2000 Server
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional Edition



This article was previously published under Q250461

SYMPTOMS

When you are doing a namespace query for the SVCID_HOSTNAME globally unique identifier (GUID) and use the WSALookupServiceNext Winsock API to dynamically determine the buffer size required for the WSAQUERYSET, the subsequent call to WSALookupServiceNext with the allocated buffer returns incomplete data and should not be relied upon.

RESOLUTION

To work around this problem, you can allocate an appropriately sized buffer before you make the first call to WSALookupServiceNext.

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

MORE INFORMATION

The following code exhibits the bug on Windows 2000, whereas on Windows NT 4.0 this code works as expected.

If you uncomment the lines noted in the code, the call works because the buffer is allocated beforehand.

#include <stdio.h>      // Standard I/O
#include <winsock2.h>   // winsock 2.0
#include <svcguid.h>    // guids

int main(int argc, char * argv[])
{
  WSADATA wsaData;
  DWORD dwResult;
  HANDLE hLookup = 0;
  WSAQUERYSET lpRestrictions;
  GUID guid = SVCID_HOSTNAME;

  dwResult = WSAStartup(MAKEWORD(2,2), &wsaData);

  if (dwResult != 0)
    {
    printf("Cannot startup Winsock: %d\n", dwResult);
    exit(1);
    }

  ZeroMemory(&lpRestrictions, sizeof(WSAQUERYSET));
  lpRestrictions.dwSize = sizeof(WSAQUERYSET);
  lpRestrictions.lpServiceClassId = &guid;

  dwResult = WSALookupServiceBegin(&lpRestrictions, LUP_RETURN_NAME, &hLookup);
  if (dwResult != SOCKET_ERROR)
    {
    DWORD dwLength = 0;
    WSAQUERYSET * pqs = NULL;
    
    // 
    // picking an arbitrary value works fine 
    // 
    // UNCOMMENT below for success on Windows 2000
    // 
    // pqs = (WSAQUERYSET *) malloc(sizeof(WSAQUERYSET) + 100);
    // dwLength = sizeof(WSAQUERYSET) + 100;
    // 

    do
      {
      if (WSALookupServiceNext(hLookup, 0, &dwLength, pqs) != 0)
        dwResult = WSAGetLastError();
      else
        dwResult = 0;

      if (dwResult == WSAEFAULT)
        {
        if (pqs) 
          free(pqs);
        pqs = (WSAQUERYSET *) malloc(dwLength);
        if (!pqs)
          {
          printf("Could not allocate memory: %d\n", GetLastError());
          exit(2);
          }
        else          
          continue;
        }
      
      // output it since we have it now        
      if ((dwResult == 0) && (pqs))
        printf("%s\n", pqs->lpszServiceInstanceName);

      }
      while ((dwResult != WSA_E_NO_MORE) && (dwResult != WSAENOMORE));      
    
    // clean-up
    free(pqs);
    WSALookupServiceEnd(hLookup);
    }
  else
    {
    printf("Error on WSALookupServiceBegin: %d\n", WSAGetLastError());
    exit(3);
    }
  

  WSACleanup();

  return 0;
}
                

Keywords: kbapi kbbug kbnetwork kbwinsock KB250461