Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1305 lines
33 KiB

  1. //***********************************************************************************
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: UrlAgent.cpp
  6. //
  7. // Description:
  8. //
  9. // This class encapsulates the logic about where to get the right logic
  10. // for various purposes, including the case of running WU in corporate
  11. // environments.
  12. //
  13. // An object based on this class should be created first, then call
  14. // GetOriginalIdentServer() function to get where to download ident,
  15. // then download ident, then call PopulateData() function to read
  16. // all URL related data.
  17. //
  18. // Created by:
  19. // Charles Ma
  20. //
  21. // Date Creatd:
  22. // Oct 19, 2001
  23. //
  24. //***********************************************************************************
  25. #include <windows.h>
  26. #include <iucommon.h>
  27. #include <osdet.h>
  28. #include <logging.h>
  29. #include <fileUtil.h>
  30. #include <memutil.h>
  31. #include <shlwapi.h>
  32. #include <UrlAgent.h>
  33. #include <MISTSAFE.h>
  34. #include <wusafefn.h>
  35. #ifndef INTERNET_MAX_URL_LENGTH
  36. #define INTERNET_MAX_URL_LENGTH 2200
  37. #endif
  38. //
  39. // starting size of url array
  40. //
  41. const int C_INIT_URL_ARRAY_SIZE = 4; // for time being,we only have this many clients
  42. //
  43. // define the default original ident url
  44. //
  45. const TCHAR C_DEFAULT_IDENT_URL[] = _T("http://windowsupdate.microsoft.com/v4/");
  46. //
  47. // define reg keys to get ident server override for debugging
  48. //
  49. const TCHAR REGKEY_IDENT_SERV[] = _T("IdentServer");
  50. const TCHAR REGKEY_IUCTL[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\IUControl");
  51. const TCHAR REGVAL_ISBETA[] = _T("IsBeta");
  52. //
  53. // define reg keys used by related policies
  54. //
  55. //
  56. // define policy location
  57. //
  58. const TCHAR REGKEY_CORPWU_POLICY[] = _T("Software\\Policies\\Microsoft\\Windows\\WindowsUpdate");
  59. //
  60. // define ident and selfupdate server, and ping server
  61. //
  62. const TCHAR REGKEY_CORPWU_WUSERVER[] = _T("WUServer");
  63. const TCHAR REGKEY_CORPWU_PINGSERVER[] = _T("WUStatusServer");
  64. //
  65. // define the boolean (DWORD) value under each client
  66. //
  67. const TCHAR REGKEY_USEWUSERVER[] = _T("UseWUServer");
  68. //
  69. // define ident data
  70. //
  71. const TCHAR IDENT_SECTION_PINGSERVER[] = _T("IUPingServer"); // section name in ident
  72. const TCHAR IDENT_ENTRY_SERVERURL[] = _T("ServerUrl"); // ping server entry name
  73. const TCHAR IDENT_SECITON_IUSERVERCACHE[] = _T("IUServerCache"); // query server section
  74. const TCHAR IDENT_ENTRY_QUERYSEVERINDEX[] = _T("QueryServerIndex"); // suffix of client entry
  75. const TCHAR IDENT_ENTRY_BETAQUERYSERVERINDEX[] = _T("BetaQueryServerIndex"); // for beta server
  76. const TCHAR IDENT_ENTRY_SERVER[] = _T("Server"); // prefix of server entry
  77. // main IU selfupdate keys
  78. const TCHAR IDENT_IUSELFUPDATE[] = _T("IUSelfUpdate");
  79. const TCHAR IDENT_IUBETASELFUPDATE[] = _T("IUBetaSelfUpdate");
  80. const TCHAR IDENT_STRUCTUREKEY[] = _T("StructureKey");
  81. // IU selfupdate architecture flags
  82. const TCHAR IDENT_ARCH[] = _T("ARCH");
  83. const TCHAR IDENT_OS[] = _T("OS");
  84. const TCHAR IDENT_LOCALE[] = _T("LOCALE");
  85. const TCHAR IDENT_CHARTYPE[] = _T("CHARTYPE");
  86. // IU selfupdate sections
  87. const TCHAR IDENT_IUARCH[] = _T("IUArch");
  88. const TCHAR IDENT_IUOS[] = _T("IUOS");
  89. const TCHAR IDENT_IULOCALE[] = _T("IULocale");
  90. const TCHAR IDENT_IUCHARTYPE[] = _T("IUCharType");
  91. // IU selfupdate arch keys
  92. const TCHAR IDENT_X86[] = _T("x86");
  93. const TCHAR IDENT_IA64[] = _T("ia64");
  94. // IU selfupdate chartypes
  95. const TCHAR IDENT_ANSI[] = _T("ansi");
  96. const TCHAR IDENT_UNICODE[] = _T("unicode");
  97. const TCHAR SLASHENGINECAB[] = _T("/iuengine.cab");
  98. // AU specific:
  99. const TCHAR CLIENT_AU[] = _T("AU");
  100. const TCHAR CLIENT_AU_DRIVER[] = _T("AUDriver");
  101. // *********************************************************************
  102. //
  103. // begin of class implementation
  104. //
  105. // *********************************************************************
  106. CUrlAgent::CUrlAgent(void)
  107. : m_fPopulated(FALSE),
  108. m_pszOrigIdentUrl(NULL),
  109. m_pszInternetPingUrl(NULL),
  110. m_pszIntranetPingUrl(NULL),
  111. m_pszWUServer(NULL),
  112. m_ArrayUrls(NULL),
  113. m_nArrayUrlCount(0),
  114. m_nArraySize(0),
  115. m_nOrigIdentUrlBufSize(0),
  116. m_fIdentFromPolicy(FALSE)
  117. {
  118. HKEY hKey = NULL;
  119. DWORD dwRegCheckResult = 0;
  120. DWORD dwSize = 0, dwType, dwValue;
  121. LOG_Block("CUrlAgent::CUrlAgent()");
  122. //
  123. // always try to get original ident server url
  124. //
  125. m_hProcHeap = GetProcessHeap();
  126. if (NULL != m_hProcHeap)
  127. {
  128. m_nOrigIdentUrlBufSize = __max(
  129. MAX_PATH, // reg based?
  130. sizeof(C_DEFAULT_IDENT_URL)/sizeof(TCHAR)); // default
  131. m_pszOrigIdentUrl = (LPTSTR)
  132. HeapAlloc(
  133. m_hProcHeap, // allocate from process heap
  134. HEAP_ZERO_MEMORY,
  135. sizeof(TCHAR) * m_nOrigIdentUrlBufSize);
  136. if (NULL != m_pszOrigIdentUrl)
  137. {
  138. //
  139. // first, check to see if there is debug override
  140. //
  141. dwRegCheckResult= RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_IUCTL, 0, KEY_READ, &hKey);
  142. if (ERROR_SUCCESS == dwRegCheckResult)
  143. {
  144. dwSize = sizeof(TCHAR) * m_nOrigIdentUrlBufSize;
  145. dwRegCheckResult = RegQueryValueEx(hKey, REGKEY_IDENT_SERV, NULL, &dwType, (LPBYTE)m_pszOrigIdentUrl, &dwSize);
  146. if (ERROR_SUCCESS == dwRegCheckResult)
  147. {
  148. if (REG_SZ == dwType)
  149. {
  150. LOG_Internet(_T("Found debugging Ident-URL %s"), m_pszOrigIdentUrl);
  151. }
  152. else
  153. {
  154. dwRegCheckResult = ERROR_SUCCESS + 1; // any error number will do
  155. }
  156. }
  157. RegCloseKey(hKey);
  158. }
  159. if (ERROR_SUCCESS != dwRegCheckResult)
  160. {
  161. //
  162. // if there is no debug override, check to see if there is policy define
  163. // ident server for corporate case
  164. //
  165. dwRegCheckResult= RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_CORPWU_POLICY, 0, KEY_READ, &hKey);
  166. if (ERROR_SUCCESS == dwRegCheckResult)
  167. {
  168. dwSize = sizeof(TCHAR) * m_nOrigIdentUrlBufSize;
  169. dwRegCheckResult = RegQueryValueEx(hKey, REGKEY_CORPWU_WUSERVER, NULL, &dwType, (LPBYTE)m_pszOrigIdentUrl, &dwSize);
  170. if (ERROR_SUCCESS == dwRegCheckResult && REG_SZ == dwType)
  171. {
  172. m_fIdentFromPolicy = TRUE;
  173. //
  174. // for any client that its name appear here as a subkey, and
  175. // has a value "UseWUServer" set to 1 under the subkey, then
  176. // this will also be the base url used to construct the query url
  177. // for that client
  178. //
  179. m_pszWUServer = m_pszOrigIdentUrl;
  180. LOG_Internet(_T("Found corp Ident-URL %s"), m_pszOrigIdentUrl);
  181. //
  182. // since we found wu server, for any client uses this url,
  183. // we can also have an optional ping server
  184. //
  185. m_pszIntranetPingUrl = (LPTSTR) HeapAlloc(
  186. m_hProcHeap,
  187. HEAP_ZERO_MEMORY,
  188. sizeof(TCHAR) * m_nOrigIdentUrlBufSize);
  189. dwSize = sizeof(TCHAR) * m_nOrigIdentUrlBufSize;
  190. if (NULL != m_pszIntranetPingUrl)
  191. {
  192. if (ERROR_SUCCESS != (dwRegCheckResult = RegQueryValueEx(hKey, REGKEY_CORPWU_PINGSERVER, NULL, &dwType, (LPBYTE)m_pszIntranetPingUrl, &dwSize)) || REG_SZ != dwType)
  193. {
  194. StringCchCopyEx(m_pszIntranetPingUrl,m_nOrigIdentUrlBufSize,m_pszOrigIdentUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
  195. dwRegCheckResult = ERROR_SUCCESS;
  196. }
  197. }
  198. }
  199. else
  200. {
  201. dwRegCheckResult = ERROR_SUCCESS + 1; // any error number will do
  202. }
  203. RegCloseKey(hKey);
  204. }
  205. }
  206. if (ERROR_SUCCESS != dwRegCheckResult)
  207. {
  208. //
  209. // not debugging , neither corporate policy found
  210. //
  211. StringCchCopyEx(m_pszOrigIdentUrl,m_nOrigIdentUrlBufSize,C_DEFAULT_IDENT_URL,NULL,NULL,MISTSAFE_STRING_FLAGS);
  212. LOG_Internet(_T("Use default ident URL %s"), m_pszOrigIdentUrl);
  213. }
  214. }
  215. }
  216. else
  217. {
  218. LOG_ErrorMsg(GetLastError());
  219. }
  220. //
  221. // Check IUControl Reg Key for Beta Mode
  222. //
  223. m_fIsBetaMode = FALSE;
  224. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_IUCTL, &hKey))
  225. {
  226. dwValue = 0;
  227. dwSize = sizeof(dwValue);
  228. if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGVAL_ISBETA, NULL, NULL, (LPBYTE)&dwValue, &dwSize))
  229. {
  230. m_fIsBetaMode = (1 == dwValue);
  231. }
  232. RegCloseKey(hKey);
  233. }
  234. }
  235. CUrlAgent::~CUrlAgent(void)
  236. {
  237. DesertData();
  238. SafeHeapFree(m_pszOrigIdentUrl);
  239. SafeHeapFree(m_pszIntranetPingUrl);
  240. }
  241. //------------------------------------------------------------------------
  242. //
  243. // this function should be called after you downloaded ident, and get
  244. // a fresh copy of ident text file from the cab, after verifying cab was
  245. // signed properly.
  246. //
  247. // this function reads data from ident and registry
  248. //
  249. //------------------------------------------------------------------------
  250. HRESULT CUrlAgent::PopulateData(void)
  251. {
  252. LOG_Block("CUrlAgent::PopuldateData");
  253. if (m_fPopulated)
  254. return S_OK;
  255. HRESULT hr = S_OK;
  256. LPTSTR pszBuffer = NULL;
  257. LPTSTR pszCurrentKey = NULL; // ptr only, no memory alloc
  258. LPTSTR pszUrlBuffer = NULL;
  259. LPCTSTR pcszSuffix = (m_fIsBetaMode ? IDENT_ENTRY_BETAQUERYSERVERINDEX : IDENT_ENTRY_QUERYSEVERINDEX);
  260. HKEY hKey = NULL;
  261. DWORD dwRegCheckResult = 0;
  262. DWORD dwSize = 0,
  263. dwType,
  264. dwValue = 0;
  265. int iLen = 0, iLenSuffix = 0;
  266. TCHAR szIdentBuffer[MAX_PATH + 1];
  267. TCHAR szIdentFile[MAX_PATH + 1];
  268. if (NULL == m_hProcHeap)
  269. {
  270. return E_FAIL;
  271. }
  272. pszUrlBuffer = (LPTSTR) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR)*INTERNET_MAX_URL_LENGTH);
  273. CleanUpFailedAllocSetHrMsg(pszUrlBuffer);
  274. GetIndustryUpdateDirectory(szIdentBuffer);
  275. hr=PathCchCombine(szIdentFile,ARRAYSIZE(szIdentFile), szIdentBuffer, IDENTTXT);
  276. if(FAILED(hr))
  277. {
  278. SafeHeapFree(pszUrlBuffer);
  279. LOG_ErrorMsg(hr);
  280. return hr;
  281. }
  282. //
  283. // make sure we release all data, if any
  284. //
  285. DesertData();
  286. //
  287. // before populate per-client array, we want to find out inter net ping server
  288. //
  289. m_pszInternetPingUrl = RetrieveIdentStrAlloc(
  290. IDENT_SECTION_PINGSERVER,
  291. IDENT_ENTRY_SERVERURL,
  292. NULL,
  293. szIdentFile);
  294. //
  295. // allocate array of pointers for storing each server node
  296. //
  297. m_ArrayUrls = (PServerPerClient) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, C_INIT_URL_ARRAY_SIZE * sizeof(ServerPerClient));
  298. CleanUpFailedAllocSetHrMsg(m_ArrayUrls);
  299. m_nArraySize = C_INIT_URL_ARRAY_SIZE; // now array is this big
  300. //
  301. // try to read data from policy first, if WU server exists
  302. //
  303. if (NULL != m_pszWUServer &&
  304. ERROR_SUCCESS == (dwRegCheckResult= RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_CORPWU_POLICY, 0, KEY_READ, &hKey)))
  305. {
  306. //
  307. // the way we find a client name under WU policy is, to open this key, see if it has a value
  308. // called "UseWUServer"
  309. //
  310. DWORD dwSubKeyIndex = 0;
  311. TCHAR szKeyName[32];
  312. while (TRUE)
  313. {
  314. DWORD dwKeyBufLen = ARRAYSIZE(szKeyName);
  315. dwRegCheckResult = RegEnumKeyEx(
  316. hKey, // handle to key to enumerate
  317. dwSubKeyIndex, // subkey index
  318. szKeyName, // subkey name
  319. &dwKeyBufLen, // size of subkey buffer
  320. NULL, // reserved
  321. NULL, // class string buffer
  322. NULL, // size of class string buffer
  323. NULL // last write time
  324. );
  325. if (ERROR_SUCCESS == dwRegCheckResult)
  326. {
  327. //
  328. // try to open this key
  329. //
  330. HKEY hKeyClient = NULL;
  331. dwRegCheckResult= RegOpenKeyEx(hKey, szKeyName, 0, KEY_READ, &hKeyClient);
  332. if (ERROR_SUCCESS == dwRegCheckResult)
  333. {
  334. //
  335. // try to see if it has a value called UseWUServer
  336. //
  337. dwValue = 0;
  338. dwType = REG_DWORD;
  339. dwSize = sizeof(dwValue);
  340. dwRegCheckResult = RegQueryValueEx(hKeyClient, REGKEY_USEWUSERVER, NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
  341. if (ERROR_SUCCESS == dwRegCheckResult && REG_DWORD == dwType && 0x1 == dwValue)
  342. {
  343. LOG_Internet(_T("Found client %s\\UseWUServer=1"), szKeyName);
  344. //
  345. // we want to add this client to our url array
  346. //
  347. CleanUpIfFailedAndSetHrMsg(ExpandArrayIfNeeded());
  348. m_ArrayUrls[m_nArrayUrlCount].pszClientName = (LPTSTR)HeapAllocCopy(szKeyName, sizeof(TCHAR) * (lstrlen(szKeyName) + 1));
  349. CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszClientName);
  350. m_ArrayUrls[m_nArrayUrlCount].pszQueryServer = (LPTSTR) HeapAllocCopy(m_pszOrigIdentUrl, sizeof(TCHAR) * (lstrlen(m_pszOrigIdentUrl) + 1));
  351. CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszQueryServer);
  352. m_ArrayUrls[m_nArrayUrlCount].fInternalServer = TRUE;
  353. m_nArrayUrlCount++; // increase counter by 1
  354. //
  355. // BUG 507500 AUDriver Policy -
  356. // map calls with the "AUDriver client to "AU" when checking the policy for usewuserver
  357. //
  358. if (CSTR_EQUAL == WUCompareStringI(szKeyName, CLIENT_AU))
  359. {
  360. //
  361. // we want to add client "AUDriver" to our url array
  362. //
  363. CleanUpIfFailedAndSetHrMsg(ExpandArrayIfNeeded());
  364. m_ArrayUrls[m_nArrayUrlCount].pszClientName = (LPTSTR)HeapAllocCopy((LPTSTR)CLIENT_AU_DRIVER, sizeof(TCHAR) * (lstrlen(CLIENT_AU_DRIVER) + 1));
  365. CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszClientName);
  366. m_ArrayUrls[m_nArrayUrlCount].pszQueryServer = (LPTSTR) HeapAllocCopy(m_pszOrigIdentUrl, sizeof(TCHAR) * (lstrlen(m_pszOrigIdentUrl) + 1));
  367. CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszQueryServer);
  368. m_ArrayUrls[m_nArrayUrlCount].fInternalServer = TRUE;
  369. m_nArrayUrlCount++; // increase counter by 1
  370. }
  371. }
  372. }
  373. RegCloseKey(hKeyClient);
  374. }
  375. else
  376. {
  377. if (ERROR_NO_MORE_ITEMS == dwRegCheckResult)
  378. {
  379. //
  380. // there is no more sub key to loop through. get out here
  381. //
  382. break;
  383. }
  384. //
  385. // otherwise, we try next sub key
  386. //
  387. }
  388. dwSubKeyIndex++; // try next sub key
  389. }
  390. RegCloseKey(hKey); // done with policy reg
  391. }
  392. //
  393. // now we should continue to work on internet case
  394. // that is, to retrieve query server(s) from ident
  395. //
  396. dwSize = MAX_PATH;
  397. pszBuffer = (LPTSTR) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, dwSize * sizeof(TCHAR));
  398. while (NULL != pszBuffer &&
  399. GetPrivateProfileString(
  400. IDENT_SECITON_IUSERVERCACHE,
  401. NULL,
  402. _T(""),
  403. pszBuffer,
  404. dwSize,
  405. szIdentFile) == dwSize-2)
  406. {
  407. //
  408. // buffer too small?
  409. //
  410. dwSize *= 2;
  411. LPTSTR pszTemp = (LPTSTR) HeapReAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, pszBuffer, dwSize * sizeof(TCHAR));
  412. if (NULL != pszTemp)
  413. {
  414. pszBuffer = pszTemp;
  415. }
  416. else
  417. {
  418. //
  419. // HeapReAlloc failed, bail from while with origional allocation freed
  420. //
  421. SafeHeapFree(pszBuffer);
  422. }
  423. }
  424. CleanUpFailedAllocSetHrMsg(pszBuffer);
  425. //
  426. // loop through each key
  427. //
  428. pszCurrentKey = pszBuffer;
  429. while ('\0' != *pszCurrentKey)
  430. {
  431. //
  432. // for the current key, we first try to see if its index key or server key
  433. // if it's not index key, skip it
  434. //
  435. iLen = lstrlen(pszCurrentKey);
  436. iLenSuffix = lstrlen(pcszSuffix);
  437. if ((iLen > iLenSuffix) && (0 == StrCmpI((pszCurrentKey + (iLen - iLenSuffix)), pcszSuffix)))
  438. {
  439. TCHAR szClient[MAX_PATH]; // isn't MAX_PATH big enough?
  440. int nIndex = 0;
  441. BOOL fExist = FALSE;
  442. //
  443. // retrieve server index from this key
  444. //
  445. nIndex = GetPrivateProfileInt(IDENT_SECITON_IUSERVERCACHE, pszCurrentKey, 0, szIdentFile);
  446. //
  447. // no use of szIdentBuffer, so utilize it here
  448. //
  449. CleanUpIfFailedAndSetHrMsg(StringCchPrintfEx(szIdentBuffer,ARRAYSIZE(szIdentBuffer),NULL,NULL,MISTSAFE_STRING_FLAGS,_T("%s%d"), IDENT_ENTRY_SERVER, nIndex));
  450. GetPrivateProfileString(
  451. IDENT_SECITON_IUSERVERCACHE,
  452. szIdentBuffer, // use current str as key
  453. _T(""),
  454. pszUrlBuffer,
  455. INTERNET_MAX_URL_LENGTH,
  456. szIdentFile);
  457. if ('0' != *pszUrlBuffer)
  458. {
  459. //
  460. // this is an index key!
  461. // try to extract client name from this key
  462. //
  463. CleanUpIfFailedAndSetHrMsg(StringCchCopyNEx(szClient,ARRAYSIZE(szClient),pszCurrentKey,iLen - iLenSuffix,NULL,NULL,MISTSAFE_STRING_FLAGS));
  464. //
  465. // find out if this client is already defined in policy and therefore
  466. // arleady got data in the url array
  467. //
  468. for (int i = 0; i < m_nArrayUrlCount && !fExist; i++)
  469. {
  470. fExist= (StrCmpI(m_ArrayUrls[i].pszClientName, szClient) == 0);
  471. }
  472. if (!fExist)
  473. {
  474. CleanUpIfFailedAndSetHrMsg(ExpandArrayIfNeeded());
  475. m_ArrayUrls[m_nArrayUrlCount].pszClientName = (LPTSTR)HeapAllocCopy(szClient, sizeof(TCHAR) * (lstrlen(szClient) + 1));
  476. CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszClientName);
  477. m_ArrayUrls[m_nArrayUrlCount].pszQueryServer = (LPTSTR) HeapAllocCopy(pszUrlBuffer, sizeof(TCHAR) * (lstrlen(pszUrlBuffer) + 1));
  478. CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszQueryServer);
  479. m_ArrayUrls[m_nArrayUrlCount].fInternalServer = FALSE;
  480. m_nArrayUrlCount++; // increase counter by 1
  481. }
  482. else
  483. {
  484. //
  485. // this client is already defined in policy, we just need to append the QueryServer with the
  486. // rest of the url path defined in iuident
  487. //
  488. LPTSTR pszPath = NULL;
  489. //
  490. // find "//" in URL retrieved from iuident
  491. //
  492. if (NULL == (pszPath = StrStrI(pszUrlBuffer, _T("//"))))
  493. {
  494. // unexpected error
  495. hr = E_FAIL;
  496. LOG_ErrorMsg(hr);
  497. goto CleanUp;
  498. }
  499. else
  500. {
  501. //
  502. // find next "/" in URL retrieved from iuident
  503. //
  504. if (NULL != (pszPath = StrStrI(pszPath+2, _T("/"))))
  505. {
  506. DWORD dwLen = 0;
  507. LPTSTR pszTemp = NULL;
  508. //
  509. // remove trailing "/" in URL retrieved from policy
  510. //
  511. if (_T('/') == *(m_ArrayUrls[i-1].pszQueryServer + lstrlen(m_ArrayUrls[i-1].pszQueryServer) - 1))
  512. {
  513. dwLen = lstrlen(m_ArrayUrls[i-1].pszQueryServer) + lstrlen(pszPath);
  514. pszTemp = (LPTSTR)HeapReAlloc(GetProcessHeap(),
  515. HEAP_ZERO_MEMORY,
  516. m_ArrayUrls[i-1].pszQueryServer,
  517. sizeof(TCHAR) * dwLen);
  518. CleanUpFailedAllocSetHrMsg(pszTemp);
  519. m_ArrayUrls[i-1].pszQueryServer = pszTemp;
  520. hr=StringCchCatEx(m_ArrayUrls[i-1].pszQueryServer,dwLen,pszPath + 1,NULL,NULL,MISTSAFE_STRING_FLAGS);
  521. if(FAILED(hr))
  522. {
  523. LOG_ErrorMsg(hr);
  524. SafeHeapFree(pszTemp);
  525. m_ArrayUrls[i-1].pszQueryServer=NULL;
  526. }
  527. }
  528. else
  529. {
  530. dwLen = lstrlen(m_ArrayUrls[i-1].pszQueryServer) + lstrlen(pszPath) + 1;
  531. pszTemp = (LPTSTR)HeapReAlloc(GetProcessHeap(),
  532. HEAP_ZERO_MEMORY,
  533. m_ArrayUrls[i-1].pszQueryServer,
  534. sizeof(TCHAR) * dwLen);
  535. CleanUpFailedAllocSetHrMsg(pszTemp);
  536. m_ArrayUrls[i-1].pszQueryServer = pszTemp;
  537. hr=StringCchCatEx(m_ArrayUrls[i-1].pszQueryServer,dwLen,pszPath,NULL,NULL,MISTSAFE_STRING_FLAGS);
  538. if(FAILED(hr))
  539. {
  540. LOG_ErrorMsg(hr);
  541. SafeHeapFree(pszTemp);
  542. m_ArrayUrls[i-1].pszQueryServer=NULL;
  543. }
  544. }
  545. }
  546. }
  547. }
  548. }
  549. }
  550. //
  551. // move to next string
  552. //
  553. pszCurrentKey += lstrlen(pszCurrentKey) + 1;
  554. }
  555. CleanUp:
  556. if (FAILED(hr))
  557. {
  558. //
  559. // clean up half-way populated data
  560. //
  561. DesertData();
  562. }
  563. else
  564. {
  565. m_fPopulated = TRUE;
  566. }
  567. SafeHeapFree(pszBuffer);
  568. SafeHeapFree(pszUrlBuffer);
  569. return hr;
  570. }
  571. //------------------------------------------------------------------------
  572. //
  573. // get the original ident server.
  574. // *** this API should be called before PopulateData() is called ***
  575. // *** this API should be called to retrieve the base URL where you download ident ***
  576. //
  577. //------------------------------------------------------------------------
  578. HRESULT CUrlAgent::GetOriginalIdentServer(
  579. LPTSTR lpsBuffer,
  580. int nBufferSize,
  581. BOOL* pfInternalServer /*= NULL*/)
  582. {
  583. HRESULT hr=S_OK;
  584. if (NULL == lpsBuffer)
  585. {
  586. return E_INVALIDARG;
  587. }
  588. nBufferSize/=sizeof(TCHAR);
  589. if (nBufferSize <= lstrlen(m_pszOrigIdentUrl))
  590. {
  591. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  592. }
  593. hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszOrigIdentUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
  594. if( FAILED(hr) )
  595. {
  596. return hr;
  597. }
  598. if (NULL != pfInternalServer)
  599. {
  600. *pfInternalServer = m_fIdentFromPolicy;
  601. }
  602. return S_OK;
  603. }
  604. //------------------------------------------------------------------------
  605. //
  606. // get the ping/status server
  607. // *** this API should be called after PopulateData() is called ***
  608. //
  609. //------------------------------------------------------------------------
  610. HRESULT CUrlAgent::GetLivePingServer(
  611. LPTSTR lpsBuffer,
  612. int nBufferSize)
  613. {
  614. HRESULT hr=S_OK;
  615. if (!m_fPopulated)
  616. {
  617. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  618. }
  619. if (NULL == lpsBuffer || 0 >= nBufferSize)
  620. {
  621. return E_INVALIDARG;
  622. }
  623. nBufferSize/=sizeof(TCHAR);
  624. if (NULL != m_pszInternetPingUrl &&
  625. _T('\0') != *m_pszInternetPingUrl)
  626. {
  627. if (nBufferSize <= lstrlen(m_pszInternetPingUrl))
  628. {
  629. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  630. }
  631. else
  632. {
  633. hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszInternetPingUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
  634. if(FAILED(hr))
  635. return hr;
  636. }
  637. }
  638. else
  639. {
  640. *lpsBuffer = _T('\0');
  641. }
  642. return S_OK;
  643. }
  644. // *** this API can be called before PopulateData() is called ***
  645. HRESULT CUrlAgent::GetCorpPingServer(
  646. LPTSTR lpsBuffer,
  647. int nBufferSize)
  648. {
  649. HRESULT hr=S_OK;
  650. if (NULL == m_pszIntranetPingUrl)
  651. {
  652. return (E_OUTOFMEMORY);
  653. }
  654. if (NULL == lpsBuffer || 0 >= nBufferSize)
  655. {
  656. return E_INVALIDARG;
  657. }
  658. nBufferSize/=sizeof(TCHAR);
  659. if (NULL != m_pszIntranetPingUrl &&
  660. _T('\0') != *m_pszIntranetPingUrl)
  661. {
  662. if (nBufferSize <= lstrlen(m_pszIntranetPingUrl))
  663. {
  664. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  665. }
  666. else
  667. {
  668. hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszIntranetPingUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
  669. if(FAILED(hr))
  670. return hr;
  671. }
  672. }
  673. else
  674. {
  675. *lpsBuffer = _T('\0');
  676. }
  677. return hr;
  678. }
  679. //------------------------------------------------------------------------
  680. //
  681. // get the query server. this is per client based
  682. // *** this API should be called after PopulateData() is called ***
  683. //
  684. //------------------------------------------------------------------------
  685. HRESULT CUrlAgent::GetQueryServer(
  686. LPCTSTR lpsClientName,
  687. LPTSTR lpsBuffer,
  688. int nBufferSize,
  689. BOOL* pfInternalServer /*= NULL*/)
  690. {
  691. HRESULT hr=S_OK;
  692. if (!m_fPopulated)
  693. {
  694. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  695. }
  696. if (NULL == lpsClientName || NULL == lpsBuffer)
  697. {
  698. return E_INVALIDARG;
  699. }
  700. nBufferSize/=sizeof(TCHAR);
  701. for (int i = 0; i < m_nArrayUrlCount; i++)
  702. {
  703. if (StrCmpI(m_ArrayUrls[i].pszClientName, lpsClientName) == 0)
  704. {
  705. if (nBufferSize <= lstrlen(m_ArrayUrls[i].pszQueryServer))
  706. {
  707. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  708. }
  709. else
  710. {
  711. hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_ArrayUrls[i].pszQueryServer,NULL,NULL,MISTSAFE_STRING_FLAGS);
  712. if(FAILED(hr)) return hr;
  713. if (NULL != pfInternalServer)
  714. {
  715. *pfInternalServer = m_ArrayUrls[i].fInternalServer;
  716. }
  717. }
  718. return S_OK;
  719. }
  720. }
  721. return ERROR_IU_QUERYSERVER_NOT_FOUND;
  722. }
  723. //------------------------------------------------------------------------
  724. //
  725. // tell if a particular client is controlled by policy in corporate
  726. // returns:
  727. // S_OK = TRUE
  728. // S_FALSE = FALSE
  729. // other = error, so don't know
  730. //
  731. //------------------------------------------------------------------------
  732. HRESULT CUrlAgent::IsClientSpecifiedByPolicy(
  733. LPCTSTR lpsClientName
  734. )
  735. {
  736. HRESULT hr=S_OK;
  737. if (!m_fPopulated)
  738. {
  739. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  740. }
  741. if (NULL == lpsClientName)
  742. {
  743. return E_INVALIDARG;
  744. }
  745. for (int i = 0; i < m_nArrayUrlCount; i++)
  746. {
  747. if (StrCmpI(m_ArrayUrls[i].pszClientName, lpsClientName) == 0)
  748. {
  749. return (m_ArrayUrls[i].fInternalServer) ? S_OK : S_FALSE;
  750. }
  751. }
  752. return S_FALSE;
  753. }
  754. HRESULT CUrlAgent::IsIdentFromPolicy()
  755. {
  756. return TRUE == m_fIdentFromPolicy ? S_OK : S_FALSE;
  757. }
  758. //------------------------------------------------------------------------
  759. //
  760. // private function, to clean up. called by destructor
  761. //
  762. //------------------------------------------------------------------------
  763. void CUrlAgent::DesertData(void)
  764. {
  765. LOG_Block("CUrlAgent::DesertData");
  766. if (NULL != m_ArrayUrls && m_nArrayUrlCount > 0)
  767. {
  768. for (int i = 0; i < m_nArrayUrlCount; i++)
  769. {
  770. SafeHeapFree(m_ArrayUrls[i].pszClientName);
  771. SafeHeapFree(m_ArrayUrls[i].pszQueryServer);
  772. }
  773. SafeHeapFree(m_ArrayUrls);
  774. m_nArrayUrlCount = 0;
  775. m_nArraySize = 0;
  776. }
  777. SafeHeapFree(m_pszInternetPingUrl);
  778. m_fPopulated = FALSE;
  779. }
  780. //------------------------------------------------------------------------
  781. //
  782. // private function, retrieve string from ident
  783. // allocated memory will be multiple of MAX_PATH long.
  784. //
  785. //------------------------------------------------------------------------
  786. LPTSTR CUrlAgent::RetrieveIdentStrAlloc(
  787. LPCTSTR pSection,
  788. LPCTSTR pEntry,
  789. LPDWORD lpdwSizeAllocated,
  790. LPCTSTR lpszIdentFile)
  791. {
  792. LPTSTR pBuffer = NULL;
  793. DWORD dwSize = MAX_PATH;
  794. DWORD dwRet = 0;
  795. TCHAR szIdentFile[MAX_PATH + 1];
  796. if (NULL == pSection || NULL == pEntry || NULL == lpszIdentFile)
  797. {
  798. return NULL;
  799. }
  800. //
  801. // try to allocate buffer first
  802. //
  803. while (TRUE)
  804. {
  805. pBuffer = (LPTSTR) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR) * dwSize);
  806. if (NULL == pBuffer)
  807. {
  808. break;
  809. }
  810. dwRet = GetPrivateProfileString(
  811. pSection,
  812. pEntry,
  813. _T(""),
  814. pBuffer,
  815. dwSize,
  816. lpszIdentFile);
  817. if (dwSize - 1 != dwRet)
  818. {
  819. if ('\0' == pBuffer)
  820. {
  821. //
  822. // no such data found from ident!
  823. //
  824. SafeHeapFree(pBuffer);
  825. }
  826. //
  827. // we are done!
  828. //
  829. break;
  830. }
  831. //
  832. // assume it's buffer too small
  833. //
  834. SafeHeapFree(pBuffer);
  835. dwSize += MAX_PATH; // increase by 255
  836. }
  837. if (NULL != lpdwSizeAllocated)
  838. {
  839. *lpdwSizeAllocated = dwSize;
  840. }
  841. return pBuffer;
  842. }
  843. //------------------------------------------------------------------------
  844. //
  845. // helper function
  846. // if there is no empty slot, double the size of url array
  847. //
  848. //------------------------------------------------------------------------
  849. HRESULT CUrlAgent::ExpandArrayIfNeeded(void)
  850. {
  851. HRESULT hr = S_OK;
  852. LOG_Block("CUrlAgent::ExpandArrayIfNeeded()");
  853. if (m_nArrayUrlCount >= m_nArraySize)
  854. {
  855. //
  856. // we have used up all data slots. need to expand array
  857. //
  858. m_nArraySize *= 2;
  859. PServerPerClient pNewArray = (PServerPerClient) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, m_nArraySize * sizeof(ServerPerClient));
  860. if (NULL == pNewArray)
  861. {
  862. m_nArraySize /= 2; // shrink it back
  863. SetHrMsgAndGotoCleanUp(E_OUTOFMEMORY);
  864. }
  865. //
  866. // copy old data to this new array
  867. //
  868. for (int i = 0; i < m_nArrayUrlCount; i++)
  869. {
  870. pNewArray[i] = m_ArrayUrls[i];
  871. }
  872. HeapFree(m_hProcHeap, 0, m_ArrayUrls);
  873. m_ArrayUrls = pNewArray;
  874. }
  875. CleanUp:
  876. return hr;
  877. }
  878. // *********************************************************************
  879. //
  880. // begin of derived class implementation
  881. //
  882. // *********************************************************************
  883. CIUUrlAgent::CIUUrlAgent()
  884. : m_fIUPopulated(FALSE),
  885. m_pszSelfUpdateUrl(NULL)
  886. {
  887. if (m_fIdentFromPolicy)
  888. {
  889. //
  890. // since we found wu server, set selfupdate url to it
  891. //
  892. m_pszSelfUpdateUrl = (LPTSTR) HeapAlloc(
  893. m_hProcHeap,
  894. HEAP_ZERO_MEMORY,
  895. sizeof(TCHAR) * m_nOrigIdentUrlBufSize);
  896. if (NULL != m_pszSelfUpdateUrl)
  897. {
  898. //No check is made for the return value since this is a constructor and failure codes cannot be returned
  899. StringCchCopyEx(m_pszSelfUpdateUrl,m_nOrigIdentUrlBufSize,m_pszOrigIdentUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
  900. }
  901. }
  902. }
  903. CIUUrlAgent::~CIUUrlAgent()
  904. {
  905. m_fIUPopulated = FALSE;
  906. SafeHeapFree(m_pszSelfUpdateUrl);
  907. }
  908. //------------------------------------------------------------------------
  909. //
  910. // PopulateData():
  911. // Do base class PopulateData() and then populate self-update url
  912. //
  913. //------------------------------------------------------------------------
  914. HRESULT CIUUrlAgent::PopulateData(void)
  915. {
  916. LOG_Block("CIUUrlAgent::PopulateData");
  917. if (m_fIUPopulated)
  918. return S_OK;
  919. HRESULT hr = ((CUrlAgent*)this)->PopulateData();
  920. if (FAILED(hr))
  921. return hr;
  922. //
  923. // we need to populate the self-update url from iuident if wu server is not present
  924. //
  925. if (!m_fIdentFromPolicy)
  926. {
  927. if (NULL == m_hProcHeap)
  928. {
  929. return E_FAIL;
  930. }
  931. TCHAR szBaseServerUrl[INTERNET_MAX_URL_LENGTH];
  932. TCHAR szSelfUpdateStructure[MAX_PATH];
  933. TCHAR szServerDirectory[MAX_PATH] = { '\0' };
  934. TCHAR szLocalPath[MAX_PATH];
  935. TCHAR szValue[MAX_PATH];
  936. LPTSTR pszWalk = NULL, pszDelim = NULL;
  937. TCHAR szIdentBuffer[MAX_PATH + 1];
  938. TCHAR szIdentFile[MAX_PATH + 1];
  939. GetIndustryUpdateDirectory(szIdentBuffer);
  940. hr=PathCchCombine(szIdentFile,ARRAYSIZE(szIdentFile),szIdentBuffer, IDENTTXT);
  941. if(FAILED(hr))
  942. {
  943. LOG_ErrorMsg(hr);
  944. return hr;
  945. }
  946. m_pszSelfUpdateUrl = (LPTSTR) HeapAlloc(
  947. m_hProcHeap,
  948. HEAP_ZERO_MEMORY,
  949. sizeof(TCHAR) * INTERNET_MAX_URL_LENGTH);
  950. CleanUpFailedAllocSetHrMsg(m_pszSelfUpdateUrl);
  951. // Get SelfUpdate Server URL
  952. GetPrivateProfileString(m_fIsBetaMode ? IDENT_IUBETASELFUPDATE : IDENT_IUSELFUPDATE,
  953. IDENT_ENTRY_SERVERURL,
  954. _T(""),
  955. szBaseServerUrl,
  956. ARRAYSIZE(szBaseServerUrl),
  957. szIdentFile);
  958. if ('\0' == szBaseServerUrl[0])
  959. {
  960. // no URL specified in iuident..
  961. LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND);
  962. hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND;
  963. goto CleanUp;
  964. }
  965. // Get SelfUpdate Structure Key
  966. // ARCH|LOCALE
  967. GetPrivateProfileString(m_fIsBetaMode ? IDENT_IUBETASELFUPDATE : IDENT_IUSELFUPDATE,
  968. IDENT_STRUCTUREKEY,
  969. _T(""),
  970. szSelfUpdateStructure,
  971. ARRAYSIZE(szSelfUpdateStructure),
  972. szIdentFile);
  973. if ('\0' == szSelfUpdateStructure[0])
  974. {
  975. // no SelfUpdate Structure in iudent
  976. LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND);
  977. hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND;
  978. goto CleanUp;
  979. }
  980. // Parse the SelfUpdate Structure Key for Value Names to Read
  981. // Initially we will only have an ARCH key..
  982. pszWalk = szSelfUpdateStructure;
  983. while (NULL != (pszDelim = StrChr(pszWalk, '|')))
  984. {
  985. *pszDelim = '\0';
  986. if (0 == StrCmpI(pszWalk, IDENT_ARCH))
  987. {
  988. #ifdef _IA64_
  989. GetPrivateProfileString(IDENT_IUARCH, IDENT_IA64, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile);
  990. #else
  991. GetPrivateProfileString(IDENT_IUARCH, IDENT_X86, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile);
  992. #endif
  993. }
  994. else if (0 == StrCmpI(pszWalk, IDENT_OS))
  995. {
  996. // Get the Current OS String
  997. GetIdentPlatformString(szLocalPath, ARRAYSIZE(szLocalPath));
  998. if ('\0' == szLocalPath[0])
  999. {
  1000. LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND);
  1001. hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND;
  1002. goto CleanUp;
  1003. }
  1004. GetPrivateProfileString(IDENT_IUOS, szLocalPath, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile);
  1005. }
  1006. else if (0 == StrCmpI(pszWalk, IDENT_LOCALE))
  1007. {
  1008. // Get the Current Locale String
  1009. GetIdentLocaleString(szLocalPath, ARRAYSIZE(szLocalPath));
  1010. if ('\0' == szLocalPath[0])
  1011. {
  1012. LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND);
  1013. hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND;
  1014. goto CleanUp;
  1015. }
  1016. GetPrivateProfileString(IDENT_IULOCALE, szLocalPath, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile);
  1017. }
  1018. else if (0 == StrCmpI(pszWalk, IDENT_CHARTYPE))
  1019. {
  1020. #ifdef UNICODE
  1021. GetPrivateProfileString(IDENT_IUCHARTYPE, IDENT_UNICODE, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile);
  1022. #else
  1023. GetPrivateProfileString(IDENT_IUCHARTYPE, IDENT_ANSI, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile);
  1024. #endif
  1025. }
  1026. else
  1027. {
  1028. LOG_Internet(_T("Found Unrecognized Token in SelfUpdate Structure String: Token was: %s"), pszWalk);
  1029. pszWalk += lstrlen(pszWalk) + 1; // skip the previous token, and go to the next one in the string.
  1030. *pszDelim = '|';
  1031. continue;
  1032. }
  1033. if ('\0' != szValue[0])
  1034. {
  1035. CleanUpIfFailedAndSetHrMsg(StringCchCatEx(szServerDirectory,ARRAYSIZE(szServerDirectory),szValue,NULL,NULL,MISTSAFE_STRING_FLAGS));
  1036. }
  1037. pszWalk += lstrlen(pszWalk) + 1; // skip the previous token, and go to the next one in the string.
  1038. *pszDelim = '|';
  1039. }
  1040. CleanUpIfFailedAndSetHrMsg(StringCchCatEx(szServerDirectory,ARRAYSIZE(szServerDirectory),SLASHENGINECAB,NULL,NULL,MISTSAFE_STRING_FLAGS));
  1041. if ('/' == szServerDirectory[0])
  1042. {
  1043. pszWalk = CharNext(szServerDirectory);
  1044. }
  1045. else
  1046. {
  1047. pszWalk = szServerDirectory;
  1048. }
  1049. DWORD dwSize = INTERNET_MAX_URL_LENGTH;
  1050. UrlCombine(szBaseServerUrl, pszWalk, m_pszSelfUpdateUrl, &dwSize, 0);
  1051. }
  1052. CleanUp:
  1053. if (SUCCEEDED(hr))
  1054. {
  1055. m_fIUPopulated = TRUE;
  1056. }
  1057. return hr;
  1058. }
  1059. //------------------------------------------------------------------------
  1060. //
  1061. // get the self-update server.
  1062. // *** this API should be called after PopulateData() is called ***
  1063. //
  1064. //------------------------------------------------------------------------
  1065. HRESULT CIUUrlAgent::GetSelfUpdateServer(
  1066. LPTSTR lpsBuffer,
  1067. int nBufferSize,
  1068. BOOL* pfInternalServer /*= NULL*/)
  1069. {
  1070. HRESULT hr=S_OK;
  1071. if (!m_fIUPopulated)
  1072. {
  1073. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1074. }
  1075. if (NULL == m_pszSelfUpdateUrl)
  1076. {
  1077. return (E_OUTOFMEMORY);
  1078. }
  1079. if (NULL == lpsBuffer)
  1080. {
  1081. return E_INVALIDARG;
  1082. }
  1083. nBufferSize/=sizeof(TCHAR);
  1084. if (nBufferSize <= lstrlen(m_pszSelfUpdateUrl))
  1085. {
  1086. return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  1087. }
  1088. hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszSelfUpdateUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
  1089. if(FAILED(hr))
  1090. return hr;
  1091. if (NULL != pfInternalServer)
  1092. {
  1093. *pfInternalServer = m_fIdentFromPolicy;
  1094. }
  1095. return hr;
  1096. }