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.

268 lines
7.8 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998 - 2000.
  5. //
  6. // File: DrvNotif.cxx
  7. //
  8. // Contents: This class keeps the information of a volume that's
  9. // registered for device notification.
  10. //
  11. // History: 23-Jun-98 KitmanH Created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <pch.cxx>
  15. #pragma hdrstop
  16. #include <drvnotif.hxx>
  17. #include <dbt.h>
  18. extern SERVICE_STATUS_HANDLE g_hTheCiSvc;
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: CDrvNotificationInfo::CDrvNotificationInfo, public
  22. //
  23. // Synopsis: Creates a new instance of CDrvNotificationInfo
  24. //
  25. // Arguments: [wcDriveLetter] - the drive letter of the volume
  26. //
  27. // History: 6-24-98 KitmanH Created
  28. //
  29. //----------------------------------------------------------------------------
  30. CDrvNotificationInfo::CDrvNotificationInfo(
  31. WCHAR wcDriveLetter,
  32. BOOL fAutoMountMode )
  33. : _hVol(INVALID_HANDLE_VALUE),
  34. _wcDriveLetter( wcDriveLetter ),
  35. _hNotify(INVALID_HANDLE_VALUE),
  36. _dwVolState(eVolReady),
  37. _cLockAttempts(0),
  38. _fAutoMountMode( fAutoMountMode )
  39. {
  40. WCHAR awc[4];
  41. wcscpy( awc, L"C:\\" );
  42. awc[0] = wcDriveLetter;
  43. _uiDriveType = GetDriveType( awc );
  44. } //CDrvNotificationInfo
  45. //+---------------------------------------------------------------------------
  46. //
  47. // Member: CDrvNotificationInfo::~CDrvNotificationInfo, public
  48. //
  49. // Synopsis: Destrucstor for CDrvNotificationInfo
  50. //
  51. // History: 6-24-98 KitmanH Created
  52. //
  53. //----------------------------------------------------------------------------
  54. CDrvNotificationInfo::~CDrvNotificationInfo()
  55. {
  56. UnregisterNotification();
  57. CloseVolumeHandle();
  58. } //~CDrvNotificationInfo
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Member: CDrvNotificationInfo::GetVolumeHandle, private
  62. //
  63. // Synopsis: Gets the volume handle and checks if the volume is read-only
  64. //
  65. // Returns: TRUE if succeeded, FALSE otherwise
  66. //
  67. // History: 6-24-98 KitmanH Created
  68. //
  69. //----------------------------------------------------------------------------
  70. BOOL CDrvNotificationInfo::GetVolumeHandle( )
  71. {
  72. Win4Assert( INVALID_HANDLE_VALUE == _hVol );
  73. CloseVolumeHandle();
  74. ciDebugOut(( DEB_ITRACE, "GetVolumeHandle for %wc\n", _wcDriveLetter ));
  75. WCHAR wcsVolumePath[] = L"\\\\.\\a:";
  76. wcsVolumePath[4] = _wcDriveLetter;
  77. _hVol = CreateFile( wcsVolumePath,
  78. GENERIC_READ,
  79. FILE_SHARE_READ | FILE_SHARE_WRITE,
  80. NULL,
  81. OPEN_EXISTING,
  82. 0,
  83. NULL );
  84. if ( INVALID_HANDLE_VALUE == _hVol )
  85. {
  86. ciDebugOut(( DEB_IWARN, "CDrvNotificationInfo::GetVolumeHanlde: LastError is %d\n", GetLastError() ));
  87. return FALSE;
  88. }
  89. ciDebugOut(( DEB_ITRACE, "GetVolumeHanlde succeeded!!\n" ));
  90. return TRUE;
  91. } //GetVolumeHandle
  92. //+---------------------------------------------------------------------------
  93. //
  94. // Member: CDrvNotificationInfo::RegisterNotification, public
  95. //
  96. // Synopsis: register the volume for device notification
  97. //
  98. // Returns: TRUE if the registration is successful, FALSE otherwise
  99. //
  100. // History: 6-24-98 KitmanH Created
  101. //
  102. //----------------------------------------------------------------------------
  103. BOOL CDrvNotificationInfo::RegisterNotification()
  104. {
  105. UnregisterNotification();
  106. if ( !GetVolumeHandle() )
  107. return FALSE;
  108. Win4Assert( 0 != g_hTheCiSvc );
  109. Win4Assert( INVALID_HANDLE_VALUE != _hVol );
  110. DEV_BROADCAST_HANDLE DbtHandle;
  111. ZeroMemory( &DbtHandle, sizeof(DEV_BROADCAST_HANDLE) );
  112. DbtHandle.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
  113. DbtHandle.dbch_devicetype = DBT_DEVTYP_HANDLE;
  114. DbtHandle.dbch_handle = _hVol;
  115. ciDebugOut(( DEB_ITRACE, "About to RegisterDeviceNotification...\n" ));
  116. _hNotify = RegisterDeviceNotification( (HANDLE) g_hTheCiSvc,
  117. &DbtHandle,
  118. DEVICE_NOTIFY_SERVICE_HANDLE );
  119. //check if the registration succeeded
  120. if ( 0 == _hNotify )
  121. {
  122. ciDebugOut(( DEB_IWARN, "RegisterNotification on '%wc' failed: LastError is %d\n",
  123. _wcDriveLetter, GetLastError() ));
  124. CloseVolumeHandle();
  125. return FALSE;
  126. }
  127. ciDebugOut(( DEB_ITRACE, "RegisterNotification for drive %wc succeeded, handle %#x!\n",
  128. _wcDriveLetter, _hNotify ));
  129. CloseVolumeHandle();
  130. return TRUE;
  131. } //RegisterNotification
  132. //+---------------------------------------------------------------------------
  133. //
  134. // Member: CDrvNotificationInfo::UnRegisterNotification, public
  135. //
  136. // Synopsis: unregister the volume for device notification
  137. //
  138. // History: 6-30-98 KitmanH Created
  139. //
  140. //----------------------------------------------------------------------------
  141. void CDrvNotificationInfo::UnregisterNotification()
  142. {
  143. if ( INVALID_HANDLE_VALUE != _hNotify )
  144. {
  145. BOOL fOK = UnregisterDeviceNotification( _hNotify );
  146. ciDebugOut(( DEB_ITRACE, "UnregisterDeviceNotification for %wc handle %#x result %d\n",
  147. _wcDriveLetter, _hNotify, fOK ));
  148. _hNotify = INVALID_HANDLE_VALUE;
  149. }
  150. } //UnregisterNotification
  151. //+---------------------------------------------------------------------------
  152. //
  153. // Member: CDrvNotificationInfo::ReallyTouch, public
  154. //
  155. // Synopsis: Touch the volume, in an attempt to force it to mount
  156. //
  157. // Returns: TRUE if the volume appears healthy, FALSE otherwise
  158. //
  159. // History: March-9-00 dlee Created
  160. //
  161. //----------------------------------------------------------------------------
  162. BOOL CDrvNotificationInfo::ReallyTouch()
  163. {
  164. WCHAR awc[4];
  165. wcscpy( awc, L"C:\\" );
  166. awc[0] = _wcDriveLetter;
  167. WIN32_FILE_ATTRIBUTE_DATA fData;
  168. return GetFileAttributesEx( awc, GetFileExInfoStandard, &fData );
  169. } //ReallyTouch
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Member: CDrvNotificationInfo::Touch, public
  173. //
  174. // Synopsis: Touch the volume, in an attempt to force it to mount
  175. //
  176. // Returns: TRUE if the volume appears healthy, FALSE otherwise
  177. //
  178. // History: April-8-99 dlee Created
  179. //
  180. //----------------------------------------------------------------------------
  181. BOOL CDrvNotificationInfo::Touch()
  182. {
  183. //
  184. // The CreateFile or DeviceIoControl causes an infinite mount loop
  185. // on CD ROM devices.
  186. //
  187. if ( IsCDROM() )
  188. return ReallyTouch();
  189. BOOL fOk = FALSE;
  190. WCHAR wszVolumePath[] = L"\\\\.\\a:";
  191. wszVolumePath[4] = _wcDriveLetter;
  192. HANDLE hVolume = CreateFile( wszVolumePath,
  193. GENERIC_READ,
  194. FILE_SHARE_READ | FILE_SHARE_WRITE,
  195. NULL,
  196. OPEN_EXISTING,
  197. 0,
  198. NULL );
  199. if ( hVolume != INVALID_HANDLE_VALUE )
  200. {
  201. SWin32Handle xHandleVolume( hVolume );
  202. //
  203. // Is there media in the drive? This check avoids possible hard-error
  204. // popups prompting for media.
  205. //
  206. ULONG ulSequence;
  207. DWORD cb = sizeof(ULONG);
  208. fOk = DeviceIoControl( hVolume,
  209. IOCTL_STORAGE_CHECK_VERIFY,
  210. 0,
  211. 0,
  212. &ulSequence,
  213. sizeof(ulSequence),
  214. &cb,
  215. 0 );
  216. if ( fOk )
  217. fOk = ReallyTouch();
  218. }
  219. return fOk;
  220. } //Touch