X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tools%2Fprotoparse.h;h=be6c22311e584fe7ee84d7141803121b829cc794;hb=77d7983adfe3ff5944d26b3af274a15e8af05556;hp=7acd63a82858ab0ac7adc04760bbb117411d83ab;hpb=1fe8d40ebdb232ab6be27af1a3b94a2869cc3779;p=ia32rtools.git diff --git a/tools/protoparse.h b/tools/protoparse.h index 7acd63a..be6c223 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -23,8 +23,9 @@ struct parsed_proto_arg { char *reg; struct parsed_type type; struct parsed_proto *pp; // fptr or struct - void *datap; unsigned int is_saved:1; // not set here, for tool use + void **push_refs; + int push_ref_cnt; }; struct parsed_proto { @@ -33,7 +34,7 @@ struct parsed_proto { struct parsed_type ret_type; struct parsed_type type; }; - struct parsed_proto_arg arg[16]; + struct parsed_proto_arg arg[32]; int argc; int argc_stack; int argc_reg; @@ -216,6 +217,7 @@ static const char *known_ptr_types[] = { "HRSRC", "HKEY", "HMENU", + "HMONITOR", "HWAVEOUT", "HWND", "PAPPBARDATA", @@ -238,6 +240,8 @@ static const char *known_ptr_types[] = { "REFCLSID", "REFGUID", "REFIID", + "SC_HANDLE", + "SERVICE_STATUS_HANDLE", "HOOKPROC", "DLGPROC", "TIMERPROC", @@ -638,6 +642,12 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) return -1; } + if (xarg >= ARRAY_SIZE(pp->arg)) { + printf("%s:%d:%zd: too many args\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + arg = &pp->arg[xarg]; xarg++; @@ -990,22 +1000,43 @@ static inline int pp_cmp_func(const struct parsed_proto *pp1, if (pp1->argc != pp2->argc || pp1->argc_reg != pp2->argc_reg) return 1; - else { - for (i = 0; i < pp1->argc; i++) { - if ((pp1->arg[i].reg != NULL) != (pp2->arg[i].reg != NULL)) - return 1; - - if ((pp1->arg[i].reg != NULL) - && !IS(pp1->arg[i].reg, pp2->arg[i].reg)) - { - return 1; - } + if (pp1->is_stdcall != pp2->is_stdcall) + return 1; + + // because of poor void return detection, return is not + // checked for now to avoid heaps of false positives + + for (i = 0; i < pp1->argc; i++) { + if ((pp1->arg[i].reg != NULL) != (pp2->arg[i].reg != NULL)) + return 1; + + if ((pp1->arg[i].reg != NULL) + && !IS(pp1->arg[i].reg, pp2->arg[i].reg)) + { + return 1; } } return 0; } +static inline int pp_compatible_func( + const struct parsed_proto *pp_site, + const struct parsed_proto *pp_callee) +{ + if (pp_cmp_func(pp_site, pp_callee) == 0) + return 1; + + if (pp_site->argc_stack == 0 && pp_site->is_fastcall + && pp_callee->argc_stack == 0 + && (pp_callee->is_fastcall || pp_callee->argc_reg == 0) + && pp_site->argc_reg > pp_callee->argc_reg) + /* fascall compatible callee doesn't use all args -> ok */ + return 1; + + return 0; +} + static inline void pp_print(char *buf, size_t buf_size, const struct parsed_proto *pp) { @@ -1033,12 +1064,10 @@ static inline void proto_release(struct parsed_proto *pp) int i; for (i = 0; i < pp->argc; i++) { - if (pp->arg[i].reg != NULL) - free(pp->arg[i].reg); - if (pp->arg[i].type.name != NULL) - free(pp->arg[i].type.name); - if (pp->arg[i].pp != NULL) - free(pp->arg[i].pp); + free(pp->arg[i].reg); + free(pp->arg[i].type.name); + free(pp->arg[i].pp); + free(pp->arg[i].push_refs); } if (pp->ret_type.name != NULL) free(pp->ret_type.name);