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.

200 lines
6.2 KiB

  1. /****************************************************************************
  2. *
  3. * satellite.h
  4. *
  5. * Support for satellite resource DLLs.
  6. *
  7. * Owner: cthrash
  8. *
  9. * Copyright 1999-2000 Microsoft Corporation All Rights Reserved.
  10. *
  11. *****************************************************************************/
  12. #pragma once
  13. //--- Includes --------------------------------------------------------------
  14. #include <sphelper.h>
  15. //--- Forward and External Declarations -------------------------------------
  16. //--- TypeDef and Enumeration Declarations ----------------------------------
  17. //--- Constants -------------------------------------------------------------
  18. //--- Class, Struct and Union Definitions -----------------------------------
  19. class CSpSatelliteDLL
  20. {
  21. private:
  22. enum LoadState_t
  23. {
  24. LoadState_NotChecked,
  25. LoadState_Loaded,
  26. LoadState_NotFound
  27. };
  28. #pragma pack(push, LANGANDCODEPAGE, 2)
  29. struct LangAndCodePage_t
  30. {
  31. WORD wLanguage;
  32. WORD wCodePage;
  33. };
  34. #pragma pack(pop, LANGANDCODEPAGE)
  35. private:
  36. LoadState_t m_eLoadState;
  37. HINSTANCE m_hinstRes; // cached so FreeLibrary can be called;
  38. public:
  39. CSpSatelliteDLL() { m_eLoadState = LoadState_NotChecked; m_hinstRes = 0; }
  40. ~CSpSatelliteDLL() { if (m_hinstRes) { FreeLibrary(m_hinstRes); } }
  41. public:
  42. BOOL Checked() const { return LoadState_NotChecked != m_eLoadState; }
  43. public:
  44. HINSTANCE Load(
  45. HINSTANCE hinstModule, // [in] Instance handle of core DLL
  46. LPCTSTR lpszSatelliteName) // [in] Satellite DLL name
  47. {
  48. HINSTANCE hinstRes = hinstModule;
  49. LANGID langidUI = SpGetUserDefaultUILanguage();
  50. LANGID langidModule = 0;
  51. TCHAR achPath[MAX_PATH];
  52. DWORD cch = GetModuleFileName(hinstModule, achPath, sp_countof(achPath));
  53. if (cch)
  54. {
  55. //
  56. // First check the locale of the module;
  57. // If it's the same as the UI, assume it contains language-appropriate resources
  58. //
  59. DWORD dwHandle;
  60. DWORD dwVerInfoSize = GetFileVersionInfoSize(achPath, &dwHandle);
  61. if (dwVerInfoSize)
  62. {
  63. void * lpBuffer = malloc(dwVerInfoSize);
  64. if (lpBuffer)
  65. {
  66. if (GetFileVersionInfo(achPath, dwHandle, dwVerInfoSize, lpBuffer))
  67. {
  68. LangAndCodePage_t *pLangAndCodePage;
  69. UINT cch;
  70. if (VerQueryValue(lpBuffer, TEXT("\\VarFileInfo\\Translation"), (LPVOID *)&pLangAndCodePage, &cch) && cch)
  71. {
  72. // pay attention only to first entry
  73. langidModule = (LANGID)pLangAndCodePage->wLanguage;
  74. }
  75. }
  76. free(lpBuffer);
  77. }
  78. }
  79. //
  80. // If the languages don't match, look for a resource DLL
  81. //
  82. if (langidUI != langidModule)
  83. {
  84. DWORD cchDir;
  85. HINSTANCE hinst;
  86. // Look for {path}\{lcid}\{dll-name}
  87. while (cch && achPath[--cch] != TEXT('\\'));
  88. hinst = CheckDLL(achPath, achPath + cch + 1, langidUI, lpszSatelliteName);
  89. if (hinst)
  90. {
  91. hinstRes = hinst; // Found!
  92. }
  93. else
  94. {
  95. //
  96. // Couldn't find for specified UI langid; try default/netural sublangs.
  97. //
  98. if (SUBLANGID(langidUI) != SUBLANG_DEFAULT)
  99. {
  100. hinst = CheckDLL(achPath, achPath + cch + 1, MAKELANGID(PRIMARYLANGID(langidUI), SUBLANG_DEFAULT), lpszSatelliteName);
  101. }
  102. if (hinst)
  103. {
  104. hinstRes = hinst; // Found for SUBLANG_DEFAULT!
  105. }
  106. else if (SUBLANGID(langidUI) != SUBLANG_NEUTRAL)
  107. {
  108. hinst = CheckDLL(achPath, achPath + cch + 1, MAKELANGID(PRIMARYLANGID(langidUI), SUBLANG_NEUTRAL), lpszSatelliteName);
  109. if (hinst)
  110. {
  111. hinstRes = hinst; // Found for SUBLANG_NEUTRAL!
  112. }
  113. }
  114. }
  115. }
  116. }
  117. if (hinstModule != hinstRes)
  118. {
  119. m_hinstRes = hinstRes; // Cache it so the dtor can call FreeLibrary
  120. }
  121. return hinstRes;
  122. }
  123. HINSTANCE Detach(void)
  124. {
  125. HINSTANCE hinstRes = m_hinstRes;
  126. m_hinstRes = NULL;
  127. return hinstRes;
  128. }
  129. private:
  130. //
  131. // Check if satellite DLL exist for a particular LANGID
  132. //
  133. HINSTANCE CheckDLL(
  134. TCHAR * achPath, // [in] Complete path of module
  135. TCHAR * pchDir, // [in] Path to directory of module (including backslash)
  136. LANGID langid, // [in] Language of Satellite DLL
  137. LPCTSTR lpszSatelliteName) // [in] Satellite DLL name
  138. {
  139. TCHAR * pchSubDir;
  140. size_t cch;
  141. // TODO: Verify that the versions are in sync with core DLL?
  142. _itot(langid, pchDir, 10);
  143. pchSubDir = pchDir + _tcslen(pchDir);
  144. *pchSubDir++ = TEXT('\\');
  145. _tcscpy(pchSubDir, lpszSatelliteName);
  146. return LoadLibrary(achPath);
  147. }
  148. };
  149. //--- Function Declarations -------------------------------------------------
  150. //--- Inline Function Definitions -------------------------------------------