mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-11 11:25:34 +00:00
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.
209 lines
5.2 KiB
C++
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;
|
|
}
|
|
|