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.

866 lines
18 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. globals.cxx
  5. Abstract:
  6. Contains global data items for WININET.DLL and initialization function
  7. Contents:
  8. GlobalDllInitialize
  9. GlobalDllTerminate
  10. GlobalDataInitialize
  11. GlobalDataTerminate
  12. IsHttp1_1
  13. SetOfflineUserState
  14. GetWininetUserName
  15. ChangeGlobalSettings
  16. Author:
  17. Richard L Firth (rfirth) 15-Jul-1995
  18. Revision History:
  19. 15-Jul-1995 rfirth
  20. Created
  21. 07-Oct-1998 joshco
  22. updated minor version number 1->2
  23. --*/
  24. #include <wininetp.h>
  25. #include <ntverp.h>
  26. #include <schnlsp.h>
  27. #include <persist.h>
  28. //
  29. // WinHttpX major & minor versions - allow to be defined externally
  30. //
  31. #if !defined(WINHTTPX_MAJOR_VERSION)
  32. #define WINHTTPX_MAJOR_VERSION 5
  33. #endif
  34. #if !defined(WINHTTPX_MINOR_VERSION)
  35. #define WINHTTPX_MINOR_VERSION 1
  36. #endif
  37. //
  38. // external functions
  39. //
  40. #if INET_DEBUG
  41. VOID
  42. InitDebugSock(
  43. VOID
  44. );
  45. #endif
  46. //
  47. // global DLL state data
  48. //
  49. GLOBAL HINSTANCE GlobalDllHandle = NULL;
  50. GLOBAL DWORD GlobalPlatformType;
  51. GLOBAL DWORD GlobalPlatformVersion5;
  52. GLOBAL DWORD GlobalPlatformMillennium = FALSE;
  53. GLOBAL BOOL GlobalDataInitialized = FALSE;
  54. GLOBAL HANDLE g_hCompletionPort = NULL;
  55. GLOBAL LPOVERLAPPED g_lpCustomOverlapped = NULL;
  56. GLOBAL DWORD g_cNumIOCPThreads = 0;
  57. #if INET_DEBUG
  58. LONG g_cWSACompletions = 0;
  59. LONG g_cCustomCompletions = 0;
  60. #endif
  61. //
  62. // WinInet DLL version information (mainly for diagnostics)
  63. //
  64. #if !defined(VER_PRODUCTBUILD)
  65. #define VER_PRODUCTBUILD 0
  66. #endif
  67. GLOBAL DWORD InternetBuildNumber = VER_PRODUCTBUILD;
  68. //
  69. // transport-based time-outs, etc.
  70. //
  71. #ifndef unix
  72. GLOBAL const DWORD GlobalConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
  73. #else
  74. GLOBAL const DWORD GlobalConnectTimeout = 1 * 60 * 1000;
  75. #endif /* unix */
  76. GLOBAL const DWORD GlobalResolveTimeout = DEFAULT_RESOLVE_TIMEOUT;
  77. GLOBAL const DWORD GlobalConnectRetries = DEFAULT_CONNECT_RETRIES;
  78. GLOBAL const DWORD GlobalSendTimeout = DEFAULT_SEND_TIMEOUT;
  79. GLOBAL const DWORD GlobalReceiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
  80. GLOBAL const DWORD GlobalTransportPacketLength = DEFAULT_TRANSPORT_PACKET_LENGTH;
  81. GLOBAL const DWORD GlobalKeepAliveSocketTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
  82. GLOBAL const DWORD GlobalSocketSendBufferLength = DEFAULT_SOCKET_SEND_BUFFER_LENGTH;
  83. GLOBAL const DWORD GlobalSocketReceiveBufferLength = DEFAULT_SOCKET_RECEIVE_BUFFER_LENGTH;
  84. GLOBAL const DWORD GlobalMaxHttpRedirects = DEFAULT_MAX_HTTP_REDIRECTS;
  85. GLOBAL const DWORD GlobalConnectionInactiveTimeout = DEFAULT_CONNECTION_INACTIVE_TIMEOUT;
  86. GLOBAL const DWORD GlobalServerInfoTimeout = DEFAULT_SERVER_INFO_TIMEOUT;
  87. //
  88. // switches
  89. //
  90. GLOBAL BOOL InDllCleanup = FALSE;
  91. GLOBAL BOOL GlobalDynaUnload = FALSE;
  92. GLOBAL BOOL GlobalDisableKeepAlive = FALSE;
  93. GLOBAL BOOL GlobalEnableHttp1_1 = FALSE;
  94. GLOBAL BOOL GlobalEnableProxyHttp1_1 = FALSE;
  95. GLOBAL BOOL GlobalIsProcessExplorer = FALSE;
  96. #ifndef UNIX
  97. GLOBAL const BOOL GlobalEnableFortezza = TRUE;
  98. #else /* for UNIX */
  99. GLOBAL const BOOL GlobalEnableFortezza = FALSE;
  100. #endif /* UNIX */
  101. // SSL Switches (petesk 7/24/97)
  102. GLOBAL const DWORD GlobalSecureProtocols = DEFAULT_SECURE_PROTOCOLS;
  103. //
  104. // AutoDetect Proxy Globals
  105. //
  106. GLOBAL LONG GlobalInternetOpenHandleCount = -1;
  107. GLOBAL DWORD GlobalProxyVersionCount = 0;
  108. GLOBAL BOOL GlobalAutoProxyInInit = FALSE;
  109. GLOBAL BOOL GlobalAutoProxyCacheEnable = TRUE;
  110. GLOBAL BOOL GlobalDisplayScriptDownloadFailureUI = FALSE;
  111. //
  112. // Workaround for Novell's Client32
  113. //
  114. GLOBAL const BOOL fDontUseDNSLoadBalancing = FALSE;
  115. //
  116. // lists
  117. //
  118. GLOBAL SERIALIZED_LIST GlobalObjectList;
  119. //
  120. // SSL globals, for UI. We need to know
  121. // whether its ok for us to pop up UI.
  122. //
  123. //
  124. GLOBAL SECURITY_CACHE_LIST GlobalCertCache;
  125. GLOBAL BOOL GlobalDisableNTLMPreAuth = FALSE;
  126. //
  127. // critical sections
  128. //
  129. GLOBAL CCritSec MlangCritSec;
  130. // Mlang related data and functions.
  131. PRIVATE HINSTANCE hInstMlang;
  132. PRIVATE PFNINETMULTIBYTETOUNICODE pfnInetMultiByteToUnicode;
  133. PRIVATE BOOL bFailedMlangLoad; // So we don't try repeatedly if we fail once.
  134. BOOL LoadMlang( );
  135. BOOL UnloadMlang( );
  136. #define MLANGDLLNAME "mlang.dll"
  137. //
  138. // novell client32 (hack) "support"
  139. //
  140. GLOBAL BOOL GlobalRunningNovellClient32 = FALSE;
  141. GLOBAL const BOOL GlobalNonBlockingClient32 = FALSE;
  142. //
  143. // proxy info
  144. //
  145. GLOBAL PROXY_INFO_GLOBAL * g_pGlobalProxyInfo;
  146. //
  147. // DLL version info
  148. //
  149. GLOBAL INTERNET_VERSION_INFO InternetVersionInfo = {
  150. WINHTTPX_MAJOR_VERSION,
  151. WINHTTPX_MINOR_VERSION
  152. };
  153. //
  154. // HTTP version info - default 1.0
  155. //
  156. GLOBAL HTTP_VERSION_INFO HttpVersionInfo = {1, 0};
  157. GLOBAL BOOL fCdromDialogActive = FALSE; // this needs to go
  158. //
  159. // The following globals are literal strings passed to winsock.
  160. // Do NOT make them const, otherwise they end up in .text section,
  161. // and web release of winsock2 has a bug where it locks and dirties
  162. // send buffers, confusing the win95 vmm and resulting in code
  163. // getting corrupted when it is paged back in. -RajeevD
  164. //
  165. GLOBAL char gszAt[] = "@";
  166. GLOBAL char gszBang[] = "!";
  167. GLOBAL char gszCRLF[] = "\r\n";
  168. // cookie special casing
  169. GLOBAL PTSTR GlobalSpecialDomains = NULL;
  170. GLOBAL PTSTR *GlobalSDOffsets = NULL;
  171. GLOBAL LONG g_cSessionCount=0;
  172. GLOBAL CAsyncCount* g_pAsyncCount = NULL;
  173. // implemented in ihttprequest\httprequest.cxx:
  174. extern void CleanupWinHttpRequestGlobals();
  175. //
  176. // functions
  177. //
  178. BOOL AddEventSource(void)
  179. {
  180. HKEY hKey;
  181. DWORD dwData;
  182. CHAR szBuf[80];
  183. DWORD dwDispo;
  184. // Add your source name as a subkey under the Application
  185. // key in the EventLog registry key.
  186. if (RegCreateKeyExA(HKEY_LOCAL_MACHINE,
  187. "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\WinHttp5",
  188. 0,
  189. NULL,
  190. REG_OPTION_NON_VOLATILE,
  191. KEY_READ | KEY_WRITE,
  192. NULL,
  193. &hKey,
  194. &dwDispo) != ERROR_SUCCESS)
  195. {
  196. return FALSE;
  197. }
  198. if (dwDispo == REG_OPENED_EXISTING_KEY)
  199. {
  200. RegCloseKey(hKey);
  201. return TRUE;
  202. }
  203. // Set the name of the message file.
  204. strcpy(szBuf, "%SystemRoot%\\System32\\WinHttp5.dll");
  205. // Add the name to the EventMessageFile subkey.
  206. if (RegSetValueEx(hKey, // subkey handle
  207. "EventMessageFile", // value name
  208. 0, // must be zero
  209. REG_EXPAND_SZ, // value type
  210. (LPBYTE) szBuf, // pointer to value data
  211. strlen(szBuf) + 1) != ERROR_SUCCESS) // length of value data
  212. {
  213. RegCloseKey(hKey);
  214. return FALSE;
  215. }
  216. // Set the supported event types in the TypesSupported subkey.
  217. dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
  218. EVENTLOG_INFORMATION_TYPE;
  219. if (RegSetValueEx(hKey, // subkey handle
  220. "TypesSupported", // value name
  221. 0, // must be zero
  222. REG_DWORD, // value type
  223. (LPBYTE) &dwData, // pointer to value data
  224. sizeof(DWORD)) != ERROR_SUCCESS) // length of value data
  225. {
  226. RegCloseKey(hKey);
  227. return FALSE;
  228. }
  229. RegCloseKey(hKey);
  230. return TRUE;
  231. }
  232. HANDLE g_hEventLog = 0;
  233. BOOL InitializeEventLog(void)
  234. {
  235. if (AddEventSource() == FALSE)
  236. {
  237. return FALSE;
  238. }
  239. g_hEventLog = ::RegisterEventSourceA(NULL, "WinHttp5");
  240. return g_hEventLog != NULL;
  241. }
  242. void TerminateEventLog(void)
  243. {
  244. if (g_hEventLog)
  245. {
  246. ::DeregisterEventSource(g_hEventLog);
  247. g_hEventLog = NULL;
  248. }
  249. }
  250. #ifdef UNIX
  251. extern "C"
  252. #endif /* UNIX */
  253. BOOL
  254. GlobalDllInitialize(
  255. VOID
  256. )
  257. /*++
  258. Routine Description:
  259. The set of initializations - critical sections, etc. - that must be done at
  260. DLL_PROCESS_ATTACH
  261. Arguments:
  262. None.
  263. Return Value:
  264. TRUE, only FALSE when not enough memory to initialize globals
  265. --*/
  266. {
  267. BOOL fResult = FALSE;
  268. DEBUG_ENTER((DBG_GLOBAL,
  269. None,
  270. "GlobalDllInitialize",
  271. NULL
  272. ));
  273. InitializeEventLog();
  274. CLEAR_DEBUG_CRIT(szDebugBlankBuffer);
  275. if (MlangCritSec.Init() &&
  276. InitializeSerializedList(&GlobalObjectList) &&
  277. AuthOpen() &&
  278. IwinsockInitialize() &&
  279. SecurityInitialize()
  280. )
  281. {
  282. fResult = TRUE;
  283. }
  284. DEBUG_LEAVE(fResult);
  285. return fResult;
  286. }
  287. #ifdef UNIX
  288. extern "C"
  289. #endif /* UNIX */
  290. VOID
  291. GlobalDllTerminate(
  292. VOID
  293. )
  294. /*++
  295. Routine Description:
  296. Undoes the initializations of GlobalDllInitialize
  297. Arguments:
  298. None.
  299. Return Value:
  300. None.
  301. --*/
  302. {
  303. DEBUG_ENTER((DBG_GLOBAL,
  304. None,
  305. "GlobalDllTerminate",
  306. NULL
  307. ));
  308. //
  309. // only perform resource clean-up if this DLL is being unloaded due to a
  310. // FreeLibrary() call. Otherwise, we take the lazy way out and let the
  311. // system clean up after us
  312. //
  313. if (GlobalDynaUnload) {
  314. TerminateAsyncSupport(TRUE);
  315. IwinsockTerminate();
  316. HandleTerminate();
  317. }
  318. CHECK_SOCKETS();
  319. AuthClose();
  320. //
  321. //BUGBUG: we can't Terminate the list here because
  322. // of a race condition from IE3
  323. // (someone still holds the handle)
  324. // but we don't want to leak the CritSec
  325. // TerminateSerlizedList == DeleteCritSec + some Asserts
  326. //
  327. //TerminateSerializedList(&GlobalObjectList);
  328. GlobalObjectList.Lock.FreeLock();
  329. MlangCritSec.FreeLock();
  330. SecurityTerminate();
  331. TerminateEventLog();
  332. DEBUG_LEAVE(0);
  333. }
  334. DWORD
  335. GlobalDataInitialize(
  336. VOID
  337. )
  338. /*++
  339. Routine Description:
  340. Loads any global data items from the registry
  341. Arguments:
  342. None.
  343. Return Value:
  344. DWORD
  345. Success - ERROR_SUCCESS
  346. Failure - ERROR_NOT_ENOUGH_MEMORY
  347. --*/
  348. {
  349. DEBUG_ENTER((DBG_GLOBAL,
  350. Dword,
  351. "GlobalDataInitialize",
  352. NULL
  353. ));
  354. static BOOL Initializing = FALSE;
  355. static BOOL Initialized = FALSE;
  356. static DWORD error = ERROR_SUCCESS;
  357. //
  358. // only one thread initializes
  359. //
  360. if (InterlockedExchange((LPLONG)&Initializing, TRUE)) {
  361. while (!Initialized) {
  362. SleepEx(0, TRUE);
  363. }
  364. goto done;
  365. }
  366. //
  367. // create the global cert-cache and proxy lists
  368. //
  369. GlobalCertCache.Initialize();
  370. INET_ASSERT(g_pGlobalProxyInfo==NULL);
  371. g_pGlobalProxyInfo = New PROXY_INFO_GLOBAL();
  372. if (!g_pGlobalProxyInfo)
  373. {
  374. error = ERROR_NOT_ENOUGH_MEMORY;
  375. goto quit;
  376. }
  377. g_pGlobalProxyInfo->InitializeProxySettings();
  378. //
  379. // Load proxy config settings from registry...
  380. //
  381. error = LoadProxySettings();
  382. if (error != ERROR_SUCCESS)
  383. goto quit;
  384. char buf[MAX_PATH + 1];
  385. if (GetModuleFileName(NULL, buf, sizeof(buf))) {
  386. LPSTR p = strrchr(buf, DIR_SEPARATOR_CHAR);
  387. p = p ? ++p : buf;
  388. DEBUG_PRINT(INET, INFO, ("process is %q\n", p));
  389. if (lstrcmpi(p, "EXPLORER.EXE") && lstrcmpi(p, "IEXPLORE.EXE")) {
  390. //
  391. // yet another app-hack: AOL's current browser can't understand
  392. // HTTP 1.1. When they do, they have to call InternetSetOption()
  393. // with WINHTTP_OPTION_HTTP_VERSION
  394. //
  395. if (!lstrcmpi(p, "WAOL.EXE")) {
  396. GlobalEnableHttp1_1 = FALSE;
  397. }
  398. } else {
  399. GlobalIsProcessExplorer = TRUE;
  400. }
  401. } else {
  402. DEBUG_PRINT(INET,
  403. INFO,
  404. ("GetModuleFileName() returns %d\n",
  405. GetLastError()
  406. ));
  407. }
  408. //
  409. // perform module/package-specific initialization
  410. //
  411. error = HandleInitialize();
  412. if (error != ERROR_SUCCESS) {
  413. goto quit;
  414. }
  415. quit:
  416. //
  417. // finally, if EnableHttp1_1 was set to non-zero in the registry, enable
  418. // HTTP 1.1
  419. //
  420. if (GlobalEnableHttp1_1) {
  421. HttpVersionInfo.dwMajorVersion = 1;
  422. HttpVersionInfo.dwMinorVersion = 1;
  423. }
  424. if (error == ERROR_SUCCESS) {
  425. GlobalDataInitialized = TRUE;
  426. }
  427. //
  428. // irrespective of success or failure, we have attempted global data
  429. // initialization. If we failed then we assume its something fundamental
  430. // and fatal: we don't try again
  431. //
  432. Initialized = TRUE;
  433. done:
  434. DEBUG_LEAVE(error);
  435. return error;
  436. }
  437. VOID
  438. GlobalDataTerminate(
  439. VOID
  440. )
  441. /*++
  442. Routine Description:
  443. Undoes work of GlobalDataInitialize()
  444. Arguments:
  445. None.
  446. Return Value:
  447. None.
  448. --*/
  449. {
  450. DEBUG_ENTER((DBG_GLOBAL,
  451. None,
  452. "GlobalDataTerminate",
  453. NULL
  454. ));
  455. RIP(g_cSessionCount == 0);
  456. #ifndef WININET_SERVER_CORE
  457. //
  458. // Release background task manager
  459. //
  460. UnloadBackgroundTaskMgr();
  461. #endif
  462. AuthUnload();
  463. if (GlobalSpecialDomains)
  464. {
  465. delete [] GlobalSpecialDomains;
  466. delete [] GlobalSDOffsets;
  467. }
  468. //
  469. // terminate the global cert-cache and proxy lists
  470. //
  471. GlobalCertCache.Terminate();
  472. if (g_pGlobalProxyInfo)
  473. {
  474. g_pGlobalProxyInfo->TerminateProxySettings();
  475. delete g_pGlobalProxyInfo;
  476. g_pGlobalProxyInfo = NULL;
  477. }
  478. //
  479. // ServerInfo's in WinHttpX are per-session instead of global.
  480. // InternetCloseHandle on a session handles purging the server
  481. // info list.
  482. //
  483. #ifndef WININET_SERVER_CORE
  484. PurgeServerInfoList(TRUE);
  485. #endif
  486. UnloadMlang();
  487. UnloadSecurity();
  488. CleanupWinHttpRequestGlobals();
  489. GlobalDataInitialized = FALSE;
  490. DEBUG_LEAVE(0);
  491. }
  492. BOOL
  493. IsHttp1_1(
  494. VOID
  495. )
  496. /*++
  497. Routine Description:
  498. Determine if we are using HTTP 1.1 or greater
  499. Arguments:
  500. None.
  501. Return Value:
  502. BOOL
  503. --*/
  504. {
  505. return (HttpVersionInfo.dwMajorVersion > 1)
  506. ? TRUE
  507. : (((HttpVersionInfo.dwMajorVersion == 1)
  508. && (HttpVersionInfo.dwMajorVersion >= 1))
  509. ? TRUE
  510. : FALSE);
  511. }
  512. VOID
  513. ChangeGlobalSettings(
  514. VOID
  515. )
  516. /*++
  517. Routine Description:
  518. Changes global settings
  519. Arguments:
  520. None.
  521. Return Value:
  522. None.
  523. --*/
  524. {
  525. DEBUG_ENTER((DBG_GLOBAL,
  526. None,
  527. "ChangeGlobalSettings",
  528. NULL
  529. ));
  530. #ifndef WININET_SERVER_CORE
  531. InternetReadRegistryDword("EnableHttp1_1",
  532. (LPDWORD)&GlobalEnableHttp1_1
  533. );
  534. InternetReadRegistryDword("ProxyHttp1.1",
  535. (LPDWORD)&GlobalEnableProxyHttp1_1
  536. );
  537. if (!g_pGlobalProxyInfo->IsModifiedInProcess())
  538. {
  539. FixProxySettingsForCurrentConnection(
  540. FALSE
  541. );
  542. }
  543. #endif //!WININET_SERVER_CORE
  544. DEBUG_LEAVE(0);
  545. }
  546. // Loads Mlang.dll and get the entry point we are interested in.
  547. BOOL LoadMlang( )
  548. {
  549. if (!MlangCritSec.Lock())
  550. goto quit;
  551. if (hInstMlang == NULL && !bFailedMlangLoad)
  552. {
  553. INET_ASSERT(pfnInetMultiByteToUnicode == NULL);
  554. hInstMlang = LoadLibrary(MLANGDLLNAME);
  555. if (hInstMlang != NULL)
  556. {
  557. pfnInetMultiByteToUnicode = (PFNINETMULTIBYTETOUNICODE)GetProcAddress
  558. (hInstMlang,"ConvertINetMultiByteToUnicode");
  559. if (pfnInetMultiByteToUnicode == NULL)
  560. {
  561. INET_ASSERT(FALSE);
  562. FreeLibrary(hInstMlang);
  563. hInstMlang = NULL;
  564. }
  565. }
  566. else
  567. {
  568. INET_ASSERT(FALSE); // bad news if we can't load mlang.dll
  569. }
  570. if (pfnInetMultiByteToUnicode == NULL)
  571. bFailedMlangLoad = TRUE;
  572. }
  573. MlangCritSec.Unlock();
  574. quit:
  575. return (pfnInetMultiByteToUnicode != NULL);
  576. }
  577. BOOL UnloadMlang( )
  578. {
  579. if (!MlangCritSec.Lock())
  580. return FALSE;
  581. if (hInstMlang)
  582. FreeLibrary(hInstMlang);
  583. hInstMlang = NULL;
  584. pfnInetMultiByteToUnicode = NULL;
  585. bFailedMlangLoad = FALSE;
  586. MlangCritSec.Unlock();
  587. return TRUE;
  588. }
  589. PFNINETMULTIBYTETOUNICODE GetInetMultiByteToUnicode( )
  590. {
  591. // We are checking for pfnInetMultiByteToUnicode without getting a crit section.
  592. // This works only because UnloadMlang is called at the Dll unload time.
  593. if (pfnInetMultiByteToUnicode == NULL)
  594. {
  595. LoadMlang( );
  596. }
  597. return pfnInetMultiByteToUnicode;
  598. }
  599. int cdecl _sprintf(char* buffer, char* format, va_list args);
  600. void LOG_EVENT(DWORD dwEventType, char* format, ...)
  601. {
  602. if (g_hEventLog == NULL)
  603. {
  604. return;
  605. }
  606. va_list args;
  607. int n;
  608. char *pBuffer = (char *) ALLOCATE_FIXED_MEMORY(1024);
  609. if (pBuffer == NULL)
  610. return;
  611. va_start(args, format);
  612. n = _sprintf(pBuffer, format, args);
  613. va_end(args);
  614. LPCSTR pszMessages[1];
  615. pszMessages[0] = &pBuffer[0];
  616. ::ReportEvent(g_hEventLog,
  617. (WORD)dwEventType,
  618. 0,
  619. dwEventType,
  620. NULL,
  621. 1,
  622. 0,
  623. &pszMessages[0],
  624. NULL);
  625. FREE_MEMORY(pBuffer);
  626. }