//+------------------------------------------------------------------------- // // 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 #pragma hdrstop #include #include #include #include #include #include #include "scpfixup.hxx" #include //+--------------------------------------------------------------------------- // // 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 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 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