int main(int argc, char **argv) { setlocale(LC_ALL, "C"); DisableDataExecution(); WStrVec argList; ParseCmdLine(GetCommandLine(), argList); if (argList.Count() < 2) { Usage: ErrOut("%s <filename> [-pwd <password>][-full][-alt][-render <path-%%d.tga>]\n", path::GetBaseName(argList.At(0))); return 0; } ScopedMem<WCHAR> filePath; WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(argList.At(1), &fdata); if (INVALID_HANDLE_VALUE != hfind) { ScopedMem<WCHAR> dir(path::GetDir(argList.At(1))); filePath.Set(path::Join(dir, fdata.cFileName)); FindClose(hfind); } else { // embedded documents are referred to by an invalid path // containing more information after a colon (e.g. "C:\file.pdf:3:0") filePath.Set(str::Dup(argList.At(1))); } bool fullDump = false; WCHAR *password = NULL; WCHAR *renderPath = NULL; bool useAlternateHandlers = false; bool loadOnly = false; int breakAlloc = 0; for (size_t i = 2; i < argList.Count(); i++) { if (str::Eq(argList.At(i), L"-full")) fullDump = true; else if (str::Eq(argList.At(i), L"-pwd") && i + 1 < argList.Count()) password = argList.At(++i); else if (str::Eq(argList.At(i), L"-render") && i + 1 < argList.Count()) renderPath = argList.At(++i); else if (str::Eq(argList.At(i), L"-alt")) useAlternateHandlers = true; else if (str::Eq(argList.At(i), L"-loadonly")) loadOnly = true; #ifdef DEBUG else if (str::Eq(argList.At(i), L"-breakalloc") && i + 1 < argList.Count()) breakAlloc = _wtoi(argList.At(++i)); #endif else goto Usage; } #ifdef DEBUG if (breakAlloc) { _CrtSetBreakAlloc(breakAlloc); if (!IsDebuggerPresent()) MessageBox(NULL, L"Keep your debugger ready for the allocation breakpoint...", L"EngineDump", MB_ICONINFORMATION); } #endif // optionally use GDI+ rendering for PDF/XPS and the original ChmEngine for CHM DebugGdiPlusDevice(useAlternateHandlers); DebugAlternateChmEngine(!useAlternateHandlers); ScopedGdiPlus gdiPlus; DocType engineType; PasswordHolder pwdUI(password); BaseEngine *engine = EngineManager::CreateEngine(true, filePath, &pwdUI, &engineType); if (!engine) { ErrOut("Error: Couldn't create an engine for %s!\n", path::GetBaseName(filePath)); return 1; } if (!loadOnly) DumpData(engine, fullDump); if (renderPath) RenderDocument(engine, renderPath); delete engine; #ifdef DEBUG // report memory leaks on stderr for engines that shouldn't leak if (engineType != Engine_DjVu) { _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); } #endif return 0; }
int main(int argc, char **argv) { setlocale(LC_ALL, "C"); DisableDataExecution(); WStrVec argList; ParseCmdLine(GetCommandLine(), argList); if (argList.Count() < 2) { Usage: ErrOut("%s [-pwd <password>][-quick][-render <path-%%d.tga>] <filename>", path::GetBaseName(argList.At(0))); return 2; } ScopedMem<WCHAR> filePath; WCHAR *password = NULL; bool fullDump = true; WCHAR *renderPath = NULL; float renderZoom = 1.f; bool useAlternateHandlers = false; bool loadOnly = false, silent = false; #ifdef DEBUG int breakAlloc = 0; #endif for (size_t i = 1; i < argList.Count(); i++) { if (str::Eq(argList.At(i), L"-pwd") && i + 1 < argList.Count() && !password) password = argList.At(++i); else if (str::Eq(argList.At(i), L"-quick")) fullDump = false; else if (str::Eq(argList.At(i), L"-render") && i + 1 < argList.Count() && !renderPath) { // optional zoom argument (e.g. -render 50% file.pdf) float zoom; if (i + 2 < argList.Count() && str::Parse(argList.At(i + 1), L"%f%%%$", &zoom) && zoom > 0.f) { renderZoom = zoom / 100.f; i++; } renderPath = argList.At(++i); } // -alt is for debugging alternate rendering methods else if (str::Eq(argList.At(i), L"-alt")) useAlternateHandlers = true; // -loadonly and -silent are only meant for profiling else if (str::Eq(argList.At(i), L"-loadonly")) loadOnly = true; else if (str::Eq(argList.At(i), L"-silent")) silent = true; // -full is for backward compatibility else if (str::Eq(argList.At(i), L"-full")) fullDump = true; #ifdef DEBUG else if (str::Eq(argList.At(i), L"-breakalloc") && i + 1 < argList.Count()) breakAlloc = _wtoi(argList.At(++i)); #endif else if (!filePath) filePath.Set(str::Dup(argList.At(i))); else goto Usage; } if (!filePath) goto Usage; #ifdef DEBUG if (breakAlloc) { _CrtSetBreakAlloc(breakAlloc); if (!IsDebuggerPresent()) MessageBox(NULL, L"Keep your debugger ready for the allocation breakpoint...", L"EngineDump", MB_ICONINFORMATION); } #endif if (silent) { FILE *nul; freopen_s(&nul, "NUL", "w", stdout); freopen_s(&nul, "NUL", "w", stderr); } // optionally use GDI+ rendering for PDF/XPS DebugGdiPlusDevice(useAlternateHandlers); ScopedGdiPlus gdiPlus; ScopedMiniMui miniMui; WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(filePath, &fdata); // embedded documents are referred to by an invalid path // containing more information after a colon (e.g. "C:\file.pdf:3:0") if (INVALID_HANDLE_VALUE != hfind) { ScopedMem<WCHAR> dir(path::GetDir(filePath)); filePath.Set(path::Join(dir, fdata.cFileName)); FindClose(hfind); } EngineType engineType; PasswordHolder pwdUI(password); BaseEngine *engine = EngineManager::CreateEngine(filePath, &pwdUI, &engineType); if (!engine) { ErrOut("Error: Couldn't create an engine for %s!", path::GetBaseName(filePath)); return 1; } Vec<PageAnnotation> *userAnnots = LoadFileModifications(engine->FileName()); engine->UpdateUserAnnotations(userAnnots); delete userAnnots; if (!loadOnly) DumpData(engine, fullDump); if (renderPath) RenderDocument(engine, renderPath, renderZoom, silent); delete engine; #ifdef DEBUG // report memory leaks on stderr for engines that shouldn't leak if (engineType != Engine_DjVu) { _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); } #endif return 0; }