bool vtElevLayer::ImportFromFile(const wxString &strFileName, bool progress_callback(int), vtElevError *err) { // Avoid trouble with '.' and ',' in Europe - all the file readers assume // the default "C" locale. ScopedLocale normal_numbers(LC_NUMERIC, "C"); wxString strExt = strFileName.AfterLast('.'); vtString fname = (const char *) strFileName.mb_str(wxConvUTF8); VTLOG("ImportFromFile '%s'\n", (const char *) fname); if (!strExt.CmpNoCase(_T("gz"))) { // ignore .gz, look at extension under it wxString dropped = strFileName.Left(strFileName.Len()-3); strExt = dropped.AfterLast('.'); } if (!strExt.CmpNoCase(_T("bz2"))) { // ignore .bz2, look at extension under it wxString dropped = strFileName.Left(strFileName.Len()-4); strExt = dropped.AfterLast('.'); } // The first character in the file is useful for telling which format // the file really is. FILE *fp = vtFileOpen(fname, "rb"); char first = fgetc(fp); fclose(fp); bool success = false; if (!strExt.CmpNoCase(_T("dxf"))) { m_pTin = new vtTin2d; success = m_pTin->ReadDXF(fname, progress_callback); } else if (!strFileName.Right(6).CmpNoCase(_T("xy.adf"))) { m_pTin = new vtTin2d; success = m_pTin->ReadADF(fname, progress_callback); } else if (!strFileName.Right(4).CmpNoCase(_T(".tin"))) { m_pTin = new vtTin2d; success = m_pTin->ReadGMS(fname, progress_callback); } else if (!strFileName.Right(4).CmpNoCase(_T(".ply"))) { m_pTin = new vtTin2d; success = m_pTin->ReadPLY(fname, progress_callback); } else { if (m_pGrid == NULL) m_pGrid = new vtElevationGrid; } if (!strExt.CmpNoCase(_T("3tx"))) { success = m_pGrid->LoadFrom3TX(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("dem"))) { // If there is a .hdr file in the same place, it is most likely // a GTOPO30/SRTM30 file vtString hdr_fname = ChangeFileExtension(fname, ".hdr"); if (vtFileExists(hdr_fname)) success = m_pGrid->LoadFromGTOPO30(hdr_fname, progress_callback); else { if (first == '*') success = m_pGrid->LoadFromMicroDEM(fname, progress_callback); else success = m_pGrid->LoadFromDEM(fname, progress_callback, err); } } else if (!strExt.CmpNoCase(_T("asc"))) { success = m_pGrid->LoadFromASC(fname, progress_callback); // vtElevationGrid does have its own ASC reader, but use GDAL instead // success = m_pGrid->LoadWithGDAL(strFileName.mb_str(wxConvUTF8), progress_callback, err); } else if (!strExt.CmpNoCase(_T("bil"))) { success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("mem"))) { success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("ter"))) { success = m_pGrid->LoadFromTerragen(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("cdf"))) { success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("hdr"))) { success = m_pGrid->LoadFromGTOPO30(fname, progress_callback); if (!success) success = m_pGrid->LoadFromGLOBE(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("dte")) || !strExt.CmpNoCase(_T("dt0")) || !strExt.CmpNoCase(_T("dt1")) || !strExt.CmpNoCase(_T("dt2"))) { success = m_pGrid->LoadFromDTED(fname, progress_callback); } else if (!strExt.Left(3).CmpNoCase(_T("pgm"))) { success = m_pGrid->LoadFromPGM(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("grd"))) { // might by CDF, might be Surfer GRD if (first == 'D') { VTLOG("First character is 'D', attempting load as a Surfer Grid file.\n"); success = m_pGrid->LoadFromGRD(fname, progress_callback); } else { VTLOG("First character is not 'D', attempting load as a netCDF file.\n"); success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } if (!success) { VTLOG("Didn't load successfully, attempting load with GDAL.\n"); // Might be 'Arc Binary Grid', try GDAL success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } } else if (!strFileName.Right(8).CmpNoCase(_T("catd.ddf")) || !strExt.Left(3).CmpNoCase(_T("tif")) || !strExt.Left(3).CmpNoCase(_T("png")) || !strExt.Left(3).CmpNoCase(_T("img")) || !strExt.CmpNoCase(_T("adf"))) { if (m_pGrid) success = m_pGrid->LoadWithGDAL(fname, progress_callback, err); } else if (!strExt.CmpNoCase(_T("raw"))) { RawDlg dlg(NULL, -1, _("Raw Elevation File")); dlg.m_iBytes = 2; dlg.m_iWidth = 100; dlg.m_iHeight = 100; dlg.m_fVUnits = 1.0f; dlg.m_fSpacing = 30.0f; dlg.m_bBigEndian = false; dlg.m_extents.SetToZero(); g_bld->GetProjection(dlg.m_original); if (dlg.ShowModal() == wxID_OK) { success = m_pGrid->LoadFromRAW(fname, dlg.m_iWidth, dlg.m_iHeight, dlg.m_iBytes, dlg.m_fVUnits, dlg.m_bBigEndian, progress_callback); } if (success) { m_pGrid->SetEarthExtents(dlg.m_extents); m_pGrid->SetProjection(dlg.m_proj); } } else if (!strExt.CmpNoCase(_T("ntf"))) { success = m_pGrid->LoadFromNTF5(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("txt")) || !strExt.CmpNoCase(_T("xyz"))) { success = m_pGrid->LoadFromXYZ(fname, progress_callback); } else if (!strExt.CmpNoCase(_T("hgt"))) { success = m_pGrid->LoadFromHGT(fname, progress_callback); } else if (!strExt.Left(2).CmpNoCase(_T("db"))) { success = ImportFromDB(fname, progress_callback); } if (!success) return false; vtProjection *pProj; if (m_pGrid) pProj = &m_pGrid->GetProjection(); else pProj = &m_pTin->m_proj; // We should ask for a CRS before asking for extents if (!g_bld->ConfirmValidCRS(pProj)) { if (err) { err->type = vtElevError::CANCELLED; err->message = "Cancelled"; } return false; } if (m_pGrid != NULL) { if (m_pGrid->GetEarthExtents().IsEmpty()) { // No extents. wxString msg = _("File lacks geographic location (extents). Would you like to specify extents?\n Yes - specify extents\n No - use some default values\n"); int res = wxMessageBox(msg, _("Elevation Import"), wxYES_NO | wxCANCEL); if (res == wxYES) { DRECT ext; ext.SetToZero(); ExtentDlg dlg(NULL, -1, _("Elevation Grid Extents")); dlg.SetArea(ext, (pProj->IsGeographic() != 0)); if (dlg.ShowModal() == wxID_OK) m_pGrid->SetEarthExtents(dlg.m_area); else return false; } if (res == wxNO) { // Just make up some fake extents, assuming a regular even grid int xsize, ysize; m_pGrid->GetDimensions(xsize, ysize); DRECT ext; ext.left = ext.bottom = 0; if (pProj->IsGeographic()) { ext.right = xsize * (1.0/3600); // arc second ext.top = ysize * (1.0/3600); } else { ext.right = xsize * 10; // 10 linear units (meters, feet..) ext.top = ysize * 10; } m_pGrid->SetEarthExtents(ext); } if (res == wxCANCEL) { if (err) { err->type = vtElevError::CANCELLED; err->message = "Cancelled"; } return false; } } m_pGrid->SetupLocalCS(1.0f); } return true; }
int main(int argc, char *argv[]) { bool dumpBin = false; bool dumpElf = false; bool listInfo = false; bool convertBin = false; bool convertElf = false; unsigned int loadAddress = 0, entryPoint = 0; // print title printf("%s\n", title); // process args if(argc == 2) { // if no options given, list info on dol file listInfo = true; } else if(argc >= 3) { // check case-insensitively for options if( strcasecmp("-e", argv[1]) == 0) dumpElf = true; else if(strcasecmp("-b", argv[1]) == 0) dumpBin = true; else if(strcasecmp("-i", argv[1]) == 0) listInfo = true; else if(strcasecmp("-c", argv[1]) == 0) { convertBin = true; if (argc == 5) { loadAddress = strtoul(argv[3], (char **)NULL, 16); entryPoint = strtoul(argv[4], (char **)NULL, 16); } else if(argc == 3) { loadAddress = 0x80003100u; entryPoint = 0x80003100u; } else { printf("%s\n", usage); return 1; } } else if(strcasecmp("-d", argv[1]) == 0) convertElf = true; else { // usage error printf("%s\n", usage); return 1; } } else { // usage error printf("%s\n", usage); return 1; } // open/create dol file char filename[256]; strcpy(filename, argv[2]); DolFile dolFile; if(convertBin || convertElf) { char dolFilename[256]; strcpy(dolFilename, filename); ChangeFileExtension(dolFilename, "dol"); if(!dolFile.create(dolFilename)) { printf("Error creating %s!\n", dolFilename); return 2; } } else { if(!dolFile.open(filename)) { printf("Error opening %s!\n", filename); return 2; } } bool ret = true; // list info on dol file if(listInfo) ret = listDolInfo(dolFile); // dump to binary file else if(dumpBin) ret = dumpDolToBinaryFile(dolFile); // dump to elf file else if(dumpElf) ret = dumpDolToElfFile(dolFile); // convert binary file to dol else if(convertBin) ret = convertBinaryFileToDol(dolFile, filename, loadAddress, entryPoint); // convert elf file to dol else if(convertElf) ret = convertElfFileToDol(dolFile, filename); // close dol file dolFile.close(); // return ok if finished ok if(ret) return 0; return 666; }
// dump dol file to a binary file // // args: dol file object // returns: true if successful bool dumpDolToBinaryFile(const DolFile& dolFile) { unsigned int i; // get binary filename char binFilename[256]; strcpy(binFilename, dolFile.getFilename()); ChangeFileExtension(binFilename, "bin"); // open binary output file FILE* bin_fd = 0; bin_fd = fopen(binFilename, "w+b"); if(bin_fd == 0) { printf("Error creating %s!\n", binFilename); return false; } // get load address and entry point unsigned int loadAddress = dolFile.getLowestAddress(); unsigned int entryPoint = dolFile.getEntryPoint(); // check if load address is same as entry point if(loadAddress != entryPoint) { // if load address is different to exec address, // it could cause problems in binary format // check if there is space before the load address // to put in a jump to the entry point if(loadAddress >= 0x80003100 + 4) { // insert jump to entry point before code unsigned int jump = TEST_CHANGE_ENDIAN_32BIT(MY_ENDIAN == LITTLE_ENDIAN, 0x48000000 | (entryPoint - (loadAddress - 4)) ); fwrite(&jump, 1, 4, bin_fd); // update load address and entry point loadAddress -= 4; entryPoint = loadAddress; } } // dump text bits first for(i=0; i<dolFile.getMaxNumTextSections(); i++) { if(dolFile.isTextSectionValid(i)) { unsigned int address= dolFile.getTextAddress(i); //unsigned int offset = dolFile.getTextOffset(i); //unsigned int size = dolFile.getTextSize(i); // make sure binary file is big enough to contain correct section offset unsigned char zero = 0; fseek(bin_fd, 0, SEEK_END); // if its not big enough, buffer file with 0 till its big enough while((unsigned int)ftell(bin_fd) < (address-loadAddress)) fwrite(&zero, 1, 1, bin_fd); // goto section offset in binary file if(fseek(bin_fd, address-loadAddress, SEEK_SET) != 0) printf("Error seeking to TEXT section %d in binary file\n", i); // write section to binary file if(dolFile.extractTextSection(i, bin_fd) == ERROR_RETURN) printf("Error writing TEXT section %d in binary file\n", i); } } // then dump data bits for(i=0; i<dolFile.getMaxNumDataSections(); i++) { if(dolFile.isDataSectionValid(i)) { unsigned int address= dolFile.getDataAddress(i); //unsigned int offset = dolFile.getDataOffset(i); //unsigned int size = dolFile.getDataSize(i); // make sure binary file is big enough to contain correct section offset unsigned char zero = 0; fseek(bin_fd, 0, SEEK_END); // if its not big enough, buffer file with 0 till its big enough while((unsigned int)ftell(bin_fd) < (address-loadAddress)) fwrite(&zero, 1, 1, bin_fd); // goto section offset in binary file if(fseek(bin_fd, address-loadAddress, SEEK_SET) != 0) printf("Error seeking to DATA section %d in binary file\n", i); // write section to binary file if(dolFile.extractDataSection(i, bin_fd) == ERROR_RETURN) printf("Error writing DATA section %d in binary file\n", i); } } // last attempt to make the entry point the same as the load address // this checks if there are nops at the load address that we can then overwrite // (ive decided to leave it out for now incase those nops are 'required' somehow... /* if(loadAddress != entryPoint) { int instr = 0; fseek(bin_fd, 0, SEEK_SET); fread(&instr, 4, 1, bin_fd); if(SET_ENDIAN_32BIT(instr) == NOP) { // insert jump to entry point before code unsigned int jump = TEST_CHANGE_ENDIAN_32BIT(MY_ENDIAN == LITTLE_ENDIAN, (x48000000 | (entryPoint - (loadAddress - 4))); fseek(bin_fd, 0, SEEK_SET); fwrite(&jump, 1, 4, bin_fd); // update entry point entryPoint = loadAddress; } } */ // close file and finish up fclose(bin_fd); printf( "\nDumped %s to %s\n" "Load Address: 0x%08X\n" "Entry point: 0x%08X\n" , dolFile.getFilename(), binFilename, loadAddress, entryPoint); return true; }
// dump dol file to an elf file // // args: dol file object // returns: true if successful bool dumpDolToElfFile(const DolFile& dolFile) { // work out filename to use for elf file char elfFilename[256]; strcpy(elfFilename, dolFile.getFilename()); ChangeFileExtension(elfFilename, "elf"); // create elf output file ElfFile elfFile; if(!elfFile.create(elfFilename, ELFDATA2MSB)) return false; // set elf file as PPC elfFile.setMachineType(EM_PPC); // set entry point in elf file elfFile.setEntryPoint(dolFile.getEntryPoint()); // create a temp file to store section data during copy FILE* temp_fd = fopen("~temp.tmp", "w+b"); if(temp_fd == 0) { elfFile.close(); return false; } char name[32]; // add dol text sections to elf file for(u32 i=0; i<dolFile.getNumTextSections(); i++) { // get section data from dol file fseek(temp_fd, 0, SEEK_SET); dolFile.extractTextSection(i, temp_fd); sprintf(name, ".text%d", i); // add section data to elf file fseek(temp_fd, 0, SEEK_SET); elfFile.addSection(temp_fd, dolFile.getTextAddress(i), dolFile.getTextSize(i), name, SHT_PROGBITS, SHF_ALLOC|SHF_EXECINSTR, 32); // add a program header for the section just added // the section just added, was added as the last section // u32 offset = elfFile.getSectionOffset(elfFile.getNumSections() - 1); // elfFile.addProgramHeader(dolFile.getTextAddress(i), dolFile.getTextSize(i), offset, PT_LOAD, PF_EXEC|PF_READ, 32); } // add dol data sections to elf file for(u32 i=0; i<dolFile.getNumDataSections(); i++) { // get section data from dol file fseek(temp_fd, 0, SEEK_SET); dolFile.extractDataSection(i, temp_fd); sprintf(name, ".data%d", i); // add section data to elf file fseek(temp_fd, 0, SEEK_SET); elfFile.addSection(temp_fd, dolFile.getDataAddress(i), dolFile.getDataSize(i), name, SHT_PROGBITS, SHF_ALLOC|SHF_WRITE, 32); // add a program header for the section just added // the section just added, was added as the last section // u32 offset = elfFile.getSectionOffset(elfFile.getNumSections() - 1); // elfFile.addProgramHeader(dolFile.getDataAddress(i), dolFile.getDataSize(i), offset, PT_LOAD, PF_WRITE|PF_READ, 32); } // add bss section to elf file elfFile.addSectionHeader(dolFile.getBssAddress(), dolFile.getBssSize(), ".bss", 0, SHT_NOBITS, SHF_WRITE|SHF_ALLOC, 1); // add a program header for the section just added // the section just added, was added as the last section // u32 index = elfFile.getNumSections() - 1; // elfFile.addProgramHeader(elfFile.getSectionAddress(index), elfFile.getSectionSize(index), elfFile.getSectionOffset(index), PT_LOAD, PF_WRITE|PF_READ, 32); // finish up fclose(temp_fd); remove("~temp.tmp"); elfFile.close(); printf( "\nConverted %s to to %s\n", dolFile.getFilename(), elfFilename); return true; }
// Main entry point int _tmain(int argc, _TCHAR* argv[]) { // Add command line alias' cl.AddAlias(L"h", L"?"); cl.AddAlias(L"help", L"?"); cl.AddAlias(L"x", L"extract"); cl.AddAlias(L"o", L"out"); // Parse command line cl.Parse(GetCommandLine(), true); // Display logo... if (!cl.GetSwitch(L"nologo")) { wprintf(L"Structured Ini File Compiler v1.1\nCopyright (C) 2007 Topten Software. All Rights Reserved\n\n"); } // Display help if (cl.GetSwitch(L"?")) { cl.BuildHelp(L"nologo", L"Suppress display of copyright and version info", NULL, clOptional); cl.BuildHelp(L"?|h|help", L"Display help information", NULL, clOptional); cl.BuildHelp(L"i", L"Include path", L"path", clMulti|clValue|clOptional); cl.BuildHelp(L"x|extract", L"Extract (decompile)", NULL, clOptional); cl.BuildHelp(L"unicode", L"Decompile to unicode", NULL, clOptional); cl.BuildHelp(L"flat", L"Decompile to flat", NULL, clOptional); cl.BuildHelp(L"o|out", L"Output File", NULL, clOptional); cl.BuildHelp(L"InputFile", L"File to be processed", NULL, clPlaced); cl.BuildHelp(L"crcstamp", L"CRC Stamp Module", NULL, clOptional); cl.BuildHelp(L"crcverify", L"Check Module CRC Stamp", NULL, clOptional); wprintf(cl.GetHelp(L"Sinic")); return 7; } // Get input value CUniString strInputFile; cl.GetPlacedValue(0, L"InputFile", strInputFile); strInputFile=QualifyPath(strInputFile); if (cl.GetSwitch(L"crcverify")) { if (!DoesFileExist(strInputFile)) { wprintf(L"Verifying %s... file doesn't exist, ignoring\n", strInputFile); return 0; } else { if (!CheckModuleCRC(strInputFile)) { CheckModuleCRCWithErrors(strInputFile); wprintf(L"************************************************************\n"); wprintf(L" Verifying %s... FAILED\n", strInputFile); wprintf(L"************************************************************\n"); return 7; } else { wprintf(L"Verifying %s... OK\n", strInputFile); return 0; } } } // Module CRC Stamp? if (cl.GetSwitch(L"crcstamp")) { // Work out output file CUniString strOutputFile; cl.GetValue(L"out", strOutputFile); if (strOutputFile.IsEmpty()) strOutputFile=strInputFile; // Error handling... cl.CheckNoUnknownArgs(); if (cl.HasError()) { wprintf(cl.GetErrorMessage()); wprintf(L"\n\n"); return 7; } // Open file for read/write FILE* pFile; if (_wfopen_s(&pFile, strInputFile, L"rb")!=0) { wprintf(L"Error: Can't open file '%s'\n", strInputFile); return 7; } // Get file size fseek(pFile, 0, SEEK_END); DWORD dwLength=ftell(pFile); fseek(pFile, 0, SEEK_SET); // Check has length if (dwLength==0) { fclose(pFile); wprintf(L"Error: Zero length file\n"); return 7; } // Load file into memory LPBYTE pFileData=(LPBYTE)malloc(dwLength); // Read data if (fread(pFileData, dwLength, 1, pFile)!=1) { free(pFileData); fclose(pFile); wprintf(L"Error: Error reading file\n"); return 7; } // Close the file fclose(pFile); if (CountCRCControlBlocks(pFileData, dwLength)>1) { free(pFileData); fclose(pFile); wprintf(L"Error: File contains multiple CRC Control blocks!\n"); return 7; } // Locate CRC Control block CRCCONTROLBLOCK* pCRCBlock=LocateCRCControlBlock(pFileData, dwLength); if (!pCRCBlock) { free(pFileData); fclose(pFile); wprintf(L"Error: File doesn't contain CRC Control block!\n"); return 7; } wprintf(L"CRC Control Block located at offset: 0x%.8x\n", reinterpret_cast<LPBYTE>(pCRCBlock)-pFileData); // Calculate the CRC upto start of control block pCRCBlock->dwCRC=CalculateModuleCRC(pFileData, dwLength, pCRCBlock); pCRCBlock->dwModuleLength=dwLength; wprintf(L"Module length: 0x%.8x\n", dwLength); wprintf(L"CRC: 0x%.8x\n", pCRCBlock->dwCRC); pFile=NULL; if (_wfopen_s(&pFile, strOutputFile, L"wb")!=0) { wprintf(L"Error: Can't open output file '%s'\n", strOutputFile); return 7; } if (!CheckModuleCRC(pFileData, dwLength)) { wprintf(L"Error: double check failed\n"); return 7; } // Write CRC stamped fwrite(pFileData, dwLength, 1, pFile); // Clean up free(pFileData); fclose(pFile); if (!CheckModuleCRC(strOutputFile)) { CheckModuleCRCWithErrors(strOutputFile); return 7; } wprintf(L"CRC Stamped %s - OK\n\n", strOutputFile); return 0; } // Compile or decompile bool bDecompile=cl.GetSwitch(L"extract"); bool bUnicode=cl.GetSwitch(L"unicode"); bool bFlat=cl.GetSwitch(L"flat"); // Get output file CUniString strOutputFile; cl.GetValue(L"out", strOutputFile); if (strOutputFile.IsEmpty()) { strOutputFile=ChangeFileExtension(strInputFile.IsEmpty() ? L"" : strInputFile, bDecompile ? L"sini" : L"bini"); } strOutputFile=QualifyPath(strOutputFile); // Setup file content provider with include paths CFileContentProvider fp; CVector<CUniString> vecIncludePaths; cl.GetMultiValue(L"i", vecIncludePaths); for (int i=0; i<vecIncludePaths.GetSize(); i++) { CUniString str=QualifyPath(vecIncludePaths[i]); fp.AddIncludePath(str); } // Get defines CVector<CUniString> vecDefines; cl.GetMultiValue(L"d", vecDefines); // Error handling... cl.CheckNoUnknownArgs(); if (cl.HasError()) { wprintf(cl.GetErrorMessage()); wprintf(L"\n\n"); return 7; } if (!bDecompile) { // Load the input file CProfileFile file; for (int i=0; i<vecDefines.GetSize(); i++) { CUniString strName, strValue; SplitString(vecDefines[i], L"=", strName, strValue); wprintf(L"#define %s %s\n", strName, strValue); file.Define(strName, strValue); } if (!file.Load(strInputFile, &fp)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(file.GetParseError()); return 7; } // Extract encryption key DWORD dwEncryptionKey=0; CProfileSection* pSection=file.FindSection(L"Sinic"); if (pSection) { // Save the key dwEncryptionKey=pSection->GetIntValue(L"EncryptionKey", 0); // Remove the "sinic" section file.Remove(pSection); } // Create output file CFileStream OutStream; if (!OutStream.Create(strOutputFile)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to create '%s' - %s (0x%.8x)\n\n", strOutputFile, FormatError(hr), hr); return 7; } // Save as binary file HRESULT hr; if (dwEncryptionKey) { CAutoPtr<IStream, SRefCounted> spEncStream; CreateCryptorStream(&OutStream, CCryptorKey(dwEncryptionKey), &spEncStream); hr=SaveBinaryProfile(file, spEncStream); } else { hr=SaveBinaryProfile(file, &OutStream); } OutStream.Close(); if (FAILED(hr)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to save '%s' - %s (0x%.8x)\n\n", strOutputFile, FormatError(hr), hr); DeleteFile(strOutputFile); return 7; } } else { // Open stream CFileStream InStream; if (!InStream.Open(strInputFile)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to open '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr); return 7; } // Load profile CProfileFile file; HRESULT hr=LoadBinaryProfile(file, &InStream); if (FAILED(hr)) { if (hr!=E_UNEXPECTED) { wprintf(L"Failed to load '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr); return 7; } else { wprintf(L"Failed to load '%s' - not a binary profile file\n\n", strInputFile); return 7; } } // Save as heirarchial if (!file.Save(strOutputFile, bUnicode, !bFlat)) { HRESULT hr=HRESULT_FROM_WIN32(GetLastError()); wprintf(L"Failed to save '%s' - %s (0x%.8x)\n\n", strInputFile, FormatError(hr), hr); return 7; } } wprintf(L"%s - OK\n\n", strOutputFile); return 0; }