|  | /* | 
|  | genidl - Generate interface defintion language listing from a | 
|  | Portable Executable. | 
|  | Copyright (C) 2009-2016  mingw-w64 project | 
|  |  | 
|  | This program is free software: you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation, either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  | */ | 
|  |  | 
|  | #define _CRT_SECURE_NO_WARNINGS | 
|  | #include "genidl_cfg.h" | 
|  | #include "genidl_typeinfo.h" | 
|  | #include "genidl_typinfo.h" | 
|  | #include <malloc.h> | 
|  | #include <string.h> | 
|  | #include <memory.h> | 
|  |  | 
|  | int32_t | 
|  | TI_init_typs (sTITyps *ptyp) | 
|  | { | 
|  | if (!ptyp) | 
|  | return -1; | 
|  | memset (ptyp, 0, sizeof (sTITyps)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI_dest_typs (sTITyps *ptyp) | 
|  | { | 
|  | size_t i; | 
|  | int32_t j; | 
|  | if (!ptyp) | 
|  | return -1; | 
|  | for (j=0;j<TITYP_MAX;j++) | 
|  | { | 
|  | if (ptyp->buc[j].arr != NULL) | 
|  | { | 
|  | for (i = 0; i < ptyp->buc[j].count; i++) | 
|  | { | 
|  | if (ptyp->buc[j].arr[i]->refstr) | 
|  | free (ptyp->buc[j].arr[i]->refstr); | 
|  | if (ptyp->buc[j].arr[i]->poststr) | 
|  | free (ptyp->buc[j].arr[i]->poststr); | 
|  | free (ptyp->buc[j].arr[i]); | 
|  | } | 
|  | free (ptyp->buc[j].arr); | 
|  | } | 
|  | } | 
|  | memset (ptyp, 0, sizeof (sTITyps)); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t TI_add_typ (sTITyps *ptyp, uint32_t memid, int32_t kind, int32_t refkind, uint32_t refmem, | 
|  | const char *refstr, const char *name, const char *poststr) | 
|  | { | 
|  | sTITyp *t, **h; | 
|  | if (TI_get_typ (ptyp, memid, kind) != NULL || kind >= TITYP_MAX) | 
|  | return -1; | 
|  | if (!name) | 
|  | name = ""; | 
|  | if (!refstr) | 
|  | refstr=""; | 
|  | if (!poststr) | 
|  | poststr = ""; | 
|  | if (ptyp->buc[kind].count >= ptyp->buc[kind].max) | 
|  | { | 
|  | h = (sTITyp **) malloc (sizeof (sTITyp *) * (ptyp->buc[kind].count + 32)); | 
|  | if (ptyp->buc[kind].arr) | 
|  | { | 
|  | memcpy (h, ptyp->buc[kind].arr, sizeof (sTITyp*) * ptyp->buc[kind].count); | 
|  | free (ptyp->buc[kind].arr); | 
|  | } | 
|  | ptyp->buc[kind].arr = h; | 
|  | ptyp->buc[kind].max += 32; | 
|  | } | 
|  | t = (sTITyp *) malloc (sizeof (sTITyp) + strlen (name)); | 
|  | t->memid = memid; | 
|  | t->kind = kind; | 
|  | t->refkind = refkind; | 
|  | t->refmem = refmem; | 
|  | t->refstr = strdup (refstr); | 
|  | t->poststr = strdup (poststr); | 
|  | strcpy (t->name, name); | 
|  | ptyp->buc[kind].arr[ptyp->buc[kind].count] = t; | 
|  | ptyp->buc[kind].count += 1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | sTITyp * | 
|  | TI_get_typ (sTITyps *ptyp, uint32_t memid, int32_t kind) | 
|  | { | 
|  | size_t i; | 
|  | if (!ptyp || kind < 0 || kind >= TITYP_MAX) | 
|  | return NULL; | 
|  | for (i = 0; i < ptyp->buc[kind].count; i++) | 
|  | { | 
|  | if (ptyp->buc[kind].arr[i]->kind == kind && ptyp->buc[kind].arr[i]->memid == memid) | 
|  | return ptyp->buc[kind].arr[i]; | 
|  | } | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | static char * | 
|  | ti_cat (const char *t, const char *r) | 
|  | { | 
|  | char *ret; | 
|  | size_t l; | 
|  | if (!t) | 
|  | t = ""; | 
|  | if (!r) | 
|  | r = ""; | 
|  | l = strlen (t) + strlen (r) +1; | 
|  | ret = (char *) malloc (l); | 
|  | strcpy (ret, t); | 
|  | strcat (ret, r); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static char * | 
|  | ti_cat_freel (char *t, const char *r) | 
|  | { | 
|  | char *ret = ti_cat (t, r); | 
|  | if (t) | 
|  | free (t); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static int32_t | 
|  | end_isref (const char *ret) | 
|  | { | 
|  | if (!ret || *ret == 0) | 
|  | return 1; | 
|  | ret += strlen (ret); | 
|  | if (ret[-1] == '&' || ret[-1] == '*' || ret[-1] == ']') | 
|  | return 1; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | char * | 
|  | TI_get_typ_name (sTITyps *ptyp, uint32_t memid, int32_t kind, const char *varName) | 
|  | { | 
|  | static const char *szKind[TITYP_MAX] = { | 
|  | "Name_", "Str_", "Guid_", "TypeB_", "TypeD_", "Arr_", "Ref_", "Imp_", | 
|  | "Unknown_", "CD_", "CDGuid_", "ImpR_" | 
|  | }; | 
|  | sTITyp *t = TI_get_typ (ptyp, memid, kind); | 
|  | char s[128]; | 
|  | char *ret; | 
|  |  | 
|  | if (!t) | 
|  | { | 
|  | sprintf (s, "%s%x",szKind[kind],memid); | 
|  | ret = strdup (s); | 
|  | } | 
|  | else if (t->name[0] == 0) | 
|  | { | 
|  | ret = TI_get_typ_name (ptyp, t->refmem, t->refkind, ""); | 
|  | } | 
|  | else | 
|  | ret = strdup (t->name); | 
|  | if (t && t->refstr != NULL && t->refstr[0] != 0) | 
|  | { | 
|  | if (!end_isref (ret)) | 
|  | ret = ti_cat_freel (ret, " "); | 
|  | ret = ti_cat_freel (ret, t->refstr); | 
|  | } | 
|  | if (varName != NULL && varName[0] != 0) | 
|  | { | 
|  | char *hl = strchr (ret, '['); | 
|  | char *ar = NULL; | 
|  | if (hl) | 
|  | { | 
|  | ar = strdup (hl); | 
|  | *hl = 0; | 
|  | } | 
|  | if (!end_isref (ret)) | 
|  | ret = ti_cat_freel (ret, " "); | 
|  | ret = ti_cat_freel (ret, varName); | 
|  | if (ar) | 
|  | { | 
|  | ret = ti_cat_freel (ret, ar); | 
|  | free (ar); | 
|  | } | 
|  | } | 
|  | if (t && t->poststr != NULL && t->poststr[0] != 0) | 
|  | { | 
|  | if (!end_isref (ret) && t->poststr[0] != '[') | 
|  | ret = ti_cat_freel (ret, " "); | 
|  | ret = ti_cat_freel (ret, t->poststr); | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_name (sTITyps *nptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | struct sMSFTNamePrologue { | 
|  | int32_t res1; | 
|  | int32_t res2; | 
|  | #ifdef __GNUC__ | 
|  | __extension__ | 
|  | #endif | 
|  | union { | 
|  | unsigned char v[4]; | 
|  | uint16_t us[2]; | 
|  | }; | 
|  | }; | 
|  | #ifdef __GNUC__ | 
|  | __extension__ | 
|  | #endif | 
|  | union { | 
|  | unsigned char *dta; | 
|  | struct sMSFTNamePrologue *p; | 
|  | } v; | 
|  | uint32_t off = 0; | 
|  |  | 
|  | if (!len) | 
|  | return 0; | 
|  | while ((off + 12) <= len) | 
|  | { | 
|  | uint32_t memid = off; | 
|  | unsigned char l; | 
|  | char *name; | 
|  | v.dta = &dta[off]; | 
|  | l = v.p->v[0]; | 
|  |  | 
|  | name = (char *) malloc (l + 1); | 
|  | if (!name) | 
|  | return -1; | 
|  | if (l != 0) | 
|  | memcpy (name, &dta[off + 12], l); | 
|  | name[l] = 0; | 
|  |  | 
|  | if (TI_add_typ (nptr,memid,TITYP_NAME, 0,0,"", name, "") < 0) | 
|  | return -1; | 
|  | free (name); | 
|  | off = (12 + off + (uint32_t) l + 3) & ~3; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_string (sTITyps *sptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | uint32_t off = 0; | 
|  | union { | 
|  | unsigned char *dta; | 
|  | unsigned short *len; | 
|  | } v; | 
|  |  | 
|  | if (!len) | 
|  | return 0; | 
|  |  | 
|  | while ((off + 2) <= len) | 
|  | { | 
|  | char *h; | 
|  | v.dta = &dta[off]; | 
|  | h = (char *) malloc (v.len[0] + 1); | 
|  | memcpy (h, &dta[off + 2], v.len[0]); | 
|  | h[v.len[0]]=0; | 
|  | if (TI_add_typ (sptr, off, TITYP_STR, 0, 0, "", h, "") < 0) | 
|  | return -1; | 
|  | free (h); | 
|  | off += 2 + (uint32_t) v.len[0]; | 
|  | off = (off + 3) & ~3; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_guid (sTITyps *gptr, unsigned char *dta, uint32_t length) | 
|  | { | 
|  | struct sGuidTab { | 
|  | uint32_t data1; | 
|  | uint16_t data2[2]; | 
|  | unsigned char data3[8]; | 
|  | int32_t res1; | 
|  | int32_t res2; /* Forwarder GUID */ | 
|  | }; | 
|  |  | 
|  | char str[260]; | 
|  | uint32_t off = 0; | 
|  | union { | 
|  | unsigned char *d; | 
|  | struct sGuidTab *g; | 
|  | } v; | 
|  | if (!length) | 
|  | return -1; | 
|  | while ((off + 24) <= length) | 
|  | { | 
|  | v.d = &dta[off]; | 
|  | sprintf (str ,"\"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\"", | 
|  | v.g->data1, v.g->data2[0], v.g->data2[1], | 
|  | v.g->data3[0],v.g->data3[1],v.g->data3[2],v.g->data3[3], | 
|  | v.g->data3[4],v.g->data3[5],v.g->data3[6],v.g->data3[7]); | 
|  | TI_add_typ (gptr, (uint32_t) off, TITYP_GUIDS, 0, 0, "", str, ""); | 
|  | off += 24; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_typinfo_names (sTITyps *tptr, unsigned char *dta, uint32_t length) | 
|  | { | 
|  | char name_unk[32]; | 
|  | char prefix_unk[32]; | 
|  | char *h; | 
|  | char *name; | 
|  | const char *prefix; | 
|  | sMSFT_TypeInfoBase *t = (sMSFT_TypeInfoBase *) dta; | 
|  | int32_t i; | 
|  | int32_t free_name; | 
|  | uint32_t off = 0; | 
|  |  | 
|  | if (!length) | 
|  | return 0; | 
|  | i = 0; | 
|  | while ((off + sizeof (sMSFT_TypeInfoBase)) <= length) | 
|  | { | 
|  | free_name = 1; | 
|  | name = TI_get_typ_name (tptr, (uint32_t) t[i].NameOffset, TITYP_NAME,""); | 
|  | prefix = ""; | 
|  | if (!name) | 
|  | { | 
|  | free_name = 0; | 
|  | sprintf (name_unk,"Name_%0x", t[i].NameOffset); | 
|  | name = &name_unk[0]; | 
|  | } | 
|  | switch (t[i].typekind & 0xf) | 
|  | { | 
|  | case TKIND_ENUM: prefix = "enum "; break; | 
|  | case TKIND_RECORD: prefix = "struct "; break; | 
|  | case TKIND_MODULE: prefix = "module "; break; | 
|  | case TKIND_INTERFACE: prefix = "interface "; break; | 
|  | case TKIND_DISPATCH: prefix = "dispinterface "; break; | 
|  | case TKIND_COCLASS: prefix = "coclass "; break; | 
|  | case TKIND_ALIAS: break; | 
|  | case TKIND_UNION: prefix = "union "; break; | 
|  | default: | 
|  | prefix = &prefix_unk[0]; | 
|  | sprintf (prefix_unk, "TK_%u ", t[i].typekind&0xf); | 
|  | break; | 
|  | } | 
|  | h = (char *) malloc (strlen (prefix) + strlen (name) + 1); | 
|  | sprintf (h, "%s%s", prefix, name); | 
|  | TI_add_typ (tptr, (uint32_t) off, TITYP_TYPINFO_NAMES, 0,0, "", h, ""); | 
|  | free (h); | 
|  | if (free_name) | 
|  | free (name); | 
|  | off += sizeof (sMSFT_TypeInfoBase); | 
|  | i++; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | char * | 
|  | getTypeBOrImpRef (sTITyps *dptr, uint32_t off, const char *var) | 
|  | { | 
|  | if (off == (uint32_t) -1) | 
|  | return NULL; | 
|  | if ((off&1) != 0) | 
|  | return TI_get_typ_name (dptr, off & ~1U,TITYP_IMPREF, var); | 
|  | return TI_get_typ_name (dptr, off, TITYP_TYPINFO_NAMES, var); | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_typedesc (sTITyps *dptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | sMSFT_TypeDesc *p; | 
|  | uint32_t off = 0; | 
|  | if (!len) | 
|  | return -1; | 
|  | while ((off + 7) < len) | 
|  | { | 
|  | p = (sMSFT_TypeDesc *) &dta[off]; | 
|  |  | 
|  | switch ((p->kind)) | 
|  | { | 
|  | case 26: /* VT_PTR */ | 
|  | if ((p->vt & 0x80000000) != 0) | 
|  | { | 
|  | const char *name; | 
|  | name = decode_VT_name_tmp (((uint32_t) (p->vt)) & 0xffff); | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, TITYP_UNKNOWN, | 
|  | (uint32_t) p->oArrayD & 0xffff, | 
|  | ((p->flag & 0x7fff) != 0x7ffe ? "*" : ""), &name[0], ""); | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((p->oTypeB & 1) != 0) | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, | 
|  | TITYP_IMPREF, (uint32_t) p->oTypeB & 0xfffffffe, | 
|  | ((p->flag & 0x7fff) != 0x7ffe ? "*" : ""), "", ""); | 
|  | else | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, | 
|  | TITYP_DEREF, (uint32_t) p->oTypeB, | 
|  | ((p->flag & 0x7fff) != 0x7ffe ? "*" : ""), "", ""); | 
|  | } | 
|  | break; | 
|  | case 27: /* SAFEARRAY */ | 
|  | if ((p->vt & 0x80000000) != 0) | 
|  | { | 
|  | const char *name; | 
|  | name = decode_VT_name_tmp (((uint32_t) (p->vt)) & 0xffff); | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, TITYP_UNKNOWN, | 
|  | (uint32_t) p->oArrayD  & 0xffff, | 
|  | "", &name[0], ((p->flag & 0x7fff) != 0x7ffe ? "[]" : "")); | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((p->oTypeB & 1) != 0) | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, | 
|  | TITYP_IMPREF, (uint32_t) p->oTypeB & 0xfffffffe, | 
|  | "", "", ((p->flag & 0x7fff) != 0x7ffe ? "[]" : "")); | 
|  | else | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, | 
|  | TITYP_DEREF, (uint32_t) p->oTypeB, | 
|  | "", "", ((p->flag & 0x7fff) != 0x7ffe ? "[]" : "")); | 
|  | } | 
|  | break; | 
|  | case 28: /* VT_CARRAY */ | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, TITYP_ARRAY, | 
|  | (uint32_t) p->oArrayD & 0xffff, "", "", ""); | 
|  | break; | 
|  | case 29: /* VT_USERDEFINED */ | 
|  | if ((p->vt & 0x80000000) != 0) | 
|  | { | 
|  | const char *name; | 
|  | name = decode_VT_name_tmp (((uint32_t) (p->vt)) & 0xffff); | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, TITYP_UNKNOWN, | 
|  | (uint32_t) p->oArrayD  & 0xffff, | 
|  | "", &name[0], ""); | 
|  | } | 
|  | else | 
|  | { | 
|  | if ((p->oTypeB & 1) != 0) | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, | 
|  | TITYP_IMPREF, (uint32_t) p->oTypeB & 0xfffffffe, | 
|  | "", "", ""); | 
|  | else | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, | 
|  | TITYP_TYPINFO_NAMES, (uint32_t) p->oTypeB, | 
|  | "", "", ""); | 
|  | } | 
|  | break; | 
|  | default: | 
|  | { | 
|  | const char *name; | 
|  | const char *prefix = ""; | 
|  | name = decode_VT_name_tmp (((uint32_t) (p->vt)) & 0xffff); | 
|  | if ((p->flag & 0xf000) == 0x4000) | 
|  | prefix = "*"; | 
|  | TI_add_typ (dptr, (uint32_t) off, TITYP_DEREF, TITYP_UNKNOWN, | 
|  | (uint32_t) p->oArrayD, prefix, &name[0], ""); | 
|  | } | 
|  | break; | 
|  | } | 
|  | off += 8; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_customdata (sTITyps *dptr, unsigned char *dta, uint32_t length) | 
|  | { | 
|  | sMSFT_CustomData *p; | 
|  | uint32_t off = 0; | 
|  | if (!length) | 
|  | return 0; | 
|  | while (off < length) | 
|  | { | 
|  | uint32_t soff = off; | 
|  | char *s; | 
|  | s = NULL; | 
|  | p = (sMSFT_CustomData *) &dta[off]; | 
|  | off += getVT_data (dptr, p->vt, p->dta, &s); | 
|  | TI_add_typ (dptr,soff,TITYP_CUSTOMDATA,0,0,"",s,""); | 
|  | if(s) free (s); | 
|  | off = (off + 3) & ~3; | 
|  | //fprintf (fp, "\n"); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | size_t | 
|  | getVT_data (sTITyps *dptr, uint32_t vt, unsigned char *dta, char **ret) | 
|  | { | 
|  | char s[4096]; | 
|  | size_t b, l, sz; | 
|  | if (dptr) | 
|  | sz = 0; | 
|  | l = getVT_size (vt, dta,&b); | 
|  | dta += b - 2; | 
|  | if (l == 0xffffffff) | 
|  | { | 
|  | if (vt == 8) | 
|  | sprintf (s, "L\"\""); | 
|  | else { | 
|  | fprintf (stderr, "vt: 0x%x with size of -1!!!\n", vt); | 
|  | sprintf (s, "vt:0x%x_zero", vt); | 
|  | } | 
|  | if (ret) | 
|  | *ret = strdup (s); | 
|  | return b; | 
|  | } | 
|  | sz = l; | 
|  | s[0] = 0; | 
|  |  | 
|  | switch (vt) { | 
|  | case 16: /* VT_I1 */ sprintf (s,"(char) %d", *((char *) dta)); break; | 
|  | case 17: /* VT_UI1 */ sprintf (s,"(unsigned char) %u", *((unsigned char *) dta)); break; | 
|  | case 18: /* VT_UI2 */ sprintf (s,"(USHORT) %u", *((uint16_t *) dta)); break; | 
|  | case 23: /* VT_UINT */ | 
|  | case 19: /* VT_UI4 */ sprintf (s,"(UINT) %uU", *((uint32_t *) dta)); break; | 
|  | case 20: /* VT_I8 */ | 
|  | #ifdef _WIN32 | 
|  | sprintf (s,"(LONGLONG) %I64dLL", *((int64_t *) dta)); break; | 
|  | #else | 
|  | sprintf (s,"(LONGLONG) %lldLL", *((int64_t *) dta)); break; | 
|  | #endif | 
|  | case 21: /* VT_UI8 */ | 
|  | #ifdef _WIN32 | 
|  | sprintf (s,"(ULONGLONG) %I64uULL", *((uint64_t *) dta)); break; | 
|  | #else | 
|  | sprintf (s,"(ULONGLONG) %lluULL", *((uint64_t *) dta)); break; | 
|  | #endif | 
|  | case 10: /* VT_ERROR */ sprintf (s, " = (SCODE) %dL", *((int32_t *) dta)); break; | 
|  | case 11: /* VT_BOOL */ sprintf (s,"(WINBOOL) %d", *((int16_t *) dta)); break; | 
|  | case 2: /* VT_I2 */ sprintf (s,"(short) %d", *((int16_t *) dta)); break; | 
|  | case 22: /* VT_INT */ | 
|  | case 3: /* VT_I4 */ sprintf (s,"(int) %d", *((int32_t *) dta)); break; | 
|  | case 4: /* VT_R4 */ sprintf (s,"(float) %f", *((float *) dta)); break; | 
|  | case 5: /* VT_R8 */ sprintf (s,"(double) %g", *((double *) dta)); break; | 
|  | case 6: /* VT_CY */ | 
|  | #ifdef _WIN32 | 
|  | sprintf (s,"(CY) %I64dLL", *((int64_t *) dta)); break; | 
|  | #else | 
|  | sprintf (s,"(CY) %lldLL", *((int64_t *) dta)); break; | 
|  | #endif | 
|  | case 8: /* VT_BSTR */ | 
|  | sprintf (s,"L\""); | 
|  | while (sz>0 && sz < 4094) | 
|  | { | 
|  | if (strlen (s) >= 4080) | 
|  | { | 
|  | fprintf (stderr, "String too big (%lu)\n", (unsigned long) l); | 
|  | break; | 
|  | } | 
|  | if (*dta >= 0x20 && *dta <= 0x7f) | 
|  | sprintf (&s[strlen(s)], "%c", *dta); | 
|  | else | 
|  | sprintf (&s[strlen(s)],"\\%03o", *dta); | 
|  | dta++; --sz; | 
|  | } | 
|  | sprintf (&s[strlen(s)],"\""); | 
|  | break; | 
|  | case 25: /* VT_HRESULT */ | 
|  | case 26: /* VT_PTR */ | 
|  | sprintf (s,"(HRESULT) 0x%x", *((int32_t *) dta)); break; | 
|  | default: | 
|  | sprintf (s, "(%s) with %u size", decode_VT_name_tmp (vt), (uint32_t) l); | 
|  | break; | 
|  | } | 
|  | if (ret) | 
|  | *ret = strdup (s); | 
|  | return l + b; | 
|  | } | 
|  |  | 
|  | size_t | 
|  | getVT_size (uint32_t vt, unsigned char *dta, size_t *basesz) | 
|  | { | 
|  | size_t ret = 0; | 
|  | size_t bsz = 2; | 
|  |  | 
|  | switch (vt&0xfff) { | 
|  | case 0: /* VT_EMPTY */ break; | 
|  | case 1: /* VT_NULL */ break; | 
|  | case 2: /* VT_I2 */ ret = 2; break; | 
|  | case 3: /* VT_I4 */ ret = 4; break; | 
|  | case 4: /* VT_R4 */ ret = 4; break; | 
|  | case 5: /* VT_R8 */ ret = 8; break; | 
|  | case 6: /* VT_CY */ ret = 16; break; | 
|  | case 7: /* VT_DATE */ ret = 16; break; | 
|  | case 8: /* VT_BSTR */ ret = 0; bsz += 4; break; | 
|  | case 9: /* VT_DISPATCH */ ret = 4; break; | 
|  | case 10: /* VT_ERROR */ ret = 4; break; | 
|  | case 11: /* VT_BOOL */ ret = 2; break; | 
|  | case 12: /* VT_VARIANT */ ret = 0; break; | 
|  | case 13: /* VT_UNKNOWN */ ret = 4; break; | 
|  | case 14: /* VT_DECIMAL */ ret = 16; break; | 
|  | case 16: /* VT_I1 */ ret = 1; break; | 
|  | case 17: /* VT_UI1 */ ret = 1; break; | 
|  | case 18: /* VT_UI2 */ ret = 2; break; | 
|  | case 19: /* VT_UI4 */ ret = 4; break; | 
|  | case 20: /* VT_I8 */ ret = 8; break; | 
|  | case 21: /* VT_UI8 */ ret = 8; break; | 
|  | case 22: /* VT_INT */ ret = 4; break; | 
|  | case 23: /* VT_UINT */ ret = 4; break; | 
|  | case 24: /* VT_VOID */ ret = 0; break; | 
|  | case 25: /* VT_HRESULT */ ret = 4; break; | 
|  | case 26: /* VT_PTR */ ret = 4; break; | 
|  | case 27: /* VT_SAFEARRAY */ ret = 0; bsz+=4; break; | 
|  | case 28: /* VT_CARRAY */ ret = 0; bsz+=4; break; | 
|  | case 29: /* VT_USERDEFINED */ ret = 0; bsz+=4; break; | 
|  | case 30: /* VT_LPSTR */ ret = 4; break; | 
|  | case 31: /* VT_LPWSTR */ ret = 4; break; | 
|  | case 36: /* VT_RECORD */  ret = 0; bsz+=4; break; | 
|  | case 37: /* VT_INT_PTR */ ret = 4; break; | 
|  | case 38: /* VT_UINT_PTR */ ret = 4; break; | 
|  | case 64: /* VT_FILETIME */ ret = 8; break; | 
|  | case 65: /* VT_BLOB */  ret = 0; bsz+=4; break; | 
|  | case 66: /* VT_STREAM */  ret = 0; bsz+=4; break; | 
|  | case 67: /* VT_STORAGE */  ret = 0; bsz+=4; break; | 
|  | case 68: /* VT_STREAMED_OBJECT */  ret = 0; bsz+=4; break; | 
|  | case 69: /* VT_STORED_OBJECT */  ret = 0; bsz+=4; break; | 
|  | case 70: /* VT_BLOB_OBJECT */  ret = 0; bsz+=4; break; | 
|  | case 71: /* VT_CF*/ ret = 0; bsz+=4; break; | 
|  | case 72: /* VT_CLSID */ ret = 0; bsz+=4; break; | 
|  | case 73: /* VT_VERSIONED_STREAM */ ret = 0; bsz+=4; break; | 
|  | case  0xfff: /* VT_BSTR_BLOB */ ret = 0; bsz+=4; break; | 
|  | default: | 
|  | ret = 0; break; | 
|  | break; | 
|  | } | 
|  | if (bsz>2) | 
|  | { | 
|  | ret = *((uint32_t *) dta); | 
|  | } | 
|  | if (basesz) | 
|  | *basesz = bsz; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | const char * | 
|  | decode_VT_name_tmp (uint16_t vt) | 
|  | { | 
|  | static char str[128]; | 
|  | const char *name = "???"; | 
|  |  | 
|  | switch ((vt&0xfff)) | 
|  | { | 
|  | case 0: /* VT_EMPTY */ name = "EMPTY"; break; | 
|  | case 1: /* VT_NULL */ name = "NULL"; break; | 
|  | case 2: /* VT_I2 */ name = "short"; break; | 
|  | case 3: /* VT_I4 */ name = "long"; break; | 
|  | case 4: /* VT_R4 */ name = "float"; break; | 
|  | case 5: /* VT_R8 */ name = "double"; break; | 
|  | case 6: /* VT_CY */ name = "CY"; break; | 
|  | case 7: /* VT_DATE */ name = "DATE"; break; | 
|  | case 8: /* VT_BSTR */ name = "BSTR"; break; | 
|  | case 9: /* VT_DISPATCH */ name = "IDispatch *"; break; | 
|  | case 10: /* VT_ERROR */ name = "SCODE"; break; | 
|  | case 11: /* VT_BOOL */ name = "WINBOOL"; break; | 
|  | case 12: /* VT_VARIANT */ name = "VARIANT"; break; | 
|  | case 13: /* VT_UNKNOWN */ name = "IUnknown *"; break; | 
|  | case 14: /* VT_DECIMAL */ name = "DECIMAL"; break; | 
|  | case 16: /* VT_I1 */ name = "CHAR"; break; | 
|  | case 17: /* VT_UI1 */ name = "UCHAR"; break; | 
|  | case 18: /* VT_UI2 */ name = "USHORT"; break; | 
|  | case 19: /* VT_UI4 */ name = "UINT"; break; | 
|  | case 20: /* VT_I8 */ name = "LONGLONG"; break; | 
|  | case 21: /* VT_UI8 */ name = "ULONGLONG"; break; | 
|  | case 22: /* VT_INT */ name = "int"; break; | 
|  | case 23: /* VT_UINT */ name = "unsigned int"; break; | 
|  | case 24: /* VT_VOID */ name = "void"; break; | 
|  | case 25: /* VT_HRESULT */ name = "HRESULT"; break; | 
|  | case 26: /* VT_PTR */ name = "PTR"; break; | 
|  | case 27: /* VT_SAFEARRAY */ name = "SAFEARRAY"; break; | 
|  | case 28: /* VT_CARRAY */ name = "CARRAY"; break; | 
|  | case 29: /* VT_USERDEFINED */ name = "USERDEFINED"; break; | 
|  | case 30: /* VT_LPSTR */ name = "LPSTR"; break; | 
|  | case 31: /* VT_LPWSTR */ name = "LPWSTR"; break; | 
|  | case 36: /* VT_RECORD */ name = "RECORD"; break; | 
|  | case 37: /* VT_INT_PTR */ name = "INT_PTR"; break; | 
|  | case 38: /* VT_UINT_PTR */ name = "UINT_PTR"; break; | 
|  | case 64: /* VT_FILETIME */ name = "FILETIME"; break; | 
|  | case 65: /* VT_BLOB */ name = "BLOB"; break; | 
|  | case 66: /* VT_STREAM */ name = "STREAM"; break; | 
|  | case 67: /* VT_STORAGE */ name = "STORAGE"; break; | 
|  | case 68: /* VT_STREAMED_OBJECT */ name = "STREAMED_OBJECT"; break; | 
|  | case 69: /* VT_STORED_OBJECT */ name = "STORED_OBJECT"; break; | 
|  | case 70: /* VT_BLOB_OBJECT */ name = "BLOB_OBJECT"; break; | 
|  | case 71: /* VT_CF*/ name = "CF"; break; | 
|  | case 72: /* VT_CLSID */ name = "CLSID"; break; | 
|  | case 73: /* VT_VERSIONED_STREAM */ name = "VERSIONED_STREAM"; break; | 
|  | case  0xfff: /* VT_BSTR_BLOB */ name = "BSTR_BLOB"; break; | 
|  | default: | 
|  | sprintf (str, "VT_%08x", vt & 0xfff); | 
|  | name = &str[0]; | 
|  | break; | 
|  | } | 
|  | if ((vt & 0xf000) == 0x4000) | 
|  | strcat (str, " *"); | 
|  | return name; | 
|  | } | 
|  |  | 
|  | char * | 
|  | TI_getVTorDref (sTITyps *ptyp,uint32_t vt, const char *varName, int beBase) | 
|  | { | 
|  | char *name; | 
|  | if ((vt & 0x80000000)!=0) | 
|  | { | 
|  | name = strdup (decode_VT_name_tmp (vt)); | 
|  | if (varName != NULL && varName[0] != 0) | 
|  | { | 
|  | name = ti_cat_freel (name, " "); | 
|  | name = ti_cat_freel (name, varName); | 
|  | } | 
|  | } | 
|  | else if ((vt&1)!=0) | 
|  | name = TI_get_typ_name (ptyp, vt & ~1, TITYP_IMPREF, varName); | 
|  | else if ((vt&3)!=0) | 
|  | name = TI_get_typ_name (ptyp, vt, TITYP_UNKNOWN, varName); | 
|  | else | 
|  | { | 
|  | if (!beBase) | 
|  | name = TI_get_typ_name (ptyp, vt, TITYP_DEREF, varName); | 
|  | else | 
|  | name = TI_get_typ_name (ptyp, vt, TITYP_TYPINFO_NAMES, varName); | 
|  | } | 
|  | return name; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_importlibs (sTITyps *iptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | sMSFT_ImpFiles *p; | 
|  | uint32_t off = 0; | 
|  | if (!len) | 
|  | return 0; | 
|  | while ((off + 13) < len) | 
|  | { | 
|  | char *h; | 
|  | unsigned short l; | 
|  | p = (sMSFT_ImpFiles *) &dta[off]; | 
|  | l = (p->flag >> 2); | 
|  | h = (char *) malloc (l + 1); | 
|  | memcpy (h, &dta[off + 14], l); | 
|  | h[l] = 0; | 
|  | genidl_strlwr (h); | 
|  | TI_add_typ (iptr, (uint32_t) off, TITYP_IMP, 0,0,"",h,""); | 
|  | off = (off + 14 + l + 3) & ~3; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_ref (sTITyps *gptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | sMSFT_RefTab *p; | 
|  | uint32_t off = 0; | 
|  | if (!len) | 
|  | return 0; | 
|  | while ((off + 15) < len) | 
|  | { | 
|  | char *h; | 
|  | p = (sMSFT_RefTab *) & dta[off]; | 
|  | h = getTypeBOrImpRef (gptr, (uint32_t) p->oData1, ""); | 
|  | TI_add_typ (gptr, (uint32_t) off, TITYP_REF, p->data2, p->oNextRef,"",h,""); | 
|  | free (h); | 
|  | off += sizeof (sMSFT_RefTab); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_array (sTITyps *gptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | char postfix[256]; | 
|  | uint32_t off = 0; | 
|  | sMSFT_ArrayDesc *p; | 
|  | if (!len) | 
|  | return 0; | 
|  | while ((off + 7) < len) | 
|  | { | 
|  | uint32_t num_dims; | 
|  | uint32_t size; | 
|  | char *name = NULL; | 
|  | uint32_t i; | 
|  | p = (sMSFT_ArrayDesc *) &dta[off]; | 
|  | if ((p->vt & 0x80000000) != 0) | 
|  | name = strdup (decode_VT_name_tmp (p->vt)); | 
|  | num_dims = p->count; | 
|  | size = p->size; | 
|  | if (!size) | 
|  | size = (num_dims * 2 * 4); | 
|  | postfix[0] = 0; | 
|  | for (i=0;i < num_dims; i++) | 
|  | { | 
|  | sprintf (&postfix[strlen (postfix)], "[%u]", p->vt_offset[i*2]); | 
|  | } | 
|  | TI_add_typ (gptr, (uint32_t) off, TITYP_ARRAY, TITYP_DEREF, (uint32_t) p->vt,"", | 
|  | (name ? name : ""), postfix); | 
|  | off += 8 + size; | 
|  | off +=3; off &= ~3; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_importref (sTITyps *gptr, unsigned char *dta, uint32_t length) | 
|  | { | 
|  | MSFT_ImpInfo *p; | 
|  | uint32_t off = 0; | 
|  | char *idstr; | 
|  | char *iname; | 
|  | if (!length) | 
|  | return 0; | 
|  | while ((off + 11) < length) | 
|  | { | 
|  | const char *str; | 
|  | char s[128]; | 
|  | p = (MSFT_ImpInfo *) &dta[off]; | 
|  | iname = TI_get_typ_name (gptr, (uint32_t) p->oImpFile, TITYP_IMP, ""); | 
|  |  | 
|  | if ((p->flags & 1) == 0) | 
|  | { | 
|  | sprintf (s, "TypeB_%x", p->oGuid); | 
|  | } | 
|  | else | 
|  | { | 
|  | char *ni = TI_get_typ_name (gptr, (uint32_t) p->oGuid & ~1, TITYP_GUIDS, ""); | 
|  | if (ni) | 
|  | { | 
|  | strcpy (s, ni + 1); | 
|  | if (strrchr (s, '\"') != NULL) | 
|  | *strrchr (s, '\"')=0; | 
|  | free (ni); | 
|  | } | 
|  | else | 
|  | sprintf (s, "Guid_%x", p->oGuid); | 
|  | } | 
|  | str = genidl_find_type (iname, &s[0]); | 
|  | /*if (!str) | 
|  | { | 
|  | sprintf (s, "Name_%x", p->oGuid); | 
|  | str = genidl_find_type (iname, &s[0]); | 
|  | }*/ | 
|  | if (str) | 
|  | { | 
|  | TI_add_typ (gptr, (uint32_t) off, TITYP_IMPREF, 0,0, "", str, ""); | 
|  | } | 
|  | else | 
|  | { | 
|  | idstr = (char *) malloc (strlen (s) + strlen (iname) + 2 + 10); | 
|  | sprintf (idstr, "%s_%s_%02x_%x", iname, s, p->flags, p->tkind); | 
|  | fprintf (stderr, "Type %s count: 0x%x tkind:0x%x not found\n", idstr, p->count, p->tkind); | 
|  | TI_add_typ (gptr, (uint32_t) off, TITYP_IMPREF, 0,0, "", idstr, ""); | 
|  | free (idstr); | 
|  | } | 
|  | if (iname) | 
|  | free (iname); | 
|  | off += 12; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int32_t | 
|  | TI2_import_customdataguid (sTITyps *gptr, unsigned char *dta, uint32_t len) | 
|  | { | 
|  | if (gptr || dta || len) | 
|  | return 0; | 
|  | return 0; | 
|  | } |