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.

1004 lines
20 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. //
  5. // CCOMPUTR.CPP - Handles the computer object property pages.
  6. //
  7. #include "pch.h"
  8. #include "client.h"
  9. #include "server.h"
  10. #include "ccomputr.h"
  11. #include "varconv.h"
  12. //
  13. // Begin Class Definitions
  14. //
  15. DEFINE_MODULE("IMADMUI")
  16. DEFINE_THISCLASS("CComputer")
  17. #define THISCLASS CComputer
  18. #define LPTHISCLASS LPCComputer
  19. // ************************************************************************
  20. //
  21. // Constructor / Destructor
  22. //
  23. // ************************************************************************
  24. //
  25. // CreateInstance()
  26. //
  27. LPVOID
  28. CComputer_CreateInstance( void )
  29. {
  30. TraceFunc( "CComputer_CreateInstance()\n" );
  31. LPTHISCLASS lpcc = new THISCLASS( );
  32. if (!lpcc)
  33. RETURN(lpcc);
  34. HRESULT hr = THR( lpcc->Init( ) );
  35. if ( hr )
  36. {
  37. delete lpcc;
  38. RETURN(NULL);
  39. }
  40. RETURN((LPVOID) lpcc);
  41. }
  42. //
  43. // CreateCComputer( )
  44. //
  45. LPVOID
  46. CreateIntelliMirrorClientComputer(
  47. IADs * pads)
  48. {
  49. TraceFunc( "CreateCComputer(" );
  50. TraceMsg( TF_FUNC, "pads = 0x%08x )\n", pads );
  51. HRESULT hr;
  52. LPTHISCLASS lpcc = NULL;
  53. if ( !pads )
  54. {
  55. hr = THR( E_POINTER );
  56. goto Error;
  57. }
  58. lpcc = new THISCLASS( );
  59. if ( !lpcc )
  60. {
  61. hr = THR( E_OUTOFMEMORY );
  62. goto Error;
  63. }
  64. hr = THR( lpcc->Init( ) );
  65. if ( hr )
  66. goto Error;
  67. hr = lpcc->Init2( pads );
  68. if (hr != S_FALSE) {
  69. hr = THR(E_FAIL); // account exists?
  70. goto Error;
  71. }
  72. Cleanup:
  73. RETURN((LPVOID) lpcc);
  74. Error:
  75. if (lpcc) {
  76. delete lpcc;
  77. lpcc = NULL;
  78. }
  79. switch (hr) {
  80. case S_OK:
  81. break;
  82. default:
  83. MessageBoxFromHResult( NULL, IDC_ERROR_CREATINGACCOUNT_TITLE, hr );
  84. break;
  85. }
  86. goto Cleanup;
  87. }
  88. //
  89. // Init2( )
  90. //
  91. STDMETHODIMP
  92. THISCLASS::Init2(
  93. IADs * pads )
  94. {
  95. TraceClsFunc( "Init2( ... )\n" );
  96. HRESULT hr;
  97. _pads = pads;
  98. _pads->AddRef( );
  99. hr = _pads->Get( NETBOOTGUID, &_vGUID );
  100. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  101. goto Cleanup;
  102. hr = _pads->Get( NETBOOTSAP, &_vSCP );
  103. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  104. goto Cleanup;
  105. hr = _pads->Get( NETBOOTMACHINEFILEPATH, &_vMachineFilepath );
  106. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  107. goto Cleanup;
  108. hr = _pads->Get( NETBOOTINITIALIZATION, &_vInitialization );
  109. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  110. goto Cleanup;
  111. if ( _vSCP.vt == VT_EMPTY
  112. || _vGUID.vt == VT_EMPTY
  113. || _vInitialization.vt == VT_EMPTY
  114. || _vMachineFilepath.vt == VT_EMPTY )
  115. {
  116. //
  117. // These must be blank since we are setting the attributes
  118. // of a newly created MAO.
  119. //
  120. hr = S_FALSE;
  121. goto Cleanup;
  122. }
  123. hr = S_OK;
  124. Cleanup:
  125. HRETURN(hr);
  126. }
  127. //
  128. // Constructor
  129. //
  130. THISCLASS::THISCLASS( )
  131. {
  132. TraceClsFunc( "CComputer()\n" );
  133. InterlockIncrement( g_cObjects );
  134. TraceFuncExit();
  135. }
  136. //
  137. // Init()
  138. //
  139. STDMETHODIMP
  140. THISCLASS::Init( )
  141. {
  142. HRESULT hr = S_OK;
  143. TraceClsFunc( "Init()\n" );
  144. // IUnknown stuff
  145. BEGIN_QITABLE_IMP( CComputer, IShellExtInit );
  146. QITABLE_IMP( IShellExtInit );
  147. QITABLE_IMP( IShellPropSheetExt );
  148. QITABLE_IMP( IMAO );
  149. END_QITABLE_IMP( CComputer );
  150. Assert( _cRef == 0);
  151. AddRef( );
  152. hr = CheckClipboardFormats( );
  153. // Private Members
  154. Assert( !_pads );
  155. Assert( !_pDataObj );
  156. VariantInit( &_vGUID );
  157. VariantInit( &_vMachineFilepath );
  158. VariantInit( &_vInitialization );
  159. VariantInit( &_vSCP );
  160. // _InitParams should already be zero'ed.
  161. _InitParams.dwSize = sizeof(_InitParams);
  162. _uMode = MODE_SHELL; // default
  163. HRETURN(hr);
  164. }
  165. //
  166. // Destructor
  167. //
  168. THISCLASS::~THISCLASS( )
  169. {
  170. TraceClsFunc( "~CComputer()\n" );
  171. // Members
  172. if ( _pads )
  173. {
  174. //
  175. // note: we shouldn't commit anything in the destructor -- we can't
  176. // catch failures here. We'll just have to make sure that we
  177. // explicitly commit changes when necessary
  178. //
  179. #if 0
  180. // Commit any changes before we release
  181. THR( _pads->SetInfo( ) );
  182. #endif
  183. _pads->Release( );
  184. }
  185. if ( _pDataObj )
  186. _pDataObj->Release( );
  187. if ( _pszObjectName )
  188. TraceFree( _pszObjectName );
  189. VariantClear( &_vGUID );
  190. VariantClear( &_vMachineFilepath );
  191. VariantClear( &_vInitialization );
  192. VariantClear( &_vSCP );
  193. #if 0 // EricB might be adding an AddRef( ) to this. Until then, don't release.
  194. if ( _InitParams.pDsObj )
  195. _InitParams.pDsObj->Release( );
  196. #endif
  197. InterlockDecrement( g_cObjects );
  198. TraceFuncExit();
  199. };
  200. // ************************************************************************
  201. //
  202. // IUnknown
  203. //
  204. // ************************************************************************
  205. //
  206. // QueryInterface()
  207. //
  208. STDMETHODIMP
  209. THISCLASS::QueryInterface(
  210. REFIID riid,
  211. LPVOID *ppv )
  212. {
  213. TraceClsFunc( "" );
  214. HRESULT hr = ::QueryInterface( this, _QITable, riid, ppv );
  215. // Ugly ugly ulgy... but it works
  216. if ( hr == E_NOINTERFACE && _pDataObj ) {
  217. hr = _pDataObj->QueryInterface( riid, ppv );
  218. }
  219. QIRETURN( hr, riid );
  220. }
  221. //
  222. // AddRef()
  223. //
  224. STDMETHODIMP_(ULONG)
  225. THISCLASS::AddRef( void )
  226. {
  227. TraceClsFunc( "[IUnknown] AddRef( )\n" );
  228. InterlockIncrement( _cRef );
  229. RETURN(_cRef);
  230. }
  231. //
  232. // Release()
  233. //
  234. STDMETHODIMP_(ULONG)
  235. THISCLASS::Release( void )
  236. {
  237. TraceClsFunc( "[IUnknown] Release( )\n" );
  238. InterlockDecrement( _cRef );
  239. if ( _cRef )
  240. RETURN(_cRef);
  241. TraceDo( delete this );
  242. RETURN(0);
  243. }
  244. // ************************************************************************
  245. //
  246. // IShellExtInit
  247. //
  248. // ************************************************************************
  249. //
  250. // Initialize()
  251. //
  252. STDMETHODIMP
  253. THISCLASS::Initialize(
  254. LPCITEMIDLIST pidlFolder,
  255. LPDATAOBJECT lpdobj,
  256. HKEY hkeyProgID )
  257. {
  258. TraceClsFunc( "[IShellExtInit] Initialize( " );
  259. TraceMsg( TF_FUNC, " pidlFolder = 0x%08x, lpdobj = 0x%08x, hkeyProgID = 0x%08x )\n",
  260. pidlFolder, lpdobj, hkeyProgID );
  261. if ( !lpdobj )
  262. RETURN(E_INVALIDARG);
  263. HRESULT hr = S_OK;
  264. FORMATETC fmte;
  265. STGMEDIUM stg = { 0 };
  266. STGMEDIUM stgOptions = { 0 };
  267. LPWSTR pszObjectName;
  268. LPWSTR pszClassName;
  269. LPWSTR pszAttribPrefix;
  270. LPDSOBJECT pDsObject;
  271. LPDSOBJECTNAMES pDsObjectNames;
  272. LPDSDISPLAYSPECOPTIONS pDsDisplayOptions;
  273. BOOL b;
  274. // Hang onto it
  275. _pDataObj = lpdobj;
  276. _pDataObj->AddRef( );
  277. //
  278. // Retrieve the Object Names
  279. //
  280. fmte.cfFormat = (CLIPFORMAT)g_cfDsObjectNames;
  281. fmte.tymed = TYMED_HGLOBAL;
  282. fmte.dwAspect = DVASPECT_CONTENT;
  283. fmte.lindex = -1;
  284. fmte.ptd = 0;
  285. hr = THR( lpdobj->GetData( &fmte, &stg) );
  286. if ( hr )
  287. goto Cleanup;
  288. pDsObjectNames = (LPDSOBJECTNAMES) stg.hGlobal;
  289. Assert( stg.tymed == TYMED_HGLOBAL );
  290. TraceMsg( TF_ALWAYS, "Object's Namespace CLSID: " );
  291. TraceMsgGUID( TF_ALWAYS, pDsObjectNames->clsidNamespace );
  292. TraceMsg( TF_ALWAYS, "\tNumber of Objects: %u \n", pDsObjectNames->cItems );
  293. Assert( pDsObjectNames->cItems == 1 );
  294. pDsObject = (LPDSOBJECT) pDsObjectNames->aObjects;
  295. pszObjectName = (LPWSTR) PtrToByteOffset( pDsObjectNames, pDsObject->offsetName );
  296. pszClassName = (LPWSTR) PtrToByteOffset( pDsObjectNames, pDsObject->offsetClass );
  297. TraceMsg( TF_ALWAYS, "Object Name (Class): %s (%s)\n", pszObjectName, pszClassName );
  298. //
  299. // This must be a "Computer" class
  300. //
  301. if ( StrCmp( pszClassName, DSCOMPUTERCLASSNAME ) )
  302. {
  303. hr = S_FALSE;
  304. goto Error;
  305. }
  306. //
  307. // Retrieve the Display Spec Options
  308. //
  309. fmte.cfFormat = (CLIPFORMAT)g_cfDsDisplaySpecOptions;
  310. fmte.tymed = TYMED_HGLOBAL;
  311. fmte.dwAspect = DVASPECT_CONTENT;
  312. fmte.lindex = -1;
  313. fmte.ptd = 0;
  314. hr = THR( lpdobj->GetData( &fmte, &stgOptions ) );
  315. if ( hr )
  316. goto Cleanup;
  317. pDsDisplayOptions = (LPDSDISPLAYSPECOPTIONS) stgOptions.hGlobal;
  318. Assert( stgOptions.tymed == TYMED_HGLOBAL );
  319. Assert( pDsDisplayOptions->dwSize >= sizeof(DSDISPLAYSPECOPTIONS) );
  320. pszAttribPrefix = (LPWSTR) PtrToByteOffset( pDsDisplayOptions, pDsDisplayOptions->offsetAttribPrefix );
  321. // TraceMsg( TF_ALWAYS, TEXT("Attribute Prefix: %s\n"), pszAttribPrefix );
  322. if ( StrCmpW( pszAttribPrefix, STRING_ADMIN ) == 0 )
  323. {
  324. _uMode = MODE_ADMIN;
  325. }
  326. // else default from Init()
  327. TraceMsg( TF_ALWAYS, TEXT("Mode: %s\n"), _uMode ? TEXT("Admin") : TEXT("Shell") );
  328. ReleaseStgMedium( &stgOptions );
  329. _pszObjectName = TraceStrDup( pszObjectName );
  330. if ( !_pszObjectName )
  331. goto OutOfMemory;
  332. // create the DS notify object
  333. hr = THR( ADsPropCreateNotifyObj( _pDataObj, _pszObjectName, &_hwndNotify ) );
  334. if (FAILED( hr ))
  335. goto Error;
  336. b = ADsPropGetInitInfo( _hwndNotify, &_InitParams );
  337. if ( !b )
  338. {
  339. hr = E_FAIL;
  340. goto Error;
  341. }
  342. hr = THR( _InitParams.hr );
  343. if (FAILED( hr ))
  344. goto Error;
  345. hr = THR( _InitParams.pDsObj->QueryInterface( IID_IADs, (void**) &_pads ) );
  346. if (FAILED( hr ))
  347. goto Error;
  348. //
  349. // Retrieve the attributes
  350. //
  351. hr = _pads->Get( NETBOOTGUID, &_vGUID );
  352. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  353. goto Error;
  354. hr = _pads->Get( NETBOOTSAP, &_vSCP );
  355. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  356. goto Error;
  357. //
  358. // Check to see if this is an MAO that we need to add
  359. // ourselves to.
  360. //
  361. if ( _vSCP.vt == VT_EMPTY && _vGUID.vt == VT_EMPTY )
  362. {
  363. //
  364. // This MAO is not a IntelliMirror client or server.
  365. //
  366. hr = S_FALSE;
  367. goto Error;
  368. }
  369. hr = _pads->Get( NETBOOTMACHINEFILEPATH, &_vMachineFilepath );
  370. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  371. goto Error;
  372. hr = _pads->Get( NETBOOTINITIALIZATION, &_vInitialization );
  373. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  374. goto Error;
  375. //
  376. // Fix HR
  377. //
  378. if ( hr == E_ADS_PROPERTY_NOT_FOUND )
  379. {
  380. hr = S_OK;
  381. }
  382. Cleanup:
  383. ReleaseStgMedium( &stg );
  384. HRETURN(hr);
  385. OutOfMemory:
  386. hr = E_OUTOFMEMORY;
  387. // fall thru
  388. Error:
  389. switch (hr) {
  390. case S_OK:
  391. break;
  392. case S_FALSE:
  393. hr = E_FAIL; // don't show page
  394. break;
  395. default:
  396. MessageBoxFromHResult( NULL, IDS_ERROR_READINGCOMPUTERACCOUNT, hr );
  397. break;
  398. }
  399. goto Cleanup;
  400. }
  401. // ************************************************************************
  402. //
  403. // IShellPropSheetExt
  404. //
  405. // ************************************************************************
  406. //
  407. // AddPages()
  408. //
  409. STDMETHODIMP
  410. THISCLASS::AddPages(
  411. LPFNADDPROPSHEETPAGE lpfnAddPage,
  412. LPARAM lParam)
  413. {
  414. TraceClsFunc( "[IShellPropSheetExt] AddPages( )\n" );
  415. if ( !lpfnAddPage )
  416. HRETURN(E_POINTER);
  417. HRESULT hr = S_OK;
  418. BOOL fServer;
  419. hr = THR( IsServer( &fServer ) );
  420. if (FAILED( hr ))
  421. goto Error;
  422. if ( fServer )
  423. {
  424. //
  425. // Add the "IntelliMirror" tab for servers
  426. //
  427. hr = THR( ::AddPagesEx( NULL,
  428. CServerTab_CreateInstance,
  429. lpfnAddPage,
  430. lParam,
  431. (LPUNKNOWN) (IShellExtInit*) this ) );
  432. if (FAILED( hr ))
  433. goto Error;
  434. }
  435. else
  436. {
  437. //
  438. // Add the "IntelliMirror" tab for clients
  439. //
  440. hr = THR( ::AddPagesEx( NULL,
  441. CClientTab_CreateInstance,
  442. lpfnAddPage,
  443. lParam,
  444. (LPUNKNOWN) (IShellExtInit*) this ) );
  445. if (FAILED( hr ))
  446. goto Error;
  447. }
  448. // Release our count on it.
  449. // _pDataObj->Release( );
  450. // _pDataObj = NULL;
  451. Error:
  452. HRETURN(hr);
  453. }
  454. //
  455. // ReplacePage()
  456. //
  457. STDMETHODIMP
  458. THISCLASS::ReplacePage(
  459. UINT uPageID,
  460. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  461. LPARAM lParam )
  462. {
  463. TraceClsFunc( "[IShellPropSheetExt] ReplacePage( ) *** NOT_IMPLEMENTED ***\n" );
  464. RETURN(E_NOTIMPL);
  465. }
  466. // ************************************************************************
  467. //
  468. // IMAO (Private)
  469. //
  470. // ************************************************************************
  471. //
  472. // CommitChanges( )
  473. //
  474. STDMETHODIMP
  475. THISCLASS::CommitChanges( void )
  476. {
  477. TraceClsFunc("[IMAO] CommitChanges( )\n" );
  478. HRESULT hr = THR( _pads->SetInfo( ) );
  479. HRETURN(hr);
  480. }
  481. //
  482. // IsAdmin( )
  483. //
  484. STDMETHODIMP
  485. THISCLASS::IsAdmin(
  486. BOOL * fAdmin )
  487. {
  488. TraceClsFunc( "[IMAO] IsAdmin( )\n" );
  489. if ( !fAdmin )
  490. HRETURN( E_INVALIDARG );
  491. HRESULT hr = S_OK;
  492. *fAdmin = (_uMode == MODE_ADMIN);
  493. HRETURN(hr);
  494. }
  495. //
  496. // IsServer( )
  497. //
  498. STDMETHODIMP
  499. THISCLASS::IsServer(
  500. BOOL * fServer )
  501. {
  502. TraceClsFunc( "[IMAO] IsServer( )\n" );
  503. if ( !fServer )
  504. HRETURN( E_INVALIDARG );
  505. HRESULT hr = S_OK;
  506. *fServer = (_vSCP.vt != VT_EMPTY);
  507. HRETURN(hr);
  508. }
  509. //
  510. // IsClient( )
  511. //
  512. STDMETHODIMP
  513. THISCLASS::IsClient(
  514. BOOL * fClient )
  515. {
  516. TraceClsFunc( "[IMAO] IsClient( )\n" );
  517. if ( !fClient)
  518. HRETURN( E_INVALIDARG );
  519. HRESULT hr = S_OK;
  520. *fClient = (_vGUID.vt != VT_EMPTY ) |
  521. (_vMachineFilepath.vt != VT_EMPTY ) |
  522. (_vInitialization.vt != VT_EMPTY );
  523. HRETURN(hr);
  524. }
  525. //
  526. // SetServerName( )
  527. //
  528. STDMETHODIMP
  529. THISCLASS::SetServerName(
  530. LPWSTR pszName )
  531. {
  532. TraceClsFunc( "[IMAO] SetServerName( " );
  533. TraceMsg( TF_FUNC, "pszName = %s )\n", pszName );
  534. HRESULT hr = S_OK;
  535. LPWSTR pszFilepath = NULL;
  536. VARIANT var;
  537. if ( V_VT( &_vMachineFilepath ) == VT_BSTR )
  538. {
  539. pszFilepath = StrChr( _vMachineFilepath.bstrVal, L'\\' );
  540. }
  541. //
  542. // Create variant with new Server\Filepath string
  543. //
  544. VariantInit( &var );
  545. if ( !pszName || pszName[0] == L'\0' ) {
  546. hr = THR( _pads->PutEx( ADS_PROPERTY_CLEAR, NETBOOTMACHINEFILEPATH, var ) );
  547. DebugMsg( "Cleared MachineFilepath\n" );
  548. } else {
  549. if ( pszFilepath ) {
  550. WCHAR szBuf[ DNS_MAX_NAME_LENGTH + 1 + 128 /* DHCP BOOTP PATH */ + 1 ];
  551. wsprintf( szBuf, L"%s\\%s", pszName, pszFilepath );
  552. PackStringToVariant( &var, szBuf);
  553. DebugMsg( "Set MachineFilepath to %s\n", szBuf );
  554. } else {
  555. hr = PackStringToVariant( &var, pszName );
  556. if ( FAILED( hr ) )
  557. goto Cleanup;
  558. DebugMsg( "Set MachineFilepath to %s\n", pszName );
  559. }
  560. //
  561. // Set the property
  562. //
  563. hr = THR( _pads->Put( NETBOOTMACHINEFILEPATH, var ) );
  564. }
  565. if (FAILED( hr ))
  566. goto Cleanup;
  567. //
  568. // Release the old variant and shallow copy the new one to the
  569. // MachineFilepath variant. No need to release the "var".
  570. //
  571. VariantClear( &_vMachineFilepath );
  572. _vMachineFilepath = var;
  573. VariantInit( &var ); // don't free
  574. Cleanup:
  575. VariantClear( &var );
  576. HRETURN(hr);
  577. }
  578. //
  579. // GetServerName( )
  580. //
  581. STDMETHODIMP
  582. THISCLASS::GetServerName(
  583. LPWSTR * ppszName )
  584. {
  585. TraceClsFunc( "[IMAO] GetServerName( " );
  586. TraceMsg( TF_FUNC, "*ppszName = 0x%08x )\n", *ppszName );
  587. HRESULT hr = S_OK;
  588. LPWSTR psz = _vMachineFilepath.bstrVal;
  589. if ( !ppszName )
  590. HRETURN( E_INVALIDARG );
  591. *ppszName = NULL;
  592. if ( _vMachineFilepath.vt != VT_BSTR || _vMachineFilepath.bstrVal == NULL )
  593. HRETURN( E_ADS_PROPERTY_NOT_FOUND );
  594. if ( *psz == L'\0' ) {
  595. hr = S_FALSE;
  596. } else {
  597. // Find the Filepath
  598. while ( *psz && *psz != L'\\' )
  599. psz++;
  600. *psz = L'\0';
  601. *ppszName = (LPWSTR) TraceStrDup( _vMachineFilepath.bstrVal );
  602. if ( !*ppszName )
  603. hr = E_OUTOFMEMORY;
  604. }
  605. HRETURN(hr);
  606. }
  607. //
  608. // SetGUID( )
  609. //
  610. STDMETHODIMP
  611. THISCLASS::SetGUID(
  612. LPWSTR pszGUID )
  613. {
  614. TraceClsFunc("[IMAO] SetGUID( )\n" );
  615. HRESULT hr = E_FAIL;
  616. BYTE uGUID[16];
  617. VARIANT var;
  618. VariantInit( &var );
  619. if ( !pszGUID ) {
  620. hr = THR( _pads->PutEx( ADS_PROPERTY_CLEAR, NETBOOTGUID, var ) );
  621. if (FAILED( hr ))
  622. goto Cleanup;
  623. VariantClear( &_vGUID );
  624. } else {
  625. if ( ValidateGuid(pszGUID,uGUID,NULL) == S_OK ) {
  626. //
  627. // Put it into a variant
  628. //
  629. PackBytesToVariant( &var, uGUID, 16 );
  630. VariantClear( &_vGUID );
  631. _vGUID = var;
  632. hr = THR( _pads->Put( NETBOOTGUID, _vGUID ) );
  633. if (FAILED( hr ))
  634. goto Cleanup;
  635. }
  636. else // I don't know what it is.
  637. {
  638. Assert( FALSE );
  639. VariantClear( &var );
  640. hr = E_INVALIDARG;
  641. goto Cleanup;
  642. }
  643. }
  644. Cleanup:
  645. HRETURN(hr);
  646. }
  647. //
  648. // GetGUID( )
  649. //
  650. STDMETHODIMP
  651. THISCLASS::GetGUID(
  652. IN LPWSTR * ppszGUID OPTIONAL,
  653. IN LPBYTE uGUID OPTIONAL )
  654. {
  655. TraceClsFunc("[IMAO] GetGUID( )\n" );
  656. HRESULT hr = S_OK;
  657. LPBYTE ptr = NULL;
  658. VARIANT var = _vGUID;
  659. LONG Length;
  660. if ( ppszGUID != NULL ) {
  661. *ppszGUID = NULL;
  662. }
  663. if ( var.vt == VT_EMPTY )
  664. HRETURN( HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
  665. if ( SafeArrayGetDim( var.parray ) != 1 )
  666. HRETURN( HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
  667. hr = THR( SafeArrayGetUBound( var.parray, 1, &Length ) );
  668. if (FAILED( hr ))
  669. goto Cleanup;
  670. Assert( Length == 15 );
  671. if ( Length != 15 )
  672. {
  673. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  674. goto Cleanup;
  675. }
  676. hr = THR( SafeArrayAccessData( var.parray, (LPVOID*)&ptr ) );
  677. if (FAILED( hr ))
  678. goto Cleanup;
  679. if ( uGUID != NULL ) {
  680. memcpy( uGUID, ptr, 16 * sizeof(BYTE) );
  681. }
  682. if ( ppszGUID != NULL ) {
  683. *ppszGUID = PrettyPrintGuid( ptr );
  684. if ( !*ppszGUID )
  685. {
  686. hr = E_OUTOFMEMORY;
  687. goto Cleanup;
  688. }
  689. }
  690. hr = S_OK;
  691. Cleanup:
  692. if ( ptr )
  693. SafeArrayUnaccessData( var.parray );
  694. HRETURN(hr);
  695. }
  696. //
  697. // GetSAP( )
  698. //
  699. STDMETHODIMP
  700. THISCLASS::GetSAP(
  701. LPVOID *punk )
  702. {
  703. TraceClsFunc( "[IMAO] GetSAP( punk )\n" );
  704. HRESULT hr = S_OK;
  705. LPWSTR pszDN = NULL;
  706. *punk = NULL;
  707. if ( _vSCP.vt != VT_BSTR ) {
  708. hr = E_ADS_PROPERTY_NOT_FOUND;
  709. goto Cleanup;
  710. }
  711. Assert( _vSCP.vt == VT_BSTR );
  712. Assert( _vSCP.bstrVal );
  713. // pre-pend the "LDAP://server/" from our DN
  714. hr = _FixObjectPath( V_BSTR( &_vSCP ), &pszDN );
  715. if (FAILED( hr ))
  716. goto Cleanup;
  717. // Bind to the MAO in the DS
  718. hr = THR( ADsGetObject( pszDN, IID_IADs, punk ) );
  719. if (FAILED( hr ))
  720. goto Cleanup;
  721. Cleanup:
  722. if ( pszDN )
  723. TraceFree( pszDN );
  724. HRETURN(hr);
  725. }
  726. //
  727. // _FixObjectPath( )
  728. //
  729. HRESULT
  730. THISCLASS::_FixObjectPath( LPWSTR pszOldObjectPath, LPWSTR *ppszNewObjectPath )
  731. {
  732. TraceClsFunc( "_FixObjectPath()\n" );
  733. if ( !ppszNewObjectPath )
  734. HRETURN(E_POINTER);
  735. HRESULT hr;
  736. LPWSTR psz = NULL;
  737. *ppszNewObjectPath = NULL;
  738. // Try to parse the string to connect to the same server as the DSADMIN
  739. if ( _pszObjectName && StrCmpNI( _pszObjectName, L"LDAP://", 7 ) == 0 )
  740. {
  741. psz = _pszObjectName + 7;
  742. }
  743. else if ( _pszObjectName && StrCmpNI( _pszObjectName, L"GC://", 5 ) == 0 )
  744. {
  745. psz = _pszObjectName + 5;
  746. }
  747. if ( psz )
  748. {
  749. psz = StrChr( psz, L'/' );
  750. psz++;
  751. INT_PTR uLen = psz - _pszObjectName;
  752. // get a chunk of memory, pre-zero'ed
  753. psz = TraceAllocString( LPTR, (size_t) uLen + wcslen( pszOldObjectPath ) + 1 );
  754. if ( !psz )
  755. goto OutOfMemory;
  756. MoveMemory( psz, _pszObjectName, uLen * sizeof(WCHAR) );
  757. wcscat( psz, pszOldObjectPath);
  758. *ppszNewObjectPath = psz;
  759. }
  760. else
  761. { // find another server
  762. hr = THR( LDAPPrefix( pszOldObjectPath, ppszNewObjectPath ) );
  763. }
  764. Assert( ppszNewObjectPath || hr != S_OK );
  765. HRETURN(hr);
  766. OutOfMemory:
  767. HRETURN(E_OUTOFMEMORY);
  768. }
  769. //
  770. // GetDataObject( )
  771. //
  772. STDMETHODIMP
  773. THISCLASS::GetDataObject(
  774. LPDATAOBJECT * pDataObj
  775. )
  776. {
  777. TraceClsFunc( "GetDataObject( ... )\n ");
  778. if ( !pDataObj )
  779. HRETURN(E_POINTER);
  780. *pDataObj = _pDataObj;
  781. _pDataObj->AddRef( );
  782. HRETURN(S_OK);
  783. }
  784. //
  785. //
  786. //
  787. STDMETHODIMP
  788. THISCLASS::GetNotifyWindow(
  789. HWND *phNotifyObj
  790. )
  791. {
  792. TraceClsFunc( "GetNotifyWindow( ... )\n" );
  793. if ( !phNotifyObj )
  794. HRETURN(E_POINTER);
  795. *phNotifyObj = _hwndNotify;
  796. HRETURN(S_OK);
  797. }