write_sltg.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858
  1. /*
  2. * Typelib (SLTG) generation
  3. *
  4. * Copyright 2015,2016 Dmitry Timoshkov
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include "wine/port.h"
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdarg.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <time.h>
  28. #define NONAMELESSUNION
  29. #include "windef.h"
  30. #include "winbase.h"
  31. #include "widl.h"
  32. #include "typelib.h"
  33. #include "typelib_struct.h"
  34. #include "utils.h"
  35. #include "header.h"
  36. #include "typetree.h"
  37. static const GUID sltg_library_guid = { 0x204ff,0,0,{ 0xc0,0,0,0,0,0,0,0x46 } };
  38. struct sltg_data
  39. {
  40. int size, allocated;
  41. char *data;
  42. };
  43. struct sltg_library
  44. {
  45. short name;
  46. char *helpstring;
  47. char *helpfile;
  48. int helpcontext;
  49. int syskind;
  50. LCID lcid;
  51. int libflags;
  52. int version;
  53. GUID uuid;
  54. };
  55. struct sltg_block
  56. {
  57. int length;
  58. int index_string;
  59. void *data;
  60. struct sltg_block *next;
  61. };
  62. struct sltg_typelib
  63. {
  64. typelib_t *typelib;
  65. struct sltg_data index;
  66. struct sltg_data name_table;
  67. struct sltg_library library;
  68. struct sltg_block *blocks;
  69. int n_file_blocks;
  70. int first_block;
  71. int typeinfo_count;
  72. int typeinfo_size;
  73. struct sltg_block *typeinfo;
  74. };
  75. struct sltg_hrefmap
  76. {
  77. int href_count;
  78. int *href;
  79. };
  80. #include "pshpack1.h"
  81. struct sltg_typeinfo_header
  82. {
  83. short magic;
  84. int href_offset;
  85. int res06;
  86. int member_offset;
  87. int res0e;
  88. int version;
  89. int res16;
  90. struct
  91. {
  92. unsigned unknown1 : 3;
  93. unsigned flags : 13;
  94. unsigned unknown2 : 8;
  95. unsigned typekind : 8;
  96. } misc;
  97. int res1e;
  98. };
  99. struct sltg_member_header
  100. {
  101. short res00;
  102. short res02;
  103. char res04;
  104. int extra;
  105. };
  106. struct sltg_variable
  107. {
  108. char magic; /* 0x0a */
  109. char flags;
  110. short next;
  111. short name;
  112. short byte_offs; /* pos in struct, or offset to const type or const data (if flags & 0x08) */
  113. short type; /* if flags & 0x02 this is the type, else offset to type */
  114. int memid;
  115. short helpcontext;
  116. short helpstring;
  117. short varflags; /* only present if magic & 0x02 */
  118. };
  119. struct sltg_tail
  120. {
  121. short cFuncs;
  122. short cVars;
  123. short cImplTypes;
  124. short res06; /* always 0000 */
  125. short funcs_off; /* offset to functions (starting from the member header) */
  126. short vars_off; /* offset to vars (starting from the member header) */
  127. short impls_off; /* offset to implemented types (starting from the member header) */
  128. short funcs_bytes; /* bytes used by function data */
  129. short vars_bytes; /* bytes used by var data */
  130. short impls_bytes; /* bytes used by implemented type data */
  131. short tdescalias_vt; /* for TKIND_ALIAS */
  132. short res16; /* always ffff */
  133. short res18; /* always 0000 */
  134. short res1a; /* always 0000 */
  135. short simple_alias; /* tdescalias_vt is a vt rather than an offset? */
  136. short res1e; /* always 0000 */
  137. short cbSizeInstance;
  138. short cbAlignment;
  139. short res24;
  140. short res26;
  141. short cbSizeVft;
  142. short res2a; /* always ffff */
  143. short res2c; /* always ffff */
  144. short res2e; /* always ffff */
  145. short res30; /* always ffff */
  146. short res32; /* unknown */
  147. short type_bytes; /* bytes used by type descriptions */
  148. };
  149. struct sltg_hrefinfo
  150. {
  151. char magic; /* 0xdf */
  152. char res01; /* 0x00 */
  153. int res02; /* 0xffffffff */
  154. int res06; /* 0xffffffff */
  155. int res0a; /* 0xffffffff */
  156. int res0e; /* 0xffffffff */
  157. int res12; /* 0xffffffff */
  158. int res16; /* 0xffffffff */
  159. int res1a; /* 0xffffffff */
  160. int res1e; /* 0xffffffff */
  161. int res22; /* 0xffffffff */
  162. int res26; /* 0xffffffff */
  163. int res2a; /* 0xffffffff */
  164. int res2e; /* 0xffffffff */
  165. int res32; /* 0xffffffff */
  166. int res36; /* 0xffffffff */
  167. int res3a; /* 0xffffffff */
  168. int res3e; /* 0xffffffff */
  169. short res42;/* 0xffff */
  170. int number; /* this is 8 times the number of refs */
  171. /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */
  172. short res50;/* 0xffff */
  173. char res52; /* 0x01 */
  174. int res53; /* 0x00000000 */
  175. /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii
  176. * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the
  177. * ref refers to the nth type listed in this library (0 based). Else
  178. * the xxxx (which maybe fewer than 4 digits) is the offset into the name
  179. * table to a string "*\G{<guid>}#1.0#0#C:\WINNT\System32\stdole32.tlb#"
  180. * The guid is the typelib guid; the ref again refers to the nth type of
  181. * the imported typelib.
  182. */
  183. char resxx; /* 0xdf */
  184. };
  185. struct sltg_function
  186. {
  187. char magic; /* 0x4c, 0xcb or 0x8b with optional SLTG_FUNCTION_FLAGS_PRESENT flag */
  188. char flags; /* high nibble is INVOKE_KIND, low nibble = 2 */
  189. short next; /* byte offset from beginning of group to next fn */
  190. short name; /* Offset within name table to name */
  191. int dispid; /* dispid */
  192. short helpcontext; /* helpcontext (again 1 is special) */
  193. short helpstring; /* helpstring offset to offset */
  194. short arg_off; /* offset to args from start of block */
  195. char nacc; /* lowest 3bits are CALLCONV, rest are no of args */
  196. char retnextopt; /* if 0x80 bit set ret type follows else next WORD
  197. is offset to ret type. No of optional args is
  198. middle 6 bits */
  199. short rettype; /* return type VT_?? or offset to ret type */
  200. short vtblpos; /* position in vtbl? */
  201. short funcflags; /* present if magic & 0x20 */
  202. /* Param list starts, repeat next two as required */
  203. #if 0
  204. WORD name; /* offset to 2nd letter of name */
  205. WORD+ type; /* VT_ of param */
  206. #endif
  207. };
  208. struct sltg_impl_info
  209. {
  210. short res00;
  211. short next;
  212. short res04;
  213. char impltypeflags;
  214. char res07;
  215. short res08;
  216. short ref;
  217. short res0c;
  218. short res0e;
  219. short res10;
  220. short res12;
  221. short pos;
  222. };
  223. #include "poppack.h"
  224. static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type);
  225. static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *type);
  226. static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type);
  227. static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type);
  228. static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type);
  229. static void init_sltg_data(struct sltg_data *data)
  230. {
  231. data->size = 0;
  232. data->allocated = 0x10;
  233. data->data = xmalloc(0x10);
  234. }
  235. static int add_index(struct sltg_data *index, const char *name)
  236. {
  237. int name_offset = index->size;
  238. int new_size = index->size + strlen(name) + 1;
  239. chat("add_index: name_offset %d, \"%s\"\n", name_offset, name);
  240. if (new_size > index->allocated)
  241. {
  242. index->allocated = max(index->allocated * 2, new_size);
  243. index->data = xrealloc(index->data, index->allocated);
  244. }
  245. strcpy(index->data + index->size, name);
  246. index->size = new_size;
  247. return name_offset;
  248. }
  249. static void init_index(struct sltg_data *index)
  250. {
  251. static const char compobj[] = { 1,'C','o','m','p','O','b','j',0 };
  252. init_sltg_data(index);
  253. add_index(index, compobj);
  254. }
  255. static int add_name(struct sltg_typelib *sltg, const char *name)
  256. {
  257. int name_offset = sltg->name_table.size;
  258. int new_size = sltg->name_table.size + strlen(name) + 1 + 8;
  259. int aligned_size;
  260. chat("add_name: %s\n", name);
  261. aligned_size = (new_size + 0x1f) & ~0x1f;
  262. if (aligned_size - new_size < 4)
  263. new_size = aligned_size;
  264. else
  265. new_size = (new_size + 1) & ~1;
  266. if (new_size > sltg->name_table.allocated)
  267. {
  268. sltg->name_table.allocated = max(sltg->name_table.allocated * 2, new_size);
  269. sltg->name_table.data = xrealloc(sltg->name_table.data, sltg->name_table.allocated);
  270. }
  271. memset(sltg->name_table.data + sltg->name_table.size, 0xff, 8);
  272. strcpy(sltg->name_table.data + sltg->name_table.size + 8, name);
  273. sltg->name_table.size = new_size;
  274. sltg->name_table.data[sltg->name_table.size - 1] = 0; /* clear alignment */
  275. return name_offset;
  276. }
  277. static void init_name_table(struct sltg_typelib *sltg)
  278. {
  279. init_sltg_data(&sltg->name_table);
  280. }
  281. static void init_library(struct sltg_typelib *sltg)
  282. {
  283. const attr_t *attr;
  284. sltg->library.name = add_name(sltg, sltg->typelib->name);
  285. sltg->library.helpstring = NULL;
  286. sltg->library.helpcontext = 0;
  287. sltg->library.syskind = (pointer_size == 8) ? SYS_WIN64 : SYS_WIN32;
  288. sltg->library.lcid = 0x0409;
  289. sltg->library.libflags = 0;
  290. sltg->library.version = 0;
  291. sltg->library.helpfile = NULL;
  292. memset(&sltg->library.uuid, 0, sizeof(sltg->library.uuid));
  293. if (!sltg->typelib->attrs) return;
  294. LIST_FOR_EACH_ENTRY(attr, sltg->typelib->attrs, const attr_t, entry)
  295. {
  296. const expr_t *expr;
  297. switch (attr->type)
  298. {
  299. case ATTR_VERSION:
  300. sltg->library.version = attr->u.ival;
  301. break;
  302. case ATTR_HELPSTRING:
  303. sltg->library.helpstring = attr->u.pval;
  304. break;
  305. case ATTR_HELPFILE:
  306. sltg->library.helpfile = attr->u.pval;
  307. break;
  308. case ATTR_UUID:
  309. sltg->library.uuid = *(GUID *)attr->u.pval;
  310. break;
  311. case ATTR_HELPCONTEXT:
  312. expr = attr->u.pval;
  313. sltg->library.helpcontext = expr->cval;
  314. break;
  315. case ATTR_LIBLCID:
  316. expr = attr->u.pval;
  317. sltg->library.lcid = expr->cval;
  318. break;
  319. case ATTR_CONTROL:
  320. sltg->library.libflags |= 0x02; /* LIBFLAG_FCONTROL */
  321. break;
  322. case ATTR_HIDDEN:
  323. sltg->library.libflags |= 0x04; /* LIBFLAG_FHIDDEN */
  324. break;
  325. case ATTR_RESTRICTED:
  326. sltg->library.libflags |= 0x01; /* LIBFLAG_FRESTRICTED */
  327. break;
  328. default:
  329. break;
  330. }
  331. }
  332. }
  333. static void add_block_index(struct sltg_typelib *sltg, void *data, int size, int index)
  334. {
  335. struct sltg_block *block = xmalloc(sizeof(*block));
  336. block->length = size;
  337. block->data = data;
  338. block->index_string = index;
  339. block->next = NULL;
  340. if (sltg->blocks)
  341. {
  342. struct sltg_block *blocks = sltg->blocks;
  343. while (blocks->next)
  344. blocks = blocks->next;
  345. blocks->next = block;
  346. }
  347. else
  348. sltg->blocks = block;
  349. sltg->n_file_blocks++;
  350. }
  351. static void add_block(struct sltg_typelib *sltg, void *data, int size, const char *name)
  352. {
  353. struct sltg_block *block = xmalloc(sizeof(*block));
  354. int index;
  355. chat("add_block: %p,%d,\"%s\"\n", data, size, name);
  356. index = add_index(&sltg->index, name);
  357. add_block_index(sltg, data, size, index);
  358. }
  359. static void *create_library_block(struct sltg_typelib *typelib, int *size, int *index)
  360. {
  361. void *block;
  362. short *p;
  363. *size = sizeof(short) * 9 + sizeof(int) * 3 + sizeof(GUID);
  364. if (typelib->library.helpstring) *size += strlen(typelib->library.helpstring);
  365. if (typelib->library.helpfile) *size += strlen(typelib->library.helpfile);
  366. block = xmalloc(*size);
  367. p = block;
  368. *p++ = 0x51cc; /* magic */
  369. *p++ = 3; /* res02 */
  370. *p++ = typelib->library.name;
  371. *p++ = 0xffff; /* res06 */
  372. if (typelib->library.helpstring)
  373. {
  374. *p++ = strlen(typelib->library.helpstring);
  375. strcpy((char *)p, typelib->library.helpstring);
  376. p = (short *)((char *)p + strlen(typelib->library.helpstring));
  377. }
  378. else
  379. *p++ = 0xffff;
  380. if (typelib->library.helpfile)
  381. {
  382. *p++ = strlen(typelib->library.helpfile);
  383. strcpy((char *)p, typelib->library.helpfile);
  384. p = (short *)((char *)p + strlen(typelib->library.helpfile));
  385. }
  386. else
  387. *p++ = 0xffff;
  388. *(int *)p = typelib->library.helpcontext;
  389. p += 2;
  390. *p++ = typelib->library.syskind;
  391. *p++ = typelib->library.lcid;
  392. *(int *)p = 0; /* res12 */
  393. p += 2;
  394. *p++ = typelib->library.libflags;
  395. *(int *)p = typelib->library.version;
  396. p += 2;
  397. *(GUID *)p = typelib->library.uuid;
  398. *index = add_index(&typelib->index, "dir");
  399. return block;
  400. }
  401. static const char *new_index_name(void)
  402. {
  403. static char name[11] = "0000000000";
  404. static int pos = 0;
  405. char *new_name;
  406. if (name[pos] == 'Z')
  407. {
  408. pos++;
  409. if (pos > 9)
  410. error("too many index names\n");
  411. }
  412. name[pos]++;
  413. new_name = xmalloc(sizeof(name));
  414. strcpy(new_name, name);
  415. return new_name;
  416. }
  417. static void sltg_add_typeinfo(struct sltg_typelib *sltg, void *data, int size, const char *name)
  418. {
  419. struct sltg_block *block = xmalloc(sizeof(*block));
  420. chat("sltg_add_typeinfo: %p,%d,%s\n", data, size, name);
  421. block->length = size;
  422. block->data = data;
  423. block->index_string = 0;
  424. block->next = NULL;
  425. if (sltg->typeinfo)
  426. {
  427. struct sltg_block *typeinfo = sltg->typeinfo;
  428. while (typeinfo->next)
  429. typeinfo = typeinfo->next;
  430. typeinfo->next = block;
  431. }
  432. else
  433. sltg->typeinfo = block;
  434. sltg->typeinfo_count++;
  435. sltg->typeinfo_size += size;
  436. }
  437. static void append_data(struct sltg_data *block, const void *data, int size)
  438. {
  439. int new_size = block->size + size;
  440. if (new_size > block->allocated)
  441. {
  442. block->allocated = max(block->allocated * 2, new_size);
  443. block->data = xrealloc(block->data, block->allocated);
  444. }
  445. memcpy(block->data + block->size, data, size);
  446. block->size = new_size;
  447. }
  448. static void add_module_typeinfo(struct sltg_typelib *typelib, type_t *type)
  449. {
  450. error("add_module_typeinfo: %s not implemented\n", type->name);
  451. }
  452. static const char *add_typeinfo_block(struct sltg_typelib *typelib, const type_t *type, int kind)
  453. {
  454. const char *index_name, *other_name;
  455. void *block;
  456. short *p;
  457. int size, helpcontext = 0;
  458. GUID guid = { 0 };
  459. const expr_t *expr;
  460. index_name = new_index_name();
  461. other_name = new_index_name();
  462. expr = get_attrp(type->attrs, ATTR_HELPCONTEXT);
  463. if (expr) helpcontext = expr->cval;
  464. p = get_attrp(type->attrs, ATTR_UUID);
  465. if (p) guid = *(GUID *)p;
  466. size = sizeof(short) * 8 + 10 /* index_name */ * 2 + sizeof(int) + sizeof(GUID);
  467. block = xmalloc(size);
  468. p = block;
  469. *p++ = strlen(index_name);
  470. strcpy((char *)p, index_name);
  471. p = (short *)((char *)p + strlen(index_name));
  472. *p++ = strlen(other_name);
  473. strcpy((char *)p, other_name);
  474. p = (short *)((char *)p + strlen(other_name));
  475. *p++ = -1; /* res1a */
  476. *p++ = add_name(typelib, type->name); /* name offset */
  477. *p++ = 0; /* FIXME: helpstring */
  478. *p++ = -1; /* res20 */
  479. *(int *)p = helpcontext;
  480. p += 2;
  481. *p++ = -1; /* res26 */
  482. *(GUID *)p = guid;
  483. p += sizeof(GUID)/2;
  484. *p = kind;
  485. sltg_add_typeinfo(typelib, block, size, index_name);
  486. return index_name;
  487. }
  488. static void init_typeinfo(struct sltg_typeinfo_header *ti, const type_t *type, int kind,
  489. const struct sltg_hrefmap *hrefmap)
  490. {
  491. ti->magic = 0x0501;
  492. ti->href_offset = -1;
  493. ti->res06 = -1;
  494. ti->res0e = -1;
  495. ti->version = get_attrv(type->attrs, ATTR_VERSION);
  496. ti->res16 = 0xfffe0000;
  497. ti->misc.unknown1 = 0x02;
  498. ti->misc.flags = 0; /* FIXME */
  499. ti->misc.unknown2 = 0x02;
  500. ti->misc.typekind = kind;
  501. ti->res1e = 0;
  502. ti->member_offset = sizeof(*ti);
  503. if (hrefmap->href_count)
  504. {
  505. char name[64];
  506. int i, hrefinfo_size;
  507. hrefinfo_size = sizeof(struct sltg_hrefinfo);
  508. for (i = 0; i < hrefmap->href_count; i++)
  509. {
  510. sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]);
  511. hrefinfo_size += 8 + 2 + strlen(name);
  512. }
  513. ti->href_offset = ti->member_offset;
  514. ti->member_offset += hrefinfo_size;
  515. }
  516. }
  517. static void init_sltg_tail(struct sltg_tail *tail)
  518. {
  519. tail->cFuncs = 0;
  520. tail->cVars = 0;
  521. tail->cImplTypes = 0;
  522. tail->res06 = 0;
  523. tail->funcs_off = -1;
  524. tail->vars_off = -1;
  525. tail->impls_off = -1;
  526. tail->funcs_bytes = -1;
  527. tail->vars_bytes = -1;
  528. tail->impls_bytes = -1;
  529. tail->tdescalias_vt = -1;
  530. tail->res16 = -1;
  531. tail->res18 = 0;
  532. tail->res1a = 0;
  533. tail->simple_alias = 0;
  534. tail->res1e = 0;
  535. tail->cbSizeInstance = 0;
  536. tail->cbAlignment = 4;
  537. tail->res24 = -1;
  538. tail->res26 = -1;
  539. tail->cbSizeVft = 0;
  540. tail->res2a = -1;
  541. tail->res2c = -1;
  542. tail->res2e = -1;
  543. tail->res30 = -1;
  544. tail->res32 = 0;
  545. tail->type_bytes = 0;
  546. }
  547. static void write_hrefmap(struct sltg_data *data, const struct sltg_hrefmap *hrefmap)
  548. {
  549. struct sltg_hrefinfo hrefinfo;
  550. char name[64];
  551. int i;
  552. if (!hrefmap->href_count) return;
  553. hrefinfo.magic = 0xdf;
  554. hrefinfo.res01 = 0;
  555. hrefinfo.res02 = -1;
  556. hrefinfo.res06 = -1;
  557. hrefinfo.res0a = -1;
  558. hrefinfo.res0e = -1;
  559. hrefinfo.res12 = -1;
  560. hrefinfo.res16 = -1;
  561. hrefinfo.res1a = -1;
  562. hrefinfo.res1e = -1;
  563. hrefinfo.res22 = -1;
  564. hrefinfo.res26 = -1;
  565. hrefinfo.res2a = -1;
  566. hrefinfo.res2e = -1;
  567. hrefinfo.res32 = -1;
  568. hrefinfo.res36 = -1;
  569. hrefinfo.res3a = -1;
  570. hrefinfo.res3e = -1;
  571. hrefinfo.res42 = -1;
  572. hrefinfo.number = hrefmap->href_count * 8;
  573. hrefinfo.res50 = -1;
  574. hrefinfo.res52 = 1;
  575. hrefinfo.res53 = 0;
  576. hrefinfo.resxx = 0xdf;
  577. append_data(data, &hrefinfo, offsetof(struct sltg_hrefinfo, res50));
  578. for (i = 0; i < hrefmap->href_count; i++)
  579. append_data(data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8);
  580. append_data(data, &hrefinfo.res50, 7);
  581. for (i = 0; i < hrefmap->href_count; i++)
  582. {
  583. short len;
  584. sprintf(name, "*\\Rffff*#%x", hrefmap->href[i]);
  585. len = strlen(name);
  586. append_data(data, &len, sizeof(len));
  587. append_data(data, name, len);
  588. }
  589. append_data(data, &hrefinfo.resxx, sizeof(hrefinfo.resxx));
  590. }
  591. static void dump_var_desc(const char *data, int size)
  592. {
  593. const unsigned char *p = (const unsigned char *)data;
  594. int i;
  595. if (!(debuglevel & (DEBUGLEVEL_TRACE | DEBUGLEVEL_CHAT))) return;
  596. chat("dump_var_desc: size %d bytes\n", size);
  597. for (i = 0; i < size; i++)
  598. fprintf(stderr, " %02x", *p++);
  599. fprintf(stderr, "\n");
  600. }
  601. static int get_element_size(type_t *type)
  602. {
  603. int vt = get_type_vt(type);
  604. switch (vt)
  605. {
  606. case VT_I1:
  607. case VT_UI1:
  608. return 1;
  609. case VT_INT:
  610. case VT_UINT:
  611. return /* typelib_kind == SYS_WIN16 ? 2 : */ 4;
  612. case VT_UI2:
  613. case VT_I2:
  614. case VT_BOOL:
  615. return 2;
  616. case VT_I4:
  617. case VT_UI4:
  618. case VT_R4:
  619. case VT_ERROR:
  620. case VT_HRESULT:
  621. return 4;
  622. case VT_R8:
  623. case VT_I8:
  624. case VT_UI8:
  625. case VT_CY:
  626. case VT_DATE:
  627. return 8;
  628. case VT_DECIMAL:
  629. return 16;
  630. case VT_PTR:
  631. case VT_UNKNOWN:
  632. case VT_DISPATCH:
  633. case VT_BSTR:
  634. case VT_LPSTR:
  635. case VT_LPWSTR:
  636. return pointer_size;
  637. case VT_VOID:
  638. return 0;
  639. case VT_VARIANT:
  640. return pointer_size == 8 ? 24 : 16;
  641. case VT_USERDEFINED:
  642. return 0;
  643. default:
  644. error("get_element_size: unrecognized vt %d\n", vt);
  645. break;
  646. }
  647. return 0;
  648. }
  649. static int local_href(struct sltg_hrefmap *hrefmap, int typelib_href)
  650. {
  651. int i, href = -1;
  652. for (i = 0; i < hrefmap->href_count; i++)
  653. {
  654. if (hrefmap->href[i] == typelib_href)
  655. {
  656. href = i;
  657. break;
  658. }
  659. }
  660. if (href == -1)
  661. {
  662. href = hrefmap->href_count;
  663. if (hrefmap->href)
  664. hrefmap->href = xrealloc(hrefmap->href, sizeof(*hrefmap->href) * (hrefmap->href_count + 1));
  665. else
  666. hrefmap->href = xmalloc(sizeof(*hrefmap->href));
  667. hrefmap->href[hrefmap->href_count] = typelib_href;
  668. hrefmap->href_count++;
  669. }
  670. chat("typelib href %d mapped to local href %d\n", typelib_href, href);
  671. return href << 2;
  672. }
  673. static short write_var_desc(struct sltg_typelib *typelib, struct sltg_data *data, type_t *type, short param_flags,
  674. short flags, short base_offset, int *size_instance, struct sltg_hrefmap *hrefmap)
  675. {
  676. short vt, vt_flags, desc_offset;
  677. chat("write_var_desc: type %p, type->name %s\n",
  678. type, type->name ? type->name : "NULL");
  679. if (is_array(type) && !type_array_is_decl_as_ptr(type))
  680. {
  681. int num_dims, elements, array_start, size, array_size;
  682. type_t *atype;
  683. struct
  684. {
  685. short cDims;
  686. short fFeatures;
  687. int cbElements;
  688. int cLocks;
  689. void *pvData;
  690. int bound[2];
  691. } *array;
  692. int *bound;
  693. short vt_off[2];
  694. elements = 1;
  695. num_dims = 0;
  696. atype = type;
  697. while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
  698. {
  699. num_dims++;
  700. elements *= type_array_get_dim(atype);
  701. atype = type_array_get_element_type(atype);
  702. }
  703. chat("write_var_desc: VT_CARRAY: %d dimensions, %d elements\n", num_dims, elements);
  704. array_start = data->size;
  705. size = sizeof(*array) + (num_dims - 1) * 8 /* sizeof(SAFEARRAYBOUND) */;
  706. array = xmalloc(size);
  707. array->cDims = num_dims;
  708. array->fFeatures = 0x0004; /* FADF_EMBEDDED */
  709. array->cbElements = get_element_size(atype);
  710. array->cLocks = 0;
  711. array->pvData = NULL;
  712. bound = array->bound;
  713. array_size = array->cbElements;
  714. atype = type;
  715. while (is_array(atype) && !type_array_is_decl_as_ptr(atype))
  716. {
  717. bound[0] = type_array_get_dim(atype);
  718. array_size *= bound[0];
  719. bound[1] = 0;
  720. bound += 2;
  721. atype = type_array_get_element_type(atype);
  722. }
  723. if (size_instance)
  724. {
  725. *size_instance += array_size;
  726. size_instance = NULL; /* don't account for element size */
  727. }
  728. append_data(data, array, size);
  729. desc_offset = data->size;
  730. vt_off[0] = VT_CARRAY;
  731. vt_off[1] = array_start + base_offset;
  732. append_data(data, vt_off, sizeof(vt_off));
  733. /* fall through to write array element description */
  734. type = atype;
  735. }
  736. else
  737. desc_offset = data->size;
  738. vt = get_type_vt(type);
  739. if (vt == VT_PTR)
  740. {
  741. type_t *ref = is_ptr(type) ? type_pointer_get_ref_type(type) : type_array_get_element_type(type);
  742. if (is_ptr(ref))
  743. {
  744. chat("write_var_desc: vt VT_PTR | 0x0400 | %04x\n", param_flags);
  745. vt = VT_PTR | 0x0400 | param_flags;
  746. append_data(data, &vt, sizeof(vt));
  747. write_var_desc(typelib, data, ref, 0, 0, base_offset, size_instance, hrefmap);
  748. }
  749. else
  750. write_var_desc(typelib, data, ref, param_flags, 0x0e00, base_offset, size_instance, hrefmap);
  751. return desc_offset;
  752. }
  753. chat("write_var_desc: vt %d, flags %04x\n", vt, flags);
  754. vt_flags = vt | flags | param_flags;
  755. append_data(data, &vt_flags, sizeof(vt_flags));
  756. if (vt == VT_USERDEFINED)
  757. {
  758. short href;
  759. while (type->typelib_idx < 0 && type_is_alias(type))
  760. type = type_alias_get_aliasee_type(type);
  761. chat("write_var_desc: VT_USERDEFINED, type %p, name %s, real type %d, href %d\n",
  762. type, type->name, type_get_type(type), type->typelib_idx);
  763. if (type->typelib_idx == -1)
  764. {
  765. chat("write_var_desc: trying to ref not added type\n");
  766. switch (type_get_type(type))
  767. {
  768. case TYPE_STRUCT:
  769. add_structure_typeinfo(typelib, type);
  770. break;
  771. case TYPE_INTERFACE:
  772. add_interface_typeinfo(typelib, type);
  773. break;
  774. case TYPE_ENUM:
  775. add_enum_typeinfo(typelib, type);
  776. break;
  777. case TYPE_UNION:
  778. add_union_typeinfo(typelib, type);
  779. break;
  780. case TYPE_COCLASS:
  781. add_coclass_typeinfo(typelib, type);
  782. break;
  783. default:
  784. error("write_var_desc: VT_USERDEFINED - unhandled type %d\n",
  785. type_get_type(type));
  786. }
  787. }
  788. if (type->typelib_idx == -1)
  789. error("write_var_desc: trying to ref not added type\n");
  790. href = local_href(hrefmap, type->typelib_idx);
  791. chat("write_var_desc: VT_USERDEFINED, local href %d\n", href);
  792. append_data(data, &href, sizeof(href));
  793. }
  794. if (size_instance)
  795. *size_instance += get_element_size(type);
  796. return desc_offset;
  797. }
  798. static void add_structure_typeinfo(struct sltg_typelib *typelib, type_t *type)
  799. {
  800. struct sltg_data data, *var_data = NULL;
  801. struct sltg_hrefmap hrefmap;
  802. const char *index_name;
  803. struct sltg_typeinfo_header ti;
  804. struct sltg_member_header member;
  805. struct sltg_tail tail;
  806. int member_offset, var_count = 0, var_data_size = 0, size_instance = 0;
  807. short *type_desc_offset = NULL;
  808. if (type->typelib_idx != -1) return;
  809. chat("add_structure_typeinfo: type %p, type->name %s\n", type, type->name);
  810. type->typelib_idx = typelib->n_file_blocks;
  811. hrefmap.href_count = 0;
  812. hrefmap.href = NULL;
  813. if (type_struct_get_fields(type))
  814. {
  815. int i = 0;
  816. var_t *var;
  817. var_count = list_count(type_struct_get_fields(type));
  818. var_data = xmalloc(var_count * sizeof(*var_data));
  819. type_desc_offset = xmalloc(var_count * sizeof(*type_desc_offset));
  820. LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
  821. {
  822. short base_offset;
  823. chat("add_structure_typeinfo: var %p (%s), type %p (%s)\n",
  824. var, var->name, var->declspec.type, var->declspec.type->name);
  825. init_sltg_data(&var_data[i]);
  826. base_offset = var_data_size + (i + 1) * sizeof(struct sltg_variable);
  827. type_desc_offset[i] = write_var_desc(typelib, &var_data[i], var->declspec.type, 0, 0,
  828. base_offset, &size_instance, &hrefmap);
  829. dump_var_desc(var_data[i].data, var_data[i].size);
  830. if (var_data[i].size > sizeof(short))
  831. var_data_size += var_data[i].size;
  832. i++;
  833. }
  834. }
  835. init_sltg_data(&data);
  836. index_name = add_typeinfo_block(typelib, type, TKIND_RECORD);
  837. init_typeinfo(&ti, type, TKIND_RECORD, &hrefmap);
  838. append_data(&data, &ti, sizeof(ti));
  839. write_hrefmap(&data, &hrefmap);
  840. member_offset = data.size;
  841. member.res00 = 0x0001;
  842. member.res02 = 0xffff;
  843. member.res04 = 0x01;
  844. member.extra = var_data_size + var_count * sizeof(struct sltg_variable);
  845. append_data(&data, &member, sizeof(member));
  846. var_data_size = 0;
  847. if (type_struct_get_fields(type))
  848. {
  849. int i = 0;
  850. short next = member_offset;
  851. var_t *var;
  852. LIST_FOR_EACH_ENTRY(var, type_struct_get_fields(type), var_t, entry)
  853. {
  854. struct sltg_variable variable;
  855. next += sizeof(variable);
  856. variable.magic = 0x2a; /* always write flags to simplify calculations */
  857. variable.name = add_name(typelib, var->name);
  858. variable.byte_offs = 0;
  859. if (var_data[i].size > sizeof(short))
  860. {
  861. variable.flags = 0;
  862. var_data_size = next - member_offset + type_desc_offset[i];
  863. variable.type = var_data_size;
  864. next += var_data[i].size;
  865. }
  866. else
  867. {
  868. variable.flags = 0x02;
  869. variable.type = *(short *)var_data[i].data;
  870. }
  871. variable.next = i < var_count - 1 ? next - member_offset : -1;
  872. variable.memid = 0x40000000 + i;
  873. variable.helpcontext = -2; /* 0xfffe */
  874. variable.helpstring = -1;
  875. variable.varflags = 0;
  876. append_data(&data, &variable, sizeof(variable));
  877. if (var_data[i].size > sizeof(short))
  878. append_data(&data, var_data[i].data, var_data[i].size);
  879. i++;
  880. }
  881. }
  882. init_sltg_tail(&tail);
  883. tail.cVars = var_count;
  884. tail.vars_off = 0;
  885. tail.vars_bytes = var_data_size;
  886. tail.cbSizeInstance = size_instance;
  887. tail.type_bytes = data.size - member_offset - sizeof(member);
  888. append_data(&data, &tail, sizeof(tail));
  889. add_block(typelib, data.data, data.size, index_name);
  890. }
  891. static importinfo_t *find_importinfo(typelib_t *typelib, const char *name)
  892. {
  893. importlib_t *importlib;
  894. LIST_FOR_EACH_ENTRY(importlib, &typelib->importlibs, importlib_t, entry)
  895. {
  896. int i;
  897. for (i = 0; i < importlib->ntypeinfos; i++)
  898. {
  899. if (!strcmp(name, importlib->importinfos[i].name))
  900. {
  901. chat("Found %s in importlib list\n", name);
  902. return &importlib->importinfos[i];
  903. }
  904. }
  905. }
  906. return NULL;
  907. }
  908. static int get_func_flags(const var_t *func, int *dispid, int *invokekind, int *helpcontext, const char **helpstring)
  909. {
  910. const attr_t *attr;
  911. int flags;
  912. *invokekind = 1 /* INVOKE_FUNC */;
  913. *helpcontext = -2;
  914. *helpstring = NULL;
  915. if (!func->attrs) return 0;
  916. flags = 0;
  917. LIST_FOR_EACH_ENTRY(attr, func->attrs, const attr_t, entry)
  918. {
  919. expr_t *expr = attr->u.pval;
  920. switch(attr->type)
  921. {
  922. case ATTR_BINDABLE:
  923. flags |= 0x4; /* FUNCFLAG_FBINDABLE */
  924. break;
  925. case ATTR_DEFAULTBIND:
  926. flags |= 0x20; /* FUNCFLAG_FDEFAULTBIND */
  927. break;
  928. case ATTR_DEFAULTCOLLELEM:
  929. flags |= 0x100; /* FUNCFLAG_FDEFAULTCOLLELEM */
  930. break;
  931. case ATTR_DISPLAYBIND:
  932. flags |= 0x10; /* FUNCFLAG_FDISPLAYBIND */
  933. break;
  934. case ATTR_HELPCONTEXT:
  935. *helpcontext = expr->u.lval;
  936. break;
  937. case ATTR_HELPSTRING:
  938. *helpstring = attr->u.pval;
  939. break;
  940. case ATTR_HIDDEN:
  941. flags |= 0x40; /* FUNCFLAG_FHIDDEN */
  942. break;
  943. case ATTR_ID:
  944. *dispid = expr->cval;
  945. break;
  946. case ATTR_IMMEDIATEBIND:
  947. flags |= 0x1000; /* FUNCFLAG_FIMMEDIATEBIND */
  948. break;
  949. case ATTR_NONBROWSABLE:
  950. flags |= 0x400; /* FUNCFLAG_FNONBROWSABLE */
  951. break;
  952. case ATTR_PROPGET:
  953. *invokekind = 0x2; /* INVOKE_PROPERTYGET */
  954. break;
  955. case ATTR_PROPPUT:
  956. *invokekind = 0x4; /* INVOKE_PROPERTYPUT */
  957. break;
  958. case ATTR_PROPPUTREF:
  959. *invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */
  960. break;
  961. /* FIXME: FUNCFLAG_FREPLACEABLE */
  962. case ATTR_REQUESTEDIT:
  963. flags |= 0x8; /* FUNCFLAG_FREQUESTEDIT */
  964. break;
  965. case ATTR_RESTRICTED:
  966. flags |= 0x1; /* FUNCFLAG_FRESTRICTED */
  967. break;
  968. case ATTR_SOURCE:
  969. flags |= 0x2; /* FUNCFLAG_FSOURCE */
  970. break;
  971. case ATTR_UIDEFAULT:
  972. flags |= 0x200; /* FUNCFLAG_FUIDEFAULT */
  973. break;
  974. case ATTR_USESGETLASTERROR:
  975. flags |= 0x80; /* FUNCFLAG_FUSESGETLASTERROR */
  976. break;
  977. default:
  978. break;
  979. }
  980. }
  981. return flags;
  982. }
  983. static int get_param_flags(const var_t *param)
  984. {
  985. const attr_t *attr;
  986. int flags, in, out;
  987. if (!param->attrs) return 0;
  988. flags = 0;
  989. in = out = 0;
  990. LIST_FOR_EACH_ENTRY(attr, param->attrs, const attr_t, entry)
  991. {
  992. switch(attr->type)
  993. {
  994. case ATTR_IN:
  995. in++;
  996. break;
  997. case ATTR_OUT:
  998. out++;
  999. break;
  1000. case ATTR_PARAMLCID:
  1001. flags |= 0x2000;
  1002. break;
  1003. case ATTR_RETVAL:
  1004. flags |= 0x80;
  1005. break;
  1006. default:
  1007. chat("unhandled param attr %d\n", attr->type);
  1008. break;
  1009. }
  1010. }
  1011. if (out)
  1012. {
  1013. if (in)
  1014. flags |= 0x8000;
  1015. else
  1016. flags |= 0x4000;
  1017. }
  1018. else if (!in)
  1019. flags |= 0xc000;
  1020. return flags;
  1021. }
  1022. static int add_func_desc(struct sltg_typelib *typelib, struct sltg_data *data, var_t *func,
  1023. int idx, int dispid, short base_offset, struct sltg_hrefmap *hrefmap)
  1024. {
  1025. struct sltg_data ret_data, *arg_data;
  1026. int arg_count = 0, arg_data_size, optional = 0, defaults = 0, old_size;
  1027. int funcflags = 0, invokekind = 1 /* INVOKE_FUNC */, helpcontext;
  1028. const char *helpstring;
  1029. const var_t *arg;
  1030. short ret_desc_offset, *arg_desc_offset, arg_offset;
  1031. struct sltg_function func_desc;
  1032. chat("add_func_desc: %s, idx %#x, dispid %#x\n", func->name, idx, dispid);
  1033. old_size = data->size;
  1034. init_sltg_data(&ret_data);
  1035. ret_desc_offset = write_var_desc(typelib, &ret_data, type_function_get_rettype(func->declspec.type),
  1036. 0, 0, base_offset, NULL, hrefmap);
  1037. dump_var_desc(ret_data.data, ret_data.size);
  1038. arg_data_size = 0;
  1039. arg_offset = base_offset + sizeof(struct sltg_function);
  1040. if (ret_data.size > sizeof(short))
  1041. {
  1042. arg_data_size += ret_data.size;
  1043. arg_offset += ret_data.size;
  1044. }
  1045. if (type_function_get_args(func->declspec.type))
  1046. {
  1047. int i = 0;
  1048. arg_count = list_count(type_function_get_args(func->declspec.type));
  1049. arg_data = xmalloc(arg_count * sizeof(*arg_data));
  1050. arg_desc_offset = xmalloc(arg_count * sizeof(*arg_desc_offset));
  1051. arg_offset += arg_count * 2 * sizeof(short);
  1052. LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry)
  1053. {
  1054. const attr_t *attr;
  1055. short param_flags = get_param_flags(arg);
  1056. chat("add_func_desc: arg[%d] %p (%s), type %p (%s)\n",
  1057. i, arg, arg->name, arg->declspec.type, arg->declspec.type->name);
  1058. init_sltg_data(&arg_data[i]);
  1059. arg_desc_offset[i] = write_var_desc(typelib, &arg_data[i], arg->declspec.type, param_flags, 0,
  1060. arg_offset, NULL, hrefmap);
  1061. dump_var_desc(arg_data[i].data, arg_data[i].size);
  1062. if (arg_data[i].size > sizeof(short))
  1063. {
  1064. arg_data_size += arg_data[i].size;
  1065. arg_offset += arg_data[i].size;;
  1066. }
  1067. i++;
  1068. if (!arg->attrs) continue;
  1069. LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry)
  1070. {
  1071. if (attr->type == ATTR_DEFAULTVALUE)
  1072. defaults++;
  1073. else if(attr->type == ATTR_OPTIONAL)
  1074. optional++;
  1075. }
  1076. }
  1077. }
  1078. funcflags = get_func_flags(func, &dispid, &invokekind, &helpcontext, &helpstring);
  1079. if (base_offset != -1)
  1080. chat("add_func_desc: flags %#x, dispid %#x, invokekind %d, helpcontext %#x, helpstring %s\n",
  1081. funcflags, dispid, invokekind, helpcontext, helpstring);
  1082. func_desc.magic = 0x6c; /* always write flags to simplify calculations */
  1083. func_desc.flags = (invokekind << 4) | 0x02;
  1084. if (idx & 0x80000000)
  1085. {
  1086. func_desc.next = -1;
  1087. idx &= ~0x80000000;
  1088. }
  1089. else
  1090. func_desc.next = base_offset + sizeof(func_desc) + arg_data_size + arg_count * 2 * sizeof(short);
  1091. func_desc.name = base_offset != -1 ? add_name(typelib, func->name) : -1;
  1092. func_desc.dispid = dispid;
  1093. func_desc.helpcontext = helpcontext;
  1094. func_desc.helpstring = (helpstring && base_offset != -1) ? add_name(typelib, helpstring) : -1;
  1095. func_desc.arg_off = arg_count ? base_offset + sizeof(func_desc) : -1;
  1096. func_desc.nacc = (arg_count << 3) | 4 /* CC_STDCALL */;
  1097. func_desc.retnextopt = (optional << 1);
  1098. if (ret_data.size > sizeof(short))
  1099. {
  1100. func_desc.rettype = base_offset + sizeof(func_desc) + ret_desc_offset;
  1101. if (arg_count)
  1102. func_desc.arg_off += ret_data.size;
  1103. }
  1104. else
  1105. {
  1106. func_desc.retnextopt |= 0x80;
  1107. func_desc.rettype = *(short *)ret_data.data;
  1108. }
  1109. func_desc.vtblpos = idx * pointer_size;
  1110. func_desc.funcflags = funcflags;
  1111. append_data(data, &func_desc, sizeof(func_desc));
  1112. arg_offset = base_offset + sizeof(struct sltg_function);
  1113. if (ret_data.size > sizeof(short))
  1114. {
  1115. append_data(data, ret_data.data, ret_data.size);
  1116. func_desc.arg_off += ret_data.size;
  1117. arg_offset += ret_data.size;
  1118. }
  1119. if (arg_count)
  1120. {
  1121. int i = 0;
  1122. arg_offset += arg_count * 2 * sizeof(short);
  1123. LIST_FOR_EACH_ENTRY(arg, type_function_get_args(func->declspec.type), const var_t, entry)
  1124. {
  1125. short name, type_offset;
  1126. name = base_offset != -1 ? add_name(typelib, arg->name) : -1;
  1127. if (arg_data[i].size > sizeof(short))
  1128. {
  1129. type_offset = (arg_offset + arg_desc_offset[i]);
  1130. arg_offset += arg_data[i].size;
  1131. }
  1132. else
  1133. {
  1134. name |= 1;
  1135. type_offset = *(short *)arg_data[i].data;
  1136. }
  1137. append_data(data, &name, sizeof(name));
  1138. append_data(data, &type_offset, sizeof(type_offset));
  1139. if (base_offset != -1)
  1140. chat("add_func_desc: arg[%d] - name %s (%#x), type_offset %#x\n",
  1141. i, arg->name, name, type_offset);
  1142. i++;
  1143. }
  1144. for (i = 0; i < arg_count; i++)
  1145. {
  1146. if (arg_data[i].size > sizeof(short))
  1147. append_data(data, arg_data[i].data, arg_data[i].size);
  1148. }
  1149. }
  1150. return data->size - old_size;
  1151. }
  1152. static void write_impl_href(struct sltg_data *data, short href)
  1153. {
  1154. struct sltg_impl_info impl_info;
  1155. impl_info.res00 = 0x004a;
  1156. impl_info.next = -1;
  1157. impl_info.res04 = -1;
  1158. impl_info.impltypeflags = 0;
  1159. impl_info.res07 = 0x80;
  1160. impl_info.res08 = 0x0012;
  1161. impl_info.ref = href;
  1162. impl_info.res0c = 0x4001;
  1163. impl_info.res0e = -2; /* 0xfffe */
  1164. impl_info.res10 = -1;
  1165. impl_info.res12 = 0x001d;
  1166. impl_info.pos = 0;
  1167. append_data(data, &impl_info, sizeof(impl_info));
  1168. }
  1169. static void add_interface_typeinfo(struct sltg_typelib *typelib, type_t *iface)
  1170. {
  1171. const statement_t *stmt_func;
  1172. importinfo_t *ref_importinfo = NULL;
  1173. short inherit_href = -1;
  1174. struct sltg_data data;
  1175. struct sltg_hrefmap hrefmap;
  1176. const char *index_name;
  1177. struct sltg_typeinfo_header ti;
  1178. struct sltg_member_header member;
  1179. struct sltg_tail tail;
  1180. int member_offset, base_offset, func_data_size, i;
  1181. int func_count, inherited_func_count = 0;
  1182. int dispid, inherit_level = 0;
  1183. if (iface->typelib_idx != -1) return;
  1184. chat("add_interface_typeinfo: type %p, type->name %s\n", iface, iface->name);
  1185. if (!iface->details.iface)
  1186. {
  1187. error("interface %s is referenced but not defined\n", iface->name);
  1188. return;
  1189. }
  1190. if (is_attr(iface->attrs, ATTR_DISPINTERFACE))
  1191. {
  1192. error("support for dispinterface %s is not implemented\n", iface->name);
  1193. return;
  1194. }
  1195. hrefmap.href_count = 0;
  1196. hrefmap.href = NULL;
  1197. if (type_iface_get_inherit(iface))
  1198. {
  1199. type_t *inherit;
  1200. inherit = type_iface_get_inherit(iface);
  1201. chat("add_interface_typeinfo: inheriting from base interface %s\n", inherit->name);
  1202. ref_importinfo = find_importinfo(typelib->typelib, inherit->name);
  1203. if (!ref_importinfo && type_iface_get_inherit(inherit))
  1204. add_interface_typeinfo(typelib, inherit);
  1205. if (ref_importinfo)
  1206. error("support for imported interfaces is not implemented\n");
  1207. inherit_href = local_href(&hrefmap, inherit->typelib_idx);
  1208. while (inherit)
  1209. {
  1210. inherit_level++;
  1211. inherited_func_count += list_count(type_iface_get_stmts(inherit));
  1212. inherit = type_iface_get_inherit(inherit);
  1213. }
  1214. }
  1215. /* check typelib_idx again, it could have been added while resolving the parent interface */
  1216. if (iface->typelib_idx != -1) return;
  1217. iface->typelib_idx = typelib->n_file_blocks;
  1218. /* pass 1: calculate function descriptions data size */
  1219. init_sltg_data(&data);
  1220. STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
  1221. {
  1222. add_func_desc(typelib, &data, stmt_func->u.var, -1, -1, -1, &hrefmap);
  1223. }
  1224. func_data_size = data.size;
  1225. /* pass 2: write function descriptions */
  1226. init_sltg_data(&data);
  1227. func_count = list_count(type_iface_get_stmts(iface));
  1228. index_name = add_typeinfo_block(typelib, iface, TKIND_INTERFACE);
  1229. init_typeinfo(&ti, iface, TKIND_INTERFACE, &hrefmap);
  1230. append_data(&data, &ti, sizeof(ti));
  1231. write_hrefmap(&data, &hrefmap);
  1232. member_offset = data.size;
  1233. base_offset = 0;
  1234. member.res00 = 0x0001;
  1235. member.res02 = 0xffff;
  1236. member.res04 = 0x01;
  1237. member.extra = func_data_size;
  1238. if (inherit_href != -1)
  1239. {
  1240. member.extra += sizeof(struct sltg_impl_info);
  1241. base_offset += sizeof(struct sltg_impl_info);
  1242. }
  1243. append_data(&data, &member, sizeof(member));
  1244. if (inherit_href != -1)
  1245. write_impl_href(&data, inherit_href);
  1246. i = 0;
  1247. dispid = 0x60000000 | (inherit_level << 16);
  1248. STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
  1249. {
  1250. int idx = inherited_func_count + i;
  1251. if (i == func_count - 1) idx |= 0x80000000;
  1252. base_offset += add_func_desc(typelib, &data, stmt_func->u.var,
  1253. idx, dispid + i, base_offset, &hrefmap);
  1254. i++;
  1255. }
  1256. init_sltg_tail(&tail);
  1257. tail.cFuncs = func_count;
  1258. tail.funcs_off = 0;
  1259. tail.funcs_bytes = func_data_size;
  1260. tail.cbSizeInstance = pointer_size;
  1261. tail.cbAlignment = pointer_size;
  1262. tail.cbSizeVft = (inherited_func_count + func_count) * pointer_size;
  1263. tail.type_bytes = data.size - member_offset - sizeof(member);
  1264. tail.res24 = 0;
  1265. tail.res26 = 0;
  1266. if (inherit_href != -1)
  1267. {
  1268. tail.cImplTypes++;
  1269. tail.impls_off = 0;
  1270. tail.impls_bytes = 0;
  1271. tail.funcs_off += sizeof(struct sltg_impl_info);
  1272. }
  1273. append_data(&data, &tail, sizeof(tail));
  1274. add_block(typelib, data.data, data.size, index_name);
  1275. }
  1276. static void add_enum_typeinfo(struct sltg_typelib *typelib, type_t *type)
  1277. {
  1278. error("add_enum_typeinfo: %s not implemented\n", type->name);
  1279. }
  1280. static void add_union_typeinfo(struct sltg_typelib *typelib, type_t *type)
  1281. {
  1282. error("add_union_typeinfo: %s not implemented\n", type->name);
  1283. }
  1284. static void add_coclass_typeinfo(struct sltg_typelib *typelib, type_t *type)
  1285. {
  1286. error("add_coclass_typeinfo: %s not implemented\n", type->name);
  1287. }
  1288. static void add_type_typeinfo(struct sltg_typelib *typelib, type_t *type)
  1289. {
  1290. chat("add_type_typeinfo: adding %s, type %d\n", type->name, type_get_type(type));
  1291. switch (type_get_type(type))
  1292. {
  1293. case TYPE_INTERFACE:
  1294. add_interface_typeinfo(typelib, type);
  1295. break;
  1296. case TYPE_STRUCT:
  1297. add_structure_typeinfo(typelib, type);
  1298. break;
  1299. case TYPE_ENUM:
  1300. add_enum_typeinfo(typelib, type);
  1301. break;
  1302. case TYPE_UNION:
  1303. add_union_typeinfo(typelib, type);
  1304. break;
  1305. case TYPE_COCLASS:
  1306. add_coclass_typeinfo(typelib, type);
  1307. break;
  1308. case TYPE_BASIC:
  1309. case TYPE_POINTER:
  1310. break;
  1311. default:
  1312. error("add_type_typeinfo: unhandled type %d for %s\n", type_get_type(type), type->name);
  1313. break;
  1314. }
  1315. }
  1316. static void add_statement(struct sltg_typelib *typelib, const statement_t *stmt)
  1317. {
  1318. switch(stmt->type)
  1319. {
  1320. case STMT_LIBRARY:
  1321. case STMT_IMPORT:
  1322. case STMT_PRAGMA:
  1323. case STMT_CPPQUOTE:
  1324. case STMT_DECLARATION:
  1325. /* not included in typelib */
  1326. break;
  1327. case STMT_IMPORTLIB:
  1328. /* not processed here */
  1329. break;
  1330. case STMT_TYPEDEF:
  1331. {
  1332. const type_list_t *type_entry = stmt->u.type_list;
  1333. for (; type_entry; type_entry = type_entry->next)
  1334. {
  1335. /* in old style typelibs all types are public */
  1336. add_type_typeinfo(typelib, type_entry->type);
  1337. }
  1338. break;
  1339. }
  1340. case STMT_MODULE:
  1341. add_module_typeinfo(typelib, stmt->u.type);
  1342. break;
  1343. case STMT_TYPE:
  1344. case STMT_TYPEREF:
  1345. {
  1346. type_t *type = stmt->u.type;
  1347. add_type_typeinfo(typelib, type);
  1348. break;
  1349. }
  1350. default:
  1351. error("add_statement: unhandled statement type %d\n", stmt->type);
  1352. break;
  1353. }
  1354. }
  1355. static void sltg_write_header(struct sltg_typelib *sltg, int *library_block_start)
  1356. {
  1357. char pad[0x40];
  1358. struct sltg_header
  1359. {
  1360. int magic;
  1361. short n_file_blocks;
  1362. short res06;
  1363. short size_of_index;
  1364. short first_blk;
  1365. GUID uuid;
  1366. int res1c;
  1367. int res20;
  1368. } header;
  1369. struct sltg_block_entry
  1370. {
  1371. int length;
  1372. short index_string;
  1373. short next;
  1374. } entry;
  1375. struct sltg_block *block;
  1376. int i;
  1377. header.magic = 0x47544c53;
  1378. header.n_file_blocks = sltg->n_file_blocks + 1;
  1379. header.res06 = 9;
  1380. header.size_of_index = sltg->index.size;
  1381. header.first_blk = 1;
  1382. header.uuid = sltg_library_guid;
  1383. header.res1c = 0x00000044;
  1384. header.res20 = 0xffff0000;
  1385. put_data(&header, sizeof(header));
  1386. block = sltg->blocks;
  1387. for (i = 0; i < sltg->n_file_blocks - 1; i++)
  1388. {
  1389. assert(block->next != NULL);
  1390. entry.length = block->length;
  1391. entry.index_string = block->index_string;
  1392. entry.next = header.first_blk + i + 1;
  1393. chat("sltg_write_header: writing block entry %d: length %#x, index_string %#x, next %#x\n",
  1394. i, entry.length, entry.index_string, entry.next);
  1395. put_data(&entry, sizeof(entry));
  1396. block = block->next;
  1397. }
  1398. assert(block->next == NULL);
  1399. /* library block length includes helpstrings and name table */
  1400. entry.length = block->length + 0x40 + 2 + sltg->typeinfo_size + 4 + 6 + 12 + 0x200 + sltg->name_table.size + 12;
  1401. entry.index_string = block->index_string;
  1402. entry.next = 0;
  1403. chat("sltg_write_header: writing library block entry %d: length %#x, index_string %#x, next %#x\n",
  1404. i, entry.length, entry.index_string, entry.next);
  1405. put_data(&entry, sizeof(entry));
  1406. chat("sltg_write_header: writing index: %d bytes\n", sltg->index.size);
  1407. put_data(sltg->index.data, sltg->index.size);
  1408. memset(pad, 0, 9);
  1409. put_data(pad, 9);
  1410. block = sltg->blocks;
  1411. for (i = 0; i < sltg->n_file_blocks - 1; i++)
  1412. {
  1413. chat("sltg_write_header: writing block %d: %d bytes\n", i, block->length);
  1414. put_data(block->data, block->length);
  1415. block = block->next;
  1416. }
  1417. assert(block->next == NULL);
  1418. /* library block */
  1419. chat("library_block_start = %#lx\n", (SIZE_T)output_buffer_pos);
  1420. *library_block_start = output_buffer_pos;
  1421. chat("sltg_write_header: writing library block %d: %d bytes\n", i, block->length);
  1422. put_data(block->data, block->length);
  1423. chat("sltg_write_header: writing pad 0x40 bytes\n");
  1424. memset(pad, 0xff, 0x40);
  1425. put_data(pad, 0x40);
  1426. }
  1427. static void sltg_write_typeinfo(struct sltg_typelib *typelib)
  1428. {
  1429. int i;
  1430. struct sltg_block *block;
  1431. short count = typelib->typeinfo_count;
  1432. put_data(&count, sizeof(count));
  1433. block = typelib->typeinfo;
  1434. for (i = 0; i < typelib->typeinfo_count; i++)
  1435. {
  1436. chat("sltg_write_typeinfo: writing block %d: %d bytes\n", i, block->length);
  1437. put_data(block->data, block->length);
  1438. block = block->next;
  1439. }
  1440. assert(block == NULL);
  1441. }
  1442. static void sltg_write_helpstrings(struct sltg_typelib *typelib)
  1443. {
  1444. static const char dummy[6];
  1445. chat("sltg_write_helpstrings: writing dummy 6 bytes\n");
  1446. put_data(dummy, sizeof(dummy));
  1447. }
  1448. static void sltg_write_nametable(struct sltg_typelib *typelib)
  1449. {
  1450. static const short dummy[6] = { 0xffff,1,2,0xff00,0xffff,0xffff };
  1451. char pad[0x200];
  1452. chat("sltg_write_nametable: writing 12+0x200+%d bytes\n", typelib->name_table.size);
  1453. put_data(dummy, sizeof(dummy));
  1454. memset(pad, 0xff, 0x200);
  1455. put_data(pad, 0x200);
  1456. put_data(&typelib->name_table.size, sizeof(typelib->name_table.size));
  1457. put_data(typelib->name_table.data, typelib->name_table.size);
  1458. }
  1459. static void sltg_write_remainder(void)
  1460. {
  1461. static const short dummy1[] = { 1,0xfffe,0x0a03,0,0xffff,0xffff };
  1462. static const short dummy2[] = { 0xffff,0xffff,0x0200,0,0,0 };
  1463. static const char dummy3[] = { 0xf4,0x39,0xb2,0x71,0,0,0,0,0,0,0,0,0,0,0,0 };
  1464. static const char TYPELIB[] = { 8,0,0,0,'T','Y','P','E','L','I','B',0 };
  1465. int pad;
  1466. pad = 0x01ffff01;
  1467. put_data(&pad, sizeof(pad));
  1468. pad = 0;
  1469. put_data(&pad, sizeof(pad));
  1470. put_data(dummy1, sizeof(dummy1));
  1471. put_data(&sltg_library_guid, sizeof(sltg_library_guid));
  1472. put_data(TYPELIB, sizeof(TYPELIB));
  1473. put_data(dummy2, sizeof(dummy2));
  1474. put_data(dummy3, sizeof(dummy3));
  1475. }
  1476. static void save_all_changes(struct sltg_typelib *typelib)
  1477. {
  1478. int library_block_start;
  1479. int *name_table_offset;
  1480. sltg_write_header(typelib, &library_block_start);
  1481. sltg_write_typeinfo(typelib);
  1482. name_table_offset = (int *)(output_buffer + output_buffer_pos);
  1483. chat("name_table_offset = %#lx\n", (SIZE_T)output_buffer_pos);
  1484. put_data(&library_block_start, sizeof(library_block_start));
  1485. sltg_write_helpstrings(typelib);
  1486. *name_table_offset = output_buffer_pos - library_block_start;
  1487. chat("*name_table_offset = %#x\n", *name_table_offset);
  1488. sltg_write_nametable(typelib);
  1489. sltg_write_remainder();
  1490. if (strendswith(typelib_name, ".res")) /* create a binary resource file */
  1491. {
  1492. char typelib_id[13] = "#1";
  1493. expr_t *expr = get_attrp(typelib->typelib->attrs, ATTR_ID);
  1494. if (expr)
  1495. sprintf(typelib_id, "#%d", expr->cval);
  1496. add_output_to_resources("TYPELIB", typelib_id);
  1497. output_typelib_regscript(typelib->typelib);
  1498. }
  1499. else flush_output_buffer(typelib_name);
  1500. }
  1501. int create_sltg_typelib(typelib_t *typelib)
  1502. {
  1503. struct sltg_typelib sltg;
  1504. const statement_t *stmt;
  1505. void *library_block;
  1506. int library_block_size, library_block_index;
  1507. sltg.typelib = typelib;
  1508. sltg.typeinfo_count = 0;
  1509. sltg.typeinfo_size = 0;
  1510. sltg.typeinfo = NULL;
  1511. sltg.blocks = NULL;
  1512. sltg.n_file_blocks = 0;
  1513. sltg.first_block = 1;
  1514. init_index(&sltg.index);
  1515. init_name_table(&sltg);
  1516. init_library(&sltg);
  1517. library_block = create_library_block(&sltg, &library_block_size, &library_block_index);
  1518. if (typelib->stmts)
  1519. LIST_FOR_EACH_ENTRY(stmt, typelib->stmts, const statement_t, entry)
  1520. add_statement(&sltg, stmt);
  1521. add_block_index(&sltg, library_block, library_block_size, library_block_index);
  1522. save_all_changes(&sltg);
  1523. return 1;
  1524. }