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.

980 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: pgsrvs.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // PgSrvs.cpp : implementation file
  11. //
  12. #include "stdafx.h"
  13. #include <objsel.h>
  14. #include <secext.h>
  15. #include "acsadmin.h"
  16. #include <dsrole.h>
  17. #include "PgSrvs.h"
  18. #include "ntsecapi.h"
  19. #ifndef STATUS_SUCCESS
  20. #define STATUS_SUCCESS 0L
  21. #endif
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. typedef BOOL (*ACSINSTALL_Func)(
  28. LPWSTR HostName,
  29. LPWSTR DomainName,
  30. LPWSTR UserName,
  31. LPWSTR PassWord,
  32. LPDWORD dwError);
  33. typedef BOOL (*ACSUNINSTALL_Func)(
  34. LPWSTR HostName,
  35. LPDWORD dwError);
  36. #define ACSINSTALL "AcsInstall"
  37. #define ACSUNINSTALL "AcsUninstall"
  38. #define ACSINSTALLDLL _T("acsetupc.dll")
  39. #define ACSAccount _T("AcsService")
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CPgServers property page
  42. IMPLEMENT_DYNCREATE(CPgServers, CACSPage)
  43. #if 0 // LSA functions can only change policy on a machine, it's not the APIs we want
  44. // need to remove the code later
  45. void
  46. InitLsaString(
  47. PLSA_UNICODE_STRING LsaString,
  48. LPWSTR String
  49. )
  50. {
  51. DWORD StringLength;
  52. if (String == NULL) {
  53. LsaString->Buffer = NULL;
  54. LsaString->Length = 0;
  55. LsaString->MaximumLength = 0;
  56. return;
  57. }
  58. StringLength = wcslen(String);
  59. LsaString->Buffer = String;
  60. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  61. LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
  62. }
  63. NTSTATUS
  64. OpenPolicy(
  65. LPWSTR ServerName,
  66. DWORD DesiredAccess,
  67. PLSA_HANDLE PolicyHandle
  68. )
  69. {
  70. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  71. LSA_UNICODE_STRING ServerString;
  72. PLSA_UNICODE_STRING Server = NULL;
  73. //
  74. // Always initialize the object attributes to all zeroes.
  75. //
  76. ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  77. if (ServerName != NULL) {
  78. //
  79. // Make a LSA_UNICODE_STRING out of the LPWSTR passed in
  80. //
  81. InitLsaString(&ServerString, ServerName);
  82. Server = &ServerString;
  83. }
  84. //
  85. // Attempt to open the policy.
  86. //
  87. return LsaOpenPolicy(
  88. Server,
  89. &ObjectAttributes,
  90. DesiredAccess,
  91. PolicyHandle
  92. );
  93. }
  94. /*++
  95. This function attempts to obtain a SID representing the supplied
  96. account on the supplied system.
  97. If the function succeeds, the return value is TRUE. A buffer is
  98. allocated which contains the SID representing the supplied account.
  99. This buffer should be freed when it is no longer needed by calling
  100. HeapFree(GetProcessHeap(), 0, buffer)
  101. If the function fails, the return value is FALSE. Call GetLastError()
  102. to obtain extended error information.
  103. Scott Field (sfield) 12-Jul-95
  104. --*/
  105. BOOL
  106. GetAccountSid(
  107. LPTSTR SystemName,
  108. LPTSTR AccountName,
  109. PSID *Sid
  110. )
  111. {
  112. LPTSTR ReferencedDomain=NULL;
  113. DWORD cbSid=128; // initial allocation attempt
  114. DWORD cbReferencedDomain=16; // initial allocation size
  115. SID_NAME_USE peUse;
  116. BOOL bSuccess=FALSE; // assume this function will fail
  117. __try {
  118. //
  119. // initial memory allocations
  120. //
  121. if((*Sid=HeapAlloc(
  122. GetProcessHeap(),
  123. 0,
  124. cbSid
  125. )) == NULL) __leave;
  126. if((ReferencedDomain=(LPTSTR)HeapAlloc(
  127. GetProcessHeap(),
  128. 0,
  129. cbReferencedDomain
  130. )) == NULL) __leave;
  131. //
  132. // Obtain the SID of the specified account on the specified system.
  133. //
  134. while(!LookupAccountName(
  135. SystemName, // machine to lookup account on
  136. AccountName, // account to lookup
  137. *Sid, // SID of interest
  138. &cbSid, // size of SID
  139. ReferencedDomain, // domain account was found on
  140. &cbReferencedDomain,
  141. &peUse
  142. )) {
  143. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  144. //
  145. // reallocate memory
  146. //
  147. if((*Sid=HeapReAlloc(
  148. GetProcessHeap(),
  149. 0,
  150. *Sid,
  151. cbSid
  152. )) == NULL) __leave;
  153. if((ReferencedDomain=(LPTSTR)HeapReAlloc(
  154. GetProcessHeap(),
  155. 0,
  156. ReferencedDomain,
  157. cbReferencedDomain
  158. )) == NULL) __leave;
  159. }
  160. else __leave;
  161. }
  162. //
  163. // Indicate success.
  164. //
  165. bSuccess=TRUE;
  166. } // finally
  167. __finally {
  168. //
  169. // Cleanup and indicate failure, if appropriate.
  170. //
  171. HeapFree(GetProcessHeap(), 0, ReferencedDomain);
  172. if(!bSuccess) {
  173. if(*Sid != NULL) {
  174. HeapFree(GetProcessHeap(), 0, *Sid);
  175. *Sid = NULL;
  176. }
  177. }
  178. } // finally
  179. return bSuccess;
  180. }
  181. NTSTATUS
  182. SetPrivilegeOnAccount(
  183. LSA_HANDLE PolicyHandle, // open policy handle
  184. PSID AccountSid, // SID to grant privilege to
  185. LPWSTR PrivilegeName, // privilege to grant (Unicode)
  186. BOOL bEnable // enable or disable
  187. )
  188. {
  189. LSA_UNICODE_STRING PrivilegeString;
  190. //
  191. // Create a LSA_UNICODE_STRING for the privilege name.
  192. //
  193. InitLsaString(&PrivilegeString, PrivilegeName);
  194. //
  195. // grant or revoke the privilege, accordingly
  196. //
  197. if(bEnable) {
  198. return LsaAddAccountRights(
  199. PolicyHandle, // open policy handle
  200. AccountSid, // target SID
  201. &PrivilegeString, // privileges
  202. 1 // privilege count
  203. );
  204. }
  205. else {
  206. return LsaRemoveAccountRights(
  207. PolicyHandle, // open policy handle
  208. AccountSid, // target SID
  209. FALSE, // do not disable all rights
  210. &PrivilegeString, // privileges
  211. 1 // privilege count
  212. );
  213. }
  214. }
  215. #endif // LSA is not the right API for this
  216. HRESULT RemoveInteractiveLoginPrivilege(LPCTSTR strDomain, LPCTSTR strAccount)
  217. {
  218. return S_OK;
  219. #if 0 // LSA is not the right API for this
  220. LSA_HANDLE PolicyHandle = NULL;
  221. PSID pSid = NULL;
  222. NTSTATUS Status;
  223. HRESULT hr = S_OK;
  224. //
  225. // Open the policy on the target machine.
  226. //
  227. if((Status=OpenPolicy(
  228. (LPTSTR)strDomain, // target machine
  229. POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  230. &PolicyHandle // resultant policy handle
  231. )) != 0) {
  232. return HRESULT_FROM_WIN32(Status);
  233. }
  234. //
  235. // Obtain the SID of the user/group.
  236. // Note that we could target a specific machine, but we don't.
  237. // Specifying NULL for target machine searches for the SID in the
  238. // following order: well-known, Built-in and local, primary domain,
  239. // trusted domains.
  240. //
  241. if(GetAccountSid(
  242. NULL, // default lookup logic
  243. (LPTSTR)strAccount,// account to obtain SID
  244. &pSid // buffer to allocate to contain resultant SID
  245. )) {
  246. //
  247. // We only grant the privilege if we succeeded in obtaining the
  248. // SID. We can actually add SIDs which cannot be looked up, but
  249. // looking up the SID is a good sanity check which is suitable for
  250. // most cases.
  251. //
  252. // Grant the SeServiceLogonRight to users represented by pSid.
  253. //
  254. // #define SE_INTERACTIVE_LOGON_NAME TEXT("SeInteractiveLogonRight")
  255. // #define SE_DENY_INTERACTIVE_LOGON_NAME TEXT("SeDenyInteractiveLogonRight")
  256. if((Status=SetPrivilegeOnAccount(
  257. PolicyHandle, // policy handle
  258. pSid, // SID to grant privilege
  259. SE_INTERACTIVE_LOGON_NAME, // Unicode privilege
  260. FALSE // enable the privilege
  261. )) != STATUS_SUCCESS)
  262. {
  263. hr = HRESULT_FROM_WIN32(Status);
  264. goto L_Err;
  265. }
  266. if((Status=SetPrivilegeOnAccount(
  267. PolicyHandle, // policy handle
  268. pSid, // SID to grant privilege
  269. SE_DENY_INTERACTIVE_LOGON_NAME, // Unicode privilege
  270. TRUE // enable the privilege
  271. )) != STATUS_SUCCESS)
  272. {
  273. hr = HRESULT_FROM_WIN32(Status);
  274. goto L_Err;
  275. }
  276. }
  277. L_Err:
  278. //
  279. // Close the policy handle.
  280. //
  281. if(PolicyHandle != NULL)
  282. LsaClose(PolicyHandle);
  283. //
  284. // Free memory allocated for SID.
  285. //
  286. if(pSid != NULL) HeapFree(GetProcessHeap(), 0, pSid);
  287. return hr;
  288. #endif // LSA is not the right API
  289. }
  290. HRESULT VerifyAccount(LPCTSTR strDomain, LPCTSTR strAccount, LPCTSTR passwd, HWND hParent)
  291. {
  292. CString UserDN = _T("WinNT://");
  293. CComPtr<IADs> spADs;
  294. CComPtr<IADsUser> spADsUser;
  295. CComPtr<IADsContainer> spCont;
  296. CComPtr<IDispatch> spDisp;
  297. CWaitCursor wc;
  298. UserDN+=strDomain;
  299. UserDN+=_T("/");
  300. UserDN+=strAccount;
  301. // this doesn't compile
  302. // UserDN.Replace(_T("\\"), _T("/"));
  303. // try to create the user account in DS,
  304. HRESULT hr = ADsOpenObject((LPTSTR)(LPCTSTR)UserDN, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_USE_SIGNING | ADS_USE_SEALING, IID_IADs, (void**)&spADs);
  305. // if no such object
  306. if ( hr != S_OK)
  307. {
  308. CString strDomainDN = _T("WinNT://");
  309. strDomainDN += strDomain;
  310. CHECK_HR(hr = ADsOpenObject((LPTSTR)(LPCTSTR)strDomainDN, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_USE_SIGNING | ADS_USE_SEALING, IID_IADsContainer, (void**)&spCont));
  311. // create the user
  312. CHECK_HR(hr = spCont->Create(L"user", (LPTSTR)(LPCTSTR)strAccount, &spDisp ));
  313. hr = spDisp->QueryInterface( IID_IADsUser, (void**) &spADsUser );
  314. CHECK_HR(hr = spADsUser->SetInfo()); // Commit
  315. // set the password for the user
  316. try{
  317. BSTR bstrPasswd = SysAllocString((LPTSTR)passwd);
  318. spADsUser->SetPassword(bstrPasswd);
  319. SysFreeString(bstrPasswd);
  320. // turn the interactive login off
  321. CString str = strDomain;
  322. str += _T("\\");
  323. str += strAccount;
  324. hr = RemoveInteractiveLoginPrivilege(NULL, str);
  325. }
  326. catch(...)
  327. {
  328. hr = E_OUTOFMEMORY;
  329. }
  330. }
  331. L_ERR:
  332. if (FAILED(hr))
  333. {
  334. if (IDYES == ReportErrorEx(hr,IDS_ERR_USERACCOUNT, hParent, MB_YESNO))
  335. hr = S_OK;
  336. }
  337. return hr;
  338. }
  339. HRESULT InstallACSServer(LPCWSTR pMachineName, LPCWSTR strDomain, LPCWSTR strUser, LPCWSTR strPasswd, HWND hParent)
  340. {
  341. HRESULT hr = S_OK;
  342. ACSINSTALL_Func acsInstallFunc;
  343. HINSTANCE hAcsInstallDLL = NULL;
  344. CWaitCursor wc;
  345. hAcsInstallDLL = LoadLibrary(ACSINSTALLDLL);
  346. if ( NULL != hAcsInstallDLL )
  347. {
  348. // load the API pointer
  349. acsInstallFunc = (ACSINSTALL_Func) GetProcAddress(hAcsInstallDLL, ACSINSTALL);
  350. if(acsInstallFunc == NULL)
  351. hr = HRESULT_FROM_WIN32(GetLastError());
  352. else
  353. {
  354. DWORD dwErr;
  355. if(!acsInstallFunc((LPWSTR)pMachineName, (LPWSTR) strDomain, (LPWSTR)strUser, (LPWSTR)strPasswd, &dwErr))
  356. hr = HRESULT_FROM_WIN32(dwErr);
  357. }
  358. FreeLibrary(hAcsInstallDLL);
  359. }
  360. else
  361. hr = HRESULT_FROM_WIN32(GetLastError());
  362. return hr;
  363. }
  364. HRESULT UninstallACSServer(LPWSTR pMachineName, HWND hParent)
  365. {
  366. ACSUNINSTALL_Func acsUninstallFunc;
  367. HRESULT hr = S_OK;
  368. HINSTANCE hAcsInstallDLL = NULL;
  369. CWaitCursor wc;
  370. hAcsInstallDLL = LoadLibrary(ACSINSTALLDLL);
  371. if ( NULL != hAcsInstallDLL )
  372. {
  373. // load the API pointer
  374. acsUninstallFunc = (ACSUNINSTALL_Func) GetProcAddress(hAcsInstallDLL, ACSUNINSTALL);
  375. if(acsUninstallFunc == NULL)
  376. hr = HRESULT_FROM_WIN32(GetLastError());
  377. else
  378. {
  379. DWORD dwErr;
  380. if(!acsUninstallFunc(pMachineName, &dwErr))
  381. hr = HRESULT_FROM_WIN32(dwErr);
  382. }
  383. FreeLibrary(hAcsInstallDLL);
  384. }
  385. else
  386. hr = HRESULT_FROM_WIN32(GetLastError());
  387. return hr;
  388. }
  389. CPgServers::CPgServers(CACSSubnetConfig* pConfig) : CACSPage(CPgServers::IDD)
  390. {
  391. ASSERT(pConfig);
  392. m_spConfig = pConfig;
  393. DataInit();
  394. }
  395. CPgServers::CPgServers() : CACSPage(CPgServers::IDD)
  396. {
  397. DataInit();
  398. }
  399. void CPgServers::DataInit()
  400. {
  401. m_pServers = NULL;
  402. //{{AFX_DATA_INIT(CPgServers)
  403. // NOTE: the ClassWizard will add member initialization here
  404. //}}AFX_DATA_INIT
  405. }
  406. CPgServers::~CPgServers()
  407. {
  408. if(m_pServers)
  409. delete m_pServers;
  410. }
  411. void CPgServers::DoDataExchange(CDataExchange* pDX)
  412. {
  413. CACSPage::DoDataExchange(pDX);
  414. //{{AFX_DATA_MAP(CPgServers)
  415. // NOTE: the ClassWizard will add DDX and DDV calls here
  416. //}}AFX_DATA_MAP
  417. }
  418. BEGIN_MESSAGE_MAP(CPgServers, CACSPage)
  419. //{{AFX_MSG_MAP(CPgServers)
  420. ON_BN_CLICKED(IDC_SERVERS_ADD, OnServersAdd)
  421. ON_BN_CLICKED(IDC_SERVERS_INSTALL, OnServersInstall)
  422. ON_BN_CLICKED(IDC_SERVERS_REMOVE, OnServersRemove)
  423. //}}AFX_MSG_MAP
  424. END_MESSAGE_MAP()
  425. //+--------------------------------------------------------------------------
  426. //
  427. // Function: InitObjectPickerForComputers
  428. //
  429. // Synopsis: Call IDsObjectPicker::Initialize with arguments that will
  430. // set it to allow the user to pick a single computer object.
  431. //
  432. // Arguments: [pDsObjectPicker] - object picker interface instance
  433. //
  434. // Returns: Result of calling IDsObjectPicker::Initialize.
  435. //
  436. // History: 10-14-1998 DavidMun Created
  437. //
  438. //---------------------------------------------------------------------------
  439. HRESULT
  440. InitObjectPickerForComputers(
  441. IDsObjectPicker *pDsObjectPicker)
  442. {
  443. //
  444. // Prepare to initialize the object picker.
  445. // Set up the array of scope initializer structures.
  446. //
  447. static const int SCOPE_INIT_COUNT = 1;
  448. DSOP_SCOPE_INIT_INFO aScopeInit[SCOPE_INIT_COUNT];
  449. ZeroMemory(aScopeInit, sizeof(DSOP_SCOPE_INIT_INFO) * SCOPE_INIT_COUNT);
  450. //
  451. // Since we just want computer objects from every scope, combine them
  452. // all in a single scope initializer.
  453. //
  454. aScopeInit[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  455. aScopeInit[0].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
  456. | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN
  457. | DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN
  458. | DSOP_SCOPE_TYPE_GLOBAL_CATALOG
  459. | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN
  460. | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN
  461. | DSOP_SCOPE_TYPE_WORKGROUP
  462. | DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE
  463. | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE;
  464. aScopeInit[0].FilterFlags.Uplevel.flBothModes =
  465. DSOP_FILTER_COMPUTERS;
  466. aScopeInit[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS;
  467. //
  468. // Put the scope init array into the object picker init array
  469. //
  470. DSOP_INIT_INFO InitInfo;
  471. ZeroMemory(&InitInfo, sizeof(InitInfo));
  472. InitInfo.cbSize = sizeof(InitInfo);
  473. InitInfo.pwzTargetComputer = NULL; // NULL == local machine
  474. InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
  475. InitInfo.aDsScopeInfos = aScopeInit;
  476. InitInfo.flOptions = DSOP_FLAG_MULTISELECT;
  477. LPCTSTR attrs[] = {_T("dNSHostName"), _T("userAccountControl")};
  478. InitInfo.cAttributesToFetch = 2;
  479. InitInfo.apwzAttributeNames = attrs;
  480. //
  481. // Note object picker makes its own copy of InitInfo. Also note
  482. // that Initialize may be called multiple times, last call wins.
  483. //
  484. return pDsObjectPicker->Initialize(&InitInfo);
  485. }
  486. #define BREAK_ON_FAIL_HRESULT(hr) \
  487. if (FAILED(hr)) { printf("line %u err 0x%x\n", __LINE__, hr); break; }
  488. UINT g_cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  489. /////////////////////////////////////////////////////////////////////////////
  490. // CPgServers message handlers
  491. void CPgServers::OnServersAdd()
  492. {
  493. bool bAddedNew = false;
  494. HRESULT hr = S_OK;
  495. IDsObjectPicker *pDsObjectPicker = NULL;
  496. IDataObject *pdo = NULL;
  497. hr = CoInitialize(NULL);
  498. if (FAILED(hr)) return;
  499. do
  500. {
  501. //
  502. // Create an instance of the object picker. The implementation in
  503. // objsel.dll is apartment model.
  504. //
  505. hr = CoCreateInstance(CLSID_DsObjectPicker,
  506. NULL,
  507. CLSCTX_INPROC_SERVER,
  508. IID_IDsObjectPicker,
  509. (void **) &pDsObjectPicker);
  510. BREAK_ON_FAIL_HRESULT(hr);
  511. //
  512. // Reinitialize the object picker to choose computers
  513. //
  514. hr = InitObjectPickerForComputers(pDsObjectPicker);
  515. if(FAILED(hr))
  516. {
  517. TCHAR msg[1024];
  518. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, msg, 1024, NULL);
  519. }
  520. BREAK_ON_FAIL_HRESULT(hr);
  521. //
  522. // Now pick a computer
  523. //
  524. hr = pDsObjectPicker->InvokeDialog(this->GetSafeHwnd(), &pdo);
  525. BREAK_ON_FAIL_HRESULT(hr);
  526. if(hr == S_OK) // when user selected cancel, hr == S_FALSE,
  527. // ProcessSelectedObjects(pdo);
  528. {
  529. ASSERT(pdo);
  530. STGMEDIUM stgmedium =
  531. {
  532. TYMED_HGLOBAL,
  533. NULL,
  534. NULL
  535. };
  536. FORMATETC formatetc =
  537. {
  538. (unsigned short)g_cfDsObjectPicker,
  539. NULL,
  540. DVASPECT_CONTENT,
  541. -1,
  542. TYMED_HGLOBAL
  543. };
  544. bool fGotStgMedium = false;
  545. do
  546. {
  547. hr = pdo->GetData(&formatetc, &stgmedium);
  548. BREAK_ON_FAIL_HRESULT(hr);
  549. // user and password dialog
  550. CDlgPasswd dlg;
  551. fGotStgMedium = true;
  552. PDS_SELECTION_LIST pDsSelList =
  553. (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
  554. if (!pDsSelList)
  555. {
  556. printf("GlobalLock error %u\n", GetLastError());
  557. break;
  558. }
  559. if(pDsSelList->cItems > 0) // some are selected
  560. {
  561. // user and password dialog
  562. if(dlg.DoModal() != IDOK)
  563. break; // the selected servers are not added
  564. // validate user's existence -- return other than OK, will not do anything
  565. if (S_OK != VerifyAccount(dlg.m_strDomain, ACSAccount, dlg.m_strPasswd, GetSafeHwnd()))
  566. break;
  567. }
  568. ULONG i;
  569. for (i = 0; i < pDsSelList->cItems; i++)
  570. {
  571. CString* pStr = NULL;
  572. BSTR bstrTemp;
  573. try{
  574. if(pDsSelList->aDsSelection[i].pvarFetchedAttributes[0].vt == VT_EMPTY)
  575. {
  576. CString str;
  577. str.Format(IDS_ERR_DNSNAME, pDsSelList->aDsSelection[i].pwzName);
  578. AfxMessageBox(str, MB_OK);
  579. continue;
  580. }
  581. ASSERT(pDsSelList->aDsSelection[i].pvarFetchedAttributes[0].vt == VT_BSTR);
  582. bstrTemp = V_BSTR(&(pDsSelList->aDsSelection[i].pvarFetchedAttributes[0]));
  583. DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pDsRole;
  584. DWORD dwErr = DsRoleGetPrimaryDomainInformation(bstrTemp, DsRolePrimaryDomainInfoBasic, (PBYTE *)&pDsRole);
  585. if(dwErr == NO_ERROR && (pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation
  586. || pDsRole->MachineRole == DsRole_RoleMemberWorkstation))
  587. {
  588. CString tempMsg;
  589. tempMsg.LoadString(IDS_ERR_NOT_SERVER);
  590. CString errMsg;
  591. errMsg.Format(tempMsg, bstrTemp);
  592. AfxMessageBox(errMsg);
  593. DsRoleFreeMemory((PVOID)pDsRole);
  594. pDsRole = NULL;
  595. continue;
  596. }
  597. else
  598. {
  599. if(pDsRole)
  600. {
  601. DsRoleFreeMemory((PVOID)pDsRole);
  602. pDsRole = NULL;
  603. }
  604. }
  605. // add to the list
  606. pStr = NULL;
  607. if(m_aServers.Find(bstrTemp) == -1 )
  608. {
  609. HRESULT hr = S_OK;
  610. pStr = new CString();
  611. *pStr = bstrTemp;
  612. bAddedNew = true;
  613. hr = InstallACSServer(V_BSTR(&(pDsSelList->aDsSelection[i].pvarFetchedAttributes[0])), dlg.m_strDomain, ACSAccount, dlg.m_strPasswd, GetSafeHwnd());
  614. if( hr != S_OK)
  615. {
  616. CString Str;
  617. Str.LoadString(IDS_FAILED_INSTALL_ACSSERVER);
  618. CString strTemp1;
  619. strTemp1.LoadString(IDS_ADD_TO_LIST);
  620. CString strAskAdd1;
  621. strAskAdd1.Format(strTemp1, V_BSTR(&(pDsSelList->aDsSelection[i].pvarFetchedAttributes[0])));
  622. CString strTemp2;
  623. strTemp2.LoadString(IDS_ASK_ADD_SERVER);
  624. CString strAskAdd2;
  625. strAskAdd2.Format(strTemp2, V_BSTR(&(pDsSelList->aDsSelection[i].pvarFetchedAttributes[0])));
  626. Str += strAskAdd1;
  627. Str += strAskAdd2;
  628. UINT nAdd = IDNO;
  629. if(hr == REGDB_E_CLASSNOTREG)
  630. {
  631. CString strQosNotInstalled;
  632. strQosNotInstalled.LoadString(IDS_ERROR_QOS_NOTINSTALLED);
  633. CString strToDisplay;
  634. strToDisplay.Format(Str, strQosNotInstalled);
  635. nAdd = AfxMessageBox(strToDisplay, MB_YESNO);
  636. }
  637. else
  638. nAdd = ReportErrorEx(hr, Str, GetSafeHwnd(), MB_YESNO);
  639. if(IDYES != nAdd)
  640. continue;
  641. }
  642. m_pServers->AddString(pStr); // this will add the string to m_aServers array as well underneath
  643. }
  644. }
  645. catch(...)
  646. {
  647. delete pStr;
  648. pStr = NULL;
  649. }
  650. }
  651. GlobalUnlock(stgmedium.hGlobal);
  652. } while (0);
  653. if (fGotStgMedium)
  654. {
  655. ReleaseStgMedium(&stgmedium);
  656. }
  657. pdo->Release();
  658. pdo = NULL;
  659. }
  660. } while (0);
  661. if (pDsObjectPicker)
  662. {
  663. pDsObjectPicker->Release();
  664. }
  665. CoUninitialize();
  666. if(bAddedNew)
  667. SetModified();
  668. }
  669. void CPgServers::OnServersInstall()
  670. {
  671. int i = m_pServers->GetSelected();
  672. // nothing selected
  673. if(i == LB_ERR) return;
  674. HRESULT hr = S_OK;
  675. CString* pStr = m_aServers.GetAt(i);
  676. ASSERT(pStr);
  677. // user and password dialog
  678. CDlgPasswd dlg;
  679. if(dlg.DoModal() != IDOK)
  680. return;
  681. // validate user's existence -- return other than OK, will not do anything
  682. if (S_OK != VerifyAccount(dlg.m_strDomain, ACSAccount, dlg.m_strPasswd, GetSafeHwnd()))
  683. return;
  684. USES_CONVERSION;
  685. InstallACSServer(T2W((LPTSTR)(LPCTSTR)*pStr), dlg.m_strDomain, ACSAccount, dlg.m_strPasswd, GetSafeHwnd());
  686. }
  687. void CPgServers::OnServersRemove()
  688. {
  689. // TODO: Add your control notification handler code here
  690. int i = m_pServers->GetSelected();
  691. if(i== LB_ERR) return;
  692. HRESULT hr = S_OK;
  693. CString* pStr = m_aServers.GetAt(i);
  694. ASSERT(pStr);
  695. USES_CONVERSION;
  696. int cId = AfxMessageBox(IDS_QUESTION_UNINSTALL_ACS, MB_YESNOCANCEL);
  697. if (cId == IDCANCEL) return;
  698. if (cId == IDYES)
  699. hr = UninstallACSServer(T2W((LPTSTR)(LPCTSTR)*pStr), GetSafeHwnd());
  700. if( hr != S_OK)
  701. {
  702. CString ErrStr;
  703. ErrStr.LoadString(IDS_FAILED_UNINSTALL_ACSSERVER);
  704. CString Str;
  705. Str.Format(ErrStr, (LPCTSTR)*pStr);
  706. CString strBecause;
  707. Str += strBecause;
  708. ReportError(hr, Str, GetSafeHwnd());
  709. }
  710. m_pServers->DeleteSelected();
  711. SetModified();
  712. }
  713. BOOL CPgServers::OnApply()
  714. {
  715. // logging level
  716. DWORD dwAttrFlags = ATTR_FLAGS_NONE;
  717. m_spConfig->SetFlags(ATTR_FLAG_SAVE, ACS_SCAF_SERVERLIST, true);
  718. m_spConfig->m_strArrayServerList = m_aServers;
  719. m_spConfig->SetFlags(ATTR_FLAG_SAVE, ACS_SCAF_SERVERLIST, m_aServers.GetSize() != 0);
  720. dwAttrFlags |= ACS_SCAF_SERVERLIST;
  721. AddFlags(dwAttrFlags); // prepare flags for saving
  722. return CACSPage::OnApply();
  723. }
  724. BOOL CPgServers::OnInitDialog()
  725. {
  726. if(m_spConfig->GetFlags(ATTR_FLAG_LOAD, ACS_SCAF_SERVERLIST))
  727. {
  728. m_aServers = m_spConfig->m_strArrayServerList;
  729. }
  730. m_pServers = new CStrBox<CListBox>(this, IDC_SERVERS_LIST, m_aServers);
  731. m_pServers->Fill();
  732. CACSPage::OnInitDialog();
  733. // TODO: Add extra initialization here
  734. return TRUE; // return TRUE unless you set the focus to a control
  735. // EXCEPTION: OCX Property Pages should return FALSE
  736. }
  737. /////////////////////////////////////////////////////////////////////////////
  738. // CDlgPasswd dialog
  739. IMPLEMENT_DYNCREATE(CDlgPasswd, CACSDialog)
  740. CDlgPasswd::CDlgPasswd(CWnd* pParent /*=NULL*/)
  741. : CACSDialog(CDlgPasswd::IDD, pParent)
  742. {
  743. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  744. //{{AFX_DATA_INIT(CDlgPasswd)
  745. m_strPasswd = _T("");
  746. m_strMachine = _T("");
  747. m_strPasswd2 = _T("");
  748. m_strDomain = _T("");
  749. //}}AFX_DATA_INIT
  750. }
  751. void CDlgPasswd::DoDataExchange(CDataExchange* pDX)
  752. {
  753. CACSDialog::DoDataExchange(pDX);
  754. //{{AFX_DATA_MAP(CDlgPasswd)
  755. DDX_Text(pDX, IDC_USERPASSWD_PASSWD, m_strPasswd);
  756. DDX_Text(pDX, IDC_USERPASSWD_PASSWD2, m_strPasswd2);
  757. DDX_Text(pDX, IDC_USERPASSWD_DOMAIN, m_strDomain);
  758. //}}AFX_DATA_MAP
  759. }
  760. BEGIN_MESSAGE_MAP(CDlgPasswd, CACSDialog)
  761. //{{AFX_MSG_MAP(CDlgPasswd)
  762. //}}AFX_MSG_MAP
  763. END_MESSAGE_MAP()
  764. /////////////////////////////////////////////////////////////////////////////
  765. // CDlgPasswd message handlers
  766. void CDlgPasswd::OnOK()
  767. {
  768. // TODO: Add extra validation here
  769. // user name should be in domain\user format
  770. // password and confirmed password must be exactly the same
  771. UpdateData();
  772. // domain name field can not be empty
  773. m_strDomain.TrimLeft();
  774. m_strDomain.TrimRight();
  775. if (m_strDomain.IsEmpty())
  776. {
  777. AfxMessageBox(IDS_EMPTY_DOMAIN);
  778. GotoDlgCtrl(GetDlgItem(IDC_USERPASSWD_DOMAIN));
  779. return;
  780. }
  781. if (m_strPasswd.Compare(m_strPasswd2) != 0) // not the same
  782. {
  783. AfxMessageBox(IDS_PASSWORDMUSTBESAME);
  784. GotoDlgCtrl(GetDlgItem(IDC_USERPASSWD_PASSWD));
  785. return;
  786. }
  787. CACSDialog::OnOK();
  788. }