source: trunk/tools/database/APIImport.cpp@ 3114

Last change on this file since 3114 was 2789, checked in by bird, 26 years ago

Bugfixes. Functionnames may be quite long...

File size: 13.1 KB
Line 
1/* $Id: APIImport.cpp,v 1.5 2000-02-15 13:31:05 bird Exp $ */
2/*
3 *
4 * APIImport - imports a DLL or Dll-.def with functions into the Odin32 database.
5 *
6 * Copyright (c) 1999-2000 knut st. osmundsen
7 *
8 */
9
10
11/*******************************************************************************
12* Header Files *
13*******************************************************************************/
14#include <os2.h>
15#include <stdio.h>
16#include <string.h>
17
18#include "APIImport.h"
19#include "kFileFormatBase.h"
20#include "kFilePE.h"
21#include "kFileDef.h"
22#include "db.h"
23
24
25/*******************************************************************************
26* Global Variables *
27*******************************************************************************/
28static FILE *phLog = NULL;
29
30/*******************************************************************************
31* Internal Functions *
32*******************************************************************************/
33static void syntax(void);
34static void openLog(void);
35static void closeLog(void);
36static long processFile(const char *pszFilename, const POPTIONS pOptions, long &cFunctions);
37static void demangle(char *pszDemangled, const char *pszMangledName);
38
39
40/**
41 * Main function.
42 * @returns low word : number of errors
43 * high word: flags.
44 * @param argc Argument count.
45 * @param argv Argument array.
46 */
47int main(int argc, char **argv)
48{
49 int argi;
50 BOOL fFatal = FALSE;
51 long lRc = 0;
52 OPTIONS options = {0};
53 char *pszHost = "localhost";
54 char *pszDatabase = "Odin32";
55 char *pszUser = "root";
56 char *pszPasswd = "";
57 long cFunctions = 0;
58
59
60 /**************************************************************************
61 * parse arguments.
62 * options: -h or -? help
63 * -o[+|-] ordinals, o- ignore them, o+ import them (def).
64 * -d:<dbname> Database name
65 * -p:<passwd> Password
66 * -u:<user> Userid
67 * -h:<host> Hostname/IP-address
68 **************************************************************************/
69 if (argc == 1)
70 syntax();
71 argi = 1;
72 while (argi < argc && !fFatal)
73 {
74 if(argv[argi][0] == '-' || argv[argi][0] == '/')
75 {
76 switch (argv[argi][1])
77 {
78 case 'd':
79 case 'D':
80 if (argv[argi][2] == ':')
81 pszDatabase = &argv[argi][3];
82 else
83 fprintf(stderr, "warning: option '-d:' requires database name.\n");
84 break;
85
86 case 'h':
87 case 'H':
88 if (argv[argi][2] == ':')
89 {
90 pszHost = &argv[argi][3];
91 break;
92 }
93 case '?':
94 syntax();
95 return 0;
96
97 case 'o': /* ordinals*/
98 case 'O':
99 options.fIgnoreOrdinals = argv[argi][2] != '-';
100 break;
101
102 case 'p':
103 case 'P':
104 if (argv[argi][2] == ':')
105 pszPasswd = &argv[argi][3];
106 else
107 fprintf(stderr, "warning: option '-p:' requires password.\n");
108 break;
109
110 case 'u':
111 case 'U':
112 if (argv[argi][2] == ':')
113 pszUser = &argv[argi][3];
114 else
115 fprintf(stderr, "error: option '-u:' requires userid.\n");
116 break;
117
118 default:
119 fprintf(stderr, "incorrect parameter. (argi=%d, argv[argi]=%s)\n", argi, argv[argi]);
120 fFatal = TRUE;
121 break;
122 }
123 }
124 else
125 {
126 long l;
127 if (phLog == NULL)
128 openLog();
129 /* try connect to db */
130 if (dbConnect(pszHost, pszUser, pszPasswd, pszDatabase))
131 {
132 l = processFile(argv[argi], &options, cFunctions);
133 lRc = ((lRc & 0xffff0000UL) | (l & 0xffff0000UL)) | ((lRc & 0x0000ffffUL) + l & 0x0000ffffUL);
134 dbDisconnect();
135 }
136 else
137 {
138 fprintf(phLog, "Could not connect to database (Odin32). \n\terror description: %s\n", dbGetLastErrorDesc());
139 l = 0x00010001;
140 lRc = ((lRc & 0xffff0000UL) | (l & 0xffff0000UL)) | ((lRc & 0x0000ffffUL) + l & 0x0000ffffUL);
141 break;
142 }
143 }
144 argi++;
145 }
146
147 /* write function count */
148 if (phLog != NULL)
149 fprintf(phLog, "\n %d functions were imported!\n\n", cFunctions);
150
151 /* close the log */
152 closeLog();
153
154 /* warn if error during processing. */
155 if (!fFatal && lRc > 0)
156 fprintf(stderr, "%s did occur during the processing. Please check the log file. lRc=0x%08lx\n",
157 (0x0000FFFFL & lRc) > 1 ? "Errors" : "An error", lRc);
158 return (int)lRc;
159}
160
161
162
163/**
164 * Display syntax/help .
165 */
166static void syntax()
167{
168 printf("\n"
169 "APIImport v%01d.%02d - Odin32 API Database utility\n"
170 "----------------------------------------------\n"
171 "syntax: APIImport.exe [-h|-?] [options] <dll/defnames>\n"
172 "\n"
173 " -h or -? Syntax help. (this)\n"
174 " -o[+|-] Ordinals, '+' imports (default), '-' ignores.\n"
175 " -h:<hostname> Database server hostname. default: localhost\n"
176 " -u:<username> Username on the server. default: root\n"
177 " -p:<password> Password. default: <empty>\n"
178 " -d:<database> Database to use. default: Odin32\n"
179 " dll/defnames List of DLL/Defs to process.\n"
180 "\n"
181 "Note. Options may be switched on and off between dlls.\n"
182 "\n"
183 "\n"
184 "This utility will insert or update the 'dll' and 'function' tables in the\n"
185 "database. It read a PE-DLL or a OS/2 Definition file (.Def). From the file\n"
186 "it imports the:\n"
187 "\t1) module name\n"
188 "\t2) function name\n"
189 "\t3) function ordinal (If not option 'o-' is specified.)\n"
190 "This utililty is not destructive but additive. That is, it would not remove any\n"
191 "rows in the database, only add or update them. On existing functions the\n"
192 "ordinal value will be updated when 'o+' is specified.\n"
193 "\n"
194 "Copyright (c) 1999 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)",
195 MAJOR_VER, MINOR_VER
196 );
197}
198
199
200/**
201 * Opens the log file.
202 * @remark If open fails stderr is used.
203 */
204static void openLog(void)
205{
206 if (phLog == NULL)
207 {
208 phLog = fopen("APIImport.Log", "w");
209 if (phLog == NULL)
210 {
211 fprintf(stderr,"error occured while opening log file - will use stderr instead.\n");
212 phLog = stderr;
213 }
214 }
215}
216
217
218/**
219 * Closes log file.
220 */
221static void closeLog(void)
222{
223 if (phLog != stderr && phLog != NULL)
224 fclose(phLog);
225}
226
227
228/**
229 * Processes a file using the given options. Transparently processes .Def's and PE DLLs
230 * @returns low word, number of errors.
231 * high word, flags (currently not flags are defined/used).
232 * @param pszFilename Pointer to the filename of the file which is to be processed.
233 * @param pOptions Pointer to the options-struct.
234 * @param cFunctions Function count which is to be updated when functions are imported.
235 */
236static long processFile(const char *pszFilename, const POPTIONS pOptions, long &cFunctions)
237{
238 kFileFormatBase *pFile;
239 FILE *phFile;
240 long lRc = 1;
241
242 /* try open file */
243 phFile = fopen(pszFilename, "rb");
244 if (phFile != NULL)
245 {
246 try
247 {
248 char achDataBuffer[0x200];
249 char *pszModuleName = &achDataBuffer[0];
250 signed short sDll;
251
252 /* try create file objects */
253 try
254 {
255 pFile = new kFilePE(phFile);
256 }
257 catch (int i)
258 {
259 i = i;
260 pFile = new kFileDef(phFile);
261 }
262
263 if (pFile->queryModuleName(pszModuleName))
264 {
265 int cch = strlen(pszModuleName);
266
267 /* remove '.dll' */
268 if (cch > 4 && !stricmp(&pszModuleName[cch-4], ".dll"))
269 pszModuleName[cch-4] = '\0';
270 fprintf(phLog, "%s: modulename = %s\n", pszFilename, pszModuleName);
271
272 /* find or insert module name */
273 if ((sDll = dbCheckInsertDll(pszModuleName)) >= 0)
274 {
275 BOOL fOk;
276 EXPORTENTRY export;
277
278 lRc = 0;
279 fOk = pFile->findFirstExport(&export);
280 while (fOk)
281 {
282 /* check if name or not */
283 if (!pFile->isDef() || export.ulOrdinal < ORD_START_INTERNAL_FUNCTIONS)
284 {
285 char szIntName[256];
286 char szName[256];
287
288 /* exported name */
289 if (export.achName == '\0')
290 sprintf(&szName[0], "Ordinal%04ld", export.ulOrdinal);
291 else
292 demangle(&szName[0], &export.achName[0]);
293
294 /* internal name */
295 if (export.achIntName[0] == '\0')
296 demangle(&szIntName[0], &szName[0]);
297 else
298 demangle(&szIntName[0], export.achIntName);
299
300 fprintf(phLog, "%s: %08ld %-30s %s\n",
301 pszFilename, export.ulOrdinal, &szName[0], &szIntName[0]);
302
303 /* length test */
304 if (strlen(szIntName) > 100)
305 {
306 fprintf(phLog, "%s: error - intname is too long (%d). %s\n", pszFilename, strlen(szIntName), szIntName);
307 lRc++;
308 }
309 else if (strlen(szName) > 100)
310 {
311 fprintf(phLog, "%s: error - name is too long (%d). %s\n", pszFilename, strlen(szName), szName);
312 lRc++;
313 }
314 else
315 {
316 fOk = dbInsertUpdateFunction(sDll,
317 &szName[0],
318 &szIntName[0],
319 export.ulOrdinal,
320 pOptions->fIgnoreOrdinals && export.ulOrdinal != 0xffffffffUL);
321 if (fOk)
322 cFunctions++;
323 }
324 }
325
326 if (!fOk)
327 {
328 fprintf(phLog, "%s: error - dbInsertUpdateFunction failed.\n\terror description: %s \n",
329 pszFilename, dbGetLastErrorDesc());
330 lRc = 1;
331 }
332
333 /* next */
334 fOk = pFile->findNextExport(&export);
335 }
336
337 }
338 else
339 fprintf(phLog, "%s: error - could not find/insert module name (%s).\n", pszFilename, pszModuleName);
340 }
341 else
342 fprintf(phLog, "%s: error - could not get module name.\n", pszFilename);
343
344 delete(pFile);
345 }
346 catch (int err)
347 {
348 fprintf(phLog, "%s: error - could not map dll/def into memory, errorno=%d.\n", pszFilename, err);
349 }
350 fclose(phFile);
351 }
352 else
353 fprintf(phLog, "%s: error - could not open file.\n", pszFilename);
354
355 /* close db */
356 dbDisconnect();
357
358 return lRc;
359}
360
361
362/**
363 * Demangles stdcall functions.
364 * @param pszDemangled Pointer to buffer which will hold the demangled name upon return.
365 * @param pszMangledName Mangled name
366 */
367static void demangle(char *pszDemangled, const char *pszMangledName)
368{
369 int iEnd;
370 /* check for @ */
371 iEnd = strlen(pszMangledName);
372 if (iEnd-- > 3 && *pszMangledName == '_')
373 {
374 while ((pszMangledName[iEnd] >= '0' && pszMangledName[iEnd] <= '9') && iEnd > 0)
375 iEnd--;
376 if (pszMangledName[iEnd] == '@')
377 {
378 *pszDemangled = '\0';
379 strncat(pszDemangled, pszMangledName+1, iEnd - 1);
380 return;
381 }
382 }
383
384 /* not stdcall */
385 strcpy(pszDemangled, pszMangledName);
386}
387
Note: See TracBrowser for help on using the repository browser.