Solved

Remote Registry Operations - Reading Mapped Drives on Remote Machine

Posted on 2004-04-23
5
855 Views
Last Modified: 2007-12-19
This is very similar to the question I posed yeaterday, but unlike yesterday's problem, this should be pretty easy.

To recap, I guess I cannot enumerate persistently mapped drives for a particular user using the registry (possibly through any means). In discussing this with a number of LAN Managers woh are trialing this, they have requested that I code it assuming the user whose data is to be backed up is logged on, i.e. I would be able to access their drives through HKCU.

To accomplish this, I pretty much ported over some code I have used numerous times for similar operations. For some reason that I cannot figure out, it doesn't work. I'll post the code below in a second, but to briefly explain it, following my call to RegConnectRegistry (which works) I place a call to RegOpenKeyEx, which returns a #2, and when I look that up it translates to ERROR_FILE_NOT_FOUND. The code may not look now look as it once did because I have been playing around with changing the parameters.

If anyone has any ideas, I would greatly appreciate them.

Thanks,
Jeff
*************************************************************
BOOL CFileBackupDlg::getMappings(CString strComputer)
{
      HKEY                        hKey;
      HKEY                        hSubKey;
      HKEY                        hTmpKey;
      FILE                        *fp;
      TCHAR                        szTemp[MAX_PATH];
      DWORD                        dwcSubKeys = 0;
      DWORD                        dwcValues = 0;
      DWORD                        dwcMaxSubKeyName = 0;
      DWORD                        dwcMaxValueName = 0;
      DWORD                        dwcMaxValueData = 0;
      DWORD                        dwSubKeyIndex = 0;            
      DWORD                        dwValueIndex = 0;
      DWORD                        dwBytes;
      DWORD                        dwType = 0;
      DWORD                        cchClassName = MAX_PATH;
      CString                        csBuf;
      char                        strMsg[MAX_PATH];
      char                        szBuffer[MAX_PATH];
      char                        lpArray[MAX_PATH];
      char                        lpszValueData[1024];
      char                        lpszSubKeyName[MAX_PATH];
      char                        lpName[MAX_PATH];
      char                        szLogFile[MAX_PATH];
      const unsigned int      BUF_SIZE = 1024;

      GetEnvironmentVariable ("TEMP", szTemp, sizeof (szTemp));
      lstrcpy (szLogFile, szTemp);
      lstrcat (szLogFile, "\\fileBackup.log");
      fp = fopen (szLogFile, "a+");
      fprintf (fp, "Mapped drives detected for: %s\n", strComputer);

      lstrcpy (lpName, "\\\\");
      lstrcat (lpName, strComputer);

      LONG lReturn = RegConnectRegistry (lpName, HKEY_CURRENT_USER, &hKey);
      if (lReturn != ERROR_SUCCESS)
      {
            CString            buf("Error reading drive mapping information on: ");
            buf += strComputer;
            MessageBox (buf, "Error Reading Drive Mapping Info", MB_OK | MB_ICONEXCLAMATION);
            fprintf (fp, "%s\n", buf);
            fclose (fp);
            return FALSE;
      }
      else
      {
            lReturn = RegOpenKeyEx (hKey,
                        "Network",
                        0,
                        KEY_QUERY_VALUE,
                        &hSubKey);
            if (lReturn == ERROR_SUCCESS)
            {
                  RegQueryInfoKey( hSubKey,
                              szBuffer,
                              &cchClassName,
                              NULL,
                              &dwcSubKeys,
                              &dwcMaxSubKeyName,
                              NULL,
                              &dwcValues,
                              &dwcMaxValueName,
                              &dwcMaxValueData,
                              NULL,
                              NULL );
                  if ( dwcValues != 0 || dwcSubKeys != 0 )
                  {
                        int nCount = 0;
                        do
                        {
                              DWORD dwcSubKeyName = dwcMaxSubKeyName + 1;

                              // Get data about the sub key.
                              lReturn = RegEnumKeyEx( hSubKey, dwSubKeyIndex, lpszSubKeyName,
                                   &dwcSubKeyName, NULL, NULL, NULL, NULL );
                              if ( lReturn == ERROR_SUCCESS )
                              {
                                    //create full subkey name to open
                                    lstrcpy (lpArray, "Network\\");
                                    lstrcat (lpArray, lpszSubKeyName);
                                    
                                    lReturn = RegOpenKeyEx(HKEY_CURRENT_USER,
                                                lpArray,
                                                0,
                                                KEY_ALL_ACCESS,
                                                &hTmpKey);

                                    if (lReturn == ERROR_SUCCESS)
                                    {
                                          dwBytes = BUF_SIZE;
                                          lReturn = RegQueryValueEx (hTmpKey,
                                                TEXT ("RemotePath"),
                                                NULL,
                                                &dwType,
                                                (unsigned char*)lpszValueData,
                                                &dwBytes);
                                          if ( lReturn == ERROR_SUCCESS )
                                          {
                                                fprintf (fp, "%\tDrive map letter: %s\n", lpszSubKeyName);
                                                fprintf (fp, "%\tDrive map path: %s\n", lpszValueData);
                                                wsprintf (strMsg, "Drive detected...drive letter = %s ", lpszSubKeyName);
                                                lstrcat (strMsg, "\n");
                                                wsprintf (strMsg, "Drive detected...drive path = %s ", lpszValueData);

                                          }
                                    }
                                    SetDlgItemText (IDC_STATUS, strMsg);
                                    RegCloseKey (hTmpKey);
                              }
                              dwSubKeyIndex++;
                              nCount++;
                        }while ( lReturn == ERROR_SUCCESS );
                  }
                  RegCloseKey (hSubKey);
            }
            else
                  return FALSE;
      }
      RegCloseKey (hKey);
      fclose (fp);
      return TRUE;
0
Comment
Question by:jpetter
  • 4
5 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 10902978
The problem is that you are trying to remotely connect to HKEY_CURRENT_USER - the docs explicitly state that

-------------------------------------------->8------------------------------

hKey
Specifies the one of the following predefined registry handles on the remote computer.
HKEY_LOCAL_MACHINE
HKEY_USERS
Windows NT: HKEY_PERFORMANCE_DATA, if the remote computer is running Windows NT
Windows 95 and Windows 98: HKEY_DYN_DATA, if the remote computer is running Windows 95 or Windows 98
Windows 95 and Windows 98: HKEY_CURRENT_CONFIG, if the remote computer is running Windows 95 or Windows 98

You cannot specify the HKEY_CLASSES_ROOT or HKEY_CURRENT_USER value for this parameter.

-------------------------------------------->8------------------------------


You need to connect to 'HKEY_USERS' and read the information from there.

0
 
LVL 86

Expert Comment

by:jkr
ID: 10903003
BTW, there might be more than one user logged on to a machine - check the source code at http://www.sysinternals.com/files/PsLoggedonSrc.zip on how to enumerate through the HKEY_USERS entries.
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 10903082
BTW, here's the relevant code from the samle (UNICODE):

    //
    // Use RegConnectRegistry so that we work with remote computers
    //
      if( ServerName ) {
            
            wprintf(L"Connecting to Registry of %s...", ServerName );
            fflush( stdout );

            if( RegConnectRegistry( ServerName, HKEY_USERS, &usersKey ) != ERROR_SUCCESS) {
       
                  wprintf(L"\r                                                      \r");
                  wprintf( L"Error opening HKEY_USERS for %s\n", ServerName );
                  return;
            }
            wprintf(L"\r                                                      \r");

      } else {

            if( RegOpenKey( HKEY_USERS, NULL, &usersKey ) != ERROR_SUCCESS ) {

                  wprintf( errorMessage, L"Error opening HKEY_USERS" );
                  PrintWin32Error( errorMessage, GetLastError() );
                  return;
            }
      }
   
    //
    // Enumerate keys under HKEY_USERS
    //
    index = 0;
    subKeyNameSize = sizeof( subKeyName );
    while( RegEnumKeyEx( usersKey, index, subKeyName, &subKeyNameSize,
                         NULL, NULL, NULL, &lastWriteTime ) == ERROR_SUCCESS ) {

        //
        // Ignore the default subkey and win2K user class subkeys
        //
        if( wcsicmp( subKeyName, L".default" ) &&
                  !wcsstr( subKeyName, L"Classes")) {

             wchar_t networkName [ MAX_PATH];

             wsprintf ( networkName,L"%s\\Network", subKeyName);

         lReturn = RegOpenKeyEx (usersKey,
                    networkName,
                    0,
                    KEY_QUERY_VALUE,
                    &hSubKey);

         if (lReturn == ERROR_SUCCESS) {

                  // gather information

             }

            }

        index++;
    }
0
 

Author Comment

by:jpetter
ID: 10903092
I was wondering if that may be a problem, because if I manually (through regedt32) access a registry remotely those keys are not available. However, as per the February 2003 Platform SDK, when using RegConnectRegistry the hKey can be either a predefined registry handle or HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_PERFORMANCE_DATA
HKEY_USERS

I believe you, but cannot confirm it with the documentation I have. Thanks (again)
0
 
LVL 86

Expert Comment

by:jkr
ID: 10903152
HKEY_CURRENT_USER does not make sense for a remote connection - think of it, this key is only a sybolic link to one of the entries under HKEY_USERS. From 'Inside Windows 2000":

HKEY_CURRENT_USER
The HKCU root key contains data regarding the preferences and software configuration of the locally logged-on user. It points to the currently logged-on user's user profile, located on the hard disk at \Documents and Settings\<username>\Ntuser.dat. (See the section "Registry Internals" later in this chapter to find out how root keys are mapped to files on the hard disk.) Whenever a user profile is loaded (such as at logon time or when a service process runs under the context of a specific username), HKCU is created as a link to the user's key under HKEY_USERS
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

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

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
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 be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

776 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