intres.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2008 by Giulio Bernardi
  4. Resource support for non-PECOFF targets (ELF, Mach-O)
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. type
  12. PResInfoNode = ^TResInfoNode;
  13. TResInfoNode = packed record
  14. nameid : PChar; //name / integer ID / languageID
  15. ncounthandle : longword; //named sub-entries count / resource handle
  16. idcountsize : longword; //id sub-entries count / resource size
  17. subptr : PResInfoNode; //first sub-entry pointer
  18. end;
  19. TResHdr = packed record
  20. rootptr : PResInfoNode; //pointer to root node
  21. count : longword; //number of resources in the file
  22. usedhandles : longword; //last resource handle used
  23. handles : PPtrUint; //pointer to handles
  24. end;
  25. PResHdr = ^TResHdr;
  26. PPResHdr = ^PResHdr;
  27. TLibGetResHdr=function():PResHdr;
  28. var
  29. {$ifdef FPC_HAS_WINLIKERESOURCES}
  30. {$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
  31. ResHeader : PPResHdr; external name '_FPC_ResLocation';
  32. {$else}
  33. ResHeaderVar: PResHdr; external name 'FPC_RESLOCATION';
  34. ResHeader : PPResHdr = @ResHeaderVar;
  35. {$endif}
  36. {$else}
  37. ResHeaderVar : PResHdr = nil;
  38. ResHeader : PPResHdr= @ResHeaderVar;
  39. {$endif}
  40. (*****************************************************************************
  41. Private Helper Functions
  42. *****************************************************************************)
  43. function ExtGetResHdr(ModuleHandle : TFPResourceHMODULE):PResHdr;
  44. var
  45. p:TLibGetResHdr;
  46. pp:pointer;
  47. begin
  48. ExtGetResHdr:=nil;
  49. if ModuleHandle=0 then
  50. ExtGetResHdr:=ResHeader^ // internal
  51. else
  52. begin
  53. // 1-st way to get resource location
  54. p:=TLibGetResHdr(GetProcAddress(ModuleHandle,'rsrc'));
  55. if p<>nil then // there is public
  56. ExtGetResHdr:=p();
  57. if ExtGetResHdr=nil then // try another way
  58. begin
  59. // 2-nd way to get resource location
  60. pp:=GetProcAddress(ModuleHandle,'FPC_RESLOCATION');
  61. if pp<>nil then
  62. ExtGetResHdr:=PResHDR(pp^);
  63. end;
  64. end;
  65. end;
  66. //resource functions are case insensitive... copied from genstr.inc
  67. function ResStrIComp(Str1, Str2 : PChar): SizeInt;
  68. var
  69. counter: SizeInt;
  70. c1, c2: char;
  71. begin
  72. counter := 0;
  73. c1 := upcase(str1[counter]);
  74. c2 := upcase(str2[counter]);
  75. while c1 = c2 do
  76. begin
  77. if (c1 = #0) or (c2 = #0) then break;
  78. inc(counter);
  79. c1 := upcase(str1[counter]);
  80. c2 := upcase(str2[counter]);
  81. end;
  82. ResStrIComp := ord(c1) - ord(c2);
  83. end;
  84. {!fixme!}
  85. //function InternalIsIntResource(aStr : pchar; out aInt : PtrUint) : boolean;
  86. function InternalIsIntResource(aStr : pchar; var aInt : PtrUint) : boolean;
  87. var i : integer;
  88. s : shortstring;
  89. code : word;
  90. begin
  91. InternalIsIntResource:=((PtrUInt(aStr) shr 16)=0);
  92. if InternalIsIntResource then aInt:=PtrUInt(aStr)
  93. else
  94. begin
  95. //a string like #number specifies an integer id
  96. if aStr[0]='#' then
  97. begin
  98. i:=1;
  99. while aStr[i]<>#0 do
  100. inc(i);
  101. if i>256 then i:=256;
  102. s[0]:=chr(i-1);
  103. Move(aStr[1],s[1],i-1);
  104. Val(s,aInt,code);
  105. InternalIsIntResource:=code=0;
  106. end;
  107. end;
  108. end;
  109. function BinSearchStr(arr : PResInfoNode; query : pchar; left, right : integer)
  110. : PResInfoNode;
  111. var pivot, res : integer;
  112. resstr : pchar;
  113. begin
  114. BinSearchStr:=nil;
  115. while left<=right do
  116. begin
  117. pivot:=(left+right) div 2;
  118. resstr:=arr[pivot].nameid;
  119. res:=ResStrIComp(resstr,query);
  120. if res<0 then left:=pivot+1
  121. else if res>0 then right:=pivot-1
  122. else
  123. begin
  124. BinSearchStr:=@arr[pivot];
  125. exit;
  126. end;
  127. end;
  128. end;
  129. function BinSearchInt(arr : PResInfoNode; query : pchar; left, right : integer)
  130. : PResInfoNode;
  131. var pivot : integer;
  132. begin
  133. BinSearchInt:=nil;
  134. while left<=right do
  135. begin
  136. pivot:=(left+right) div 2;
  137. if PtrUint(arr[pivot].nameid)<PtrUInt(query) then left:=pivot+1
  138. else if PtrUint(arr[pivot].nameid)>PtrUInt(query) then right:=pivot-1
  139. else
  140. begin
  141. BinSearchInt:=@arr[pivot];
  142. exit;
  143. end;
  144. end;
  145. end;
  146. function BinSearchRes(root : PResInfoNode; aDesc : PChar) : PResInfoNode;
  147. var aID : PtrUint;
  148. begin
  149. if InternalIsIntResource(aDesc,aID) then
  150. BinSearchRes:=BinSearchInt(root^.subptr,PChar(aID),root^.ncounthandle,
  151. root^.ncounthandle+root^.idcountsize-1)
  152. else
  153. BinSearchRes:=BinSearchStr(root^.subptr,aDesc,0,root^.ncounthandle-1);
  154. end;
  155. //Returns a pointer to a name node.
  156. function InternalFindResource(ResHdr:PResHdr;ResourceName, ResourceType: PChar):
  157. PResInfoNode;
  158. begin
  159. InternalFindResource:=nil;
  160. if ResHdr=nil then exit;
  161. InternalFindResource:=ResHdr^.rootptr;
  162. InternalFindResource:=BinSearchRes(InternalFindResource,ResourceType);
  163. if InternalFindResource<>nil then
  164. InternalFindResource:=BinSearchRes(InternalFindResource,ResourceName);
  165. end;
  166. function FindSubLanguage(aPtr : PResInfoNode; aLangID : word; aMask: word) : PResInfoNode;
  167. var arr : PResInfoNode;
  168. i : longword;
  169. begin
  170. FindSubLanguage:=nil;
  171. arr:=aPtr^.subptr;
  172. i:=0;
  173. while i<aPtr^.idcountsize do
  174. begin
  175. if (PtrUInt(arr[i].nameid) and aMask)=(aLangID and aMask) then
  176. begin
  177. FindSubLanguage:=@arr[i];
  178. exit;
  179. end;
  180. inc(i);
  181. end;
  182. end;
  183. (*****************************************************************************
  184. Public Resource Functions
  185. *****************************************************************************)
  186. Function IntHINSTANCE : TFPResourceHMODULE;
  187. begin
  188. IntHINSTANCE:=0;
  189. end;
  190. Function IntEnumResourceTypes(ModuleHandle : TFPResourceHMODULE; EnumFunc : EnumResTypeProc; lParam : PtrInt) : LongBool;
  191. var ptr : PResInfoNode;
  192. tot, i : integer;
  193. res_hdr:PResHdr;
  194. begin
  195. IntEnumResourceTypes:=False;
  196. res_hdr:=ExtGetResHdr(ModuleHandle);
  197. if res_hdr=nil then exit;
  198. tot:=res_hdr^.rootptr^.ncounthandle+res_hdr^.rootptr^.idcountsize;
  199. ptr:=res_hdr^.rootptr^.subptr;
  200. IntEnumResourceTypes:=true;
  201. i:=0;
  202. while i<tot do
  203. begin
  204. if not EnumFunc(ModuleHandle,ptr[i].nameid,lParam) then exit;
  205. inc(i);
  206. end;
  207. end;
  208. Function IntEnumResourceNames(ModuleHandle : TFPResourceHMODULE; ResourceType : PChar; EnumFunc : EnumResNameProc; lParam : PtrInt) : LongBool;
  209. var ptr : PResInfoNode;
  210. tot, i : integer;
  211. res_hdr:PResHdr;
  212. begin
  213. IntEnumResourceNames:=False;
  214. res_hdr:=ExtGetResHdr(ModuleHandle);
  215. if res_hdr=nil then exit;
  216. ptr:=res_hdr^.rootptr;
  217. ptr:=BinSearchRes(ptr,ResourceType);
  218. if ptr=nil then exit;
  219. tot:=ptr^.ncounthandle+ptr^.idcountsize;
  220. ptr:=ptr^.subptr;
  221. IntEnumResourceNames:=true;
  222. i:=0;
  223. while i<tot do
  224. begin
  225. if not EnumFunc(ModuleHandle,ResourceType,ptr[i].nameid,lParam) then exit;
  226. inc(i);
  227. end;
  228. end;
  229. Function IntEnumResourceLanguages(ModuleHandle : TFPResourceHMODULE; ResourceType, ResourceName : PChar; EnumFunc : EnumResLangProc; lParam : PtrInt) : LongBool;
  230. var ptr : PResInfoNode;
  231. tot, i : integer;
  232. res_hdr:PResHdr;
  233. begin
  234. IntEnumResourceLanguages:=False;
  235. res_hdr:=ExtGetResHdr(ModuleHandle);
  236. if res_hdr=nil then exit;
  237. ptr:=InternalFindResource(res_hdr,ResourceName,ResourceType);
  238. if ptr=nil then exit;
  239. tot:=ptr^.idcountsize;
  240. ptr:=ptr^.subptr;
  241. IntEnumResourceLanguages:=true;
  242. i:=0;
  243. while i<tot do
  244. begin
  245. if not EnumFunc(ModuleHandle,ResourceType,ResourceName,PtrUInt(ptr[i].nameid),lParam) then exit;
  246. inc(i);
  247. end;
  248. end;
  249. Function IntFindResource(ModuleHandle: TFPResourceHMODULE; ResourceName,
  250. ResourceType: PChar): TFPResourceHandle;
  251. var ptr : PResInfoNode;
  252. res_hdr: PresHdr;
  253. begin
  254. IntFindResource:=0;
  255. res_hdr:=ExtGetResHdr(ModuleHandle);
  256. if res_hdr=nil then exit;
  257. ptr:=InternalFindResource(res_hdr,ResourceName,ResourceType);
  258. if ptr=nil then exit;
  259. //first language id
  260. ptr:=ptr^.subptr;
  261. if ptr^.ncounthandle=0 then
  262. begin
  263. res_hdr^.handles[res_hdr^.usedhandles]:=PtrUint(ptr);
  264. inc(res_hdr^.usedhandles);
  265. ptr^.ncounthandle:=res_hdr^.usedhandles;
  266. end;
  267. IntFindResource:=ptr^.ncounthandle;
  268. end;
  269. Function IntFindResourceEx(ModuleHandle: TFPResourceHMODULE; ResourceType,
  270. ResourceName: PChar; Language : word): TFPResourceHandle;
  271. const LANG_NEUTRAL = 0;
  272. LANG_ENGLISH = 9;
  273. var nameptr,ptr : PResInfoNode;
  274. res_hdr: PResHdr;
  275. begin
  276. IntFindResourceEx:=0;
  277. res_hdr:=ExtGetResHdr(ModuleHandle);
  278. if res_hdr=nil then exit;
  279. nameptr:=InternalFindResource(res_hdr,ResourceName,ResourceType);
  280. if nameptr=nil then exit;
  281. //try exact match
  282. ptr:=FindSubLanguage(nameptr,Language,$FFFF);
  283. //try primary language
  284. if ptr=nil then
  285. ptr:=FindSubLanguage(nameptr,Language,$3FF);
  286. //try language neutral
  287. if ptr=nil then
  288. ptr:=FindSubLanguage(nameptr,LANG_NEUTRAL,$3FF);
  289. //try english
  290. if ptr=nil then
  291. ptr:=FindSubLanguage(nameptr,LANG_ENGLISH,$3FF);
  292. //nothing found, return the first one
  293. if ptr=nil then
  294. ptr:=nameptr^.subptr;
  295. if ptr^.ncounthandle=0 then
  296. begin
  297. res_hdr^.handles[res_hdr^.usedhandles]:=PtrUint(ptr);
  298. inc(res_hdr^.usedhandles);
  299. ptr^.ncounthandle:=res_hdr^.usedhandles;
  300. end;
  301. IntFindResourceEx:=ptr^.ncounthandle;
  302. end;
  303. Function IntLoadResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): TFPResourceHGLOBAL;
  304. var res_hdr: PResHdr;
  305. begin
  306. IntLoadResource:=0;
  307. res_hdr:=ExtGetResHdr(ModuleHandle);
  308. if res_hdr=nil then exit;
  309. if (ResHandle<=0) or (ResHandle>res_hdr^.usedhandles) then exit;
  310. IntLoadResource:=TFPResourceHGLOBAL(PResInfoNode(res_hdr^.handles[ResHandle-1])^.subptr);
  311. end;
  312. Function IntSizeofResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): LongWord;
  313. var res_hdr: PResHdr;
  314. begin
  315. IntSizeofResource:=0;
  316. res_hdr:=ExtGetResHdr(ModuleHandle);
  317. if res_hdr=nil then exit;
  318. if (ResHandle<=0) or (ResHandle>res_hdr^.usedhandles) then exit;
  319. IntSizeofResource:=PResInfoNode(res_hdr^.handles[ResHandle-1])^.idcountsize;
  320. end;
  321. Function IntLockResource(ResData: TFPResourceHGLOBAL): Pointer;
  322. begin
  323. IntLockResource:=Nil;
  324. if ResHeader^=nil then exit;
  325. IntLockResource:=Pointer(ResData);
  326. end;
  327. Function IntUnlockResource(ResData: TFPResourceHGLOBAL): LongBool;
  328. begin
  329. IntUnlockResource:=(ResHeader^<>nil);
  330. end;
  331. Function IntFreeResource(ResData: TFPResourceHGLOBAL): LongBool;
  332. begin
  333. IntFreeResource:=(ResHeader^<>nil);
  334. end;
  335. const
  336. InternalResourceManager : TResourceManager =
  337. (
  338. HINSTANCEFunc : @IntHINSTANCE;
  339. EnumResourceTypesFunc : @IntEnumResourceTypes;
  340. EnumResourceNamesFunc : @IntEnumResourceNames;
  341. EnumResourceLanguagesFunc : @IntEnumResourceLanguages;
  342. FindResourceFunc : @IntFindResource;
  343. FindResourceExFunc : @IntFindResourceEx;
  344. LoadResourceFunc : @IntLoadResource;
  345. SizeofResourceFunc : @IntSizeofResource;
  346. LockResourceFunc : @IntLockResource;
  347. UnlockResourceFunc : @IntUnlockResource;
  348. FreeResourceFunc : @IntFreeResource;
  349. );