winapi_function.pm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. #
  2. # Copyright 1999, 2000, 2001 Patrik Stridvall
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Lesser General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2.1 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # Lesser General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Lesser General Public
  15. # License along with this library; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  17. #
  18. package winapi_function;
  19. use strict;
  20. use warnings 'all';
  21. use base qw(function);
  22. use config qw($current_dir $wine_dir);
  23. use util qw(normalize_set);
  24. my $import = 0;
  25. use vars qw($modules $win16api $win32api @winapis);
  26. ########################################################################
  27. # constructor
  28. #
  29. sub new($) {
  30. my $proto = shift;
  31. my $class = ref($proto) || $proto;
  32. my $self = {};
  33. bless ($self, $class);
  34. if (!$import) {
  35. require modules;
  36. import modules qw($modules);
  37. require winapi;
  38. import winapi qw($win16api $win32api @winapis);
  39. $import = 1;
  40. }
  41. return $self;
  42. }
  43. ########################################################################
  44. # is_win
  45. #
  46. sub is_win16($) { my $self = shift; return defined($self->_module($win16api, @_)); }
  47. sub is_win32($) { my $self = shift; return defined($self->_module($win32api, @_)); }
  48. ########################################################################
  49. # external_name
  50. #
  51. sub _external_name($$) {
  52. my $self = shift;
  53. my $winapi = shift;
  54. my $file = $self->file;
  55. my $internal_name = $self->internal_name;
  56. my $external_name = $winapi->function_external_name($internal_name);
  57. my $module = $winapi->function_internal_module($internal_name);
  58. if(!defined($external_name) && !defined($module)) {
  59. return undef;
  60. }
  61. my @external_names = split(/\s*&\s*/, $external_name);
  62. my @modules = split(/\s*&\s*/, $module);
  63. my @external_names2;
  64. while(defined(my $external_name = shift @external_names) &&
  65. defined(my $module = shift @modules))
  66. {
  67. if($modules->is_allowed_module_in_file($module, "$current_dir/$file")) {
  68. push @external_names2, $external_name;
  69. }
  70. }
  71. return join(" & ", @external_names2);
  72. }
  73. sub _external_names($$) {
  74. my $self = shift;
  75. my $winapi = shift;
  76. my $external_name = $self->_external_name($winapi);
  77. if(defined($external_name)) {
  78. return split(/\s*&\s*/, $external_name);
  79. } else {
  80. return ();
  81. }
  82. }
  83. sub external_name($) {
  84. my $self = shift;
  85. foreach my $winapi (@winapis) {
  86. my $external_name = $self->_external_name($winapi, @_);
  87. if(defined($external_name)) {
  88. return $external_name;
  89. }
  90. }
  91. return undef;
  92. }
  93. sub external_name16($) { my $self = shift; return $self->_external_name($win16api, @_); }
  94. sub external_name32($) { my $self = shift; return $self->_external_name($win32api, @_); }
  95. sub external_names16($) { my $self = shift; return $self->_external_names($win16api, @_); }
  96. sub external_names32($) { my $self = shift; return $self->_external_names($win32api, @_); }
  97. sub external_names($) { my $self = shift; return ($self->external_names16, $self->external_names32); }
  98. ########################################################################
  99. # module
  100. #
  101. sub _module($$) {
  102. my $self = shift;
  103. my $winapi = shift;
  104. my $file = $self->file;
  105. my $internal_name = $self->internal_name;
  106. my $module = $winapi->function_internal_module($internal_name);
  107. if(!defined($module)) {
  108. return undef;
  109. }
  110. if(!defined($file)) {
  111. return undef;
  112. }
  113. my @modules;
  114. foreach my $module (split(/\s*&\s*/, $module)) {
  115. if($modules->is_allowed_module_in_file($module, "$current_dir/$file")) {
  116. push @modules, $module;
  117. }
  118. }
  119. return join(" & ", @modules);
  120. }
  121. sub _modules($$) {
  122. my $self = shift;
  123. my $winapi = shift;
  124. my $module = $self->_module($winapi);
  125. if(defined($module)) {
  126. return split(/\s*&\s*/, $module);
  127. } else {
  128. return ();
  129. }
  130. }
  131. sub module16($) { my $self = shift; return $self->_module($win16api, @_); }
  132. sub module32($) { my $self = shift; return $self->_module($win32api, @_); }
  133. sub module($) { my $self = shift; return join (" & ", $self->modules); }
  134. sub modules16($) { my $self = shift; return $self->_modules($win16api, @_); }
  135. sub modules32($) { my $self = shift; return $self->_modules($win32api, @_); }
  136. sub modules($) { my $self = shift; return ($self->modules16, $self->modules32); }
  137. ########################################################################
  138. # ordinal
  139. #
  140. sub _ordinal($$) {
  141. my $self = shift;
  142. my $winapi = shift;
  143. my $file = $self->file;
  144. my $internal_name = $self->internal_name;
  145. my $ordinal = $winapi->function_internal_ordinal($internal_name);
  146. my $module = $winapi->function_internal_module($internal_name);
  147. if(!defined($ordinal) && !defined($module)) {
  148. return undef;
  149. }
  150. my @ordinals = split(/\s*&\s*/, $ordinal);
  151. my @modules = split(/\s*&\s*/, $module);
  152. my @ordinals2;
  153. while(defined(my $ordinal = shift @ordinals) &&
  154. defined(my $module = shift @modules))
  155. {
  156. if($modules->is_allowed_module_in_file($module, "$current_dir/$file")) {
  157. push @ordinals2, $ordinal;
  158. }
  159. }
  160. return join(" & ", @ordinals2);
  161. }
  162. sub _ordinals($$) {
  163. my $self = shift;
  164. my $winapi = shift;
  165. my $ordinal = $self->_ordinal($winapi);
  166. if(defined($ordinal)) {
  167. return split(/\s*&\s*/, $ordinal);
  168. } else {
  169. return ();
  170. }
  171. }
  172. sub ordinal16($) { my $self = shift; return $self->_ordinal($win16api, @_); }
  173. sub ordinal32($) { my $self = shift; return $self->_ordinal($win32api, @_); }
  174. sub ordinal($) { my $self = shift; return join (" & ", $self->ordinals); }
  175. sub ordinals16($) { my $self = shift; return $self->_ordinals($win16api, @_); }
  176. sub ordinals32($) { my $self = shift; return $self->_ordinals($win32api, @_); }
  177. sub ordinals($) { my $self = shift; return ($self->ordinals16, $self->ordinals32); }
  178. ########################################################################
  179. # prefix
  180. #
  181. sub prefix($) {
  182. my $self = shift;
  183. my $module16 = $self->module16;
  184. my $module32 = $self->module32;
  185. my $file = $self->file;
  186. my $function_line = $self->function_line;
  187. my $return_type = $self->return_type;
  188. my $internal_name = $self->internal_name;
  189. my $calling_convention = $self->calling_convention;
  190. my $refargument_types = $self->argument_types;
  191. my @argument_types = ();
  192. if(defined($refargument_types)) {
  193. @argument_types = @$refargument_types;
  194. if($#argument_types < 0) {
  195. @argument_types = ("void");
  196. }
  197. }
  198. my $prefix = "";
  199. my @modules = ();
  200. my %used;
  201. foreach my $module ($self->modules) {
  202. if($used{$module}) { next; }
  203. push @modules, $module;
  204. $used{$module}++;
  205. }
  206. $prefix .= "$file:";
  207. if(defined($function_line)) {
  208. $prefix .= "$function_line: ";
  209. } else {
  210. $prefix .= "<>: ";
  211. }
  212. if($#modules >= 0) {
  213. $prefix .= join(" & ", @modules) . ": ";
  214. } else {
  215. $prefix .= "<>: ";
  216. }
  217. $prefix .= "$return_type ";
  218. $prefix .= "$calling_convention " if $calling_convention;
  219. $prefix .= "$internal_name(" . join(",", @argument_types) . "): ";
  220. return $prefix;
  221. }
  222. ########################################################################
  223. # calling_convention
  224. #
  225. sub calling_convention16($) {
  226. my $self = shift;
  227. my $return_kind16 = $self->return_kind16;
  228. my $suffix;
  229. if(!defined($return_kind16)) {
  230. $suffix = undef;
  231. } elsif($return_kind16 =~ /^(?:void|s_word|word)$/) {
  232. $suffix = "16";
  233. } elsif($return_kind16 =~ /^(?:long|ptr|segptr|segstr|str|wstr)$/) {
  234. $suffix = "";
  235. } else {
  236. $suffix = undef;
  237. }
  238. local $_ = $self->calling_convention;
  239. if($_ eq "__cdecl") {
  240. return "cdecl";
  241. } elsif(/^(?:VFWAPIV|WINAPIV)$/) {
  242. if(!defined($suffix)) { return undef; }
  243. return "pascal$suffix"; # FIXME: Is this correct?
  244. } elsif(/^(?:__stdcall|__RPC_STUB|__RPC_USER|NET_API_FUNCTION|RPC_ENTRY|SEC_ENTRY|VFWAPI|WINGDIPAPI|WMIAPI|WINAPI|CALLBACK)$/) {
  245. if(!defined($suffix)) { return undef; }
  246. return "pascal$suffix";
  247. } elsif($_ eq "__asm") {
  248. return "asm";
  249. } else {
  250. return "cdecl";
  251. }
  252. }
  253. sub calling_convention32($) {
  254. my $self = shift;
  255. local $_ = $self->calling_convention;
  256. if($_ eq "__cdecl") {
  257. return "cdecl";
  258. } elsif(/^(?:VFWAPIV|WINAPIV)$/) {
  259. return "varargs";
  260. } elsif(/^(?:__stdcall|__RPC_STUB|__RPC_USER|NET_API_FUNCTION|RPC_ENTRY|SEC_ENTRY|VFWAPI|WINGDIPAPI|WMIAPI|WINAPI|CALLBACK)$/) {
  261. return "stdcall";
  262. } elsif($_ eq "__asm") {
  263. return "asm";
  264. } else {
  265. return "cdecl";
  266. }
  267. }
  268. sub get_all_module_ordinal16($) {
  269. my $self = shift;
  270. my $internal_name = $self->internal_name;
  271. return winapi::get_all_module_internal_ordinal16($internal_name);
  272. }
  273. sub get_all_module_ordinal32($) {
  274. my $self = shift;
  275. my $internal_name = $self->internal_name;
  276. return winapi::get_all_module_internal_ordinal32($internal_name);
  277. }
  278. sub get_all_module_ordinal($) {
  279. my $self = shift;
  280. my $internal_name = $self->internal_name;
  281. return winapi::get_all_module_internal_ordinal($internal_name);
  282. }
  283. sub _return_kind($$) {
  284. my $self = shift;
  285. my $winapi = shift;
  286. my $return_type = $self->return_type;
  287. return $winapi->translate_argument($return_type);
  288. }
  289. sub return_kind16($) {
  290. my $self = shift; return $self->_return_kind($win16api, @_);
  291. }
  292. sub return_kind32($) {
  293. my $self = shift; return $self->_return_kind($win32api, @_);
  294. }
  295. sub _argument_kinds($$) {
  296. my $self = shift;
  297. my $winapi = shift;
  298. my $refargument_types = $self->argument_types;
  299. if(!defined($refargument_types)) {
  300. return undef;
  301. }
  302. my @argument_kinds;
  303. foreach my $argument_type (@$refargument_types) {
  304. my $argument_kind = $winapi->translate_argument($argument_type);
  305. if(defined($argument_kind) && $argument_kind eq "longlong") {
  306. push @argument_kinds, "double";
  307. } else {
  308. push @argument_kinds, $argument_kind;
  309. }
  310. }
  311. return [@argument_kinds];
  312. }
  313. sub argument_kinds16($) {
  314. my $self = shift; return $self->_argument_kinds($win16api, @_);
  315. }
  316. sub argument_kinds32($) {
  317. my $self = shift; return $self->_argument_kinds($win32api, @_);
  318. }
  319. ##############################################################################
  320. # Accounting
  321. #
  322. sub function_called($$) {
  323. my $self = shift;
  324. my $called_function_names = \%{$self->{CALLED_FUNCTION_NAMES}};
  325. my $name = shift;
  326. $$called_function_names{$name}++;
  327. }
  328. sub function_called_by($$) {
  329. my $self = shift;
  330. my $called_by_function_names = \%{$self->{CALLED_BY_FUNCTION_NAMES}};
  331. my $name = shift;
  332. $$called_by_function_names{$name}++;
  333. }
  334. sub called_function_names($) {
  335. my $self = shift;
  336. my $called_function_names = \%{$self->{CALLED_FUNCTION_NAMES}};
  337. return sort(keys(%$called_function_names));
  338. }
  339. sub called_by_function_names($) {
  340. my $self = shift;
  341. my $called_by_function_names = \%{$self->{CALLED_BY_FUNCTION_NAMES}};
  342. return sort(keys(%$called_by_function_names));
  343. }
  344. 1;