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

Last change on this file since 5120 was 5053, checked in by bird, 25 years ago

Corrected kFileLX and kFilePE constructors.
Made kDump.exe work again.
Added import module dump to kFilePE.

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