Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 456
  • Last Modified:

Getting group information for a user

I'm writing an application with Visual C++ 6.0 on Windows 2000.  I would like to determine user privileges based on a user being in a group.  For example, a user that logs in and that user is in the group TestAdmins.  In the applicatin, I want to be able to take the username that is logged in and find out if they are currently a member of the group TestAdmins.  I've read a little about ADSI but not sure if this is the way I should go.

Any help is truly appreciated.

0
jstephe1
Asked:
jstephe1
  • 5
  • 4
1 Solution
 
migelCommented:
Hi!
1. To get current user uou can use GetUserName API
2. to find User group you have to use NetUserGetGroups API
for example:

{
   LPGROUP_USERS_INFO_0 pBuf = NULL;
   DWORD dwLevel = 0;
   DWORD dwPrefMaxLen = -1;
   DWORD dwEntriesRead = 0;
   DWORD dwTotalEntries = 0;
   NET_API_STATUS nStatus;

   //
   // Call the NetUserGetGroups function, specifying level 0.
   //
   nStatus = NetUserGetGroups(NULL,
                              lpszUserName,
                              0,
                              (LPBYTE*)&pBuf,
                              dwPrefMaxLen,
                              &dwEntriesRead,
                              &dwTotalEntries);
   //
   // If the call succeeds,
   //
   if (nStatus == NERR_Success)
   {
      LPGROUP_USERS_INFO_0 pTmpBuf;
      DWORD i;
      DWORD dwTotalCount = 0;

      if ((pTmpBuf = pBuf) != NULL)
      {
         fprintf(stderr, "\nGlobal group(s):\n");
         //
         // Loop through the entries;
         //  print the name of the global groups
         //  to which the user belongs.
         //
         for (i = 0; i < dwEntriesRead; i++)
         {
            assert(pTmpBuf != NULL);

            if (pTmpBuf == NULL)
            {
               break;
            }

            //to get GroupName use:
            // pTmpBuf->grui0_name

            pTmpBuf++;
            dwTotalCount++;
         }
      }
      //
      // If all available entries were
      //  not enumerated, print the number actually
      //  enumerated and the total number available.
   }
   else
     // error occured!
       MessageBox();

   //
   // Free the allocated buffer.
   //
   if (pBuf != NULL)
      NetApiBufferFree(pBuf);
0
 
jstephe1Author Commented:
I implemented the GetUserName function like this:

TCHAR lpszUserName[250];
DWORD dwUserNameLength = 250;

GetUserName( lpszUserName, &dwUserNameLength );

I get the user name "Administrator" after the call.  I then did your if condition call to the NetUserGetGroups.  Everytime I call it it comes back NERR_UserNotFound.  Do I need to specify the server as the first parameter?  If so, how would I do that?

0
 
migelCommented:
Hi!
it is strange I run this code and status is ok;
1. my code enumerate global users groups for local ones you need to use
NetUserGetLocalGroups
here is example that working for me (console APP):

#ifndef UNICODE
#define UNICODE
#endif

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

int wmain(int argc, wchar_t *argv[])
{
   LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
   DWORD dwLevel = 0;
   DWORD dwFlags = LG_INCLUDE_INDIRECT ;
   DWORD dwPrefMaxLen = -1;
   DWORD dwEntriesRead = 0;
   DWORD dwTotalEntries = 0;
   NET_API_STATUS nStatus;
/*
   if (argc != 3)
   {
      fwprintf(stderr, L"Usage: %s \\\\ServerName UserName\n", argv[0]);
      exit(1);
   }
*/
     TCHAR lpszUserName[250];
     DWORD dwUserNameLength = 250;

     GetUserName( lpszUserName, &dwUserNameLength );   //
   nStatus = NetUserGetLocalGroups(NULL,
                                   lpszUserName,
                                   dwLevel,
                                   dwFlags,
                                   (LPBYTE *) &pBuf,
                                   dwPrefMaxLen,
                                   &dwEntriesRead,
                                   &dwTotalEntries);
   //
   // If the call succeeds,
   //
   if (nStatus == NERR_Success)
   {
      LPLOCALGROUP_USERS_INFO_0 pTmpBuf;
      DWORD i;
      DWORD dwTotalCount = 0;

      if ((pTmpBuf = pBuf) != NULL)
      {
         fprintf(stderr, "\nLocal group(s):\n");
         //
         // Loop through the entries and
         //  print the names of the local groups
         //  to which the user belongs.
         //
         for (i = 0; i < dwEntriesRead; i++)
         {
            assert(pTmpBuf != NULL);

            if (pTmpBuf == NULL)
            {
               fprintf(stderr, "An access violation has occurred\n");
               break;
            }

            wprintf(L"\t-- %s\n", pTmpBuf->lgrui0_name);

            pTmpBuf++;
            dwTotalCount++;
         }
      }
         //
         // If all available entries were
         //  not enumerated, print the number actually
         //  enumerated and the total number available.
         //
      if (dwEntriesRead < dwTotalEntries)
         fprintf(stderr, "\nTotal entries: %d", dwTotalEntries);
      //
      // Otherwise, just print the total.
      //
      printf("\nEntries enumerated: %d\n", dwTotalCount);
   }
   else
      fprintf(stderr, "A system error has occurred: %d\n", nStatus);
   //
   // Free the allocated memory.
   //
   if (pBuf != NULL)
      NetApiBufferFree(pBuf);

   return 0;
}
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
jstephe1Author Commented:
still comes back with user not found.  Could I use ADSI to do the same thing?

I tried to implement some ADSI code but I get an undeclared identifier for IADsUser when I try to use it.  How do I get started with ADSI?
0
 
migelCommented:
did you use UNICODE?
0
 
migelCommented:
did you use UNICODE?
0
 
jstephe1Author Commented:
I put the #ifndef UNICODE.. statements in.  The only difference in our code is that I had to cast the lpszUserName variable to a (LPCWSTR).  Could that be causing it not to be found?
0
 
JShaftCommented:
I've been trying this same code with the same problems. What I finally figured out is that casting lpszUserName is not enough. I put this code in there to perform the translation and it worked fine...
#include <windows.h>
#include <lm.h>
#include <stdio.h>
#pragma hdrstop

int main( void );

int main( void )
{
DWORD rc, pref, got, total;
GROUP_USERS_INFO_0 *buf;
TCHAR lpszUserName[250];
DWORD dwUserNameLength = 250;
wchar_t *user = new wchar_t[250];

GetUserName(lpszUserName, &dwUserNameLength);

for( int i=0;i<(int)dwUserNameLength;i++)
{
   user[i] = lpszUserName[i];
}

pref = 16;
buf = NULL;

do{
   pref *= 2;
   if( buf != NULL )
   {
      NetApiBufferFree(buf);
      buf = NULL;
   }
   rc = NetUserGetLocalGroups(NULL, user, 0, 0, (LPBYTE *) &buf, pref, &got, &total);
}while( rc == NERR_BufTooSmall || rc == ERROR_MORE_DATA );

if( rc != 0 )
{
   printf("Error %lu\n", rc);
   return 1;
}
for( rc=0;buf!=NULL && rc<got; rc++)
{
   printf("%S\n", buf[rc].grui0_name);
}

if( buf != NULL )
{
   NetApiBufferFree( buf );
}
}
0
 
migelCommented:
it is so strange
cite from MSDN:
"...Windows 2000 servers and workstations: If you call one of the affected functions on a Windows 2000 member server or workstation to perform a query, all authenticated users can view the information. Anonymous access is also possible if the RestrictAnonymous policy setting allows anonymous access. For updates, only Administrators and account operators can write information..."

hmm what about ADSI?
here is example how to achieve same for ADSI
HRESULT CheckUserGroups(IADsUser *pUser)
{
    IADsMembers *pGroups;
    HRESULT hr = S_OK;
    hr = pUser->Groups(&pGroups);
    pUser->Release();
    if (FAILED(hr)) return hr;

    IUnknown *pUnk;
    hr = pGroups->get__NewEnum(&pUnk);
    if (FAILED(hr)) return hr;
    pGroups->Release();

    IEnumVARIANT *pEnum;
    hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
    if (FAILED(hr)) return hr;

    pUnk->Release();

    // Now Enumerate
    BSTR bstr;
    VARIANT var;
    IADs *pADs;
    ULONG lFetch;
    IDispatch *pDisp;

    VariantInit(&var);
    hr = pEnum->Next(1, &var, &lFetch);
    while(hr == S_OK)
    {
        if (lFetch == 1)
        {
             pDisp = V_DISPATCH(&var);
             pDisp->QueryInterface(IID_IADs, (void**)&pADs);
             pADs->get_Name(&bstr);
             printf("Group belonged: %S\n",bstr);
             SysFreeString(bstr);
             pADs->Release();
        }
        VariantClear(&var);
        pDisp=NULL;
        hr = pEnum->Next(1, &var, &lFetch);
    };
    hr = pEnum->Release();
    return S_OK;
}

IADsUser *GetUserObject(LPWSTR uPath)
{
    IADsUser *pUser;
    HRESULT hr = ADsGetObject(uPath,IID_IADsUser,(void**)&pUser);
    if (FAILED(hr)) {return NULL;}
    BSTR bstr;
    hr = pUser->get_FullName(&bstr);
    printf("User: %S\n", bstr);
    SysFreeString(bstr);
    return pUser;
}

int main(int argc, char* argv[])
{
    HRESULT hr = CoInitialize(NULL);
    // form here your Account name (represented as *****)
    // in form: WinNT://Microsoft/*****,user
    IADsUser *pUser = GetUserObject(
                      L"WinNT://Microsoft/JSmith,user");
    pUser->AddRef();
    hr = CheckUserGroups(pUser);
    if(pUser) pUser->Release();
    CoUninitialize();
    return 0;
}
0
 
jstephe1Author Commented:
Thanks for all the help.  I used the ADSI version with some minor changes and it works.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now