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

Last change on this file since 6677 was 6677, checked in by bird, 24 years ago

dll to module conversion.

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