/*++ Copyright (c) 2000 Microsoft Corporation Module Name: dbcsfchk.cpp Abstract: Does some simple checking to see if the file is a valid DBCS file and counts the number of DBCS characters Author: Vijay Jayaseelan (vijayj) Oct-18-2000 Revision History: None --*/ #include #include #include #include #include // // Usage format // std::wstring Usage(L"Usage: dbcsfchk.exe filename codepage"); // // Helper dump operators // std::ostream& operator<<(std::ostream &os, const std::wstring &str) { FILE *OutStream = (&os == &std::cerr) ? stderr : stdout; fwprintf(OutStream, str.c_str()); return os; } // // Abstracts a Win32 error // struct W32Error{ DWORD ErrorCode; W32Error(DWORD ErrCode) : ErrorCode(ErrCode){} void Dump(std::ostream &os) { WCHAR MsgBuffer[4096]; MsgBuffer[0] = UNICODE_NULL; DWORD CharCount = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MsgBuffer, sizeof(MsgBuffer)/sizeof(WCHAR), NULL); if (CharCount) { std::wstring Msg(MsgBuffer); os << Msg; } else { os << std::hex << ErrorCode; } } }; // // Parses the arguments // BOOL ParseArguments( IN INT Argc, IN TCHAR *Argv[], OUT TCHAR *FileName, OUT ULONG &CodePage ) { BOOL Result = FALSE; if (FileName && (Argc > 2)) { _tcscpy(FileName, Argv[1]); CodePage = atol(Argv[2]); Result = TRUE; } return Result; } BOOL ValidateDbcsData( IN const TCHAR *Data, IN ULONG Length, OUT ULONG &LineNumber, OUT ULONG &Offset, OUT ULONG &ValidDbcsChars ) { BOOL Result = FALSE; const TCHAR *CurrPtr = Data; Offset = 0; ValidDbcsChars = 0; while (Offset < Length) { if (_ismbblead(*(UCHAR*)CurrPtr)) { Offset++; if (_ismbbtrail(*(UCHAR *)(CurrPtr + 1))) { Offset++; CurrPtr += 2; ValidDbcsChars++; continue; } else { break; } } if (*CurrPtr == '\n') { LineNumber++; } else if ((*CurrPtr == '\r') && (*(CurrPtr+1) == '\n')) { LineNumber++; Offset++; CurrPtr++; } Offset++; CurrPtr++; } Result = (Offset == Length); if (Result) { LineNumber = 0; } return Result; } // // Main entry point // INT __cdecl _tmain( IN INT Argc, IN TCHAR *Argv[] ) { INT Result = 1; try { TCHAR FileName[MAX_PATH] = {0}; ULONG CodePage = 0; // // Parse the arguments // if (ParseArguments(Argc, Argv, FileName, CodePage)) { // // Set the code page // if (!_setmbcp(CodePage)) { std::cout << "Using Code Page : " << _getmbcp() << std::endl; // // Open the file // HANDLE FileHandle = CreateFile(FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (FileHandle == INVALID_HANDLE_VALUE) { throw new W32Error(GetLastError()); } // // Map the file in memory (as readonly) // HANDLE FileMapHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL); if (!FileMapHandle) { DWORD Error = GetLastError(); CloseHandle(FileHandle); throw new W32Error(Error); } TCHAR *Data = (TCHAR *)MapViewOfFile(FileMapHandle, FILE_MAP_READ, 0, 0, 0); if (!Data) { DWORD Error = GetLastError(); CloseHandle(FileMapHandle); CloseHandle(FileHandle); throw new W32Error(Error); } // // Get the length of the file // BY_HANDLE_FILE_INFORMATION FileInfo = {0}; if (!GetFileInformationByHandle(FileHandle, &FileInfo)) { DWORD Error = GetLastError(); UnmapViewOfFile(Data); CloseHandle(FileMapHandle); CloseHandle(FileHandle); throw new W32Error(Error); } ULONG LineNumber = 0; ULONG ErrorOffset = 0; ULONG DbcsCount = 0; // // Validate the Data // BOOL Result = ValidateDbcsData(Data, FileInfo.nFileSizeLow, LineNumber, ErrorOffset, DbcsCount); if (!Result) { std::cout << "Character not valid at line number : " << std::dec << LineNumber << " offset : " << std::dec << ErrorOffset << std::endl; } else { Result = 0; // no errors\ std::cout << FileName << " is valid DBCS file with " << std::dec << DbcsCount << " DBCS char(s)" << std::endl; } // // Clean up // UnmapViewOfFile(Data); CloseHandle(FileMapHandle); CloseHandle(FileHandle); } else { std::cout << "Error in setting Code Page to : " << std::dec << CodePage << std::endl; } } else { std::cout << Usage << std::endl; } } catch(W32Error *Error) { Error->Dump(std::cout); delete Error; } catch(...) { std::cout << "Internal error" << std::endl; } return Result; }