Solved

NTDomain, Workgroup, Active Directory Domain

Posted on 2004-04-28
8
358 Views
Last Modified: 2007-12-19
Hello Experts,
I'm new in VC++.
I created an MFC application (in .Net 2002 unmanaged C++)
and want to detect if my computer where I'm logged in
is member of an NTDomain, of a Workgroup, an Active Directory Domain
or runs in isolated mode (is not connected to any network).
I'm looking for C++ snippets to get this information.
If anyone can help me, please supply an appropriate information.

Thank you for any help.

  HStrix
0
Comment
Question by:HStrix
  • 6
  • 2
8 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 200 total points
ID: 10941262
For the Active Directory part, see http://support.microsoft.com/default.aspx?scid=kb;en-us;233023 ("http://support.microsoft.com/default.aspx?scid=kb;en-us;233023") and http://support.microsoft.com/default.aspx?scid=kb;en-us;200126 ("HOWTO: Determining the Domain of A User Through ADSI") For the NT domain and workgoup part, you wil need to use 'LsaEnumerateTrustedDomains()'. Check out the sample at http://win32.mvps.org/lsa/lsa_letd.cpp
0
 

Author Comment

by:HStrix
ID: 10946817
Thank you jkr,
I started incorporating your suggestions with ADSI
(http://support.microsoft.com/default.aspx?scid=kb;en-us;200126).
My question is now:
what arguments are expected for argc and argv:
    extern "C" int wmain (int argc, wchar_t *argv[])
can you give me a sample?

  Thank you HStrix
0
 

Author Comment

by:HStrix
ID: 10951201
I modified the original line
   extern "C" int wmain (int argc, wchar_t *argv[])
to
   bool detectActiveDirectoryDomainName(int argc, wchar_t *argv[])
Now I need to invoke that routine,
the problem is, how to fill argv.
I need to have something like
  detectActiveDirectoryDomainName(1,"mycomputername");
But this doesn't work.
There is some casting required.
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!

 
LVL 86

Expert Comment

by:jkr
ID: 10951263
>>I need to have something like
>> detectActiveDirectoryDomainName(1,"mycomputername");

Make the sample read

   #define UNICODE
   #define _UNICODE
   #include <windows.h>
   #include <activeds.h>
   #include <atlbase.h>
   #include <stdio.h>
   #include <assert.h>
   #include <atlimpl.cpp>

   #define RTN_OK      0
   #define RTN_USAGE   1
   #define RTN_ERROR   13

   extern "C" int detectActiveDirectoryDomainName (wchar_t* pwszUser)
   {

       DWORD dwRes;
       CComPtr<IADsUser> pUser;
       CComPtr<IADs> pObject;
       CComBSTR strDomainPath, strUser, strDomain;
       CComBSTR strClass;
       HRESULT hr;

       // initialize COM
       //
       hr = CoInitialize (NULL);
       assert (SUCCEEDED(hr));

       // get the user object
       //
       hr = ADsGetObject (
                   pwszUser,
                   IID_IADsUser,
                   reinterpret_cast<void**>(&pUser)
                   );
       assert (SUCCEEDED(hr));

       // get the user name
       //
       hr = pUser->get_Name (&strUser);
       assert (SUCCEEDED(hr));

       // get the parent of the object
       //
       hr = pUser->get_Parent (&strDomainPath);
       assert (SUCCEEDED (hr));

       hr = ADsGetObject (
                   strDomainPath,
                   IID_IADs,
                   reinterpret_cast<void**>(&pObject)
                   );
       assert (SUCCEEDED(hr));

       // verify that it's a domain - this could have been done by
       // getting an IADsDomain interface in the ADsGetObject call...
       //
       hr = pObject->get_Class (&strClass);
       assert (SUCCEEDED(hr));

       assert (!wcscmp (TEXT("Domain"), strClass));

       // get the domain name
       //
       hr = pObject->get_Name (&strDomain);
       assert (SUCCEEDED(hr));

       printf ("Domain of user %S is %S\n", strUser, strDomain);

       return (RTN_OK);
   }


0
 

Author Comment

by:HStrix
ID: 10957656
OK jkr,
I think there was a slightly misunderstanding.
--
But using your sample (I incorporated it as a routine into an existing c file),
how do I need to call it?
I need something like
   CString strMyUserName = "myusername";
   detectActiveDirectoryDomainName ( (wchar_t*) strMyUserName); // <== this does not work. What to do?
I tried several more simular things,
but I couldn't get rid of the casting problem (as I mentioned in my yesterdays comment above).
--
Everything else seems working.

 Thank you for any hint

   HStrix




0
 

Author Comment

by:HStrix
ID: 10975819
In the meantime I could solve something.
-----------------------------------------------
 
I could make the calling working with the following code:
---
 CString MyComputername;
 CString MyUserID;
 //
 using namespace std;
 //
 string strInput;
 wchar_t *wcUserArg;
 
 // this works for a domain user on a domain controller (i.e.. on the local computer):
 strInput = "WinNT://" + (string) MyComputername +"/" + (string) MyUserID + ",user";  
 
 // this works for a workgroup user or a user that isn't connected  to the domain but to the local computer:
 strInput = "WinNT://" + (string) MyComputername +"/" + (string) MyUserID + ",user";  
 
 // this doesn't work for a domain user (i.e. connected to a domain):
 //strInput = "WinNT://" + (string) MyComputername +"/" + (string) MyUserID + ",user";  
 
 // this works for a domain user (i.e. connected to a domain)
 //      but -> I need to know the domain already and that was not my intension
 //strInput = "WinNT://" + (string) MyDomainname +"/" + (string) MyUserID + ",user";  
 
 wchar_t* pwsz = new wchar_t [ strInput.length() + 1];
 mbstowcs ( pwsz, strInput.c_str(), strInput.length() + 1);
 wcUserArg = pwsz;
 detectActiveDirectoryDomainName((wchar_t*) wcUserArg);
 delete [] pwsz;
---
 
in routine extern "C" int detectActiveDirectoryDomainName (wchar_t* pwszUser)
I needed to make the following changes:
---       ...
 
       // get the user object
       //
       hr = ADsGetObject (
                   pwszUser,           // WinNT://<computername>/<username> or WinNT://<domainname>/<username>
                   IID_IADsUser,
                   reinterpret_cast<void**>(&pUser)
                   );
       assert (SUCCEEDED(hr));
 
       // get the user name
       //
       hr = pUser->get_Name (&strUser);
       assert (SUCCEEDED(hr));
 
       // get the parent of the object
       //
       hr = pUser->get_Parent (&strDomainPath); // WinNT://<workgroupname>/<computername>
       assert (SUCCEEDED (hr));
 
       hr = ADsGetObject (
                   strDomainPath,
                   IID_IADs,
                   reinterpret_cast<void**>(&pObject)
                   );
       assert (SUCCEEDED(hr));
 
       // verify that it's a domain - this could have been done by
       // getting an IADsDomain interface in the ADsGetObject call...
       //
       hr = pObject->get_Class (&strClass);  // for Workgroups "Computer"
       assert (SUCCEEDED(hr));
 
 //   assert (!wcscmp ((CComBSTR)TEXT("Domain"), strClass)); // <== does NOT work for Workgroups(assert)

       // get the domain name
       //
       hr = pObject->get_Name (&strDomain);
       assert (SUCCEEDED(hr));
 
       if (wcscmp ((CComBSTR)TEXT("Domain"), strClass) == 0)
      {  
         infoGrouptype = "NT Domain";
         infoGroupname = (CString) strDomain;
      }else
      {  
         CString tmpDomain;
         tmpDomain = (CString) strDomainPath;  // current format is here: WinNT://<workgroup>/<computer>
         // <== here a substr is still required to select the workgroup only
         infoGrouptype = "Workgroup";
         infoGroupname = tmpDomain;
     }
---

I think now I need to incorporate the sample given in
---
   http://win32.mvps.org/lsa/lsa_letd.cpp
---
first.

   HStrix

0
 

Author Comment

by:HStrix
ID: 11116604
Hi jkr, in the meantime I made some improvements.
Now I found that there is a netapi function called netgetjoininformation,
but I couldn't make it working.
I'ld like to use this function to detect if my computer is running in a domain, workgroup or isolated.
Is there a working snippet for that function?
I couldn't detect what's wrong with my sample below?

  HStrix

I use the following code:
---
      PNETSETUP_JOIN_STATUS lngBufferType = 0;
      LPWSTR lpNameBuffer;
      NET_API_STATUS      nStatus = 0;
      LPCWSTR lpServerName;
      CString cstrServername = "\\\\" + CStringMyComputername;
      lpServerName = (LPCWSTR) cstrServername.AllocSysString();
      nStatus = NetGetJoinInformation(  lpServerName,
                                             (LPWSTR *) &lpNameBuffer,
                                                 lngBufferType);   // Returned BufferType
             // I get always:
      // nStatus==1780 ::= A null reference pointer was passed to the stub.
             // code 1780 => name  RPC_X_NULL_REF_POINTER
---
0
 

Author Comment

by:HStrix
ID: 11178996
That is a working sample for me:
--------------------------------------
DWORD getNetworkJoinInformation()
{            
      CString my_strDomainName = NULL;
      NET_API_STATUS      nStatusJ = 0;
      LPCWSTR lpszServer = NULL;
      LPWSTR  szDomain;
      LPWSTR* lpszDomain = &szDomain;
      NETSETUP_JOIN_STATUS njsBufferType;
      PNETSETUP_JOIN_STATUS pnjsBufferType = &njsBufferType;
      nStatusJ = NetGetJoinInformation(NULL,                         // Local machine (Server) or NULL (for local environment)
                                                                lpszDomain,        // Returned Domain nam
                                                                pnjsBufferType);          // Returned BufferType
//      NetApiBufferFree(lpszDomain);
// Here it is possible to detect Domain, Workstation, ...  checking njsBufferType.
// The name is contained in szDomain.
      return nStatusJ;
}
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

756 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