spiegel-keyman/windows/src/developer/kmdecomp/kmdecomp.cpp
Marc Durdin d5790ca9b6 fix(windows): cleanup pointer to int typecasts
Fixes #3084.

This does two things:

1. Cleans up a bunch of places where we used to use `(int)` typecasts
   for pointer math, which was problematic. We now use `(INT_PTR)` per
   MSDN https://docs.microsoft.com/en-us/windows/win32/winprog64/rules-for-using-pointers
   and then cast that down to `(int)` where necessary, e.g. when storing
   string lengths which are never going to be more than a few hundred
   characters! Doing this explicitly helps to clarify that we are aware
   of the typecast and believe it to be safe.

2. Adds in some build infrastructure for future use of Coverity Scan
   https://scan.coverity.com/ which we plan to use for further code
   quality updates. I have submitted the project to Coverity and are
   now waiting for approval so we can check results. Once we have
   approval, I do plan to add this to the nightly build (we need to
   keep submissions under 3 builds/day).

   Note: I have not yet added Keyman Core (Windows) to this project,
   nor are we currently building Keyman Core (macOS) or Keyman for
   Linux, but we should consider adding those in future.
2020-09-24 14:39:59 +10:00

209 lines
5.2 KiB
C++

/*
Name: kmdecomp
Copyright: Copyright (C) 2003-2017 SIL International.
Documentation:
Description:
Create Date: 12 Oct 2012
Modified Date: 12 Oct 2012
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 12 Oct 2012 - mcdurdin - I3467 - V9.0 - Upgrade KMDECOMP to compile with KM9 source tree
*/
#define STRICT
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <keymansentry.h>
#define _KEYMAN64_LIGHT
#include "keyman64.h"
BOOL LoadKeyboard(LPSTR fileName, LPKEYBOARD *lpKeyboard, LPBYTE *lpBitmap, DWORD *cbBitmap);
extern BOOL VerifyChecksum(LPBYTE buf, LPDWORD CheckSum, DWORD sz);
void Err(char *p);
int SaveKeyboardSource(LPKEYBOARD kbd, LPBYTE lpBitmap, DWORD cbBitmap, char *filename, char *bmpfile);
int run(int argc, char *argv[]);
/*
* Keyman
*
* Version 6.0
*
* KMDFILE compiled file loading
*
*/
#define KEYMAN_SENTRY_LOGGER_DEVELOPER_TOOLS_KMDECOMP KEYMAN_SENTRY_LOGGER_DEVELOPER_TOOLS ".kmdecomp"
int main(int argc, char *argv[])
{
return keyman_sentry_main(TRUE, KEYMAN_SENTRY_LOGGER_DEVELOPER_TOOLS_KMDECOMP, argc, argv, run);
}
int run(int argc, char *argv[])
{
LPKEYBOARD kbd;
LPBYTE lpBitmap;
DWORD cbBitmap;
char buf[_MAX_PATH], buf2[_MAX_PATH], drive[_MAX_DRIVE], dir[_MAX_DIR], filename[_MAX_FNAME];
if(argc < 2 || !strcmp(argv[1], "--help"))
{
puts("KMDECOMP: Decompile Keyman Desktop .kmx keyboard");
puts("(C) SIL International");
puts("Usage: KMDECOMP <filename>\n");
puts("Will create a .kmn and optionally a .bmp/.ico with the same filename and in the same location as the input");
return 1;
}
if(!LoadKeyboard(argv[1], &kbd, &lpBitmap, &cbBitmap)) return 2;
_splitpath_s(argv[1], drive, _MAX_DRIVE, dir, _MAX_DIR, filename, _MAX_FNAME, NULL, 0);
_makepath_s(buf, _MAX_PATH, drive, dir, filename, ".kmn");
_makepath_s(buf2, _MAX_PATH, drive, dir, filename, ".bmp");
int n = SaveKeyboardSource(kbd, lpBitmap, cbBitmap, buf, buf2);
if(lpBitmap) delete lpBitmap;
delete kbd;
return n;
}
void Err(char *p)
{
printf("Fatal Error: %s\n", p);
}
BOOL LoadKeyboard(LPSTR fileName, LPKEYBOARD *lpKeyboard, LPBYTE *lpBitmap, DWORD *cbBitmap)
{
DWORD sz, i, j;
LPBYTE buf;
HANDLE hFile;
PCOMP_KEYBOARD ckbp;
PCOMP_GROUP cgp;
PCOMP_STORE csp;
PCOMP_KEY ckp;
LPKEYBOARD kbp;
LPGROUP gp;
LPSTORE sp;
LPKEY kp;
if(!lpKeyboard)
{
Err("Internal error 001");
return FALSE;
}
if(!fileName)
{
Err("Bad Filename");
return FALSE;
}
hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
Err("Could not open file");
return FALSE;
}
sz = GetFileSize(hFile, NULL);
buf = new BYTE[sz];
if(!buf)
{
CloseHandle(hFile);
Err("Could not allocate memory");
return FALSE;
}
ReadFile(hFile, buf, sz, &sz, NULL);
CloseHandle(hFile);
kbp = (LPKEYBOARD) buf;
ckbp = (PCOMP_KEYBOARD) buf;
if(kbp->dwIdentifier != FILEID_COMPILED) { delete buf; Err("errNotFileID"); return FALSE; }
/* Check file version */
if(ckbp->dwFileVersion < VERSION_MIN ||
ckbp->dwFileVersion > VERSION_MAX)
{
/* Old or new version -- identify the desired program version */
if(VerifyChecksum(buf, &kbp->dwCheckSum, sz))
{
kbp->dpStoreArray = (LPSTORE) (buf + ckbp->dpStoreArray);
for(sp = kbp->dpStoreArray, i = 0; i < kbp->cxStoreArray; i++, sp++)
if(sp->dwSystemID == TSS_COMPILEDVERSION)
{
char buf2[256];
wsprintf(buf2, "Wrong File Version: file version is %ls", ((PBYTE)kbp) + (INT_PTR)sp->dpString);
delete buf;
Err(buf2);
return FALSE;
}
}
delete buf; Err("Unknown File Version: try using the latest version of KMDECOMP");
return FALSE;
}
if(!VerifyChecksum(buf, &kbp->dwCheckSum, sz)) { delete buf; Err("Bad Checksum in file"); return FALSE; }
kbp->dpStoreArray = (LPSTORE) (buf + ckbp->dpStoreArray);
kbp->dpGroupArray = (LPGROUP) (buf + ckbp->dpGroupArray);
//kbp->dpName = (PWSTR) (buf + ckbp->dpName);
//kbp->dpCopyright = (PWSTR) (buf + ckbp->dpCopyright);
//kbp->dpMessage = (PWSTR) (buf + ckbp->dpMessage);
//kbp->dpLanguageName = (PWSTR) (buf + ckbp->dpLanguageName);
if(ckbp->dwBitmapSize > 0)
{
*lpBitmap = new BYTE[ckbp->dwBitmapSize];
*cbBitmap = ckbp->dwBitmapSize;
memcpy(*lpBitmap, buf + ckbp->dpBitmapOffset, *cbBitmap);
}
else
{
*lpBitmap = NULL;
*cbBitmap = 0;
}
for(sp = kbp->dpStoreArray, csp = (PCOMP_STORE) sp, i = 0; i < kbp->cxStoreArray; i++, sp++, csp++)
{
if(csp->dpName > 0) sp->dpName = (PWSTR) (buf + csp->dpName); else sp->dpName = NULL;
sp->dpString = (PWSTR) (buf + csp->dpString);
}
for(gp = kbp->dpGroupArray, cgp = (PCOMP_GROUP) gp, i = 0; i < kbp->cxGroupArray; i++, gp++, cgp++)
{
if(cgp->dpName > 0) gp->dpName = (PWSTR) (buf + cgp->dpName); else gp->dpName = NULL;
gp->dpKeyArray = (LPKEY) (buf + cgp->dpKeyArray);
if(cgp->dpMatch != NULL) gp->dpMatch = (PWSTR) (buf + cgp->dpMatch);
if(cgp->dpNoMatch != NULL) gp->dpNoMatch = (PWSTR) (buf + cgp->dpNoMatch);
for(kp = gp->dpKeyArray, ckp = (PCOMP_KEY) kp, j = 0; j < gp->cxKeyArray; j++, kp++, ckp++)
{
kp->dpOutput = (PWSTR) (buf + ckp->dpOutput);
kp->dpContext = (PWSTR) (buf + ckp->dpContext);
}
}
*lpKeyboard = kbp;
return TRUE;
}