0

This is my first question on Stackoverflow so please be indulgent with me.

I am getting the local groups of the current logged on Windows user with my C++ MFC application with the following code:

#include <windows.h>
#include <lm.h>
#include <stdio.h>
#include <sstream>
#pragma comment(lib, "netapi32")
int test()
{
    char acUserName[100];
    DWORD nUserName = sizeof(acUserName);
    if (GetUserName(acUserName, &nUserName))
    {
        sysout( "User name is " << acUserName << "." << endl);
    }

    //printf("Local groups: \n");
    sysout("Local groups :\n");

    LPBYTE buffer;
    DWORD entries, total_entries;

    NetUserGetLocalGroups(NULL, L"EUROPE\\D*****", 0, LG_INCLUDE_INDIRECT, &buffer, MAX_PREFERRED_LENGTH, &entries, &total_entries);

    LOCALGROUP_USERS_INFO_0 *groups = (LOCALGROUP_USERS_INFO_0*)buffer;
    for (int i = 0; i<entries; i++)
    {
        sysout(groups[i].lgrui0_name << endl);
    }

    sysout("Entries Local: " << entries << endl);

    NetApiBufferFree(buffer);

    //printf("Global groups: \n");
    sysout("Global groups: \n");

    NetUserGetGroups(NULL, L"EUROPE\\DEU218535", 0, &buffer, MAX_PREFERRED_LENGTH, &entries, &total_entries);

    sysout("Entries Global: " << entries << endl);

    GROUP_USERS_INFO_0 *ggroups = (GROUP_USERS_INFO_0*)buffer;
    for (int i = 0; i<entries; i++)
    {
        //printf("\t%S\n", ggroups[i].grui0_name);
        sysout(ggroups[i].grui0_name << endl);
    }

    NetApiBufferFree(buffer);

    return 0;
}

NOTE: I defined sysout for easier console printing in Visual Studio

#define sysout( s )                         \
{                                           \
   std::ostringstream os_;                  \
   os_ << s;                                \
   OutputDebugString( os_.str().c_str() );  \
}

The output I'm getting when I run test() is this:

User name is D*****.
Local groups :
007A1E02
007A1DD6
007A1DCA
Entries Local: 3
Global groups: 
Entries Global: 0

Additional Info:

I am using Multi-Byte Character Set.

I know that:

  • 007A1E02
  • 007A1DD6
  • 007A1DCA

... look suspiciously like memory addresses. I tried everything to reinterpret the location as a readable datatype without any success.

Before I used GetUserName I used GetUserNameW, and that also returned a memory address instead of the clear text. Maybe there is a connection?

Thank you for your help!

zett42
  • 25,437
  • 3
  • 35
  • 72
KBell
  • 3
  • 1
  • What is a string if not a memory location, as a pointer to the first character. My guess is that cout interprets the value that it receives as an int/pointer rather than as a string. – Philippe Lignon Feb 15 '18 at 15:23
  • 1
    You have UNICODE #defined in your project, like you should. But your sysout() does not know beans about Unicode. So all you get from operator<<() is the pointer. Lose the macro, write functions. – Hans Passant Feb 15 '18 at 15:27
  • I tried: AllocConsole(); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); cout << groups[i].lgrui0_name << endl; And I am still getting memory locations – KBell Feb 15 '18 at 15:32

1 Answers1

1

The documentation says:

lgrui0_name

Pointer to a Unicode string specifying the name of a local group to which the user belongs

You need to use UNICODE methods (normally marked with an uppercase W in the end on Windows) or you need to convert it:

for (int i = 0; i<entries; i++)
{
    OutputDebugStringW(groups[i].lgrui0_name);
}
Community
  • 1
  • 1
nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • Thank you. This did the trick. Upvoted. I wasn't aware that this is an encoding problem. But I could have had the idea to look into the documentation. My bad! – KBell Feb 15 '18 at 15:37