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.

878 lines
21 KiB

  1. /*
  2. ** Copyright (c) 1998 Microsoft Corporation
  3. ** All Rights Reserved
  4. **
  5. */
  6. #include <windows.h>
  7. #include <wchar.h>
  8. #include <objbase.h>
  9. #include <winbase.h>
  10. // Required by SSPI.H
  11. #define SECURITY_WIN32
  12. #include <sspi.h>
  13. #include <dsgetdc.h>
  14. #include <ntdsapi.h>
  15. #include <lmcons.h>
  16. #include <lmapibuf.h>
  17. #include <activeds.h>
  18. #define CWSTR_SIZE(x) (sizeof(x) - (sizeof(WCHAR) * 2))
  19. #define DWSTR_SIZE(x) ((wcslen(x) + 1) * sizeof(WCHAR))
  20. #define LICENSE_SETTINGS L"TS-Enterprise-License-Server"
  21. #define LICENSE_SETTINGS2 L"CN=TS-Enterprise-License-Server"
  22. #define LICENSE_SETTINGS_OBJECT_CLASS L"LicensingSiteSettings"
  23. #define LICENSE_SETTINGS_FORMAT L"LDAP://CN=%ws,CN=%ws,CN=%ws,%ws"
  24. #define LICENSE_SETTINGS_SIZE CWSTR_SIZE(LICENSE_SETTINGS)
  25. #define LICENSE_SETTINGS_FORMAT_SIZE CWSTR_SIZE(LICENSE_SETTINGS_FORMAT)
  26. #define SITES L"sites"
  27. #define SITES_SIZE CWSTR_SIZE(SITES)
  28. #define SITE_SERVER L"siteServer"
  29. #define SITE_FORMAT L"LDAP://CN=%ws,CN=%ws,%ws"
  30. #define SITE_FORMAT_SIZE CWSTR_SIZE(SITE_FORMAT)
  31. #define CONFIG_CNTNR L"ConfigurationNamingContext"
  32. #define ROOT_DSE_PATH L"LDAP://RootDSE"
  33. HRESULT GetLicenseSettingsObjectP(VARIANT *pvar,
  34. LPWSTR *ppwszLicenseSettings,
  35. LPWSTR *ppwszSiteName,
  36. IADs **ppADs)
  37. {
  38. HRESULT hr;
  39. DWORD dwErr;
  40. LPWSTR pwszConfigContainer;
  41. IADs * pADs = NULL;
  42. VariantInit(pvar);
  43. dwErr = DsGetSiteName(NULL, ppwszSiteName);
  44. if (dwErr != 0)
  45. {
  46. #ifdef PRIVATEDEBUG
  47. wprintf(L"DsGetSiteName failed %d - 0x%x\n",dwErr,HRESULT_FROM_WIN32(dwErr));
  48. #endif
  49. return HRESULT_FROM_WIN32(dwErr);
  50. }
  51. //
  52. // Obtain the path to the configuration container.
  53. //
  54. hr = ADsGetObject(ROOT_DSE_PATH, IID_IADs, (void **)&pADs);
  55. if (FAILED(hr)) {
  56. #ifdef PRIVATEDEBUG
  57. wprintf(L"ADsGetObject (%ws) failed 0x%x \n",ROOT_DSE_PATH,dwErr);
  58. #endif
  59. goto CleanExit;
  60. }
  61. BSTR bstrval = SysAllocString(CONFIG_CNTNR);
  62. if(NULL == bstrval)
  63. {
  64. hr = E_OUTOFMEMORY;
  65. goto CleanExit;
  66. }
  67. hr = pADs->Get(bstrval, pvar);
  68. SysFreeString(bstrval);
  69. if (FAILED(hr)) {
  70. #ifdef PRIVATEDEBUG
  71. wprintf(L"Get (%ws) failed 0x%x \n",CONFIG_CNTNR,hr);
  72. #endif
  73. goto CleanExit;
  74. }
  75. if (V_VT(pvar) != VT_BSTR) {
  76. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  77. #ifdef PRIVATEDEBUG
  78. wprintf(L"Bad pvar 0x%x \n",hr);
  79. #endif
  80. goto CleanExit;
  81. }
  82. pwszConfigContainer = pvar->bstrVal; // For sake of readability.
  83. //
  84. // Build the X.500 path to the LicenseSettings object.
  85. //
  86. *ppwszLicenseSettings = (LPWSTR)LocalAlloc(
  87. LPTR,
  88. LICENSE_SETTINGS_FORMAT_SIZE
  89. + LICENSE_SETTINGS_SIZE
  90. + DWSTR_SIZE(*ppwszSiteName)
  91. + SITES_SIZE
  92. + DWSTR_SIZE(pwszConfigContainer)
  93. + sizeof(WCHAR));
  94. if (*ppwszLicenseSettings == NULL) {
  95. hr = E_OUTOFMEMORY;
  96. #ifdef PRIVATEDEBUG
  97. wprintf(L"LocalAlloc failed 0x%x \n",hr);
  98. #endif
  99. goto CleanExit;
  100. }
  101. wsprintf(*ppwszLicenseSettings,
  102. LICENSE_SETTINGS_FORMAT,
  103. LICENSE_SETTINGS,
  104. *ppwszSiteName,
  105. SITES,
  106. pwszConfigContainer);
  107. hr = ADsGetObject(*ppwszLicenseSettings, IID_IADs, (void **)ppADs);
  108. CleanExit:
  109. #ifdef PRIVATEDEBUG
  110. wprintf(L"ADsGetObject (%ws) failed? 0x%x \n",*ppwszLicenseSettings,hr);
  111. #endif
  112. if (NULL != pADs) {
  113. pADs->Release();
  114. }
  115. return hr;
  116. }
  117. HRESULT
  118. GetServerPos(IADs *pADs,
  119. VARIANT *pvar,
  120. LONG *plLower,
  121. LONG *plUpper,
  122. LONG *plPos,
  123. WCHAR *ComputerName
  124. )
  125. {
  126. HRESULT hr;
  127. VARIANT var;
  128. SAFEARRAY *psaServers;
  129. VariantInit(&var);
  130. BSTR bstrval = SysAllocString(SITE_SERVER);
  131. if(bstrval == NULL)
  132. {
  133. hr = E_OUTOFMEMORY;
  134. goto CleanExit;
  135. }
  136. hr = pADs->GetEx(bstrval,pvar);
  137. SysFreeString(bstrval);
  138. if (FAILED(hr))
  139. {
  140. hr = S_FALSE; // already gone
  141. goto CleanExit;
  142. }
  143. psaServers = V_ARRAY(pvar);
  144. if (NULL == psaServers)
  145. {
  146. hr = S_FALSE; // already gone
  147. goto CleanExit;
  148. }
  149. hr= SafeArrayGetLBound( psaServers, 1, plLower );
  150. if (FAILED(hr))
  151. {
  152. goto CleanExit;
  153. }
  154. hr= SafeArrayGetUBound( psaServers, 1, plUpper );
  155. if (FAILED(hr))
  156. {
  157. goto CleanExit;
  158. }
  159. for( *plPos = *plLower; *plPos <= *plUpper; *plPos++ )
  160. {
  161. VariantClear( &var );
  162. hr = SafeArrayGetElement( psaServers, plPos, &var );
  163. if (SUCCEEDED(hr) && (V_VT(&var) == VT_BSTR) && (V_BSTR(&var) != NULL))
  164. {
  165. if (0 == lstrcmpi(V_BSTR(&var),ComputerName))
  166. {
  167. hr = S_OK;
  168. goto CleanExit;
  169. }
  170. }
  171. }
  172. hr = S_FALSE;
  173. CleanExit:
  174. VariantClear(&var);
  175. return hr;
  176. }
  177. extern "C"
  178. HRESULT
  179. PublishEnterpriseServer()
  180. {
  181. LPWSTR pwszSiteName = NULL;
  182. DWORD dwErr;
  183. LPWSTR pwszConfigContainer;
  184. IADs * pADs = NULL;
  185. IADs * pADs2 = NULL;
  186. IADsContainer * pADsContainer = NULL;
  187. VARIANT var;
  188. VARIANT var2;
  189. VARIANT var3;
  190. VARIANT var4;
  191. LPWSTR pwszLicenseSettings = NULL;
  192. LPWSTR pwszSite = NULL;
  193. IDispatch * pDisp = NULL;
  194. WCHAR ComputerName[MAX_PATH+1];
  195. ULONG ulen;
  196. BOOL br;
  197. HRESULT hr;
  198. LONG lLower,lUpper,lPos;
  199. SAFEARRAYBOUND sabServers;
  200. LPWSTR pwszDN = NULL;
  201. DS_NAME_RESULT * pDsResult = NULL;
  202. HANDLE hDS;
  203. LPWSTR rgpwszNames[2];
  204. DOMAIN_CONTROLLER_INFO *pDCInfo = NULL;
  205. LPWSTR pwszDomain;
  206. WCHAR wszName[MAX_PATH + 1];
  207. BSTR bstrObjectclass = NULL;
  208. BSTR bstrSettings = NULL;
  209. //
  210. // We're going to use ADSI, so initialize COM. We don't
  211. // care about OLE 1.0 so disable OLE 1 DDE
  212. //
  213. hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
  214. if (FAILED(hr))
  215. {
  216. #ifdef PRIVATEDEBUG
  217. wprintf(L"CoInitializeEx failed 0x%lx\n",hr);
  218. #endif
  219. return hr;
  220. }
  221. VariantInit(&var);
  222. VariantInit(&var2);
  223. VariantInit(&var3);
  224. VariantInit(&var4);
  225. // Get the computer name of the local computer.
  226. ulen = sizeof(ComputerName) / sizeof(TCHAR);
  227. br = GetComputerName(ComputerName, &ulen);
  228. if (!br)
  229. {
  230. hr = HRESULT_FROM_WIN32(GetLastError());
  231. #ifdef PRIVATEDEBUG
  232. wprintf(L"GetComputerName failed 0x%lx\n",hr);
  233. #endif
  234. goto CleanExit;
  235. }
  236. //
  237. // Get domain name
  238. //
  239. hr = DsGetDcName(NULL,
  240. NULL,
  241. NULL,
  242. NULL,
  243. DS_DIRECTORY_SERVICE_PREFERRED | DS_RETURN_FLAT_NAME,
  244. &pDCInfo);
  245. if (hr != ERROR_SUCCESS) {
  246. #ifdef PRIVATEDEBUG
  247. wprintf(L"DsGetDcName failed 0x%lx\n",hr);
  248. #endif
  249. goto CleanExit;
  250. }
  251. pwszDomain = pDCInfo->DomainName;
  252. //
  253. // Bind to the DS (get a handle for use with DsCrackNames).
  254. //
  255. hr = DsBind(NULL, pwszDomain, &hDS);
  256. if (hr != ERROR_SUCCESS) {
  257. #ifdef PRIVATEDEBUG
  258. wprintf(L"DsBind failed 0x%lx\n",hr);
  259. #endif
  260. goto CleanExit;
  261. }
  262. //
  263. // Request the DS-DN of this server's computer object.
  264. //
  265. if (lstrlen(pwszDomain) + lstrlen(ComputerName) + 3 > sizeof(wszName) / sizeof(WCHAR))
  266. {
  267. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  268. #ifdef PRIVATEDEBUG
  269. wprintf(L"Domain or ComputerName too long\n",hr);
  270. #endif
  271. goto CleanExit;
  272. }
  273. wsprintf(wszName,
  274. L"%ws\\%ws$",
  275. pwszDomain,
  276. ComputerName);
  277. rgpwszNames[0] = wszName;
  278. rgpwszNames[1] = NULL;
  279. hr = DsCrackNames(hDS,
  280. DS_NAME_NO_FLAGS,
  281. DS_UNKNOWN_NAME,
  282. DS_FQDN_1779_NAME,
  283. 1,
  284. &rgpwszNames[0],
  285. &pDsResult);
  286. DsUnBind(&hDS);
  287. if (hr != ERROR_SUCCESS)
  288. {
  289. #ifdef PRIVATEDEBUG
  290. wprintf(L"DsCrackNames failed 0x%lx\n",hr);
  291. #endif
  292. goto CleanExit;
  293. }
  294. if (pDsResult->rItems[0].status != DS_NAME_NO_ERROR) {
  295. if (pDsResult->rItems[0].status == DS_NAME_ERROR_RESOLVING) {
  296. hr = ERROR_PATH_NOT_FOUND;
  297. }
  298. else {
  299. hr = pDsResult->rItems[0].status;
  300. }
  301. #ifdef PRIVATEDEBUG
  302. wprintf(L"DsCrackNames (%ws) result bad 0x%lx\n",ComputerName,hr);
  303. #endif
  304. goto CleanExit;
  305. }
  306. V_VT(&var3) = VT_BSTR;
  307. pwszDN = pDsResult->rItems[0].pName;
  308. V_BSTR(&var3) = SysAllocString(pwszDN);
  309. if (NULL == V_BSTR(&var3))
  310. {
  311. hr = E_OUTOFMEMORY;
  312. goto CleanExit;
  313. }
  314. hr = GetLicenseSettingsObjectP(&var,
  315. &pwszLicenseSettings,
  316. &pwszSiteName,
  317. &pADs);
  318. pwszConfigContainer = var.bstrVal;
  319. if (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
  320. {
  321. // Doesn't yet exist, create it
  322. //
  323. // Build the X.500 path to the Site object.
  324. //
  325. pwszSite = (LPWSTR)LocalAlloc(LPTR,
  326. SITE_FORMAT_SIZE
  327. + DWSTR_SIZE(pwszSiteName)
  328. + SITES_SIZE
  329. + DWSTR_SIZE(pwszConfigContainer)
  330. + sizeof(WCHAR));
  331. if (pwszSite == NULL) {
  332. hr = E_OUTOFMEMORY;
  333. goto CleanExit;
  334. }
  335. wsprintf(pwszSite,
  336. SITE_FORMAT,
  337. pwszSiteName,
  338. SITES,
  339. pwszConfigContainer);
  340. hr = ADsGetObject(pwszSite,
  341. IID_IADsContainer,
  342. (void **)&pADsContainer);
  343. if (FAILED(hr)) {
  344. #ifdef PRIVATEDEBUG
  345. wprintf(L"ADsGetObject (%ws) failed 0x%lx\n",pwszSite,hr);
  346. #endif
  347. goto CleanExit;
  348. }
  349. #ifdef PRIVATEDEBUG
  350. wprintf(L"Got container (%ws)\n",pwszSite);
  351. #endif
  352. //
  353. // Create the license settings leaf object.
  354. //
  355. bstrObjectclass = SysAllocString(LICENSE_SETTINGS_OBJECT_CLASS);
  356. if(NULL == bstrObjectclass)
  357. {
  358. hr = E_OUTOFMEMORY;
  359. goto CleanExit;
  360. }
  361. bstrSettings = SysAllocString(LICENSE_SETTINGS2);
  362. if(NULL == bstrSettings)
  363. {
  364. hr = E_OUTOFMEMORY;
  365. goto CleanExit;
  366. }
  367. hr = pADsContainer->Create(bstrObjectclass,
  368. bstrSettings,
  369. &pDisp);
  370. SysFreeString(bstrObjectclass);
  371. SysFreeString(bstrSettings);
  372. if (FAILED(hr)) {
  373. #ifdef PRIVATEDEBUG
  374. wprintf(L"Create (LICENSE_SETTINGS) failed 0x%lx\n",hr);
  375. #endif
  376. goto CleanExit;
  377. }
  378. #ifdef PRIVATEDEBUG
  379. wprintf(L"Created (%ws)\n",LICENSE_SETTINGS2);
  380. #endif
  381. hr = pDisp->QueryInterface(IID_IADs,
  382. (void **)&pADs2);
  383. if (FAILED(hr)) {
  384. #ifdef PRIVATEDEBUG
  385. wprintf(L"QueryInterface failed 0x%lx\n",hr);
  386. #endif
  387. goto CleanExit;
  388. }
  389. bstrSettings = SysAllocString(SITE_SERVER);
  390. if(NULL == bstrSettings)
  391. {
  392. hr = E_OUTOFMEMORY;
  393. goto CleanExit;
  394. }
  395. hr = pADs2->Put(bstrSettings,var3);
  396. SysFreeString(bstrSettings);
  397. if (FAILED(hr)) {
  398. #ifdef PRIVATEDEBUG
  399. wprintf(L"Put (%ws) failed 0x%lx\n",SITE_SERVER,hr);
  400. #endif
  401. goto CleanExit;
  402. }
  403. //
  404. // Persist the change via SetInfo.
  405. //
  406. hr = pADs2->SetInfo();
  407. if (FAILED(hr)) {
  408. #ifdef PRIVATEDEBUG
  409. wprintf(L"SetInfo (%ws)=(%ws) failed 0x%lx\n",SITE_SERVER,V_BSTR(&var3),hr);
  410. #endif
  411. goto CleanExit;
  412. }
  413. } else if (SUCCEEDED(hr))
  414. {
  415. // Already exists; update it
  416. hr = GetServerPos(pADs,&var2,&lLower,&lUpper,&lPos,pwszDN);
  417. if (FAILED(hr) || (hr == S_OK))
  418. {
  419. #ifdef PRIVATEDEBUG
  420. wprintf(L"GetServerPos failed ? 0x%lx\n",hr);
  421. #endif
  422. goto CleanExit;
  423. }
  424. hr = ADsBuildVarArrayStr( &(V_BSTR(&var3)), 1, &var4);
  425. if (FAILED(hr)) {
  426. #ifdef PRIVATEDEBUG
  427. wprintf(L"ADsBuildVarArrayStr (%ws) failed 0x%lx\n",V_BSTR(&var3),hr);
  428. #endif
  429. goto CleanExit;
  430. }
  431. bstrSettings = SysAllocString(SITE_SERVER);
  432. if(NULL == bstrSettings)
  433. {
  434. hr = E_OUTOFMEMORY;
  435. goto CleanExit;
  436. }
  437. hr = pADs->PutEx(ADS_PROPERTY_APPEND,bstrSettings,var4);
  438. SysFreeString(bstrSettings);
  439. if (FAILED(hr)) {
  440. #ifdef PRIVATEDEBUG
  441. wprintf(L"PutEx (%ws)=(%ws) failed 0x%lx\n",SITE_SERVER,V_BSTR(&var3),hr);
  442. #endif
  443. goto CleanExit;
  444. }
  445. hr = pADs->SetInfo();
  446. if (FAILED(hr)) {
  447. #ifdef PRIVATEDEBUG
  448. wprintf(L"SetInfo 2 failed 0x%lx\n",hr);
  449. #endif
  450. goto CleanExit;
  451. }
  452. } else
  453. {
  454. #ifdef PRIVATEDEBUG
  455. wprintf(L"GetLicenseSettingsObject failed 0x%lx\n",hr);
  456. #endif
  457. goto CleanExit;
  458. }
  459. CleanExit:
  460. VariantClear(&var);
  461. VariantClear(&var2);
  462. VariantClear(&var3);
  463. VariantClear(&var4);
  464. if (pwszSiteName != NULL) { // Allocated from DsGetSiteName
  465. NetApiBufferFree(pwszSiteName);
  466. }
  467. if (pwszLicenseSettings != NULL) {
  468. LocalFree(pwszLicenseSettings);
  469. }
  470. if (pwszSite != NULL) {
  471. LocalFree(pwszSite);
  472. }
  473. if (NULL != pADs) {
  474. pADs->Release();
  475. }
  476. if (NULL != pADs2) {
  477. pADs2->Release();
  478. }
  479. if (NULL != pDisp) {
  480. pDisp->Release();
  481. }
  482. if (NULL != pADsContainer) {
  483. pADsContainer->Release();
  484. }
  485. if (pDsResult != NULL) {
  486. DsFreeNameResult(pDsResult);
  487. }
  488. if (pDCInfo != NULL) {
  489. NetApiBufferFree(pDCInfo); // Allocated from DsGetDcName
  490. }
  491. CoUninitialize();
  492. return hr;
  493. }
  494. extern "C"
  495. HRESULT
  496. UnpublishEnterpriseServer()
  497. {
  498. IADs * pADs = NULL;
  499. HRESULT hr;
  500. LPWSTR pwszLicenseSettings = NULL;
  501. LPWSTR pwszSiteName = NULL;
  502. VARIANT var;
  503. VARIANT var2;
  504. VARIANT var3;
  505. SAFEARRAYBOUND sabServers;
  506. WCHAR ComputerName[MAX_PATH+1];
  507. ULONG ulen;
  508. BOOL br;
  509. LONG lPos,lLower, lUpper;
  510. DS_NAME_RESULT * pDsResult = NULL;
  511. HANDLE hDS;
  512. LPWSTR rgpwszNames[2];
  513. LPWSTR pwszDN;
  514. DOMAIN_CONTROLLER_INFO *pDCInfo = NULL;
  515. LPWSTR pwszDomain;
  516. WCHAR wszName[MAX_PATH + 1];
  517. // We're going to use ADSI, so initialize COM. We don't
  518. // care about OLE 1.0 so disable OLE 1 DDE
  519. hr = CoInitializeEx(NULL,COINIT_MULTITHREADED| COINIT_DISABLE_OLE1DDE);
  520. if (FAILED(hr))
  521. {
  522. return hr;
  523. }
  524. VariantInit(&var);
  525. VariantInit(&var2);
  526. VariantInit(&var3);
  527. // Get the computer name of the local computer.
  528. ulen = sizeof(ComputerName) / sizeof(TCHAR);
  529. br=GetComputerName(ComputerName,
  530. &ulen);
  531. if (!br)
  532. {
  533. hr = HRESULT_FROM_WIN32(GetLastError());
  534. goto CleanExit;
  535. }
  536. //
  537. // Get domain name
  538. //
  539. hr = DsGetDcName(NULL,
  540. NULL,
  541. NULL,
  542. NULL,
  543. DS_DIRECTORY_SERVICE_PREFERRED | DS_RETURN_FLAT_NAME,
  544. &pDCInfo);
  545. if (hr != ERROR_SUCCESS) {
  546. #ifdef PRIVATEDEBUG
  547. wprintf(L"DsGetDcName failed 0x%lx\n",hr);
  548. #endif
  549. goto CleanExit;
  550. }
  551. pwszDomain = pDCInfo->DomainName;
  552. //
  553. // Bind to the DS (get a handle for use with DsCrackNames).
  554. //
  555. hr = DsBind(NULL, pwszDomain, &hDS);
  556. if (hr != ERROR_SUCCESS) {
  557. #ifdef PRIVATEDEBUG
  558. wprintf(L"DsBind failed 0x%lx\n",hr);
  559. #endif
  560. goto CleanExit;
  561. }
  562. //
  563. // Request the DS-DN of this server's computer object.
  564. //
  565. if (lstrlen(pwszDomain) + lstrlen(ComputerName) + 3 > sizeof(wszName) / sizeof(WCHAR))
  566. {
  567. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  568. #ifdef PRIVATEDEBUG
  569. wprintf(L"Domain or ComputerName too long\n",hr);
  570. #endif
  571. goto CleanExit;
  572. }
  573. wsprintf(wszName,
  574. L"%ws\\%ws$",
  575. pwszDomain,
  576. ComputerName);
  577. rgpwszNames[0] = wszName;
  578. rgpwszNames[1] = NULL;
  579. hr = DsCrackNames(hDS,
  580. DS_NAME_NO_FLAGS,
  581. DS_UNKNOWN_NAME,
  582. DS_FQDN_1779_NAME,
  583. 1,
  584. &rgpwszNames[0],
  585. &pDsResult);
  586. DsUnBind(&hDS);
  587. if (hr != ERROR_SUCCESS)
  588. {
  589. #ifdef PRIVATEDEBUG
  590. wprintf(L"DsCrackNames failed 0x%lx\n",hr);
  591. #endif
  592. goto CleanExit;
  593. }
  594. if (pDsResult->rItems[0].status != DS_NAME_NO_ERROR) {
  595. if (pDsResult->rItems[0].status == DS_NAME_ERROR_RESOLVING) {
  596. hr = ERROR_PATH_NOT_FOUND;
  597. }
  598. else {
  599. hr = pDsResult->rItems[0].status;
  600. }
  601. #ifdef PRIVATEDEBUG
  602. wprintf(L"DsCrackNames result bad 0x%lx\n",hr);
  603. #endif
  604. goto CleanExit;
  605. }
  606. V_VT(&var3) = VT_BSTR;
  607. pwszDN = pDsResult->rItems[0].pName;
  608. V_BSTR(&var3) = SysAllocString(pwszDN);
  609. if (NULL == V_BSTR(&var3))
  610. {
  611. hr = E_OUTOFMEMORY;
  612. goto CleanExit;
  613. }
  614. hr = GetLicenseSettingsObjectP(&var,
  615. &pwszLicenseSettings,
  616. &pwszSiteName,
  617. &pADs);
  618. if (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
  619. {
  620. hr = S_OK; // already gone
  621. goto CleanExit;
  622. }
  623. if (FAILED(hr))
  624. {
  625. goto CleanExit;
  626. }
  627. #ifdef PRIVATEDEBUG
  628. wprintf(L"pADs %ws NULL \n",(pADs == NULL) ? L"==" : L"!=");
  629. if (NULL == pADs)
  630. {
  631. goto CleanExit;
  632. }
  633. #endif
  634. hr = GetServerPos(pADs,&var2,&lLower,&lUpper,&lPos,pwszDN);
  635. if (FAILED(hr))
  636. {
  637. goto CleanExit;
  638. }
  639. if (hr == S_FALSE)
  640. {
  641. hr = S_OK; // Already gone
  642. goto CleanExit;
  643. }
  644. if (lLower == lUpper)
  645. {
  646. BSTR bstrval = SysAllocString(SITE_SERVER);
  647. if(NULL == bstrval)
  648. {
  649. hr = E_OUTOFMEMORY;
  650. goto CleanExit;
  651. }
  652. // only one element, delete
  653. hr = pADs->PutEx(ADS_PROPERTY_CLEAR,bstrval,var2);
  654. SysFreeString(bstrval);
  655. bstrval = NULL;
  656. if (FAILED(hr)) {
  657. goto CleanExit;
  658. }
  659. }
  660. else
  661. {
  662. if (lPos != lUpper)
  663. {
  664. // move the last element here
  665. hr = SafeArrayGetElement(V_ARRAY(&var2),&lUpper,&var3);
  666. if(SUCCEEDED(hr))
  667. {
  668. hr = SafeArrayPutElement(V_ARRAY(&var2),&lPos,&var3);
  669. }
  670. if (FAILED(hr))
  671. {
  672. goto CleanExit;
  673. }
  674. }
  675. sabServers.lLbound = lLower;
  676. sabServers.cElements = lUpper-lLower;
  677. hr = SafeArrayRedim(V_ARRAY(&var2),&sabServers);
  678. if(FAILED(hr))
  679. {
  680. hr = E_FAIL;
  681. goto CleanExit;
  682. }
  683. BSTR bstrval = SysAllocString(SITE_SERVER);
  684. if(NULL == bstrval)
  685. {
  686. hr = E_OUTOFMEMORY;
  687. goto CleanExit;
  688. }
  689. hr = pADs->Put(bstrval,var2);
  690. SysFreeString (bstrval);
  691. if (FAILED(hr)) {
  692. goto CleanExit;
  693. }
  694. }
  695. hr = pADs->SetInfo();
  696. if (FAILED(hr)) {
  697. goto CleanExit;
  698. }
  699. CleanExit:
  700. VariantClear(&var);
  701. VariantClear(&var2);
  702. VariantClear(&var3);
  703. if (pwszSiteName != NULL) { // Allocated from DsGetSiteName
  704. NetApiBufferFree(pwszSiteName);
  705. }
  706. if (pwszLicenseSettings != NULL) {
  707. LocalFree(pwszLicenseSettings);
  708. }
  709. if (NULL != pADs) {
  710. pADs->Release();
  711. }
  712. if (pDCInfo != NULL) {
  713. NetApiBufferFree(pDCInfo); // Allocated from DsGetDcName
  714. }
  715. CoUninitialize();
  716. return hr;
  717. }