Solved

Getting group information for a user

Posted on 2002-07-29
10
434 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
  • 5
  • 4
10 Comments
 
LVL 12

Expert Comment

by:migel
Comment Utility
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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:jstephe1
Comment Utility
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
Comment Utility
did you use UNICODE?
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 12

Expert Comment

by:migel
Comment Utility
did you use UNICODE?
0
 

Author Comment

by:jstephe1
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Thanks for all the help.  I used the ADSI version with some minor changes and it works.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Host to IP 7 73
modThree challenge 4 64
haveThree challenge 22 100
Can not remove SSL certificate on iPhone 6 - iOS10.2 12 84
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

744 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now