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.

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