Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Remote Registry Operations - Reading Mapped Drives on Remote Machine

Posted on 2004-04-23
5
Medium Priority
?
862 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
[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
  • 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 2000 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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering 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

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

730 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