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.

517 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: gencreat.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////
  11. // gencreat.cpp
  12. //
  13. // Implementation of the "Generic Create" wizard.
  14. //
  15. // DATATYPES SUPPORTED
  16. // - Unicode strings
  17. // - Unsigned long decimal integers (32 bits)
  18. // - Signed long decimal integers (32 bits)
  19. // - Numeric decimal strings
  20. // - Boolean flags
  21. //
  22. // TO BE DONE
  23. // - 32 bit hexadecimal integers
  24. // - 64 bit hexadecimal integers
  25. // - Blob
  26. // - Distinguished Names with a "Browse" button
  27. //
  28. // HISTORY
  29. // 21-Aug-97 Dan Morin Creation.
  30. //
  31. /////////////////////////////////////////////////////////////////////
  32. #include "stdafx.h"
  33. #include "util.h"
  34. #include "uiutil.h"
  35. #include "newobj.h" // CNewADsObjectCreateInfo : NOTE: this has to be before gencreat.h
  36. #include "gencreat.h"
  37. #include "schemarc.h"
  38. /////////////////////////////////////////////////////////////////////
  39. /////////////////////////////////////////////////////////////////////
  40. static const SCHEMA_ATTR_SYNTAX_INFO g_rgSchemaAttrSyntaxInfo[] =
  41. {
  42. { L"2.5.5.1", IDS_SCHEMA_ATTR_SYNTAX_DN, VT_BSTR }, // "Distinguished Name"
  43. { L"2.5.5.2", IDS_SCHEMA_ATTR_SYNTAX_OID, VT_BSTR }, // "Object Identifier"
  44. { L"2.5.5.3", IDS_SCHEMA_ATTR_SYNTAX_CASE_STR, VT_BSTR }, // "Case Sensitive String"
  45. { L"2.5.5.4", IDS_SCHEMA_ATTR_SYNTAX_NOCASE_STR, VT_BSTR }, // "Case Insensitive String"
  46. { L"2.5.5.5", IDS_SCHEMA_ATTR_SYNTAX_PRCS_STR, VT_BSTR }, // "Print Case String"
  47. { L"2.5.5.6", IDS_SCHEMA_ATTR_SYNTAX_NUMSTR, VT_BSTR }, // "Numerical String"
  48. { L"2.5.5.7", IDS_SCHEMA_ATTR_SYNTAX_OR_NAME, VT_BSTR }, // "OR Name"
  49. { L"2.5.5.8", IDS_SCHEMA_ATTR_SYNTAX_BOOLEAN, VT_BOOL }, // "Boolean"
  50. { L"2.5.5.9", IDS_SCHEMA_ATTR_SYNTAX_INTEGER, VT_I4 }, // "Integer"
  51. { L"2.5.5.10", IDS_SCHEMA_ATTR_SYNTAX_OCTET, VT_BSTR }, // "Octet String"
  52. { L"2.5.5.11", IDS_SCHEMA_ATTR_SYNTAX_UTC, VT_BSTR }, // "UTC Coded Time"
  53. { L"2.5.5.12", IDS_SCHEMA_ATTR_SYNTAX_UNICODE, VT_BSTR }, // "Unicode String"
  54. { L"2.5.5.13", IDS_SCHEMA_ATTR_SYNTAX_ADDRESS, VT_BSTR }, // "Address"
  55. { L"2.5.5.14", IDS_SCHEMA_ATTR_SYNTAX_DNADDR, VT_BSTR }, // "Distname Address"
  56. { L"2.5.5.15", IDS_SCHEMA_ATTR_SYNTAX_SEC_DESC, VT_BSTR }, // "NT Security Descriptor"
  57. { L"2.5.5.16", IDS_SCHEMA_ATTR_SYNTAX_LINT, VT_I8 }, // "Large Integer"
  58. { L"2.5.5.17", IDS_SCHEMA_ATTR_SYNTAX_SID, VT_BSTR }, // "SID"
  59. { NULL, IDS_UNKNOWN, VT_BSTR } // Must be last
  60. };
  61. /////////////////////////////////////////////////////////////////////
  62. // PFindSchemaAttrSyntaxInfo()
  63. //
  64. // Search the array g_rgSchemaAttrSyntaxInfo and match the
  65. // syntax OID.
  66. //
  67. // This function NEVER return NULL. If no match found, the
  68. // function will return pointer to the last entry in the table.
  69. //
  70. const SCHEMA_ATTR_SYNTAX_INFO *
  71. PFindSchemaAttrSyntaxInfo(LPCTSTR pszAttrSyntaxOID)
  72. {
  73. ASSERT(pszAttrSyntaxOID != NULL);
  74. const int iSchemaAttrSyntaxInfoLast = ARRAYLEN(g_rgSchemaAttrSyntaxInfo) - 1;
  75. ASSERT(iSchemaAttrSyntaxInfoLast >= 0);
  76. for (int i = 0; i < iSchemaAttrSyntaxInfoLast; i++)
  77. {
  78. if (0 == lstrcmpi(pszAttrSyntaxOID, g_rgSchemaAttrSyntaxInfo[i].pszSyntaxOID))
  79. {
  80. return &g_rgSchemaAttrSyntaxInfo[i];
  81. }
  82. }
  83. ASSERT(g_rgSchemaAttrSyntaxInfo[iSchemaAttrSyntaxInfoLast].pszSyntaxOID == NULL);
  84. // Return pointer to the last entry in table
  85. return &g_rgSchemaAttrSyntaxInfo[iSchemaAttrSyntaxInfoLast];
  86. } // PFindSchemaAttrSyntaxInfo()
  87. /////////////////////////////////////////////////////////////////////
  88. /////////////////////////////////////////////////////////////////////
  89. class CGenericCreateWizPage : public CPropertyPageEx_Mine
  90. {
  91. enum { IDD = IDD_CREATE_NEW_OBJECT_GENERIC_WIZARD };
  92. protected:
  93. CCreateNewObjectGenericWizard * m_pParent; // Pointer to parent holding the dat
  94. CPropertySheet * m_pPropertySheetParent; // Pointer of the parent property sheet
  95. int m_iPage; // Index of the current page
  96. CMandatoryADsAttribute * m_pAttribute; // INOUT: Pointer to attribute to edit
  97. protected:
  98. VARTYPE m_vtEnum; // IN: Datatype from SCHEMA_ATTR_SYNTAX_INFO.vtEnum
  99. VARIANT * m_pvarAttrValue; // OUT: Pointer to variant in CMandatoryADsAttribute.m_varAttrValue
  100. public:
  101. CGenericCreateWizPage(CCreateNewObjectGenericWizard * pParent,
  102. int iIpage, INOUT CMandatoryADsAttribute * pAttribute);
  103. ~CGenericCreateWizPage()
  104. {
  105. }
  106. // Overrides
  107. // ClassWizard generate virtual function overrides
  108. //{{AFX_VIRTUAL(CGenericCreateWizPage)
  109. public:
  110. virtual BOOL OnSetActive();
  111. virtual BOOL OnKillActive();
  112. virtual BOOL OnWizardFinish();
  113. protected:
  114. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  115. //}}AFX_VIRTUAL
  116. // Implementation
  117. protected:
  118. // Generated message map functions
  119. //{{AFX_MSG(CGenericCreateWizPage)
  120. virtual BOOL OnInitDialog();
  121. afx_msg void OnChangeEditAttributeValue();
  122. afx_msg void OnBoolSelChange();
  123. //}}AFX_MSG
  124. DECLARE_MESSAGE_MAP()
  125. protected:
  126. void _UpdateWizardButtons(BOOL bValid);
  127. void _UpdateUI();
  128. }; // CGenericCreateWizPage
  129. /////////////////////////////////////////////////////////////////////
  130. // CGenericCreateWizPage() - Constructor
  131. //
  132. // Initialize the member variables for a wizard page
  133. // and add the page to the property sheet.
  134. //
  135. CGenericCreateWizPage::CGenericCreateWizPage(
  136. CCreateNewObjectGenericWizard * pParent,
  137. int iPage,
  138. INOUT CMandatoryADsAttribute * pAttribute)
  139. : CPropertyPageEx_Mine(IDD)
  140. {
  141. ASSERT(pParent != NULL);
  142. ASSERT(iPage >= 0);
  143. ASSERT(pAttribute != NULL);
  144. m_pParent = pParent;
  145. m_iPage = iPage;
  146. m_pAttribute = pAttribute;
  147. ASSERT(m_pAttribute->m_pSchemaAttrSyntaxInfo != NULL);
  148. m_vtEnum = m_pAttribute->m_pSchemaAttrSyntaxInfo->vtEnum;
  149. m_pvarAttrValue = &m_pAttribute->m_varAttrValue;
  150. // Add the page to the property sheet
  151. m_pPropertySheetParent = pParent->m_paPropertySheet;
  152. ASSERT(m_pPropertySheetParent != NULL);
  153. m_pPropertySheetParent->AddPage(this);
  154. } // CGenericCreateWizPage::CGenericCreateWizPage()
  155. /////////////////////////////////////////////////////////////////////
  156. // Validate the data and store it into a variant.
  157. void CGenericCreateWizPage::DoDataExchange(CDataExchange* pDX)
  158. {
  159. ASSERT(m_pAttribute != NULL);
  160. ASSERT(m_pAttribute->m_pSchemaAttrSyntaxInfo != NULL);
  161. // Get the description of the attribute.
  162. UINT uAttributeDescription = m_pAttribute->m_pSchemaAttrSyntaxInfo->uStringIdDesc;
  163. CPropertyPage::DoDataExchange(pDX);
  164. //{{AFX_DATA_MAP(CGenericCreateWizPage)
  165. // NOTE: the ClassWizard will add DDX and DDV calls here
  166. //}}AFX_DATA_MAP
  167. if (!pDX->m_bSaveAndValidate)
  168. return;
  169. VariantClear(INOUT m_pvarAttrValue);
  170. CString strAttrValue;
  171. GetDlgItemText(IDC_EDIT_ATTRIBUTE_VALUE, OUT strAttrValue);
  172. const TCHAR * pch = strAttrValue;
  173. ASSERT(pch != NULL);
  174. switch (m_vtEnum)
  175. {
  176. case VT_BOOL:
  177. {
  178. UINT uStringId = (UINT)ComboBox_GetSelectedItemLParam(HGetDlgItem(IDC_COMBO_ATTRIBUTE_VALUE));
  179. ASSERT(uStringId == IDS_TRUE || uStringId == IDS_FALSE);
  180. m_pvarAttrValue->boolVal = (uStringId == IDS_TRUE);
  181. }
  182. break;
  183. case VT_I4: // 32-bit signed and unsigned integer
  184. m_pvarAttrValue->lVal = 0;
  185. if (!strAttrValue.IsEmpty())
  186. DDX_Text(pDX, IDC_EDIT_ATTRIBUTE_VALUE, OUT m_pvarAttrValue->lVal);
  187. break;
  188. case VT_I8: // 64 bit integer
  189. {
  190. ASSERT(sizeof(VARIANT) == sizeof(*m_pvarAttrValue));
  191. ZeroMemory(OUT m_pvarAttrValue, sizeof(VARIANT));
  192. LARGE_INTEGER liVal;
  193. if (!strAttrValue.IsEmpty())
  194. {
  195. wtoli(strAttrValue, liVal);
  196. m_pvarAttrValue->llVal = liVal.QuadPart;
  197. }
  198. }
  199. break;
  200. case VT_BSTR:
  201. switch (uAttributeDescription)
  202. {
  203. case IDS_SCHEMA_ATTR_SYNTAX_NUMSTR: // Numeric string
  204. for ( ; *pch != _T('\0'); pch++)
  205. {
  206. if (*pch < _T('0') || *pch > _T('9'))
  207. {
  208. ReportErrorEx(GetSafeHwnd(), IDS_ERR_INVALID_DIGIT, S_OK,
  209. MB_OK, NULL, 0);
  210. pDX->Fail();
  211. }
  212. }
  213. break;
  214. default:
  215. break;
  216. } // switch
  217. m_pvarAttrValue->bstrVal = ::SysAllocString(strAttrValue);
  218. break; // VT_BSTR
  219. default:
  220. m_pvarAttrValue->vt = VT_EMPTY; // Just in case
  221. ASSERT(FALSE && "Unsupported variant type");
  222. return;
  223. } // switch
  224. m_pvarAttrValue->vt = m_vtEnum;
  225. } // CGenericCreateWizPage::DoDataExchange()
  226. BEGIN_MESSAGE_MAP(CGenericCreateWizPage, CPropertyPageEx_Mine)
  227. //{{AFX_MSG_MAP(CGenericCreateWizPage)
  228. ON_EN_CHANGE(IDC_EDIT_ATTRIBUTE_VALUE, OnChangeEditAttributeValue)
  229. ON_CBN_SELCHANGE(IDC_COMBO_ATTRIBUTE_VALUE, OnBoolSelChange)
  230. //}}AFX_MSG_MAP
  231. END_MESSAGE_MAP()
  232. /////////////////////////////////////////////////////////////////////
  233. BOOL CGenericCreateWizPage::OnInitDialog()
  234. {
  235. static const UINT rgzuStringId[] = { IDS_TRUE, IDS_FALSE, 0 };
  236. CPropertyPage::OnInitDialog();
  237. HWND hwndCombo = HGetDlgItem(IDC_COMBO_ATTRIBUTE_VALUE);
  238. switch (m_vtEnum)
  239. {
  240. case VT_BOOL:
  241. HideDlgItem(IDC_EDIT_ATTRIBUTE_VALUE, TRUE);
  242. HideDlgItem(IDC_COMBO_ATTRIBUTE_VALUE, FALSE);
  243. ComboBox_AddStrings(hwndCombo, rgzuStringId);
  244. ComboBox_SelectItemByLParam(hwndCombo, IDS_FALSE);
  245. _UpdateWizardButtons(TRUE);
  246. break;
  247. }
  248. LPCTSTR pszAttrName = m_pAttribute->m_strAttrName;
  249. LPCTSTR pszAttrDescr = m_pAttribute->m_strAttrDescription;
  250. if (pszAttrDescr[0] == _T('\0'))
  251. pszAttrDescr = pszAttrName;
  252. CString strAttrType;
  253. VERIFY( strAttrType.LoadString(m_pAttribute->m_pSchemaAttrSyntaxInfo->uStringIdDesc) );
  254. SetDlgItemText(IDC_STATIC_ATTRIBUTE_NAME, pszAttrName);
  255. SetDlgItemText(IDC_STATIC_ATTRIBUTE_DESCRIPTION, pszAttrDescr);
  256. SetDlgItemText(IDC_STATIC_ATTRIBUTE_TYPE, strAttrType);
  257. return TRUE;
  258. } // CGenericCreateWizPage::OnInitDialog()
  259. /////////////////////////////////////////////////////////////////////
  260. // Update the wizard buttons
  261. void CGenericCreateWizPage::OnChangeEditAttributeValue()
  262. {
  263. _UpdateUI();
  264. }
  265. /////////////////////////////////////////////////////////////////////
  266. // Update the wizard buttons
  267. void CGenericCreateWizPage::OnBoolSelChange()
  268. {
  269. if (SendDlgItemMessage(IDC_COMBO_ATTRIBUTE_VALUE, CB_GETCURSEL, 0, 0) != CB_ERR)
  270. {
  271. _UpdateWizardButtons(TRUE);
  272. }
  273. }
  274. /////////////////////////////////////////////////////////////////////
  275. // Update the wizard buttons
  276. void CGenericCreateWizPage::_UpdateWizardButtons(BOOL bValid)
  277. {
  278. DWORD dwWizButtons = 0;
  279. if (m_pParent->m_cMandatoryAttributes > 1)
  280. {
  281. // we have multiple pages
  282. if (m_iPage == 0)
  283. {
  284. // first page
  285. dwWizButtons = bValid ? PSWIZB_NEXT : 0;
  286. }
  287. else if (m_iPage == (m_pParent->m_cMandatoryAttributes-1))
  288. {
  289. // last page
  290. dwWizButtons = bValid ? (PSWIZB_BACK|PSWIZB_FINISH) : (PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  291. }
  292. else
  293. {
  294. // intemediate pages
  295. dwWizButtons = bValid ? (PSWIZB_BACK|PSWIZB_NEXT) : PSWIZB_BACK;
  296. }
  297. }
  298. else
  299. {
  300. // single page wizard
  301. ASSERT(m_iPage == 0);
  302. CString szCaption;
  303. szCaption.LoadString(IDS_WIZARD_OK);
  304. PropSheet_SetFinishText(m_pPropertySheetParent->GetSafeHwnd(), (LPCWSTR)szCaption);
  305. dwWizButtons = bValid ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH;
  306. }
  307. m_pPropertySheetParent->SetWizardButtons(dwWizButtons);
  308. }
  309. void CGenericCreateWizPage::_UpdateUI()
  310. {
  311. switch (m_vtEnum)
  312. {
  313. case VT_BOOL:
  314. _UpdateWizardButtons(TRUE);
  315. break;
  316. default:
  317. CString strName;
  318. GetDlgItemText(IDC_EDIT_ATTRIBUTE_VALUE, OUT strName);
  319. strName.TrimLeft();
  320. strName.TrimRight();
  321. _UpdateWizardButtons(!strName.IsEmpty());
  322. break;
  323. }
  324. }
  325. /////////////////////////////////////////////////////////////////////
  326. BOOL CGenericCreateWizPage::OnSetActive()
  327. {
  328. const int nPage = m_iPage + 1; // Current page
  329. const int cPages = m_pParent->m_cMandatoryAttributes; // Total pages
  330. const TCHAR * pszClassName = m_pParent->m_pszObjectClass;
  331. ASSERT(pszClassName != NULL);
  332. CString strCaption;
  333. if (cPages > 1)
  334. strCaption.Format(IDS_sdd_CREATE_NEW_STEP, pszClassName, nPage, cPages);
  335. else
  336. strCaption.Format(IDS_s_CREATE_NEW, pszClassName);
  337. ASSERT(!strCaption.IsEmpty());
  338. m_pPropertySheetParent->SetWindowText(strCaption);
  339. _UpdateUI();
  340. return CPropertyPage::OnSetActive();
  341. } // CGenericCreateWizPage::OnSetActive()
  342. /////////////////////////////////////////////////////////////////////
  343. BOOL CGenericCreateWizPage::OnKillActive()
  344. {
  345. return CPropertyPage::OnKillActive();
  346. } // CGenericCreateWizPage::OnKillActive()
  347. /////////////////////////////////////////////////////////////////////
  348. // Create and persist the object.
  349. BOOL CGenericCreateWizPage::OnWizardFinish()
  350. {
  351. ASSERT(m_pParent != NULL);
  352. if (!UpdateData())
  353. {
  354. // DDX/DDV failed
  355. return FALSE;
  356. }
  357. HRESULT hr;
  358. CNewADsObjectCreateInfo * pNewADsObjectCreateInfo; // Temporary storage
  359. pNewADsObjectCreateInfo = m_pParent->m_pNewADsObjectCreateInfo;
  360. ASSERT(pNewADsObjectCreateInfo != NULL);
  361. // Write each attribute into the temporary storage
  362. CMandatoryADsAttributeList* pList = m_pParent->m_paMandatoryAttributeList;
  363. int iPage = 0;
  364. for (POSITION pos = pList->GetHeadPosition(); pos != NULL; )
  365. {
  366. CMandatoryADsAttribute* pAttribute = pList->GetNext(pos);
  367. ASSERT(pAttribute != NULL);
  368. if (iPage == 0)
  369. {
  370. // first page is the naming attribute
  371. hr = pNewADsObjectCreateInfo->HrCreateNew(pAttribute->m_varAttrValue.bstrVal);
  372. }
  373. else
  374. {
  375. hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(CComBSTR(pAttribute->m_strAttrName),
  376. pAttribute->m_varAttrValue);
  377. }
  378. ASSERT(SUCCEEDED(hr));
  379. iPage++;
  380. }
  381. // Try to create and persist the object with all its attributes
  382. hr = pNewADsObjectCreateInfo->HrSetInfo();
  383. if (FAILED(hr))
  384. {
  385. // Failure to create object, prevent the wizard from terminating
  386. return FALSE;
  387. }
  388. return CPropertyPage::OnWizardFinish();
  389. } // CGenericCreateWizPage::OnWizardFinish()
  390. /////////////////////////////////////////////////////////////////////
  391. /////////////////////////////////////////////////////////////////////
  392. /////////////////////////////////////////////////////////////////////
  393. /////////////////////////////////////////////////////////////////////
  394. CCreateNewObjectGenericWizard::CCreateNewObjectGenericWizard()
  395. {
  396. m_pNewADsObjectCreateInfo = NULL;
  397. m_paPropertySheet = NULL;
  398. m_cMandatoryAttributes = 0;
  399. m_paMandatoryAttributeList = NULL;
  400. m_pPageArr = NULL;
  401. }
  402. /////////////////////////////////////////////////////////////////////
  403. CCreateNewObjectGenericWizard::~CCreateNewObjectGenericWizard()
  404. {
  405. if (m_pPageArr != NULL)
  406. {
  407. for (int i=0; i< m_cMandatoryAttributes; i++)
  408. delete m_pPageArr[i];
  409. free(m_pPageArr);
  410. }
  411. delete m_paPropertySheet;
  412. }
  413. /////////////////////////////////////////////////////////////////////
  414. // FDoModal()
  415. //
  416. // Query the mandatory attributes and create one wizard
  417. // page for each attribute.
  418. //
  419. BOOL
  420. CCreateNewObjectGenericWizard::FDoModal(
  421. INOUT CNewADsObjectCreateInfo * pNewADsObjectCreateInfo)
  422. {
  423. CThemeContextActivator activator;
  424. ASSERT(pNewADsObjectCreateInfo != NULL);
  425. m_pNewADsObjectCreateInfo = pNewADsObjectCreateInfo;
  426. m_pszObjectClass = m_pNewADsObjectCreateInfo->m_pszObjectClass;
  427. ASSERT(m_pszObjectClass != NULL);
  428. // Query the mandatory attributes
  429. m_paMandatoryAttributeList =
  430. m_pNewADsObjectCreateInfo->GetMandatoryAttributeListFromCacheItem();
  431. ASSERT(m_paMandatoryAttributeList != NULL);
  432. m_cMandatoryAttributes = (int)m_paMandatoryAttributeList->GetCount();
  433. if (m_cMandatoryAttributes <= 0)
  434. {
  435. ReportErrorEx(pNewADsObjectCreateInfo->GetParentHwnd(),
  436. IDS_ERR_CANNOT_FIND_MANDATORY_ATTRIBUTES,
  437. S_OK, MB_OK, NULL, 0);
  438. return FALSE;
  439. }
  440. m_paPropertySheet = new CPropertySheet(L"",
  441. CWnd::FromHandle(pNewADsObjectCreateInfo->GetParentHwnd()));
  442. // Create one wizard page for each attribute
  443. m_pPageArr = (CGenericCreateWizPage**)
  444. malloc(m_cMandatoryAttributes*sizeof(CGenericCreateWizPage*));
  445. if (m_pPageArr != NULL)
  446. {
  447. int iPage = 0;
  448. for (POSITION pos = m_paMandatoryAttributeList->GetHeadPosition(); pos != NULL; )
  449. {
  450. CMandatoryADsAttribute* pAttribute = m_paMandatoryAttributeList->GetNext(pos);
  451. ASSERT(pAttribute != NULL);
  452. m_pPageArr[iPage] = new CGenericCreateWizPage(this, iPage, INOUT pAttribute);
  453. iPage++;
  454. }
  455. }
  456. m_paPropertySheet->SetWizardMode();
  457. if (ID_WIZFINISH == m_paPropertySheet->DoModal())
  458. return TRUE;
  459. return FALSE;
  460. } // FDoModal()