Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

357 lines
12 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998-1999.
//
// File: DrvNotifArray.cxx
//
// Contents: This file contains the class, CDrvNotifArray.
//
// History: 15-Jul-98 KitmanH Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <ciregkey.hxx>
#include <notifary.hxx>
#include <catalog.hxx>
#include <cimbmgr.hxx>
#include <regscp.hxx>
#include <regacc.hxx>
#include "scpfixup.hxx"
#include <catreg.hxx>
//+---------------------------------------------------------------------------
//
// Member: CDrvNotifArray::RegisterCatForNotifInRegistry, public
//
// Synopsis: Register all the catalogs for device notifications
//
// History: 7-15-98 KitmanH Created
// 8-14-98 KitmanH Register for notifications for drives
// on which an indexed scope exists too
//
//----------------------------------------------------------------------------
void CDrvNotifArray::RegisterCatForNotifInRegistry()
{
HKEY hKey;
if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
wcsRegCatalogsSubKey,
0,
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS,
&hKey ) )
{
SRegKey xKey( hKey );
DWORD iSubKey = 0;
do
{
FILETIME ft;
WCHAR awcName[MAX_PATH];
DWORD cwcName = sizeof awcName / sizeof WCHAR;
LONG err = RegEnumKeyEx( hKey,
iSubKey,
awcName,
&cwcName,
0, 0, 0, &ft );
// either error or end of enumeration
if ( ERROR_SUCCESS != err )
break;
iSubKey++;
HKEY hCatName;
if ( ERROR_SUCCESS == RegOpenKeyEx( hKey,
awcName,
0,
KEY_QUERY_VALUE,
&hCatName ) )
{
SRegKey xCatNameKey( hCatName );
// Check if the catalog is inactive and can be ignored
WCHAR awcKey[MAX_PATH];
wcscpy( awcKey, wcsRegJustCatalogsSubKey );
wcscat( awcKey, L"\\" );
wcscat( awcKey, awcName );
CRegAccess reg( RTL_REGISTRY_CONTROL, awcKey );
BOOL fInactive = reg.Read( wcsCatalogInactive,
CI_CATALOG_INACTIVE_DEFAULT );
if ( !fInactive )
{
WCHAR awcPath[MAX_PATH];
DWORD cbPath = sizeof awcPath;
if ( ERROR_SUCCESS == RegQueryValueEx( hCatName,
wcsCatalogLocation,
0,
0,
(BYTE *)awcPath,
&cbPath ) )
{
AddDriveNotification( awcPath[0] );
unsigned cwcNeeded = wcslen( wcsRegJustCatalogsSubKey );
cwcNeeded += 3; // "\\" x 2 + null termination
cwcNeeded += wcslen( awcName );
cwcNeeded += wcslen( wcsCatalogScopes );
XArray<WCHAR> xKey( cwcNeeded );
wcscpy( xKey.Get(), wcsRegJustCatalogsSubKey );
wcscat( xKey.Get(), L"\\" );
wcscat( xKey.Get(), awcName );
wcscat( xKey.Get(), L"\\" );
wcscat( xKey.Get(), wcsCatalogScopes );
CRegAccess regScopes( RTL_REGISTRY_CONTROL, xKey.Get() );
CRegistryScopesCallBackAddDrvNotif callback( this );
regScopes.EnumerateValues( 0, callback );
}
}
}
} while ( TRUE );
}
} //RegisterCatForNotifInRegistry
//+-------------------------------------------------------------------------
//
// Member: UnregisterDeviceNotifications, public
//
// Synopsis: Unregister all the device notifications
//
// History: 07-07-98 kitmanh Created.
//
//--------------------------------------------------------------------------
void CDrvNotifArray::UnregisterDeviceNotifications()
{
ciDebugOut(( DEB_ITRACE, "Unregister Device Notificaiton On Shutdown\n" ));
CReleasableLock lock( _mutex );
for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
{
CDrvNotificationInfo * pDrvNot = _aDriveNotification.Get(i);
delete pDrvNot;
}
_aDriveNotification.Clear();
// If the async thread is around, get rid of it
if ( !_xWorker.IsNull() )
{
_fAbort = TRUE;
ciDebugOut(( DEB_ITRACE, "waking up async register for shutdown\n" ));
_evtWorker.Set();
lock.Release();
ciDebugOut(( DEB_ITRACE, "waiting for async register death\n" ));
_xWorker->WaitForDeath();
_xWorker.Free();
_fAbort = FALSE;
}
} //UnregisterDeviceNotifications
//+-------------------------------------------------------------------------
//
// Member: AddDriveNotification, public
//
// Synopsis: Register the volume for device notification. Add an entry in
// the array _aDriveNotification for record
//
// Arguments: [wcDriveLetter] -- DriveLetter of the volume where the
// catalog resides
//
// History: 18-May-98 KitmanH Created
//
//--------------------------------------------------------------------------
void CDrvNotifArray::AddDriveNotification( WCHAR wcDriveLetter, BOOL fNotInRegistry )
{
// first, look up the table to see if the volume is alreay in the table
if ( FindDriveNotification( wcDriveLetter ) )
{
ciDebugOut(( DEB_ITRACE, "Volume %wc is already in the DriveNotification array\n",
wcDriveLetter ));
return;
}
// if not in the table, check the volume and add an entry of DriveNotificationInfo
ciDebugOut(( DEB_ITRACE, "CDrvNotifArray::AddDriveNotification: Adding volume %wc to the DriveNot Array\n",
wcDriveLetter ));
XPtr <CDrvNotificationInfo> xDrvNotif(new CDrvNotificationInfo( wcDriveLetter,
fNotInRegistry ));
{
CLock lockx( _mutex );
if ( xDrvNotif->RegisterNotification() )
{
_aDriveNotification.Add( xDrvNotif.GetPointer(),
_aDriveNotification.Count() );
xDrvNotif->CloseVolumeHandle();
xDrvNotif.Acquire();
ciDebugOut(( DEB_ITRACE, "AddDriveNotification succeeded for DRIVE %wc\n",
wcDriveLetter ));
}
}
} //AddDriveNotification
//+-------------------------------------------------------------------------
//
// Function: FindDriveNotificationByHandle, public
//
// Synopsis: return the device notification for a particular volume (
// matching the handle).
//
// Arguments: [hNotify] -- handle for volume when a custom device
// notification occurs
//
// History: 22-Jun-98 KitmanH Created
//
//--------------------------------------------------------------------------
CDrvNotificationInfo * CDrvNotifArray::FindDriveNotificationByHandle( HDEVNOTIFY hNotify )
{
CLock lockx( _mutex );
for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
{
CDrvNotificationInfo * pDrvNot = _aDriveNotification.Get(i);
if ( pDrvNot->GethNotify() == hNotify )
return pDrvNot;
}
ciDebugOut(( DEB_ITRACE, "Can't find drive notification in array\n" ));
return 0;
} //FindDriveNotificationByHandle
//+-------------------------------------------------------------------------
//
// Function: FindDriveNotification, public
//
// Synopsis: return the device notification for a particular volume (
// matching the handle).
//
// Arguments: [wcDrvLetter] -- Drive Letter for a volume
//
// History: 01-July-98 KitmanH Created
//
//--------------------------------------------------------------------------
CDrvNotificationInfo * CDrvNotifArray::FindDriveNotification( WCHAR wcDrvLetter )
{
CLock lockx( _mutex );
for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
{
CDrvNotificationInfo * pDrvNot = _aDriveNotification.Get(i);
if ( toupper(pDrvNot->GetDrvLetter()) == toupper(wcDrvLetter) )
return pDrvNot;
}
ciDebugOut(( DEB_ITRACE, "Can't find drive notification in array\n" ));
return 0;
} //FindDriveNotification
//+-------------------------------------------------------------------------
//
// Function: CDrvNotifArray::RegisterRemovableDrives, public
//
// Synopsis: Registers all removable drives for notification (except a:
// and b:).
//
// History: 26-March-99 dlee Created
//
//--------------------------------------------------------------------------
void CDrvNotifArray::RegisterRemovableDrives()
{
// Determine which drives exist in this bitmask
DWORD dwDriveMask = GetLogicalDrives();
dwDriveMask >>= 2;
// loop through all the drives c-z
for ( WCHAR wc = L'C'; wc <= L'Z'; wc++ )
{
DWORD dwTemp = ( dwDriveMask & 1 );
dwDriveMask >>= 1;
if ( 0 != dwTemp )
{
if ( IsRemovableDrive( wc ) )
AddDriveNotification( wc, TRUE );
}
}
} //RegisterRemovableDrives
//+-------------------------------------------------------------------------
//
// Function: CDrvNotifArray::RegisterThread, private
//
// Synopsis: The worker thread function.
//
// History: 12-April-99 dlee Created
//
//--------------------------------------------------------------------------
DWORD WINAPI CDrvNotifArray::RegisterThread( void * self )
{
return ( (CDrvNotifArray *) self)->DoRegisterWork();
} //RegisterThread
//+-------------------------------------------------------------------------
//
// Function: CDrvNotifArray::RegisterThread, private
//
// Synopsis: Waits around to be told to register for device notificaitons
// on volumes not currently registered.
//
// History: 12-April-99 dlee Created
//
//--------------------------------------------------------------------------
DWORD CDrvNotifArray::DoRegisterWork()
{
do
{
_evtWorker.Wait();
CLock lock( _mutex );
ciDebugOut(( DEB_ITRACE, "async register woke up, _fAbort: %d\n", _fAbort ));
if ( _fAbort )
break;
for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
{
CDrvNotificationInfo & DrvNot = * _aDriveNotification.Get(i);
if ( !DrvNot.IsRegistered() )
DrvNot.RegisterNotification();
}
_evtWorker.Reset();
} while (TRUE);
return 0;
} //DoRegisterWork