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.

466 lines
14 KiB

  1. #include "stdafx.h"
  2. #include "namemap.h"
  3. #include "query.h"
  4. #include "assert.h"
  5. #include <iostream>
  6. using std::wcout;
  7. using std::endl;
  8. DisplayNameMapMap DisplayNames::m_mapMap;
  9. DisplayNameMap* DisplayNames::m_pmapClass = NULL;
  10. LCID DisplayNames::m_locale = GetSystemDefaultLCID();
  11. ///////////////////////////////////////////////
  12. DisplayNameMapMap::~DisplayNameMapMap()
  13. {
  14. for (DisplayNameMapMap::iterator it = begin(); it != end(); it++)
  15. delete (*it).second;
  16. }
  17. ///////////////////////////////////////////////////////////////////////
  18. //
  19. // class DisplayNames
  20. //
  21. ///////////////////////////////////////////////
  22. DisplayNameMap* DisplayNames::GetMap(LPCWSTR name)
  23. {
  24. DisplayNameMapMap::iterator it;
  25. if ((it = m_mapMap.find(name)) != m_mapMap.end())
  26. {
  27. (*it).second->AddRef();
  28. return (*it).second;
  29. }
  30. else
  31. {
  32. DisplayNameMap* nameMap = new DisplayNameMap();
  33. if( !nameMap) return NULL;
  34. m_mapMap.insert(DisplayNameMapMap::value_type(name, nameMap));
  35. nameMap->AddRef();
  36. nameMap->InitializeMap(name);
  37. return nameMap;
  38. }
  39. }
  40. DisplayNameMap* DisplayNames::GetClassMap()
  41. {
  42. if( !m_pmapClass )
  43. {
  44. m_pmapClass = new DisplayNameMap();
  45. if( !m_pmapClass ) return NULL;
  46. m_pmapClass->InitializeClassMap();
  47. }
  48. return m_pmapClass;
  49. }
  50. ///////////////////////////////////////////////
  51. DisplayNameMap::DisplayNameMap()
  52. {
  53. m_nRefCount = 0;
  54. }
  55. void DisplayNameMap::InitializeMap(LPCWSTR name)
  56. {
  57. if( !name ) return;
  58. // Check schema for naming attribute
  59. do
  60. {
  61. // Special case for printer queue
  62. // (display descr maps "Name" to printerName, but schema reports cn)
  63. if (wcscmp(name, L"printQueue") == 0)
  64. {
  65. m_strNameAttr = L"printerName";
  66. break;
  67. }
  68. tstring strScope = L"LDAP://schema/";
  69. strScope += name;
  70. CComPtr<IADsClass> pObj;
  71. HRESULT hr = ADsGetObject((LPWSTR)strScope.c_str(), IID_IADsClass, (void**)&pObj);
  72. BREAK_ON_FAILURE(hr)
  73. CComVariant var;
  74. hr = pObj->get_NamingProperties(&var);
  75. BREAK_ON_FAILURE(hr);
  76. if (var.vt == VT_BSTR)
  77. m_strNameAttr = var.bstrVal;
  78. } while (FALSE);
  79. // if no display name specified, default to "cn"
  80. if (m_strNameAttr.empty())
  81. m_strNameAttr = L"cn";
  82. CComPtr<IADs> spDispSpecCont;
  83. CComBSTR bstrProp;
  84. CComVariant svar;
  85. // Open Display specifier for this object
  86. LPCWSTR pszConfigDN;
  87. EXIT_ON_FAILURE(GetNamingContext(NAMECTX_CONFIG, &pszConfigDN));
  88. //Build the string to bind to the DisplaySpecifiers container.
  89. WCHAR szPath[MAX_PATH];
  90. _snwprintf(szPath, MAX_PATH-1, L"LDAP://cn=%s-Display,cn=%x,cn=DisplaySpecifiers,%s", name, DisplayNames::GetLocale(), pszConfigDN);
  91. //Bind to the DisplaySpecifiers container.
  92. EXIT_ON_FAILURE(ADsOpenObject(szPath,
  93. NULL,
  94. NULL,
  95. ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
  96. IID_IADs,
  97. (void**)&spDispSpecCont));
  98. bstrProp = _T("attributeDisplayNames");
  99. EXIT_ON_FAILURE(spDispSpecCont->Get( bstrProp, &svar ));
  100. #ifdef MAP_DEBUG_PRINT
  101. WCHAR szBuf[128];
  102. _snwprintf(szBuf, (128)-1, L"\n DisplayNameMap for %s\n", name);
  103. OutputDebugString(szBuf);
  104. #endif
  105. tstring strIntName;
  106. tstring strFriendlyName;
  107. if ((svar.vt & VT_ARRAY) == VT_ARRAY)
  108. {
  109. CComVariant svarItem;
  110. SAFEARRAY *sa = V_ARRAY(&svar);
  111. LONG lStart, lEnd;
  112. // Get the lower and upper bound
  113. EXIT_ON_FAILURE(SafeArrayGetLBound(sa, 1, &lStart));
  114. EXIT_ON_FAILURE(SafeArrayGetUBound(sa, 1, &lEnd));
  115. for (long idx=lStart; idx <= lEnd; idx++)
  116. {
  117. CONTINUE_ON_FAILURE(SafeArrayGetElement(sa, &idx, &svarItem));
  118. if( svarItem.vt != VT_BSTR ) return;
  119. strIntName.erase();
  120. strIntName = wcstok(svarItem.bstrVal, L",");
  121. if (strIntName != m_strNameAttr)
  122. {
  123. strFriendlyName.erase();
  124. strFriendlyName = wcstok(NULL, L",");
  125. m_map.insert(STRINGMAP::value_type(strIntName, strFriendlyName));
  126. }
  127. #ifdef MAP_DEBUG_PRINT
  128. _snwprintf( szBuf, (128)-1, L" %-20s %s\n", strIntName.c_str(), strFriendlyName.c_str() );
  129. OutputDebugString(szBuf);
  130. #endif
  131. svarItem.Clear();
  132. }
  133. }
  134. else
  135. {
  136. if( svar.vt != VT_BSTR ) return;
  137. strIntName = wcstok(svar.bstrVal, L",");
  138. if (strIntName != m_strNameAttr)
  139. {
  140. strFriendlyName = wcstok(NULL, L",");
  141. m_map.insert(STRINGMAP::value_type(strIntName, strFriendlyName));
  142. }
  143. }
  144. svar.Clear();
  145. bstrProp = _T("classDisplayName");
  146. EXIT_ON_FAILURE(spDispSpecCont->Get( bstrProp, &svar ));
  147. m_strFriendlyClassName = svar.bstrVal;
  148. }
  149. void DisplayNameMap::InitializeClassMap()
  150. {
  151. CComPtr<IDirectorySearch> spDirSrch;
  152. CComVariant svar;
  153. tstring strIntName;
  154. tstring strFriendlyName;
  155. m_strFriendlyClassName = L"";
  156. LPCWSTR pszConfigContext;
  157. EXIT_ON_FAILURE(GetNamingContext(NAMECTX_CONFIG, &pszConfigContext));
  158. HRESULT hr;
  159. do
  160. {
  161. //Build the string to bind to the DisplaySpecifiers container.
  162. WCHAR szPath[MAX_PATH];
  163. _snwprintf( szPath, MAX_PATH-1, L"LDAP://cn=%x,cn=DisplaySpecifiers,%s", DisplayNames::GetLocale(), pszConfigContext );
  164. //Bind to the DisplaySpecifiers container.
  165. hr = ADsOpenObject(szPath,
  166. NULL,
  167. NULL,
  168. ADS_SECURE_AUTHENTICATION, //Use Secure Authentication
  169. IID_IDirectorySearch,
  170. (void**)&spDirSrch);
  171. // if no display specifiers found, change locale to English (if not already English) and try again
  172. if (FAILED(hr) && DisplayNames::GetLocale() != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US))
  173. DisplayNames::SetLocale(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
  174. else
  175. break;
  176. } while (TRUE);
  177. EXIT_ON_FAILURE(hr);
  178. // Set search preferences
  179. ADS_SEARCHPREF_INFO prefInfo[3];
  180. prefInfo[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; // sub-tree search
  181. prefInfo[0].vValue.dwType = ADSTYPE_INTEGER;
  182. prefInfo[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  183. prefInfo[1].dwSearchPref = ADS_SEARCHPREF_ASYNCHRONOUS; // async
  184. prefInfo[1].vValue.dwType = ADSTYPE_BOOLEAN;
  185. prefInfo[1].vValue.Boolean = TRUE;
  186. prefInfo[2].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; // paged results
  187. prefInfo[2].vValue.dwType = ADSTYPE_INTEGER;
  188. prefInfo[2].vValue.Integer = 64;
  189. EXIT_ON_FAILURE(spDirSrch->SetSearchPreference(prefInfo, 3));
  190. static LPWSTR pAttr[] = {L"name", L"classDisplayName", L"iconPath"};
  191. static LPWSTR pFilter = L"(&(objectCategory=displaySpecifier)(attributeDisplayNames=*))";
  192. // Initiate search
  193. ADS_SEARCH_HANDLE hSearch = NULL;
  194. EXIT_ON_FAILURE(spDirSrch->ExecuteSearch(pFilter, pAttr, lengthof(pAttr), &hSearch));
  195. // Get Results
  196. while (spDirSrch->GetNextRow(hSearch) == S_OK)
  197. {
  198. ADS_SEARCH_COLUMN col;
  199. CONTINUE_ON_FAILURE(spDirSrch->GetColumn(hSearch, const_cast<LPWSTR>(pAttr[0]), &col));
  200. strIntName.erase();
  201. strIntName = wcstok(col.pADsValues->PrintableString, L"-");
  202. spDirSrch->FreeColumn(&col);
  203. CONTINUE_ON_FAILURE(spDirSrch->GetColumn(hSearch, const_cast<LPWSTR>(pAttr[1]), &col));
  204. strFriendlyName.erase();
  205. strFriendlyName = col.pADsValues->PrintableString;
  206. spDirSrch->FreeColumn(&col);
  207. m_map.insert(STRINGMAP::value_type(strIntName, strFriendlyName));
  208. //add icon string to map
  209. ICONHOLDER IH;
  210. //if iconPath exists in the AD, copy the value to the ICONHOLDER structure
  211. if(SUCCEEDED(spDirSrch->GetColumn(hSearch, const_cast<LPWSTR>(pAttr[2]), &col))) {
  212. IH.strPath = col.pADsValues->PrintableString;
  213. spDirSrch->FreeColumn(&col);
  214. }
  215. //add the ICONHOLDER structure to the map (empty string for default types)
  216. m_msIcons.insert(std::pair<tstring, ICONHOLDER>(strFriendlyName, IH));
  217. }
  218. spDirSrch->CloseSearchHandle(hSearch);
  219. }
  220. LPCWSTR DisplayNameMap::GetAttributeDisplayName(LPCWSTR pszname)
  221. {
  222. if( !pszname ) return L"";
  223. STRINGMAP::iterator it;
  224. if ((it = m_map.find(pszname)) != m_map.end())
  225. return (*it).second.c_str();
  226. else
  227. return pszname;
  228. }
  229. LPCWSTR DisplayNameMap::GetInternalName(LPCWSTR pszDisplayName)
  230. {
  231. if( !pszDisplayName ) return L"";
  232. STRINGMAP::iterator it;
  233. for (it = m_map.begin(); it != m_map.end(); it++)
  234. {
  235. if ((*it).second == pszDisplayName)
  236. return (*it).first.c_str();
  237. }
  238. return pszDisplayName;
  239. }
  240. LPCWSTR DisplayNameMap::GetFriendlyName(LPCWSTR pszDisplayName)
  241. {
  242. if( !pszDisplayName ) return L"";
  243. STRINGMAP::iterator it;
  244. if((it = m_map.find(pszDisplayName)) != m_map.end())
  245. return it->second.c_str();
  246. return pszDisplayName;
  247. }
  248. void DisplayNameMap::GetFriendlyNames(string_vector* vec)
  249. {
  250. if( !vec ) return;
  251. STRINGMAP::iterator it;
  252. for (it = m_map.begin(); it != m_map.end(); it++)
  253. {
  254. vec->push_back((*it).first);
  255. }
  256. }
  257. // retreives a handle to the icon for the provided class
  258. // params: pszClassName - class name
  259. // returns: boolean success
  260. bool DisplayNameMap::GetIcons(LPCWSTR pszClassName, ICONHOLDER** pReturnIH)
  261. {
  262. if( !pszClassName || !pReturnIH ) return FALSE;
  263. static UINT iFreeIconIndex = RESULT_ITEM_IMAGE + 1; //next free virtual index
  264. static ICONHOLDER DefaultIH; //upon construction, this item holds default values
  265. *pReturnIH = &DefaultIH; //In the case of errors, returned icon will hold default icon
  266. std::map<tstring, ICONHOLDER>::iterator iconIter;
  267. ICONHOLDER *pIH; //pointer to the ICONHOLDER
  268. //CASE: Requested class not found in list returned by Active Directory
  269. if((iconIter = m_msIcons.find(pszClassName)) == m_msIcons.end()) {
  270. return false;
  271. }
  272. pIH = &(iconIter->second); //convenience variable to ICONHOLDER
  273. //CASE: Requsted icons already loaded
  274. if(pIH->bAttempted == true) {
  275. *pReturnIH = pIH;
  276. return true;
  277. }
  278. //CASE: An attempt to load the icon has not yet been made
  279. while(pIH->bAttempted == false)
  280. {
  281. //making first attempt
  282. pIH->bAttempted = true;
  283. //try to load the icon using the IDsDisplaySpecifier interface first
  284. IDsDisplaySpecifier *pDS;
  285. HRESULT hr = CoCreateInstance(CLSID_DsDisplaySpecifier,
  286. NULL,
  287. CLSCTX_INPROC_SERVER,
  288. IID_IDsDisplaySpecifier,
  289. (void**)&pDS);
  290. if( FAILED(hr) ) return false;
  291. //load all icon sizes and states
  292. tstring strIntClassName = GetInternalName(pszClassName);
  293. pIH->hSmall = pDS->GetIcon(strIntClassName.c_str(), DSGIF_ISNORMAL, 16, 16);
  294. pIH->hLarge = pDS->GetIcon(strIntClassName.c_str(), DSGIF_ISNORMAL, 32, 32);
  295. pIH->hSmallDis = pDS->GetIcon(strIntClassName.c_str(), DSGIF_ISDISABLED, 16, 16);
  296. pIH->hLargeDis = pDS->GetIcon(strIntClassName.c_str(), DSGIF_ISDISABLED, 32, 32);
  297. pDS->Release();
  298. //CASE: Icon loaded from AD
  299. if(pIH->hSmall) break;
  300. //CASE: No file specified
  301. if(pIH->strPath.empty()) break;
  302. //tokenize the iconPath variable
  303. tstring strState = wcstok(const_cast<wchar_t*>(pIH->strPath.c_str()), L",");
  304. tstring strFile = wcstok(NULL, L",");
  305. tstring strIndex = wcstok(NULL, L",");
  306. int iIndex; //integer value of index
  307. //CASE: file is environment variable
  308. if(strFile.at(0) == L'%' && strFile.at(strFile.length()-1) == L'%')
  309. {
  310. //chop off '%' indicators
  311. strFile = strFile.substr(1, strFile.length()-2);
  312. int nSize = 512;
  313. WCHAR* pwszBuffer = new WCHAR[nSize];
  314. if( !pwszBuffer ) break;
  315. DWORD dwSize = GetEnvironmentVariable( strFile.c_str(), pwszBuffer, nSize );
  316. if( dwSize == 0 ) break;
  317. if( dwSize >= nSize )
  318. {
  319. delete [] pwszBuffer;
  320. nSize = dwSize;
  321. pwszBuffer = new WCHAR[nSize];
  322. if( !pwszBuffer ) break;
  323. dwSize = GetEnvironmentVariable( strFile.c_str(), pwszBuffer, nSize );
  324. if( dwSize == 0 || dwSize >= nSize ) break;
  325. }
  326. strFile = pwszBuffer;
  327. }
  328. if(strIndex.empty())
  329. {
  330. //CASE: ICO file specified
  331. pIH->hSmall = (HICON)LoadImage(NULL, strFile.c_str(), IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
  332. pIH->hLarge = (HICON)LoadImage(NULL, strFile.c_str(), IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
  333. }
  334. else
  335. {
  336. //CASE: DLL file specified
  337. iIndex = _wtoi(strIndex.c_str());
  338. assert(iIndex <= 0); //in all known cases, the index is indicating an absolute reference
  339. HINSTANCE hLib = LoadLibraryEx(strFile.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE);
  340. if(hLib == NULL) break;
  341. pIH->hSmall = CopyIcon((HICON)LoadImage(hLib, MAKEINTRESOURCE(-iIndex), IMAGE_ICON, 16, 16, NULL));
  342. pIH->hLarge = CopyIcon((HICON)LoadImage(hLib, MAKEINTRESOURCE(-iIndex), IMAGE_ICON, 32, 32, NULL));
  343. FreeLibrary(hLib);
  344. }
  345. }
  346. //CASE: something failed. Fill with default values and return.
  347. if(pIH->hSmall == NULL)
  348. {
  349. pIH->hSmall = pIH->hSmallDis = NULL;
  350. pIH->hLarge = pIH->hLargeDis = NULL;
  351. pIH->iNormal = RESULT_ITEM_IMAGE;
  352. pIH->iDisabled = RESULT_ITEM_IMAGE;
  353. }
  354. //CASE: succeeded. Must assign permanent virtual index.
  355. else
  356. {
  357. pIH->iNormal = iFreeIconIndex++;
  358. pIH->iDisabled = pIH->hSmallDis ? iFreeIconIndex++ : pIH->iNormal;
  359. }
  360. *pReturnIH = pIH;
  361. return true;
  362. }