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.

3650 lines
102 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 2002
  6. //
  7. // File: _util.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. PWSTR g_wzRootDSE = L"RootDSE";
  11. PWSTR g_wzSchemaNamingContext = L"schemaNamingContext";
  12. PWSTR g_wzLDAPAbstractSchemaFormat = L"LDAP://%s/schema/%s";
  13. //
  14. // Attribute names:
  15. //
  16. PWSTR g_wzDescription = L"description"; // ADSTYPE_CASE_IGNORE_STRING
  17. PWSTR g_wzName = L"name"; // ADSTYPE_CASE_IGNORE_STRING
  18. PWSTR g_wzMemberAttr = L"member"; // ADSTYPE_DN_STRING
  19. #define _WIZ_FULL_CTRL _GRANT_ALL
  20. // turn off check for warning C4127: conditional expression is constant
  21. #pragma warning (disable : 4127)
  22. ///////////////////////////////////////////////////////////////////////
  23. // CWString
  24. BOOL CWString::LoadFromResource(UINT uID)
  25. {
  26. int nBufferSize = 128;
  27. static const int nCountMax = 4;
  28. int nCount = 1;
  29. do
  30. {
  31. LPWSTR lpszBuffer = (LPWSTR)alloca(nCount*nBufferSize*sizeof(WCHAR));
  32. int iRet = ::LoadString(_Module.GetResourceInstance(), uID,
  33. lpszBuffer, nBufferSize);
  34. if (iRet == 0)
  35. {
  36. (*this) = L"?";
  37. return FALSE; // not found
  38. }
  39. if (iRet == nBufferSize-1) // truncation
  40. {
  41. if (nCount > nCountMax)
  42. {
  43. // too many reallocations
  44. (*this) = lpszBuffer;
  45. return FALSE; // truncation
  46. }
  47. // try to expand buffer
  48. nBufferSize *=2;
  49. nCount++;
  50. }
  51. else
  52. {
  53. // got it
  54. (*this) = lpszBuffer;
  55. break;
  56. }
  57. }
  58. while (TRUE);
  59. return TRUE;
  60. }
  61. ///////////////////////////////////////////////////////////////////////////////////
  62. // catenate the server name and the 1779 name
  63. // to get an LDAP path like "LDAP://myserv.foo.com./cn=host,..."
  64. void BuildLdapPathHelper(LPCWSTR lpszServerName, LPCWSTR lpszNamingContext, CWString& szLdapPath)
  65. {
  66. static LPCWSTR lpszFmt = L"LDAP://%s/%s";
  67. int nServerNameLen = lstrlen(lpszServerName)+1;
  68. int nFormatStringLen = lstrlen(lpszFmt)+1;
  69. int nNamingContext = lstrlen(lpszNamingContext)+1;
  70. // build the LDAP path for the schema class
  71. WCHAR* pwszNewObjectPath =
  72. (WCHAR*)alloca(sizeof(WCHAR)*(nServerNameLen+nFormatStringLen+nNamingContext));
  73. wsprintf(pwszNewObjectPath, lpszFmt, lpszServerName, lpszNamingContext);
  74. szLdapPath = pwszNewObjectPath;
  75. }
  76. // catenate the server name and the 1779 name
  77. // to get something like "\\myserv.foo.com.\cn=host,..."
  78. void BuildWin32PathHelper(LPCWSTR lpszServerName, LPCWSTR lpszNamingContext, CWString& szWin32Path)
  79. {
  80. static LPCWSTR lpszFmt = L"\\\\%s\\%s";
  81. int nServerNameLen = lstrlen(lpszServerName)+1;
  82. int nFormatStringLen = lstrlen(lpszFmt)+1;
  83. int nNamingContext = lstrlen(lpszNamingContext)+1;
  84. // build the LDAP path for the schema class
  85. WCHAR* pwszNewObjectPath =
  86. (WCHAR*)alloca(sizeof(WCHAR)*(nServerNameLen+nFormatStringLen+nNamingContext));
  87. wsprintf(pwszNewObjectPath, lpszFmt, lpszServerName, lpszNamingContext);
  88. szWin32Path = pwszNewObjectPath;
  89. }
  90. HRESULT GetCanonicalNameFromNamingContext(LPCWSTR lpszNamingContext, CWString& szCanonicalName)
  91. {
  92. szCanonicalName = L"";
  93. // assume in the form "cn=xyz,..."
  94. LPWSTR lpszCanonicalName = NULL;
  95. HRESULT hr = CrackName((LPWSTR)lpszNamingContext, &lpszCanonicalName, GET_OBJ_CAN_NAME);
  96. if (SUCCEEDED(hr) && (lpszCanonicalName != NULL))
  97. {
  98. szCanonicalName = lpszCanonicalName;
  99. }
  100. if (lpszCanonicalName != NULL)
  101. ::LocalFree(lpszCanonicalName);
  102. return hr;
  103. }
  104. /////////////////////////////////////////////////////////////////////////
  105. class CContainerProxyBase
  106. {
  107. public:
  108. CContainerProxyBase() { }
  109. virtual ~CContainerProxyBase() {}
  110. virtual BOOL Add(LPCWSTR lpsz) = 0;
  111. };
  112. template <class TOBJ, class TARR, class TFILTR> class CContainerProxy
  113. : public CContainerProxyBase
  114. {
  115. public:
  116. CContainerProxy(TARR* pArr, TFILTR* pFilter)
  117. {
  118. m_pArr = pArr;
  119. m_pFilter = pFilter;
  120. }
  121. virtual BOOL Add(LPCWSTR lpsz)
  122. {
  123. ULONG filterFlags = 0x0;
  124. if ( (m_pFilter == NULL) ||
  125. (m_pFilter->CanAdd(lpsz, &filterFlags)) )
  126. {
  127. TOBJ* p = new TOBJ(filterFlags, lpsz);
  128. if (p == NULL)
  129. return FALSE;
  130. return m_pArr->Add(p);
  131. }
  132. return TRUE;
  133. }
  134. private:
  135. TARR* m_pArr;
  136. TFILTR* m_pFilter;
  137. };
  138. /////////////////////////////////////////////////////////////////////////
  139. BOOL LoadStringHelper(UINT uID, LPTSTR lpszBuffer, int nBufferMax)
  140. {
  141. int iRet = ::LoadString(_Module.GetResourceInstance(), uID,
  142. lpszBuffer, nBufferMax);
  143. if (iRet == 0)
  144. {
  145. lpszBuffer[0] = NULL;
  146. return FALSE; // not found
  147. }
  148. if (iRet == nBufferMax-1)
  149. return FALSE; // truncation
  150. return TRUE;
  151. }
  152. BOOL GetStringFromHRESULTError(HRESULT hr, CWString& szErrorString, BOOL bTryADsIErrors)
  153. {
  154. HRESULT hrGetLast = S_OK;
  155. DWORD status;
  156. PTSTR ptzSysMsg = NULL;
  157. // first check if we have extended ADs errors
  158. if ((hr != S_OK) && bTryADsIErrors)
  159. {
  160. WCHAR Buf1[256], Buf2[256];
  161. hrGetLast = ::ADsGetLastError(&status, Buf1, 256, Buf2, 256);
  162. TRACE(_T("ADsGetLastError returned status of %lx, error: %s, name %s\n"),
  163. status, Buf1, Buf2);
  164. if ((status != ERROR_INVALID_DATA) && (status != 0))
  165. {
  166. hr = status;
  167. }
  168. }
  169. // try the system first
  170. int nChars = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  171. | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr,
  172. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  173. (PTSTR)&ptzSysMsg, 0, NULL);
  174. if (nChars == 0)
  175. {
  176. //try ads errors
  177. static HMODULE g_adsMod = 0;
  178. if (0 == g_adsMod)
  179. g_adsMod = GetModuleHandle (L"activeds.dll");
  180. nChars = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  181. | FORMAT_MESSAGE_FROM_HMODULE, g_adsMod, hr,
  182. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  183. (PTSTR)&ptzSysMsg, 0, NULL);
  184. }
  185. if (nChars > 0)
  186. {
  187. szErrorString = ptzSysMsg;
  188. ::LocalFree(ptzSysMsg);
  189. }
  190. return (nChars > 0);
  191. }
  192. BOOL GetStringFromWin32Error(DWORD dwErr, CWString& szErrorString)
  193. {
  194. return GetStringFromHRESULTError(HRESULT_FROM_WIN32(dwErr),szErrorString);
  195. }
  196. //
  197. // Given a GUID struct, it returns a GUID in string format, without {}
  198. //
  199. BOOL FormatStringGUID(LPWSTR lpszBuf, UINT nBufSize, const GUID* pGuid)
  200. {
  201. lpszBuf[0] = NULL;
  202. // if it is a NULL GUID*, just return an empty string
  203. if (pGuid == NULL)
  204. {
  205. return FALSE;
  206. }
  207. /*
  208. typedef struct _GUID {
  209. unsigned long Data1;
  210. unsigned short Data2;
  211. unsigned short Data3;
  212. unsigned char Data4[ 8 ];
  213. }
  214. */
  215. if(SUCCEEDED(StringCchPrintf(lpszBuf, nBufSize,
  216. L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  217. pGuid->Data1, pGuid->Data2, pGuid->Data3,
  218. pGuid->Data4[0], pGuid->Data4[1],
  219. pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4], pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7])))
  220. {
  221. return TRUE;
  222. }
  223. else
  224. {
  225. return FALSE;
  226. }
  227. }
  228. //
  229. // Given a GUID in string format (without {}) it returns a GUID struct
  230. //
  231. // e.g. "00299570-246d-11d0-a768-00aa006e0529" to a struct form
  232. //
  233. BOOL GuidFromString(GUID* pGuid, LPCWSTR lpszGuidString)
  234. {
  235. ZeroMemory(pGuid, sizeof(GUID));
  236. if (lpszGuidString == NULL)
  237. {
  238. return FALSE;
  239. }
  240. int nLen = lstrlen(lpszGuidString);
  241. // the string length should be 36
  242. if (nLen != 36)
  243. return FALSE;
  244. // add the braces to call the Win32 API
  245. LPWSTR lpszWithBraces = (LPWSTR)alloca((nLen+1+2)*sizeof(WCHAR)); // NULL plus {}
  246. wsprintf(lpszWithBraces, L"{%s}", lpszGuidString);
  247. return SUCCEEDED(::CLSIDFromString(lpszWithBraces, pGuid));
  248. }
  249. DWORD AddEntryInAcl(PEXPLICIT_ACCESS pAccessEntry, PACL* ppAcl)
  250. {
  251. // add an entry in the DACL
  252. PACL pOldAcl = *ppAcl;
  253. TRACE(L"Calling SetEntriesInAcl()\n");
  254. DWORD dwErr = ::SetEntriesInAcl(1, pAccessEntry, pOldAcl, ppAcl);
  255. TRACE(L"SetEntriesInAcl() returned dwErr = 0x%x\n", dwErr);
  256. if (dwErr == ERROR_SUCCESS && NULL != pOldAcl )
  257. {
  258. ::LocalFree(pOldAcl);
  259. }
  260. return dwErr;
  261. }
  262. #ifdef DBG
  263. void TraceGuid(LPCWSTR lpszMsg, const GUID* pGuid)
  264. {
  265. WCHAR szGuid[128];
  266. FormatStringGUID(szGuid, 128, pGuid);
  267. TRACE(L"%s %s\n", lpszMsg, szGuid);
  268. }
  269. #define TRACE_GUID(msg, pGuid)\
  270. TraceGuid(msg, pGuid);
  271. #else
  272. #define TRACE_GUID(msg, pGuid)
  273. #endif
  274. DWORD AddObjectRightInAcl(IN PSID pSid,
  275. IN ULONG uAccess,
  276. IN const GUID* pRightGUID,
  277. IN const GUID* pInheritGUID,
  278. IN OUT PACL* ppAcl)
  279. {
  280. // trace input parameters
  281. TRACE(L"AddObjectRightInAcl()\n");
  282. TRACE(L"ULONG uAccess = 0x%x\n", uAccess);
  283. TRACE_GUID(L"pRightGUID =", pRightGUID);
  284. TRACE_GUID(L"pInheritGUID =", pInheritGUID);
  285. EXPLICIT_ACCESS AccessEntry;
  286. ZeroMemory(&AccessEntry, sizeof(EXPLICIT_ACCESS));
  287. if( uAccess == 0 )
  288. return ERROR_SUCCESS;
  289. // initialize EXPLICIT_ACCESS
  290. AccessEntry.grfAccessPermissions = uAccess;
  291. AccessEntry.grfAccessMode = GRANT_ACCESS;
  292. AccessEntry.grfInheritance = SUB_CONTAINERS_ONLY_INHERIT;
  293. if (pInheritGUID != NULL)
  294. {
  295. AccessEntry.grfInheritance |= INHERIT_ONLY;
  296. }
  297. OBJECTS_AND_SID ObjectsAndSid;
  298. ZeroMemory(&ObjectsAndSid, sizeof(OBJECTS_AND_SID));
  299. TRACE(L"AccessEntry.grfAccessPermissions = 0x%x\n", AccessEntry.grfAccessPermissions);
  300. TRACE(L"AccessEntry.grfAccessMode = 0x%x\n", AccessEntry.grfAccessMode);
  301. TRACE(L"AccessEntry.grfInheritance = 0x%x\n", AccessEntry.grfInheritance);
  302. TRACE(L"BuildTrusteeWithObjectsAndSid()\n");
  303. BuildTrusteeWithObjectsAndSid(&(AccessEntry.Trustee),
  304. &ObjectsAndSid,
  305. const_cast<GUID*>(pRightGUID), // class, right or property
  306. const_cast<GUID*>(pInheritGUID), // inherit guid (class)
  307. pSid // SID for user or group
  308. );
  309. return ::AddEntryInAcl(&AccessEntry, ppAcl);
  310. }
  311. //////////////////////////////////////////////////////////////////////////////
  312. long SafeArrayGetCount(const VARIANT& refvar)
  313. {
  314. if (V_VT(&refvar) == VT_BSTR)
  315. {
  316. return (long)1;
  317. }
  318. if ( V_VT(&refvar) != ( VT_ARRAY | VT_VARIANT ) )
  319. {
  320. ASSERT(FALSE);
  321. return (long)0;
  322. }
  323. SAFEARRAY *saAttributes = V_ARRAY( &refvar );
  324. long start, end;
  325. HRESULT hr = SafeArrayGetLBound( saAttributes, 1, &start );
  326. if( FAILED(hr) )
  327. return (long)0;
  328. hr = SafeArrayGetUBound( saAttributes, 1, &end );
  329. if( FAILED(hr) )
  330. return (long)0;
  331. return (end - start + 1);
  332. }
  333. HRESULT VariantArrayToContainer(const VARIANT& refvar, CContainerProxyBase* pCont)
  334. {
  335. HRESULT hr = S_OK;
  336. long start, end, current;
  337. if (V_VT(&refvar) == VT_BSTR)
  338. {
  339. //TRACE(_T("VT_BSTR: %s\n"),V_BSTR(&refvar));
  340. pCont->Add(V_BSTR(&refvar));
  341. return S_OK;
  342. }
  343. //
  344. // Check the VARIANT to make sure we have
  345. // an array of variants.
  346. //
  347. if ( V_VT(&refvar) != ( VT_ARRAY | VT_VARIANT ) )
  348. {
  349. ASSERT(FALSE);
  350. return E_UNEXPECTED;
  351. }
  352. SAFEARRAY *saAttributes = V_ARRAY( &refvar );
  353. //
  354. // Figure out the dimensions of the array.
  355. //
  356. hr = SafeArrayGetLBound( saAttributes, 1, &start );
  357. if( FAILED(hr) )
  358. return hr;
  359. hr = SafeArrayGetUBound( saAttributes, 1, &end );
  360. if( FAILED(hr) )
  361. return hr;
  362. //
  363. // Process the array elements.
  364. //
  365. VARIANT SingleResult;
  366. for ( current = start ;
  367. current <= end ;
  368. current++ )
  369. {
  370. ::VariantInit( &SingleResult );
  371. hr = SafeArrayGetElement( saAttributes, &current, &SingleResult );
  372. if( FAILED(hr) )
  373. return hr;
  374. if ( V_VT(&SingleResult) != VT_BSTR )
  375. return E_UNEXPECTED;
  376. //TRACE(_T("VT_BSTR: %s\n"),V_BSTR(&SingleResult));
  377. pCont->Add(V_BSTR(&SingleResult));
  378. VariantClear( &SingleResult );
  379. }
  380. return S_OK;
  381. }
  382. HRESULT GetGlobalNamingContexts(LPCWSTR lpszServerName,
  383. CWString& szPhysicalSchemaNamingContext,
  384. CWString& szConfigurationNamingContext)
  385. {
  386. HRESULT hr = S_OK;
  387. CComPtr<IADs> spRootDSE;
  388. CWString szRootDSEPath;
  389. BuildLdapPathHelper(lpszServerName, g_wzRootDSE, szRootDSEPath);
  390. hr = ::ADsOpenObjectHelper(szRootDSEPath,
  391. IID_IADs,
  392. 0,
  393. (void**)&spRootDSE
  394. );
  395. if (FAILED(hr))
  396. {
  397. TRACE(L"Error opening ADsOpenObjectHelper(%S), hr=%x\n", (LPCWSTR)szRootDSEPath,hr);
  398. return hr;
  399. }
  400. CComVariant varSchemaNamingContext;
  401. hr = spRootDSE->Get(CComBSTR (g_wzSchemaNamingContext),
  402. &varSchemaNamingContext);
  403. if (FAILED(hr))
  404. {
  405. TRACE(_T("Error spRootDSE->Get((PWSTR)g_wzSchemaNamingContext), hr=%x\n"), hr);
  406. return hr;
  407. }
  408. // finally get value
  409. // (e.g. "cn=schema,cn=configuration,dc=marcocdev,dc=ntdev,dc=microsoft,dc=com")
  410. ASSERT(varSchemaNamingContext.vt == VT_BSTR);
  411. szPhysicalSchemaNamingContext = varSchemaNamingContext.bstrVal;
  412. // get the configuration container naming context
  413. CComVariant varConfigurationNamingContext;
  414. hr = spRootDSE->Get(CComBSTR (L"configurationNamingContext"),
  415. &varConfigurationNamingContext);
  416. if (FAILED(hr))
  417. {
  418. TRACE(L"Failed spRootDSE->Get(configurationNamingContext,&varConfigurationNamingContext), returned hr = 0x%x\n", hr);
  419. return hr;
  420. }
  421. ASSERT(varConfigurationNamingContext.vt == VT_BSTR);
  422. szConfigurationNamingContext = varConfigurationNamingContext.bstrVal;
  423. return hr;
  424. }
  425. LPCWSTR g_lpszSummaryIdent = L" ";
  426. LPCWSTR g_lpszSummaryNewLine = L"\r\n";
  427. void WriteSummaryTitleLine(CWString& szSummary, UINT nTitleID, LPCWSTR lpszNewLine)
  428. {
  429. CWString szTemp;
  430. szTemp.LoadFromResource(nTitleID);
  431. WriteSummaryLine(szSummary, szTemp, NULL, lpszNewLine);
  432. szSummary += lpszNewLine;
  433. }
  434. void WriteSummaryLine(CWString& szSummary, LPCWSTR lpsz, LPCWSTR lpszIdent, LPCWSTR lpszNewLine)
  435. {
  436. if (lpszIdent != NULL)
  437. szSummary += lpszIdent;
  438. szSummary += lpsz;
  439. szSummary += lpszNewLine;
  440. }
  441. //////////////////////////////////////////////////////////////////////////////
  442. LPCWSTR _GetFilePath()
  443. {
  444. static LPCWSTR g_lpszFileName = L"\\system32\\dssec.dat";
  445. static WCHAR g_lpszFilePath[2*MAX_PATH] = L"";
  446. if (g_lpszFilePath[0] == NULL)
  447. {
  448. UINT nLen = ::GetSystemWindowsDirectory(g_lpszFilePath, MAX_PATH);
  449. if (nLen == 0)
  450. return NULL;
  451. wcscat(g_lpszFilePath, g_lpszFileName);
  452. }
  453. return g_lpszFilePath;
  454. }
  455. ULONG GetClassFlags(LPCWSTR lpszClassName)
  456. {
  457. LPCWSTR lpszAttr = L"@";
  458. INT nDefault = 0;
  459. return ::GetPrivateProfileInt(lpszClassName, lpszAttr, nDefault, _GetFilePath());
  460. //return nDefault;
  461. }
  462. /////////////////////////////////////////////////////////////////////////////
  463. // CFilterEntry
  464. class CFilterEntry
  465. {
  466. public:
  467. CFilterEntry(LPWSTR lpszEntry)
  468. {
  469. m_lpszName = lpszEntry;
  470. m_nFlags = 0;
  471. Parse();
  472. }
  473. LPCWSTR m_lpszName;
  474. ULONG m_nFlags;
  475. bool operator<(CFilterEntry& x)
  476. {
  477. UNREFERENCED_PARAMETER (x);
  478. return false;
  479. }
  480. private:
  481. void Parse()
  482. {
  483. WCHAR* p = (WCHAR*)m_lpszName;
  484. while (*p != NULL)
  485. {
  486. if (*p == TEXT('='))
  487. {
  488. *p = NULL;
  489. m_nFlags = _wtoi(p+1);
  490. break;
  491. }
  492. p++;
  493. }
  494. }
  495. };
  496. class CFilterEntryHolder
  497. {
  498. public:
  499. CFilterEntryHolder()
  500. {
  501. m_pCharBuf = NULL;
  502. m_dwCharBufSize = 0;
  503. }
  504. ~CFilterEntryHolder()
  505. {
  506. if (m_pCharBuf != NULL)
  507. free(m_pCharBuf);
  508. }
  509. ULONG GetAttributeFlags(LPCWSTR lpszClassName, LPCWSTR lpszAttr);
  510. private:
  511. CWString m_szClassName;
  512. CGrowableArr<CFilterEntry> m_entries;
  513. WCHAR* m_pCharBuf;
  514. DWORD m_dwCharBufSize;
  515. BOOL _ReadFile();
  516. void _LoadFromFile();
  517. ULONG _FindInCache(LPCWSTR lpszAttr);
  518. };
  519. BOOL CFilterEntryHolder::_ReadFile()
  520. {
  521. if (m_pCharBuf == NULL)
  522. {
  523. m_dwCharBufSize = 4096;
  524. m_pCharBuf = (WCHAR*)malloc(sizeof(WCHAR)*m_dwCharBufSize);
  525. }
  526. if (m_pCharBuf == NULL)
  527. return FALSE;
  528. BOOL bNeedRealloc = FALSE;
  529. int nReallocCount = 0;
  530. do
  531. {
  532. DWORD dwCharCount = ::GetPrivateProfileSection(m_szClassName,
  533. m_pCharBuf, m_dwCharBufSize, _GetFilePath());
  534. if (dwCharCount == 0)
  535. return FALSE;
  536. bNeedRealloc = dwCharCount == (m_dwCharBufSize - 2);
  537. if (bNeedRealloc)
  538. {
  539. if (nReallocCount > 4)
  540. return FALSE;
  541. m_dwCharBufSize = 2*m_dwCharBufSize;
  542. WCHAR* pCharBuf = (WCHAR*)realloc(m_pCharBuf, sizeof(WCHAR)*m_dwCharBufSize);
  543. if ( pCharBuf )
  544. {
  545. m_pCharBuf = pCharBuf;
  546. }
  547. else
  548. break;
  549. nReallocCount++;
  550. }
  551. }
  552. while (bNeedRealloc);
  553. return TRUE;
  554. }
  555. void CFilterEntryHolder::_LoadFromFile()
  556. {
  557. m_entries.Clear();
  558. if (!_ReadFile())
  559. return;
  560. WCHAR* p = m_pCharBuf;
  561. WCHAR* pEntry = p;
  562. while ( ! (( *p == NULL ) && ( *(p+1) == NULL )) )
  563. {
  564. if (*p == NULL)
  565. {
  566. TRACE(_T("pEntry = <%s>\n"), pEntry);
  567. m_entries.Add(new CFilterEntry(pEntry));
  568. pEntry = p+1;
  569. }
  570. p++;
  571. }
  572. if ( pEntry < p)
  573. m_entries.Add(new CFilterEntry(pEntry)); // add the last one
  574. for (ULONG k=0; k<m_entries.GetCount(); k++)
  575. {
  576. TRACE(_T("k = %d, <%s> flags = %d\n"), k, m_entries[k]->m_lpszName, m_entries[k]->m_nFlags);
  577. }
  578. }
  579. ULONG CFilterEntryHolder::_FindInCache(LPCWSTR lpszAttr)
  580. {
  581. for (ULONG k=0; k<m_entries.GetCount(); k++)
  582. {
  583. if (_wcsicmp(m_entries[k]->m_lpszName, lpszAttr) == 0)
  584. return m_entries[k]->m_nFlags;
  585. }
  586. return 0; // default
  587. }
  588. ULONG CFilterEntryHolder::GetAttributeFlags(LPCWSTR lpszClassName, LPCWSTR lpszAttr)
  589. {
  590. if (_wcsicmp(lpszClassName, m_szClassName) != 0)
  591. {
  592. // class name changed
  593. m_szClassName = lpszClassName;
  594. _LoadFromFile();
  595. }
  596. return _FindInCache(lpszAttr);
  597. }
  598. ULONG GetAttributeFlags(LPCWSTR lpszClassName, LPCWSTR lpszAttr)
  599. {
  600. static CFilterEntryHolder g_holder;
  601. return g_holder.GetAttributeFlags(lpszClassName, lpszAttr);
  602. // INT nDefault = 0;
  603. // return ::GetPrivateProfileInt(lpszClassName, lpszAttr, nDefault, _GetFilePath());
  604. //return nDefault;
  605. }
  606. ///////////////////////////////////////////////////////////////////////
  607. // CPrincipal
  608. HRESULT CPrincipal::Initialize(PDS_SELECTION pDsSelection, HICON hClassIcon)
  609. {
  610. TRACE(_T("pwzName = %s\n"), pDsSelection->pwzName); // e.g. JoeB
  611. TRACE(_T("pwzADsPath = %s\n"), pDsSelection->pwzADsPath); // "LDAP:..." or "WINNT:..."
  612. TRACE(_T("pwzClass = %s\n"), pDsSelection->pwzClass); // e.g. "user"
  613. TRACE(_T("pwzUPN = %s\n"), pDsSelection->pwzUPN); // .e.g. "[email protected]."
  614. WCHAR const c_szClassComputer[] = L"computer";
  615. // get the SID
  616. ASSERT(pDsSelection->pvarFetchedAttributes);
  617. if (pDsSelection->pvarFetchedAttributes[0].vt == VT_EMPTY)
  618. {
  619. TRACE(L"CPrincipal::Initialize() failed on VT_EMPTY sid\n");
  620. // fatal error, we cannot proceed
  621. return E_INVALIDARG;
  622. }
  623. if (pDsSelection->pvarFetchedAttributes[0].vt != (VT_ARRAY | VT_UI1))
  624. {
  625. TRACE(L"CPrincipal::Initialize() failed on (VT_ARRAY | VT_UI1) sid\n");
  626. // fatal error, we cannot proceed
  627. return E_INVALIDARG;
  628. }
  629. // make sure we have a good SID
  630. PSID pSid = pDsSelection->pvarFetchedAttributes[0].parray->pvData;
  631. HRESULT hr = Initialize (pSid);
  632. if ( FAILED (hr) )
  633. return hr;
  634. // copy the icon
  635. m_hClassIcon = hClassIcon;
  636. // copy the strings
  637. m_szClass = pDsSelection->pwzClass;
  638. //Strip from Computer Name
  639. //16414 02/28/2000 *DS Admin snapin - DelWiz, need to strip the '$' from the end of computer names
  640. m_szName = pDsSelection->pwzName;
  641. if( m_szClass && m_szName && ( wcscmp( m_szClass, (LPWSTR)c_szClassComputer) == 0 ) )
  642. {
  643. // Strip the trailing '$'
  644. LPWSTR pszTemp;
  645. pszTemp= (LPWSTR)(LPCWSTR)m_szName;
  646. int nLen = lstrlen(pszTemp);
  647. if (nLen && pszTemp[nLen-1] == TEXT('$'))
  648. {
  649. pszTemp[nLen-1] = TEXT('\0');
  650. }
  651. }
  652. m_szADsPath = pDsSelection->pwzADsPath;
  653. if( m_szClass && m_szADsPath && ( wcscmp( m_szClass, (LPWSTR)c_szClassComputer) == 0 ) )
  654. {
  655. // Strip the trailing '$'
  656. LPWSTR pszTemp;
  657. pszTemp= (LPWSTR)(LPCWSTR)m_szADsPath;
  658. int nLen = lstrlen(pszTemp);
  659. if (nLen && pszTemp[nLen-1] == TEXT('$'))
  660. {
  661. pszTemp[nLen-1] = TEXT('\0');
  662. }
  663. }
  664. m_szUPN = pDsSelection->pwzUPN;
  665. // set the display name
  666. _ComposeDisplayName();
  667. return S_OK;
  668. }
  669. HRESULT CPrincipal::Initialize (PSID pSid)
  670. {
  671. if (!IsValidSid(pSid))
  672. {
  673. TRACE(L"CPrincipal::Initialize() failed on IsValidSid()\n");
  674. // fatal error, we cannot proceed
  675. return E_INVALIDARG;
  676. }
  677. // we have a good SID, copy it
  678. if (!m_sidHolder.Copy(pSid))
  679. {
  680. TRACE(L"CPrincipal::Initialize() failed on m_sidHolder.Copy(pSid)\n");
  681. // fatal error, we cannot proceed
  682. return E_OUTOFMEMORY;
  683. }
  684. return S_OK;
  685. }
  686. BOOL BuildSamName(LPCWSTR lpszPath, CWString& s)
  687. {
  688. // strip the WINNT provider and reverse slashes
  689. static LPCWSTR lpszPrefix = L"WinNT://";
  690. int nPrefixLen = lstrlen(lpszPrefix);
  691. if (_wcsnicmp(lpszPath, lpszPrefix, nPrefixLen ) != 0)
  692. {
  693. // not matching
  694. return FALSE;
  695. }
  696. // make a copy
  697. LPCWSTR lpzsTemp = lpszPath+nPrefixLen; // past the prefix
  698. s = L"";
  699. for (WCHAR* pChar = const_cast<LPWSTR>(lpzsTemp); (*pChar) != NULL; pChar++)
  700. {
  701. if (*pChar == L'/')
  702. s += L'\\';
  703. else
  704. s += *pChar;
  705. }
  706. return TRUE;
  707. }
  708. void CPrincipal::_ComposeDisplayName()
  709. {
  710. LPCWSTR lpszAddToName = NULL;
  711. // check if there is a UPN
  712. LPCWSTR lpszUPN = m_szUPN;
  713. if ( (lpszUPN != NULL) && (lstrlen(lpszUPN) > 0))
  714. {
  715. lpszAddToName = lpszUPN;
  716. }
  717. // as a second chance, add the domain\name
  718. LPCWSTR lpszPath = m_szADsPath;
  719. CWString sTemp;
  720. if ((lpszAddToName == NULL) && (lpszPath != NULL) && (lstrlen(lpszPath) > 0))
  721. {
  722. if (BuildSamName(lpszPath,sTemp))
  723. {
  724. lpszAddToName = sTemp;
  725. }
  726. }
  727. if (lpszAddToName != NULL)
  728. {
  729. static LPCWSTR lpszFormat = L"%s (%s)";
  730. size_t nLen = lstrlen(lpszAddToName) + lstrlen(lpszFormat) + m_szName.size() + 1;
  731. LPWSTR lpszTemp = (LPWSTR)alloca(nLen*sizeof(WCHAR));
  732. wsprintf(lpszTemp, lpszFormat, m_szName.c_str(), lpszAddToName);
  733. m_szDisplayName = lpszTemp;
  734. }
  735. else
  736. {
  737. // got nothing, just use the name
  738. m_szDisplayName = m_szName;
  739. }
  740. }
  741. BOOL CPrincipal::IsEqual(CPrincipal* p)
  742. {
  743. return (_wcsicmp(m_szADsPath, p->m_szADsPath) == 0);
  744. }
  745. BOOL CPrincipalList::AddIfNotPresent(CPrincipal* p)
  746. {
  747. CPrincipalList::iterator i;
  748. for (i = begin(); i != end(); ++i)
  749. {
  750. if ((*i)->IsEqual(p))
  751. {
  752. delete p; // duplicate
  753. return FALSE;
  754. }
  755. }
  756. push_back(p);
  757. return TRUE;
  758. }
  759. void CPrincipalList::WriteSummaryInfo(CWString& szSummary, LPCWSTR lpszIdent, LPCWSTR lpszNewLine)
  760. {
  761. WriteSummaryTitleLine(szSummary, IDS_DELEGWIZ_FINISH_PRINCIPALS, lpszNewLine);
  762. CPrincipalList::iterator i;
  763. for (i = begin(); i != end(); ++i)
  764. {
  765. WriteSummaryLine(szSummary, (*i)->GetDisplayName(), lpszIdent, lpszNewLine);
  766. }
  767. szSummary += lpszNewLine;
  768. }
  769. ///////////////////////////////////////////////////////////////////////
  770. // CControlRightInfo
  771. void CControlRightInfo::SetLocalizedName(UINT nLocalizationDisplayId, HMODULE hModule)
  772. {
  773. WCHAR szLocalizedDisplayName[256];
  774. DWORD dwChars = 0;
  775. if (hModule != NULL)
  776. {
  777. dwChars = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
  778. hModule,
  779. nLocalizationDisplayId,
  780. 0,
  781. szLocalizedDisplayName,
  782. 256,
  783. NULL);
  784. }
  785. if (dwChars > 0)
  786. {
  787. m_szLocalizedName = szLocalizedDisplayName;
  788. }
  789. else
  790. {
  791. // failed, just use the LDAP display name
  792. m_szLocalizedName = m_szLdapDisplayName;
  793. }
  794. // need to set the display name
  795. if (IsPropertySet())
  796. {
  797. CWString szPropertySetFormat;
  798. szPropertySetFormat.LoadFromResource(IDS_DELEGWIZ_RW_PROPERTYSET);
  799. WCHAR* lpszBuffer = (WCHAR*)alloca(sizeof(WCHAR)*(szPropertySetFormat.size()+m_szLocalizedName.size()+1));
  800. // we have a different display name
  801. wsprintf(lpszBuffer, szPropertySetFormat, (LPCWSTR)m_szLocalizedName);
  802. m_szDisplayName = lpszBuffer;
  803. }
  804. else
  805. {
  806. // same as raw
  807. m_szDisplayName = m_szLocalizedName;
  808. }
  809. }
  810. ///////////////////////////////////////////////////////////////////////
  811. // CControlRightInfoArray
  812. class CDsSecLib
  813. {
  814. public:
  815. CDsSecLib()
  816. {
  817. m_hInstance = ::LoadLibrary(L"dssec.dll");
  818. }
  819. ~CDsSecLib()
  820. {
  821. if (m_hInstance != NULL)
  822. ::FreeLibrary(m_hInstance);
  823. }
  824. HINSTANCE Get() { return m_hInstance; }
  825. private:
  826. HINSTANCE m_hInstance;
  827. };
  828. HRESULT CControlRightInfoArray::InitFromDS(CAdsiObject* pADSIObj,
  829. const GUID* pSchemaIDGUID)
  830. {
  831. TRACE(L"CControlRightInfoArray::InitFromDS()\n\n");
  832. ASSERT(pSchemaIDGUID != NULL);
  833. LPWSTR lpszSchemaIDGUID = (LPWSTR)alloca(128*sizeof(WCHAR));
  834. if(!lpszSchemaIDGUID)
  835. return E_OUTOFMEMORY;
  836. if (!FormatStringGUID(lpszSchemaIDGUID, 128, pSchemaIDGUID))
  837. {
  838. return E_INVALIDARG;
  839. }
  840. // build the LDAP path for the schema class
  841. CWString szPhysicalSchemaPath;
  842. LPCWSTR lpszPhysicalSchemaNamingContext = pADSIObj->GetPhysicalSchemaNamingContext();
  843. BuildLdapPathHelper(pADSIObj->GetServerName(), lpszPhysicalSchemaNamingContext, szPhysicalSchemaPath);
  844. // build the extended rights container naming context and LDAP path
  845. CWString szExtendedRightsNamingContext;
  846. szExtendedRightsNamingContext = L"CN=Extended-Rights,";
  847. szExtendedRightsNamingContext += pADSIObj->GetConfigurationNamingContext();
  848. CWString szExtendedRightsPath;
  849. BuildLdapPathHelper(pADSIObj->GetServerName(), szExtendedRightsNamingContext, szExtendedRightsPath);
  850. // bind a query to the extended rights container
  851. CAdsiSearch search;
  852. HRESULT hr = search.Init(szExtendedRightsPath);
  853. TRACE(L"search.Init(%s) returned hr = 0x%x\n", (LPCWSTR)szExtendedRightsPath, hr);
  854. if (FAILED(hr))
  855. {
  856. return hr;
  857. }
  858. // build an LDAP query string
  859. static LPCWSTR lpszFilterFormat = L"(&(objectCategory=CN=Control-Access-Right,%s)(AppliesTo=%s))";
  860. int nFmtLen = lstrlen(lpszFilterFormat);
  861. int nArgumentLen = lstrlen(lpszPhysicalSchemaNamingContext) + lstrlen(lpszSchemaIDGUID);
  862. WCHAR* lpszFilter = (WCHAR*)alloca(sizeof(WCHAR)*(nFmtLen+nArgumentLen+1));
  863. wsprintf(lpszFilter, lpszFilterFormat, lpszPhysicalSchemaNamingContext, lpszSchemaIDGUID);
  864. // build an array of wanted columns
  865. static const int cAttrs = 4;
  866. static LPCWSTR pszAttribsArr[cAttrs] =
  867. {
  868. L"displayName", // e.g. "Change Password"
  869. L"rightsGuid", // e.g. "ab721a53-1e2f-...." (i.e. GUID in string form w/o {})
  870. L"validAccesses", // bitmask of access righs
  871. L"localizationDisplayId" // bitmask of access righs
  872. };
  873. hr = search.SetSearchScope(ADS_SCOPE_ONELEVEL);
  874. TRACE(L"search.SetSearchScope(ADS_SCOPE_ONELEVEL) returned hr = 0x%x\n", hr);
  875. if (FAILED(hr))
  876. return hr;
  877. hr = search.DoQuery(lpszFilter, pszAttribsArr, cAttrs);
  878. TRACE(L"search.DoQuery(lpszFilter, pszAttribsArr, cAttrs) returned hr = 0x%x\n", hr);
  879. if (FAILED(hr))
  880. return hr;
  881. TRACE(L"\n");
  882. CWString szRightsGUID;
  883. ULONG nLocalizationDisplayId;
  884. // load DSSEC.DLL to provide localized
  885. CDsSecLib DsSecLib;
  886. while ((hr = search.GetNextRow()) != S_ADS_NOMORE_ROWS)
  887. {
  888. if (FAILED(hr))
  889. continue;
  890. CControlRightInfo* pInfo = new CControlRightInfo();
  891. HRESULT hr0 = search.GetColumnString(pszAttribsArr[0], pInfo->m_szLdapDisplayName);
  892. // the DS gives us the GUID in string form, but we need it in struct form
  893. HRESULT hr1 = search.GetColumnString(pszAttribsArr[1], szRightsGUID);
  894. if (SUCCEEDED(hr1))
  895. {
  896. if (!::GuidFromString(&(pInfo->m_rightsGUID), szRightsGUID.c_str()))
  897. {
  898. TRACE(L"GuidFromString(_, %s) failed!\n", szRightsGUID.c_str());
  899. hr1 = E_INVALIDARG;
  900. }
  901. }
  902. HRESULT hr2 = search.GetColumnInteger(pszAttribsArr[2], pInfo->m_fAccess);
  903. HRESULT hr3 = search.GetColumnInteger(pszAttribsArr[3], nLocalizationDisplayId);
  904. TRACE(L"Name = <%s>, \n Guid = <%s>, Access = 0x%x, nLocalizationDisplayId = %d\n",
  905. pInfo->m_szLdapDisplayName.c_str(), szRightsGUID.c_str(), pInfo->m_fAccess, nLocalizationDisplayId);
  906. if (FAILED(hr0) || FAILED(hr1) || FAILED(hr2) || FAILED(hr3))
  907. {
  908. TRACE(L"WARNING: discarding right, failed on columns: hr0 = 0x%x, hr1 = 0x%x, hr2 = 0x%x, hr3 = 0x%x\n",
  909. hr0, hr1, hr2, hr3);
  910. delete pInfo;
  911. }
  912. else
  913. {
  914. pInfo->SetLocalizedName(nLocalizationDisplayId, DsSecLib.Get());
  915. Add(pInfo);
  916. }
  917. } // while
  918. TRACE(L"\n\n");
  919. if (hr == S_ADS_NOMORE_ROWS)
  920. hr = S_OK;
  921. return hr;
  922. }
  923. //////////////////////////////////////////////////////////////////////
  924. // CPropertyRightInfo
  925. const ULONG CPropertyRightInfo::m_nRightCountMax = 2;
  926. const ULONG CPropertyRightInfo::m_nReadIndex = 0;
  927. const ULONG CPropertyRightInfo::m_nWriteIndex = 1;
  928. LPCWSTR CPropertyRightInfo::GetRightDisplayString(ULONG iRight)
  929. {
  930. static WCHAR szReadFmt[256] = L"";
  931. static WCHAR szWriteFmt[256] = L"";
  932. static WCHAR szReadAll[256] = L"";
  933. static WCHAR szWriteAll[256] = L"";
  934. static WCHAR szDisplay[512];
  935. ASSERT(GetName() != NULL); // must have a name!!!
  936. szDisplay[0] = NULL;
  937. WCHAR* pFmt = NULL;
  938. if (iRight == m_nReadIndex)
  939. {
  940. if (szReadFmt[0] == NULL)
  941. LoadStringHelper(IDS_DELEGWIZ_READ_PROPERTY, szReadFmt, ARRAYSIZE(szReadFmt));
  942. pFmt = szReadFmt;
  943. }
  944. else if (iRight == m_nWriteIndex)
  945. {
  946. if (szWriteFmt[0] == NULL)
  947. LoadStringHelper(IDS_DELEGWIZ_WRITE_PROPERTY, szWriteFmt, ARRAYSIZE(szWriteFmt));
  948. pFmt = szWriteFmt;
  949. }
  950. if(pFmt)
  951. {
  952. if(SUCCEEDED(StringCchPrintf(szDisplay, sizeof(szDisplay)/sizeof(WCHAR), pFmt, GetDisplayName())))
  953. {
  954. return szDisplay;
  955. }
  956. }
  957. return NULL;
  958. }
  959. void CPropertyRightInfo::SetRight(ULONG iRight, BOOL b)
  960. {
  961. switch (iRight)
  962. {
  963. case m_nReadIndex:
  964. if (b)
  965. m_Access |= ACTRL_DS_READ_PROP;
  966. else
  967. m_Access &= ~ACTRL_DS_READ_PROP;
  968. break;
  969. case m_nWriteIndex:
  970. if (b)
  971. m_Access |= ACTRL_DS_WRITE_PROP;
  972. else
  973. m_Access &= ~ACTRL_DS_WRITE_PROP;
  974. break;
  975. default:
  976. ASSERT(FALSE);
  977. };
  978. }
  979. ULONG CPropertyRightInfo::GetRight(ULONG iRight)
  980. {
  981. switch (iRight)
  982. {
  983. case m_nReadIndex:
  984. return (ULONG)ACTRL_DS_READ_PROP;
  985. break;
  986. case m_nWriteIndex:
  987. return (ULONG)ACTRL_DS_WRITE_PROP;
  988. break;
  989. default:
  990. ASSERT(FALSE);
  991. };
  992. return 0;
  993. }
  994. BOOL CPropertyRightInfo::IsRightSelected(ULONG iRight)
  995. {
  996. BOOL bRes = FALSE;
  997. switch (iRight)
  998. {
  999. case m_nReadIndex:
  1000. bRes = m_Access & ACTRL_DS_READ_PROP;
  1001. break;
  1002. case m_nWriteIndex:
  1003. bRes = m_Access & ACTRL_DS_WRITE_PROP;
  1004. break;
  1005. default:
  1006. ASSERT(FALSE);
  1007. };
  1008. return bRes;
  1009. }
  1010. //////////////////////////////////////////////////////////////////////
  1011. // CPropertyRightInfoArray
  1012. template <class T> class CClassPtr
  1013. {
  1014. public:
  1015. CClassPtr() { m_p = NULL;}
  1016. ~CClassPtr() { if (m_p) delete m_p;}
  1017. CClassPtr& operator=(T* p)
  1018. {
  1019. m_p = p;
  1020. return *this;
  1021. }
  1022. T* operator->()
  1023. {
  1024. return m_p;
  1025. }
  1026. T* operator&()
  1027. {
  1028. return m_p;
  1029. }
  1030. private:
  1031. T* m_p;
  1032. };
  1033. HRESULT CPropertyRightInfoArray::InitFromSchema(CAdsiObject* pADSIObj,
  1034. IADsClass * pDsSchemaClass,
  1035. LPCWSTR lpszClassName,
  1036. BOOL bUseFilter)
  1037. {
  1038. // setup
  1039. Clear();
  1040. CClassPtr<CPropertyRightInfoFilter> spFilter;
  1041. if (bUseFilter)
  1042. {
  1043. spFilter = new CPropertyRightInfoFilter();
  1044. spFilter->SetClassName(lpszClassName);
  1045. }
  1046. if (pDsSchemaClass == NULL)
  1047. {
  1048. ASSERT(lpszClassName == NULL);
  1049. return S_OK;
  1050. }
  1051. // get data from DS for specific properties
  1052. VARIANT MandatoryListVar, OptionalListVar;
  1053. ::VariantInit(&MandatoryListVar);
  1054. ::VariantInit(&OptionalListVar);
  1055. HRESULT hr = pDsSchemaClass->get_MandatoryProperties(&MandatoryListVar);
  1056. if (FAILED(hr))
  1057. {
  1058. ::VariantClear(&MandatoryListVar);
  1059. return hr;
  1060. }
  1061. hr = pDsSchemaClass->get_OptionalProperties(&OptionalListVar);
  1062. if (FAILED(hr))
  1063. {
  1064. ::VariantClear(&OptionalListVar);
  1065. return hr;
  1066. }
  1067. // add the results to the array
  1068. CContainerProxy<CPropertyRightInfo, CPropertyRightInfoArray, CPropertyRightInfoFilter>
  1069. cont(this, &spFilter);
  1070. VariantArrayToContainer(MandatoryListVar, &cont);
  1071. VariantArrayToContainer(OptionalListVar, &cont);
  1072. ::VariantClear(&MandatoryListVar);
  1073. ::VariantClear(&OptionalListVar);
  1074. // now need to set the friendly names
  1075. ULONG nCount = (ULONG) GetCount();
  1076. WCHAR szFrendlyName[1024];
  1077. HRESULT hrName;
  1078. for (ULONG i=0; i<nCount; i++)
  1079. {
  1080. LPCWSTR lpszName = (*this)[i]->GetName();
  1081. if (lpszName != NULL)
  1082. {
  1083. hrName = pADSIObj->GetFriendlyAttributeName(lpszClassName,
  1084. lpszName,
  1085. szFrendlyName, 1024);
  1086. ASSERT(SUCCEEDED(hrName));
  1087. (*this)[i]->SetDisplayName(SUCCEEDED(hrName) ? szFrendlyName : NULL);
  1088. }
  1089. }
  1090. // get guids
  1091. for (i=0; i<nCount; i++)
  1092. {
  1093. CPropertyRightInfo* pInfo = (*this)[i];
  1094. LPCWSTR lpszName = pInfo->GetName();
  1095. hr = pADSIObj->GetClassGuid(lpszName, TRUE, pInfo->m_schemaIDGUID);
  1096. if (SUCCEEDED(hr))
  1097. {
  1098. WCHAR szTest[128];
  1099. FormatStringGUID(szTest, 128, &(pInfo->m_schemaIDGUID));
  1100. TRACE(L"name = <%s>, guid = <%s>\n", lpszName, szTest);
  1101. }
  1102. else
  1103. {
  1104. TRACE(L"GetClassGuid(%s) failed hr = 0x%x\n", lpszName, hr);
  1105. return hr;
  1106. }
  1107. }
  1108. Sort();
  1109. return hr;
  1110. }
  1111. //////////////////////////////////////////////////////////////////////
  1112. // CClassRightInfo
  1113. const ULONG CClassRightInfo::m_nRightCountMax = 2;
  1114. const ULONG CClassRightInfo::m_nCreateIndex = 0;
  1115. const ULONG CClassRightInfo::m_nDeleteIndex = 1;
  1116. LPCWSTR CClassRightInfo::GetRightDisplayString(ULONG iRight)
  1117. {
  1118. static WCHAR szCreateFmt[256] = L"";
  1119. static WCHAR szDeleteFmt[256] = L"";
  1120. static WCHAR szCreateAll[256] = L"";
  1121. static WCHAR szDeleteAll[256] = L"";
  1122. static WCHAR szDisplay[512];
  1123. ASSERT(GetName() != NULL); // must have a name!!!
  1124. szDisplay[0] = NULL;
  1125. WCHAR* pFmt = NULL;
  1126. if (iRight == m_nCreateIndex)
  1127. {
  1128. if (szCreateFmt[0] == NULL)
  1129. LoadStringHelper(IDS_DELEGWIZ_CREATE_CLASS, szCreateFmt, ARRAYSIZE(szCreateFmt));
  1130. pFmt = szCreateFmt;
  1131. }
  1132. else if (iRight == m_nDeleteIndex)
  1133. {
  1134. if (szDeleteFmt[0] == NULL)
  1135. LoadStringHelper(IDS_DELEGWIZ_DELETE_CLASS, szDeleteFmt, ARRAYSIZE(szDeleteFmt));
  1136. pFmt = szDeleteFmt;
  1137. }
  1138. if(pFmt)
  1139. {
  1140. if(SUCCEEDED(StringCchPrintf(szDisplay,
  1141. sizeof(szDisplay)/sizeof(WCHAR),
  1142. pFmt,
  1143. GetDisplayName())))
  1144. {
  1145. return szDisplay;
  1146. }
  1147. }
  1148. return NULL;
  1149. }
  1150. void CClassRightInfo::SetRight(ULONG iRight, BOOL b)
  1151. {
  1152. switch (iRight)
  1153. {
  1154. case m_nCreateIndex:
  1155. if (b)
  1156. m_Access |= ACTRL_DS_CREATE_CHILD;
  1157. else
  1158. m_Access &= ~ACTRL_DS_CREATE_CHILD;
  1159. break;
  1160. case m_nDeleteIndex:
  1161. if (b)
  1162. m_Access |= ACTRL_DS_DELETE_CHILD;
  1163. else
  1164. m_Access &= ~ACTRL_DS_DELETE_CHILD;
  1165. break;
  1166. default:
  1167. ASSERT(FALSE);
  1168. };
  1169. }
  1170. ULONG CClassRightInfo::GetRight(ULONG iRight)
  1171. {
  1172. switch (iRight)
  1173. {
  1174. case m_nCreateIndex:
  1175. return (ULONG)ACTRL_DS_CREATE_CHILD;
  1176. break;
  1177. case m_nDeleteIndex:
  1178. return (ULONG)ACTRL_DS_DELETE_CHILD;
  1179. break;
  1180. default:
  1181. ASSERT(FALSE);
  1182. };
  1183. return 0;
  1184. }
  1185. BOOL CClassRightInfo::IsRightSelected(ULONG iRight)
  1186. {
  1187. BOOL bRes = FALSE;
  1188. switch (iRight)
  1189. {
  1190. case m_nCreateIndex:
  1191. bRes = m_Access & ACTRL_DS_CREATE_CHILD;
  1192. break;
  1193. case m_nDeleteIndex:
  1194. bRes = m_Access & ACTRL_DS_DELETE_CHILD;
  1195. break;
  1196. default:
  1197. ASSERT(FALSE);
  1198. };
  1199. return bRes;
  1200. }
  1201. //////////////////////////////////////////////////////////////////////
  1202. // CClassRightInfoArray
  1203. HRESULT CClassRightInfoArray::InitFromSchema(CAdsiObject* pADSIObj,
  1204. IADsClass* pDsSchemaClass,
  1205. BOOL bUseFilter)
  1206. {
  1207. // setup
  1208. Clear();
  1209. if (pDsSchemaClass == NULL)
  1210. return S_OK;
  1211. // read from DS
  1212. VARIANT ContainmentListVar;
  1213. ::VariantInit(&ContainmentListVar);
  1214. HRESULT hr = pDsSchemaClass->get_Containment(&ContainmentListVar);
  1215. if (FAILED(hr))
  1216. {
  1217. ::VariantClear(&ContainmentListVar);
  1218. return hr;
  1219. }
  1220. CClassPtr<CClassRightInfoFilter> spFilter;
  1221. if (bUseFilter)
  1222. {
  1223. spFilter = new CClassRightInfoFilter();
  1224. }
  1225. // add to array and filter
  1226. CContainerProxy<CClassRightInfo, CClassRightInfoArray, CClassRightInfoFilter>
  1227. cont(this, &spFilter);
  1228. VariantArrayToContainer(ContainmentListVar, &cont);
  1229. ::VariantClear(&ContainmentListVar);
  1230. // now need to set the friendly names
  1231. ULONG nCount = (ULONG) GetCount();
  1232. WCHAR szFrendlyName[1024];
  1233. HRESULT hrName;
  1234. for (ULONG i=0; i<nCount; i++)
  1235. {
  1236. LPCWSTR lpszName = (*this)[i]->GetName();
  1237. if (lpszName != NULL)
  1238. {
  1239. hrName = pADSIObj->GetFriendlyClassName(lpszName, szFrendlyName, 1024);
  1240. ASSERT(SUCCEEDED(hrName));
  1241. (*this)[i]->SetDisplayName(SUCCEEDED(hrName) ? szFrendlyName : NULL);
  1242. }
  1243. }
  1244. // get guids
  1245. for (i=0; i<nCount; i++)
  1246. {
  1247. CClassRightInfo* pInfo = (*this)[i];
  1248. LPCWSTR lpszName = pInfo->GetName();
  1249. hr = pADSIObj->GetClassGuid(lpszName, FALSE, pInfo->m_schemaIDGUID);
  1250. if (SUCCEEDED(hr))
  1251. {
  1252. WCHAR szTest[128];
  1253. FormatStringGUID(szTest, 128, &(pInfo->m_schemaIDGUID));
  1254. TRACE(L"name = <%s>, guid = <%s>\n", lpszName, szTest);
  1255. }
  1256. else
  1257. {
  1258. TRACE(L"GetClassGuid(%s) failed hr = 0x%x\n", lpszName, hr);
  1259. return hr;
  1260. }
  1261. }
  1262. Sort();
  1263. return hr;
  1264. }
  1265. ///////////////////////////////////////////////////////////////////////
  1266. // CAccessPermissionsHolderBase
  1267. CAccessPermissionsHolderBase::CAccessPermissionsHolderBase(BOOL bUseFilter)
  1268. {
  1269. m_bUseFilter = bUseFilter;
  1270. }
  1271. CAccessPermissionsHolderBase::~CAccessPermissionsHolderBase()
  1272. {
  1273. Clear();
  1274. }
  1275. void CAccessPermissionsHolderBase::Clear()
  1276. {
  1277. m_accessRightInfoArr.Clear();
  1278. m_controlRightInfoArr.Clear();
  1279. m_propertyRightInfoArray.Clear();
  1280. m_classRightInfoArray.Clear();
  1281. }
  1282. BOOL CAccessPermissionsHolderBase::HasPermissionSelected()
  1283. {
  1284. ULONG i,j;
  1285. // check access rigths
  1286. for (i = 0; i < m_accessRightInfoArr.GetCount(); i++)
  1287. {
  1288. if (m_accessRightInfoArr[i]->IsSelected())
  1289. return TRUE;
  1290. }
  1291. // check control rigths
  1292. for (i = 0; i < m_controlRightInfoArr.GetCount(); i++)
  1293. {
  1294. if (m_controlRightInfoArr[i]->IsSelected())
  1295. return TRUE;
  1296. }
  1297. // subobjects rigths
  1298. for (i = 0; i < m_classRightInfoArray.GetCount(); i++)
  1299. {
  1300. for (j=0; j< m_classRightInfoArray[i]->GetRightCount(); j++)
  1301. {
  1302. if ( m_classRightInfoArray[i]->IsRightSelected(j) )
  1303. return TRUE;
  1304. }
  1305. }
  1306. // property rights
  1307. for (i = 0; i < m_propertyRightInfoArray.GetCount(); i++)
  1308. {
  1309. for (j=0; j< m_propertyRightInfoArray[i]->GetRightCount(); j++)
  1310. {
  1311. if ( m_propertyRightInfoArray[i]->IsRightSelected(j) )
  1312. return TRUE;
  1313. }
  1314. }
  1315. return FALSE;
  1316. }
  1317. /*
  1318. typedef struct _ACTRL_CONTROL_INFOW
  1319. {
  1320. LPWSTR lpControlId;
  1321. LPWSTR lpControlName;
  1322. } ACTRL_CONTROL_INFOW, *PACTRL_CONTROL_INFOW;
  1323. typedef struct _ACTRL_ACCESS_INFOW
  1324. {
  1325. ULONG fAccessPermission;
  1326. LPWSTR lpAccessPermissionName;
  1327. } ACTRL_ACCESS_INFOW, *PACTRL_ACCESS_INFOW;
  1328. */
  1329. HRESULT CAccessPermissionsHolderBase::ReadDataFromDS(CAdsiObject* pADSIObj,
  1330. LPCWSTR /*lpszObjectNamingContext*/,
  1331. LPCWSTR lpszClassName,
  1332. const GUID* pSchemaIDGUID,
  1333. BOOL bChildClass,
  1334. BOOL bHideListObject)
  1335. {
  1336. #if DBG
  1337. WCHAR szGUID[128];
  1338. FormatStringGUID(szGUID, 128, pSchemaIDGUID);
  1339. TRACE(L"CAccessPermissionsHolderBase::ReadDataFromDS(_, %s, %s)\n",
  1340. lpszClassName, szGUID);
  1341. #endif
  1342. Clear();
  1343. HRESULT hr = S_OK;
  1344. if (pSchemaIDGUID != NULL)
  1345. {
  1346. hr = m_controlRightInfoArr.InitFromDS(pADSIObj, pSchemaIDGUID);
  1347. TRACE(L"hr = m_controlRightInfoArr.InitFromDS(...) returned hr = 0x%x\n", hr);
  1348. if (FAILED(hr))
  1349. {
  1350. return hr;
  1351. }
  1352. }
  1353. hr = _ReadClassInfoFromDS(pADSIObj, lpszClassName);
  1354. if (FAILED(hr))
  1355. {
  1356. return hr;
  1357. }
  1358. hr = _LoadAccessRightInfoArrayFromTable(bChildClass,bHideListObject);
  1359. return hr;
  1360. }
  1361. HRESULT CAccessPermissionsHolderBase::_ReadClassInfoFromDS(CAdsiObject* pADSIObj,
  1362. LPCWSTR lpszClassName)
  1363. {
  1364. HRESULT hr = S_OK;
  1365. CComPtr<IADsClass> spSchemaObjectClass;
  1366. if (lpszClassName != NULL)
  1367. {
  1368. int nServerNameLen = lstrlen(pADSIObj->GetServerName());
  1369. int nClassNameLen = lstrlen(lpszClassName);
  1370. int nFormatStringLen = lstrlen(g_wzLDAPAbstractSchemaFormat);
  1371. // build the LDAP path for the schema class
  1372. WCHAR* pwszSchemaObjectPath =
  1373. (WCHAR*)alloca(sizeof(WCHAR)*(nServerNameLen+nClassNameLen+nFormatStringLen+1));
  1374. wsprintf(pwszSchemaObjectPath, g_wzLDAPAbstractSchemaFormat, pADSIObj->GetServerName(), lpszClassName);
  1375. // get the schema class ADSI object
  1376. hr = ::ADsOpenObjectHelper(pwszSchemaObjectPath,
  1377. IID_IADsClass, 0,(void**)&spSchemaObjectClass);
  1378. if (FAILED(hr))
  1379. return hr;
  1380. }
  1381. //TRACE(_T("\nObject Properties\n\n"));
  1382. hr = m_propertyRightInfoArray.InitFromSchema(pADSIObj, spSchemaObjectClass,lpszClassName, m_bUseFilter);
  1383. if (FAILED(hr))
  1384. return hr;
  1385. //TRACE(_T("\nObject contained classes\n\n"));
  1386. return m_classRightInfoArray.InitFromSchema(pADSIObj, spSchemaObjectClass, m_bUseFilter);
  1387. }
  1388. DWORD CAccessPermissionsHolderBase::UpdateAccessList( CPrincipal* pPrincipal,
  1389. CSchemaClassInfo* pClassInfo,
  1390. LPCWSTR /*lpszServerName*/,
  1391. LPCWSTR /*lpszPhysicalSchemaNamingContext*/,
  1392. PACL *ppAcl)
  1393. {
  1394. TRACE(L"CAccessPermissionsHolderBase::UpdateAccessList()\n");
  1395. const GUID* pClassGUID = NULL;
  1396. TRACE(L"User or Group Name: %s\n", pPrincipal->GetDisplayName());
  1397. BOOL bChildClass = TRUE;
  1398. if (pClassInfo != NULL)
  1399. {
  1400. pClassGUID = pClassInfo->GetSchemaGUID();
  1401. bChildClass = (pClassInfo->m_dwChildClass != CHILD_CLASS_NOT_EXIST );
  1402. }
  1403. return _UpdateAccessListHelper(pPrincipal->GetSid(), pClassGUID, ppAcl,bChildClass);
  1404. }
  1405. DWORD CAccessPermissionsHolderBase::_UpdateAccessListHelper(PSID pSid,
  1406. const GUID* pClassGUID,
  1407. PACL *ppAcl,
  1408. BOOL bChildClass)
  1409. {
  1410. TRACE(L"CAccessPermissionsHolderBase::_UpdateAccessListHelper()\n");
  1411. ASSERT(pSid != NULL);
  1412. ULONG AccessAllClass = 0;
  1413. ULONG AccessAllProperty = 0;
  1414. DWORD dwErr = 0;
  1415. // set common variables
  1416. ULONG uAccess = 0; // to be set and reset as see fit
  1417. if (m_accessRightInfoArr[0]->IsSelected()) // full control
  1418. {
  1419. uAccess = _WIZ_FULL_CTRL;
  1420. dwErr = ::AddObjectRightInAcl(pSid, uAccess, NULL, pClassGUID, ppAcl);
  1421. if (dwErr != ERROR_SUCCESS)
  1422. goto exit;
  1423. }
  1424. else
  1425. {
  1426. // add an entry for all the standard access permissions:
  1427. // OR all the selected permissions together
  1428. uAccess = 0;
  1429. UINT nSel = 0;
  1430. for (UINT k=0; k < m_accessRightInfoArr.GetCount(); k++)
  1431. {
  1432. if (m_accessRightInfoArr[k]->IsSelected())
  1433. {
  1434. nSel++;
  1435. uAccess |= m_accessRightInfoArr[k]->GetAccess();
  1436. }
  1437. } // for
  1438. if( !bChildClass )
  1439. uAccess &= (~(ACTRL_DS_CREATE_CHILD|ACTRL_DS_DELETE_CHILD));
  1440. if (nSel > 0)
  1441. {
  1442. // keep track of "All" flags
  1443. if (uAccess & ACTRL_DS_READ_PROP)
  1444. AccessAllProperty |= ACTRL_DS_READ_PROP;
  1445. if (uAccess & ACTRL_DS_WRITE_PROP)
  1446. AccessAllProperty |= ACTRL_DS_WRITE_PROP;
  1447. if (uAccess & ACTRL_DS_CREATE_CHILD)
  1448. AccessAllClass |= ACTRL_DS_CREATE_CHILD;
  1449. if (uAccess & ACTRL_DS_DELETE_CHILD)
  1450. AccessAllClass |= ACTRL_DS_DELETE_CHILD;
  1451. dwErr = ::AddObjectRightInAcl(pSid, uAccess, NULL, pClassGUID, ppAcl);
  1452. if (dwErr != ERROR_SUCCESS)
  1453. goto exit;
  1454. }
  1455. // add an entry for each of the control rights
  1456. for (k=0; k < m_controlRightInfoArr.GetCount(); k++)
  1457. {
  1458. if (m_controlRightInfoArr[k]->IsSelected())
  1459. {
  1460. uAccess = m_controlRightInfoArr[k]->GetAccess();
  1461. dwErr = ::AddObjectRightInAcl(pSid, uAccess,
  1462. m_controlRightInfoArr[k]->GetRightsGUID(),
  1463. pClassGUID,
  1464. ppAcl);
  1465. if (dwErr != ERROR_SUCCESS)
  1466. goto exit;
  1467. }
  1468. } // for
  1469. // add an entry for each of the subobjects rigths
  1470. for (ULONG iClass = 0; iClass < m_classRightInfoArray.GetCount(); iClass++)
  1471. {
  1472. ULONG Access = m_classRightInfoArray[iClass]->GetAccess();
  1473. if (Access != 0)
  1474. {
  1475. if (iClass > 0)
  1476. {
  1477. ULONG nRightCount = m_classRightInfoArray[iClass]->GetRightCount();
  1478. for (ULONG iCurrRight=0; iCurrRight<nRightCount; iCurrRight++)
  1479. {
  1480. // the first entry is the Create/Delete All, no need for other permissions,
  1481. ULONG currAccess = m_classRightInfoArray[iClass]->GetRight(iCurrRight);
  1482. if (currAccess & AccessAllClass)
  1483. {
  1484. // right already present, strip out
  1485. Access &= ~currAccess;
  1486. }
  1487. } // for
  1488. }
  1489. if (Access != 0)
  1490. {
  1491. uAccess = Access;
  1492. dwErr = ::AddObjectRightInAcl(pSid, uAccess,
  1493. m_classRightInfoArray[iClass]->GetSchemaGUID(),
  1494. pClassGUID,
  1495. ppAcl);
  1496. if (dwErr != ERROR_SUCCESS)
  1497. goto exit;
  1498. }
  1499. }
  1500. } // for
  1501. // add an entry for each property right to set
  1502. for (ULONG iProperty=0; iProperty < m_propertyRightInfoArray.GetCount(); iProperty++)
  1503. {
  1504. ULONG Access = m_propertyRightInfoArray[iProperty]->GetAccess();
  1505. if (Access != 0)
  1506. {
  1507. if (iProperty > 0)
  1508. {
  1509. ULONG nRightCount = m_propertyRightInfoArray[iProperty]->GetRightCount();
  1510. for (ULONG iCurrRight=0; iCurrRight<nRightCount; iCurrRight++)
  1511. {
  1512. // the first entry is the Create/Delete All, no need for other permissions,
  1513. ULONG currAccess = m_propertyRightInfoArray[iProperty]->GetRight(iCurrRight);
  1514. if (currAccess & AccessAllProperty)
  1515. {
  1516. // right already present, strip out
  1517. Access &= ~currAccess;
  1518. }
  1519. } // for
  1520. }
  1521. if (Access != 0)
  1522. {
  1523. uAccess = Access;
  1524. dwErr = ::AddObjectRightInAcl(pSid, uAccess,
  1525. m_propertyRightInfoArray[iProperty]->GetSchemaGUID(),
  1526. pClassGUID,
  1527. ppAcl);
  1528. if (dwErr != ERROR_SUCCESS)
  1529. goto exit;
  1530. }
  1531. }
  1532. }
  1533. } // if
  1534. exit:
  1535. return dwErr;
  1536. }
  1537. ///////////////////////////////////////////////////////////////////////
  1538. // CCustomAccessPermissionsHolder
  1539. CCustomAccessPermissionsHolder::CCustomAccessPermissionsHolder()
  1540. : CAccessPermissionsHolderBase(TRUE)
  1541. {
  1542. }
  1543. CCustomAccessPermissionsHolder::~CCustomAccessPermissionsHolder()
  1544. {
  1545. Clear();
  1546. }
  1547. void CCustomAccessPermissionsHolder::Clear()
  1548. {
  1549. CAccessPermissionsHolderBase::Clear();
  1550. m_listViewItemArr.Clear();
  1551. }
  1552. struct CAccessRightTableEntry
  1553. {
  1554. UINT m_nStringID;
  1555. ULONG m_fAccess;
  1556. };
  1557. #define _WIZ_READ \
  1558. (READ_CONTROL | ACTRL_DS_LIST | ACTRL_DS_READ_PROP | ACTRL_DS_LIST_OBJECT)
  1559. #define _WIZ_WRITE \
  1560. (ACTRL_DS_SELF | ACTRL_DS_WRITE_PROP)
  1561. HRESULT CCustomAccessPermissionsHolder::_LoadAccessRightInfoArrayFromTable(BOOL bCreateDeleteChild,BOOL bHideListObject)
  1562. {
  1563. static CAccessRightTableEntry _pTable[] =
  1564. {
  1565. { IDS_DELEGWIZ_ACTRL_FULL, _WIZ_FULL_CTRL },
  1566. { IDS_DELEGWIZ_ACTRL_READ, _WIZ_READ },
  1567. { IDS_DELEGWIZ_ACTRL_WRITE, _WIZ_WRITE },
  1568. /*
  1569. { IDS_DELEGWIZ_ACTRL_SYSTEM_ACCESS, ACCESS_SYSTEM_SECURITY },
  1570. { IDS_DELEGWIZ_ACTRL_DELETE, DELETE },
  1571. { IDS_DELEGWIZ_ACTRL_READ_CONTROL, READ_CONTROL },
  1572. { IDS_DELEGWIZ_ACTRL_CHANGE_ACCESS, WRITE_DAC },
  1573. { IDS_DELEGWIZ_ACTRL_CHANGE_OWNER, WRITE_OWNER },
  1574. */
  1575. { IDS_DELEGWIZ_ACTRL_DS_CREATE_CHILD, ACTRL_DS_CREATE_CHILD },
  1576. { IDS_DELEGWIZ_ACTRL_DS_DELETE_CHILD, ACTRL_DS_DELETE_CHILD },
  1577. /*
  1578. { IDS_DELEGWIZ_ACTRL_DS_LIST, ACTRL_DS_LIST },
  1579. { IDS_DELEGWIZ_ACTRL_DS_SELF, ACTRL_DS_SELF },
  1580. */
  1581. { IDS_DELEGWIZ_ACTRL_DS_READ_PROP, ACTRL_DS_READ_PROP },
  1582. { IDS_DELEGWIZ_ACTRL_DS_WRITE_PROP, ACTRL_DS_WRITE_PROP },
  1583. /*
  1584. { IDS_DELEGWIZ_ACTRL_DS_DELETE_TREE, ACTRL_DS_DELETE_TREE },
  1585. { IDS_DELEGWIZ_ACTRL_DS_LIST_OBJECT, ACTRL_DS_LIST_OBJECT },
  1586. { IDS_DELEGWIZ_ACTRL_DS_CONTROL_ACCESS, ACTRL_DS_CONTROL_ACCESS },
  1587. */
  1588. {0, 0x0 } // end of table marker
  1589. };
  1590. if(bHideListObject)
  1591. {
  1592. _pTable[0].m_fAccess &= ~ACTRL_DS_LIST_OBJECT;
  1593. _pTable[1].m_fAccess &= ~ACTRL_DS_LIST_OBJECT;
  1594. }
  1595. TRACE(L"\nCCustomAccessPermissionsHolder::_LoadAccessRightInfoArrayFromTable()\n\n");
  1596. for(CAccessRightTableEntry* pCurrEntry = (CAccessRightTableEntry*)_pTable;
  1597. pCurrEntry->m_nStringID != NULL; pCurrEntry++)
  1598. {
  1599. if( !bCreateDeleteChild && (
  1600. (pCurrEntry->m_fAccess == ACTRL_DS_CREATE_CHILD) ||
  1601. (pCurrEntry->m_fAccess == ACTRL_DS_DELETE_CHILD ) ) )
  1602. continue;
  1603. CAccessRightInfo* pInfo = new CAccessRightInfo();
  1604. if( !pInfo )
  1605. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
  1606. if (!pInfo->m_szDisplayName.LoadFromResource(pCurrEntry->m_nStringID))
  1607. {
  1608. delete pInfo;
  1609. continue;
  1610. }
  1611. pInfo->m_fAccess = pCurrEntry->m_fAccess;
  1612. TRACE(L"Display Name = <%s>, Access = 0x%x\n",
  1613. pInfo->m_szDisplayName.c_str(), pInfo->m_fAccess);
  1614. m_accessRightInfoArr.Add(pInfo);
  1615. }
  1616. TRACE(L"\nCCustomAccessPermissionsHolder::_LoadAccessRightInfoArrayFromTable() exiting\n\n");
  1617. return S_OK;
  1618. }
  1619. void CCustomAccessPermissionsHolder::_SelectAllRigths()
  1620. {
  1621. ULONG i,j;
  1622. // select all access rigths
  1623. for (i = 0; i < m_accessRightInfoArr.GetCount(); i++)
  1624. {
  1625. m_accessRightInfoArr[i]->Select(TRUE);
  1626. }
  1627. // select all control rights rigths
  1628. for (i = 0; i < m_controlRightInfoArr.GetCount(); i++)
  1629. {
  1630. m_controlRightInfoArr[i]->Select(TRUE);
  1631. }
  1632. // select all subobjects rigths
  1633. for (i = 0; i < m_classRightInfoArray.GetCount(); i++)
  1634. {
  1635. for (j=0; j< m_classRightInfoArray[i]->GetRightCount(); j++)
  1636. {
  1637. m_classRightInfoArray[i]->SetRight(j, TRUE);
  1638. }
  1639. }
  1640. // select all property rights
  1641. for (i = 0; i < m_propertyRightInfoArray.GetCount(); i++)
  1642. {
  1643. for (j=0; j< m_propertyRightInfoArray[i]->GetRightCount(); j++)
  1644. {
  1645. m_propertyRightInfoArray[i]->SetRight(j, TRUE);
  1646. }
  1647. }
  1648. }
  1649. void CCustomAccessPermissionsHolder::_SelectAllPropertyRigths(ULONG fAccessPermission)
  1650. {
  1651. for (UINT i=0; i<m_propertyRightInfoArray.GetCount(); i++)
  1652. {
  1653. m_propertyRightInfoArray[i]->AddAccessRight(fAccessPermission);
  1654. }
  1655. }
  1656. void CCustomAccessPermissionsHolder::_SelectAllSubObjectRigths(ULONG fAccessPermission)
  1657. {
  1658. for (UINT i=0; i<m_classRightInfoArray.GetCount(); i++)
  1659. {
  1660. m_classRightInfoArray[i]->AddAccessRight(fAccessPermission);
  1661. }
  1662. }
  1663. void CCustomAccessPermissionsHolder::_DeselectAssociatedRights(ULONG fAccessPermission)
  1664. {
  1665. // deselect full control first
  1666. m_accessRightInfoArr[0]->Select(FALSE);
  1667. if (fAccessPermission != 0)
  1668. {
  1669. // deselect any other basic right that contains the flag
  1670. UINT nCount = (ULONG) m_accessRightInfoArr.GetCount();
  1671. for (ULONG iAccess=0; iAccess<nCount; iAccess++)
  1672. {
  1673. if (m_accessRightInfoArr[iAccess]->GetAccess() & fAccessPermission)
  1674. m_accessRightInfoArr[iAccess]->Select(FALSE);
  1675. }
  1676. }
  1677. }
  1678. void CCustomAccessPermissionsHolder::Select(IN CRigthsListViewItem* pItem,
  1679. IN BOOL bSelect,
  1680. OUT ULONG* pnNewFilterState)
  1681. {
  1682. ASSERT(pItem != NULL);
  1683. *pnNewFilterState = 0;
  1684. switch (pItem->m_type)
  1685. {
  1686. case CRigthsListViewItem::access: // access rights
  1687. case CRigthsListViewItem::ctrl: // general rights
  1688. {
  1689. // make the change to the entry that was passed in as argument
  1690. if (pItem->m_type == CRigthsListViewItem::access)
  1691. {
  1692. m_accessRightInfoArr[pItem->m_iIndex]->Select(bSelect);
  1693. }
  1694. else
  1695. {
  1696. m_controlRightInfoArr[pItem->m_iIndex]->Select(bSelect);
  1697. }
  1698. // now see if this triggers changes to the other entries
  1699. if (bSelect)
  1700. {
  1701. if (pItem->m_type == CRigthsListViewItem::access)
  1702. {
  1703. if (pItem->m_iIndex == 0)
  1704. {
  1705. // the user checked full control, need to select all the rigths
  1706. _SelectAllRigths();
  1707. // set flags to mark which set of flags is affected
  1708. *pnNewFilterState |= FILTER_EXP_GEN;
  1709. if (m_propertyRightInfoArray.GetCount() > 0)
  1710. *pnNewFilterState |= FILTER_EXP_PROP;
  1711. if (m_classRightInfoArray.GetCount() > 0)
  1712. *pnNewFilterState |= FILTER_EXP_SUBOBJ;
  1713. }
  1714. else
  1715. {
  1716. // check if the user selected some read/write all or create/delete all right
  1717. UINT iAccess = pItem->m_iIndex;
  1718. ULONG fAccessPermission = m_accessRightInfoArr[iAccess]->GetAccess();
  1719. if ((fAccessPermission == _WIZ_READ) || (fAccessPermission == _WIZ_WRITE) )
  1720. {
  1721. // need to select all the Read or Write Properties entried
  1722. // and the ACTRL_DS_READ_PROP ACTRL_DS_WRITE_PROP (Read All/Write All)
  1723. // select all access rigths
  1724. UINT nAssociatedAccessRight =
  1725. (fAccessPermission == _WIZ_READ) ? ACTRL_DS_READ_PROP : ACTRL_DS_WRITE_PROP;
  1726. for (UINT i = 0; i < m_accessRightInfoArr.GetCount(); i++)
  1727. {
  1728. if (m_accessRightInfoArr[i]->GetAccess() == nAssociatedAccessRight)
  1729. {
  1730. m_accessRightInfoArr[i]->Select(TRUE);
  1731. _SelectAllPropertyRigths(nAssociatedAccessRight);
  1732. if (m_propertyRightInfoArray.GetCount() > 0)
  1733. *pnNewFilterState |= FILTER_EXP_PROP;
  1734. break;
  1735. }
  1736. }
  1737. }
  1738. if ( (fAccessPermission == ACTRL_DS_CREATE_CHILD) || (fAccessPermission == ACTRL_DS_DELETE_CHILD) )
  1739. {
  1740. // need to select all the Create or Delete Child entries, if present
  1741. _SelectAllSubObjectRigths(fAccessPermission);
  1742. // set the flags
  1743. if (m_classRightInfoArray.GetCount() > 0)
  1744. *pnNewFilterState |= FILTER_EXP_SUBOBJ;
  1745. }
  1746. else if ( (fAccessPermission == ACTRL_DS_READ_PROP) || (fAccessPermission == ACTRL_DS_WRITE_PROP) )
  1747. {
  1748. // need to select all the Read or Write Property entries, if present
  1749. _SelectAllPropertyRigths(fAccessPermission);
  1750. // set the flags
  1751. if (m_propertyRightInfoArray.GetCount() > 0)
  1752. *pnNewFilterState |= FILTER_EXP_PROP;
  1753. } // if
  1754. } // if index zero
  1755. } // if type is access
  1756. }
  1757. else // i.e. !bSelect
  1758. {
  1759. if (pItem->m_type == CRigthsListViewItem::access)
  1760. {
  1761. if (pItem->m_iIndex != 0)
  1762. {
  1763. // deselection on anything but full control
  1764. _DeselectAssociatedRights(m_accessRightInfoArr[pItem->m_iIndex]->GetAccess());
  1765. }
  1766. }
  1767. else if (pItem->m_type == CRigthsListViewItem::ctrl)
  1768. {
  1769. _DeselectAssociatedRights(m_controlRightInfoArr[pItem->m_iIndex]->GetAccess());
  1770. }
  1771. /*
  1772. // deselection on anything but full control
  1773. if ( !((pItem->m_iIndex == 0) && (pItem->m_type == CRigthsListViewItem::access)) )
  1774. {
  1775. _DeselectAssociatedRights(0);
  1776. }
  1777. */
  1778. }
  1779. }
  1780. break;
  1781. case CRigthsListViewItem::prop: // property rights
  1782. {
  1783. ASSERT(pItem->m_iIndex < m_propertyRightInfoArray.GetCount());
  1784. m_propertyRightInfoArray[pItem->m_iIndex]->SetRight(pItem->m_iRight, bSelect);
  1785. if (!bSelect)
  1786. {
  1787. // unchecking any Read/Write property, will unckeck the Read/Write All,
  1788. // Read and full control
  1789. _DeselectAssociatedRights(m_propertyRightInfoArray[pItem->m_iIndex]->GetRight(pItem->m_iRight));
  1790. }
  1791. }
  1792. break;
  1793. case CRigthsListViewItem::subobj: // subobject rigths
  1794. {
  1795. ASSERT(pItem->m_iIndex < m_classRightInfoArray.GetCount());
  1796. m_classRightInfoArray[pItem->m_iIndex]->SetRight(pItem->m_iRight, bSelect);
  1797. if (!bSelect)
  1798. {
  1799. // unchecking any Create/Delete property, will unckeck the Create/Delete All
  1800. // and full control
  1801. _DeselectAssociatedRights(m_classRightInfoArray[pItem->m_iIndex]->GetRight(pItem->m_iRight));
  1802. }
  1803. }
  1804. break;
  1805. default:
  1806. ASSERT(FALSE);
  1807. };
  1808. }
  1809. void CCustomAccessPermissionsHolder::FillAccessRightsListView(
  1810. CCheckListViewHelper* pListViewHelper,
  1811. ULONG nFilterState)
  1812. {
  1813. // clear the array of list view item proxies
  1814. m_listViewItemArr.Clear();
  1815. // enumerate the permissions and add to the checklist
  1816. ULONG i,j;
  1817. ULONG iListViewItem = 0;
  1818. // GENERAL RIGTHS
  1819. if (nFilterState & FILTER_EXP_GEN)
  1820. {
  1821. // add the list of access rights
  1822. UINT nAccessCount = (ULONG) m_accessRightInfoArr.GetCount();
  1823. for (i = 0; i < nAccessCount; i++)
  1824. {
  1825. // filter out entries with ACTRL_SYSTEM_ACCESS (auditing rigths)
  1826. if ( (m_accessRightInfoArr[i]->GetAccess() & ACTRL_SYSTEM_ACCESS) == 0)
  1827. {
  1828. CRigthsListViewItem* p = new CRigthsListViewItem(i, // index in m_accessRightInfoArr
  1829. 0, // iRight
  1830. CRigthsListViewItem::access);
  1831. m_listViewItemArr.Add(p);
  1832. pListViewHelper->InsertItem(iListViewItem,
  1833. m_accessRightInfoArr[i]->GetDisplayName(),
  1834. (LPARAM)p,
  1835. m_accessRightInfoArr[i]->IsSelected());
  1836. iListViewItem++;
  1837. }
  1838. }
  1839. // add the list of control rights
  1840. UINT nControlCount = (ULONG) m_controlRightInfoArr.GetCount();
  1841. for (i = 0; i < nControlCount; i++)
  1842. {
  1843. CRigthsListViewItem* p = new CRigthsListViewItem(i, // index in m_controlRightInfoArr
  1844. 0, // iRight
  1845. CRigthsListViewItem::ctrl);
  1846. m_listViewItemArr.Add(p);
  1847. pListViewHelper->InsertItem(iListViewItem,
  1848. m_controlRightInfoArr[i]->GetDisplayName(),
  1849. (LPARAM)p,
  1850. m_controlRightInfoArr[i]->IsSelected());
  1851. iListViewItem++;
  1852. }
  1853. }
  1854. // PROPERTY RIGTHS
  1855. if (nFilterState & FILTER_EXP_PROP)
  1856. {
  1857. // it expands (2x)
  1858. for (i = 0; i < (ULONG) m_propertyRightInfoArray.GetCount(); i++)
  1859. {
  1860. for (j=0; j< m_propertyRightInfoArray[i]->GetRightCount(); j++)
  1861. {
  1862. LPCWSTR pszRightDisplayName = m_propertyRightInfoArray[i]->GetRightDisplayString(j);
  1863. if(pszRightDisplayName)
  1864. {
  1865. CRigthsListViewItem* p = new CRigthsListViewItem(i,j, CRigthsListViewItem::prop);
  1866. m_listViewItemArr.Add(p);
  1867. pListViewHelper->InsertItem(iListViewItem,
  1868. pszRightDisplayName,
  1869. (LPARAM)p,
  1870. m_propertyRightInfoArray[i]->IsRightSelected(j));
  1871. iListViewItem++;
  1872. }
  1873. }
  1874. }
  1875. }
  1876. // SUBOBJECT RIGTHS
  1877. if (nFilterState & FILTER_EXP_SUBOBJ)
  1878. {
  1879. // it expands (2x)
  1880. for (i = 0; i < m_classRightInfoArray.GetCount(); i++)
  1881. {
  1882. for (j=0; j< m_classRightInfoArray[i]->GetRightCount(); j++)
  1883. {
  1884. LPCWSTR pszRightDisplayName = m_classRightInfoArray[i]->GetRightDisplayString(j);
  1885. if(pszRightDisplayName)
  1886. {
  1887. CRigthsListViewItem* p = new CRigthsListViewItem(i,j, CRigthsListViewItem::subobj);
  1888. m_listViewItemArr.Add(p);
  1889. pListViewHelper->InsertItem(iListViewItem,
  1890. pszRightDisplayName,
  1891. (LPARAM)p,
  1892. m_classRightInfoArray[i]->IsRightSelected(j));
  1893. iListViewItem++;
  1894. }
  1895. }
  1896. }
  1897. } // if
  1898. ASSERT(iListViewItem == m_listViewItemArr.GetCount());
  1899. }
  1900. void CCustomAccessPermissionsHolder::UpdateAccessRightsListViewSelection(
  1901. CCheckListViewHelper* pListViewHelper,
  1902. ULONG /*nFilterState*/)
  1903. {
  1904. // syncrhonize the UI with the data
  1905. int nListViewCount = pListViewHelper->GetItemCount();
  1906. for (int iListViewItem=0; iListViewItem < nListViewCount; iListViewItem++)
  1907. {
  1908. CRigthsListViewItem* pCurrItem =
  1909. (CRigthsListViewItem*)pListViewHelper->GetItemData(iListViewItem);
  1910. switch (pCurrItem->m_type)
  1911. {
  1912. case CRigthsListViewItem::access:
  1913. {
  1914. pListViewHelper->SetItemCheck(iListViewItem,
  1915. m_accessRightInfoArr[pCurrItem->m_iIndex]->IsSelected());
  1916. }
  1917. break;
  1918. case CRigthsListViewItem::ctrl:
  1919. {
  1920. pListViewHelper->SetItemCheck(iListViewItem,
  1921. m_controlRightInfoArr[pCurrItem->m_iIndex]->IsSelected());
  1922. }
  1923. break;
  1924. case CRigthsListViewItem::prop:
  1925. {
  1926. pListViewHelper->SetItemCheck(iListViewItem,
  1927. m_propertyRightInfoArray[pCurrItem->m_iIndex]->IsRightSelected(pCurrItem->m_iRight));
  1928. }
  1929. break;
  1930. case CRigthsListViewItem::subobj:
  1931. {
  1932. pListViewHelper->SetItemCheck(iListViewItem,
  1933. m_classRightInfoArray[pCurrItem->m_iIndex]->IsRightSelected(pCurrItem->m_iRight));
  1934. }
  1935. break;
  1936. } // switch
  1937. } // for
  1938. }
  1939. void CCustomAccessPermissionsHolder::WriteSummary(CWString& szSummary, LPCWSTR lpszIdent, LPCWSTR lpszNewLine)
  1940. {
  1941. WriteSummaryTitleLine(szSummary, IDS_DELEGWIZ_FINISH_PERMISSIONS, lpszNewLine);
  1942. if (m_accessRightInfoArr[0]->IsSelected()) // full control
  1943. {
  1944. WriteSummaryLine(szSummary, m_accessRightInfoArr[0]->GetDisplayName(), lpszIdent, lpszNewLine);
  1945. }
  1946. else
  1947. {
  1948. ULONG AccessAllClass = 0;
  1949. ULONG AccessAllProperty = 0;
  1950. UINT i,j,k;
  1951. // add an entry for all the standard access permissions:
  1952. for (k=0; k < m_accessRightInfoArr.GetCount(); k++)
  1953. {
  1954. if (m_accessRightInfoArr[k]->IsSelected())
  1955. {
  1956. // keep track of "All" flags
  1957. if (m_accessRightInfoArr[k]->GetAccess() & ACTRL_DS_READ_PROP)
  1958. AccessAllProperty |= ACTRL_DS_READ_PROP;
  1959. if (m_accessRightInfoArr[k]->GetAccess() & ACTRL_DS_WRITE_PROP)
  1960. AccessAllProperty |= ACTRL_DS_WRITE_PROP;
  1961. if (m_accessRightInfoArr[k]->GetAccess() & ACTRL_DS_CREATE_CHILD)
  1962. AccessAllClass |= ACTRL_DS_CREATE_CHILD;
  1963. if (m_accessRightInfoArr[k]->GetAccess() & ACTRL_DS_DELETE_CHILD)
  1964. AccessAllClass |= ACTRL_DS_DELETE_CHILD;
  1965. WriteSummaryLine(szSummary, m_accessRightInfoArr[k]->GetDisplayName(), lpszIdent, lpszNewLine);
  1966. }
  1967. } // for
  1968. // add an entry for each of the control rights
  1969. for (k=0; k < m_controlRightInfoArr.GetCount(); k++)
  1970. {
  1971. if (m_controlRightInfoArr[k]->IsSelected())
  1972. {
  1973. WriteSummaryLine(szSummary, m_controlRightInfoArr[k]->GetDisplayName(), lpszIdent, lpszNewLine);
  1974. }
  1975. } // for
  1976. // add an entry for each of the subobjects rigths
  1977. for (i = 0; i < m_classRightInfoArray.GetCount(); i++)
  1978. {
  1979. for (j=0; j< m_classRightInfoArray[i]->GetRightCount(); j++)
  1980. {
  1981. if ( m_classRightInfoArray[i]->IsRightSelected(j) &&
  1982. ((AccessAllClass & m_classRightInfoArray[i]->GetRight(j)) == 0) )
  1983. {
  1984. LPCWSTR pszRightDisplayString = m_classRightInfoArray[i]->GetRightDisplayString(j);
  1985. if(pszRightDisplayString)
  1986. {
  1987. WriteSummaryLine(szSummary, pszRightDisplayString, lpszIdent, lpszNewLine);
  1988. }
  1989. }
  1990. }
  1991. }
  1992. // add an entry for each property right to set
  1993. for (i = 0; i < m_propertyRightInfoArray.GetCount(); i++)
  1994. {
  1995. for (j=0; j< m_propertyRightInfoArray[i]->GetRightCount(); j++)
  1996. {
  1997. if ( m_propertyRightInfoArray[i]->IsRightSelected(j) &&
  1998. ((AccessAllProperty & m_propertyRightInfoArray[0]->GetRight(j)) == 0) )
  1999. {
  2000. LPCWSTR pszRightDisplayString = m_propertyRightInfoArray[i]->GetRightDisplayString(j);
  2001. if(pszRightDisplayString)
  2002. {
  2003. WriteSummaryLine(szSummary, pszRightDisplayString, lpszIdent, lpszNewLine);
  2004. }
  2005. }
  2006. }
  2007. }
  2008. } // if
  2009. szSummary += lpszNewLine;
  2010. }
  2011. ///////////////////////////////////////////////////////////////////////
  2012. // CCheckListViewHelper
  2013. #define CHECK_BIT(x) ((x >> 12) -1)
  2014. #define CHECK_CHANGED(pNMListView) \
  2015. (CHECK_BIT(pNMListView->uNewState) ^ CHECK_BIT(pNMListView->uOldState))
  2016. #define LVIS_STATEIMAGEMASK_CHECK (0x2000)
  2017. #define LVIS_STATEIMAGEMASK_UNCHECK (0x1000)
  2018. BOOL CCheckListViewHelper::IsChecked(NM_LISTVIEW* pNMListView)
  2019. {
  2020. return (CHECK_BIT(pNMListView->uNewState) != 0);
  2021. }
  2022. BOOL CCheckListViewHelper::CheckChanged(NM_LISTVIEW* pNMListView)
  2023. {
  2024. if (pNMListView->uOldState == 0)
  2025. return FALSE; // adding new items...
  2026. return CHECK_CHANGED(pNMListView) ? TRUE : FALSE;
  2027. }
  2028. BOOL CCheckListViewHelper::Initialize(UINT nID, HWND hParent)
  2029. {
  2030. m_hWnd = GetDlgItem(hParent, nID);
  2031. if (m_hWnd == NULL)
  2032. return FALSE;
  2033. ListView_SetExtendedListViewStyle(m_hWnd, LVS_EX_CHECKBOXES);
  2034. RECT r;
  2035. ::GetClientRect(m_hWnd, &r);
  2036. int scroll = ::GetSystemMetrics(SM_CXVSCROLL);
  2037. LV_COLUMN col;
  2038. ZeroMemory(&col, sizeof(LV_COLUMN));
  2039. col.mask = LVCF_WIDTH;
  2040. col.cx = (r.right - r.left) - scroll;
  2041. return (0 == ListView_InsertColumn(m_hWnd,0,&col));
  2042. }
  2043. int CCheckListViewHelper::InsertItem(int iItem, LPCTSTR lpszText, LPARAM lParam, BOOL bCheck)
  2044. {
  2045. TRACE(_T("CCheckListViewHelper::InsertItem(%d,%s,%x)\n"),iItem, lpszText, lParam);
  2046. LV_ITEM item;
  2047. ZeroMemory(&item, sizeof(LV_ITEM));
  2048. item.mask = LVIF_TEXT | LVIF_PARAM;
  2049. item.pszText = (LPTSTR)lpszText;
  2050. item.lParam = lParam;
  2051. item.iItem = iItem;
  2052. int iRes = ListView_InsertItem(m_hWnd, &item);
  2053. if ((iRes != -1) && bCheck)
  2054. SetItemCheck(iItem, TRUE);
  2055. return iRes;
  2056. }
  2057. BOOL CCheckListViewHelper::SetItemCheck(int iItem, BOOL bCheck)
  2058. {
  2059. LV_ITEM item;
  2060. ZeroMemory(&item, sizeof(LV_ITEM));
  2061. item.mask = LVIF_STATE;
  2062. item.state = bCheck ? LVIS_STATEIMAGEMASK_CHECK : LVIS_STATEIMAGEMASK_UNCHECK;
  2063. item.stateMask = LVIS_STATEIMAGEMASK;
  2064. item.iItem = iItem;
  2065. return ListView_SetItem(m_hWnd, &item);
  2066. }
  2067. void CCheckListViewHelper::SetCheckAll(BOOL bCheck)
  2068. {
  2069. LV_ITEM item;
  2070. ZeroMemory(&item, sizeof(LV_ITEM));
  2071. item.mask = LVIF_STATE;
  2072. item.state = bCheck ? LVIS_STATEIMAGEMASK_CHECK : LVIS_STATEIMAGEMASK_UNCHECK;
  2073. item.stateMask = LVIS_STATEIMAGEMASK;
  2074. int nCount = ListView_GetItemCount(m_hWnd);
  2075. for (int k = 0; k< nCount; k++)
  2076. {
  2077. item.iItem = k;
  2078. ListView_SetItem(m_hWnd, &item);
  2079. }
  2080. }
  2081. LPARAM CCheckListViewHelper::GetItemData(int iItem)
  2082. {
  2083. LV_ITEM item;
  2084. ZeroMemory(&item, sizeof(LV_ITEM));
  2085. item.mask = LVIF_PARAM;
  2086. item.iItem = iItem;
  2087. ListView_GetItem(m_hWnd, &item);
  2088. return item.lParam;
  2089. }
  2090. int CCheckListViewHelper::GetCheckCount()
  2091. {
  2092. int nCount = GetItemCount();
  2093. int nCheckCount = 0;
  2094. for (int k=0; k<nCount; k++)
  2095. {
  2096. if (ListView_GetCheckState(m_hWnd,k))
  2097. nCheckCount++;
  2098. }
  2099. return nCheckCount;
  2100. }
  2101. BOOL CCheckListViewHelper::IsItemChecked(int iItem)
  2102. {
  2103. return ListView_GetCheckState(m_hWnd, iItem);
  2104. }
  2105. void CCheckListViewHelper::GetCheckedItems(int nCheckCount, int* nCheckArray)
  2106. {
  2107. int nCount = GetItemCount();
  2108. int nCurrentCheck = 0;
  2109. for (int k=0; k<nCount; k++)
  2110. {
  2111. if (ListView_GetCheckState(m_hWnd,k) && nCurrentCheck < nCheckCount)
  2112. {
  2113. nCheckArray[nCurrentCheck++] = k;
  2114. }
  2115. }
  2116. }
  2117. ////////////////////////////////////////////////////////////////////////////
  2118. // CNamedSecurityInfo
  2119. /*
  2120. DWORD CNamedSecurityInfo::Get()
  2121. {
  2122. Reset(); // clear previous data
  2123. LPWSTR lpProvider = NULL; // not used
  2124. LPWSTR lpProperty = NULL; // want all
  2125. return ::GetNamedSecurityInfoEx(IN (LPWSTR) m_szObjectName.data(),
  2126. IN SE_DS_OBJECT_ALL,
  2127. IN DACL_SECURITY_INFORMATION,
  2128. IN lpProvider,
  2129. IN lpProperty,
  2130. OUT &m_pAccessList,
  2131. OUT &m_pAuditList,
  2132. OUT &m_pOwner,
  2133. OUT &m_pGroup);
  2134. }
  2135. DWORD CNamedSecurityInfo::Set()
  2136. {
  2137. LPWSTR lpProvider = NULL; // not used
  2138. dwErr = ::SetNamedSecurityInfoEx(IN (LPWSTR) m_szObjectName.data(),
  2139. IN SE_DS_OBJECT_ALL,
  2140. IN DACL_SECURITY_INFORMATION,
  2141. IN lpProvider,
  2142. IN m_pAccessList,
  2143. IN m_pAuditList,
  2144. IN m_pOwner,
  2145. IN m_pGroup,
  2146. IN NULL); // PACTRL_OVERLAPPED pOverlapped;
  2147. }
  2148. CNamedSecurityInfo::Reset()
  2149. {
  2150. if (m_pAuditList != NULL)
  2151. ::LocalFree(m_pAuditList);
  2152. if (m_pOwner != NULL)
  2153. ::LocalFree(m_pOwner);
  2154. if (m_pGroup != NULL)
  2155. ::LocalFree(m_pGroup);
  2156. if (m_pAccessList != NULL)
  2157. ::LocalFree(m_pAccessList);
  2158. }
  2159. */
  2160. ////////////////////////////////////////////////////////////////////////////
  2161. // CAdsiObject
  2162. HRESULT CAdsiObject::Bind(LPCWSTR lpszLdapPath)
  2163. {
  2164. _Clear();
  2165. CComBSTR bstrNamingContext;
  2166. CComBSTR bstrClass;
  2167. // try to bind to the given LDAP path
  2168. HRESULT hr = ::ADsOpenObjectHelper(lpszLdapPath,
  2169. IID_IADs,
  2170. 0,
  2171. (void **)&m_spIADs);
  2172. if (FAILED(hr))
  2173. {
  2174. TRACE(_T("Bind to DS object for IADs failed: %lx.\n"), hr);
  2175. goto error;
  2176. }
  2177. // get the DNS server name
  2178. hr = _QueryDNSServerName();
  2179. if (FAILED(hr))
  2180. {
  2181. TRACE(_T("Trying to get the DNS server name failed: %lx.\n"), hr);
  2182. goto error;
  2183. }
  2184. hr = _InitGlobalNamingContexts();
  2185. if (FAILED(hr))
  2186. {
  2187. TRACE(_T("Trying to get the physical schema naming context failed: %lx.\n"), hr);
  2188. goto error;
  2189. }
  2190. // need now to rebuild the LDAP path
  2191. // to make sure we talk always to the same server
  2192. hr = GetPathNameObject()->SkipPrefix(lpszLdapPath, &bstrNamingContext);
  2193. if (FAILED(hr))
  2194. {
  2195. TRACE(_T("Trying to get X500 name failed: %lx.\n"), hr);
  2196. goto error;
  2197. }
  2198. if ( (!bstrNamingContext ) || (!bstrNamingContext[0]))
  2199. {
  2200. goto error;
  2201. }
  2202. m_szNamingContext = bstrNamingContext;
  2203. BuildLdapPathHelper(GetServerName(), bstrNamingContext, m_szLdapPath);
  2204. // get the canonical name
  2205. hr = GetCanonicalNameFromNamingContext(bstrNamingContext, m_szCanonicalName);
  2206. if (FAILED(hr))
  2207. {
  2208. TRACE(_T("Trying to get canonical name failed, using naming context instead: %lx.\n"), hr);
  2209. m_szCanonicalName = bstrNamingContext;
  2210. }
  2211. // get the object class
  2212. hr = m_spIADs->get_Class(&bstrClass);
  2213. if (FAILED(hr))
  2214. {
  2215. TRACE(_T("Trying to get class name failed: %lx.\n"), hr);
  2216. goto error;
  2217. }
  2218. ASSERT(bstrClass != NULL);
  2219. m_szClass = bstrClass;
  2220. // load and set the display specifier cache
  2221. hr = ::CoCreateInstance(CLSID_DsDisplaySpecifier,
  2222. NULL,
  2223. CLSCTX_INPROC_SERVER,
  2224. IID_IDsDisplaySpecifier,
  2225. (void**)&m_spIDsDisplaySpecifier);
  2226. if (FAILED(hr))
  2227. {
  2228. TRACE(_T("Trying to get the display specifier cache failed: %lx.\n"), hr);
  2229. goto error;
  2230. }
  2231. hr = m_spIDsDisplaySpecifier->SetServer(GetServerName(), NULL, NULL, 0x0);
  2232. if (FAILED(hr))
  2233. {
  2234. TRACE(_T("m_spIDsDisplaySpecifier->SetServer(%s) failed\n"), GetServerName());
  2235. goto error;
  2236. }
  2237. ASSERT(SUCCEEDED(hr)); // all went fine
  2238. return hr;
  2239. error:
  2240. // on error condition, just reset the info, we do not
  2241. // want a partially constructed object
  2242. _Clear();
  2243. return hr;
  2244. }
  2245. #define DO_TIMING
  2246. HRESULT CAdsiObject::QuerySchemaClasses(CGrowableArr<CSchemaClassInfo>* pSchemaClassesInfoArray,
  2247. BOOL bGetAttributes)
  2248. {
  2249. TRACE(L"\n==================================================\n");
  2250. TRACE(L"CAdsiObject::QuerySchemaClasses\n\n");
  2251. #if defined (DO_TIMING)
  2252. DWORD dwTick1 = ::GetTickCount();
  2253. #endif
  2254. // make sure we are bound
  2255. if (m_spIADs == NULL)
  2256. {
  2257. return E_INVALIDARG;
  2258. }
  2259. // cleanup current entries in the list
  2260. pSchemaClassesInfoArray->Clear();
  2261. // build the LDAP path for the schema class
  2262. CWString szPhysicalSchemaPath;
  2263. LPCWSTR lpszPhysicalSchemaNamingContext = GetPhysicalSchemaNamingContext();
  2264. BuildLdapPathHelper(GetServerName(), lpszPhysicalSchemaNamingContext, szPhysicalSchemaPath);
  2265. CAdsiSearch search;
  2266. HRESULT hr = search.Init(szPhysicalSchemaPath);
  2267. if (FAILED(hr))
  2268. return hr;
  2269. static LPCWSTR lpszClassFilterFormat = L"(&(objectCategory=CN=Class-Schema,%s)(lDAPDisplayName=*))";
  2270. static LPCWSTR lpszAttributeFilterFormat = L"(&(objectCategory=CN=Attribute-Schema,%s)(lDAPDisplayName=*))";
  2271. LPCWSTR lpszFilterFormat = bGetAttributes ? lpszAttributeFilterFormat : lpszClassFilterFormat;
  2272. int nFmtLen = lstrlen(lpszFilterFormat);
  2273. int nSchemaContextLen = lstrlen(lpszPhysicalSchemaNamingContext);
  2274. WCHAR* lpszFilter = (WCHAR*)alloca(sizeof(WCHAR)*(nFmtLen+nSchemaContextLen+1));
  2275. wsprintf(lpszFilter, lpszFilterFormat, lpszPhysicalSchemaNamingContext);
  2276. static const int cAttrs = 4;
  2277. static LPCWSTR pszAttribsArr[cAttrs] =
  2278. {
  2279. L"lDAPDisplayName", // e.g. "organizationalUnit"
  2280. L"name", // e.g. "Organizational-Unit"
  2281. L"schemaIDGUID",
  2282. L"objectClassCategory",
  2283. };
  2284. hr = search.SetSearchScope(ADS_SCOPE_ONELEVEL);
  2285. if (FAILED(hr))
  2286. return hr;
  2287. hr = search.DoQuery(lpszFilter, pszAttribsArr, cAttrs);
  2288. if (FAILED(hr))
  2289. return hr;
  2290. CWString szLDAPName, szName;
  2291. szLDAPName = L"";
  2292. szName = L"";
  2293. GUID schemaIDGUID;
  2294. ULONG iObjectClassCategory=0;
  2295. while ((hr = search.GetNextRow()) != S_ADS_NOMORE_ROWS)
  2296. {
  2297. if (FAILED(hr))
  2298. continue;
  2299. HRESULT hr0 = search.GetColumnString(pszAttribsArr[0], szLDAPName);
  2300. HRESULT hr1 = search.GetColumnString(pszAttribsArr[1], szName);
  2301. HRESULT hr2 = search.GetColumnOctectStringGUID(pszAttribsArr[2], schemaIDGUID);
  2302. HRESULT hr3 = search.GetColumnInteger(pszAttribsArr[3], iObjectClassCategory);
  2303. if (FAILED(hr0) || FAILED(hr1) || FAILED(hr2) || FAILED(hr3))
  2304. continue;
  2305. ULONG fFilterFlags = ::GetClassFlags(szLDAPName);
  2306. CSchemaClassInfo* p = new CSchemaClassInfo(szLDAPName, szName, &schemaIDGUID);
  2307. if(!p)
  2308. return E_OUTOFMEMORY;
  2309. BOOL bFilter = (fFilterFlags & IDC_CLASS_NO);
  2310. if (bFilter)
  2311. p->SetFiltered();
  2312. //is class Auxiallary
  2313. if(iObjectClassCategory == 3)
  2314. p->SetAux();
  2315. pSchemaClassesInfoArray->Add(p);
  2316. //TRACE(L"Class %s inserted, IsFiltered() == %d\n", (LPCWSTR)szName, p->IsFiltered());
  2317. } // while
  2318. TRACE(L"\n================================================\n");
  2319. #if defined (DO_TIMING)
  2320. DWORD dwTick2 = ::GetTickCount();
  2321. TRACE(L"Time to do Schema Query loop (mSec) = %d\n", dwTick2-dwTick1);
  2322. #endif
  2323. _GetFriendlyClassNames(pSchemaClassesInfoArray);
  2324. #if defined (DO_TIMING)
  2325. dwTick2 = ::GetTickCount();
  2326. #endif
  2327. pSchemaClassesInfoArray->Sort(); // wrt friendly class name
  2328. #if defined (DO_TIMING)
  2329. DWORD dwTick3 = ::GetTickCount();
  2330. TRACE(L"Time to sort (mSec) = %d\n", dwTick3-dwTick2);
  2331. #endif
  2332. TRACE(L"exiting CAdsiObject::QuerySchemaClasses()\n\n");
  2333. return hr;
  2334. }
  2335. HRESULT CAdsiObject::GetClassGuid(LPCWSTR lpszClassLdapDisplayName, BOOL bGetAttribute, GUID& guid)
  2336. {
  2337. //TRACE(L"CAdsiObject::GetClassGuid(%s, _)\n\n", lpszClassLdapDisplayName);
  2338. ZeroMemory(&guid, sizeof(GUID));
  2339. // make sure we are bound
  2340. if (m_spIADs == NULL)
  2341. {
  2342. return E_INVALIDARG;
  2343. }
  2344. // build the LDAP path for the schema class
  2345. CWString szPhysicalSchemaPath;
  2346. LPCWSTR lpszPhysicalSchemaNamingContext = GetPhysicalSchemaNamingContext();
  2347. BuildLdapPathHelper(GetServerName(), lpszPhysicalSchemaNamingContext, szPhysicalSchemaPath);
  2348. CAdsiSearch search;
  2349. HRESULT hr = search.Init(szPhysicalSchemaPath);
  2350. if (FAILED(hr))
  2351. return hr;
  2352. static LPCWSTR lpszClassFilterFormat = L"(&(objectCategory=CN=Class-Schema,%s)(lDAPDisplayName=%s))";
  2353. static LPCWSTR lpszAttributeFilterFormat = L"(&(objectCategory=CN=Attribute-Schema,%s)(lDAPDisplayName=%s))";
  2354. LPCWSTR lpszFilterFormat = bGetAttribute ? lpszAttributeFilterFormat : lpszClassFilterFormat;
  2355. int nFmtLen = lstrlen(lpszFilterFormat);
  2356. int nSchemaContextLen = lstrlen(lpszPhysicalSchemaNamingContext);
  2357. int nlDAPDisplayNameLen = lstrlen(lpszClassLdapDisplayName);
  2358. WCHAR* lpszFilter = (WCHAR*)alloca(sizeof(WCHAR)*(nFmtLen+nSchemaContextLen+nlDAPDisplayNameLen+1));
  2359. wsprintf(lpszFilter, lpszFilterFormat, lpszPhysicalSchemaNamingContext, lpszClassLdapDisplayName);
  2360. //TRACE(L"lpszFilter = %s\n", lpszFilter);
  2361. static const int cAttrs = 1;
  2362. static LPCWSTR pszAttribsArr[cAttrs] =
  2363. {
  2364. L"schemaIDGUID",
  2365. };
  2366. hr = search.SetSearchScope(ADS_SCOPE_ONELEVEL);
  2367. if (FAILED(hr))
  2368. return hr;
  2369. hr = search.DoQuery(lpszFilter, pszAttribsArr, cAttrs);
  2370. if (FAILED(hr))
  2371. return hr;
  2372. // expect a single result
  2373. hr = search.GetNextRow();
  2374. if ( hr == S_ADS_NOMORE_ROWS)
  2375. {
  2376. hr = E_ADS_UNKNOWN_OBJECT;
  2377. }
  2378. if (FAILED(hr))
  2379. return hr;
  2380. hr = search.GetColumnOctectStringGUID(pszAttribsArr[0], guid);
  2381. //TRACE(L"exiting CAdsiObject::GetClassGuid()\n\n");
  2382. return hr;
  2383. }
  2384. HRESULT CAdsiObject::_QueryDNSServerName()
  2385. {
  2386. // make sure we are bound
  2387. if (m_spIADs == NULL)
  2388. {
  2389. return E_INVALIDARG;
  2390. }
  2391. m_szServerName = L"";
  2392. CComPtr<IADsObjectOptions> spIADsObjectOptions;
  2393. HRESULT hr = m_spIADs->QueryInterface(IID_IADsObjectOptions, (void**)&spIADsObjectOptions);
  2394. if (FAILED(hr))
  2395. return hr;
  2396. CComVariant var;
  2397. hr = spIADsObjectOptions->GetOption(ADS_OPTION_SERVERNAME, &var);
  2398. if (FAILED(hr))
  2399. return hr;
  2400. if(var.vt == VT_BSTR)
  2401. {
  2402. m_szServerName = V_BSTR(&var);
  2403. }
  2404. else
  2405. {
  2406. hr = E_INVALIDARG;
  2407. }
  2408. return hr;
  2409. }
  2410. HRESULT CAdsiObject::_InitGlobalNamingContexts()
  2411. {
  2412. return ::GetGlobalNamingContexts(GetServerName(),
  2413. m_szPhysicalSchemaNamingContext,
  2414. m_szConfigurationNamingContext);
  2415. }
  2416. HICON CAdsiObject::GetClassIcon(LPCWSTR lpszObjectClass)
  2417. {
  2418. ASSERT(m_spIDsDisplaySpecifier != NULL);
  2419. return m_spIDsDisplaySpecifier->GetIcon(lpszObjectClass,
  2420. DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON,
  2421. 32, 32);
  2422. }
  2423. HRESULT CAdsiObject::GetFriendlyClassName(LPCWSTR lpszObjectClass,
  2424. LPWSTR lpszBuffer, int cchBuffer)
  2425. {
  2426. ASSERT(m_spIDsDisplaySpecifier != NULL);
  2427. return m_spIDsDisplaySpecifier->GetFriendlyClassName(lpszObjectClass,
  2428. lpszBuffer,
  2429. cchBuffer);
  2430. }
  2431. HRESULT CAdsiObject::GetFriendlyAttributeName(LPCWSTR lpszObjectClass,
  2432. LPCWSTR lpszAttributeName,
  2433. LPWSTR lpszBuffer, int cchBuffer)
  2434. {
  2435. ASSERT(m_spIDsDisplaySpecifier != NULL);
  2436. return m_spIDsDisplaySpecifier->GetFriendlyAttributeName(lpszObjectClass,
  2437. lpszAttributeName,
  2438. lpszBuffer, cchBuffer);
  2439. }
  2440. #if (FALSE)
  2441. HRESULT CAdsiObject::_GetFriendlyClassNames(CGrowableArr<CSchemaClassInfo>* pSchemaClassesInfoArray)
  2442. {
  2443. TRACE(L"begin _GetFriendlyClassNames() loop on all classes\n");
  2444. #if defined (DO_TIMING)
  2445. DWORD dwTick1 = ::GetTickCount();
  2446. #endif
  2447. // now get the friendly class name to display
  2448. ULONG nCount = pSchemaClassesInfoArray->GetCount();
  2449. WCHAR szFrendlyName[1024];
  2450. for (UINT k=0; k<nCount; k++)
  2451. {
  2452. CSchemaClassInfo* p = (*pSchemaClassesInfoArray)[k];
  2453. HRESULT hrFriendlyName = this->GetFriendlyClassName(p->GetName(), szFrendlyName, 1024);
  2454. ASSERT(SUCCEEDED(hrFriendlyName));
  2455. (*pSchemaClassesInfoArray)[k]->SetDisplayName(SUCCEEDED(hrFriendlyName) ? szFrendlyName : NULL);
  2456. }
  2457. #if defined (DO_TIMING)
  2458. DWORD dwTick2 = ::GetTickCount();
  2459. TRACE(L"Time to call _GetFriendlyClassNames() loop (mSec) = %d\n", dwTick2-dwTick1);
  2460. #endif
  2461. return S_OK;
  2462. }
  2463. #else
  2464. HRESULT CAdsiObject::_GetFriendlyClassNames(CGrowableArr<CSchemaClassInfo>* pSchemaClassesInfoArray)
  2465. {
  2466. TRACE(L"\nbegin _GetFriendlyClassNames() using ADSI query\n");
  2467. #if defined (DO_TIMING)
  2468. DWORD dwTick1 = ::GetTickCount();
  2469. #endif
  2470. ASSERT(m_spIDsDisplaySpecifier != NULL);
  2471. // get the display specifiers locale container (e.g. 409)
  2472. CComPtr<IADs> spLocaleContainer;
  2473. HRESULT hr = m_spIDsDisplaySpecifier->GetDisplaySpecifier(NULL, IID_IADs, (void**)&spLocaleContainer);
  2474. if (FAILED(hr))
  2475. return hr;
  2476. // get distinguished name of the container
  2477. CComVariant varLocaleContainerDN;
  2478. hr = spLocaleContainer->Get(CComBSTR (L"distinguishedName"), &varLocaleContainerDN);
  2479. if (FAILED(hr))
  2480. return hr;
  2481. // build the LDAP path for it
  2482. CWString szLocaleContainerPath;
  2483. BuildLdapPathHelper(GetServerName(), varLocaleContainerDN.bstrVal, szLocaleContainerPath);
  2484. // build the LDAP path for the schema class
  2485. CWString szPhysicalSchemaPath;
  2486. LPCWSTR lpszPhysicalSchemaNamingContext = GetPhysicalSchemaNamingContext();
  2487. BuildLdapPathHelper(GetServerName(), lpszPhysicalSchemaNamingContext, szPhysicalSchemaPath);
  2488. // build an LDAP query string
  2489. static LPCWSTR lpszFilterFormat = L"(objectCategory=CN=Display-Specifier,%s)";
  2490. int nFmtLen = lstrlen(lpszFilterFormat);
  2491. int nArgumentLen = lstrlen(lpszPhysicalSchemaNamingContext);
  2492. WCHAR* lpszFilter = (WCHAR*)alloca(sizeof(WCHAR)*(nFmtLen+nArgumentLen+1));
  2493. wsprintf(lpszFilter, lpszFilterFormat, lpszPhysicalSchemaNamingContext);
  2494. // execute a query to get the CN and the class display name
  2495. CAdsiSearch search;
  2496. hr = search.Init(szLocaleContainerPath);
  2497. if (FAILED(hr))
  2498. return hr;
  2499. // build an array of wanted columns
  2500. static const int cAttrs = 2;
  2501. static LPCWSTR pszAttribsArr[cAttrs] =
  2502. {
  2503. L"cn", // e.g. "organizationalUnit-Display"
  2504. L"classDisplayName", // e.g. "Organizational Unit" (i.e. the localizable one)
  2505. };
  2506. hr = search.SetSearchScope(ADS_SCOPE_ONELEVEL);
  2507. //TRACE(L"search.SetSearchScope(ADS_SCOPE_ONELEVEL) returned hr = 0x%x\n", hr);
  2508. if (FAILED(hr))
  2509. return hr;
  2510. hr = search.DoQuery(lpszFilter, pszAttribsArr, cAttrs);
  2511. //TRACE(L"search.DoQuery(lpszFilter, pszAttribsArr, cAttrs) returned hr = 0x%x\n", hr);
  2512. if (FAILED(hr))
  2513. return hr;
  2514. // need to keep track of matches
  2515. size_t nCount = pSchemaClassesInfoArray->GetCount();
  2516. BOOL* bFoundArray = (BOOL*)alloca(nCount*sizeof(BOOL));
  2517. ZeroMemory(bFoundArray, nCount*sizeof(BOOL));
  2518. WCHAR szBuffer[1024];
  2519. CWString szNamingAttribute, szClassDisplayName;
  2520. while ((hr = search.GetNextRow()) != S_ADS_NOMORE_ROWS)
  2521. {
  2522. if (FAILED(hr))
  2523. continue;
  2524. HRESULT hr0 = search.GetColumnString(pszAttribsArr[0], szNamingAttribute);
  2525. HRESULT hr1 = search.GetColumnString(pszAttribsArr[1], szClassDisplayName);
  2526. //TRACE(L"szNamingAttribute = <%s>, szClassDisplayName = <%s>\n",
  2527. // szNamingAttribute.c_str(), szClassDisplayName.c_str());
  2528. if (FAILED(hr0) || FAILED(hr1) )
  2529. {
  2530. TRACE(L"WARNING: discarding right, failed on columns: hr0 = 0x%x, hr1 = 0x%x\n",
  2531. hr0, hr1);
  2532. continue;
  2533. }
  2534. // got a good name, need to match with the entries in the array
  2535. for (UINT k=0; k<nCount; k++)
  2536. {
  2537. if (!bFoundArray[k])
  2538. {
  2539. CSchemaClassInfo* p = (*pSchemaClassesInfoArray)[k];
  2540. //If its truncate, than string comparison will fail and
  2541. //it will be treated as if DisplayName didn't exist which
  2542. //is fine.
  2543. //NTRAID#NTBUG9-530206-2002/06/18-ronmart-Check return code and abort if failed
  2544. HRESULT hres = StringCchPrintf(szBuffer,sizeof(szBuffer)/sizeof(szBuffer[0]), L"%s-Display",p->GetName());
  2545. if(FAILED(hres))
  2546. return hres;
  2547. if (_wcsicmp(szBuffer, szNamingAttribute) == 0)
  2548. {
  2549. //TRACE(L" matching for %s\n",p->GetName());
  2550. p->SetDisplayName(szClassDisplayName);
  2551. bFoundArray[k] = TRUE;
  2552. }
  2553. }
  2554. } // for
  2555. } // while
  2556. // take care of the ones that did not have any display specifier
  2557. for (UINT k=0; k<nCount; k++)
  2558. {
  2559. if (!bFoundArray[k])
  2560. {
  2561. (*pSchemaClassesInfoArray)[k]->SetDisplayName(NULL);
  2562. }
  2563. } // for
  2564. TRACE(L"\n\n");
  2565. if (hr == S_ADS_NOMORE_ROWS)
  2566. hr = S_OK;
  2567. #if defined (DO_TIMING)
  2568. DWORD dwTick2 = ::GetTickCount();
  2569. TRACE(L"Time to call _GetFriendlyClassNames() on ADSI query (mSec) = %d\n", dwTick2-dwTick1);
  2570. #endif
  2571. return hr;
  2572. }
  2573. #endif
  2574. bool
  2575. CAdsiObject::GetListObjectEnforced()
  2576. {
  2577. if(m_iListObjectEnforced != -1)
  2578. return (m_iListObjectEnforced==1);
  2579. PADS_ATTR_INFO pAttributeInfo = NULL;
  2580. IDirectoryObject *pDirectoryService = NULL;
  2581. IADsPathname *pPath = NULL;
  2582. BSTR strServicePath = NULL;
  2583. do
  2584. {
  2585. m_iListObjectEnforced = 0; // Assume "not enforced"
  2586. HRESULT hr = S_OK;
  2587. int i;
  2588. // Create a path object for manipulating ADS paths
  2589. hr = CoCreateInstance(CLSID_Pathname,
  2590. NULL,
  2591. CLSCTX_INPROC_SERVER,
  2592. IID_IADsPathname,
  2593. (LPVOID*)&pPath);
  2594. if(FAILED(hr))
  2595. break;
  2596. CComBSTR bstrConfigPath = L"LDAP://";
  2597. if(GetServerName())
  2598. {
  2599. bstrConfigPath += GetServerName();
  2600. bstrConfigPath += L"/";
  2601. }
  2602. if(!GetConfigurationNamingContext())
  2603. break;
  2604. bstrConfigPath += GetConfigurationNamingContext();
  2605. if(!bstrConfigPath.Length())
  2606. break;
  2607. hr = pPath->Set(bstrConfigPath, ADS_SETTYPE_FULL);
  2608. if(FAILED(hr))
  2609. break;
  2610. const LPWSTR aszServicePath[] =
  2611. {
  2612. L"CN=Services",
  2613. L"CN=Windows NT",
  2614. L"CN=Directory Service",
  2615. };
  2616. for (i = 0; i < ARRAYSIZE(aszServicePath); i++)
  2617. {
  2618. hr = pPath->AddLeafElement(CComBSTR (aszServicePath[i]));
  2619. if(FAILED(hr))
  2620. break;
  2621. }
  2622. hr = pPath->Retrieve(ADS_FORMAT_WINDOWS, &strServicePath);
  2623. if(FAILED(hr))
  2624. break;
  2625. hr = ADsOpenObjectHelper(strServicePath,
  2626. IID_IDirectoryObject,
  2627. 0,
  2628. (LPVOID*)&pDirectoryService);
  2629. if(FAILED(hr))
  2630. break;
  2631. WCHAR const c_szDsHeuristics[] = L"dSHeuristics";
  2632. LPWSTR pszDsHeuristics = (LPWSTR)c_szDsHeuristics;
  2633. DWORD dwAttributesReturned = 0;
  2634. hr = pDirectoryService->GetObjectAttributes(&pszDsHeuristics,
  2635. 1,
  2636. &pAttributeInfo,
  2637. &dwAttributesReturned);
  2638. if (FAILED(hr)|| !pAttributeInfo)
  2639. break;
  2640. ASSERT(ADSTYPE_DN_STRING <= pAttributeInfo->dwADsType);
  2641. ASSERT(ADSTYPE_NUMERIC_STRING >= pAttributeInfo->dwADsType);
  2642. ASSERT(1 == pAttributeInfo->dwNumValues);
  2643. LPWSTR pszHeuristicString = pAttributeInfo->pADsValues->NumericString;
  2644. if (pszHeuristicString &&
  2645. lstrlenW(pszHeuristicString) > 2 &&
  2646. L'0' != pszHeuristicString[2])
  2647. {
  2648. m_iListObjectEnforced = 1;
  2649. }
  2650. }while(0);
  2651. if (pAttributeInfo)
  2652. FreeADsMem(pAttributeInfo);
  2653. if(pDirectoryService)
  2654. pDirectoryService->Release();
  2655. if(pPath)
  2656. pPath->Release();
  2657. if(strServicePath)
  2658. SysFreeString(strServicePath);
  2659. return (m_iListObjectEnforced==1);
  2660. }
  2661. ////////////////////////////////////////////////////////////////////////////////////////
  2662. // CAdsiSearch
  2663. HRESULT CAdsiSearch::DoQuery(LPCWSTR lpszFilter, LPCWSTR* pszAttribsArr, int cAttrs)
  2664. {
  2665. if (m_spSearchObj == NULL)
  2666. return E_ADS_BAD_PATHNAME;
  2667. static const int NUM_PREFS=3;
  2668. static const int QUERY_PAGESIZE = 256;
  2669. ADS_SEARCHPREF_INFO aSearchPref[NUM_PREFS];
  2670. aSearchPref[0].dwSearchPref = ADS_SEARCHPREF_CHASE_REFERRALS;
  2671. aSearchPref[0].vValue.dwType = ADSTYPE_INTEGER;
  2672. aSearchPref[0].vValue.Integer = ADS_CHASE_REFERRALS_EXTERNAL;
  2673. aSearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  2674. aSearchPref[1].vValue.dwType = ADSTYPE_INTEGER;
  2675. aSearchPref[1].vValue.Integer = QUERY_PAGESIZE;
  2676. aSearchPref[2].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
  2677. aSearchPref[2].vValue.dwType = ADSTYPE_BOOLEAN;
  2678. aSearchPref[2].vValue.Integer = FALSE;
  2679. HRESULT hr = m_spSearchObj->SetSearchPreference (aSearchPref, NUM_PREFS);
  2680. if (FAILED(hr))
  2681. return hr;
  2682. return m_spSearchObj->ExecuteSearch((LPWSTR)lpszFilter,
  2683. (LPWSTR*)pszAttribsArr,
  2684. cAttrs,
  2685. &m_SearchHandle);
  2686. }
  2687. //
  2688. //Functions to replace GetNamedSecurityInfo and SetNamedSecurityInfo
  2689. //
  2690. #pragma warning (disable : 4127)
  2691. HRESULT
  2692. SetSecInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si)
  2693. {
  2694. HRESULT hr = E_INVALIDARG;
  2695. if (punk)
  2696. {
  2697. IADsObjectOptions *pOptions;
  2698. hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions);
  2699. if (SUCCEEDED(hr))
  2700. {
  2701. VARIANT var;
  2702. VariantInit(&var);
  2703. V_VT(&var) = VT_I4;
  2704. V_I4(&var) = si;
  2705. hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var);
  2706. pOptions->Release();
  2707. }
  2708. }
  2709. return hr;
  2710. }
  2711. //+---------------------------------------------------------------------------
  2712. //
  2713. // Function: GetSDForDsObject
  2714. // Synopsis: Reads the security descriptor from the specied DS object
  2715. // It only reads the DACL portion of the security descriptor
  2716. //
  2717. // Arguments: [IN pDsObject] -- DS object
  2718. // [ppDACL] --pointer to dacl in ppSD is returned here
  2719. // [OUT ppSD] -- Security descriptor returned here.
  2720. // calling API must free this by calling LocalFree
  2721. //
  2722. // Notes: The returned security descriptor must be freed with LocalFree
  2723. //
  2724. //----------------------------------------------------------------------------
  2725. HRESULT GetSDForDsObject(IDirectoryObject* pDsObject,
  2726. PACL* ppDACL,
  2727. PSECURITY_DESCRIPTOR* ppSD)
  2728. {
  2729. if(!pDsObject || !ppSD)
  2730. {
  2731. return E_POINTER;
  2732. }
  2733. *ppSD = NULL;
  2734. if(ppDACL)
  2735. {
  2736. *ppDACL = NULL;
  2737. }
  2738. HRESULT hr = S_OK;
  2739. PADS_ATTR_INFO pSDAttributeInfo = NULL;
  2740. do
  2741. {
  2742. WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
  2743. LPWSTR pszProperty = (LPWSTR)c_szSDProperty;
  2744. // Set the SECURITY_INFORMATION mask to DACL_SECURITY_INFORMATION
  2745. hr = SetSecInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  2746. if(FAILED(hr))
  2747. break;
  2748. DWORD dwAttributesReturned;
  2749. // Read the security descriptor attribute
  2750. hr = pDsObject->GetObjectAttributes(&pszProperty,
  2751. 1,
  2752. &pSDAttributeInfo,
  2753. &dwAttributesReturned);
  2754. if(SUCCEEDED(hr) && !pSDAttributeInfo)
  2755. {
  2756. hr = E_FAIL;
  2757. }
  2758. if(FAILED(hr))
  2759. break;
  2760. if((ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->dwADsType) &&
  2761. (ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->pADsValues->dwType))
  2762. {
  2763. *ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, pSDAttributeInfo->pADsValues->SecurityDescriptor.dwLength);
  2764. if (!*ppSD)
  2765. {
  2766. hr = E_OUTOFMEMORY;
  2767. break;
  2768. }
  2769. CopyMemory(*ppSD,
  2770. pSDAttributeInfo->pADsValues->SecurityDescriptor.lpValue,
  2771. pSDAttributeInfo->pADsValues->SecurityDescriptor.dwLength);
  2772. if(ppDACL)
  2773. {
  2774. BOOL bDaclPresent,bDaclDeafulted;
  2775. if(!GetSecurityDescriptorDacl(*ppSD,
  2776. &bDaclPresent,
  2777. ppDACL,
  2778. &bDaclDeafulted))
  2779. {
  2780. DWORD dwErr = GetLastError();
  2781. hr = HRESULT_FROM_WIN32(dwErr);
  2782. break;
  2783. }
  2784. }
  2785. }
  2786. else
  2787. {
  2788. hr = E_FAIL;
  2789. }
  2790. }while(0);
  2791. if (pSDAttributeInfo)
  2792. FreeADsMem(pSDAttributeInfo);
  2793. if(FAILED(hr))
  2794. {
  2795. if(*ppSD)
  2796. {
  2797. LocalFree(*ppSD);
  2798. *ppSD = NULL;
  2799. if(ppDACL)
  2800. *ppDACL = NULL;
  2801. }
  2802. }
  2803. return hr;
  2804. }
  2805. //+---------------------------------------------------------------------------
  2806. //
  2807. // Function: GetSDForDsObjectPath
  2808. // Synopsis: Reads the security descriptor from the specied DS object
  2809. // It only reads the DACL portion of the security descriptor
  2810. //
  2811. // Arguments: [IN pszObjectPath] -- LDAP Path of ds object
  2812. // [ppDACL] --pointer to dacl in ppSD is returned here
  2813. // [OUT ppSD] -- Security descriptor returned here.
  2814. // calling API must free this by calling LocalFree
  2815. //
  2816. // Notes: The returned security descriptor must be freed with LocalFree
  2817. //
  2818. //----------------------------------------------------------------------------
  2819. HRESULT GetSDForDsObjectPath(LPCWSTR pszObjectPath,
  2820. PACL* ppDACL,
  2821. PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
  2822. {
  2823. if(!pszObjectPath || !ppSecurityDescriptor)
  2824. {
  2825. return E_POINTER;
  2826. }
  2827. IDirectoryObject* pDsObject = NULL;
  2828. HRESULT hr = ADsOpenObjectHelper(pszObjectPath, IID_IDirectoryObject,0,(void**)&pDsObject);
  2829. if(SUCCEEDED(hr))
  2830. {
  2831. hr = GetSDForDsObject(pDsObject,ppDACL,ppSecurityDescriptor);
  2832. }
  2833. if(pDsObject)
  2834. pDsObject->Release();
  2835. return hr;
  2836. }
  2837. //+---------------------------------------------------------------------------
  2838. //
  2839. // Function: SetDaclForDsObject
  2840. // Synopsis: Sets the the DACL for the specified DS object
  2841. //
  2842. // Arguments: [IN pDsObject] -- ds object
  2843. // [IN pDACL] --pointer to dacl to be set
  2844. //
  2845. //----------------------------------------------------------------------------
  2846. HRESULT SetDaclForDsObject(IDirectoryObject* pDsObject,
  2847. PACL pDACL)
  2848. {
  2849. if(!pDsObject || !pDACL)
  2850. {
  2851. return E_POINTER;
  2852. }
  2853. WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
  2854. PSECURITY_DESCRIPTOR pSD = NULL;
  2855. PSECURITY_DESCRIPTOR pSDCurrent = NULL;
  2856. HRESULT hr = S_OK;
  2857. do
  2858. {
  2859. //Get the current SD for the object
  2860. hr = GetSDForDsObject(pDsObject,NULL,&pSDCurrent);
  2861. if(FAILED(hr))
  2862. break;
  2863. //Get the control for the current security descriptor
  2864. SECURITY_DESCRIPTOR_CONTROL currentControl;
  2865. DWORD dwRevision = 0;
  2866. if(!GetSecurityDescriptorControl(pSDCurrent, &currentControl, &dwRevision))
  2867. {
  2868. DWORD dwErr = GetLastError();
  2869. hr = HRESULT_FROM_WIN32(dwErr);
  2870. break;
  2871. }
  2872. //Allocate the buffer for Security Descriptor
  2873. pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH + pDACL->AclSize);
  2874. if(!pSD)
  2875. {
  2876. hr = E_OUTOFMEMORY;
  2877. break;
  2878. }
  2879. if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  2880. {
  2881. DWORD dwErr = GetLastError();
  2882. hr = HRESULT_FROM_WIN32(dwErr);
  2883. break;
  2884. }
  2885. PISECURITY_DESCRIPTOR pISD = (PISECURITY_DESCRIPTOR)pSD;
  2886. //
  2887. // Finally, build the security descriptor
  2888. //
  2889. pISD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ
  2890. | (currentControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  2891. if (pDACL->AclSize > 0)
  2892. {
  2893. pISD->Dacl = (PACL)(pISD + 1);
  2894. CopyMemory(pISD->Dacl, pDACL, pDACL->AclSize);
  2895. }
  2896. //We are only setting DACL information
  2897. hr = SetSecInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  2898. if(FAILED(hr))
  2899. break;
  2900. // Need the total size
  2901. DWORD dwSDLength = GetSecurityDescriptorLength(pSD);
  2902. //
  2903. // If necessary, make a self-relative copy of the security descriptor
  2904. //
  2905. SECURITY_DESCRIPTOR_CONTROL sdControl = 0;
  2906. if(!GetSecurityDescriptorControl(pSD, &sdControl, &dwRevision))
  2907. {
  2908. DWORD dwErr = GetLastError();
  2909. hr = HRESULT_FROM_WIN32(dwErr);
  2910. break;
  2911. }
  2912. if (!(sdControl & SE_SELF_RELATIVE))
  2913. {
  2914. PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDLength);
  2915. if (psd == NULL ||
  2916. !MakeSelfRelativeSD(pSD, psd, &dwSDLength))
  2917. {
  2918. DWORD dwErr = GetLastError();
  2919. hr = HRESULT_FROM_WIN32(dwErr);
  2920. break;
  2921. }
  2922. // Point to the self-relative copy
  2923. LocalFree(pSD);
  2924. pSD = psd;
  2925. }
  2926. ADSVALUE attributeValue;
  2927. ADS_ATTR_INFO attributeInfo;
  2928. attributeValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  2929. attributeValue.SecurityDescriptor.dwLength = dwSDLength;
  2930. attributeValue.SecurityDescriptor.lpValue = (LPBYTE)pSD;
  2931. attributeInfo.pszAttrName = (LPWSTR)c_szSDProperty;
  2932. attributeInfo.dwControlCode = ADS_ATTR_UPDATE;
  2933. attributeInfo.dwADsType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  2934. attributeInfo.pADsValues = &attributeValue;
  2935. attributeInfo.dwNumValues = 1;
  2936. DWORD dwAttributesModified;
  2937. // Write the security descriptor
  2938. hr = pDsObject->SetObjectAttributes(&attributeInfo,
  2939. 1,
  2940. &dwAttributesModified);
  2941. }while(0);
  2942. if(pSDCurrent)
  2943. {
  2944. LocalFree(pSDCurrent);
  2945. }
  2946. if(pSD)
  2947. {
  2948. LocalFree(pSD);
  2949. }
  2950. return S_OK;
  2951. }
  2952. HRESULT SetDaclForDsObjectPath(LPCWSTR pszObjectPath,
  2953. PACL pDACL)
  2954. {
  2955. if(!pszObjectPath || !pDACL)
  2956. return E_POINTER;
  2957. IDirectoryObject* pDsObject = NULL;
  2958. HRESULT hr = ADsOpenObjectHelper(pszObjectPath, IID_IDirectoryObject,0,(void**)&pDsObject);
  2959. if(SUCCEEDED(hr))
  2960. {
  2961. hr = SetDaclForDsObject(pDsObject,pDACL);
  2962. }
  2963. if(pDsObject)
  2964. pDsObject->Release();
  2965. return hr;
  2966. }