1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /************************************************************************************************ |
6 | * * |
7 | * File: winmain.cpp * |
8 | * * |
9 | * Purpose: Main program for graphic COM+ 2.0 disassembler ILDASM.exe * |
10 | * * |
11 | ************************************************************************************************/ |
12 | #include "ildasmpch.h" |
13 | |
14 | #include "dynamicarray.h" |
15 | |
16 | #include "dasmenum.hpp" |
17 | #include "dis.h" |
18 | #include <ndpversion.h> |
19 | #include "resource.h" |
20 | |
21 | #include "new.hpp" |
22 | |
23 | #define MODE_DUMP_ALL 0 |
24 | #define MODE_DUMP_CLASS 1 |
25 | #define MODE_DUMP_CLASS_METHOD 2 |
26 | #define MODE_DUMP_CLASS_METHOD_SIG 3 |
27 | |
28 | // All externs are defined in DASM.CPP |
29 | extern BOOL g_fDumpIL; |
30 | extern BOOL ; |
31 | extern BOOL g_fDumpAsmCode; |
32 | extern BOOL g_fDumpTokens; |
33 | extern BOOL g_fDumpStats; |
34 | extern BOOL g_fDumpClassList; |
35 | extern BOOL g_fDumpTypeList; |
36 | extern BOOL g_fDumpSummary; |
37 | extern BOOL g_fDecompile; // still in progress |
38 | extern BOOL g_fShowRefs; |
39 | |
40 | extern BOOL g_fDumpToPerfWriter; |
41 | |
42 | extern BOOL g_fShowBytes; |
43 | extern BOOL g_fShowSource; |
44 | extern BOOL g_fInsertSourceLines; |
45 | extern BOOL g_fTryInCode; |
46 | extern BOOL g_fQuoteAllNames; |
47 | extern BOOL g_fTDC; |
48 | extern BOOL g_fShowCA; |
49 | extern BOOL g_fCAVerbal; |
50 | |
51 | extern char g_pszClassToDump[]; |
52 | extern char g_pszMethodToDump[]; |
53 | extern char g_pszSigToDump[]; |
54 | |
55 | extern char g_szAsmCodeIndent[]; |
56 | |
57 | extern DWORD g_Mode; |
58 | |
59 | extern char* g_pszExeFile; |
60 | extern char g_szInputFile[]; // in UTF-8 |
61 | extern WCHAR g_wszFullInputFile[]; // in UTF-16 |
62 | extern char g_szOutputFile[]; // in UTF-8 |
63 | extern char* g_pszObjFileName; |
64 | extern FILE* g_pFile; |
65 | |
66 | extern BOOL g_fLimitedVisibility; |
67 | #if defined(_DEBUG) && defined(FEATURE_PREJIT) |
68 | extern BOOL g_fNGenNativeMetadata; |
69 | #endif |
70 | extern BOOL g_fHidePub; |
71 | extern BOOL g_fHidePriv; |
72 | extern BOOL g_fHideFam; |
73 | extern BOOL g_fHideAsm; |
74 | extern BOOL g_fHideFAA; |
75 | extern BOOL g_fHideFOA; |
76 | extern BOOL g_fHidePrivScope; |
77 | extern BOOL g_fProject; |
78 | |
79 | extern unsigned g_uCodePage; |
80 | extern unsigned g_uConsoleCP; |
81 | extern BOOL g_fForwardDecl; |
82 | extern BOOL g_fUseProperName; |
83 | |
84 | #include "../tools/metainfo/mdinfo.h" |
85 | extern BOOL g_fDumpMetaInfo; |
86 | extern ULONG g_ulMetaInfoFilter; |
87 | HINSTANCE g_hInstance; |
88 | HINSTANCE g_hResources; |
89 | HANDLE hConsoleOut=NULL; |
90 | HANDLE hConsoleErr=NULL; |
91 | // These are implemented in DASM.CPP: |
92 | BOOL Init(); |
93 | void Uninit(); |
94 | void Cleanup(); |
95 | void DumpMetaInfo(__in __nullterminated const WCHAR* pszFileName, __in __nullterminated const char* pszObjFileName, void* GUICookie); |
96 | FILE* OpenOutput(__in __nullterminated const char* szFileName); |
97 | |
98 | void PrintLogo() |
99 | { |
100 | printf("Microsoft (R) .NET Framework IL Disassembler. Version " VER_FILEVERSION_STR); |
101 | printf("\n%S\n\n" , VER_LEGALCOPYRIGHT_LOGO_STR_L); |
102 | } |
103 | |
104 | void SyntaxCon() |
105 | { |
106 | DWORD l; |
107 | |
108 | for(l=IDS_USAGE_01; l<= IDS_USAGE_23; l++) printf(RstrANSI(l)); |
109 | if(g_fTDC) |
110 | { |
111 | for(l=IDS_USAGE_24; l<= IDS_USAGE_32; l++) printf(RstrANSI(l)); |
112 | for(l=IDS_USAGE_34; l<= IDS_USAGE_36; l++) printf(RstrANSI(l)); |
113 | for(l=IDS_USAGE_37; l<= IDS_USAGE_39; l++) printf(RstrANSI(l)); |
114 | } |
115 | else printf(RstrANSI(IDS_USAGE_40)); |
116 | for(l=IDS_USAGE_41; l<= IDS_USAGE_42; l++) printf(RstrANSI(l)); |
117 | |
118 | } |
119 | |
120 | char* CheckForDQuotes(__inout __nullterminated char* sz) |
121 | { |
122 | char* ret = sz; |
123 | if(*sz == '"') |
124 | { |
125 | ret++; |
126 | sz[strlen(sz)-1] = 0; |
127 | } |
128 | return ret; |
129 | } |
130 | |
131 | char* EqualOrColon(__in __nullterminated char* szArg) |
132 | { |
133 | char* pchE = strchr(szArg,'='); |
134 | char* pchC = strchr(szArg,':'); |
135 | char* ret; |
136 | if(pchE == NULL) ret = pchC; |
137 | else if(pchC == NULL) ret = pchE; |
138 | else ret = (pchE < pchC)? pchE : pchC; |
139 | return ret; |
140 | } |
141 | |
142 | void GetInputFileFullPath() |
143 | { |
144 | // We need the input file's full path to make uses of it later, despite changing CurrentDirectory |
145 | |
146 | // First, convert back up to UTF16 |
147 | DWORD len = (DWORD) strlen(g_szInputFile) + 16; |
148 | WCHAR* wzArg = new WCHAR[len]; |
149 | memset(wzArg, 0, len * sizeof(WCHAR)); |
150 | WszMultiByteToWideChar(g_uConsoleCP, 0, g_szInputFile, -1, wzArg, len); |
151 | |
152 | // Get the full path |
153 | len = WszGetFullPathName(wzArg, MAX_PATH, g_wszFullInputFile, NULL); |
154 | VDELETE(wzArg); |
155 | } |
156 | |
157 | int ProcessOneArg(__in __nullterminated char* szArg, __out char** ppszObjFileName) |
158 | { |
159 | char szOpt[128]; |
160 | if(strlen(szArg) == 0) return 0; |
161 | if ((strcmp(szArg, "/?" ) == 0) || (strcmp(szArg, "-?" ) == 0)) return 1; |
162 | |
163 | #ifdef FEATURE_PAL |
164 | if(szArg[0] == '-') |
165 | #else |
166 | if((szArg[0] == '/') || (szArg[0] == '-')) |
167 | #endif |
168 | { |
169 | strncpy_s(szOpt,128, &szArg[1],10); |
170 | szOpt[3] = 0; |
171 | if (_stricmp(szOpt, "dec" ) == 0) |
172 | { |
173 | g_fDecompile = TRUE; |
174 | } |
175 | else if (_stricmp(szOpt, "hea" ) == 0) |
176 | { |
177 | g_fDumpHeader = TRUE; |
178 | } |
179 | else if (_stricmp(szOpt, "adv" ) == 0) |
180 | { |
181 | g_fTDC = TRUE; |
182 | } |
183 | else if (_stricmp(szOpt, "tok" ) == 0) |
184 | { |
185 | g_fDumpTokens = TRUE; |
186 | } |
187 | else if (_stricmp(szOpt, "noi" ) == 0) |
188 | { |
189 | g_fDumpAsmCode = FALSE; |
190 | } |
191 | else if (_stricmp(szOpt, "noc" ) == 0) |
192 | { |
193 | g_fShowCA = FALSE; |
194 | } |
195 | else if (_stricmp(szOpt, "cav" ) == 0) |
196 | { |
197 | g_fCAVerbal = TRUE; |
198 | } |
199 | else if (_stricmp(szOpt, "not" ) == 0) |
200 | { |
201 | g_fTryInCode = FALSE; |
202 | } |
203 | else if (_stricmp(szOpt, "raw" ) == 0) |
204 | { |
205 | g_fTryInCode = FALSE; |
206 | } |
207 | else if (_stricmp(szOpt, "byt" ) == 0) |
208 | { |
209 | g_fShowBytes = TRUE; |
210 | } |
211 | else if (_stricmp(szOpt, "sou" ) == 0) |
212 | { |
213 | printf("Warning: 'SOURCE' option is ignored for ildasm on CoreCLR.\n" ); |
214 | } |
215 | else if (_stricmp(szOpt, "lin" ) == 0) |
216 | { |
217 | g_fInsertSourceLines = TRUE; |
218 | } |
219 | else if ((_stricmp(szOpt, "sta" ) == 0)&&g_fTDC) |
220 | { |
221 | g_fDumpStats = g_fTDC; |
222 | } |
223 | else if ((_stricmp(szOpt, "cla" ) == 0)&&g_fTDC) |
224 | { |
225 | g_fDumpClassList = g_fTDC; |
226 | } |
227 | else if (_stricmp(szOpt, "typ" ) == 0) |
228 | { |
229 | g_fDumpTypeList = TRUE; |
230 | } |
231 | else if (_stricmp(szOpt, "sum" ) == 0) |
232 | { |
233 | g_fDumpSummary = TRUE; |
234 | } |
235 | else if (_stricmp(szOpt, "per" ) == 0) |
236 | { |
237 | g_fDumpToPerfWriter = TRUE; |
238 | } |
239 | else if (_stricmp(szOpt, "for" ) == 0) |
240 | { |
241 | g_fForwardDecl = TRUE; |
242 | } |
243 | else if (_stricmp(szOpt, "ref" ) == 0) |
244 | { |
245 | g_fShowRefs = TRUE; |
246 | } |
247 | else if (_stricmp(szOpt, "pub" ) == 0) |
248 | { |
249 | g_fLimitedVisibility = TRUE; |
250 | g_fHidePub = FALSE; |
251 | } |
252 | #if defined(_DEBUG) && defined(FEATURE_PREJIT) |
253 | else if (_stricmp(szOpt, "nat" ) == 0) |
254 | { |
255 | g_fNGenNativeMetadata = TRUE; |
256 | } |
257 | #endif |
258 | else if (_stricmp(szOpt, "pre" ) == 0) |
259 | { |
260 | //g_fPrettyPrint = TRUE; |
261 | } |
262 | else if (_stricmp(szOpt, "pro" ) == 0) |
263 | { |
264 | g_fProject = TRUE; |
265 | } |
266 | else if (_stricmp(szOpt, "vis" ) == 0) |
267 | { |
268 | char *pc = EqualOrColon(szArg); |
269 | char *pStr; |
270 | if(pc == NULL) return -1; |
271 | do { |
272 | pStr = pc+1; |
273 | pStr = CheckForDQuotes(pStr); |
274 | if((pc = strchr(pStr,'+'))) *pc=0; |
275 | if (!_stricmp(pStr,"pub" )) g_fHidePub = FALSE; |
276 | else if(!_stricmp(pStr,"pri" )) g_fHidePriv = FALSE; |
277 | else if(!_stricmp(pStr,"fam" )) g_fHideFam = FALSE; |
278 | else if(!_stricmp(pStr,"asm" )) g_fHideAsm = FALSE; |
279 | else if(!_stricmp(pStr,"faa" )) g_fHideFAA = FALSE; |
280 | else if(!_stricmp(pStr,"foa" )) g_fHideFOA = FALSE; |
281 | else if(!_stricmp(pStr,"psc" )) g_fHidePrivScope = FALSE; |
282 | } while(pc); |
283 | g_fLimitedVisibility = g_fHidePub || |
284 | g_fHidePriv || |
285 | g_fHideFam || |
286 | g_fHideAsm || |
287 | g_fHideFAA || |
288 | g_fHideFOA || |
289 | g_fHidePrivScope; |
290 | } |
291 | else if (_stricmp(szOpt, "quo" ) == 0) |
292 | { |
293 | g_fQuoteAllNames = TRUE; |
294 | } |
295 | else if (_stricmp(szOpt, "utf" ) == 0) |
296 | { |
297 | g_uCodePage = CP_UTF8; |
298 | } |
299 | else if (_stricmp(szOpt, "uni" ) == 0) |
300 | { |
301 | g_uCodePage = 0xFFFFFFFF; |
302 | } |
303 | else if (_stricmp(szOpt, "rtf" ) == 0) |
304 | { |
305 | g_fDumpRTF = TRUE; |
306 | g_fDumpHTML = FALSE; |
307 | } |
308 | else if (_stricmp(szOpt, "htm" ) == 0) |
309 | { |
310 | g_fDumpRTF = FALSE; |
311 | g_fDumpHTML = TRUE; |
312 | } |
313 | else if (_stricmp(szOpt, "all" ) == 0) |
314 | { |
315 | g_fDumpStats = g_fTDC; |
316 | g_fDumpHeader = TRUE; |
317 | g_fShowBytes = TRUE; |
318 | g_fDumpClassList = g_fTDC; |
319 | g_fDumpTokens = TRUE; |
320 | } |
321 | else if (_stricmp(szOpt, "ite" ) == 0) |
322 | { |
323 | char *pStr = EqualOrColon(szArg); |
324 | char *p, *q; |
325 | if(pStr == NULL) return -1; |
326 | pStr++; |
327 | pStr = CheckForDQuotes(pStr); |
328 | // treat it as meaning "dump only class X" or "class X method Y" |
329 | p = strchr(pStr, ':'); |
330 | |
331 | if (p == NULL) |
332 | { |
333 | // dump one class |
334 | g_Mode = MODE_DUMP_CLASS; |
335 | strcpy_s(g_pszClassToDump, MAX_CLASSNAME_LENGTH, pStr); |
336 | } |
337 | else |
338 | { |
339 | *p++ = '\0'; |
340 | if (*p != ':') return -1; |
341 | |
342 | strcpy_s(g_pszClassToDump, MAX_CLASSNAME_LENGTH, pStr); |
343 | |
344 | p++; |
345 | |
346 | q = strchr(p, '('); |
347 | if (q == NULL) |
348 | { |
349 | // dump class::method |
350 | g_Mode = MODE_DUMP_CLASS_METHOD; |
351 | strcpy_s(g_pszMethodToDump, MAX_MEMBER_LENGTH, p); |
352 | } |
353 | else |
354 | { |
355 | // dump class::method(sig) |
356 | g_Mode = MODE_DUMP_CLASS_METHOD_SIG; |
357 | *q = '\0'; |
358 | strcpy_s(g_pszMethodToDump, MAX_MEMBER_LENGTH, p); |
359 | // get rid of external parentheses: |
360 | q++; |
361 | strcpy_s(g_pszSigToDump, MAX_SIGNATURE_LENGTH, q); |
362 | } |
363 | } |
364 | } |
365 | else if ((_stricmp(szOpt, "met" ) == 0)&&g_fTDC) |
366 | { |
367 | printf("Warning: 'METADATA' option is ignored for ildasm on CoreCLR.\n" ); |
368 | } |
369 | else if (_stricmp(szOpt, "obj" ) == 0) |
370 | { |
371 | char *pStr = EqualOrColon(szArg); |
372 | if(pStr == NULL) return -1; |
373 | pStr++; |
374 | pStr = CheckForDQuotes(pStr); |
375 | *ppszObjFileName = new char[strlen(pStr)+1]; |
376 | strcpy_s(*ppszObjFileName,strlen(pStr)+1,pStr); |
377 | } |
378 | else if (_stricmp(szOpt, "out" ) == 0) |
379 | { |
380 | char *pStr = EqualOrColon(szArg); |
381 | if(pStr == NULL) return -1; |
382 | pStr++; |
383 | pStr = CheckForDQuotes(pStr); |
384 | if(*pStr == 0) return -1; |
385 | if(_stricmp(pStr,"con" )) |
386 | { |
387 | strncpy_s(g_szOutputFile, MAX_FILENAME_LENGTH, pStr,MAX_FILENAME_LENGTH-1); |
388 | g_szOutputFile[MAX_FILENAME_LENGTH-1] = 0; |
389 | } |
390 | } |
391 | else |
392 | { |
393 | PrintLogo(); |
394 | printf(RstrANSI(IDS_E_INVALIDOPTION),szArg); //"INVALID COMMAND LINE OPTION: %s\n\n",szArg); |
395 | return -1; |
396 | } |
397 | } |
398 | else |
399 | { |
400 | if(g_szInputFile[0]) |
401 | { |
402 | PrintLogo(); |
403 | printf(RstrANSI(IDS_E_MULTIPLEINPUT)); //"MULTIPLE INPUT FILES SPECIFIED\n\n"); |
404 | return -1; // check if it was already specified |
405 | } |
406 | szArg = CheckForDQuotes(szArg); |
407 | strncpy_s(g_szInputFile, MAX_FILENAME_LENGTH,szArg,MAX_FILENAME_LENGTH-1); |
408 | g_szInputFile[MAX_FILENAME_LENGTH-1] = 0; |
409 | GetInputFileFullPath(); |
410 | } |
411 | return 0; |
412 | } |
413 | |
414 | char* UTF8toANSI(__in __nullterminated char* szUTF) |
415 | { |
416 | ULONG32 L = (ULONG32) strlen(szUTF)+16; |
417 | WCHAR* wzUnicode = new WCHAR[L]; |
418 | memset(wzUnicode,0,L*sizeof(WCHAR)); |
419 | WszMultiByteToWideChar(CP_UTF8,0,szUTF,-1,wzUnicode,L); |
420 | L <<= 2; |
421 | char* szANSI = new char[L]; |
422 | memset(szANSI,0,L); |
423 | WszWideCharToMultiByte(g_uConsoleCP,0,wzUnicode,-1,szANSI,L,NULL,NULL); |
424 | VDELETE(wzUnicode); |
425 | return szANSI; |
426 | } |
427 | char* ANSItoUTF8(__in __nullterminated char* szANSI) |
428 | { |
429 | ULONG32 L = (ULONG32) strlen(szANSI)+16; |
430 | WCHAR* wzUnicode = new WCHAR[L]; |
431 | memset(wzUnicode,0,L*sizeof(WCHAR)); |
432 | WszMultiByteToWideChar(g_uConsoleCP,0,szANSI,-1,wzUnicode,L); |
433 | L *= 3; |
434 | char* szUTF = new char[L]; |
435 | memset(szUTF,0,L); |
436 | WszWideCharToMultiByte(CP_UTF8,0,wzUnicode,-1,szUTF,L,NULL,NULL); |
437 | VDELETE(wzUnicode); |
438 | return szUTF; |
439 | } |
440 | |
441 | int ParseCmdLineW(__in __nullterminated WCHAR* wzCmdLine, __out char** ppszObjFileName) |
442 | { |
443 | int argc,ret=0; |
444 | LPWSTR* argv= SegmentCommandLine(wzCmdLine, (DWORD*)&argc); |
445 | char* szArg = new char[2048]; |
446 | for(int i=1; i < argc; i++) |
447 | { |
448 | memset(szArg,0,2048); |
449 | WszWideCharToMultiByte(CP_UTF8,0,argv[i],-1,szArg,2048,NULL,NULL); |
450 | if((ret = ProcessOneArg(szArg,ppszObjFileName)) != 0) break; |
451 | } |
452 | VDELETE(szArg); |
453 | return ret; |
454 | } |
455 | |
456 | int ParseCmdLineA(__in __nullterminated char* szCmdLine, __out char** ppszObjFileName) |
457 | { |
458 | if((szCmdLine == NULL)||(*szCmdLine == 0)) return 0; |
459 | |
460 | // ANSI to UTF-8 |
461 | char* szCmdLineUTF = ANSItoUTF8(szCmdLine); |
462 | |
463 | // Split into argv[] |
464 | int argc=0, ret = 0; |
465 | DynamicArray<char*> argv; |
466 | char* pch; |
467 | char* pchend; |
468 | bool bUnquoted = true; |
469 | |
470 | pch = szCmdLineUTF; |
471 | pchend = pch+strlen(szCmdLineUTF); |
472 | while(pch) |
473 | { |
474 | for(; *pch == ' '; pch++); // skip the blanks |
475 | argv[argc++] = pch; |
476 | for(; pch < pchend; pch++) |
477 | { |
478 | if(*pch == '"') bUnquoted = !bUnquoted; |
479 | else if((*pch == ' ')&&bUnquoted) break; |
480 | } |
481 | |
482 | if(pch < pchend) *pch++ = 0; |
483 | else break; |
484 | } |
485 | |
486 | for(int i=1; i < argc; i++) |
487 | { |
488 | if((ret = ProcessOneArg(argv[i],ppszObjFileName)) != 0) break; |
489 | } |
490 | VDELETE(szCmdLineUTF); |
491 | return ret; |
492 | } |
493 | |
494 | int __cdecl main(int nCmdShow, char* lpCmdLine[]) |
495 | { |
496 | #if defined(FEATURE_PAL) |
497 | if (0 != PAL_Initialize(nCmdShow, lpCmdLine)) |
498 | { |
499 | printError(g_pFile, "Error: Fail to PAL_Initialize\n" ); |
500 | exit(1); |
501 | } |
502 | g_pszExeFile = lpCmdLine[0]; |
503 | #endif |
504 | |
505 | // ildasm does not need to be SO-robust. |
506 | SO_NOT_MAINLINE_FUNCTION; |
507 | |
508 | // SWI has requested that the exact form of the function call below be used. For details see http://swi/SWI%20Docs/Detecting%20Heap%20Corruption.doc |
509 | (void)HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); |
510 | |
511 | #ifdef _DEBUG |
512 | DisableThrowCheck(); |
513 | #endif |
514 | |
515 | int iCommandLineParsed = 0; |
516 | WCHAR* wzCommandLine = NULL; |
517 | char* szCommandLine = NULL; |
518 | |
519 | g_fUseProperName = TRUE; |
520 | |
521 | g_pszClassToDump[0]=0; |
522 | g_pszMethodToDump[0]=0; |
523 | g_pszSigToDump[0]=0; |
524 | memset(g_szInputFile,0,MAX_FILENAME_LENGTH); |
525 | memset(g_szOutputFile,0,MAX_FILENAME_LENGTH); |
526 | #if defined(_DEBUG) |
527 | g_fTDC = TRUE; |
528 | #endif |
529 | |
530 | #undef GetCommandLineW |
531 | #undef CreateProcessW |
532 | g_pszObjFileName = NULL; |
533 | |
534 | g_szAsmCodeIndent[0] = 0; |
535 | hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE); |
536 | hConsoleErr = GetStdHandle(STD_ERROR_HANDLE); |
537 | |
538 | #ifndef FEATURE_PAL |
539 | // Dev11 #5320 - pull the localized resource loader up so if ParseCmdLineW need resources, they're already loaded |
540 | g_hResources = LoadLocalizedResourceDLLForSDK(L"ildasmrc.dll" ); |
541 | #endif |
542 | |
543 | iCommandLineParsed = ParseCmdLineW((wzCommandLine = GetCommandLineW()),&g_pszObjFileName); |
544 | |
545 | if(!g_fLimitedVisibility) |
546 | { |
547 | g_fHidePub = FALSE; |
548 | g_fHidePriv = FALSE; |
549 | g_fHideFam = FALSE; |
550 | g_fHideAsm = FALSE; |
551 | g_fHideFAA = FALSE; |
552 | g_fHideFOA = FALSE; |
553 | g_fHidePrivScope = FALSE; |
554 | } |
555 | if(hConsoleOut != INVALID_HANDLE_VALUE) //First pass: console |
556 | { |
557 | g_uConsoleCP = GetConsoleOutputCP(); |
558 | |
559 | if(iCommandLineParsed) |
560 | { |
561 | if(iCommandLineParsed > 0) PrintLogo(); |
562 | SyntaxCon(); |
563 | exit((iCommandLineParsed == 1) ? 0 : 1); |
564 | } |
565 | |
566 | { |
567 | DWORD exitCode = 1; |
568 | if(g_szInputFile[0] == 0) |
569 | { |
570 | SyntaxCon(); |
571 | exit(1); |
572 | } |
573 | g_pFile = NULL; |
574 | if(g_szOutputFile[0]) |
575 | { |
576 | g_pFile = OpenOutput(g_szOutputFile); |
577 | if(g_pFile == NULL) |
578 | { |
579 | char sz[4096]; |
580 | sprintf_s(sz,4096,RstrUTF(IDS_E_CANTOPENOUT)/*"Unable to open '%s' for output."*/, g_szOutputFile); |
581 | g_uCodePage = CP_ACP; |
582 | printError(NULL,sz); |
583 | exit(1); |
584 | } |
585 | } |
586 | else // console output -- force the code page to ANSI |
587 | { |
588 | g_uCodePage = g_uConsoleCP; |
589 | g_fDumpRTF = FALSE; |
590 | g_fDumpHTML = FALSE; |
591 | } |
592 | if (Init() == TRUE) |
593 | { |
594 | exitCode = DumpFile() ? 0 : 1; |
595 | Cleanup(); |
596 | } |
597 | Uninit(); |
598 | exit(exitCode); |
599 | } |
600 | } |
601 | return 0; |
602 | } |
603 | |
604 | |