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.

643 lines
19 KiB

  1. #ifndef _AUSRUTIL_H
  2. #define _AUSRUTIL_H
  3. #include <activeds.h>
  4. #include "EscStr.h"
  5. #include <lm.h>
  6. #include <lmapibuf.h>
  7. #include <lmshare.h>
  8. #define SECURITY_WIN32
  9. #include <security.h>
  10. enum NameContextType
  11. {
  12. NAMECTX_SCHEMA = 0,
  13. NAMECTX_CONFIG = 1,
  14. NAMECTX_COUNT
  15. };
  16. // ----------------------------------------------------------------------------
  17. // GetADNamingContext()
  18. // ----------------------------------------------------------------------------
  19. inline HRESULT GetADNamingContext(NameContextType ctx, LPCWSTR* ppszContextDN)
  20. {
  21. const static LPCWSTR pszContextName[NAMECTX_COUNT] = { L"schemaNamingContext", L"configurationNamingContext"};
  22. static CString strContextDN[NAMECTX_COUNT];
  23. HRESULT hr = S_OK;
  24. if (strContextDN[ctx].IsEmpty())
  25. {
  26. CComVariant var;
  27. CComPtr<IADs> pObj;
  28. hr = ADsGetObject(L"LDAP://rootDSE", IID_IADs, (void**)&pObj);
  29. if (SUCCEEDED(hr))
  30. {
  31. CComBSTR bstrProp = pszContextName[ctx];
  32. hr = pObj->Get( bstrProp, &var );
  33. if (SUCCEEDED(hr))
  34. {
  35. strContextDN[ctx] = var.bstrVal;
  36. *ppszContextDN = strContextDN[ctx];
  37. }
  38. }
  39. }
  40. else
  41. {
  42. *ppszContextDN = strContextDN[ctx];
  43. hr = S_OK;
  44. }
  45. return hr;
  46. }
  47. //--------------------------------------------------------------------------
  48. // EnableButton
  49. //
  50. // Enables or disables a dialog control. If the control has the focus when
  51. // it is disabled, the focus is moved to the next control
  52. //--------------------------------------------------------------------------
  53. inline void EnableButton(HWND hwndDialog, int iCtrlID, BOOL bEnable)
  54. {
  55. HWND hWndCtrl = ::GetDlgItem(hwndDialog, iCtrlID);
  56. ATLASSERT(::IsWindow(hWndCtrl));
  57. if (!bEnable && ::GetFocus() == hWndCtrl)
  58. {
  59. HWND hWndNextCtrl = ::GetNextDlgTabItem(hwndDialog, hWndCtrl, FALSE);
  60. if (hWndNextCtrl != NULL && hWndNextCtrl != hWndCtrl)
  61. {
  62. ::SetFocus(hWndNextCtrl);
  63. }
  64. }
  65. ::EnableWindow(hWndCtrl, bEnable);
  66. }
  67. // ----------------------------------------------------------------------------
  68. // ErrorMsg()
  69. // ----------------------------------------------------------------------------
  70. inline void ErrorMsg(UINT uiError, UINT uiTitle)
  71. {
  72. CString csError;
  73. CString csTitle;
  74. csError.LoadString(uiError);
  75. csTitle.LoadString(uiTitle);
  76. ::MessageBox(NULL, (LPCWSTR)csError, (LPCWSTR)csTitle, MB_OK | MB_TASKMODAL | MB_ICONERROR);
  77. }
  78. inline BOOL StrContainsDBCS(LPCTSTR szIn)
  79. {
  80. if( !szIn ) return FALSE;
  81. BOOL bFound = FALSE;
  82. TCHAR *pch = NULL;
  83. for ( pch=(LPTSTR)szIn; *pch && !bFound; pch=_tcsinc(pch) )
  84. {
  85. if ( IsDBCSLeadByte((BYTE)*pch) )
  86. {
  87. bFound = TRUE;
  88. }
  89. }
  90. return bFound;
  91. }
  92. inline BOOL LdapToDCName(LPCTSTR pszPath, LPTSTR pszOutBuf, int nOutBufSize)
  93. {
  94. if( !pszPath || !pszOutBuf || !nOutBufSize ) return FALSE;
  95. pszOutBuf[0] = 0;
  96. TCHAR* pszTemp = _tcsstr( pszPath, _T("DC=") );
  97. if( !pszTemp ) return FALSE;
  98. DWORD dwSize = nOutBufSize;
  99. BOOLEAN bSuccess = TranslateName( pszTemp, NameFullyQualifiedDN, NameCanonical, pszOutBuf, &dwSize );
  100. if( bSuccess && (dwSize > 2) )
  101. {
  102. if( pszOutBuf[dwSize-2] == _T('/') )
  103. {
  104. pszOutBuf[dwSize-2] = 0;
  105. }
  106. }
  107. return (BOOL)bSuccess;
  108. }
  109. // ----------------------------------------------------------------------------
  110. // FindADsObject()
  111. //
  112. // szFilterFmt must be of the format "(|(cn=%1)(ou=%1))"
  113. // NOTE: szFilterFmt must contain ONLY %1's.. i.e. %2 is right out!
  114. // ----------------------------------------------------------------------------
  115. inline HRESULT FindADsObject( LPCTSTR szOU, LPCTSTR szObject, LPCTSTR szFilterFmt, CString &csResult, DWORD dwRetType/*=0*/, BOOL bRoot/*=FALSE*/ )
  116. {
  117. if( !szOU || !szObject || !szFilterFmt ) return E_POINTER;
  118. // Find out if the szObject contains any '(' or ')'s.. if so then we have to exit.
  119. if ( _tcschr(szObject, _T('(')) ||
  120. _tcschr(szObject, _T(')')) )
  121. {
  122. return S_FALSE;
  123. }
  124. HRESULT hr = S_OK;
  125. CString csTmp = szOU;
  126. CString csOU = L"LDAP://";
  127. TCHAR *pch = NULL;
  128. if ( bRoot )
  129. {
  130. csTmp.MakeUpper();
  131. pch = _tcsstr( (LPCTSTR)csTmp, L"DC=" ); // Find the first DC=
  132. if ( !pch ) return E_FAIL;
  133. csOU += pch; // Append from the DC= on.
  134. if ( (pch = _tcschr((LPCTSTR)csOU + 7, L'/')) != NULL )
  135. {
  136. // Hmmm. . something was after the DC='s... I don't even know
  137. // if that's allowed.
  138. // (e.g. LDAP://DC=ted,DC=microsoft,DC=com/foo)
  139. // If so, let's end the string at the /
  140. *pch = 0;
  141. }
  142. }
  143. else
  144. {
  145. csTmp.MakeUpper();
  146. pch = _tcsstr( (LPCTSTR)csTmp, L"LDAP://" ); // Did the string include the LDAP://?
  147. if ( !pch )
  148. {
  149. csOU += csTmp;
  150. }
  151. else
  152. {
  153. csOU = csTmp;
  154. }
  155. // Now csOU contains the LDAP:// for sure.
  156. }
  157. // Set query parameters
  158. CComPtr<IDirectorySearch> spDirSearch = NULL;
  159. ADS_SEARCH_HANDLE hSearch; // Handle used for searching.
  160. ADS_SEARCH_COLUMN col; // Used to hold the current column.
  161. CString csFilter;
  162. LPTSTR pszAttr[] = { _T("cn"), _T("distinguishedName"), _T("description"), _T("sAMAccountName"), _T("mailNickname") };
  163. DWORD dwCount = sizeof(pszAttr) / sizeof(LPTSTR);
  164. csFilter.FormatMessage(szFilterFmt, szObject);
  165. // Open our search object.
  166. hr = ::ADsOpenObject(const_cast<LPTSTR>((LPCTSTR)csOU), NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (void**)&spDirSearch);
  167. if ( !SUCCEEDED(hr) )
  168. {
  169. _ASSERT(FALSE);
  170. return hr;
  171. }
  172. // Search for out object.
  173. hr = spDirSearch->ExecuteSearch(const_cast<LPTSTR>((LPCTSTR)csFilter), pszAttr, dwCount, &hSearch);
  174. if ( !SUCCEEDED(hr) )
  175. {
  176. return(hr);
  177. }
  178. if ( spDirSearch->GetNextRow(hSearch) == S_ADS_NOMORE_ROWS )
  179. {
  180. spDirSearch->CloseSearchHandle(hSearch);
  181. return(E_FAIL);
  182. }
  183. // If we got to here, then we got the object, so let's get the LDAP path to the
  184. // object so that we can return it to the caller.
  185. hr = spDirSearch->GetColumn(hSearch, pszAttr[dwRetType], &col);
  186. if ( !SUCCEEDED(hr) )
  187. {
  188. _ASSERT(FALSE);
  189. csResult = _T("");
  190. }
  191. else
  192. {
  193. csResult = col.pADsValues->CaseExactString;
  194. spDirSearch->FreeColumn(&col);
  195. }
  196. spDirSearch->CloseSearchHandle(hSearch);
  197. return(S_OK);
  198. }
  199. inline tstring GetDomainPath( LPCTSTR lpServer )
  200. {
  201. if( !lpServer ) return _T("");
  202. // get the domain information
  203. CComVariant var;
  204. tstring strRet = _T("");
  205. TCHAR pszString[MAX_PATH*2] = {0};
  206. _sntprintf( pszString, (MAX_PATH*2)-1, L"LDAP://%s/rootDSE", lpServer );
  207. CComPtr<IADs> pDS = NULL;
  208. HRESULT hr = ::ADsGetObject( pszString, IID_IADs, (void**)&pDS );
  209. if( SUCCEEDED(hr) )
  210. {
  211. CComBSTR bstrProp = _T("defaultNamingContext");
  212. hr = pDS->Get( bstrProp, &var );
  213. }
  214. if( SUCCEEDED(hr) && (V_VT(&var) == VT_BSTR) )
  215. {
  216. strRet = V_BSTR( &var );
  217. }
  218. return strRet;
  219. }
  220. //+----------------------------------------------------------------------------
  221. //
  222. // Function: RemoveTrailingWhitespace
  223. //
  224. // Synopsis: Trailing white space is replaced by NULLs.
  225. //
  226. //-----------------------------------------------------------------------------
  227. inline void RemoveTrailingWhitespace(LPTSTR pszIn)
  228. {
  229. if( !pszIn ) return;
  230. int nLen = _tcslen(pszIn);
  231. while( nLen )
  232. {
  233. if( !iswspace(pszIn[nLen - 1]) )
  234. {
  235. return;
  236. }
  237. pszIn[nLen - 1] = L'\0';
  238. nLen--;
  239. }
  240. }
  241. inline tstring StrFormatSystemError( HRESULT hrErr )
  242. {
  243. tstring strError = _T("");
  244. LPVOID lpMsgBuf = NULL;
  245. // look up the error from the system
  246. if ( ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  247. FORMAT_MESSAGE_FROM_SYSTEM |
  248. FORMAT_MESSAGE_IGNORE_INSERTS,
  249. NULL,
  250. hrErr,
  251. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  252. (LPTSTR)&lpMsgBuf,
  253. 0,
  254. NULL ))
  255. {
  256. if( lpMsgBuf )
  257. {
  258. strError = (LPTSTR)lpMsgBuf;
  259. LocalFree( lpMsgBuf );
  260. }
  261. }
  262. // return the error string
  263. return strError;
  264. }
  265. inline tstring StrGetWindowText( HWND hWnd )
  266. {
  267. if( !hWnd || !IsWindow(hWnd) )
  268. {
  269. return _T("");
  270. }
  271. TSTRING strRet = _T("");
  272. INT iLen = GetWindowTextLength(hWnd);
  273. TCHAR* pszText = new TCHAR[ iLen + 1 ];
  274. if ( pszText )
  275. {
  276. if ( GetWindowText(hWnd, pszText, iLen + 1) )
  277. {
  278. strRet = pszText;
  279. }
  280. delete[] pszText;
  281. }
  282. return strRet;
  283. }
  284. inline HRESULT SetSecInfoMask( LPUNKNOWN punk, SECURITY_INFORMATION si )
  285. {
  286. HRESULT hr = E_INVALIDARG;
  287. if( punk )
  288. {
  289. CComPtr<IADsObjectOptions> spOptions;
  290. hr = punk->QueryInterface( IID_IADsObjectOptions, (void**)&spOptions );
  291. if( SUCCEEDED(hr) )
  292. {
  293. VARIANT var;
  294. VariantInit( &var );
  295. V_VT( &var ) = VT_I4;
  296. V_I4( &var ) = si;
  297. hr = spOptions->SetOption( ADS_OPTION_SECURITY_MASK, var );
  298. }
  299. }
  300. return hr;
  301. }
  302. //+---------------------------------------------------------------------------
  303. //
  304. // Function: GetSDForDsObject
  305. // Synopsis: Reads the security descriptor from the specied DS object
  306. // It only reads the DACL portion of the security descriptor
  307. //
  308. // Arguments: [IN pDsObject] -- DS object
  309. // [ppDACL] --pointer to dacl in ppSD is returned here
  310. // [OUT ppSD] -- Security descriptor returned here.
  311. // calling API must free this by calling LocalFree
  312. //
  313. // Notes: The returned security descriptor must be freed with LocalFree
  314. //
  315. //----------------------------------------------------------------------------
  316. inline HRESULT GetSDForDsObject( IDirectoryObject* pDsObject, PACL* ppDACL, PSECURITY_DESCRIPTOR* ppSD )
  317. {
  318. if(!pDsObject || !ppSD) return E_POINTER;
  319. *ppSD = NULL;
  320. if(ppDACL)
  321. {
  322. *ppDACL = NULL;
  323. }
  324. HRESULT hr = S_OK;
  325. PADS_ATTR_INFO pSDAttributeInfo = NULL;
  326. WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
  327. LPWSTR pszProperty = (LPWSTR)c_szSDProperty;
  328. // Set the SECURITY_INFORMATION mask to DACL_SECURITY_INFORMATION
  329. hr = SetSecInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  330. DWORD dwAttributesReturned;
  331. if( SUCCEEDED(hr) )
  332. {
  333. // Read the security descriptor attribute
  334. hr = pDsObject->GetObjectAttributes( &pszProperty, 1, &pSDAttributeInfo, &dwAttributesReturned );
  335. if(SUCCEEDED(hr) && !pSDAttributeInfo)
  336. {
  337. hr = E_FAIL;
  338. }
  339. }
  340. if( SUCCEEDED(hr) )
  341. {
  342. if((ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->dwADsType) &&
  343. (ADSTYPE_NT_SECURITY_DESCRIPTOR == pSDAttributeInfo->pADsValues->dwType))
  344. {
  345. *ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, pSDAttributeInfo->pADsValues->SecurityDescriptor.dwLength);
  346. if (!*ppSD)
  347. {
  348. hr = E_OUTOFMEMORY;
  349. }
  350. }
  351. else
  352. {
  353. hr = E_FAIL;
  354. }
  355. }
  356. if( SUCCEEDED(hr) )
  357. {
  358. CopyMemory( *ppSD, pSDAttributeInfo->pADsValues->SecurityDescriptor.lpValue, pSDAttributeInfo->pADsValues->SecurityDescriptor.dwLength );
  359. if( ppDACL )
  360. {
  361. BOOL bDaclPresent,bDaclDeafulted;
  362. if( !GetSecurityDescriptorDacl(*ppSD, &bDaclPresent, ppDACL, &bDaclDeafulted) )
  363. {
  364. DWORD dwErr = GetLastError();
  365. hr = HRESULT_FROM_WIN32(dwErr);
  366. }
  367. }
  368. }
  369. if( pSDAttributeInfo )
  370. {
  371. FreeADsMem( pSDAttributeInfo );
  372. }
  373. if( FAILED(hr) )
  374. {
  375. if(*ppSD)
  376. {
  377. LocalFree(*ppSD);
  378. *ppSD = NULL;
  379. if(ppDACL)
  380. *ppDACL = NULL;
  381. }
  382. }
  383. return hr;
  384. }
  385. //+---------------------------------------------------------------------------
  386. //
  387. // Function: GetSDForDsObjectPath
  388. // Synopsis: Reads the security descriptor from the specied DS object
  389. // It only reads the DACL portion of the security descriptor
  390. //
  391. // Arguments: [IN pszObjectPath] -- LDAP Path of ds object
  392. // [ppDACL] --pointer to dacl in ppSD is returned here
  393. // [OUT ppSD] -- Security descriptor returned here.
  394. // calling API must free this by calling LocalFree
  395. //
  396. // Notes: The returned security descriptor must be freed with LocalFree
  397. //
  398. //----------------------------------------------------------------------------
  399. inline HRESULT GetSDForDsObjectPath( LPCWSTR pszObjectPath, PACL* ppDACL, PSECURITY_DESCRIPTOR* ppSecurityDescriptor )
  400. {
  401. if(!pszObjectPath || !ppSecurityDescriptor) return E_POINTER;
  402. CComPtr<IDirectoryObject> spDsObject = NULL;
  403. HRESULT hr = ADsGetObject(pszObjectPath, IID_IDirectoryObject,(void**)&spDsObject);
  404. if(SUCCEEDED(hr))
  405. {
  406. hr = GetSDForDsObject( spDsObject, ppDACL, ppSecurityDescriptor );
  407. }
  408. return hr;
  409. }
  410. //+---------------------------------------------------------------------------
  411. //
  412. // Function: SetDaclForDsObject
  413. // Synopsis: Sets the the DACL for the specified DS object
  414. //
  415. // Arguments: [IN pDsObject] -- ds object
  416. // [IN pDACL] --pointer to dacl to be set
  417. //
  418. //----------------------------------------------------------------------------
  419. inline HRESULT SetDaclForDsObject( IDirectoryObject* pDsObject, PACL pDACL )
  420. {
  421. if(!pDsObject || !pDACL) return E_POINTER;
  422. WCHAR const c_szSDProperty[] = L"nTSecurityDescriptor";
  423. PSECURITY_DESCRIPTOR pSD = NULL;
  424. PSECURITY_DESCRIPTOR pSDCurrent = NULL;
  425. HRESULT hr = S_OK;
  426. //Get the current SD for the object
  427. hr = GetSDForDsObject(pDsObject,NULL,&pSDCurrent);
  428. //Get the control for the current security descriptor
  429. SECURITY_DESCRIPTOR_CONTROL currentControl;
  430. DWORD dwRevision = 0;
  431. if( SUCCEEDED(hr) )
  432. {
  433. if( !GetSecurityDescriptorControl(pSDCurrent, &currentControl, &dwRevision) )
  434. {
  435. DWORD dwErr = GetLastError();
  436. hr = HRESULT_FROM_WIN32(dwErr);
  437. }
  438. }
  439. if( SUCCEEDED(hr) )
  440. {
  441. //Allocate the buffer for Security Descriptor
  442. pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH + pDACL->AclSize);
  443. if(!pSD)
  444. {
  445. hr = E_OUTOFMEMORY;
  446. }
  447. }
  448. if( SUCCEEDED(hr) )
  449. {
  450. if(!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
  451. {
  452. DWORD dwErr = GetLastError();
  453. hr = HRESULT_FROM_WIN32(dwErr);
  454. }
  455. }
  456. if( SUCCEEDED(hr) )
  457. {
  458. PISECURITY_DESCRIPTOR pISD = (PISECURITY_DESCRIPTOR)pSD;
  459. //
  460. // Finally, build the security descriptor
  461. //
  462. pISD->Control |= SE_DACL_PRESENT | SE_DACL_AUTO_INHERIT_REQ | (currentControl & (SE_DACL_PROTECTED | SE_DACL_AUTO_INHERITED));
  463. if (pDACL->AclSize > 0)
  464. {
  465. pISD->Dacl = (PACL)(pISD + 1);
  466. CopyMemory(pISD->Dacl, pDACL, pDACL->AclSize);
  467. }
  468. // We are only setting DACL information
  469. hr = SetSecInfoMask(pDsObject, DACL_SECURITY_INFORMATION);
  470. }
  471. SECURITY_DESCRIPTOR_CONTROL sdControl = 0;
  472. if( SUCCEEDED(hr) )
  473. {
  474. //
  475. // If necessary, make a self-relative copy of the security descriptor
  476. //
  477. if(!GetSecurityDescriptorControl(pSD, &sdControl, &dwRevision))
  478. {
  479. DWORD dwErr = GetLastError();
  480. hr = HRESULT_FROM_WIN32(dwErr);
  481. }
  482. }
  483. DWORD dwSDLength = 0;
  484. if( SUCCEEDED(hr) )
  485. {
  486. // Need the total size
  487. dwSDLength = GetSecurityDescriptorLength(pSD);
  488. if (!(sdControl & SE_SELF_RELATIVE))
  489. {
  490. PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSDLength);
  491. if (psd == NULL || !MakeSelfRelativeSD(pSD, psd, &dwSDLength))
  492. {
  493. DWORD dwErr = GetLastError();
  494. hr = HRESULT_FROM_WIN32(dwErr);
  495. }
  496. // Point to the self-relative copy
  497. LocalFree(pSD);
  498. pSD = psd;
  499. }
  500. }
  501. if( SUCCEEDED(hr) )
  502. {
  503. ADSVALUE attributeValue;
  504. attributeValue.dwType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  505. attributeValue.SecurityDescriptor.dwLength = dwSDLength;
  506. attributeValue.SecurityDescriptor.lpValue = (LPBYTE)pSD;
  507. ADS_ATTR_INFO attributeInfo;
  508. attributeInfo.pszAttrName = (LPWSTR)c_szSDProperty;
  509. attributeInfo.dwControlCode = ADS_ATTR_UPDATE;
  510. attributeInfo.dwADsType = ADSTYPE_NT_SECURITY_DESCRIPTOR;
  511. attributeInfo.pADsValues = &attributeValue;
  512. attributeInfo.dwNumValues = 1;
  513. // Write the security descriptor
  514. DWORD dwAttributesModified;
  515. hr = pDsObject->SetObjectAttributes(&attributeInfo, 1, &dwAttributesModified);
  516. }
  517. if(pSDCurrent)
  518. {
  519. LocalFree(pSDCurrent);
  520. }
  521. if(pSD)
  522. {
  523. LocalFree(pSD);
  524. }
  525. return S_OK;
  526. }
  527. inline HRESULT SetDaclForDsObjectPath( LPCWSTR pszObjectPath, PACL pDACL )
  528. {
  529. // VAlidate the parameters
  530. if(!pszObjectPath || !pDACL) return E_POINTER;
  531. // Get the object and then pass it on to the helper function
  532. CComPtr<IDirectoryObject> spDsObject = NULL;
  533. HRESULT hr = ADsGetObject( pszObjectPath, IID_IDirectoryObject, (void**)&spDsObject );
  534. if( SUCCEEDED(hr) )
  535. {
  536. hr = SetDaclForDsObject( spDsObject, pDACL );
  537. }
  538. return hr;
  539. }
  540. #endif // _AUSRUTIL_H