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.

731 lines
18 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. //
  5. // SERVER.CPP - Handles the "IntelliMirror" IDD_PROP_INTELLIMIRROR_SERVER tab
  6. //
  7. #include "pch.h"
  8. #include <dns.h>
  9. #include "utils.h"
  10. #include "cservice.h"
  11. #include "cenumsif.h"
  12. #include "ccomputr.h"
  13. #include "server.h"
  14. #include "dpguidqy.h"
  15. #include "querypb.h"
  16. DEFINE_MODULE("IMADMUI")
  17. DEFINE_THISCLASS("CServerTab")
  18. #define THISCLASS CServerTab
  19. #define LPTHISCLASS LPSERVERTAB
  20. DWORD aServerHelpMap[] = {
  21. IDC_C_RESPOND, HIDC_C_RESPOND,
  22. IDC_C_KNOWNCLIENTS, HIDC_C_KNOWNCLIENTS,
  23. IDC_B_CHECKSERVER, HIDC_B_CHECKSERVER,
  24. IDC_B_CLIENTS, HIDC_B_CLIENTS,
  25. IDC_B_SERVICE, HIDC_B_SERVICE,
  26. IDC_G_CHECKSERVER, HIDC_G_CHECKSERVER,
  27. IDC_G_CLIENTSERVICING, HIDC_G_CLIENTSERVICING,
  28. NULL, NULL
  29. };
  30. //
  31. // CreateInstance()
  32. //
  33. LPVOID
  34. CServerTab_CreateInstance( void )
  35. {
  36. TraceFunc( "CServerTab_CreateInstance()\n" );
  37. LPTHISCLASS lpcc = new THISCLASS( );
  38. HRESULT hr = THR( lpcc->Init( ) );
  39. if ( FAILED(hr) ) {
  40. delete lpcc;
  41. RETURN(NULL);
  42. }
  43. RETURN((LPVOID) lpcc);
  44. }
  45. //
  46. // Constructor
  47. //
  48. THISCLASS::THISCLASS( ) :
  49. _hDlg(NULL),
  50. _fChanged(FALSE),
  51. _uMode(MODE_SHELL),
  52. _punkService(NULL),
  53. _pido(NULL),
  54. _pszSCPDN(NULL),
  55. _pszGroupDN(NULL),
  56. _punkComputer(NULL),
  57. _hNotify(NULL)
  58. {
  59. TraceClsFunc( "CServerTab()\n" );
  60. InterlockIncrement( g_cObjects );
  61. Assert( !_punkService );
  62. Assert( !_pido );
  63. Assert( !_pszGroupDN );
  64. Assert( !_pszSCPDN );
  65. TraceFuncExit();
  66. }
  67. //
  68. // Init()
  69. //
  70. STDMETHODIMP
  71. THISCLASS::Init( )
  72. {
  73. HRESULT hr = S_OK;
  74. TraceClsFunc( "Init()\n" );
  75. _uMode = MODE_SHELL; // default
  76. HRETURN(hr);
  77. }
  78. //
  79. // Destructor
  80. //
  81. THISCLASS::~THISCLASS( )
  82. {
  83. TraceClsFunc( "~CServerTab()\n" );
  84. if ( _pido )
  85. _pido->Release( );
  86. if ( _punkService )
  87. _punkService->Release( );
  88. if ( _punkComputer )
  89. _punkComputer->Release( );
  90. if ( _pszSCPDN )
  91. TraceFree( _pszSCPDN );
  92. if ( _pszGroupDN )
  93. TraceFree( _pszGroupDN );
  94. // tell ADS to destroy the notify object
  95. // NOTE: Another property page may do this before us. Ignore errors.
  96. SendMessage( _hNotify, WM_ADSPROP_NOTIFY_EXIT, 0, 0 );
  97. InterlockDecrement( g_cObjects );
  98. TraceFuncExit();
  99. };
  100. // *************************************************************************
  101. //
  102. // ITab
  103. //
  104. // *************************************************************************
  105. STDMETHODIMP
  106. THISCLASS::AddPages(
  107. LPFNADDPROPSHEETPAGE lpfnAddPage,
  108. LPARAM lParam,
  109. LPUNKNOWN punk )
  110. {
  111. TraceClsFunc( "AddPages( )\n" );
  112. if ( !punk )
  113. RRETURN(E_POINTER);
  114. HRESULT hr = S_OK;
  115. PROPSHEETPAGE psp;
  116. HPROPSHEETPAGE hpage;
  117. psp.dwSize = sizeof(psp);
  118. psp.dwFlags = PSP_USEREFPARENT | PSP_USECALLBACK;
  119. psp.hInstance = (HINSTANCE) g_hInstance;
  120. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP_INTELLIMIRROR_SERVER);
  121. psp.pcRefParent = (UINT *) &g_cObjects;
  122. psp.pfnCallback = (LPFNPSPCALLBACK) PropSheetPageProc;
  123. psp.pfnDlgProc = PropSheetDlgProc;
  124. psp.lParam = (LPARAM) this;
  125. LPSHELLEXTINIT pShellExtInit = NULL;
  126. IMAO * pmao = NULL;
  127. _punkComputer = punk;
  128. _punkComputer->AddRef( );
  129. hr = THR( _punkComputer->QueryInterface( IID_IMAO, (void**) &pmao ) );
  130. if (FAILED( hr ))
  131. goto Error;
  132. hr = THR( pmao->GetDataObject( &_pido ) );
  133. if (FAILED( hr ))
  134. goto Error;
  135. _punkService = (LPUNKNOWN) CService_CreateInstance( );
  136. if ( !_punkService ) {
  137. hr = E_OUTOFMEMORY;
  138. goto Error;
  139. }
  140. hr = THR( _punkService->QueryInterface( IID_IShellExtInit, (void **) &pShellExtInit ) );
  141. if (FAILED( hr ))
  142. goto Error;
  143. hr = THR( pShellExtInit->Initialize( NULL, _pido, NULL ) );
  144. if (FAILED( hr ))
  145. goto Error;
  146. hpage = CreatePropertySheetPage( &psp );
  147. if ( hpage ) {
  148. if ( !lpfnAddPage( hpage, lParam ) ) {
  149. DestroyPropertySheetPage( hpage );
  150. hr = THR(E_FAIL);
  151. }
  152. }
  153. Cleanup:
  154. if ( pShellExtInit )
  155. pShellExtInit->Release( );
  156. if ( pmao )
  157. pmao->Release( );
  158. HRETURN(hr);
  159. Error:
  160. MessageBoxFromHResult( NULL, NULL, hr );
  161. goto Cleanup;
  162. }
  163. //
  164. // ReplacePage()
  165. //
  166. STDMETHODIMP
  167. THISCLASS::ReplacePage(
  168. UINT uPageID,
  169. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  170. LPARAM lParam,
  171. LPUNKNOWN punk )
  172. {
  173. TraceClsFunc( "ReplacePage( ) *** NOT_IMPLEMENTED ***\n" );
  174. HRETURN(E_NOTIMPL);
  175. }
  176. //
  177. // QueryInformation( )
  178. //
  179. STDMETHODIMP
  180. THISCLASS::QueryInformation(
  181. LPWSTR pszAttribute,
  182. LPWSTR * pszResult )
  183. {
  184. TraceClsFunc( "QueryInformation( )\n" );
  185. HRETURN(E_NOTIMPL);
  186. }
  187. //
  188. // AllowActivation( )
  189. //
  190. STDMETHODIMP
  191. THISCLASS::AllowActivation(
  192. BOOL * pfAllow )
  193. {
  194. TraceClsFunc( "AllowActivation( )\n" );
  195. HRETURN(E_NOTIMPL);
  196. }
  197. // ************************************************************************
  198. //
  199. // Property Sheet Functions
  200. //
  201. // ************************************************************************
  202. //
  203. // PropSheetDlgProc()
  204. //
  205. INT_PTR CALLBACK
  206. THISCLASS::PropSheetDlgProc(
  207. HWND hDlg,
  208. UINT uMsg,
  209. WPARAM wParam,
  210. LPARAM lParam )
  211. {
  212. //TraceMsg( TEXT("PropSheetDlgProc(") );
  213. //TraceMsg( TF_FUNC, TEXT(" hDlg = 0x%08x, uMsg = 0x%08x, wParam = 0x%08x, lParam = 0x%08x )\n"),
  214. // hDlg, uMsg, wParam, lParam );
  215. LPTHISCLASS pcc = (LPTHISCLASS) GetWindowLongPtr( hDlg, GWLP_USERDATA );
  216. if ( uMsg == WM_INITDIALOG ) {
  217. TraceMsg( TF_WM, TEXT("WM_INITDIALOG\n"));
  218. LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE) lParam;
  219. SetWindowLongPtr( hDlg, GWLP_USERDATA, psp->lParam );
  220. pcc = (LPTHISCLASS) psp->lParam;
  221. return pcc->_InitDialog( hDlg, lParam );
  222. }
  223. if (pcc) {
  224. Assert( hDlg == pcc->_hDlg );
  225. switch ( uMsg ) {
  226. case WM_NOTIFY:
  227. return pcc->_OnNotify( wParam, lParam );
  228. case WM_COMMAND:
  229. TraceMsg( TF_WM, TEXT("WM_COMMAND\n") );
  230. return pcc->_OnCommand( wParam, lParam );
  231. break;
  232. case WM_HELP:// F1
  233. {
  234. LPHELPINFO phelp = (LPHELPINFO) lParam;
  235. WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aServerHelpMap );
  236. }
  237. break;
  238. case WM_CONTEXTMENU: // right mouse click
  239. WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aServerHelpMap );
  240. break;
  241. case WM_ADSPROP_PAGE_GET_NOTIFY:
  242. {
  243. HWND *phwnd = (HWND *) wParam;
  244. *phwnd = pcc->_hNotify;
  245. }
  246. return TRUE;
  247. }
  248. }
  249. return FALSE;
  250. }
  251. //
  252. // PropSheetPageProc()
  253. //
  254. UINT CALLBACK
  255. THISCLASS::PropSheetPageProc(
  256. HWND hwnd,
  257. UINT uMsg,
  258. LPPROPSHEETPAGE ppsp )
  259. {
  260. TraceClsFunc( "PropSheetPageProc( " );
  261. TraceMsg( TF_FUNC, TEXT("hwnd = 0x%08x, uMsg = 0x%08x, ppsp= 0x%08x )\n"),
  262. hwnd, uMsg, ppsp );
  263. switch ( uMsg ) {
  264. case PSPCB_CREATE:
  265. RETURN(TRUE); // create it
  266. break;
  267. case PSPCB_RELEASE:
  268. LPTHISCLASS pcc = (LPTHISCLASS) ppsp->lParam;
  269. delete pcc;
  270. break;
  271. }
  272. RETURN(FALSE);
  273. }
  274. //
  275. // _InitDialog( )
  276. //
  277. BOOL
  278. THISCLASS::_InitDialog(
  279. HWND hDlg,
  280. LPARAM lParam )
  281. {
  282. TraceClsFunc( "_InitDialog( )\n" );
  283. CWaitCursor Wait;
  284. BOOL fAdmin = FALSE;
  285. LPINTELLIMIRRORSAP pimsap = NULL;
  286. HRESULT hr;
  287. HRESULT hResult = S_OK;
  288. WCHAR szRISETUPPath[ MAX_PATH ];
  289. HANDLE hFind;
  290. BOOL fOnOff;
  291. IMAO * pmao = NULL;
  292. WIN32_FIND_DATA fda;
  293. _hDlg = hDlg;
  294. hr = THR( _punkService->QueryInterface( IID_IIntelliMirrorSAP, (void**) &pimsap ) );
  295. if (FAILED( hr ))
  296. goto Error;
  297. hr = THR( _punkComputer->QueryInterface( IID_IMAO, (void**) &pmao ) );
  298. if (FAILED( hr ))
  299. goto Error;
  300. hr = THR( pmao->GetNotifyWindow( &_hNotify ) );
  301. if (FAILED( hr ))
  302. goto Error;
  303. ADsPropSetHwnd( _hNotify, _hDlg );
  304. hr = THR( pimsap->IsAdmin( &fAdmin ) );
  305. Assert( SUCCEEDED(hr) || fAdmin == FALSE );
  306. hr = THR( pimsap->GetAnswerRequests( &fOnOff) );
  307. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND && hResult == S_OK ) {
  308. hResult = hr;
  309. }
  310. Assert( SUCCEEDED(hr) || fOnOff == FALSE );
  311. Button_SetCheck( GetDlgItem( _hDlg, IDC_C_RESPOND ), ( fOnOff ? BST_CHECKED : BST_UNCHECKED ) );
  312. EnableWindow( GetDlgItem( _hDlg, IDC_C_KNOWNCLIENTS ), fOnOff );
  313. hr = THR( pimsap->GetAnswerOnlyValidClients( &fOnOff) );
  314. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND && hResult == S_OK ) {
  315. hResult = hr;
  316. }
  317. Assert( SUCCEEDED(hr) || fOnOff == FALSE );
  318. Button_SetCheck( GetDlgItem( _hDlg, IDC_C_KNOWNCLIENTS ), ( fOnOff ? BST_CHECKED : BST_UNCHECKED ) );
  319. // See if we can enable the "Check Server" button.
  320. if (!ExpandEnvironmentStrings(L"%SystemRoot%\\system32\\risetup.exe", szRISETUPPath, ARRAYSIZE(szRISETUPPath))) {
  321. hr = THR(HRESULT_FROM_WIN32( GetLastError() ));
  322. goto Error;
  323. }
  324. hFind = FindFirstFile( szRISETUPPath, &fda );
  325. if ( hFind != INVALID_HANDLE_VALUE ) {
  326. FindClose( hFind );
  327. LPWSTR pszServerName;
  328. WCHAR szFQDNS[ DNS_MAX_NAME_BUFFER_LENGTH ];
  329. DWORD cbSize = ARRAYSIZE( szFQDNS );
  330. hr = THR( pimsap->GetServerName( &pszServerName ) );
  331. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND ) {
  332. goto Error;
  333. }
  334. if (SUCCEEDED( hr )) {
  335. GetComputerNameEx( ComputerNameNetBIOS, szFQDNS, &cbSize );
  336. if ( StrCmpI( szFQDNS, pszServerName ) == 0) {
  337. EnableWindow( GetDlgItem( _hDlg, IDC_B_CHECKSERVER ), TRUE );
  338. }
  339. TraceFree( pszServerName );
  340. }
  341. }
  342. Assert( !_pszSCPDN );
  343. hr = THR( pimsap->GetSCPDN( &_pszSCPDN ) );
  344. if (FAILED( hr )) {
  345. goto Error;
  346. }
  347. EnableWindow( GetDlgItem( _hDlg, IDC_B_SERVICE ), !!_pszSCPDN );
  348. if (FAILED( hResult )) {
  349. MessageBoxFromHResult( _hDlg, IDS_ERROR_READINGCOMPUTERACCOUNT, hResult );
  350. }
  351. Cleanup:
  352. if ( pmao )
  353. pmao->Release( );
  354. if ( pimsap )
  355. pimsap->Release( );
  356. RETURN(FALSE);
  357. Error:
  358. MessageBoxFromHResult( _hDlg, IDS_ERROR_READINGCOMPUTERACCOUNT, hr );
  359. goto Cleanup;
  360. }
  361. //
  362. // _DisplayClientsQueryForm( )
  363. //
  364. HRESULT
  365. THISCLASS::_DisplayClientsQueryForm( )
  366. {
  367. TraceClsFunc( "_DisplayClientsQueryForm( )\n" );
  368. HRESULT hr;
  369. DSQUERYINITPARAMS dqip;
  370. OPENQUERYWINDOW oqw;
  371. LPDSOBJECTNAMES pDsObjects;
  372. ICommonQuery * pCommonQuery = NULL;
  373. IPropertyBag * ppb = NULL;
  374. VARIANT var;
  375. LPINTELLIMIRRORSAP pimsap = NULL;
  376. LPWSTR pszServerName = NULL;
  377. WCHAR szServerQuery[ DNS_MAX_NAME_BUFFER_LENGTH + 1 ];
  378. BSTR tmp;
  379. VariantInit( &var );
  380. hr = THR( _punkService->QueryInterface( IID_IIntelliMirrorSAP, (void**) &pimsap ) );
  381. if (FAILED( hr )) {
  382. goto Clients_Error;
  383. }
  384. hr = THR( pimsap->GetServerName( &pszServerName ) );
  385. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND ) {
  386. goto Clients_Error;
  387. }
  388. hr = THR( CoCreateInstance( CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_ICommonQuery, (PVOID *)&pCommonQuery) );
  389. if (FAILED( hr )) {
  390. goto Clients_Error;
  391. }
  392. if (wcslen(pszServerName) + 1 + 1 <= ARRAYSIZE(szServerQuery)) {
  393. wcscpy( szServerQuery, pszServerName );
  394. wcscat( szServerQuery, L"*" );
  395. } else {
  396. hr = E_INVALIDARG;
  397. goto Clients_Error;
  398. }
  399. tmp = SysAllocString( szServerQuery );
  400. if (!tmp) {
  401. hr = E_OUTOFMEMORY;
  402. goto Clients_Error;
  403. }
  404. V_VT( &var ) = VT_BSTR;
  405. V_BSTR( &var ) = tmp;
  406. ZeroMemory( &dqip, sizeof(dqip) );
  407. dqip.cbStruct = sizeof(dqip);
  408. dqip.dwFlags = DSQPF_NOSAVE | DSQPF_SHOWHIDDENOBJECTS | DSQPF_ENABLEADMINFEATURES;
  409. dqip.dwFlags |= DSQPF_ENABLEADVANCEDFEATURES;
  410. ppb = (IPropertyBag *) QueryPropertyBag_CreateInstance( );
  411. if ( !ppb ) {
  412. hr = E_OUTOFMEMORY;
  413. goto Clients_Error;
  414. }
  415. hr = THR( ppb->Write( L"ServerName", &var ) );
  416. if (FAILED(hr)) {
  417. goto Clients_Error;
  418. }
  419. ZeroMemory( &oqw, sizeof(oqw) );
  420. oqw.cbStruct = sizeof(oqw);
  421. oqw.dwFlags = OQWF_SHOWOPTIONAL | OQWF_ISSUEONOPEN | OQWF_DEFAULTFORM;
  422. oqw.clsidHandler = CLSID_DsQuery;
  423. oqw.pHandlerParameters = &dqip;
  424. oqw.clsidDefaultForm = CLSID_RIQueryForm;
  425. oqw.pFormParameters = ppb;
  426. hr = pCommonQuery->OpenQueryWindow( _hDlg, &oqw, NULL /* don't need results */);
  427. Clients_Error:
  428. VariantClear( &var );
  429. if ( ppb )
  430. ppb->Release( );
  431. if ( pCommonQuery )
  432. pCommonQuery->Release( );
  433. if ( pszServerName )
  434. TraceFree( pszServerName );
  435. if ( pimsap )
  436. pimsap->Release( );
  437. HRETURN(hr);
  438. }
  439. //
  440. // _OnCommand( )
  441. //
  442. BOOL
  443. THISCLASS::_OnCommand( WPARAM wParam, LPARAM lParam )
  444. {
  445. TraceClsFunc( "_OnCommand( " );
  446. TraceMsg( TF_FUNC, "wParam = 0x%08x, lParam = 0x%08x )\n", wParam, lParam );
  447. BOOL fChanged = FALSE;
  448. BOOL fReturn = FALSE;
  449. HWND hwndCtl = (HWND) lParam;
  450. switch ( LOWORD(wParam) ) {
  451. case IDC_C_RESPOND:
  452. if ( HIWORD(wParam) == BN_CLICKED ) {
  453. EnableWindow( GetDlgItem( _hDlg, IDC_C_KNOWNCLIENTS ), Button_GetCheck( hwndCtl ) == BST_CHECKED );
  454. fChanged = TRUE;
  455. }
  456. break;
  457. case IDC_C_KNOWNCLIENTS:
  458. if ( HIWORD(wParam) == BN_CLICKED ) {
  459. fChanged = TRUE;
  460. }
  461. break;
  462. case IDC_B_CLIENTS:
  463. if ( HIWORD(wParam) == BN_CLICKED ) {
  464. HRESULT hr = _DisplayClientsQueryForm( );
  465. if (FAILED(hr)) {
  466. MessageBoxFromHResult( _hDlg, 0, hr );
  467. }
  468. }
  469. break;
  470. case IDC_B_CHECKSERVER:
  471. {
  472. const WCHAR szCommand[] = { L"RISETUP.EXE -check"};
  473. WCHAR szRealCommandLine[MAX_PATH + 7 + 1]; // 7 for ' -check' and 1 for null
  474. STARTUPINFO startupInfo;
  475. PROCESS_INFORMATION pi;
  476. ZeroMemory( &startupInfo, sizeof( startupInfo) );
  477. startupInfo.cb = sizeof( startupInfo );
  478. if (ExpandEnvironmentStrings(szCommand, szRealCommandLine, ARRAYSIZE(szRealCommandLine)) &&
  479. CreateProcess( NULL,
  480. szRealCommandLine,
  481. NULL,
  482. NULL,
  483. TRUE,
  484. NORMAL_PRIORITY_CLASS,
  485. NULL,
  486. NULL,
  487. &startupInfo,
  488. &pi )) {
  489. CloseHandle( pi.hProcess );
  490. CloseHandle( pi.hThread );
  491. } else {
  492. DWORD dwErr = GetLastError( );
  493. MessageBoxFromError( _hDlg, IDS_RISETUP_FAILED_TO_START, dwErr );
  494. }
  495. }
  496. break;
  497. case IDC_B_SERVICE:
  498. if ( HIWORD(wParam) == BN_CLICKED ) {
  499. Assert( _pszSCPDN );
  500. THR( PostADsPropSheet( _pszSCPDN, _pido, _hDlg, FALSE) );
  501. }
  502. break;
  503. }
  504. if ( fChanged ) {
  505. if ( !_fChanged ) {
  506. _fChanged = TRUE;
  507. SendMessage( GetParent( _hDlg ), PSM_CHANGED, (WPARAM)_hDlg, 0 );
  508. }
  509. }
  510. RETURN(fReturn);
  511. }
  512. //
  513. // _ApplyChanges( )
  514. //
  515. HRESULT
  516. THISCLASS::_ApplyChanges( )
  517. {
  518. TraceClsFunc( "_ApplyChanges( )\n" );
  519. if ( !_fChanged )
  520. HRETURN(S_FALSE); // nop
  521. HRESULT hr;
  522. HRESULT hResult = S_OK;
  523. BOOL fOnOff;
  524. HWND hwnd;
  525. LPINTELLIMIRRORSAP pimsap;
  526. hr = THR( _punkService->QueryInterface( IID_IIntelliMirrorSAP, (void**) &pimsap ) );
  527. if (FAILED( hr )) {
  528. goto Error;
  529. }
  530. hwnd = GetDlgItem( _hDlg, IDC_C_RESPOND );
  531. fOnOff = Button_GetCheck( hwnd ) == BST_CHECKED;
  532. hr = THR( pimsap->SetAnswerRequests( fOnOff ) );
  533. if (FAILED( hr ) && hResult == S_OK ) {
  534. hResult = hr;
  535. SetFocus( hwnd );
  536. }
  537. hwnd = GetDlgItem( _hDlg, IDC_C_KNOWNCLIENTS );
  538. fOnOff = Button_GetCheck( hwnd ) == BST_CHECKED;
  539. hr = THR( pimsap->SetAnswerOnlyValidClients( fOnOff ) );
  540. if (FAILED( hr ) && hResult == S_OK ) {
  541. hResult = hr;
  542. SetFocus( hwnd );
  543. }
  544. hr = THR( pimsap->CommitChanges() );
  545. if (FAILED( hr ))
  546. goto Error;
  547. if (FAILED( hResult )) {
  548. MessageBoxFromHResult( NULL, NULL, hResult );
  549. hr = hResult;
  550. }
  551. Cleanup:
  552. if ( pimsap )
  553. pimsap->Release( );
  554. // Tell DSA that someone hit Apply
  555. SendMessage( _hNotify, WM_ADSPROP_NOTIFY_APPLY, !!SUCCEEDED( hr ), 0 );
  556. HRETURN(hr);
  557. Error:
  558. MessageBoxFromHResult( NULL, NULL, hr );
  559. goto Cleanup;
  560. }
  561. //
  562. // _OnNotify( )
  563. //
  564. INT
  565. THISCLASS::_OnNotify(
  566. WPARAM wParam,
  567. LPARAM lParam )
  568. {
  569. TraceClsFunc( "_OnNotify( " );
  570. TraceMsg( TF_FUNC, "wParam = 0x%08x, lParam = 0x%08x )\n", wParam, lParam );
  571. LV_DISPINFO * plvdi = (LV_DISPINFO *) lParam;
  572. switch ( plvdi->hdr.code ) {
  573. case PSN_APPLY:
  574. {
  575. HRESULT hr;
  576. TraceMsg( TF_WM, TEXT("WM_NOTIFY: PSN_APPLY\n"));
  577. hr = _ApplyChanges( );
  578. _fChanged = FALSE;
  579. SetWindowLongPtr( _hDlg, DWLP_MSGRESULT, ( SUCCEEDED(hr) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ));
  580. RETURN(TRUE);
  581. }
  582. break;
  583. default:
  584. break;
  585. }
  586. RETURN(FALSE);
  587. }