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.

493 lines
16 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
  123. DECLARE_MESSAGE_MAP()
  124. protected:
  125. void _UpdateWizardButtons(BOOL bValid);
  126. void _UpdateUI();
  127. }; // CGenericCreateWizPage
  128. /////////////////////////////////////////////////////////////////////
  129. // CGenericCreateWizPage() - Constructor
  130. //
  131. // Initialize the member variables for a wizard page
  132. // and add the page to the property sheet.
  133. //
  134. CGenericCreateWizPage::CGenericCreateWizPage(
  135. CCreateNewObjectGenericWizard * pParent,
  136. int iPage,
  137. INOUT CMandatoryADsAttribute * pAttribute)
  138. : CPropertyPageEx_Mine(IDD)
  139. {
  140. ASSERT(pParent != NULL);
  141. ASSERT(iPage >= 0);
  142. ASSERT(pAttribute != NULL);
  143. m_pParent = pParent;
  144. m_iPage = iPage;
  145. m_pAttribute = pAttribute;
  146. ASSERT(m_pAttribute->m_pSchemaAttrSyntaxInfo != NULL);
  147. m_vtEnum = m_pAttribute->m_pSchemaAttrSyntaxInfo->vtEnum;
  148. m_pvarAttrValue = &m_pAttribute->m_varAttrValue;
  149. // Add the page to the property sheet
  150. m_pPropertySheetParent = pParent->m_paPropertySheet;
  151. ASSERT(m_pPropertySheetParent != NULL);
  152. m_pPropertySheetParent->AddPage(this);
  153. } // CGenericCreateWizPage::CGenericCreateWizPage()
  154. /////////////////////////////////////////////////////////////////////
  155. // Validate the data and store it into a variant.
  156. void CGenericCreateWizPage::DoDataExchange(CDataExchange* pDX)
  157. {
  158. ASSERT(m_pAttribute != NULL);
  159. ASSERT(m_pAttribute->m_pSchemaAttrSyntaxInfo != NULL);
  160. // Get the description of the attribute.
  161. UINT uAttributeDescription = m_pAttribute->m_pSchemaAttrSyntaxInfo->uStringIdDesc;
  162. CPropertyPage::DoDataExchange(pDX);
  163. //{{AFX_DATA_MAP(CGenericCreateWizPage)
  164. // NOTE: the ClassWizard will add DDX and DDV calls here
  165. //}}AFX_DATA_MAP
  166. if (!pDX->m_bSaveAndValidate)
  167. return;
  168. VariantClear(INOUT m_pvarAttrValue);
  169. CString strAttrValue;
  170. GetDlgItemText(IDC_EDIT_ATTRIBUTE_VALUE, OUT strAttrValue);
  171. const TCHAR * pch = strAttrValue;
  172. ASSERT(pch != NULL);
  173. switch (m_vtEnum)
  174. {
  175. case VT_BOOL:
  176. {
  177. UINT uStringId = (UINT)ComboBox_GetSelectedItemLParam(HGetDlgItem(IDC_COMBO_ATTRIBUTE_VALUE));
  178. ASSERT(uStringId == IDS_TRUE || uStringId == IDS_FALSE);
  179. m_pvarAttrValue->boolVal = (uStringId == IDS_TRUE);
  180. }
  181. break;
  182. case VT_I4: // 32-bit signed and unsigned integer
  183. m_pvarAttrValue->lVal = 0;
  184. if (!strAttrValue.IsEmpty())
  185. DDX_Text(pDX, IDC_EDIT_ATTRIBUTE_VALUE, OUT m_pvarAttrValue->lVal);
  186. break;
  187. case VT_I8: // 64 bit integer
  188. {
  189. ASSERT(sizeof(VARIANT) == sizeof(*m_pvarAttrValue));
  190. ZeroMemory(OUT m_pvarAttrValue, sizeof(VARIANT));
  191. LARGE_INTEGER liVal;
  192. if (!strAttrValue.IsEmpty())
  193. {
  194. wtoli(strAttrValue, liVal);
  195. m_pvarAttrValue->llVal = liVal.QuadPart;
  196. }
  197. }
  198. break;
  199. case VT_BSTR:
  200. switch (uAttributeDescription)
  201. {
  202. case IDS_SCHEMA_ATTR_SYNTAX_NUMSTR: // Numeric string
  203. for ( ; *pch != _T('\0'); pch++)
  204. {
  205. if (*pch < _T('0') || *pch > _T('9'))
  206. {
  207. ReportErrorEx(GetSafeHwnd(), IDS_ERR_INVALID_DIGIT, S_OK,
  208. MB_OK, NULL, 0);
  209. pDX->Fail();
  210. }
  211. }
  212. break;
  213. default:
  214. break;
  215. } // switch
  216. m_pvarAttrValue->bstrVal = ::SysAllocString(strAttrValue);
  217. break; // VT_BSTR
  218. default:
  219. m_pvarAttrValue->vt = VT_EMPTY; // Just in case
  220. ASSERT(FALSE && "Unsupported variant type");
  221. return;
  222. } // switch
  223. m_pvarAttrValue->vt = m_vtEnum;
  224. } // CGenericCreateWizPage::DoDataExchange()
  225. BEGIN_MESSAGE_MAP(CGenericCreateWizPage, CPropertyPageEx_Mine)
  226. //{{AFX_MSG_MAP(CGenericCreateWizPage)
  227. ON_EN_CHANGE(IDC_EDIT_ATTRIBUTE_VALUE, OnChangeEditAttributeValue)
  228. //}}AFX_MSG_MAP
  229. END_MESSAGE_MAP()
  230. /////////////////////////////////////////////////////////////////////
  231. BOOL CGenericCreateWizPage::OnInitDialog()
  232. {
  233. static const UINT rgzuStringId[] = { IDS_TRUE, IDS_FALSE, 0 };
  234. CPropertyPage::OnInitDialog();
  235. HWND hwndCombo = HGetDlgItem(IDC_COMBO_ATTRIBUTE_VALUE);
  236. switch (m_vtEnum)
  237. {
  238. case VT_BOOL:
  239. HideDlgItem(IDC_EDIT_ATTRIBUTE_VALUE, TRUE);
  240. HideDlgItem(IDC_COMBO_ATTRIBUTE_VALUE, FALSE);
  241. ComboBox_AddStrings(hwndCombo, rgzuStringId);
  242. ComboBox_SelectItemByLParam(hwndCombo, IDS_FALSE);
  243. break;
  244. }
  245. LPCTSTR pszAttrName = m_pAttribute->m_strAttrName;
  246. LPCTSTR pszAttrDescr = m_pAttribute->m_strAttrDescription;
  247. if (pszAttrDescr[0] == _T('\0'))
  248. pszAttrDescr = pszAttrName;
  249. CString strAttrType;
  250. VERIFY( strAttrType.LoadString(m_pAttribute->m_pSchemaAttrSyntaxInfo->uStringIdDesc) );
  251. SetDlgItemText(IDC_STATIC_ATTRIBUTE_NAME, pszAttrName);
  252. SetDlgItemText(IDC_STATIC_ATTRIBUTE_DESCRIPTION, pszAttrDescr);
  253. SetDlgItemText(IDC_STATIC_ATTRIBUTE_TYPE, strAttrType);
  254. return TRUE;
  255. } // CGenericCreateWizPage::OnInitDialog()
  256. /////////////////////////////////////////////////////////////////////
  257. // Update the wizard buttons
  258. void CGenericCreateWizPage::OnChangeEditAttributeValue()
  259. {
  260. _UpdateUI();
  261. }
  262. /////////////////////////////////////////////////////////////////////
  263. // Update the wizard buttons
  264. void CGenericCreateWizPage::_UpdateWizardButtons(BOOL bValid)
  265. {
  266. DWORD dwWizButtons = 0;
  267. if (m_pParent->m_cMandatoryAttributes > 1)
  268. {
  269. // we have multiple pages
  270. if (m_iPage == 0)
  271. {
  272. // first page
  273. dwWizButtons = bValid ? PSWIZB_NEXT : 0;
  274. }
  275. else if (m_iPage == (m_pParent->m_cMandatoryAttributes-1))
  276. {
  277. // last page
  278. dwWizButtons = bValid ? (PSWIZB_BACK|PSWIZB_FINISH) : (PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  279. }
  280. else
  281. {
  282. // intemediate pages
  283. dwWizButtons = bValid ? (PSWIZB_BACK|PSWIZB_NEXT) : PSWIZB_BACK;
  284. }
  285. }
  286. else
  287. {
  288. // single page wizard
  289. ASSERT(m_iPage == 0);
  290. CString szCaption;
  291. szCaption.LoadString(IDS_WIZARD_OK);
  292. PropSheet_SetFinishText(m_pPropertySheetParent->GetSafeHwnd(), (LPCWSTR)szCaption);
  293. dwWizButtons = bValid ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH;
  294. }
  295. m_pPropertySheetParent->SetWizardButtons(dwWizButtons);
  296. }
  297. void CGenericCreateWizPage::_UpdateUI()
  298. {
  299. CString strName;
  300. GetDlgItemText(IDC_EDIT_ATTRIBUTE_VALUE, OUT strName);
  301. strName.TrimLeft();
  302. strName.TrimRight();
  303. _UpdateWizardButtons(!strName.IsEmpty());
  304. }
  305. /////////////////////////////////////////////////////////////////////
  306. BOOL CGenericCreateWizPage::OnSetActive()
  307. {
  308. const int nPage = m_iPage + 1; // Current page
  309. const int cPages = m_pParent->m_cMandatoryAttributes; // Total pages
  310. const TCHAR * pszClassName = m_pParent->m_pszObjectClass;
  311. ASSERT(pszClassName != NULL);
  312. CString strCaption;
  313. if (cPages > 1)
  314. strCaption.Format(IDS_sdd_CREATE_NEW_STEP, pszClassName, nPage, cPages);
  315. else
  316. strCaption.Format(IDS_s_CREATE_NEW, pszClassName);
  317. ASSERT(!strCaption.IsEmpty());
  318. m_pPropertySheetParent->SetWindowText(strCaption);
  319. _UpdateUI();
  320. return CPropertyPage::OnSetActive();
  321. } // CGenericCreateWizPage::OnSetActive()
  322. /////////////////////////////////////////////////////////////////////
  323. BOOL CGenericCreateWizPage::OnKillActive()
  324. {
  325. return CPropertyPage::OnKillActive();
  326. } // CGenericCreateWizPage::OnKillActive()
  327. /////////////////////////////////////////////////////////////////////
  328. // Create and persist the object.
  329. BOOL CGenericCreateWizPage::OnWizardFinish()
  330. {
  331. ASSERT(m_pParent != NULL);
  332. if (!UpdateData())
  333. {
  334. // DDX/DDV failed
  335. return FALSE;
  336. }
  337. HRESULT hr;
  338. CNewADsObjectCreateInfo * pNewADsObjectCreateInfo; // Temporary storage
  339. pNewADsObjectCreateInfo = m_pParent->m_pNewADsObjectCreateInfo;
  340. ASSERT(pNewADsObjectCreateInfo != NULL);
  341. // Write each attribute into the temporary storage
  342. CMandatoryADsAttributeList* pList = m_pParent->m_paMandatoryAttributeList;
  343. int iPage = 0;
  344. for (POSITION pos = pList->GetHeadPosition(); pos != NULL; )
  345. {
  346. CMandatoryADsAttribute* pAttribute = pList->GetNext(pos);
  347. ASSERT(pAttribute != NULL);
  348. if (iPage == 0)
  349. {
  350. // first page is the naming attribute
  351. hr = pNewADsObjectCreateInfo->HrCreateNew(pAttribute->m_varAttrValue.bstrVal);
  352. }
  353. else
  354. {
  355. hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(const_cast<PWSTR>((LPCWSTR)pAttribute->m_strAttrName),
  356. pAttribute->m_varAttrValue);
  357. }
  358. ASSERT(SUCCEEDED(hr));
  359. iPage++;
  360. }
  361. // Try to create and persist the object with all its attributes
  362. hr = pNewADsObjectCreateInfo->HrSetInfo();
  363. if (FAILED(hr))
  364. {
  365. // Failure to create object, prevent the wizard from terminating
  366. return FALSE;
  367. }
  368. return CPropertyPage::OnWizardFinish();
  369. } // CGenericCreateWizPage::OnWizardFinish()
  370. /////////////////////////////////////////////////////////////////////
  371. /////////////////////////////////////////////////////////////////////
  372. /////////////////////////////////////////////////////////////////////
  373. /////////////////////////////////////////////////////////////////////
  374. CCreateNewObjectGenericWizard::CCreateNewObjectGenericWizard()
  375. {
  376. m_pNewADsObjectCreateInfo = NULL;
  377. m_paPropertySheet = NULL;
  378. m_cMandatoryAttributes = 0;
  379. m_paMandatoryAttributeList = NULL;
  380. m_pPageArr = NULL;
  381. }
  382. /////////////////////////////////////////////////////////////////////
  383. CCreateNewObjectGenericWizard::~CCreateNewObjectGenericWizard()
  384. {
  385. if (m_pPageArr != NULL)
  386. {
  387. for (int i=0; i< m_cMandatoryAttributes; i++)
  388. delete m_pPageArr[i];
  389. free(m_pPageArr);
  390. }
  391. delete m_paPropertySheet;
  392. }
  393. /////////////////////////////////////////////////////////////////////
  394. // FDoModal()
  395. //
  396. // Query the mandatory attributes and create one wizard
  397. // page for each attribute.
  398. //
  399. BOOL
  400. CCreateNewObjectGenericWizard::FDoModal(
  401. INOUT CNewADsObjectCreateInfo * pNewADsObjectCreateInfo)
  402. {
  403. ASSERT(pNewADsObjectCreateInfo != NULL);
  404. m_pNewADsObjectCreateInfo = pNewADsObjectCreateInfo;
  405. m_pszObjectClass = m_pNewADsObjectCreateInfo->m_pszObjectClass;
  406. ASSERT(m_pszObjectClass != NULL);
  407. // Query the mandatory attributes
  408. m_paMandatoryAttributeList =
  409. m_pNewADsObjectCreateInfo->GetMandatoryAttributeListFromCacheItem();
  410. ASSERT(m_paMandatoryAttributeList != NULL);
  411. m_cMandatoryAttributes = (int)m_paMandatoryAttributeList->GetCount();
  412. if (m_cMandatoryAttributes <= 0)
  413. {
  414. ReportErrorEx(pNewADsObjectCreateInfo->GetParentHwnd(),
  415. IDS_ERR_CANNOT_FIND_MANDATORY_ATTRIBUTES,
  416. S_OK, MB_OK, NULL, 0);
  417. return FALSE;
  418. }
  419. m_paPropertySheet = new CPropertySheet(L"",
  420. CWnd::FromHandle(pNewADsObjectCreateInfo->GetParentHwnd()));
  421. // Create one wizard page for each attribute
  422. m_pPageArr = (CGenericCreateWizPage**)
  423. malloc(m_cMandatoryAttributes*sizeof(CGenericCreateWizPage*));
  424. if (m_pPageArr != NULL)
  425. {
  426. int iPage = 0;
  427. for (POSITION pos = m_paMandatoryAttributeList->GetHeadPosition(); pos != NULL; )
  428. {
  429. CMandatoryADsAttribute* pAttribute = m_paMandatoryAttributeList->GetNext(pos);
  430. ASSERT(pAttribute != NULL);
  431. m_pPageArr[iPage] = new CGenericCreateWizPage(this, iPage, INOUT pAttribute);
  432. iPage++;
  433. }
  434. }
  435. m_paPropertySheet->SetWizardMode();
  436. if (ID_WIZFINISH == m_paPropertySheet->DoModal())
  437. return TRUE;
  438. return FALSE;
  439. } // FDoModal()