ResourceModule.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. unit ResourceModule;
  2. interface
  3. function GetResourceModule(ModuleName: PChar): string;
  4. implementation
  5. //uses
  6. // Windows;
  7. const
  8. advapi32 = 'advapi32.dll';
  9. kernel = 'kernel32.dll';
  10. user = 'user32.dll';
  11. HKEY_CURRENT_USER = $80000001;
  12. HKEY_LOCAL_MACHINE = $80000002;
  13. OldLocaleOverrideKey = 'Software\Borland\Delphi\Locales'; // do not localize
  14. NewLocaleOverrideKey = 'Software\Borland\Locales'; // do not localize
  15. KEY_READ = $000F0019;
  16. LOCALE_SABBREVLANGNAME = $00000003; { abbreviated language name }
  17. LOAD_LIBRARY_AS_DATAFILE = 2;
  18. type
  19. TWin32FindData = packed record
  20. dwFileAttributes: Integer;
  21. ftCreationTime: Int64;
  22. ftLastAccessTime: Int64;
  23. ftLastWriteTime: Int64;
  24. nFileSizeHigh: Integer;
  25. nFileSizeLow: Integer;
  26. dwReserved0: Integer;
  27. dwReserved1: Integer;
  28. cFileName: array[0..259] of Char;
  29. cAlternateFileName: array[0..13] of Char;
  30. end;
  31. function GetModuleHandle(ModuleName: PChar): Integer; stdcall;
  32. external kernel name 'GetModuleHandleA';
  33. function CharNext(lpsz: PChar): PChar; stdcall;
  34. external user name 'CharNextA';
  35. function GetProcAddress(Module: Integer; ProcName: PChar): Pointer; stdcall;
  36. external kernel name 'GetProcAddress';
  37. function FindClose(FindFile: Integer): LongBool; stdcall;
  38. external kernel name 'FindClose';
  39. function _strlen(lpString: PChar): Integer; stdcall;
  40. external kernel name 'lstrlenA';
  41. function lstrcpyn(lpString1, lpString2: PChar;
  42. iMaxLength: Integer): PChar; stdcall;
  43. external kernel name 'lstrcpynA';
  44. function FindFirstFile(FileName: PChar; var FindFileData: TWIN32FindData): Integer; stdcall;
  45. external kernel name 'FindFirstFileA';
  46. function GetModuleFileName(Module: Integer; Filename: PChar;
  47. Size: Integer): Integer; stdcall;
  48. external kernel name 'GetModuleFileNameA';
  49. function RegOpenKeyEx(hKey: LongWord; lpSubKey: PChar; ulOptions,
  50. samDesired: LongWord; var phkResult: LongWord): Longint; stdcall;
  51. external advapi32 name 'RegOpenKeyExA';
  52. function RegQueryValueEx(hKey: LongWord; lpValueName: PChar;
  53. lpReserved: Pointer; lpType: Pointer; lpData: PChar; lpcbData: Pointer): Integer; stdcall;
  54. external advapi32 name 'RegQueryValueExA';
  55. function RegCloseKey(hKey: Integer): Longint; stdcall;
  56. external advapi32 name 'RegCloseKey';
  57. function GetLocaleInfo(Locale: Longint; LCType: Longint; lpLCData: PChar; cchData: Integer): Integer; stdcall;
  58. external kernel name 'GetLocaleInfoA';
  59. function GetThreadLocale: Longint; stdcall;
  60. external kernel name 'GetThreadLocale';
  61. function LoadLibraryEx(LibName: PChar; hFile: Longint; Flags: Longint): Longint; stdcall;
  62. external kernel name 'LoadLibraryExA';
  63. function GetResourceModule(ModuleName: PChar): string;
  64. var
  65. FileName: array[0..260] of Char;
  66. Key: LongWord;
  67. LocaleName, LocaleOverride: array[0..4] of Char;
  68. Size: Integer;
  69. P: PChar;
  70. R: Integer;
  71. function FindBS(Current: PChar): PChar;
  72. begin
  73. Result := Current;
  74. while (Result^ <> #0) and (Result^ <> '\') do
  75. Result := CharNext(Result);
  76. end;
  77. function ToLongPath(AFileName: PChar; BufSize: Integer): PChar;
  78. var
  79. CurrBS, NextBS: PChar;
  80. Handle, L: Integer;
  81. FindData: TWin32FindData;
  82. Buffer: array[0..260] of Char;
  83. GetLongPathName: function (ShortPathName: PChar; LongPathName: PChar;
  84. cchBuffer: Integer): Integer stdcall;
  85. begin
  86. Result := AFileName;
  87. Handle := GetModuleHandle(kernel);
  88. if Handle <> 0 then
  89. begin
  90. @GetLongPathName := GetProcAddress(Handle, 'GetLongPathNameA');
  91. if Assigned(GetLongPathName) and
  92. (GetLongPathName(AFileName, Buffer, SizeOf(Buffer)) <> 0) then
  93. begin
  94. lstrcpyn(AFileName, Buffer, BufSize);
  95. Exit;
  96. end;
  97. end;
  98. if AFileName[0] = '\' then
  99. begin
  100. if AFileName[1] <> '\' then Exit;
  101. CurrBS := FindBS(AFileName + 2); // skip server name
  102. if CurrBS^ = #0 then Exit;
  103. CurrBS := FindBS(CurrBS + 1); // skip share name
  104. if CurrBS^ = #0 then Exit;
  105. end else
  106. CurrBS := AFileName + 2; // skip drive name
  107. L := CurrBS - AFileName;
  108. lstrcpyn(Buffer, AFileName, L + 1);
  109. while CurrBS^ <> #0 do
  110. begin
  111. NextBS := FindBS(CurrBS + 1);
  112. if L + (NextBS - CurrBS) + 1 > SizeOf(Buffer) then Exit;
  113. lstrcpyn(Buffer + L, CurrBS, (NextBS - CurrBS) + 1);
  114. Handle := FindFirstFile(Buffer, FindData);
  115. if (Handle = -1) then Exit;
  116. FindClose(Handle);
  117. if L + 1 + _strlen(FindData.cFileName) + 1 > SizeOf(Buffer) then Exit;
  118. Buffer[L] := '\';
  119. lstrcpyn(Buffer + L + 1, FindData.cFileName, Sizeof(Buffer) - L - 1);
  120. Inc(L, _strlen(FindData.cFileName) + 1);
  121. CurrBS := NextBS;
  122. end;
  123. lstrcpyn(AFileName, Buffer, BufSize);
  124. end;
  125. begin
  126. GetModuleFileName(0, FileName, SizeOf(FileName)); // Get host application name
  127. LocaleOverride[0] := #0;
  128. if (RegOpenKeyEx(HKEY_CURRENT_USER, NewLocaleOverrideKey, 0, KEY_READ, Key) = 0) or
  129. (RegOpenKeyEx(HKEY_LOCAL_MACHINE, NewLocaleOverrideKey, 0, KEY_READ, Key) = 0) or
  130. (RegOpenKeyEx(HKEY_CURRENT_USER, OldLocaleOverrideKey, 0, KEY_READ, Key) = 0) then
  131. try
  132. Size := sizeof(LocaleOverride);
  133. ToLongPath(FileName, sizeof(FileName));
  134. if RegQueryValueEx(Key, FileName, nil, nil, LocaleOverride, @Size) <> 0 then
  135. if RegQueryValueEx(Key, '', nil, nil, LocaleOverride, @Size) <> 0 then
  136. LocaleOverride[0] := #0;
  137. LocaleOverride[sizeof(LocaleOverride)-1] := #0;
  138. finally
  139. RegCloseKey(Key);
  140. end;
  141. lstrcpyn(FileName, ModuleName, sizeof(FileName));
  142. GetLocaleInfo(GetThreadLocale, LOCALE_SABBREVLANGNAME, LocaleName, sizeof(LocaleName));
  143. if (FileName[0] <> #0) and ((LocaleName[0] <> #0) or (LocaleOverride[0] <> #0)) then
  144. begin
  145. P := PChar(@FileName) + _strlen(FileName);
  146. while (P^ <> '.') and (P <> @FileName) do Dec(P);
  147. if P <> @FileName then
  148. begin
  149. Inc(P);
  150. R := 0;
  151. // First look for a locale registry override
  152. if LocaleOverride[0] <> #0 then
  153. begin
  154. lstrcpyn(P, LocaleOverride, sizeof(FileName) - (P - FileName));
  155. R := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
  156. end;
  157. if (R = 0) and (LocaleName[0] <> #0) then
  158. begin
  159. // Then look for a potential language/country translation
  160. lstrcpyn(P, LocaleName, sizeof(FileName) - (P - FileName));
  161. R := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
  162. if R = 0 then
  163. begin
  164. // Finally look for a language only translation
  165. LocaleName[2] := #0;
  166. lstrcpyn(P, LocaleName, sizeof(FileName) - (P - FileName));
  167. R := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
  168. end;
  169. end
  170. end;
  171. end;
  172. if R = 0 then Result := ''
  173. else Result := FileName;
  174. end;
  175. end.