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.

1620 lines
40 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: oleds.odl
  7. //
  8. // Contents: Top level odl file for the ADs project
  9. //
  10. // History: 11-1-95 krishnag Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "winnt.hxx"
  14. #pragma hdrstop
  15. // Class CWinNTComputer
  16. DEFINE_IDispatch_ExtMgr_Implementation(CWinNTComputer)
  17. DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTComputer)
  18. DEFINE_IADs_TempImplementation(CWinNTComputer)
  19. DEFINE_IADs_PutGetImplementation(CWinNTComputer, ComputerClass,gdwComputerTableSize)
  20. DEFINE_IADsPropertyList_Implementation(CWinNTComputer,ComputerClass,gdwComputerTableSize)
  21. CWinNTComputer::CWinNTComputer():
  22. _pDispMgr(NULL),
  23. _pExtMgr(NULL),
  24. _pPropertyCache(NULL),
  25. _DomainName(NULL),
  26. _fCredentialsBound(FALSE),
  27. _hrBindingResult(S_OK),
  28. _fNoWKSTA(FALSE)
  29. {
  30. VariantInit(&_vFilter);
  31. }
  32. HRESULT
  33. CWinNTComputer::CreateComputer(
  34. BSTR Parent,
  35. BSTR DomainName,
  36. BSTR ComputerName,
  37. DWORD dwObjectState,
  38. REFIID riid,
  39. CWinNTCredentials& Credentials,
  40. void **ppvObj
  41. )
  42. {
  43. CWinNTComputer FAR * pComputer = NULL;
  44. HRESULT hr = S_OK;
  45. hr = AllocateComputerObject(&pComputer);
  46. BAIL_ON_FAILURE(hr);
  47. ADsAssert(pComputer->_pDispMgr);
  48. hr = pComputer->InitializeCoreObject(
  49. Parent,
  50. ComputerName,
  51. COMPUTER_CLASS_NAME,
  52. COMPUTER_SCHEMA_NAME,
  53. CLSID_WinNTComputer,
  54. dwObjectState
  55. );
  56. BAIL_ON_FAILURE(hr);
  57. hr = ADsAllocString( DomainName, &pComputer->_DomainName);
  58. BAIL_ON_FAILURE(hr);
  59. if (DomainName == NULL) {
  60. pComputer->_fNoWKSTA = TRUE;
  61. }
  62. //
  63. // The computer is a special case for using credentials. If it is
  64. // created from a Domain object, the credentials will have the server
  65. // name of the Domain's DC. So when we go to RefServer the computer
  66. // object, it has a different machine name, which should ordinarily fail.
  67. // We obviously don't want that, so we tell RefServer to allow a change
  68. // of server names.
  69. //
  70. // We also don't want to try to bind to each computer in a domain, since
  71. // most computers won't actually be examined in detail. So we don't
  72. // RefServer until we perform an operation on this object.
  73. //
  74. pComputer->_Credentials = Credentials;
  75. //
  76. // Load ext mgr and extensions
  77. //
  78. hr = ADSILoadExtensionManager(
  79. COMPUTER_CLASS_NAME,
  80. (IADsComputer *) pComputer,
  81. pComputer->_pDispMgr,
  82. Credentials,
  83. &pComputer->_pExtMgr
  84. );
  85. BAIL_ON_FAILURE(hr);
  86. ADsAssert(pComputer->_pExtMgr);
  87. // check if the call is from UMI
  88. if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
  89. //
  90. // we do not pass riid to InitUmiObject below. This is because UMI object
  91. // does not support IDispatch. There are several places in ADSI code where
  92. // riid passed into this function is defaulted to IID_IDispatch -
  93. // IADsContainer::Create for example. To handle these cases, we always
  94. // request IID_IUnknown from the UMI object. Subsequent code within UMI
  95. // will QI for the appropriate interface.
  96. //
  97. if(2 == pComputer->_dwNumComponents) {
  98. pComputer->_CompClasses[0] = L"Domain";
  99. pComputer->_CompClasses[1] = L"Computer";
  100. }
  101. else if(1 == pComputer->_dwNumComponents) {
  102. pComputer->_CompClasses[0] = L"Computer";
  103. }
  104. else
  105. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  106. hr = pComputer->InitUmiObject(
  107. pComputer->_Credentials,
  108. ComputerClass,
  109. gdwComputerTableSize,
  110. pComputer->_pPropertyCache,
  111. (IUnknown *)(INonDelegatingUnknown *) pComputer,
  112. pComputer->_pExtMgr,
  113. IID_IUnknown,
  114. ppvObj
  115. );
  116. BAIL_ON_FAILURE(hr);
  117. //
  118. // UMI object was created and the interface was obtained successfully.
  119. // UMI object now has a reference to the inner unknown of IADs, since
  120. // the call to Release() below is not going to be made in this case.
  121. //
  122. RRETURN(hr);
  123. }
  124. hr = pComputer->QueryInterface(riid, ppvObj);
  125. BAIL_ON_FAILURE(hr);
  126. pComputer->Release();
  127. RRETURN(hr);
  128. error:
  129. delete pComputer;
  130. RRETURN_EXP_IF_ERR(hr);
  131. }
  132. CWinNTComputer::~CWinNTComputer( )
  133. {
  134. VariantClear(&_vFilter);
  135. if (_DomainName) {
  136. ADsFreeString(_DomainName);
  137. }
  138. delete _pExtMgr; // created last, destroyed first
  139. delete _pDispMgr;
  140. delete _pPropertyCache;
  141. }
  142. //----------------------------------------------------------------------------
  143. // Function: QueryInterface
  144. //
  145. // Synopsis: If this object is aggregated within another object, then
  146. // all calls will delegate to the outer object. Otherwise, the
  147. // non-delegating QI is called
  148. //
  149. // Arguments:
  150. //
  151. // iid interface requested
  152. // ppInterface Returns pointer to interface requested. NULL if interface
  153. // is not supported.
  154. //
  155. // Returns: S_OK on success. Error code otherwise.
  156. //
  157. // Modifies: *ppInterface to return interface pointer
  158. //
  159. //----------------------------------------------------------------------------
  160. STDMETHODIMP CWinNTComputer::QueryInterface(
  161. REFIID iid,
  162. LPVOID *ppInterface
  163. )
  164. {
  165. if(_pUnkOuter != NULL)
  166. RRETURN(_pUnkOuter->QueryInterface(
  167. iid,
  168. ppInterface
  169. ));
  170. RRETURN(NonDelegatingQueryInterface(
  171. iid,
  172. ppInterface
  173. ));
  174. }
  175. //----------------------------------------------------------------------------
  176. // Function: AddRef
  177. //
  178. // Synopsis: IUnknown::AddRef. If this object is aggregated within
  179. // another, all calls will delegate to the outer object.
  180. // Otherwise, the non-delegating AddRef is called
  181. //
  182. // Arguments:
  183. //
  184. // None
  185. //
  186. // Returns: New reference count
  187. //
  188. // Modifies: Nothing
  189. //
  190. //----------------------------------------------------------------------------
  191. STDMETHODIMP_(ULONG) CWinNTComputer::AddRef(void)
  192. {
  193. if(_pUnkOuter != NULL)
  194. RRETURN(_pUnkOuter->AddRef());
  195. RRETURN(NonDelegatingAddRef());
  196. }
  197. //----------------------------------------------------------------------------
  198. // Function: Release
  199. //
  200. // Synopsis: IUnknown::Release. If this object is aggregated within
  201. // another, all calls will delegate to the outer object.
  202. // Otherwise, the non-delegating Release is called
  203. //
  204. // Arguments:
  205. //
  206. // None
  207. //
  208. // Returns: New reference count
  209. //
  210. // Modifies: Nothing
  211. //
  212. //----------------------------------------------------------------------------
  213. STDMETHODIMP_(ULONG) CWinNTComputer::Release(void)
  214. {
  215. if(_pUnkOuter != NULL)
  216. RRETURN(_pUnkOuter->Release());
  217. RRETURN(NonDelegatingRelease());
  218. }
  219. //----------------------------------------------------------------------------
  220. STDMETHODIMP
  221. CWinNTComputer::NonDelegatingQueryInterface(
  222. REFIID iid,
  223. LPVOID FAR* ppv
  224. )
  225. {
  226. HRESULT hr = S_OK;
  227. if (ppv == NULL) {
  228. RRETURN(E_POINTER);
  229. }
  230. if (IsEqualIID(iid, IID_IUnknown))
  231. {
  232. *ppv = (IADsComputer FAR *) this;
  233. }
  234. else if (IsEqualIID(iid, IID_IADsComputer))
  235. {
  236. *ppv = (IADsComputer FAR *) this;
  237. }
  238. else if (IsEqualIID(iid, IID_IADsComputerOperations))
  239. {
  240. *ppv = (IADsComputerOperations FAR *) this;
  241. }
  242. else if (IsEqualIID(iid, IID_IADsContainer))
  243. {
  244. *ppv = (IADsContainer FAR *) this;
  245. }
  246. else if (IsEqualIID(iid, IID_IADsPropertyList))
  247. {
  248. *ppv = (IADsPropertyList FAR *) this;
  249. }
  250. else if (IsEqualIID(iid, IID_IADs))
  251. {
  252. *ppv = (IADsComputer FAR *) this;
  253. }
  254. else if (IsEqualIID(iid, IID_IDispatch))
  255. {
  256. *ppv = (IADsComputer FAR *) this;
  257. }
  258. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  259. {
  260. *ppv = (ISupportErrorInfo FAR *) this;
  261. }
  262. else if( (_pDispatch != NULL) &&
  263. IsEqualIID(iid, IID_IADsExtension) )
  264. {
  265. *ppv = (IADsExtension *) this;
  266. }
  267. else if (_pExtMgr)
  268. {
  269. RRETURN( _pExtMgr->QueryInterface(iid, ppv));
  270. }
  271. else
  272. {
  273. *ppv = NULL;
  274. return E_NOINTERFACE;
  275. }
  276. AddRef();
  277. return NOERROR;
  278. }
  279. HRESULT
  280. CWinNTComputer::InterfaceSupportsErrorInfo(
  281. THIS_ REFIID riid
  282. )
  283. {
  284. if (IsEqualIID(riid, IID_IADs) ||
  285. IsEqualIID(riid, IID_IADsComputer) ||
  286. IsEqualIID(riid, IID_IADsComputerOperations) ||
  287. IsEqualIID(riid, IID_IADsContainer) ||
  288. IsEqualIID(riid, IID_IADsPropertyList)) {
  289. RRETURN(S_OK);
  290. } else {
  291. RRETURN(S_FALSE);
  292. }
  293. }
  294. HRESULT
  295. CWinNTComputer::RefCredentials()
  296. {
  297. if (!_fCredentialsBound)
  298. {
  299. //
  300. // Only try it once, regardless of whether we succeed.
  301. //
  302. _fCredentialsBound = TRUE;
  303. //
  304. // Also let us rebind to a different server (the TRUE flag).
  305. //
  306. _hrBindingResult = _Credentials.RefServer(_Name, TRUE);
  307. }
  308. //
  309. // We also want to return the same value on each call; if we failed to
  310. // bind, this object shouldn't be allowed to do anything.
  311. //
  312. RRETURN_EXP_IF_ERR(_hrBindingResult);
  313. }
  314. /* IADs methods */
  315. STDMETHODIMP
  316. CWinNTComputer::SetInfo(THIS)
  317. {
  318. HRESULT hr = S_OK;
  319. NET_API_STATUS nasStatus;
  320. WCHAR szHostServerName[MAX_PATH];
  321. // We should ref the credentials only if the computer exists
  322. // otherwise the call will fail.
  323. if (GetObjectState() != ADS_OBJECT_UNBOUND) {
  324. BAIL_ON_FAILURE(hr = RefCredentials());
  325. }
  326. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  327. hr = WinNTGetCachedDCName(
  328. _DomainName,
  329. szHostServerName,
  330. _Credentials.GetFlags()
  331. );
  332. BAIL_ON_FAILURE(hr);
  333. hr = WinNTCreateComputer(
  334. (szHostServerName + 2),
  335. _Name
  336. );
  337. BAIL_ON_FAILURE(hr);
  338. SetObjectState(ADS_OBJECT_BOUND);
  339. }else {
  340. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  341. }
  342. if(SUCCEEDED(hr))
  343. _pPropertyCache->ClearModifiedFlags();
  344. error:
  345. RRETURN_EXP_IF_ERR(hr);
  346. }
  347. STDMETHODIMP
  348. CWinNTComputer::GetInfo(THIS)
  349. {
  350. _pPropertyCache->flushpropcache();
  351. RRETURN(GetInfo(4, TRUE));
  352. }
  353. STDMETHODIMP
  354. CWinNTComputer::ImplicitGetInfo(THIS)
  355. {
  356. RRETURN(GetInfo(4, FALSE));
  357. }
  358. /* IADsContainer methods */
  359. STDMETHODIMP
  360. CWinNTComputer::get_Count(long FAR* retval)
  361. {
  362. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  363. }
  364. STDMETHODIMP
  365. CWinNTComputer::get_Filter(THIS_ VARIANT FAR* pVar)
  366. {
  367. HRESULT hr;
  368. VariantInit(pVar);
  369. hr = VariantCopy(pVar, &_vFilter);
  370. RRETURN_EXP_IF_ERR(hr);
  371. }
  372. STDMETHODIMP
  373. CWinNTComputer::put_Filter(THIS_ VARIANT Var)
  374. {
  375. HRESULT hr;
  376. hr = VariantCopy(&_vFilter, &Var);
  377. RRETURN_EXP_IF_ERR(hr);
  378. }
  379. STDMETHODIMP
  380. CWinNTComputer::put_Hints(THIS_ VARIANT Var)
  381. {
  382. RRETURN_EXP_IF_ERR( E_NOTIMPL);
  383. }
  384. STDMETHODIMP
  385. CWinNTComputer::get_Hints(THIS_ VARIANT FAR* pVar)
  386. {
  387. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  388. }
  389. STDMETHODIMP
  390. CWinNTComputer::GetObject(
  391. THIS_ BSTR ClassName,
  392. BSTR RelativeName,
  393. IDispatch * FAR* ppObject
  394. )
  395. {
  396. WCHAR szBuffer[MAX_PATH];
  397. DWORD dwLength = 0;
  398. HRESULT hr = S_OK;
  399. if (!RelativeName || !*RelativeName) {
  400. RRETURN_EXP_IF_ERR(E_ADS_UNKNOWN_OBJECT);
  401. }
  402. // Make sure we have proper credentials.
  403. BAIL_ON_FAILURE(hr = RefCredentials());
  404. //
  405. // Length of ADsPath, the relative name and
  406. // +2 for / and \0
  407. //
  408. dwLength = wcslen(_ADsPath) + wcslen(RelativeName) + 2;
  409. if ( dwLength > MAX_PATH) {
  410. RRETURN(hr = E_ADS_BAD_PARAMETER);
  411. }
  412. wcscpy(szBuffer, _ADsPath);
  413. wcscat(szBuffer, L"/");
  414. wcscat(szBuffer, RelativeName);
  415. if (ClassName) {
  416. //
  417. // +1 for the ",".
  418. //
  419. dwLength += wcslen(ClassName) + 1;
  420. //
  421. // See if this will cause a buffer overflow.
  422. //
  423. if (dwLength > MAX_PATH) {
  424. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  425. }
  426. wcscat(szBuffer,L",");
  427. wcscat(szBuffer, ClassName);
  428. }
  429. hr = ::GetObject(
  430. szBuffer,
  431. (LPVOID *)ppObject,
  432. _Credentials
  433. );
  434. BAIL_ON_FAILURE(hr);
  435. error:
  436. RRETURN_EXP_IF_ERR(hr);
  437. }
  438. STDMETHODIMP
  439. CWinNTComputer::get__NewEnum(THIS_ IUnknown * FAR* retval)
  440. {
  441. HRESULT hr;
  442. IUnknown FAR* punkEnum=NULL;
  443. IEnumVARIANT * penum = NULL;
  444. *retval = NULL;
  445. // Make sure we have proper credentials.
  446. BAIL_ON_FAILURE(hr = RefCredentials());
  447. hr = CWinNTComputerEnum::Create(
  448. (CWinNTComputerEnum **)&penum,
  449. _ADsPath,
  450. _DomainName,
  451. _Name,
  452. _vFilter,
  453. _Credentials
  454. );
  455. BAIL_ON_FAILURE(hr);
  456. hr = penum->QueryInterface(
  457. IID_IUnknown,
  458. (VOID FAR* FAR*)retval
  459. );
  460. BAIL_ON_FAILURE(hr);
  461. if (penum) {
  462. penum->Release();
  463. }
  464. RRETURN(NOERROR);
  465. error:
  466. if (penum) {
  467. delete penum;
  468. }
  469. RRETURN_EXP_IF_ERR(hr);
  470. }
  471. STDMETHODIMP
  472. CWinNTComputer::Create(
  473. THIS_ BSTR ClassName,
  474. BSTR RelativeName,
  475. IDispatch * FAR* ppObject
  476. )
  477. {
  478. ULONG ObjectType = 0;
  479. HRESULT hr;
  480. POBJECTINFO pObjectInfo = NULL;
  481. // Make sure we have proper credentials.
  482. BAIL_ON_FAILURE(hr = RefCredentials());
  483. hr = GetObjectType(gpFilters,
  484. gdwMaxFilters,
  485. ClassName,
  486. (PDWORD)&ObjectType
  487. );
  488. BAIL_ON_FAILURE(hr);
  489. hr = BuildObjectInfo(_ADsPath,
  490. RelativeName,
  491. &pObjectInfo
  492. );
  493. BAIL_ON_FAILURE(hr);
  494. switch (ObjectType) {
  495. case WINNT_USER_ID:
  496. hr = CWinNTUser::CreateUser(_ADsPath,
  497. WINNT_COMPUTER_ID,
  498. _DomainName,
  499. _Name,
  500. RelativeName,
  501. ADS_OBJECT_UNBOUND,
  502. IID_IDispatch,
  503. _Credentials,
  504. (void **)ppObject
  505. );
  506. break;
  507. case WINNT_PRINTER_ID:
  508. hr = CWinNTPrintQueue::CreatePrintQueue(_ADsPath,
  509. WINNT_COMPUTER_ID,
  510. pObjectInfo->ComponentArray[0],
  511. pObjectInfo->ComponentArray[1],
  512. RelativeName,
  513. ADS_OBJECT_UNBOUND,
  514. IID_IDispatch,
  515. _Credentials,
  516. (void**)ppObject
  517. );
  518. break;
  519. //
  520. // default "group" to local group in computer container for backward
  521. // compatiblity
  522. //
  523. case WINNT_GROUP_ID:
  524. hr = CWinNTGroup::CreateGroup(
  525. _ADsPath,
  526. WINNT_COMPUTER_ID,
  527. _DomainName,
  528. _Name,
  529. RelativeName,
  530. WINNT_GROUP_LOCAL,
  531. ADS_OBJECT_UNBOUND,
  532. IID_IDispatch,
  533. _Credentials,
  534. (void **)ppObject
  535. );
  536. break;
  537. case WINNT_SERVICE_ID:
  538. hr = CWinNTService::Create(_ADsPath,
  539. pObjectInfo->ComponentArray[0],
  540. pObjectInfo->ComponentArray[1],
  541. RelativeName,
  542. ADS_OBJECT_UNBOUND,
  543. IID_IDispatch,
  544. _Credentials,
  545. (void**)ppObject
  546. );
  547. break;
  548. default:
  549. hr = E_ADS_UNKNOWN_OBJECT;
  550. break;
  551. }
  552. BAIL_ON_FAILURE(hr);
  553. error:
  554. if (pObjectInfo) {
  555. FreeObjectInfo(pObjectInfo);
  556. }
  557. RRETURN_EXP_IF_ERR(hr);
  558. }
  559. STDMETHODIMP
  560. CWinNTComputer::Delete(
  561. BSTR bstrClassName,
  562. BSTR bstrSourceName
  563. )
  564. {
  565. ULONG ObjectType = 0;
  566. POBJECTINFO pObjectInfo = NULL;
  567. BOOL fStatus = FALSE;
  568. HRESULT hr = S_OK;
  569. WCHAR szUncServerName[MAX_PATH];
  570. // Check if the input parameters are valid
  571. if (bstrClassName == NULL || bstrSourceName == NULL) {
  572. BAIL_ON_FAILURE(hr = E_ADS_BAD_PARAMETER);
  573. }
  574. // Make sure we have proper credentials.
  575. BAIL_ON_FAILURE(hr = RefCredentials());
  576. hr = GetObjectType(gpFilters,
  577. gdwMaxFilters,
  578. bstrClassName,
  579. (PDWORD)&ObjectType );
  580. BAIL_ON_FAILURE(hr);
  581. hr = BuildObjectInfo(
  582. _ADsPath,
  583. bstrSourceName,
  584. &pObjectInfo
  585. );
  586. BAIL_ON_FAILURE(hr);
  587. switch (ObjectType) {
  588. case WINNT_USER_ID:
  589. hr = WinNTDeleteUser(pObjectInfo, _Credentials);
  590. // This might be the case where the user is on the local
  591. // machine and there workstation is not available
  592. if (FAILED(hr) && _fNoWKSTA) {
  593. // We need to go ahead and whack this user
  594. hr = WinNTDeleteUser(
  595. pObjectInfo->ComponentArray[0],
  596. bstrSourceName
  597. );
  598. }
  599. break;
  600. case WINNT_GROUP_ID:
  601. //
  602. // for backward compatability: allow user to delete by classname "group"
  603. //
  604. hr = WinNTDeleteGroup(pObjectInfo, WINNT_GROUP_EITHER, _Credentials);
  605. if (FAILED(hr) && _fNoWKSTA) {
  606. //
  607. // We need to whack this group.
  608. //
  609. hr = WinNTDeleteLocalGroup(
  610. pObjectInfo->ComponentArray[0],
  611. bstrSourceName
  612. );
  613. }
  614. break;
  615. //
  616. // Global Group and LocalGroup ID's will now goto default
  617. //
  618. case WINNT_PRINTER_ID:
  619. hr = WinNTDeletePrinter(pObjectInfo);
  620. break;
  621. case WINNT_SERVICE_ID:
  622. hr = WinNTDeleteService(pObjectInfo);
  623. break;
  624. default:
  625. hr = E_ADS_UNKNOWN_OBJECT;
  626. break;
  627. }
  628. BAIL_ON_FAILURE(hr);
  629. error:
  630. if (pObjectInfo) {
  631. FreeObjectInfo(pObjectInfo);
  632. }
  633. RRETURN_EXP_IF_ERR(hr);
  634. }
  635. STDMETHODIMP
  636. CWinNTComputer::CopyHere(
  637. THIS_ BSTR SourceName,
  638. BSTR NewName,
  639. IDispatch * FAR* ppObject
  640. )
  641. {
  642. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  643. }
  644. /* IADsComputer methods */
  645. HRESULT
  646. CWinNTComputer::AllocateComputerObject(
  647. CWinNTComputer ** ppComputer
  648. )
  649. {
  650. CWinNTComputer FAR * pComputer = NULL;
  651. CPropertyCache FAR * pPropertyCache = NULL;
  652. CAggregatorDispMgr FAR * pDispMgr = NULL;
  653. HRESULT hr = S_OK;
  654. pComputer = new CWinNTComputer();
  655. if (pComputer == NULL) {
  656. hr = E_OUTOFMEMORY;
  657. }
  658. BAIL_ON_FAILURE(hr);
  659. pDispMgr = new CAggregatorDispMgr;
  660. if (pDispMgr == NULL) {
  661. hr = E_OUTOFMEMORY;
  662. }
  663. BAIL_ON_FAILURE(hr);
  664. hr = LoadTypeInfoEntry(
  665. pDispMgr,
  666. LIBID_ADs,
  667. IID_IADsComputer,
  668. (IADsComputer *)pComputer,
  669. DISPID_REGULAR
  670. );
  671. BAIL_ON_FAILURE(hr);
  672. hr = LoadTypeInfoEntry(
  673. pDispMgr,
  674. LIBID_ADs,
  675. IID_IADsComputerOperations,
  676. (IADsComputerOperations *)pComputer,
  677. DISPID_REGULAR
  678. );
  679. BAIL_ON_FAILURE(hr);
  680. hr = LoadTypeInfoEntry(
  681. pDispMgr,
  682. LIBID_ADs,
  683. IID_IADsContainer,
  684. (IADsContainer *)pComputer,
  685. DISPID_NEWENUM
  686. );
  687. BAIL_ON_FAILURE(hr);
  688. hr = LoadTypeInfoEntry(
  689. pDispMgr,
  690. LIBID_ADs,
  691. IID_IADsPropertyList,
  692. (IADsPropertyList *)pComputer,
  693. DISPID_VALUE
  694. );
  695. BAIL_ON_FAILURE(hr);
  696. hr = CPropertyCache::createpropertycache(
  697. ComputerClass,
  698. gdwComputerTableSize,
  699. (CCoreADsObject *)pComputer,
  700. &pPropertyCache
  701. );
  702. BAIL_ON_FAILURE(hr);
  703. pDispMgr->RegisterPropertyCache(
  704. pPropertyCache
  705. );
  706. pComputer->_pPropertyCache = pPropertyCache;
  707. pComputer->_pDispMgr = pDispMgr;
  708. *ppComputer = pComputer;
  709. RRETURN(hr);
  710. error:
  711. delete pPropertyCache;
  712. delete pDispMgr;
  713. delete pComputer;
  714. RRETURN(hr);
  715. }
  716. WCHAR *szCurrentVersion = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
  717. WCHAR *szHardwareInfo = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
  718. STDMETHODIMP
  719. CWinNTComputer::GetInfo(
  720. THIS_ DWORD dwApiLevel,
  721. BOOL fExplicit
  722. )
  723. {
  724. COMP_INFO_4 CompInfo4;
  725. PCOMP_INFO_4 pCompInfo4 = &CompInfo4;
  726. DWORD dwRet = 0;
  727. HKEY hKey = NULL;
  728. HKEY hCurrentKey = NULL;
  729. HKEY hHardwareKey = NULL;
  730. DWORD cbData = 0;
  731. HRESULT hr = S_OK;
  732. WCHAR lpszServerName[MAX_PATH];
  733. NET_API_STATUS nasStatus;
  734. LPSERVER_INFO_101 lpServerInfo =NULL;
  735. WCHAR szMajorVersion[20];
  736. WCHAR szMinorVersion[20];
  737. // Make sure we have proper credentials.
  738. BAIL_ON_FAILURE(hr = RefCredentials());
  739. memset(pCompInfo4, 0, sizeof(COMP_INFO_4));
  740. switch (dwApiLevel) {
  741. case 4:
  742. hr = MakeUncName(_Name, lpszServerName);
  743. BAIL_ON_FAILURE(hr);
  744. dwRet = RegConnectRegistry(
  745. lpszServerName,
  746. HKEY_LOCAL_MACHINE,
  747. &hKey
  748. );
  749. if (dwRet !=ERROR_SUCCESS) {
  750. hr = HRESULT_FROM_WIN32(dwRet);
  751. BAIL_ON_FAILURE(hr);
  752. }
  753. dwRet = RegOpenKeyEx(
  754. hKey,
  755. szCurrentVersion,
  756. 0,
  757. KEY_READ,
  758. &hCurrentKey
  759. );
  760. if (dwRet != ERROR_SUCCESS) {
  761. hr = HRESULT_FROM_WIN32(dwRet);
  762. BAIL_ON_FAILURE(hr);
  763. }
  764. wcscpy(pCompInfo4->szOS, L"Windows NT");
  765. nasStatus = NetServerGetInfo(lpszServerName,
  766. 101,
  767. (LPBYTE *)&lpServerInfo
  768. );
  769. hr = HRESULT_FROM_WIN32(nasStatus);
  770. BAIL_ON_FAILURE(hr);
  771. _itow(
  772. lpServerInfo->sv101_version_major,
  773. szMajorVersion,
  774. 10
  775. );
  776. _itow(
  777. lpServerInfo->sv101_version_minor,
  778. szMinorVersion,
  779. 10
  780. );
  781. wcscpy(
  782. pCompInfo4->szOSVersion,
  783. szMajorVersion
  784. );
  785. wcscat(
  786. pCompInfo4->szOSVersion,
  787. L"."
  788. );
  789. wcscat(
  790. pCompInfo4->szOSVersion,
  791. szMinorVersion
  792. );
  793. cbData = sizeof(pCompInfo4->szOwner);
  794. dwRet = RegQueryValueEx(
  795. hCurrentKey,
  796. L"RegisteredOwner",
  797. NULL,
  798. NULL,
  799. (LPBYTE)pCompInfo4->szOwner,
  800. &cbData
  801. );
  802. cbData = sizeof(pCompInfo4->szDivision),
  803. dwRet = RegQueryValueEx(
  804. hCurrentKey,
  805. L"RegisteredOrganization",
  806. NULL,
  807. NULL,
  808. (LPBYTE)pCompInfo4->szDivision,
  809. &cbData
  810. );
  811. cbData = sizeof(pCompInfo4->szProcessorCount),
  812. dwRet = RegQueryValueEx(
  813. hCurrentKey,
  814. L"CurrentType",
  815. NULL,
  816. NULL,
  817. (LPBYTE)pCompInfo4->szProcessorCount,
  818. &cbData
  819. );
  820. dwRet = RegOpenKeyEx(
  821. hKey,
  822. szHardwareInfo,
  823. 0,
  824. KEY_READ,
  825. &hHardwareKey
  826. );
  827. if (dwRet != ERROR_SUCCESS) {
  828. hr = HRESULT_FROM_WIN32(dwRet);
  829. BAIL_ON_FAILURE(hr);
  830. }
  831. cbData = sizeof(pCompInfo4->szProcessor),
  832. dwRet = RegQueryValueEx(
  833. hHardwareKey,
  834. L"Identifier",
  835. NULL,
  836. NULL,
  837. (LPBYTE)pCompInfo4->szProcessor,
  838. &cbData
  839. );
  840. hr = UnMarshall_Level4(fExplicit, pCompInfo4);
  841. error:
  842. if(lpServerInfo) {
  843. NetApiBufferFree(lpServerInfo);
  844. }
  845. if (hCurrentKey) {
  846. RegCloseKey(hCurrentKey);
  847. }
  848. if (hHardwareKey) {
  849. RegCloseKey(hHardwareKey);
  850. }
  851. if (hKey) {
  852. RegCloseKey(hKey);
  853. }
  854. RRETURN_EXP_IF_ERR(hr);
  855. default:
  856. RRETURN_EXP_IF_ERR(E_FAIL);
  857. }
  858. }
  859. HRESULT
  860. CWinNTComputer::UnMarshall_Level4(
  861. BOOL fExplicit,
  862. LPCOMP_INFO_4 pCompInfo4
  863. )
  864. {
  865. HRESULT hr = S_OK;
  866. hr = SetLPTSTRPropertyInCache(
  867. _pPropertyCache,
  868. TEXT("OperatingSystem"),
  869. pCompInfo4->szOS,
  870. fExplicit
  871. );
  872. hr = SetLPTSTRPropertyInCache(
  873. _pPropertyCache,
  874. TEXT("OperatingSystemVersion"),
  875. pCompInfo4->szOSVersion,
  876. fExplicit
  877. );
  878. hr = SetLPTSTRPropertyInCache(
  879. _pPropertyCache,
  880. TEXT("Owner"),
  881. pCompInfo4->szOwner,
  882. fExplicit
  883. );
  884. hr = SetLPTSTRPropertyInCache(
  885. _pPropertyCache,
  886. TEXT("Division"),
  887. pCompInfo4->szDivision,
  888. fExplicit
  889. );
  890. hr = SetLPTSTRPropertyInCache(
  891. _pPropertyCache,
  892. TEXT("ProcessorCount"),
  893. pCompInfo4->szProcessorCount,
  894. fExplicit
  895. );
  896. hr = SetLPTSTRPropertyInCache(
  897. _pPropertyCache,
  898. TEXT("Processor"),
  899. pCompInfo4->szProcessor,
  900. fExplicit
  901. );
  902. hr = SetLPTSTRPropertyInCache(
  903. _pPropertyCache,
  904. TEXT("Name"),
  905. _Name,
  906. fExplicit
  907. );
  908. RRETURN(S_OK);
  909. }
  910. STDMETHODIMP
  911. CWinNTComputer::Status(
  912. IDispatch * FAR * ppObject
  913. )
  914. {
  915. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  916. }
  917. STDMETHODIMP
  918. CWinNTComputer::Shutdown(
  919. VARIANT_BOOL bReboot
  920. )
  921. {
  922. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  923. }
  924. HRESULT
  925. RenameUserObject(
  926. POBJECTINFO pObjectInfo,
  927. LPWSTR szNewName,
  928. CWinNTCredentials& Credentials
  929. )
  930. {
  931. WCHAR szHostServerName[MAX_PATH];
  932. LPUSER_INFO_0 lpUI = NULL;
  933. HRESULT hr;
  934. WCHAR lpszUncName[MAX_PATH];
  935. NET_API_STATUS nasStatus;
  936. DWORD dwParam = 0;
  937. USER_INFO_0 userinfo;
  938. memset(&userinfo, 0, sizeof(USER_INFO_0));
  939. switch (pObjectInfo->NumComponents) {
  940. case 2:
  941. //
  942. // if 2 components then either it is user in computer
  943. // or user in domain.
  944. hr = WinNTGetCachedDCName(
  945. pObjectInfo->ComponentArray[0],
  946. szHostServerName,
  947. Credentials.GetFlags()
  948. );
  949. if(SUCCEEDED(hr)){
  950. nasStatus = NetUserGetInfo(szHostServerName,
  951. pObjectInfo->ComponentArray[1],
  952. 1,
  953. (LPBYTE *)&lpUI);
  954. hr = HRESULT_FROM_WIN32(nasStatus);
  955. userinfo.usri0_name = szNewName;
  956. nasStatus = NetUserSetInfo(szHostServerName,
  957. pObjectInfo->ComponentArray[1],
  958. 0,
  959. (LPBYTE)&userinfo,
  960. &dwParam);
  961. hr = HRESULT_FROM_WIN32(nasStatus);
  962. }
  963. //
  964. // if we are here with hr != S_OK it could be that we have
  965. // user in a computer.
  966. //
  967. if(FAILED(hr)){
  968. hr = ValidateComputerParent(
  969. NULL,
  970. pObjectInfo->ComponentArray[0],
  971. Credentials
  972. );
  973. BAIL_ON_FAILURE(hr);
  974. MakeUncName(pObjectInfo->ComponentArray[0],
  975. lpszUncName);
  976. nasStatus = NetUserGetInfo(lpszUncName,
  977. pObjectInfo->ComponentArray[1],
  978. 0,
  979. (LPBYTE *)&lpUI);
  980. hr = HRESULT_FROM_WIN32(nasStatus);
  981. userinfo.usri0_name = szNewName;
  982. nasStatus = NetUserSetInfo(lpszUncName,
  983. pObjectInfo->ComponentArray[1],
  984. 0,
  985. (LPBYTE)&userinfo,
  986. &dwParam);
  987. hr = HRESULT_FROM_WIN32(nasStatus);
  988. }
  989. BAIL_ON_FAILURE(hr);
  990. break;
  991. case 3:
  992. //
  993. // user in domain\computer or user in workgroup\computer
  994. //
  995. hr = ValidateComputerParent(pObjectInfo->ComponentArray[0],
  996. pObjectInfo->ComponentArray[1],
  997. Credentials);
  998. BAIL_ON_FAILURE(hr);
  999. MakeUncName(pObjectInfo->ComponentArray[1],
  1000. lpszUncName);
  1001. nasStatus = NetUserGetInfo(lpszUncName,
  1002. pObjectInfo->ComponentArray[2],
  1003. 0,
  1004. (LPBYTE *)&lpUI);
  1005. hr = HRESULT_FROM_WIN32(nasStatus);
  1006. BAIL_ON_FAILURE(hr);
  1007. userinfo.usri0_name = szNewName;
  1008. nasStatus = NetUserSetInfo(lpszUncName,
  1009. pObjectInfo->ComponentArray[2],
  1010. 0,
  1011. (LPBYTE)&userinfo,
  1012. &dwParam);
  1013. hr = HRESULT_FROM_WIN32(nasStatus);
  1014. break;
  1015. default:
  1016. RRETURN(E_ADS_BAD_PATHNAME);
  1017. }
  1018. error:
  1019. if (lpUI) {
  1020. NetApiBufferFree((LPBYTE)lpUI);
  1021. }
  1022. RRETURN(hr);
  1023. }
  1024. HRESULT
  1025. RenameGroupObject(
  1026. POBJECTINFO pObjectInfo,
  1027. LPWSTR szNewName,
  1028. CWinNTCredentials& Credentials
  1029. )
  1030. {
  1031. WCHAR szHostServerName[MAX_PATH];
  1032. LPGROUP_INFO_0 lpGI = NULL;
  1033. HRESULT hr;
  1034. WCHAR lpszUncName[MAX_PATH];
  1035. NET_API_STATUS nasStatus;
  1036. GROUP_INFO_0 groupinfo;
  1037. memset(&groupinfo, 0, sizeof(GROUP_INFO_0));
  1038. groupinfo.grpi0_name = szNewName;
  1039. DWORD dwParam;
  1040. switch (pObjectInfo->NumComponents) {
  1041. case 2:
  1042. //
  1043. // if 2 components then either it is a group in computer
  1044. // or group in domain.
  1045. //
  1046. hr = WinNTGetCachedDCName(
  1047. pObjectInfo->ComponentArray[0],
  1048. szHostServerName,
  1049. Credentials.GetFlags()
  1050. );
  1051. if(SUCCEEDED(hr)){
  1052. //
  1053. // must be a group in a domain
  1054. //
  1055. hr = ValidateGlobalGroupObject(
  1056. szHostServerName,
  1057. &(pObjectInfo->ComponentArray[1]),
  1058. Credentials
  1059. );
  1060. if (FAILED(hr)) {
  1061. hr = ValidateLocalGroupObject(
  1062. szHostServerName,
  1063. &(pObjectInfo->ComponentArray[1]),
  1064. Credentials
  1065. );
  1066. if(SUCCEEDED(hr)){
  1067. nasStatus = NetLocalGroupSetInfo(szHostServerName,
  1068. pObjectInfo->ComponentArray[1],
  1069. 0,
  1070. (LPBYTE)&groupinfo,
  1071. &dwParam);
  1072. hr = HRESULT_FROM_WIN32(nasStatus);
  1073. }
  1074. }else{
  1075. nasStatus = NetGroupSetInfo(szHostServerName,
  1076. pObjectInfo->ComponentArray[1],
  1077. 0,
  1078. (LPBYTE)&groupinfo,
  1079. &dwParam);
  1080. hr = HRESULT_FROM_WIN32(nasStatus);
  1081. }
  1082. }
  1083. if(FAILED(hr)){
  1084. //
  1085. // potentially a group in a computer
  1086. //
  1087. hr = ValidateComputerParent(NULL,
  1088. pObjectInfo->ComponentArray[0],
  1089. Credentials);
  1090. BAIL_ON_FAILURE(hr);
  1091. //
  1092. // group in a computer
  1093. //
  1094. MakeUncName(pObjectInfo->ComponentArray[0],
  1095. lpszUncName);
  1096. hr = ValidateGlobalGroupObject(
  1097. lpszUncName,
  1098. &(pObjectInfo->ComponentArray[1]),
  1099. Credentials
  1100. );
  1101. if (FAILED(hr)) {
  1102. hr = ValidateLocalGroupObject(
  1103. lpszUncName,
  1104. &(pObjectInfo->ComponentArray[1]),
  1105. Credentials
  1106. );
  1107. BAIL_ON_FAILURE(hr);
  1108. nasStatus = NetLocalGroupSetInfo(lpszUncName,
  1109. pObjectInfo->ComponentArray[1],
  1110. 0,
  1111. (LPBYTE)&groupinfo,
  1112. &dwParam);
  1113. hr = HRESULT_FROM_WIN32(nasStatus);
  1114. }else{
  1115. nasStatus = NetGroupSetInfo(lpszUncName,
  1116. pObjectInfo->ComponentArray[1],
  1117. 0,
  1118. (LPBYTE)&groupinfo,
  1119. &dwParam);
  1120. hr = HRESULT_FROM_WIN32(nasStatus);
  1121. }
  1122. }
  1123. break;
  1124. case 3:
  1125. //
  1126. // if there are 3 components then we must have parentid
  1127. // WINNT_COMPUTER_ID
  1128. //
  1129. hr = ValidateComputerParent(pObjectInfo->ComponentArray[0],
  1130. pObjectInfo->ComponentArray[1],
  1131. Credentials);
  1132. BAIL_ON_FAILURE(hr);
  1133. MakeUncName(
  1134. pObjectInfo->ComponentArray[1],
  1135. lpszUncName
  1136. );
  1137. hr = ValidateGlobalGroupObject(
  1138. lpszUncName,
  1139. &(pObjectInfo->ComponentArray[2]),
  1140. Credentials
  1141. );
  1142. if (FAILED(hr)) {
  1143. hr = ValidateLocalGroupObject(
  1144. lpszUncName,
  1145. &(pObjectInfo->ComponentArray[2]),
  1146. Credentials
  1147. );
  1148. BAIL_ON_FAILURE(hr);
  1149. nasStatus = NetLocalGroupSetInfo(lpszUncName,
  1150. pObjectInfo->ComponentArray[2],
  1151. 0,
  1152. (LPBYTE)&groupinfo,
  1153. &dwParam);
  1154. hr = HRESULT_FROM_WIN32(nasStatus);
  1155. }else{
  1156. nasStatus = NetGroupSetInfo(lpszUncName,
  1157. pObjectInfo->ComponentArray[2],
  1158. 0,
  1159. (LPBYTE)&groupinfo,
  1160. &dwParam);
  1161. hr = HRESULT_FROM_WIN32(nasStatus);
  1162. }
  1163. break;
  1164. default:
  1165. RRETURN(E_ADS_BAD_PATHNAME);
  1166. }
  1167. error:
  1168. if (lpGI) {
  1169. NetApiBufferFree((LPBYTE)lpGI);
  1170. }
  1171. RRETURN(hr);
  1172. }
  1173. HRESULT
  1174. CompareBasePath(POBJECTINFO pObjectInfo, POBJECTINFO pObjectInfoParent)
  1175. {
  1176. HRESULT hr = S_OK;
  1177. DWORD i;
  1178. if (wcscmp(pObjectInfo->ProviderName,
  1179. pObjectInfoParent->ProviderName) != 0) {
  1180. hr = E_FAIL;
  1181. BAIL_ON_FAILURE(hr);
  1182. }
  1183. if (pObjectInfo->NumComponents != pObjectInfoParent->NumComponents+1) {
  1184. hr = E_FAIL;
  1185. BAIL_ON_FAILURE(hr);
  1186. }
  1187. for (i=0;i<pObjectInfoParent->NumComponents;i++) {
  1188. if (wcscmp(pObjectInfo->ComponentArray[i],
  1189. pObjectInfoParent->ComponentArray[i]) != 0) {
  1190. hr = E_FAIL;
  1191. BAIL_ON_FAILURE(hr);
  1192. }
  1193. }
  1194. error:
  1195. return hr;
  1196. }
  1197. HRESULT
  1198. MoveUserGroupObject(
  1199. THIS_ BSTR SourceName,
  1200. BSTR NewName,
  1201. BSTR bstrParentADsPath,
  1202. CWinNTCredentials& Credentials,
  1203. IDispatch * FAR* ppObject
  1204. )
  1205. {
  1206. HRESULT hr = S_OK;
  1207. POBJECTINFO pObjectInfo = NULL;
  1208. POBJECTINFO pObjectInfoParent = NULL;
  1209. if ((!SourceName || *SourceName == NULL) ||
  1210. (!NewName || *NewName == NULL)) {
  1211. hr = E_ADS_BAD_PARAMETER;
  1212. BAIL_IF_ERROR(hr);
  1213. }
  1214. hr = BuildObjectInfo(
  1215. SourceName,
  1216. &pObjectInfo
  1217. );
  1218. BAIL_IF_ERROR(hr);
  1219. hr = BuildObjectInfo(
  1220. bstrParentADsPath,
  1221. &pObjectInfoParent
  1222. );
  1223. BAIL_IF_ERROR(hr);
  1224. hr = CompareBasePath(pObjectInfo,
  1225. pObjectInfoParent);
  1226. BAIL_IF_ERROR(hr);
  1227. hr = ValidateProvider(pObjectInfo);
  1228. BAIL_IF_ERROR(hr);
  1229. // check if the call is from UMI. If so, the old path will have a class
  1230. // specified in it. Try to rename the object of that class, as opposed
  1231. // to trying to trying to rename a user first and then rename a group.
  1232. if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
  1233. if(pObjectInfo->ObjectType == TOKEN_USER) {
  1234. hr = RenameUserObject(
  1235. pObjectInfo,
  1236. NewName,
  1237. Credentials
  1238. );
  1239. }
  1240. else if(pObjectInfo->ObjectType == TOKEN_GROUP) {
  1241. hr = RenameGroupObject(
  1242. pObjectInfo,
  1243. NewName,
  1244. Credentials
  1245. );
  1246. }
  1247. else
  1248. hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  1249. }
  1250. else {
  1251. hr = RenameUserObject(
  1252. pObjectInfo,
  1253. NewName,
  1254. Credentials
  1255. );
  1256. if (FAILED(hr)
  1257. && hr != HRESULT_FROM_WIN32(ERROR_BAD_USERNAME)
  1258. && hr != HRESULT_FROM_WIN32(NERR_UserExists)
  1259. && hr != HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)
  1260. ) {
  1261. hr = RenameGroupObject(
  1262. pObjectInfo,
  1263. NewName,
  1264. Credentials
  1265. );
  1266. if (hr == HRESULT_FROM_WIN32(NERR_GroupNotFound)) {
  1267. //
  1268. // The object to move wasn't a group or user
  1269. //
  1270. hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  1271. }
  1272. }
  1273. } // else
  1274. BAIL_ON_FAILURE(hr);
  1275. if (pObjectInfo) {
  1276. FreeObjectInfo(pObjectInfo);
  1277. }
  1278. hr = BuildObjectInfo(
  1279. bstrParentADsPath,
  1280. NewName,
  1281. &pObjectInfo
  1282. );
  1283. BAIL_IF_ERROR(hr);
  1284. hr = HeuristicGetObject(
  1285. pObjectInfo,
  1286. (void**)ppObject,
  1287. Credentials);
  1288. BAIL_IF_ERROR(hr);
  1289. cleanup:
  1290. error:
  1291. if (pObjectInfo) {
  1292. FreeObjectInfo(pObjectInfo);
  1293. }
  1294. if (pObjectInfoParent) {
  1295. FreeObjectInfo(pObjectInfoParent);
  1296. }
  1297. return hr;
  1298. }
  1299. STDMETHODIMP
  1300. CWinNTComputer::MoveHere(
  1301. THIS_ BSTR SourceName,
  1302. BSTR NewName,
  1303. IDispatch * FAR* ppObject
  1304. )
  1305. {
  1306. return MoveUserGroupObject(SourceName,
  1307. NewName,
  1308. _ADsPath,
  1309. _Credentials,
  1310. ppObject);
  1311. }