| /* | |
| 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; | |
| } |