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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998-1999.
  5. //
  6. // File: DrvNotifArray.cxx
  7. //
  8. // Contents: This file contains the class, CDrvNotifArray.
  9. //
  10. // History: 15-Jul-98 KitmanH Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <ciregkey.hxx>
  16. #include <notifary.hxx>
  17. #include <catalog.hxx>
  18. #include <cimbmgr.hxx>
  19. #include <regscp.hxx>
  20. #include <regacc.hxx>
  21. #include "scpfixup.hxx"
  22. #include <catreg.hxx>
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Member: CDrvNotifArray::RegisterCatForNotifInRegistry, public
  26. //
  27. // Synopsis: Register all the catalogs for device notifications
  28. //
  29. // History: 7-15-98 KitmanH Created
  30. // 8-14-98 KitmanH Register for notifications for drives
  31. // on which an indexed scope exists too
  32. //
  33. //----------------------------------------------------------------------------
  34. void CDrvNotifArray::RegisterCatForNotifInRegistry()
  35. {
  36. HKEY hKey;
  37. if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  38. wcsRegCatalogsSubKey,
  39. 0,
  40. KEY_QUERY_VALUE |
  41. KEY_ENUMERATE_SUB_KEYS,
  42. &hKey ) )
  43. {
  44. SRegKey xKey( hKey );
  45. DWORD iSubKey = 0;
  46. do
  47. {
  48. FILETIME ft;
  49. WCHAR awcName[MAX_PATH];
  50. DWORD cwcName = sizeof awcName / sizeof WCHAR;
  51. LONG err = RegEnumKeyEx( hKey,
  52. iSubKey,
  53. awcName,
  54. &cwcName,
  55. 0, 0, 0, &ft );
  56. // either error or end of enumeration
  57. if ( ERROR_SUCCESS != err )
  58. break;
  59. iSubKey++;
  60. HKEY hCatName;
  61. if ( ERROR_SUCCESS == RegOpenKeyEx( hKey,
  62. awcName,
  63. 0,
  64. KEY_QUERY_VALUE,
  65. &hCatName ) )
  66. {
  67. SRegKey xCatNameKey( hCatName );
  68. // Check if the catalog is inactive and can be ignored
  69. WCHAR awcKey[MAX_PATH];
  70. wcscpy( awcKey, wcsRegJustCatalogsSubKey );
  71. wcscat( awcKey, L"\\" );
  72. wcscat( awcKey, awcName );
  73. CRegAccess reg( RTL_REGISTRY_CONTROL, awcKey );
  74. BOOL fInactive = reg.Read( wcsCatalogInactive,
  75. CI_CATALOG_INACTIVE_DEFAULT );
  76. if ( !fInactive )
  77. {
  78. WCHAR awcPath[MAX_PATH];
  79. DWORD cbPath = sizeof awcPath;
  80. if ( ERROR_SUCCESS == RegQueryValueEx( hCatName,
  81. wcsCatalogLocation,
  82. 0,
  83. 0,
  84. (BYTE *)awcPath,
  85. &cbPath ) )
  86. {
  87. AddDriveNotification( awcPath[0] );
  88. unsigned cwcNeeded = wcslen( wcsRegJustCatalogsSubKey );
  89. cwcNeeded += 3; // "\\" x 2 + null termination
  90. cwcNeeded += wcslen( awcName );
  91. cwcNeeded += wcslen( wcsCatalogScopes );
  92. XArray<WCHAR> xKey( cwcNeeded );
  93. wcscpy( xKey.Get(), wcsRegJustCatalogsSubKey );
  94. wcscat( xKey.Get(), L"\\" );
  95. wcscat( xKey.Get(), awcName );
  96. wcscat( xKey.Get(), L"\\" );
  97. wcscat( xKey.Get(), wcsCatalogScopes );
  98. CRegAccess regScopes( RTL_REGISTRY_CONTROL, xKey.Get() );
  99. CRegistryScopesCallBackAddDrvNotif callback( this );
  100. regScopes.EnumerateValues( 0, callback );
  101. }
  102. }
  103. }
  104. } while ( TRUE );
  105. }
  106. } //RegisterCatForNotifInRegistry
  107. //+-------------------------------------------------------------------------
  108. //
  109. // Member: UnregisterDeviceNotifications, public
  110. //
  111. // Synopsis: Unregister all the device notifications
  112. //
  113. // History: 07-07-98 kitmanh Created.
  114. //
  115. //--------------------------------------------------------------------------
  116. void CDrvNotifArray::UnregisterDeviceNotifications()
  117. {
  118. ciDebugOut(( DEB_ITRACE, "Unregister Device Notificaiton On Shutdown\n" ));
  119. CReleasableLock lock( _mutex );
  120. for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
  121. {
  122. CDrvNotificationInfo * pDrvNot = _aDriveNotification.Get(i);
  123. delete pDrvNot;
  124. }
  125. _aDriveNotification.Clear();
  126. // If the async thread is around, get rid of it
  127. if ( !_xWorker.IsNull() )
  128. {
  129. _fAbort = TRUE;
  130. ciDebugOut(( DEB_ITRACE, "waking up async register for shutdown\n" ));
  131. _evtWorker.Set();
  132. lock.Release();
  133. ciDebugOut(( DEB_ITRACE, "waiting for async register death\n" ));
  134. _xWorker->WaitForDeath();
  135. _xWorker.Free();
  136. _fAbort = FALSE;
  137. }
  138. } //UnregisterDeviceNotifications
  139. //+-------------------------------------------------------------------------
  140. //
  141. // Member: AddDriveNotification, public
  142. //
  143. // Synopsis: Register the volume for device notification. Add an entry in
  144. // the array _aDriveNotification for record
  145. //
  146. // Arguments: [wcDriveLetter] -- DriveLetter of the volume where the
  147. // catalog resides
  148. //
  149. // History: 18-May-98 KitmanH Created
  150. //
  151. //--------------------------------------------------------------------------
  152. void CDrvNotifArray::AddDriveNotification( WCHAR wcDriveLetter, BOOL fNotInRegistry )
  153. {
  154. // first, look up the table to see if the volume is alreay in the table
  155. if ( FindDriveNotification( wcDriveLetter ) )
  156. {
  157. ciDebugOut(( DEB_ITRACE, "Volume %wc is already in the DriveNotification array\n",
  158. wcDriveLetter ));
  159. return;
  160. }
  161. // if not in the table, check the volume and add an entry of DriveNotificationInfo
  162. ciDebugOut(( DEB_ITRACE, "CDrvNotifArray::AddDriveNotification: Adding volume %wc to the DriveNot Array\n",
  163. wcDriveLetter ));
  164. XPtr <CDrvNotificationInfo> xDrvNotif(new CDrvNotificationInfo( wcDriveLetter,
  165. fNotInRegistry ));
  166. {
  167. CLock lockx( _mutex );
  168. if ( xDrvNotif->RegisterNotification() )
  169. {
  170. _aDriveNotification.Add( xDrvNotif.GetPointer(),
  171. _aDriveNotification.Count() );
  172. xDrvNotif->CloseVolumeHandle();
  173. xDrvNotif.Acquire();
  174. ciDebugOut(( DEB_ITRACE, "AddDriveNotification succeeded for DRIVE %wc\n",
  175. wcDriveLetter ));
  176. }
  177. }
  178. } //AddDriveNotification
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Function: FindDriveNotificationByHandle, public
  182. //
  183. // Synopsis: return the device notification for a particular volume (
  184. // matching the handle).
  185. //
  186. // Arguments: [hNotify] -- handle for volume when a custom device
  187. // notification occurs
  188. //
  189. // History: 22-Jun-98 KitmanH Created
  190. //
  191. //--------------------------------------------------------------------------
  192. CDrvNotificationInfo * CDrvNotifArray::FindDriveNotificationByHandle( HDEVNOTIFY hNotify )
  193. {
  194. CLock lockx( _mutex );
  195. for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
  196. {
  197. CDrvNotificationInfo * pDrvNot = _aDriveNotification.Get(i);
  198. if ( pDrvNot->GethNotify() == hNotify )
  199. return pDrvNot;
  200. }
  201. ciDebugOut(( DEB_ITRACE, "Can't find drive notification in array\n" ));
  202. return 0;
  203. } //FindDriveNotificationByHandle
  204. //+-------------------------------------------------------------------------
  205. //
  206. // Function: FindDriveNotification, public
  207. //
  208. // Synopsis: return the device notification for a particular volume (
  209. // matching the handle).
  210. //
  211. // Arguments: [wcDrvLetter] -- Drive Letter for a volume
  212. //
  213. // History: 01-July-98 KitmanH Created
  214. //
  215. //--------------------------------------------------------------------------
  216. CDrvNotificationInfo * CDrvNotifArray::FindDriveNotification( WCHAR wcDrvLetter )
  217. {
  218. CLock lockx( _mutex );
  219. for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
  220. {
  221. CDrvNotificationInfo * pDrvNot = _aDriveNotification.Get(i);
  222. if ( toupper(pDrvNot->GetDrvLetter()) == toupper(wcDrvLetter) )
  223. return pDrvNot;
  224. }
  225. ciDebugOut(( DEB_ITRACE, "Can't find drive notification in array\n" ));
  226. return 0;
  227. } //FindDriveNotification
  228. //+-------------------------------------------------------------------------
  229. //
  230. // Function: CDrvNotifArray::RegisterRemovableDrives, public
  231. //
  232. // Synopsis: Registers all removable drives for notification (except a:
  233. // and b:).
  234. //
  235. // History: 26-March-99 dlee Created
  236. //
  237. //--------------------------------------------------------------------------
  238. void CDrvNotifArray::RegisterRemovableDrives()
  239. {
  240. // Determine which drives exist in this bitmask
  241. DWORD dwDriveMask = GetLogicalDrives();
  242. dwDriveMask >>= 2;
  243. // loop through all the drives c-z
  244. for ( WCHAR wc = L'C'; wc <= L'Z'; wc++ )
  245. {
  246. DWORD dwTemp = ( dwDriveMask & 1 );
  247. dwDriveMask >>= 1;
  248. if ( 0 != dwTemp )
  249. {
  250. if ( IsRemovableDrive( wc ) )
  251. AddDriveNotification( wc, TRUE );
  252. }
  253. }
  254. } //RegisterRemovableDrives
  255. //+-------------------------------------------------------------------------
  256. //
  257. // Function: CDrvNotifArray::RegisterThread, private
  258. //
  259. // Synopsis: The worker thread function.
  260. //
  261. // History: 12-April-99 dlee Created
  262. //
  263. //--------------------------------------------------------------------------
  264. DWORD WINAPI CDrvNotifArray::RegisterThread( void * self )
  265. {
  266. return ( (CDrvNotifArray *) self)->DoRegisterWork();
  267. } //RegisterThread
  268. //+-------------------------------------------------------------------------
  269. //
  270. // Function: CDrvNotifArray::RegisterThread, private
  271. //
  272. // Synopsis: Waits around to be told to register for device notificaitons
  273. // on volumes not currently registered.
  274. //
  275. // History: 12-April-99 dlee Created
  276. //
  277. //--------------------------------------------------------------------------
  278. DWORD CDrvNotifArray::DoRegisterWork()
  279. {
  280. do
  281. {
  282. _evtWorker.Wait();
  283. CLock lock( _mutex );
  284. ciDebugOut(( DEB_ITRACE, "async register woke up, _fAbort: %d\n", _fAbort ));
  285. if ( _fAbort )
  286. break;
  287. for ( unsigned i = 0; i < _aDriveNotification.Count(); i++ )
  288. {
  289. CDrvNotificationInfo & DrvNot = * _aDriveNotification.Get(i);
  290. if ( !DrvNot.IsRegistered() )
  291. DrvNot.RegisterNotification();
  292. }
  293. _evtWorker.Reset();
  294. } while (TRUE);
  295. return 0;
  296. } //DoRegisterWork