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.

938 lines
28 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * Abstract:
  6. *
  7. * Initialization routines for GDI+.
  8. *
  9. * Revision History:
  10. *
  11. * 12/02/1998 andrewgo
  12. * Created it.
  13. *
  14. \**************************************************************************/
  15. #include "precomp.hpp"
  16. #if GP_ICECAP>1
  17. #include "icecap.h"
  18. #endif
  19. // Add this to the Globals namespace.
  20. namespace Globals {
  21. extern BOOL RuntimeInitialized;
  22. };
  23. /**************************************************************************\
  24. *
  25. * Function Description:
  26. *
  27. * Generates a token that an init API can return, used to match the
  28. * startup call with the shutdown call.
  29. *
  30. * Return value:
  31. *
  32. * A non-zero value. It doesn't really matter what it is - it could be
  33. * a simple magic number, but we don't want apps relying on it being a
  34. * particular value.
  35. *
  36. * History:
  37. *
  38. * 09/15/2000 agodfrey
  39. * Created it.
  40. *
  41. \**************************************************************************/
  42. ULONG_PTR GenerateInitToken()
  43. {
  44. ULONG_PTR ret = GetTickCount();
  45. if (ret == 0)
  46. {
  47. ret = 1;
  48. }
  49. return ret;
  50. }
  51. /**************************************************************************\
  52. *
  53. * Function Description:
  54. *
  55. * This routine should undo all of the initialization done in
  56. * 'InternalGdiplusStartup'.
  57. *
  58. * Notes:
  59. *
  60. * Whenever this function, or the functions it calls, frees a pointer or
  61. * destroys a resource, it should set the corresponding global to NULL.
  62. * This is because it's legal for clients to call GdiplusStartup later.
  63. *
  64. * In addition, for resources, like DC's and DLL handles, we don't want to
  65. * call the "destroy" API if the handle is NULL, since it can waste time -
  66. * some API's take their time about recognizing the NULL.
  67. *
  68. * "delete" doesn't have this problem (the compiler generates a
  69. * NULL check for us.)
  70. *
  71. * Preconditions:
  72. *
  73. * GdiplusStartupCriticalSection must be held.
  74. *
  75. * History:
  76. *
  77. * 12/02/1998 andrewgo
  78. * Created it.
  79. * 10/03/2000 agodfrey
  80. * Changed it to zero out any pointers/handles that it cleans up,
  81. * so that InternalGdiplusStartup can safely be called later.
  82. *
  83. \**************************************************************************/
  84. VOID
  85. InternalGdiplusShutdown(
  86. VOID
  87. )
  88. {
  89. if (Globals::ThreadNotify != NULL)
  90. {
  91. BackgroundThreadShutdown();
  92. }
  93. // BackgroundThreadShutdown should NULL this variable itself:
  94. ASSERT(Globals::ThreadNotify == NULL);
  95. delete Globals::PathLookAside; Globals::PathLookAside = NULL;
  96. delete Globals::MatrixLookAside; Globals::MatrixLookAside = NULL;
  97. delete Globals::PenLookAside; Globals::PenLookAside = NULL;
  98. delete Globals::DesktopDevice; Globals::DesktopDevice = NULL;
  99. delete Globals::DeviceList; Globals::DeviceList = NULL;
  100. delete Globals::EngineDriver; Globals::EngineDriver = NULL;
  101. delete Globals::DesktopDriver; Globals::DesktopDriver = NULL;
  102. delete Globals::GdiDriver; Globals::GdiDriver = NULL;
  103. delete Globals::D3DDriver; Globals::D3DDriver = NULL;
  104. delete Globals::InfoDriver; Globals::InfoDriver = NULL;
  105. delete Globals::MetaDriver; Globals::MetaDriver = NULL;
  106. delete Globals::DesktopSurface; Globals::DesktopSurface = NULL;
  107. if (Globals::DdrawHandle)
  108. {
  109. FreeLibrary(Globals::DdrawHandle);
  110. Globals::DdrawHandle = NULL;
  111. }
  112. if (Globals::CachedGdiRegion)
  113. {
  114. DeleteObject(Globals::CachedGdiRegion);
  115. Globals::CachedGdiRegion = NULL;
  116. }
  117. if (Globals::DesktopIc)
  118. {
  119. DeleteDC(Globals::DesktopIc);
  120. Globals::DesktopIc = NULL;
  121. }
  122. delete Globals::FontCollection; Globals::FontCollection = NULL;
  123. delete Globals::FontLinkTable; Globals::FontLinkTable = NULL;
  124. if (Globals::SurrogateFontsTable!= NULL &&
  125. Globals::SurrogateFontsTable!= (GpFontFamily **)-1)
  126. {
  127. GpFree(Globals::SurrogateFontsTable);
  128. }
  129. Globals::SurrogateFontsTable = (GpFontFamily **) -1;
  130. delete Globals::FontCacheLastRecentlyUsedList;
  131. Globals::FontCacheLastRecentlyUsedList = NULL;
  132. delete Globals::NationalDigitCache; Globals::NationalDigitCache = NULL;
  133. // destroy the Generic objects
  134. GpStringFormat::DestroyStaticObjects();
  135. delete [] Globals::FontsDirW; Globals::FontsDirW = NULL;
  136. delete [] Globals::FontsDirA; Globals::FontsDirA = NULL;
  137. if (Globals::LookAsideBuffer)
  138. {
  139. GpFree(Globals::LookAsideBuffer);
  140. Globals::LookAsideBuffer = NULL;
  141. }
  142. if (Globals::TextCriticalSectionInitialized)
  143. {
  144. DeleteCriticalSection(&Globals::TextCriticalSection);
  145. Globals::TextCriticalSectionInitialized = FALSE;
  146. }
  147. if (Globals::DcimanHandle)
  148. {
  149. FreeLibrary(Globals::DcimanHandle);
  150. Globals::DcimanHandle = NULL;
  151. }
  152. // Uninitialize imaging library
  153. CleanupImagingLibrary();
  154. GpTextImager::CleanupTextImager();
  155. if (Globals::UniscribeDllModule)
  156. {
  157. FreeLibrary(Globals::UniscribeDllModule);
  158. Globals::UniscribeDllModule = NULL;
  159. }
  160. if (Globals::RuntimeInitialized)
  161. {
  162. GpRuntime::Uninitialize();
  163. Globals::RuntimeInitialized = FALSE;
  164. }
  165. // We leak Globals::Monitors intentionally, so that it can be used
  166. // around GdiplusShutdown as well. It's okay because:
  167. //
  168. // 1) Unless the user has called GdipMonitorControl (to be removed before
  169. // we ship), nothing will be leaked.
  170. // 2) GpMonitors defines its own new and delete, which bypass GpMalloc/
  171. // GpFree. So, this won't cause us to hit the memory leak assertion.
  172. // delete Globals::Monitors; Globals::Monitors = NULL;
  173. LoadLibraryCriticalSection::DeleteCriticalSection();
  174. BackgroundThreadCriticalSection::DeleteCriticalSection();
  175. // Perform memory leak detection.
  176. // Must be done after all memory cleanup.
  177. GpAssertShutdownNoMemoryLeaks();
  178. VERBOSE(("InternalGdiplusShutdown completed"));
  179. // This must be done last.
  180. GpMallocTrackingCriticalSection::DeleteCriticalSection();
  181. if (GpRuntime::GpMemHeap)
  182. {
  183. HeapDestroy(GpRuntime::GpMemHeap);
  184. GpRuntime::GpMemHeap = NULL;
  185. }
  186. }
  187. /******************************Public*Routine******************************\
  188. *
  189. * Routine Name:
  190. *
  191. * GetLanguageID
  192. *
  193. * Routine Description:
  194. *
  195. * This routines returns the default language ID. Normally, we would call
  196. * GetLocaleInfoW to get this information but that API is not available in
  197. * kernel mode. Since GetLocaleInfoW gets it from the registry we'll do the
  198. * same.
  199. *
  200. * Arguments: none
  201. *
  202. * Called by:
  203. *
  204. * Return Value:
  205. *
  206. * The default language ID. If the call fails it will just return 0x0409
  207. * for English.
  208. *
  209. \**************************************************************************/
  210. USHORT GetLanguageID(VOID)
  211. {
  212. // Language ID is the low word of lcid
  213. DWORD lcid = GetSystemDefaultLCID();
  214. USHORT result = USHORT(lcid & 0x0000ffff);
  215. #if INITIALIZE_DBG
  216. TERSE(("Language ID = 0x%04x", result));
  217. #endif
  218. return(result);
  219. }
  220. /**************************************************************************\
  221. *
  222. * Function Description:
  223. *
  224. * Initialize the version-related data. This may be called several times,
  225. * so this must not allocate memory, etc. This is called both by
  226. * InternalGdiplusStartup() and by the GpObject class constructor. Since an
  227. * object can be global, an object may be created before
  228. * InternalGdiplusStartup() is called, which is why the GpObject
  229. * constructor may need to call this.
  230. *
  231. * Only state that is needed by our initialization routines should be
  232. * initialized here.
  233. *
  234. * !!! [agodfrey] I disagree with the above. I don't think it's safe to let
  235. * apps call us before they call GdiplusStartup. For one thing, we will
  236. * erroneously assert that memory was leaked - but I think we could AV.
  237. *
  238. * It does make life a little tricky for app developers if
  239. * they want global objects that call us in their constructors.
  240. * We need to publish sample code for how to do this safely
  241. * (e.g. see test\gpinit.inc)
  242. *
  243. * Arguments:
  244. *
  245. * NONE
  246. *
  247. * Return Value:
  248. *
  249. * NONE
  250. *
  251. * Created:
  252. *
  253. * 7/26/1999 DCurtis
  254. *
  255. \**************************************************************************/
  256. VOID
  257. InitVersionInfo()
  258. {
  259. if (!Globals::VersionInfoInitialized)
  260. {
  261. Globals::OsVer.dwOSVersionInfoSize = sizeof(Globals::OsVer);
  262. GetVersionExA(&Globals::OsVer);
  263. Globals::IsNt = (Globals::OsVer.dwPlatformId == VER_PLATFORM_WIN32_NT);
  264. Globals::IsWin95 = ((Globals::OsVer.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
  265. (Globals::OsVer.dwMajorVersion == 4) &&
  266. (Globals::OsVer.dwMinorVersion == 0));
  267. Globals::ACP = GetACP();
  268. Globals::VersionInfoInitialized = TRUE;
  269. }
  270. }
  271. VOID SysColorNotify();
  272. /**************************************************************************\
  273. *
  274. * Function Description:
  275. *
  276. * Initialize globals for the GDI+ engine.
  277. *
  278. * NOTE: Initialization should not be extremely expensive!
  279. * Do NOT put a lot of gratuitous junk into here; consider instead
  280. * doing lazy initialization.
  281. *
  282. * Arguments:
  283. *
  284. * debugEventFunction - A function the caller can give us that we'll call
  285. * to report ASSERTs or WARNINGs. Can be NULL.
  286. *
  287. * Preconditions:
  288. *
  289. * GdiplusStartupCriticalSection must be held.
  290. *
  291. * Return Value:
  292. *
  293. * FALSE if failure (such as low memory).
  294. *
  295. * History:
  296. *
  297. * 12/02/1998 andrewgo
  298. * Created it.
  299. *
  300. \**************************************************************************/
  301. GpStatus
  302. InternalGdiplusStartup(
  303. const GdiplusStartupInput *input)
  304. {
  305. // Set up the debug event reporting function, before we use ASSERT or
  306. // WARNING.
  307. Globals::UserDebugEventProc = input->DebugEventCallback;
  308. #if GDIPPRIVATEBUILD
  309. #define GDIPCREATEUSERNAMEMESSAGE() "This is a private build from " USERNAME \
  310. "\nBuilt on " __DATE__ " " __TIME__
  311. ::MessageBoxA(NULL, GDIPCREATEUSERNAMEMESSAGE(), "Private Build", MB_OK);
  312. #undef GDIPCREATEUSERNAMEMESSAGE
  313. #endif
  314. // Create the GDI+ heap...
  315. ASSERT(!GpRuntime::GpMemHeap);
  316. GpRuntime::GpMemHeap = HeapCreate(GPMEMHEAPFLAGS, GPMEMHEAPINITIAL, GPMEMHEAPLIMIT);
  317. // If we cannot create the heap, give up!
  318. if (!GpRuntime::GpMemHeap)
  319. goto ErrorOut;
  320. // This must happen first.
  321. __try
  322. {
  323. GpMallocTrackingCriticalSection::InitializeCriticalSection();
  324. BackgroundThreadCriticalSection::InitializeCriticalSection();
  325. LoadLibraryCriticalSection::InitializeCriticalSection();
  326. }
  327. __except(EXCEPTION_EXECUTE_HANDLER)
  328. {
  329. // We couldn't allocate the criticalSection
  330. // Return an error
  331. goto ErrorOut;
  332. }
  333. // If Allocation failures are turned on, do some initialization here.
  334. GpInitializeAllocFailures();
  335. GpStartInitializeAllocFailureMode();
  336. INT height;
  337. INT width;
  338. GpDevice *device;
  339. Globals::RuntimeInitialized = GpRuntime::Initialize();
  340. if (!Globals::RuntimeInitialized)
  341. goto ErrorOut;
  342. InitVersionInfo();
  343. Globals::CachedGdiRegion = CreateRectRgn(0, 0, 1, 1);
  344. if (!Globals::CachedGdiRegion)
  345. goto ErrorOut;
  346. // Initialize Stack Back Trace functionality if necessary.
  347. Globals::CaptureStackBackTraceFunction = NULL;
  348. // This stuff requires NT (ntdll.dll)
  349. #if GPMEM_ALLOC_CHK
  350. if(Globals::IsNt)
  351. {
  352. HMODULE module = GetModuleHandleA("ntdll.dll");
  353. Globals::CaptureStackBackTraceFunction = (CAPTURESTACKBACKTRACEFUNCTION)
  354. GetProcAddress(module, "RtlCaptureStackBackTrace");
  355. }
  356. #endif
  357. // Memory allocation subsystem is initialized. It is now safe to use
  358. // GpMalloc.
  359. // Initialize multi-monitor and window event related function pointers
  360. {
  361. HMODULE module = GetModuleHandleA("user32.dll");
  362. Globals::GetWindowInfoFunction = (GETWINDOWINFOFUNCTION)
  363. GetProcAddress(module, "GetWindowInfo");
  364. Globals::GetAncestorFunction = (GETANCESTORFUNCTION)
  365. GetProcAddress(module, "GetAncestor");
  366. Globals::GetMonitorInfoFunction = (GETMONITORINFOFUNCTION)
  367. GetProcAddress(module, "GetMonitorInfoA");
  368. Globals::EnumDisplayMonitorsFunction = (ENUMDISPLAYMONITORSFUNCTION)
  369. GetProcAddress(module, "EnumDisplayMonitors");
  370. Globals::EnumDisplayDevicesFunction = (ENUMDISPLAYDEVICESFUNCTION)
  371. GetProcAddress(module, "EnumDisplayDevicesA");
  372. Globals::SetWinEventHookFunction = (SETWINEVENTHOOKFUNCTION)
  373. GetProcAddress(module, "SetWinEventHook");
  374. Globals::UnhookWinEventFunction = (UNHOOKWINEVENTFUNCTION)
  375. GetProcAddress(module, "UnhookWinEvent");
  376. }
  377. // Create the default desktop device representation.
  378. if (GetSystemMetrics(SM_REMOTESESSION))
  379. {
  380. // it is a remote session
  381. Globals::IsTerminalServer = TRUE;
  382. }
  383. else
  384. {
  385. // it isn't a remote session.
  386. Globals::IsTerminalServer = FALSE;
  387. }
  388. // On the NT codebase, the CreateDC(DISPLAY, NULL, NULL, NULL) call has
  389. // thread affinity. This means that the desktop DC would go away if the
  390. // thread which called GdiplusStartup terminated even if we were still
  391. // using it.
  392. // On NT we create an Info DC which has process affinity. Rendering onto
  393. // an Info DC is not supported but that's ok because we always create
  394. // DriverMulti on NT - and therefore always render on a monitor specific
  395. // DC instead.
  396. // Win9x does not have the thread affinity problem and we'd use an IC
  397. // if it weren't for the fact that win95 doesn't have EnumDisplayMonitors
  398. // and hence uses DriverGdi instead of DriverMulti - rendering directly
  399. // on the DesktopIc
  400. // see RAID:
  401. // 301407 GDI+ Globals::DesktopDc has thread affinity
  402. // 312342 CreateDC("Display", NULL, NULL, NULL) has thread affinity.
  403. // and gdiplus/test/multithread for a test app that exposes this problem.
  404. if(Globals::IsNt)
  405. {
  406. Globals::DesktopIc = CreateICA("DISPLAY", NULL, NULL, NULL);
  407. }
  408. else
  409. {
  410. Globals::DesktopIc = CreateDCA("DISPLAY", NULL, NULL, NULL);
  411. }
  412. if (!Globals::DesktopIc)
  413. {
  414. goto ErrorOut;
  415. }
  416. Globals::DesktopDpiX = (REAL)::GetDeviceCaps(Globals::DesktopIc, LOGPIXELSX);
  417. Globals::DesktopDpiY = (REAL)::GetDeviceCaps(Globals::DesktopIc, LOGPIXELSY);
  418. if ((Globals::DesktopDpiX <= 0) || (Globals::DesktopDpiY <= 0))
  419. {
  420. WARNING(("GetDeviceCaps failed"));
  421. Globals::DesktopDpiX = DEFAULT_RESOLUTION;
  422. Globals::DesktopDpiY = DEFAULT_RESOLUTION;
  423. }
  424. device = Globals::DesktopDevice = new GpDevice(Globals::DesktopIc);
  425. if (!CheckValid(Globals::DesktopDevice))
  426. goto ErrorOut;
  427. Globals::DeviceList = new GpDeviceList();
  428. if(Globals::DeviceList == NULL)
  429. goto ErrorOut;
  430. // Create the virtual driver representing all GDI+ Eng drawing:
  431. Globals::EngineDriver = new DpDriver(device);
  432. if (!CheckValid(Globals::EngineDriver))
  433. goto ErrorOut;
  434. // Create the driver for use with the desktop device
  435. // NOTE: for now we always use the multimon driver. In the future
  436. // we will be able to dynamically redirect desktop drawing
  437. // through different drivers as the desktop changes. This will
  438. // require that we have a mechanism to safely modify various
  439. // GDI+ objects in response to the mode change.
  440. // Only use multi-mon driver on multi-mon capable systems
  441. if(Globals::GetMonitorInfoFunction != NULL &&
  442. Globals::EnumDisplayMonitorsFunction != NULL)
  443. {
  444. Globals::DesktopDriver = new DriverMulti(device);
  445. if (!CheckValid(Globals::DesktopDriver))
  446. goto ErrorOut;
  447. }
  448. else
  449. {
  450. Globals::DesktopDriver = new DriverGdi(device);
  451. if (!CheckValid(Globals::DesktopDriver))
  452. goto ErrorOut;
  453. }
  454. Globals::GdiDriver = new DriverGdi(device);
  455. if (!CheckValid(Globals::GdiDriver))
  456. goto ErrorOut;
  457. Globals::D3DDriver = new DriverD3D(device);
  458. if (!CheckValid(Globals::D3DDriver))
  459. goto ErrorOut;
  460. Globals::InfoDriver = new DriverInfo(device);
  461. if (!CheckValid(Globals::InfoDriver))
  462. goto ErrorOut;
  463. Globals::MetaDriver = new DriverMeta(device);
  464. if (!CheckValid(Globals::MetaDriver))
  465. goto ErrorOut;
  466. Globals::DesktopSurface = new DpBitmap();
  467. if (!CheckValid(Globals::DesktopSurface))
  468. goto ErrorOut;
  469. // Get the multimon meta-desktop resolution. SM_CX/CYVIRTUALSCREEN
  470. // doesn't work on Win95 or NT4, though...
  471. width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
  472. height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
  473. if ((width == 0) || (height == 0))
  474. {
  475. width = GetSystemMetrics(SM_CXSCREEN);
  476. height = GetSystemMetrics(SM_CYSCREEN);
  477. }
  478. Globals::DesktopSurface->InitializeForGdiScreen(
  479. Globals::DesktopDevice,
  480. width,
  481. height);
  482. // Give the driver an opportunity to adjust the surface.
  483. // If we're on multimon, we need to fix up the
  484. // pixel format for the DesktopSurface.
  485. Globals::DesktopDriver->UpdateSurfacePixelFormat(
  486. Globals::DesktopSurface
  487. );
  488. // GDI+ v1 DCR 336742
  489. // We are disabling image codecs for v1, so ignore the
  490. // input->SuppressExternalCodecs flag and hardwire to TRUE.
  491. // Jbronsk
  492. if (!InitImagingLibrary(TRUE /* suppressExternalCodecs */))
  493. {
  494. // If we couldn't initialize the ImagingLibrary
  495. goto ErrorOut;
  496. }
  497. // Initialize the system colors in fastest search order
  498. Globals::SystemColors [0] = RGB(0x00,0x00,0x00);
  499. Globals::SystemColors [1] = RGB(0xFF,0xFF,0xFF);
  500. Globals::SystemColors [2] = RGB(0xC0,0xC0,0xC0);
  501. Globals::SystemColors [3] = RGB(0x80,0x80,0x80);
  502. Globals::SystemColors [4] = RGB(0x00,0x00,0xFF);
  503. Globals::SystemColors [5] = RGB(0x00,0x00,0x80);
  504. Globals::SystemColors [6] = RGB(0x00,0xFF,0x00);
  505. Globals::SystemColors [7] = RGB(0x00,0x80,0x00);
  506. Globals::SystemColors [8] = RGB(0xFF,0x00,0x00);
  507. Globals::SystemColors [9] = RGB(0x80,0x00,0x00);
  508. Globals::SystemColors[10] = RGB(0xFF,0xFF,0x00);
  509. Globals::SystemColors[11] = RGB(0x80,0x80,0x00);
  510. Globals::SystemColors[12] = RGB(0x00,0xFF,0xFF);
  511. Globals::SystemColors[13] = RGB(0x00,0x80,0x80);
  512. Globals::SystemColors[14] = RGB(0xFF,0x00,0xFF);
  513. Globals::SystemColors[15] = RGB(0x80,0x00,0x80);
  514. SysColorNotify(); // update last 4 colors
  515. if (Globals::IsNt)
  516. {
  517. HMODULE module = GetModuleHandle(TEXT("gdi32.dll"));
  518. Globals::ExtTextOutFunction = (EXTTEXTOUTFUNCTION)
  519. GetProcAddress(module, "ExtTextOutW");
  520. Globals::GdiIsMetaPrintDCFunction = (GDIISMETAPRINTDCFUNCTION)
  521. GetProcAddress(module, "GdiIsMetaPrintDC");
  522. }
  523. else
  524. {
  525. HMODULE module = GetModuleHandleA("gdi32.dll");
  526. Globals::ExtTextOutFunction = (EXTTEXTOUTFUNCTION)
  527. GetProcAddress(module, "ExtTextOutA");
  528. Globals::GdiIsMetaPrintDCFunction = GdiIsMetaPrintDCWin9x;
  529. }
  530. Globals::LanguageID = GetLanguageID();
  531. if (!InitSystemFontsDirs())
  532. goto ErrorOut;
  533. // globals are initialized to NULL
  534. ASSERT(Globals::NationalDigitCache == NULL);
  535. Globals::UserDigitSubstituteInvalid = TRUE;
  536. Globals::CurrentSystemRenderingHintInvalid = TRUE;
  537. Globals::CurrentSystemRenderingHint = TextRenderingHintSingleBitPerPixelGridFit;
  538. VERBOSE(("Loading fonts..."));
  539. Globals::FontCollection = GpInstalledFontCollection::GetGpInstalledFontCollection();
  540. if (!Globals::FontCollection || !(Globals::FontCollection->GetFontTable()))
  541. goto ErrorOut;
  542. // font caching, least recently used list
  543. Globals::FontCacheLastRecentlyUsedList = new GpCacheFaceRealizationList;
  544. if (!Globals::FontCacheLastRecentlyUsedList)
  545. goto ErrorOut;
  546. // Initialize for font file cache criticalization
  547. __try
  548. {
  549. InitializeCriticalSection(&Globals::TextCriticalSection);
  550. Globals::TextCriticalSectionInitialized = TRUE;
  551. }
  552. __except(EXCEPTION_EXECUTE_HANDLER)
  553. {
  554. // We couldn't allocate the criticalSection
  555. // Return an error
  556. goto ErrorOut;
  557. }
  558. // If allocation failures are on, start default failure rate
  559. GpDoneInitializeAllocFailureMode();
  560. // Now that everything's initialized, it's safe to start the background
  561. // thread. (The danger: It may immediately receive a message, and the
  562. // message-handling code assumes that we've been initialized already.)
  563. if (!input->SuppressBackgroundThread)
  564. {
  565. if (!BackgroundThreadStartup())
  566. {
  567. goto ErrorOut;
  568. }
  569. }
  570. #if GP_ICECAP>1
  571. CommentMarkProfile(1, "InternalGdiplusStartup completed");
  572. #endif
  573. VERBOSE(("InternalGdiplusStartup completed successfully"));
  574. return Ok;
  575. ErrorOut:
  576. WARNING(("InternalGdiplusStartup: Initialization failed"));
  577. // Note that the following should free anything we've stuck in
  578. // the 'globals' class:
  579. InternalGdiplusShutdown();
  580. return GenericError;
  581. }
  582. /**************************************************************************\
  583. *
  584. * Function Description:
  585. *
  586. * Initialize font directory goop.
  587. *
  588. * Return Value:
  589. *
  590. * FALSE if failure (such as low memory).
  591. *
  592. * History:
  593. *
  594. * 6/10/1999 bodind
  595. * Created it.
  596. *
  597. * 3/1/2002 mikhaill - fixed bug 556954
  598. \**************************************************************************/
  599. #define numberof(x) (sizeof(x)/sizeof(x[0]))
  600. BOOL InitSystemFontsDirs(void)
  601. {
  602. // Check if already initialized
  603. if (Globals::FontsDirW) return TRUE;
  604. WCHAR windowsStr[MAX_PATH+1];
  605. UINT windowsStrLength; // size of windows directory path, placed in windowsStr,
  606. // without trailing zero, in wide chars
  607. if (Globals::IsNt)
  608. {
  609. // GetWindowsDirectoryW is not working with TS
  610. // Also GetSystemWidowsDirectoryW is not supported in NT4
  611. // So we only can use GetSystemDirectory and truncated system32
  612. windowsStrLength = GetSystemDirectoryW(windowsStr, numberof(windowsStr));
  613. if (windowsStrLength <= 0 || windowsStrLength >= numberof(windowsStr))
  614. return FALSE;
  615. for (INT i = windowsStrLength - 1; i >= 0; i--)
  616. {
  617. if (windowsStr[i] == L'\\')
  618. {
  619. windowsStrLength = (UINT)i;
  620. break;
  621. }
  622. }
  623. }
  624. else
  625. {
  626. CHAR windowsStrA[numberof(windowsStr)];
  627. windowsStrLength = GetWindowsDirectoryA(windowsStrA, numberof(windowsStrA));
  628. if (windowsStrLength <= 0 || windowsStrLength >= numberof(windowsStrA))
  629. return FALSE;
  630. int r = MultiByteToWideChar(CP_ACP, 0, windowsStrA, -1,
  631. windowsStr, numberof(windowsStr));
  632. if (r == 0) return FALSE;
  633. // (mikhaill) The following check for trailing '\\' was inherited from old code.
  634. // Seems to be useless, but harmless.
  635. // In theory, can serve some weird situations, say, when
  636. // GetWindowsDirectory() returns "C:\\".
  637. if ((windowsStr[windowsStrLength - 1] == L'\\'))
  638. {
  639. windowsStrLength -= 1;
  640. }
  641. }
  642. if (windowsStrLength == 0) return FALSE;
  643. // Compute the font directory pathname length, including NULL
  644. static const WCHAR FontsSubdirW[] = L"\\fonts";
  645. UINT fontsTotalLength = windowsStrLength + numberof(FontsSubdirW);
  646. // compose unicode path
  647. Globals::FontsDirW = new WCHAR[fontsTotalLength];
  648. if (!Globals::FontsDirW) return FALSE;
  649. memcpy(Globals::FontsDirW, windowsStr, windowsStrLength*sizeof(WCHAR));
  650. memcpy(Globals::FontsDirW + windowsStrLength, FontsSubdirW, sizeof(FontsSubdirW));
  651. // make ansi path from unicode:
  652. // get the required buffer length
  653. int ansiLng = WideCharToMultiByte(CP_ACP, 0, Globals::FontsDirW, -1,
  654. NULL, 0, 0, 0);
  655. if (ansiLng == 0) goto fail;
  656. Globals::FontsDirA = new CHAR[ansiLng];
  657. if (!Globals::FontsDirA) goto fail;
  658. int ansiLn2 = WideCharToMultiByte(CP_ACP, 0, Globals::FontsDirW, -1,
  659. Globals::FontsDirA, ansiLng,
  660. 0, 0);
  661. if (ansiLn2 != ansiLng) goto fail;
  662. #if INITIALIZE_DBG
  663. TERSE(("Fonts path is %ws (%d chars).", Globals::FontsDirW, fontsTotalLength));
  664. #endif
  665. return TRUE;
  666. fail:
  667. delete[] Globals::FontsDirW; Globals::FontsDirW = NULL;
  668. delete[] Globals::FontsDirA; Globals::FontsDirA = NULL;
  669. return FALSE;
  670. }
  671. /**************************************************************************\
  672. *
  673. * Function Description:
  674. *
  675. * Initializes direct draw and direct 3D related globals.
  676. *
  677. * Arguments:
  678. *
  679. * NONE
  680. *
  681. * Return Value:
  682. *
  683. * TRUE for success otherwise FALSE.
  684. *
  685. * History:
  686. *
  687. * 10/06/1999 bhouse
  688. * Created it.
  689. *
  690. \**************************************************************************/
  691. BOOL InitializeDirectDrawGlobals(void)
  692. {
  693. if(Globals::DirectDrawInitialized)
  694. return TRUE;
  695. if(Globals::DirectDrawInitAttempted)
  696. return FALSE;
  697. // This critical section is used to protect LoadLibrary calls.
  698. LoadLibraryCriticalSection llcs;
  699. Globals::DirectDrawInitAttempted = TRUE;
  700. Globals::DdrawHandle = LoadLibraryA("ddraw.dll");
  701. if(Globals::DdrawHandle == NULL)
  702. {
  703. WARNING(("Unable to load direct draw library"));
  704. return(FALSE);
  705. }
  706. Globals::GetDdrawSurfaceFromDcFunction
  707. = (GETDDRAWSURFACEFROMDCFUNCTION)
  708. GetProcAddress(Globals::DdrawHandle,
  709. "GetSurfaceFromDC");
  710. if(Globals::GetDdrawSurfaceFromDcFunction == NULL)
  711. {
  712. WARNING(("Unable to get GetSurfaceFromDC procedure address"));
  713. return(FALSE);
  714. }
  715. Globals::DirectDrawCreateExFunction
  716. = (DIRECTDRAWCREATEEXFUNCTION)
  717. GetProcAddress(Globals::DdrawHandle,
  718. "DirectDrawCreateEx");
  719. if(Globals::DirectDrawCreateExFunction == NULL)
  720. {
  721. WARNING(("Unable to get DirectDrawCreateEx procedure address"));
  722. return(FALSE);
  723. }
  724. Globals::DirectDrawEnumerateExFunction
  725. = (DIRECTDRAWENUMERATEEXFUNCTION)
  726. GetProcAddress(Globals::DdrawHandle,
  727. "DirectDrawEnumerateExA");
  728. if(Globals::DirectDrawEnumerateExFunction == NULL)
  729. {
  730. WARNING(("Unable to get DirectDrawEnumerateEx procedure address"));
  731. return(FALSE);
  732. }
  733. HRESULT hr;
  734. hr = Globals::DirectDrawCreateExFunction(NULL,
  735. &Globals::DirectDraw,
  736. IID_IDirectDraw7,
  737. NULL);
  738. if(hr != DD_OK)
  739. {
  740. WARNING(("Unable to create Direct Draw interface"));
  741. return(FALSE);
  742. }
  743. hr = Globals::DirectDraw->SetCooperativeLevel(NULL, DDSCL_NORMAL);
  744. if(hr != DD_OK)
  745. {
  746. WARNING(("Unable to set DDSCL_NORMAL cooperative level"));
  747. return(FALSE);
  748. }
  749. hr = Globals::DirectDraw->QueryInterface(IID_IDirect3D7,
  750. (void **) &Globals::Direct3D);
  751. if(hr != DD_OK)
  752. {
  753. WARNING(("Unable to get D3D interface"));
  754. return(FALSE);
  755. }
  756. Globals::DirectDrawInitialized = TRUE;
  757. return TRUE;
  758. }