Solved

Getting group information for a user

Posted on 2002-07-29
10
442 Views
Last Modified: 2013-11-20
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
Comment
Question by:jstephe1
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 12

Expert Comment

by:migel
ID: 7186005
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
 

Author Comment

by:jstephe1
ID: 7186226
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
 
LVL 12

Expert Comment

by:migel
ID: 7187249
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!

 

Author Comment

by:jstephe1
ID: 7188025
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
 
LVL 12

Expert Comment

by:migel
ID: 7188198
did you use UNICODE?
0
 
LVL 12

Expert Comment

by:migel
ID: 7188212
did you use UNICODE?
0
 

Author Comment

by:jstephe1
ID: 7188310
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
 

Expert Comment

by:JShaft
ID: 7188522
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
 
LVL 12

Accepted Solution

by:
migel earned 200 total points
ID: 7188733
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
 

Author Comment

by:jstephe1
ID: 7190797
Thanks for all the help.  I used the ADSI version with some minor changes and it works.
0

Featured Post

Industry Leaders: 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!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
has77  challenge 9 104
FizzBuzz challenge 9 87
matchUp  challenge 9 133
Problem to open Excel file 15 260
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question