Skip to content

It is impossible to use resumeHandle in NetWkstaUserEnum #4955

@OrbintSoft

Description

@OrbintSoft

Describe the bug

NetWkstaUserEnum appears to retrieve users in reverse order and makes a misuse resumeHandle , this makes impossible to use the function with a specified buffer size.
If you execute the code from Microsoft documentation: https://learn.microsoft.com/en-us/windows/win32/api/lmwksta/nf-lmwksta-netwkstauserenum
and you setup a buffer able to hold only a partial list of users, the code will be blocked in the loop forever returning always the same chunk of users.

You can refer at this stackoverflow answer: https://stackoverflow.com/a/79271924/5081328 where [RbMm] did a detailed analysis of the bug.

Steps to reproduce the bug

Take a windows machine with a considerable amount of currently simultaneously logged users.

execute this code as taken from Microsoft documentation:

`#ifndef UNICODE
#define UNICODE
#endif
#pragma comment(lib, "netapi32.lib")

#include <stdio.h>
#include <assert.h>
#include <windows.h> 
#include <lm.h>

int wmain(int argc, wchar_t *argv[])
{
   LPWKSTA_USER_INFO_0 pBuf = NULL;
   LPWKSTA_USER_INFO_0 pTmpBuf;
   DWORD dwLevel = 0;
   DWORD dwPrefMaxLen = 100;
   DWORD dwEntriesRead = 0;
   DWORD dwTotalEntries = 0;
   DWORD dwResumeHandle = 0;
   DWORD i;
   DWORD dwTotalCount = 0;
   NET_API_STATUS nStatus;
   LPWSTR pszServerName = NULL;

   if (argc > 2)
   {
      fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
      exit(1);
   }
   // The server is not the default local computer.
   //
   if (argc == 2)
      pszServerName = argv[1];
   fwprintf(stderr, L"\nUsers currently logged on %s:\n", pszServerName);
   //
   // Call the NetWkstaUserEnum function, specifying level 0.
   //
   do // begin do
   {
      nStatus = NetWkstaUserEnum( pszServerName,
                                  dwLevel,
                                  (LPBYTE*)&pBuf,
                                  dwPrefMaxLen,
                                  &dwEntriesRead,
                                  &dwTotalEntries,
                                  &dwResumeHandle);
      //
      // If the call succeeds,
      //
      if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
      {
         if ((pTmpBuf = pBuf) != NULL)
         {
            //
            // Loop through the entries.
            //
            for (i = 0; (i < dwEntriesRead); i++)
            {
               assert(pTmpBuf != NULL);

               if (pTmpBuf == NULL)
               {
                  //
                  // Only members of the Administrators local group
                  //  can successfully execute NetWkstaUserEnum
                  //  locally and on a remote server.
                  //
                  fprintf(stderr, "An access violation has occurred\n");
                  break;
               }
               //
               // Print the user logged on to the workstation. 
               //
               wprintf(L"\t-- %s\n", pTmpBuf->wkui0_username);

               pTmpBuf++;
               dwTotalCount++;
            }
         }
      }
      //
      // Otherwise, indicate a system error.
      //
      else
         fprintf(stderr, "A system error has occurred: %d\n", nStatus);
      //
      // Free the allocated memory.
      //
      if (pBuf != NULL)
      {
         NetApiBufferFree(pBuf);
         pBuf = NULL;
      }
   }
   // 
   // Continue to call NetWkstaUserEnum while 
   //  there are more entries. 
   // 
   while (nStatus == ERROR_MORE_DATA); // end do
   //
   // Check again for allocated memory.
   //
   if (pBuf != NULL)
      NetApiBufferFree(pBuf);
   //
   // Print the final count of workstation users.
   //
   fprintf(stderr, "\nTotal of %d entries enumerated\n", dwTotalCount);

   return 0;
}

Set dwPrefMaxLen to a size able hold at least one user, execute the code.

Expected behavior

It should fetch all users that can be hold in the buffer specified by dwPrefMaxLen , the call should give a chunk of users and return ERROR_MORE_DATA-

At the next iteration NetWkstaUserEnum should retrieve the next chunk of users.

Screenshots

No response

NuGet package version

None

Packaging type

No response

Windows version

Windows 11 version 22H2 (22621, 2022 Update), Windows 10 version 22H2 (19045, 2022 Update), Windows 11 version 21H2 (22000), Windows 10 version 21H2 (19044, November 2021 Update), Windows 10 version 21H1 (19043, May 2021 Update), Windows 10 version 20H2 (19042, October 2020 Update), Windows 10 version 2004 (19041, May 2020 Update), Windows 10 version 1909 (18363, November 2019 Update), Windows 10 version 1903 (18362, May 2019 Update), Windows 10 version 1809 (17763, October 2018 Update)

IDE

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-ExternalTopics external to Windows App SDK

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions