Leaked source code of windows server 2003
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.

949 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2002.
  5. //
  6. // File: FatNot.cxx
  7. //
  8. // Contents: Downlevel notification.
  9. //
  10. // Classes: CGenericNotify
  11. //
  12. // History: 2-23-96 KyleP Lifed from DLNotify.?xx
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <fatnot.hxx>
  18. #include <pathpars.hxx>
  19. #include <imprsnat.hxx>
  20. #include <catalog.hxx>
  21. #include <cicat.hxx>
  22. #include <ciregkey.hxx>
  23. #include <cievtmsg.h>
  24. #include <eventlog.hxx>
  25. #include <lm.h>
  26. //+---------------------------------------------------------------------------
  27. //
  28. // Class: CRemoteNotifications
  29. //
  30. // Purpose: A class to impersonate and enable notifications for remote
  31. // shares.
  32. //
  33. // History: 7-15-96 srikants Created
  34. //
  35. // Notes: When there are multiple alternatives possible for a remote
  36. // share, we have to use the one that allows access to remote
  37. // share (if there is one). There may be some which don't allow
  38. // the required access and we should skip those.
  39. //
  40. //----------------------------------------------------------------------------
  41. class CRemoteNotifications : public PImpersonatedWorkItem
  42. {
  43. public:
  44. CRemoteNotifications( WCHAR const * pwszPath,
  45. CGenericNotify & notify,
  46. OBJECT_ATTRIBUTES & objAttr )
  47. : PImpersonatedWorkItem( pwszPath ),
  48. _notify(notify),
  49. _objAttr(objAttr),
  50. _status(STATUS_SUCCESS)
  51. {
  52. }
  53. NTSTATUS OpenAndStart( CImpersonateRemoteAccess & remoteAccess );
  54. virtual BOOL DoIt();
  55. private:
  56. CGenericNotify & _notify;
  57. OBJECT_ATTRIBUTES & _objAttr;
  58. NTSTATUS _status;
  59. };
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Member: CRemoteNotifications::DoIt
  63. //
  64. // Synopsis: The virtual method that does the work under an impersonated
  65. // context.
  66. //
  67. // Returns: TRUE if successful;
  68. // FALSE o/w
  69. //
  70. // History: 7-15-96 srikants Created
  71. //
  72. //----------------------------------------------------------------------------
  73. BOOL CRemoteNotifications::DoIt()
  74. {
  75. _status = _notify.OpenDirectory( _objAttr );
  76. if ( IsRetryableError( _status ) )
  77. {
  78. //
  79. // We should attempt the open under a different impersonation
  80. // if possible.
  81. //
  82. return FALSE;
  83. }
  84. if ( NT_ERROR(_status) )
  85. THROW( CException( _status ) );
  86. //
  87. // Now, enable the notifications.
  88. //
  89. _notify.StartNotification( &_status ); // already impersonated
  90. if ( NT_ERROR(_status) )
  91. {
  92. _notify.CloseDirectory();
  93. if ( IsRetryableError(_status) )
  94. return FALSE;
  95. THROW( CException( _status ) );
  96. }
  97. //
  98. // Successfully enabled notifications.
  99. //
  100. return TRUE;
  101. }
  102. //+---------------------------------------------------------------------------
  103. //
  104. // Member: CRemoteNotifications::OpenAndStart
  105. //
  106. // Synopsis: Opens and start notifications for the remote root by trying
  107. // various impersonation contexts if necessary.
  108. //
  109. // Arguments: [remoteAccess] - The object to use for remote access.
  110. //
  111. // Returns: NTSTATUS of the whole operation.
  112. //
  113. // History: 7-15-96 srikants Created
  114. //
  115. //----------------------------------------------------------------------------
  116. NTSTATUS
  117. CRemoteNotifications::OpenAndStart( CImpersonateRemoteAccess & remoteAccess )
  118. {
  119. TRY
  120. {
  121. ImpersonateAndDoWork( remoteAccess );
  122. }
  123. CATCH( CException,e )
  124. {
  125. vqDebugOut(( DEB_ERROR, "OpenAndStart failed with error (0x%X)\n",
  126. e.GetErrorCode() ));
  127. _status = e.GetErrorCode();
  128. }
  129. END_CATCH
  130. return _status;
  131. }
  132. //+---------------------------------------------------------------------------
  133. //
  134. // Member: CGenericNotify::CGenericNotify
  135. //
  136. // Synopsis: Constructor of the single scope notification object CGenericNotify.
  137. //
  138. // Arguments: [wcsScope] -- Scope to watch
  139. // [cwcScope] -- Size in chars of [wcsScope]
  140. // [fDeep] -- Set to TRUE if deep notifications are enabled.
  141. //
  142. // History: 1-17-96 srikants Created
  143. //
  144. //----------------------------------------------------------------------------
  145. CGenericNotify::CGenericNotify( PCatalog *pCat,
  146. WCHAR const * wcsScope,
  147. unsigned cwcScope,
  148. BOOL fDeep,
  149. BOOL fLogEvents )
  150. : _refCount(1),
  151. _pCat( pCat ),
  152. _fNotifyActive(FALSE),
  153. _fRemoteDrive(FALSE),
  154. _cwcScope(cwcScope),
  155. _fDeep(fDeep),
  156. _fLogEvents(fLogEvents),
  157. _fAbort(FALSE),
  158. _hNotify(0),
  159. _pbBuffer(0)
  160. {
  161. if ( cwcScope >= MAX_PATH )
  162. {
  163. THROW( CException( STATUS_INVALID_PARAMETER ) );
  164. }
  165. RtlCopyMemory( _wcsScope, wcsScope, cwcScope * sizeof(WCHAR) );
  166. _wcsScope[cwcScope] = 0;
  167. CDoubleLink::Close();
  168. //
  169. // Bigger buffer for local scopes.
  170. //
  171. _fRemoteDrive = !IsFixedDrive( _wcsScope, _cwcScope );
  172. if ( _fRemoteDrive )
  173. _cbBuffer = CB_REMOTENOTIFYBUFFER;
  174. else
  175. _cbBuffer = CB_NOTIFYBUFFER;
  176. //
  177. // Client should call EnableNotification() in ctor. Delay allocating
  178. // the buffer in case this is a USN volume and no buffer is needed.
  179. //
  180. }
  181. //+---------------------------------------------------------------------------
  182. //
  183. // Member: CGenericNotify::~CGenericNotify
  184. //
  185. // Synopsis: ~dtor . Disables further notifications and frees up
  186. // memory.
  187. //
  188. // History: 1-17-96 srikants Created
  189. //
  190. // Notes:
  191. //
  192. //----------------------------------------------------------------------------
  193. CGenericNotify::~CGenericNotify()
  194. {
  195. Win4Assert( 0 == _refCount );
  196. Win4Assert( IsSingle() );
  197. Win4Assert( 0 == _hNotify );
  198. delete [] _pbBuffer;
  199. }
  200. //+---------------------------------------------------------------------------
  201. //
  202. // Member: CGenericNotify::OpenDirectory
  203. //
  204. // Synopsis: Opens a remote directory and uses the given object attributes.
  205. //
  206. // Arguments: [ObjectAttr] -
  207. //
  208. // Returns: STATUS of the operation.
  209. //
  210. // History: 7-15-96 srikants Created
  211. //
  212. //----------------------------------------------------------------------------
  213. NTSTATUS
  214. CGenericNotify::OpenDirectory( OBJECT_ATTRIBUTES & ObjectAttr )
  215. {
  216. BOOL fSuccess = TRUE;
  217. ULONG cSkip = 0;
  218. NTSTATUS Status = STATUS_SUCCESS;
  219. IO_STATUS_BLOCK IoStatus;
  220. Status = NtOpenFile( &_hNotify, // Handle
  221. FILE_LIST_DIRECTORY | SYNCHRONIZE, // Access
  222. &ObjectAttr, // Object Attributes
  223. &IoStatus, // I/O Status block
  224. FILE_SHARE_READ |
  225. FILE_SHARE_WRITE |
  226. FILE_SHARE_DELETE,
  227. FILE_DIRECTORY_FILE ); // Flags
  228. if ( NT_ERROR(Status) )
  229. _hNotify = 0;
  230. return Status;
  231. }
  232. //+---------------------------------------------------------------------------
  233. //
  234. // Member: CGenericNotify::CloseDirectory
  235. //
  236. // Synopsis: Closes the directory handle if open and sets it to 0.
  237. //
  238. // History: 7-15-96 srikants Created
  239. //
  240. //----------------------------------------------------------------------------
  241. void CGenericNotify::CloseDirectory()
  242. {
  243. if ( 0 != _hNotify )
  244. {
  245. NtClose( _hNotify );
  246. _hNotify = 0;
  247. }
  248. }
  249. //+---------------------------------------------------------------------------
  250. //
  251. // Member: CGenericNotify::EnableNotification
  252. //
  253. // Synopsis: Enables notifications for the current scope.
  254. //
  255. // History: 1-17-96 srikants Created
  256. //
  257. //----------------------------------------------------------------------------
  258. void CGenericNotify::EnableNotification()
  259. {
  260. vqDebugOut(( DEB_ITRACE, "Enable notification for scope %ws this=0x%x\n", _wcsScope, this ));
  261. if ( 0 == _pbBuffer )
  262. _pbBuffer = new BYTE [_cbBuffer];
  263. //
  264. // Open file
  265. //
  266. NTSTATUS Status;
  267. UNICODE_STRING uScope;
  268. if ( !RtlDosPathNameToNtPathName_U( _wcsScope,
  269. &uScope,
  270. 0,
  271. 0 ) )
  272. {
  273. vqDebugOut(( DEB_ERROR, "Error converting %ws to Nt path\n", _wcsScope ));
  274. THROW( CException(STATUS_INSUFFICIENT_RESOURCES) );
  275. }
  276. XRtlHeapMem xScopeBuf( uScope.Buffer );
  277. OBJECT_ATTRIBUTES ObjectAttr;
  278. InitializeObjectAttributes( &ObjectAttr, // Structure
  279. &uScope, // Name
  280. OBJ_CASE_INSENSITIVE, // Attributes
  281. 0, // Root
  282. 0 ); // Security
  283. CImpersonateRemoteAccess remoteAccess( GetCatalog()->GetImpersonationTokenCache() );
  284. CRemoteNotifications remoteNotify( _wcsScope, *this, ObjectAttr );
  285. if ( _fRemoteDrive )
  286. {
  287. //
  288. // Check if remote notifications are disabled.
  289. //
  290. if ( (GetCatalog()->GetRegParams())->GetCiCatalogFlags() &
  291. CI_FLAGS_NO_REMOTE_NOTIFY )
  292. {
  293. vqDebugOut(( DEB_WARN,
  294. "Not enabling remote notifications because it is disabled in registry\n" ));
  295. return;
  296. }
  297. //
  298. // Check if the remote drive is a DFS share. If so, don't try
  299. // to enabled notifications on the share. We have to just periodically
  300. // scan for changed documents.
  301. //
  302. if ( IsDfsShare( _wcsScope, _cwcScope ) )
  303. {
  304. vqDebugOut(( DEB_WARN, "Not enabling notifications for DFS Share (%ws) \n",
  305. _wcsScope ));
  306. LogDfsShare();
  307. return;
  308. }
  309. Status = remoteNotify.OpenAndStart( remoteAccess );
  310. }
  311. else
  312. {
  313. //
  314. // Check if local notifications are disabled.
  315. //
  316. if ( (GetCatalog()->GetRegParams())->GetCiCatalogFlags() &
  317. CI_FLAGS_NO_LOCAL_NOTIFY )
  318. {
  319. vqDebugOut(( DEB_WARN,
  320. "Not enabling local notifications because it is disabled in registry\n" ));
  321. return;
  322. }
  323. Status = OpenDirectory( ObjectAttr );
  324. if ( NT_ERROR( Status ) )
  325. {
  326. vqDebugOut(( DEB_ERROR,
  327. "Notification disabled. NtOpenFile( %ws ) returned 0x%lx\n",
  328. _wcsScope, Status ));
  329. _hNotify = 0;
  330. if ( _fLogEvents )
  331. LogNoNotifications( Status );
  332. return;
  333. }
  334. StartNotification( &Status );
  335. }
  336. if ( !_fNotifyActive && _fLogEvents )
  337. {
  338. LogNoNotifications( Status );
  339. }
  340. }
  341. //+---------------------------------------------------------------------------
  342. //
  343. // Member: CGenericNotify::DisableNotification
  344. //
  345. // Synopsis: Disables further notifications for this scope.
  346. //
  347. // History: 1-17-96 srikants Created
  348. //
  349. // Notes: This must be called from within the lock of the notify manager.
  350. //
  351. //----------------------------------------------------------------------------
  352. void CGenericNotify::DisableNotification()
  353. {
  354. vqDebugOut(( DEB_ITRACE, "Disable notification for scope %ws this=0x%x\n", _wcsScope, this ));
  355. if ( 0 != _hNotify )
  356. {
  357. NtClose( _hNotify );
  358. _hNotify = 0;
  359. }
  360. Release();
  361. }
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Member: CGenericNotify::StartNotification
  365. //
  366. // Synopsis: Starts notifications by setting the APC for receiving
  367. // notifications. If successful, the object will be refcounted
  368. // and the status set to indicate that the operation is
  369. // successful.
  370. //
  371. // History: 1-17-96 srikants Created
  372. //
  373. // Notes: This must be called from within the lock of the notify manager.
  374. // If successful, the notify manager will also be
  375. // refcounted. This is because the APC depends upon the mutex
  376. // in the notify manager to be around when it is invoked.
  377. //
  378. //----------------------------------------------------------------------------
  379. void CGenericNotify::StartNotification( NTSTATUS * pStatus )
  380. {
  381. //
  382. // Set up query directory file.
  383. //
  384. if ( 0 == _hNotify )
  385. {
  386. *pStatus = STATUS_TOO_LATE;
  387. return;
  388. }
  389. NTSTATUS Status = STATUS_SUCCESS;
  390. DWORD dwFlags = GetNotifyFlags();
  391. Status = NtNotifyChangeDirectoryFile( _hNotify,
  392. 0,
  393. APC,
  394. this,
  395. &_iosNotify,
  396. _pbBuffer,
  397. _cbBuffer,
  398. dwFlags,
  399. (BYTE)_fDeep );
  400. if ( NT_ERROR(Status) )
  401. {
  402. vqDebugOut(( DEB_ERROR,
  403. "NtNotifyChangeDirectoryFile( %ws ) returned 0x%lx\n",
  404. _wcsScope, Status ));
  405. }
  406. else
  407. {
  408. _fNotifyActive = TRUE;
  409. AddRef();
  410. }
  411. if ( pStatus )
  412. *pStatus = Status;
  413. }
  414. //+---------------------------------------------------------------------------
  415. //
  416. // Member: CGenericNotify::AddRef
  417. //
  418. // History: 1-17-96 srikants Created
  419. //
  420. //----------------------------------------------------------------------------
  421. void CGenericNotify::AddRef()
  422. {
  423. InterlockedIncrement(&_refCount);
  424. }
  425. //+---------------------------------------------------------------------------
  426. //
  427. // Member: CGenericNotify::Release
  428. //
  429. // Synopsis: If the refcount goes to 0, the object will be deleted.
  430. //
  431. // History: 1-17-96 srikants Created
  432. //
  433. //----------------------------------------------------------------------------
  434. void CGenericNotify::Release()
  435. {
  436. Win4Assert( _refCount > 0 );
  437. if ( InterlockedDecrement(&_refCount) <= 0 )
  438. delete this;
  439. }
  440. //+---------------------------------------------------------------------------
  441. //
  442. // Member: CGenericNotify::AdjustForOverflow
  443. //
  444. // Synopsis: Increases the size of the notification buffer if it is not
  445. // a remote drive and if the current size is < the maximum.
  446. //
  447. // History: 2-27-96 srikants Created
  448. //
  449. // Notes:
  450. //
  451. //----------------------------------------------------------------------------
  452. void CGenericNotify::AdjustForOverflow()
  453. {
  454. if ( !_fRemoteDrive && CB_MAXSIZE > _cbBuffer )
  455. {
  456. unsigned cbNew = min( _cbBuffer + CB_DELTAINCR, CB_MAXSIZE );
  457. vqDebugOut(( DEB_ITRACE,
  458. "Resizing notification buffer from 0x%X to 0x%X bytes\n",
  459. _cbBuffer, cbNew ));
  460. BYTE * pbNew = new BYTE [cbNew];
  461. delete [] _pbBuffer;
  462. _pbBuffer = pbNew;
  463. _cbBuffer = cbNew;
  464. }
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Member: CGenericNotify::APC
  469. //
  470. // Synopsis: Asynchronous Procedure Call invoked by the system when there
  471. // is a change notification (or related error).
  472. //
  473. // Arguments: [ApcContext] - Pointer to "this"
  474. // [IoStatusBlock] -
  475. // [Reserved] -
  476. //
  477. // History: 1-17-96 srikants Created
  478. //
  479. // Notes:
  480. //
  481. //----------------------------------------------------------------------------
  482. void CGenericNotify::APC( void * ApcContext,
  483. IO_STATUS_BLOCK * IoStatusBlock,
  484. ULONG Reserved )
  485. {
  486. Win4Assert( 0 != ApcContext );
  487. CGenericNotify * pthis = (CGenericNotify *)ApcContext;
  488. NTSTATUS status = STATUS_SUCCESS;
  489. TRY
  490. {
  491. pthis->_fOverflow = FALSE;
  492. Win4Assert( &pthis->_iosNotify == IoStatusBlock );
  493. // DbgPrint( "notifications...\n" );
  494. if ( NT_ERROR( IoStatusBlock->Status ) )
  495. {
  496. if ( !pthis->_fAbort )
  497. {
  498. // DbgPrint( "Async notification for scope %ws received error 0x%x\n",
  499. // pthis->_wcsScope,
  500. // IoStatusBlock->Status );
  501. vqDebugOut(( DEB_ERROR,
  502. "Async notification for scope %ws received error 0x%x\n",
  503. pthis->_wcsScope,
  504. IoStatusBlock->Status ));
  505. vqDebugOut(( DEB_ITRACE, "CiNotification APC: ERROR 0x%x\n", pthis ));
  506. status = IoStatusBlock->Status;
  507. //
  508. // The I/O failed and it may be due to STATUS_DELETE_PENDING.
  509. // In any case, just close the handle so the directory is
  510. // freed for other apps.
  511. //
  512. pthis->CloseDirectory();
  513. }
  514. }
  515. else if ( IoStatusBlock->Status == STATUS_NOTIFY_CLEANUP )
  516. {
  517. vqDebugOut(( DEB_ITRACE, "CiNotification APC: CLOSE 0x%x\n", pthis ));
  518. }
  519. else
  520. {
  521. if ( IoStatusBlock->Status == STATUS_NOTIFY_ENUM_DIR )
  522. {
  523. // DbgPrint( "***** CiNotification LOST UPDATES for scope %ws *****\n",
  524. // pthis->_wcsScope );
  525. vqDebugOut(( DEB_WARN,
  526. "***** CiNotification LOST UPDATES for scope %ws *****\n",
  527. pthis->_wcsScope ));
  528. pthis->_fOverflow = TRUE;
  529. //
  530. // Let us adjust the size of the buffer if possible.
  531. //
  532. pthis->AdjustForOverflow();
  533. //
  534. // But call anyway. Client is responsible for checking ::BufferOverflow.
  535. //
  536. pthis->DoIt();
  537. }
  538. else
  539. {
  540. // .Information is the # of bytes written to the buffer.
  541. // This may be 0 even when .Status is STATUS_NOTIFY_ENUM_DIR,
  542. // and with certain builds of rdr2, STATUS_SUCCESS.
  543. if ( 0 == IoStatusBlock->Information &&
  544. 0 == IoStatusBlock->Status )
  545. {
  546. // BrianAn says NTFS won't do this, but rdr2 might
  547. vqDebugOut(( DEB_WARN,
  548. "CGenericNotify: invalid notification apc\n" ));
  549. // DbgPrint( "0 info and status block\n" );
  550. }
  551. #if 0
  552. if ( 0 != IoStatusBlock->Information )
  553. #endif
  554. {
  555. if ( !pthis->_fRemoteDrive )
  556. {
  557. pthis->DoIt();
  558. }
  559. else
  560. {
  561. //
  562. // Get sufficient impersonation context to get attributes on
  563. // the remote share. Then process the notifications.
  564. //
  565. CImpersonateRemoteAccess remote( pthis->GetCatalog()->GetImpersonationTokenCache() );
  566. CImpersonatedGetAttr getAttr( pthis->_wcsScope );
  567. getAttr.DoWork( remote );
  568. pthis->DoIt();
  569. }
  570. }
  571. }
  572. }
  573. }
  574. CATCH(CException, e)
  575. {
  576. //DbgPrint( "caught exception in notifications\n" );
  577. vqDebugOut(( DEB_ERROR,
  578. "CiNotification APC: CATCH 0x%x, iostatus: 0x%x, info: 0x%x\n",
  579. e.GetErrorCode(),
  580. IoStatusBlock->Status,
  581. IoStatusBlock->Information ));
  582. status = e.GetErrorCode();
  583. }
  584. END_CATCH;
  585. if ( STATUS_SUCCESS != status )
  586. {
  587. //DbgPrint( "clearing notify enabled\n" );
  588. pthis->ClearNotifyEnabled();
  589. if ( pthis->_fLogEvents )
  590. pthis->LogNotificationsFailed( status );
  591. }
  592. pthis->Release();
  593. } //APC
  594. //+---------------------------------------------------------------------------
  595. //
  596. // Member: CGenericNotify::IsFixedDrive, private
  597. //
  598. // Arguments: [wcsScope] -- Scope to check
  599. // [len] -- Length in chars of [wcsScope]
  600. //
  601. // Returns: TRUE if scope is for a fixed drive.
  602. //
  603. // History: 1-17-96 srikants Created
  604. //
  605. //----------------------------------------------------------------------------
  606. BOOL CGenericNotify::IsFixedDrive( WCHAR const * wcsScope, ULONG len )
  607. {
  608. CPathParser pathParser( wcsScope, len );
  609. if ( pathParser.IsUNCName() )
  610. return FALSE;
  611. WCHAR wDrive[MAX_PATH];
  612. ULONG cc=sizeof(wDrive)/sizeof(WCHAR);
  613. pathParser.GetFileName( wDrive, cc );
  614. UINT uType = GetDriveType( wDrive );
  615. return DRIVE_FIXED == uType;
  616. }
  617. //+---------------------------------------------------------------------------
  618. //
  619. // Function: CiNetShareGetInfo
  620. //
  621. // Synopsis: Calls NetShareGetInfo. Loads the library so we don't
  622. // link to netapi32.dll for the odd case of indexing remote
  623. // volumes. Also, don't cache the function pointer since
  624. // it's called so rarely.
  625. //
  626. // Arguments: Same as NetShareGetInfo
  627. //
  628. // Returns: Win32 / NetStatus error code
  629. //
  630. // History: 2-18-98 dlee Created
  631. //
  632. //----------------------------------------------------------------------------
  633. typedef NET_API_STATUS (NET_API_FUNCTION * NET_SHARE_GET_INFO_FUNC)(
  634. LPTSTR servername,
  635. LPTSTR netname,
  636. DWORD level,
  637. BYTE ** bufptr );
  638. NET_API_STATUS NET_API_FUNCTION CiNetShareGetInfo(
  639. LPTSTR servername,
  640. LPTSTR netname,
  641. DWORD level,
  642. BYTE ** bufptr )
  643. {
  644. HINSTANCE hLib = LoadLibrary( L"netapi32.dll" );
  645. if ( 0 == hLib )
  646. return GetLastError();
  647. NET_SHARE_GET_INFO_FUNC pfn = (NET_SHARE_GET_INFO_FUNC)
  648. GetProcAddress( hLib, "NetShareGetInfo" );
  649. if ( 0 == pfn )
  650. {
  651. FreeLibrary( hLib );
  652. return GetLastError();
  653. }
  654. NET_API_STATUS status = (*pfn)( servername, netname, level, bufptr );
  655. FreeLibrary( hLib );
  656. return status;
  657. } //CiNetShareGetInfo
  658. //+---------------------------------------------------------------------------
  659. //
  660. // Function: IsDfsShare
  661. //
  662. // Synopsis: Determines if the given UNC share is a DFS share.
  663. //
  664. // Arguments: [wcsScope] - scope
  665. // [len] - Length
  666. //
  667. // Returns: TRUE if it is a DFS share. FALSE o/w
  668. //
  669. // History: 6-23-96 srikants Created
  670. //
  671. //----------------------------------------------------------------------------
  672. BOOL CGenericNotify::IsDfsShare( WCHAR const * wcsScope, ULONG len )
  673. {
  674. CPathParser pathParser( wcsScope, len );
  675. if ( !pathParser.IsUNCName() )
  676. return FALSE;
  677. WCHAR wDrive[MAX_PATH];
  678. ULONG cc=sizeof(wDrive)/sizeof(WCHAR);
  679. pathParser.GetFileName( wDrive, cc );
  680. WCHAR * pwszServerName = wDrive;
  681. WCHAR * pwszShareName = 0;
  682. //
  683. // Locate the third backslash and replace it with a NULL char.
  684. //
  685. for ( unsigned i = 2; i < cc; i++ )
  686. {
  687. if ( wDrive[i] == L'\\' )
  688. {
  689. wDrive[i] = 0;
  690. pwszShareName = wDrive+i+1;
  691. break;
  692. }
  693. }
  694. Win4Assert( 0 != pwszShareName );
  695. //
  696. // Remove any trailing backslash in the share name.
  697. //
  698. i = wcslen( pwszShareName );
  699. if ( L'\\' == pwszShareName[i-1] )
  700. {
  701. pwszShareName[i-1] = 0;
  702. }
  703. BOOL fIsDfs = FALSE;
  704. PSHARE_INFO_1005 shi1005;
  705. NET_API_STATUS err = CiNetShareGetInfo( pwszServerName,
  706. pwszShareName,
  707. 1005,
  708. (PBYTE *) &shi1005 );
  709. if (err == ERROR_SUCCESS)
  710. {
  711. fIsDfs = ((shi1005->shi1005_flags & SHI1005_FLAGS_DFS) != 0);
  712. //
  713. // Netapi32.dll midl_user_allocate calls LocalAlloc, so use
  714. // LocalFree to free up the stuff the stub allocated.
  715. //
  716. LocalFree( shi1005 );
  717. }
  718. return fIsDfs;
  719. }
  720. void CGenericNotify::LogNotificationsFailed( DWORD dwError ) const
  721. {
  722. Win4Assert( 0 != dwError );
  723. TRY
  724. {
  725. CEventLog eventLog( NULL, wcsCiEventSource );
  726. CEventItem item( EVENTLOG_ERROR_TYPE,
  727. CI_SERVICE_CATEGORY,
  728. MSG_CI_NOTIFICATIONS_TURNED_OFF,
  729. 2 );
  730. item.AddArg( _wcsScope );
  731. //
  732. // When a logon fails, all the other eventlog messages have the
  733. // WIN32 error code in them. Just to keep it consistent, use the
  734. // WIN32 error code here also.
  735. //
  736. if ( STATUS_LOGON_FAILURE == dwError )
  737. dwError = ERROR_LOGON_FAILURE;
  738. item.AddError( dwError );
  739. eventLog.ReportEvent( item );
  740. }
  741. CATCH( CException, e )
  742. {
  743. vqDebugOut(( DEB_ERROR, "Exception 0x%X while writing to event log\n",
  744. e.GetErrorCode() ));
  745. }
  746. END_CATCH
  747. }
  748. void CGenericNotify::LogNoNotifications( DWORD dwError ) const
  749. {
  750. Win4Assert( 0 != dwError );
  751. TRY
  752. {
  753. CEventLog eventLog( NULL, wcsCiEventSource );
  754. CEventItem item( EVENTLOG_INFORMATION_TYPE,
  755. CI_SERVICE_CATEGORY,
  756. MSG_CI_NOTIFICATIONS_NOT_STARTED,
  757. 2 );
  758. item.AddArg( _wcsScope );
  759. //
  760. // When a logon fails, all the other eventlog messages have the
  761. // WIN32 error code in them. Just to keep it consistent, use the
  762. // WIN32 error code here also.
  763. //
  764. if ( STATUS_LOGON_FAILURE == dwError )
  765. dwError = ERROR_LOGON_FAILURE;
  766. item.AddError( dwError );
  767. eventLog.ReportEvent( item );
  768. }
  769. CATCH( CException, e )
  770. {
  771. vqDebugOut(( DEB_ERROR, "Exception 0x%X while writing to event log\n",
  772. e.GetErrorCode() ));
  773. }
  774. END_CATCH
  775. }
  776. //+---------------------------------------------------------------------------
  777. //
  778. // Member: CGenericNotify::LogDfsShare
  779. //
  780. // Synopsis: Logs the the current share is a DFS aware share.
  781. //
  782. // History: 6-27-96 srikants Created
  783. //
  784. //----------------------------------------------------------------------------
  785. void CGenericNotify::LogDfsShare() const
  786. {
  787. TRY
  788. {
  789. CEventLog eventLog( NULL, wcsCiEventSource );
  790. CEventItem item( EVENTLOG_INFORMATION_TYPE,
  791. CI_SERVICE_CATEGORY,
  792. MSG_CI_DFS_SHARE_DETECTED,
  793. 1 );
  794. item.AddArg( _wcsScope );
  795. eventLog.ReportEvent( item );
  796. }
  797. CATCH( CException, e )
  798. {
  799. vqDebugOut(( DEB_ERROR, "Exception 0x%X while writing to event log\n",
  800. e.GetErrorCode() ));
  801. }
  802. END_CATCH
  803. }