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.

888 lines
25 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: AMember.cpp
  7. //
  8. // Contents: implementation of CAttrMember
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "wsecmgr.h"
  13. #include "snapmgr.h"
  14. #include "resource.h"
  15. #include "chklist.h"
  16. #include "util.h"
  17. #include "getuser.h"
  18. #include "snapmgr.h"
  19. #include "resource.h"
  20. #include "AMember.h"
  21. #include "wrapper.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CAttrMember property page
  29. IMPLEMENT_DYNCREATE(CAttrMember, CSelfDeletingPropertyPage)
  30. CAttrMember::CAttrMember() : CSelfDeletingPropertyPage(CAttrMember::IDD)
  31. {
  32. //{{AFX_DATA_INIT(CAttrMember)
  33. m_fDefineInDatabase = FALSE;
  34. m_strHeader = _T("");
  35. //}}AFX_DATA_INIT
  36. m_psp.pszTemplate = MAKEINTRESOURCE(IDD_ATTR_GROUP);
  37. m_psp.dwFlags |= PSP_PREMATURE;
  38. m_pMergeList = NULL;
  39. m_fProcessing = FALSE;
  40. m_fInitialized = FALSE;
  41. m_bNoMembers = FALSE;
  42. m_bDirty=false;
  43. m_fOriginalDefineInDatabase=FALSE;
  44. m_bAlias=FALSE;
  45. m_dwType=0;
  46. CAttribute::m_nDialogs++;
  47. }
  48. CAttrMember::~CAttrMember()
  49. {
  50. if ( m_pMergeList ) {
  51. SceFreeMemory(m_pMergeList, SCE_STRUCT_NAME_STATUS_LIST);
  52. m_pMergeList = NULL;
  53. }
  54. m_pData->Release();
  55. CAttribute::m_nDialogs--;
  56. }
  57. void CAttrMember::DoDataExchange(CDataExchange* pDX)
  58. {
  59. CSelfDeletingPropertyPage::DoDataExchange(pDX);
  60. //{{AFX_DATA_MAP(CAttrMember)
  61. DDX_Check(pDX, IDC_DEFINE_GROUP, m_fDefineInDatabase);
  62. DDX_Text(pDX, IDC_HEADER, m_strHeader);
  63. DDX_Control(pDX, IDC_NO_MEMBERS,m_eNoMembers);
  64. //}}AFX_DATA_MAP
  65. }
  66. BEGIN_MESSAGE_MAP(CAttrMember, CSelfDeletingPropertyPage)
  67. //{{AFX_MSG_MAP(CAttrMember)
  68. ON_BN_CLICKED(IDC_DEFINE_GROUP, OnDefineInDatabase)
  69. ON_BN_CLICKED(IDC_ADD, OnAdd)
  70. //}}AFX_MSG_MAP
  71. ON_NOTIFY(CLN_CLICK, IDC_MEMBERS, OnClickMembers)
  72. ON_MESSAGE(WM_HELP, OnHelp)
  73. END_MESSAGE_MAP()
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CAttrMember message handlers
  76. void CAttrMember::OnDefineInDatabase()
  77. {
  78. if (m_fProcessing)
  79. return;
  80. m_fProcessing = TRUE;
  81. //
  82. // for some strange reason the DDX isn't getting this BOOL set, so just do it
  83. // here which is basically the same thing
  84. //
  85. m_fDefineInDatabase = ( ((CButton *)GetDlgItem(IDC_DEFINE_GROUP))->GetCheck() == 1 );
  86. if (m_fDefineInDatabase) {
  87. (GetDlgItem(IDC_ADD))->EnableWindow(TRUE);
  88. //
  89. // use non CWnd calls for the checklist control
  90. //
  91. ::SendMessage(::GetDlgItem(this->m_hWnd, IDC_MEMBERS), WM_ENABLE, (WPARAM) TRUE, (LPARAM) 0);
  92. } else {
  93. (GetDlgItem(IDC_ADD))->EnableWindow(FALSE);
  94. //
  95. // use non CWnd calls for the checklist control
  96. //
  97. ::SendMessage(::GetDlgItem(this->m_hWnd, IDC_MEMBERS), WM_ENABLE, (WPARAM) FALSE, (LPARAM) 0);
  98. }
  99. SetModified(TRUE);
  100. //
  101. // Tell our siblings the m_fDefineInDatabase has changed
  102. //
  103. if (m_pAttrMember) {
  104. m_pAttrMember->SetDefineInDatabase(m_fDefineInDatabase);
  105. }
  106. m_fProcessing = FALSE;
  107. }
  108. void CAttrMember::OnAdd()
  109. {
  110. CGetUser gu;
  111. HRESULT hr=S_OK;
  112. DWORD nFlag;
  113. BOOL fModify=FALSE; //Raid #497350, yanggao, 11/20/2001, make sure a new item is added this time.
  114. if ( GROUP_MEMBERS == m_dwType )
  115. nFlag = SCE_SHOW_USERS | SCE_SHOW_DOMAINGROUPS;
  116. else {
  117. nFlag = SCE_SHOW_GROUPS | SCE_SHOW_ALIASES; // NT5 DS, nested groups
  118. }
  119. nFlag |= SCE_SHOW_SCOPE_ALL | SCE_SHOW_DIFF_MODE_OFF_DC;
  120. if (gu.Create(GetSafeHwnd(),nFlag)) {
  121. PSCE_NAME_STATUS_LIST pList, pLast=NULL;
  122. LRESULT iItem;
  123. bool bFound;
  124. PSCE_NAME_LIST pName = gu.GetUsers();
  125. CWnd *pCheckList;
  126. pCheckList = GetDlgItem(IDC_MEMBERS);
  127. if (pName && m_bNoMembers) {
  128. m_bNoMembers = FALSE;
  129. m_eNoMembers.ShowWindow(SW_HIDE);
  130. pCheckList->ShowWindow(SW_SHOW);
  131. }
  132. while(pName) {
  133. if ( pName->Name ) {
  134. // Is the new name in m_pMerged yet?
  135. pList = m_pMergeList;
  136. pLast = NULL;
  137. iItem = 0;
  138. bFound = false;
  139. while(pList) {
  140. // If so, then make sure its "Template" box is checked
  141. if (lstrcmp(pList->Name,pName->Name) == 0) {
  142. if (!(pCheckList->SendMessage(CLM_GETSTATE,MAKELONG(iItem,1)) & CLST_CHECKED)) {
  143. m_bDirty = true;
  144. pCheckList->SendMessage(CLM_SETSTATE,MAKELONG(iItem,1),CLST_CHECKED);
  145. fModify = true;
  146. }
  147. bFound = true;
  148. break;
  149. }
  150. pLast = pList;
  151. pList = pList->Next;
  152. iItem++;
  153. }
  154. // Otherwise add it both to m_pMerged and to the CheckList
  155. if (!bFound) {
  156. PSCE_NAME_STATUS_LIST pNewNode;
  157. pNewNode = (PSCE_NAME_STATUS_LIST)LocalAlloc(0,sizeof(SCE_NAME_STATUS_LIST));
  158. if ( pNewNode ) {
  159. pNewNode->Name = (LPTSTR)LocalAlloc(0, (lstrlen(pName->Name)+1)*sizeof(TCHAR));
  160. if ( pNewNode->Name ) {
  161. // This may not be a safe usage. pNewNode->Name is PWSTR, using WCHAR instead of TCHAR,
  162. // and lstrlen dose not handle not null-terminated pointer. Consider fix
  163. lstrcpy(pNewNode->Name, pName->Name);
  164. pNewNode->Next = NULL;
  165. pNewNode->Status = MERGED_TEMPLATE;
  166. } else {
  167. LocalFree(pNewNode);
  168. pNewNode = NULL;
  169. }
  170. }
  171. if ( pNewNode ) {
  172. if ( pLast )
  173. pLast->Next = pNewNode;
  174. else
  175. m_pMergeList = pNewNode;
  176. pLast = pNewNode;
  177. iItem = pCheckList->SendMessage(CLM_ADDITEM,(WPARAM)pLast->Name,(LPARAM)pLast->Name);
  178. pCheckList->SendMessage(CLM_SETSTATE,MAKELONG(iItem,1),CLST_CHECKED);
  179. pCheckList->SendMessage(CLM_SETSTATE,MAKELONG(iItem,2),CLST_DISABLED);
  180. m_bDirty = true;
  181. fModify = true;
  182. } else {
  183. hr = E_OUTOFMEMORY;
  184. ASSERT(FALSE);
  185. break;
  186. }
  187. }
  188. }
  189. pName = pName->Next;
  190. }
  191. }
  192. if (fModify) {
  193. SetModified(TRUE);
  194. }
  195. if ( FAILED(hr) ) {
  196. CString str;
  197. str.LoadString(IDS_CANT_ADD_MEMBER);
  198. AfxMessageBox(str);
  199. }
  200. }
  201. /*---------------------------------------------------------------------
  202. Method: OnInitDialog
  203. Synopsis: Initialize the check list with members/memberof data
  204. Arguments: None
  205. Returns: TRUE = initialized successfully
  206. ----------------------------------------------------------------------*/
  207. BOOL CAttrMember::OnInitDialog()
  208. {
  209. CSelfDeletingPropertyPage::OnInitDialog();
  210. PSCE_NAME_STATUS_LIST pItem;
  211. HWND hCheckList;
  212. LRESULT nItem;
  213. PSCE_GROUP_MEMBERSHIP pgmTemplate;
  214. PSCE_GROUP_MEMBERSHIP pgmInspect;
  215. PSCE_NAME_LIST pnlTemplate=NULL;
  216. PSCE_NAME_LIST pnlInspect=NULL;
  217. PEDITTEMPLATE pet = NULL;
  218. CString str;
  219. UpdateData(TRUE);
  220. if (GROUP_MEMBER_OF == m_dwType) {
  221. str.LoadString(IDS_NO_MEMBER_OF);
  222. } else {
  223. str.LoadString(IDS_NO_MEMBERS);
  224. }
  225. m_eNoMembers.SetWindowText(str);
  226. pgmInspect = (PSCE_GROUP_MEMBERSHIP) m_pData->GetID(); // last inspection saved in ID field
  227. if ( NULL == pgmInspect ) { // last inspection can't be NULL
  228. return TRUE;
  229. }
  230. m_fOriginalDefineInDatabase = m_fDefineInDatabase = FALSE;
  231. //
  232. // Try to find the base group in the template
  233. //
  234. pet = m_pSnapin->GetTemplate(GT_COMPUTER_TEMPLATE);
  235. if ( NULL == pet ) {
  236. return TRUE;
  237. }
  238. for (pgmTemplate=pet->pTemplate->pGroupMembership;
  239. pgmTemplate!=NULL;
  240. pgmTemplate=pgmTemplate->Next) {
  241. if ( _wcsicmp(pgmTemplate->GroupName, pgmInspect->GroupName) == 0 ) {
  242. //
  243. // If the group is in the template that means it is defined.... duh
  244. //
  245. m_fOriginalDefineInDatabase = m_fDefineInDatabase = TRUE;
  246. break;
  247. }
  248. }
  249. //
  250. // find the name lists to display
  251. //
  252. if ( pgmTemplate ) {
  253. if (GROUP_MEMBER_OF == m_dwType) {
  254. pnlTemplate = pgmTemplate->pMemberOf;
  255. } else {
  256. pnlTemplate = pgmTemplate->pMembers;
  257. }
  258. }
  259. if ((LONG_PTR)ULongToPtr(SCE_NO_VALUE) != (LONG_PTR) pgmInspect &&
  260. pgmInspect ) {
  261. if (GROUP_MEMBER_OF == m_dwType) {
  262. pnlInspect = pgmInspect->pMemberOf;
  263. } else {
  264. pnlInspect = pgmInspect->pMembers;
  265. }
  266. }
  267. m_pMergeList = MergeNameStatusList(pnlTemplate, pnlInspect);
  268. pItem = m_pMergeList;
  269. hCheckList = ::GetDlgItem(m_hWnd,IDC_MEMBERS);
  270. ::SendMessage(hCheckList, CLM_RESETCONTENT, 0, 0 );
  271. ::SendMessage(hCheckList,CLM_SETCOLUMNWIDTH,0,60);
  272. if (!pItem) {
  273. m_bNoMembers = TRUE;
  274. m_eNoMembers.ShowWindow(SW_SHOW);
  275. m_eNoMembers.EnableWindow(FALSE); //Raid #469732, Yanggao
  276. ::ShowWindow(hCheckList,SW_HIDE);
  277. }
  278. while(pItem) {
  279. //
  280. // Store the name of the item in the item data so we can retrieve it later
  281. //
  282. nItem = ::SendMessage(hCheckList,CLM_ADDITEM,(WPARAM) pItem->Name,(LPARAM) pItem->Name);
  283. ::SendMessage(hCheckList,CLM_SETSTATE,MAKELONG(nItem,1),
  284. ((pItem->Status & MERGED_TEMPLATE) ? CLST_CHECKED : CLST_UNCHECKED));
  285. ::SendMessage(hCheckList,CLM_SETSTATE,MAKELONG(nItem,2),
  286. ((pItem->Status & MERGED_INSPECT) ? CLST_CHECKDISABLED : CLST_DISABLED));
  287. pItem = pItem->Next;
  288. }
  289. if ( GROUP_MEMBER_OF == m_dwType ) {
  290. m_bAlias = TRUE;
  291. } else {
  292. m_bAlias = FALSE;
  293. }
  294. CWnd *cwnd = GetDlgItem(IDC_ADD);
  295. if ( cwnd ) {
  296. cwnd->EnableWindow(!m_bAlias);
  297. }
  298. CButton *pButton = (CButton *) GetDlgItem(IDC_DEFINE_GROUP);
  299. if (pButton) {
  300. pButton->SetCheck(m_fDefineInDatabase);
  301. }
  302. OnDefineInDatabase();
  303. SetModified(FALSE);
  304. m_fInitialized = TRUE;
  305. return TRUE; // return TRUE unless you set the focus to a control
  306. // EXCEPTION: OCX Property Pages should return FALSE
  307. }
  308. /*---------------------------------------------------------------------
  309. Method: SetDefineInDatabase
  310. Synopsis: Sets the m_fDefineInDatabase member var, and UI accorsingly
  311. Arguments: fDefineInDatabase
  312. Returns: None
  313. ----------------------------------------------------------------------*/
  314. void CAttrMember::SetDefineInDatabase(BOOL fDefineInDatabase)
  315. {
  316. if (!m_fInitialized)
  317. return;
  318. if (m_fProcessing)
  319. return;
  320. m_fDefineInDatabase = fDefineInDatabase;
  321. CButton *pButton = (CButton *) GetDlgItem(IDC_DEFINE_GROUP);
  322. if (pButton) {
  323. pButton->SetCheck(fDefineInDatabase);
  324. }
  325. OnDefineInDatabase();
  326. }
  327. /*---------------------------------------------------------------------
  328. Method: SetSibling
  329. Synopsis: Sets the pointer to the Sibling class
  330. Arguments: pAttrMember
  331. Returns: None
  332. ----------------------------------------------------------------------*/
  333. void CAttrMember::SetSibling(CAttrMember *pAttrMember)
  334. {
  335. m_pAttrMember = pAttrMember;
  336. }
  337. /*---------------------------------------------------------------------
  338. Method: Initialize
  339. Synopsis: Initialize member data
  340. Arguments: pData - the CResult data record
  341. Returns: None
  342. ----------------------------------------------------------------------*/
  343. void CAttrMember::Initialize(CResult * pData)
  344. {
  345. m_pData = pData;
  346. pData->AddRef();
  347. m_bDirty=false;
  348. }
  349. /*---------------------------------------------------------------------
  350. Method: GetGroupInTemplate
  351. Synopsis: Returns a pointer to the SCE_GROUP_MEMBERSHIP structure
  352. that is being changed within the template
  353. Arguments: None
  354. Returns: Pointer the group being modified.
  355. ----------------------------------------------------------------------*/
  356. PSCE_GROUP_MEMBERSHIP CAttrMember::GetGroupInTemplate()
  357. {
  358. PSCE_GROUP_MEMBERSHIP pgmTemplate;
  359. PSCE_GROUP_MEMBERSHIP pgmInspect;
  360. PEDITTEMPLATE pet;
  361. pgmInspect = (PSCE_GROUP_MEMBERSHIP) m_pData->GetID(); // last inspection saved in ID field
  362. if ( NULL == pgmInspect ) { // last inspection can't be NULL
  363. return NULL;
  364. }
  365. pet = m_pSnapin->GetTemplate(GT_COMPUTER_TEMPLATE);
  366. if ( NULL == pet ) {
  367. return NULL;
  368. }
  369. for (pgmTemplate=pet->pTemplate->pGroupMembership;
  370. pgmTemplate!=NULL;
  371. pgmTemplate=pgmTemplate->Next) {
  372. if ( _wcsicmp(pgmTemplate->GroupName, pgmInspect->GroupName) == 0 ) {
  373. return pgmTemplate;
  374. }
  375. }
  376. return NULL;
  377. }
  378. /*---------------------------------------------------------------------
  379. Method: SetMemberType
  380. Synopsis: Initialize page data depending on the type
  381. Arguments: nType - the page type for members of memberof
  382. Returns: None
  383. ----------------------------------------------------------------------*/
  384. void CAttrMember::SetMemberType(DWORD nType)
  385. {
  386. m_dwType = nType;
  387. if (GROUP_MEMBERS == nType) {
  388. m_strHeader.LoadString(IDS_GROUP_MEMBERS_HEADER);
  389. m_strPageTitle.LoadString(IDS_GROUP_MEMBERS_PAGE_TITLE);
  390. } else {
  391. m_strHeader.LoadString(IDS_GROUP_MEMBER_OF_HEADER);
  392. m_strPageTitle.LoadString(IDS_GROUP_MEMBER_OF_PAGE_TITLE);
  393. }
  394. m_psp.dwFlags |= PSP_USETITLE;
  395. m_psp.pszTitle = (LPCTSTR) m_strPageTitle;
  396. }
  397. void CAttrMember::SetSnapin(CSnapin * pSnapin)
  398. {
  399. m_pSnapin = pSnapin;
  400. }
  401. void CAttrMember::OnCancel()
  402. {
  403. if ( m_pMergeList ) {
  404. SceFreeMemory(m_pMergeList,SCE_STRUCT_NAME_STATUS_LIST);
  405. }
  406. m_pMergeList = NULL;
  407. }
  408. void CAttrMember::OnClickMembers(NMHDR *pNM, LRESULT *pResult)
  409. {
  410. SetModified(TRUE);
  411. //
  412. // If no items are checked then show the no members edit box instead
  413. //
  414. CWnd *pCheckList;
  415. int iItem;
  416. int nItem;
  417. PNM_CHECKLIST pNMCheckList;
  418. pNMCheckList = (PNM_CHECKLIST) pNM;
  419. if (pNMCheckList->dwState & CLST_CHECKED) {
  420. //
  421. // They checked something, so obviously something is checked
  422. //
  423. return;
  424. }
  425. pCheckList = GetDlgItem(IDC_MEMBERS);
  426. nItem = (int) pCheckList->SendMessage(CLM_GETITEMCOUNT);
  427. for(iItem=0;iItem<nItem;iItem++) {
  428. if ((pCheckList->SendMessage(CLM_GETSTATE,MAKELONG(iItem,1)) & CLST_CHECKED) ||
  429. (pCheckList->SendMessage(CLM_GETSTATE,MAKELONG(iItem,2)) & CLST_CHECKED)) {
  430. //
  431. // Something's checked, so abort
  432. //
  433. return;
  434. }
  435. }
  436. //
  437. // Nothing checked. Swap to the no members edit box
  438. //
  439. m_bNoMembers = TRUE;
  440. m_eNoMembers.ShowWindow(SW_SHOW);
  441. pCheckList->ShowWindow(SW_HIDE);
  442. }
  443. BOOL CAttrMember::OnApply()
  444. {
  445. int iItem;
  446. PEDITTEMPLATE pet=NULL;
  447. PSCE_PROFILE_INFO pspi=NULL;
  448. PSCE_NAME_STATUS_LIST pIndex;
  449. CWnd *pCheckList;
  450. PSCE_NAME_LIST pTemplate=NULL;
  451. PSCE_NAME_LIST pInspect=NULL;
  452. PSCE_NAME_LIST pDeleteNameList = NULL;
  453. PSCE_GROUP_MEMBERSHIP pSetting = NULL;
  454. PSCE_GROUP_MEMBERSHIP pBaseGroup = NULL;
  455. PSCE_GROUP_MEMBERSHIP pFindGroup = NULL;
  456. PSCE_GROUP_MEMBERSHIP pModifiedGroup = NULL;
  457. LPCTSTR szGroupName = (LPCTSTR) (m_pData->GetAttr());
  458. pCheckList = GetDlgItem(IDC_MEMBERS);
  459. pIndex = m_pMergeList;
  460. iItem = 0;
  461. HRESULT hr=S_OK;
  462. //
  463. // if the fDefineInDatabase has changed it is definitely dirty
  464. //
  465. m_bDirty = ( m_bDirty || (m_fOriginalDefineInDatabase != m_fDefineInDatabase) );
  466. //
  467. // only create the name list if the group is going to be defined in the database
  468. //
  469. if (m_fDefineInDatabase) {
  470. while(pIndex) {
  471. if (pCheckList->SendMessage(CLM_GETSTATE,MAKELONG(iItem,1)) & CLST_CHECKED) {
  472. if ( !(pIndex->Status & MERGED_TEMPLATE) ) {
  473. m_bDirty = true;
  474. }
  475. if ( SCESTATUS_SUCCESS != SceAddToNameList(&pTemplate, pIndex->Name, lstrlen(pIndex->Name))) {
  476. hr = E_FAIL;
  477. break;
  478. }
  479. } else if ( pIndex->Status & MERGED_TEMPLATE ) {
  480. m_bDirty = true;
  481. }
  482. pIndex = pIndex->Next;
  483. iItem++;
  484. }
  485. }
  486. if ( SUCCEEDED(hr) && m_bDirty) {
  487. pBaseGroup = GetGroupInTemplate();
  488. //
  489. // Need to add the group to the template
  490. //
  491. if ( (!pBaseGroup || (LONG_PTR)pBaseGroup == (LONG_PTR)ULongToPtr(SCE_NO_VALUE)) &&
  492. m_fDefineInDatabase) {
  493. pBaseGroup = (PSCE_GROUP_MEMBERSHIP) LocalAlloc(LMEM_ZEROINIT,sizeof(SCE_GROUP_MEMBERSHIP));
  494. if ( pBaseGroup && szGroupName ) {
  495. pBaseGroup->GroupName = (PWSTR)LocalAlloc(0, (lstrlen(szGroupName)+1)*sizeof(TCHAR));
  496. if ( pBaseGroup->GroupName ) {
  497. // This may not be safe usage. Using WCHAR instead of TCHAR. Consider fix.
  498. lstrcpy(pBaseGroup->GroupName,szGroupName);
  499. //
  500. // link the new structure to the pGroupMembership list
  501. //
  502. pet = m_pSnapin->GetTemplate(GT_COMPUTER_TEMPLATE,AREA_GROUP_MEMBERSHIP);
  503. if (pet) {
  504. pspi = pet->pTemplate;
  505. } else {
  506. pspi = NULL;
  507. }
  508. if ( pspi ) {
  509. pBaseGroup->Next = pspi->pGroupMembership;
  510. pspi->pGroupMembership = pBaseGroup;
  511. pBaseGroup->pMembers = NULL;
  512. pBaseGroup->pMemberOf = NULL;
  513. } else {
  514. //
  515. // error
  516. ASSERT(FALSE);
  517. LocalFree(pBaseGroup->GroupName);
  518. hr = E_FAIL;
  519. }
  520. } else {
  521. //
  522. // no memory
  523. //
  524. hr = E_OUTOFMEMORY;
  525. }
  526. } else {
  527. hr = E_OUTOFMEMORY;
  528. }
  529. if ( FAILED(hr) && pBaseGroup ) {
  530. LocalFree(pBaseGroup);
  531. pBaseGroup = NULL;
  532. }
  533. pModifiedGroup = pBaseGroup;
  534. //
  535. // Need to remove the group from the template
  536. //
  537. } else if (pBaseGroup && !m_fDefineInDatabase) {
  538. CString szGroupName;
  539. szGroupName = pBaseGroup->GroupName;
  540. pBaseGroup = NULL;
  541. DeleteGroup(szGroupName);
  542. //
  543. // An existing group was modified
  544. //
  545. } else {
  546. pModifiedGroup = pBaseGroup;
  547. }
  548. //
  549. // get group address to change the status field in the last inspection
  550. //
  551. pSetting = (PSCE_GROUP_MEMBERSHIP)(m_pData->GetID());
  552. int status;
  553. if (GROUP_MEMBERS == m_dwType) {
  554. if (pModifiedGroup != NULL) {
  555. pDeleteNameList = pModifiedGroup->pMembers;
  556. pModifiedGroup->pMembers = pTemplate;
  557. }
  558. if (NULL != pSetting ) {
  559. if ( !((pSetting->Status & SCE_GROUP_STATUS_NOT_ANALYZED) ||
  560. (pSetting->Status & SCE_GROUP_STATUS_ERROR_ANALYZED))) {
  561. //
  562. // set good, not configured, or mismatch
  563. //
  564. pSetting->Status &= ~SCE_GROUP_STATUS_NC_MEMBERS;
  565. pSetting->Status &= ~SCE_GROUP_STATUS_MEMBERS_MISMATCH;
  566. if (pModifiedGroup == NULL) {
  567. pSetting->Status |= SCE_GROUP_STATUS_NC_MEMBERS;
  568. } else if ( !SceCompareNameList(pTemplate, pSetting->pMembers) ) {
  569. pSetting->Status |= SCE_GROUP_STATUS_MEMBERS_MISMATCH;
  570. }
  571. }
  572. } else {
  573. //
  574. // else should NEVER occur
  575. //
  576. status = SCE_GROUP_STATUS_MEMBERS_MISMATCH;
  577. }
  578. } else {
  579. //
  580. // memberof
  581. //
  582. if (pModifiedGroup != NULL) {
  583. pDeleteNameList = pModifiedGroup->pMemberOf;
  584. pModifiedGroup->pMemberOf = pTemplate;
  585. }
  586. if ( pSetting ) {
  587. if ( !((pSetting->Status & SCE_GROUP_STATUS_NOT_ANALYZED) ||
  588. (pSetting->Status & SCE_GROUP_STATUS_ERROR_ANALYZED))) {
  589. //
  590. // set good, not configured, or mismatch
  591. //
  592. pSetting->Status &= ~SCE_GROUP_STATUS_NC_MEMBEROF;
  593. pSetting->Status &= ~SCE_GROUP_STATUS_MEMBEROF_MISMATCH;
  594. if (pModifiedGroup == NULL) {
  595. pSetting->Status |= SCE_GROUP_STATUS_NC_MEMBEROF;
  596. } else if ( !SceCompareNameList(pTemplate, pSetting->pMemberOf) ) {
  597. pSetting->Status |= SCE_GROUP_STATUS_MEMBEROF_MISMATCH;
  598. }
  599. }
  600. } else {
  601. // else should NEVER occur
  602. status = SCE_GROUP_STATUS_MEMBEROF_MISMATCH;
  603. }
  604. }
  605. pTemplate = NULL;
  606. SceFreeMemory(pDeleteNameList,SCE_STRUCT_NAME_LIST);
  607. if ( pSetting ) {
  608. status = pSetting->Status;
  609. }
  610. //
  611. // update current record
  612. //
  613. // status
  614. m_pData->SetStatus(GetGroupStatus(status, STATUS_GROUP_RECORD));
  615. // members status
  616. m_pData->SetBase(GetGroupStatus(status, STATUS_GROUP_MEMBERS));
  617. // memberof status
  618. m_pData->SetSetting(GetGroupStatus(status, STATUS_GROUP_MEMBEROF));
  619. m_pData->Update(m_pSnapin);
  620. //
  621. // update the dirty flag in the template
  622. //
  623. pet = m_pSnapin->GetTemplate(GT_COMPUTER_TEMPLATE,AREA_GROUP_MEMBERSHIP);
  624. if (pet) {
  625. pet->SetDirty(AREA_GROUP_MEMBERSHIP);
  626. }
  627. } // failed
  628. SceFreeMemory(pTemplate,SCE_STRUCT_NAME_LIST);
  629. if ( FAILED(hr) ) {
  630. CString str;
  631. str.LoadString(IDS_SAVE_FAILED);
  632. AfxMessageBox(str);
  633. } else {
  634. CancelToClose();
  635. SetModified(TRUE);
  636. return TRUE;
  637. }
  638. return FALSE;
  639. }
  640. BOOL CAttrMember::OnHelp(WPARAM wParam, LPARAM lParam)
  641. {
  642. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  643. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  644. {
  645. this->DoContextHelp ((HWND) pHelpInfo->hItemHandle);
  646. }
  647. return TRUE;
  648. }
  649. void CAttrMember::DoContextHelp (HWND hWndControl)
  650. {
  651. // Display context help for a control
  652. if ( !::WinHelp (
  653. hWndControl,
  654. GetSeceditHelpFilename(),
  655. HELP_WM_HELP,
  656. (DWORD_PTR) a214HelpIDs) )
  657. {
  658. }
  659. }
  660. void CAttrMember::DeleteGroup(const CString &szGroupName)
  661. {
  662. CSingleLock cSL(&m_CS, FALSE);
  663. cSL.Lock();
  664. PEDITTEMPLATE pet = NULL;
  665. PSCE_PROFILE_INFO pspi = NULL;
  666. PSCE_GROUP_MEMBERSHIP pFindGroup = NULL;
  667. PSCE_GROUP_MEMBERSHIP pDeleteGroup = NULL;
  668. pet = m_pSnapin->GetTemplate(GT_COMPUTER_TEMPLATE,AREA_GROUP_MEMBERSHIP);
  669. if (pet) {
  670. pspi = pet->pTemplate;
  671. } else {
  672. pspi = NULL;
  673. }
  674. if ( pspi ) {
  675. //
  676. // find the group in the template and remove it
  677. //
  678. pFindGroup = pspi->pGroupMembership;
  679. if (pFindGroup == NULL)
  680. return;
  681. if (pFindGroup->GroupName == szGroupName) {
  682. pspi->pGroupMembership = pFindGroup->Next;
  683. pDeleteGroup = pFindGroup;
  684. } else {
  685. while (pFindGroup->Next && (pFindGroup->Next->GroupName != szGroupName)) {
  686. pFindGroup = pFindGroup->Next;
  687. }
  688. if (pFindGroup->Next) {
  689. pDeleteGroup = pFindGroup->Next;
  690. pFindGroup->Next = pDeleteGroup->Next;
  691. }
  692. }
  693. if (pDeleteGroup) {
  694. LocalFree(pDeleteGroup->GroupName);
  695. SceFreeMemory(pDeleteGroup->pMembers,SCE_STRUCT_NAME_LIST);
  696. SceFreeMemory(pDeleteGroup->pMemberOf,SCE_STRUCT_NAME_LIST);
  697. LocalFree(pDeleteGroup);
  698. }
  699. } else {
  700. //
  701. // error
  702. //
  703. ASSERT(FALSE);
  704. }
  705. }