dispspec.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 16k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "pch.h"
  2. #include "dsrole.h"
  3. #pragma hdrstop
  4. /*-----------------------------------------------------------------------------
  5. / Display specifier helpers/cache functions
  6. /----------------------------------------------------------------------------*/
  7. #define DEFAULT_LANGUAGE      0x409
  8. #define DISPLAY_SPECIFIERS    L"CN=displaySpecifiers"
  9. #define SPECIFIER_PREFIX      L"CN="
  10. #define SPECIFIER_POSTFIX     L"-Display"
  11. #define DEFAULT_SPECIFIER     L"default"
  12. /*-----------------------------------------------------------------------------
  13. / GetDisplaySpecifier
  14. / -------------------
  15. /   Get the specified display specifier (sic), given it an LANGID etc.
  16. /
  17. / In:
  18. /   pccgi -> CLASSCACHEGETINFO structure.
  19. /   riid = interface
  20. /   ppvObject = object requested
  21. /
  22. / Out:
  23.     HRESULT
  24. /----------------------------------------------------------------------------*/
  25. HRESULT _GetServerConfigPath(LPWSTR *ppszServerConfigPath, LPCLASSCACHEGETINFO pccgi)
  26. {
  27.     HRESULT hres;
  28.     IADs* padsRootDSE = NULL;
  29.     BSTR bstrConfigContainer = NULL;
  30.     VARIANT variant;
  31.     INT cchString;
  32.     LPWSTR pszServer = pccgi->pServer;
  33. #if !DOWNLEVEL_SHELL
  34.     LPWSTR pszMachineServer = NULL;
  35. #endif
  36.     USES_CONVERSION;
  37.     *ppszServerConfigPath = NULL;
  38.     VariantInit(&variant);
  39.     //
  40.     // open the RootDSE for the server we are interested in, if we are using the default
  41.     // server then lets just use the cached version.
  42.     //
  43.     hres = GetCacheInfoRootDSE(pccgi, &padsRootDSE);
  44. #if !DOWNLEVEL_SHELL
  45.     if ( (hres == HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN)) && !pccgi->pServer )
  46.     {
  47.         TraceMsg("Failed to get the RootDSE from the server - not found");
  48.         DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pInfo;
  49.         if ( DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic, (BYTE**)&pInfo) == WN_SUCCESS )
  50.         {
  51.             if ( pInfo->DomainNameDns )
  52.             {
  53.                 Trace(TEXT("Machine domain is: %s"), W2T(pInfo->DomainNameDns));
  54.                 CLASSCACHEGETINFO ccgi = *pccgi;
  55.                 ccgi.pServer = pInfo->DomainNameDns;
  56.                 hres = GetCacheInfoRootDSE(&ccgi, &padsRootDSE);
  57.                 if ( SUCCEEDED(hres) )
  58.                 {
  59.                     hres = LocalAllocStringW(&pszMachineServer, pInfo->DomainNameDns);
  60.                     pszServer = pszMachineServer;
  61.                 }
  62.             }
  63.             DsRoleFreeMemory(pInfo);
  64.         }
  65.     }
  66. #endif
  67.     FailGracefully(hres, "Failed to get the IADs for the RootDSE");
  68.     //
  69.     // we now have the RootDSE, so lets read the config container path and compose
  70.     // a string that the outside world cna use
  71.     //
  72.     hres = padsRootDSE->Get(L"configurationNamingContext", &variant);
  73.     FailGracefully(hres, "Failed to get the 'configurationNamingContext' property");
  74.     if ( V_VT(&variant) != VT_BSTR )
  75.         ExitGracefully(hres, E_FAIL, "configurationNamingContext is not a BSTR");
  76.     cchString = lstrlenW(L"LDAP://") + lstrlenW(V_BSTR(&variant));
  77.     
  78.     if ( pszServer )
  79.         cchString += lstrlenW(pszServer) + 1;   // NB: +1 for '/'
  80.     //
  81.     // allocate the buffer we want to use, and fill it
  82.     //
  83.     hres = LocalAllocStringLenW(ppszServerConfigPath, cchString);
  84.     FailGracefully(hres, "Failed to allocate buffer for server path");
  85.     StrCpyW(*ppszServerConfigPath, L"LDAP://");
  86.     
  87.     if ( pszServer )
  88.     {
  89.         StrCatW(*ppszServerConfigPath, pszServer);
  90.         StrCatW(*ppszServerConfigPath, L"/");
  91.     }
  92.     StrCatW(*ppszServerConfigPath, V_BSTR(&variant)); 
  93.     Trace(TEXT("Server config path is: %s"), W2T(*ppszServerConfigPath));
  94.     hres = S_OK;                    // success
  95. exit_gracefully:
  96.     DoRelease(padsRootDSE);
  97.     SysFreeString(bstrConfigContainer);
  98. #if !DOWNLEVEL_SHELL
  99.     LocalFreeStringW(&pszMachineServer);
  100. #endif
  101.     VariantClear(&variant);
  102.     return hres;
  103. }
  104. HRESULT _ComposeSpecifierPath(LPWSTR pSpecifier, LANGID langid, LPWSTR pConfigPath, IADsPathname* pDsPathname, BSTR *pbstrDisplaySpecifier)
  105. {
  106.     TCHAR szLANGID[16];
  107.     WCHAR szSpecifierFull[MAX_PATH];
  108.     USES_CONVERSION;
  109.     
  110.     pDsPathname->Set(pConfigPath, ADS_SETTYPE_FULL);
  111.     pDsPathname->AddLeafElement(DISPLAY_SPECIFIERS);
  112.     if ( !langid )
  113.         langid = GetUserDefaultUILanguage();
  114.     wsprintf(szLANGID, TEXT("CN=%x"), langid);
  115.     pDsPathname->AddLeafElement(T2W(szLANGID));
  116.     if ( pSpecifier )
  117.     {
  118.         StrCpyW(szSpecifierFull, SPECIFIER_PREFIX);
  119.         StrCatW(szSpecifierFull, pSpecifier);
  120.         StrCatW(szSpecifierFull, SPECIFIER_POSTFIX);
  121.         Trace(TEXT("szSpecifierFull: %s"), W2T(szSpecifierFull));
  122.         pDsPathname->AddLeafElement(szSpecifierFull);           // add to the name we are dealing with
  123.     }
  124.     return pDsPathname->Retrieve(ADS_FORMAT_WINDOWS, pbstrDisplaySpecifier);
  125. }
  126. HRESULT GetDisplaySpecifier(LPCLASSCACHEGETINFO pccgi, REFIID riid, LPVOID* ppvObject)
  127. {
  128.     HRESULT hr;
  129.     IADsPathname* pDsPathname = NULL;
  130.     BSTR bstrDisplaySpecifier = NULL;
  131.     LPWSTR pszServerConfigPath = NULL;
  132.     USES_CONVERSION;
  133.     TraceEnter(TRACE_CACHE, "GetDisplaySpecifier");
  134.     Trace(TEXT("Display specifier %s, LANGID %x"), W2T(pccgi->pObjectClass), pccgi->langid);
  135.     // When dealing with the local case lets ensure that we enable/disable the flags
  136.     // accordingly.
  137.     if ( !(pccgi->dwFlags & CLASSCACHE_DSAVAILABLE) && !ShowDirectoryUI() )
  138.     {
  139.         ExitGracefully(hr, HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT), "ShowDirectoryUI returned FALSE, and the CLASSCAHCE_DSAVAILABLE flag is not set");
  140.     }
  141.     
  142.     hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (LPVOID*)&pDsPathname);
  143.     FailGracefully(hr, "Failed to get the IADsPathname interface");
  144.     // check to see if we have a valid server config path
  145.     pszServerConfigPath = pccgi->pServerConfigPath;
  146.     if ( !pszServerConfigPath )
  147.     {
  148.         hr = _GetServerConfigPath(&pszServerConfigPath, pccgi);
  149.         FailGracefully(hr, "Failed to allocate server config path");
  150.     }
  151.     hr = _ComposeSpecifierPath(pccgi->pObjectClass, pccgi->langid, pszServerConfigPath, pDsPathname, &bstrDisplaySpecifier);
  152.     FailGracefully(hr, "Failed to retrieve the display specifier path");
  153.     // attempt to bind to the display specifier object, if we fail to find the object
  154.     // then try defaults.
  155.     Trace(TEXT("Calling GetObject on: %s"), W2T(bstrDisplaySpecifier));
  156.     hr = ADsOpenObject(bstrDisplaySpecifier, 
  157.                        pccgi->pUserName, pccgi->pPassword, 
  158.                        pccgi->dwFlags & CLASSCACHE_SIMPLEAUTHENTICATE ? 0:ADS_SECURE_AUTHENTICATION, 
  159.                        riid, ppvObject);
  160.     SysFreeString(bstrDisplaySpecifier);
  161.     if ( hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT) )
  162.     {
  163.         // Display specifier not found. Try the default specifier in the
  164.         // caller's locale. The default specifier is the catch-all for classes
  165.         // that don't have their own specifier.
  166.         hr = _ComposeSpecifierPath(DEFAULT_SPECIFIER, pccgi->langid, pszServerConfigPath, pDsPathname, &bstrDisplaySpecifier);
  167.         FailGracefully(hr, "Failed to retrieve the display specifier path");
  168.         Trace(TEXT("Calling GetObject on: %s"), W2T(bstrDisplaySpecifier));
  169.         hr = ADsOpenObject(bstrDisplaySpecifier, 
  170.                            pccgi->pUserName, pccgi->pPassword, 
  171.                            pccgi->dwFlags & CLASSCACHE_SIMPLEAUTHENTICATE ? 0:ADS_SECURE_AUTHENTICATION, 
  172.                            riid, ppvObject);
  173.         SysFreeString(bstrDisplaySpecifier);
  174.         if ((hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT)) && (pccgi->langid != DEFAULT_LANGUAGE))
  175.         {
  176.             // Now try the object's specifier in the default locale.
  177.             hr = _ComposeSpecifierPath(pccgi->pObjectClass, DEFAULT_LANGUAGE, pszServerConfigPath, pDsPathname, &bstrDisplaySpecifier);
  178.             FailGracefully(hr, "Failed to retrieve the display specifier path");
  179.             Trace(TEXT("Calling GetObject on: %s"), W2T(bstrDisplaySpecifier));
  180.             hr = ADsOpenObject(bstrDisplaySpecifier, 
  181.                                pccgi->pUserName, pccgi->pPassword, 
  182.                                pccgi->dwFlags & CLASSCACHE_SIMPLEAUTHENTICATE ? 0:ADS_SECURE_AUTHENTICATION, 
  183.                                riid, ppvObject);
  184.             SysFreeString(bstrDisplaySpecifier);
  185.             if (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
  186.             {
  187.                 // Finally try the default specifier in the default locale.
  188.                 hr = _ComposeSpecifierPath(DEFAULT_SPECIFIER, DEFAULT_LANGUAGE, pszServerConfigPath, pDsPathname, &bstrDisplaySpecifier);
  189.                 FailGracefully(hr, "Failed to retrieve the display specifier path");
  190.                 Trace(TEXT("Calling GetObject on: %s"), W2T(bstrDisplaySpecifier));
  191.                 hr = ADsOpenObject(bstrDisplaySpecifier, 
  192.                                    pccgi->pUserName, pccgi->pPassword, 
  193.                                    pccgi->dwFlags & CLASSCACHE_SIMPLEAUTHENTICATE ? 0:ADS_SECURE_AUTHENTICATION, 
  194.                                    riid, ppvObject);
  195.                 SysFreeString(bstrDisplaySpecifier);
  196.             }
  197.         }
  198.     }
  199.     FailGracefully(hr, "Failed in ADsOpenObject for display specifier");
  200.     // hr = S_OK;                   // success
  201. exit_gracefully:
  202.     DoRelease(pDsPathname);
  203.     if ( !pccgi->pServerConfigPath )
  204.         LocalFreeStringW(&pszServerConfigPath);
  205.     TraceLeaveResult(hr);
  206. }
  207. /*-----------------------------------------------------------------------------
  208. / GetServerAndCredentails
  209. / -----------------------
  210. /   Read the server and credentails information from the IDataObject.
  211. /
  212. / In:
  213. /   pccgi -> CLASSCACHEGETINFO structure to be filled
  214. /
  215. / Out:
  216. /   HRESULT
  217. /----------------------------------------------------------------------------*/
  218. HRESULT GetServerAndCredentails(CLASSCACHEGETINFO *pccgi)
  219. {
  220.     HRESULT hres;
  221.     STGMEDIUM medium = { TYMED_NULL };
  222.     FORMATETC fmte = {g_cfDsDispSpecOptions, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  223.     USES_CONVERSION;
  224.     TraceEnter(TRACE_UI, "GetServerAndCredentails");
  225.     // we can only get this information if we have a pDataObject to call.
  226.     pccgi->pUserName = NULL;
  227.     pccgi->pPassword = NULL;
  228.     pccgi->pServer = NULL;
  229.     pccgi->pServerConfigPath = NULL;
  230.     if ( pccgi->pDataObject )
  231.     {
  232.         if ( SUCCEEDED(pccgi->pDataObject->GetData(&fmte, &medium)) )
  233.         {
  234.             DSDISPLAYSPECOPTIONS *pdso = (DSDISPLAYSPECOPTIONS*)medium.hGlobal;          
  235.             TraceAssert(pdso);
  236.             // mirror the flags into the CCGI structure
  237.             if ( pdso->dwFlags & DSDSOF_SIMPLEAUTHENTICATE )
  238.             {
  239.                 TraceMsg("Setting simple authentication");
  240.                 pccgi->dwFlags |= CLASSCACHE_SIMPLEAUTHENTICATE;
  241.             }
  242.             if ( pdso->dwFlags & DSDSOF_DSAVAILABLE )
  243.             {
  244.                 TraceMsg("Setting 'DS is available' flags");
  245.                 pccgi->dwFlags |= CLASSCACHE_DSAVAILABLE;
  246.             }
  247.             // if we have credentail information that should be copied then lets grab
  248.             // that and put it into the structure.
  249.             if ( pdso->dwFlags & DSDSOF_HASUSERANDSERVERINFO )
  250.             {
  251.                 if ( pdso->offsetUserName )
  252.                 {
  253.                     LPCWSTR pszUserName = (LPCWSTR)ByteOffset(pdso, pdso->offsetUserName);
  254.                     hres = LocalAllocStringW(&pccgi->pUserName, pszUserName);
  255.                     FailGracefully(hres, "Failed to copy the user name");
  256.                 }
  257.                 if ( pdso->offsetPassword )
  258.                 {
  259.                     LPCWSTR pszPassword = (LPCWSTR)ByteOffset(pdso, pdso->offsetPassword);
  260.                     hres = LocalAllocStringW(&pccgi->pPassword, pszPassword);
  261.                     FailGracefully(hres, "Failed to copy the password");
  262.                 }
  263.                 if ( pdso->offsetServer )
  264.                 {
  265.                     LPCWSTR pszServer = (LPCWSTR)ByteOffset(pdso, pdso->offsetServer);
  266.                     hres = LocalAllocStringW(&pccgi->pServer, pszServer);
  267.                     FailGracefully(hres, "Failed to copy the server");
  268.                 }
  269.                 if ( pdso->offsetServerConfigPath )
  270.                 {
  271.                     LPCWSTR pszServerConfigPath = (LPCWSTR)ByteOffset(pdso, pdso->offsetServerConfigPath);
  272.                     hres = LocalAllocStringW(&pccgi->pServerConfigPath, pszServerConfigPath);
  273.                     FailGracefully(hres, "Failed to copy the server config path");
  274.                 }
  275.             }
  276.         }
  277.     }
  278.     hres = S_OK;            // success
  279. exit_gracefully:
  280.     
  281.     if ( FAILED(hres) )
  282.     {
  283.         LocalFreeStringW(&pccgi->pUserName);
  284.         LocalFreeStringW(&pccgi->pPassword);
  285.         LocalFreeStringW(&pccgi->pServer);
  286.         LocalFreeStringW(&pccgi->pServerConfigPath);
  287.     }
  288.     ReleaseStgMedium(&medium);
  289.     
  290.     TraceLeaveResult(hres);
  291. }
  292. /*-----------------------------------------------------------------------------
  293. / GetAttributePrefix
  294. / ------------------
  295. /   Get the attribtue prefix we must use to pick up information from the
  296. /   cache / DS.  This is part of the IDataObject we are given, if not then
  297. /   we default to shell behaviour.
  298. /
  299. / In:
  300. /   ppAttributePrefix -> receives the attribute prefix string
  301. /   pDataObject = IDataObject to query against.
  302. /
  303. / Out:
  304. /   HRESULT
  305. /----------------------------------------------------------------------------*/
  306. HRESULT GetAttributePrefix(LPWSTR* ppAttributePrefix, IDataObject* pDataObject)
  307. {   
  308.     HRESULT hr;
  309.     STGMEDIUM medium = { TYMED_NULL };
  310.     FORMATETC fmte = {g_cfDsDispSpecOptions, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  311.     PDSDISPLAYSPECOPTIONS pOptions;
  312.     LPWSTR pPrefix = NULL;
  313.     USES_CONVERSION;
  314.     TraceEnter(TRACE_UI, "GetAttributePrefix");
  315.     if ( (SUCCEEDED(pDataObject->GetData(&fmte, &medium))) && (medium.tymed == TYMED_HGLOBAL) )
  316.     {
  317.         pOptions = (PDSDISPLAYSPECOPTIONS)medium.hGlobal;
  318.         pPrefix = (LPWSTR)ByteOffset(pOptions, pOptions->offsetAttribPrefix);
  319.         Trace(TEXT("pOptions->dwSize %d"), pOptions->dwSize);
  320.         Trace(TEXT("pOptions->dwFlags %08x"), pOptions->dwFlags);
  321.         Trace(TEXT("pOptions->offsetAttribPrefix %d (%s)"), pOptions->offsetAttribPrefix, W2T(pPrefix));
  322.         hr = LocalAllocStringW(ppAttributePrefix, pPrefix);
  323.         FailGracefully(hr, "Failed when copying prefix from StgMedium");
  324.     }
  325.     else
  326.     {
  327.         hr = LocalAllocStringW(ppAttributePrefix, DS_PROP_SHELL_PREFIX);
  328.         FailGracefully(hr, "Failed when defaulting the attribute prefix string");
  329.     }
  330.     Trace(TEXT("Resulting prefix: %s"), W2T(*ppAttributePrefix));
  331.     // hr = S_OK;                       // success
  332.        
  333. exit_gracefully:
  334.     ReleaseStgMedium(&medium);
  335.     TraceLeaveResult(hr);
  336. }
  337. /*-----------------------------------------------------------------------------
  338. / GetRootDSE
  339. / ----------
  340. /   Get the RootDSE given an CLASSCACHEGETINFO structure
  341. /
  342. / In:
  343. /   pccgi -> CLASSCACHEGETINFO structure.
  344. /   pads -> IADs* interface
  345. /
  346. / Out:
  347.     HRESULT
  348. /----------------------------------------------------------------------------*/
  349. HRESULT GetRootDSE(LPCWSTR pszUserName, LPCWSTR pszPassword, LPCWSTR pszServer, BOOL fNotSecure, IADs **ppads)
  350. {
  351.     HRESULT hres;
  352.     LPWSTR pszRootDSE = L"/RootDSE";
  353.     WCHAR szBuffer[MAX_PATH];
  354.     USES_CONVERSION;
  355.     TraceEnter(TRACE_CACHE, "GetRootDSE");
  356.     StrCpyW(szBuffer, L"LDAP://");
  357.     if ( pszServer )
  358.         StrCatW(szBuffer, pszServer);
  359.     else
  360.         pszRootDSE++;
  361.     StrCatW(szBuffer, pszRootDSE);
  362.     Trace(TEXT("RootDSE path is: %s"), W2T(szBuffer));
  363.     hres = ADsOpenObject(szBuffer, 
  364.                          (LPWSTR)pszUserName, (LPWSTR)pszPassword, 
  365.                          fNotSecure ? 0:ADS_SECURE_AUTHENTICATION, 
  366.                          IID_IADs, (void **)ppads);
  367.     
  368.     TraceLeaveResult(hres);
  369. }
  370. HRESULT GetCacheInfoRootDSE(LPCLASSCACHEGETINFO pccgi, IADs **ppads)
  371. {
  372.     return GetRootDSE(pccgi->pUserName, pccgi->pPassword, pccgi->pServer,
  373.                       (pccgi->dwFlags & CLASSCACHE_SIMPLEAUTHENTICATE),
  374.                       ppads);
  375. }