2020-09-30 17:12:32 +02:00

877 lines
19 KiB
C++

#include "precomp.hxx"
#pragma hdrstop
// Used by windbg & windbgrm
// Serial transport layers
LPSTR
rgszSerialTransportLayers[ROWS_SERIAL_TRANSPORT_LAYERS][COLS_SERIAL_TRANSPORT_LAYERS] = {
{ "SER12", "Serial - COM1, 1200 baud", "tlser.dll", "com1:1200" },
{ "SER24", "Serial - COM1, 2400 baud", "tlser.dll", "com1:2400" },
{ "SER96", "Serial - COM1, 9600 baud", "tlser.dll", "com1:9600" },
{ "SER192", "Serial - COM1, 19200 baud", "tlser.dll", "com1:19200" },
{ "SER57K", "Serial - COM1, 57600 baud", "tlser.dll", "com1:57600" }
};
#ifdef _CPPRTTI
BOOL
RttiTypesEqual(
const type_info & t1,
const type_info & t2
)
{
return t1 == t2;
}
#endif
UINT
WKSP_MultiStrSize(
PCSTR psz
)
/*
Routine Description:
Returns the total size in char of a multistring, including all terminating zereos.
Arguments:
psz - Supplies the multistring
Return Value:
UINT - Total size in char. (strlen is UINT) To maintain compatibility with strlen.
--*/
{
if (NULL == psz) {
return 0;
}
DWORD dwSum = 0;
DWORD dwCur;
do {
dwCur = strlen(psz) +1;
psz += dwCur;
dwSum += dwCur;
} while (*psz);
return dwSum +1;
}
UINT
WKSP_StrSize(
PCSTR psz
)
/*
Routine Description:
Returns the total size in char of a string, including the terminating zereo.
Arguments:
psz - Supplies the multistring
Return Value:
UINT - Total size in char. (strlen is UINT) To maintain compatibility with strlen.
--*/
{
if (NULL == psz) {
return 0;
} else {
return strlen(psz) + 1;
}
}
// Copied from windbg. Minor modifications.
int
CDECL
WKSP_DisplayLastErrorMsgBox()
{
PSTR pszErr = WKSP_FormatLastErrorMessage();
if (pszErr) {
return MessageBox(NULL, pszErr, NULL, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
} else {
Assert(0);
return 0;
}
}
/*
** Description:
** if pszTitle is is NULL, the default title Error is used.
**
** Display a message box with a title, an OK
** button and a Exclamation Icon. First parameter is a
** reference string in the ressource file. The string
** can contain printf formatting chars, the arguments
** follow from the second parameter onwards.
*/
int
CDECL
WKSP_MsgBox(
PSTR pszTitle,
WORD wErrorFormat,
...
)
{
int nRes;
va_list vargs;
va_start(vargs, wErrorFormat);
nRes = WKSP_VargsCustMsgBox(MB_OK | MB_ICONINFORMATION | MB_TASKMODAL, pszTitle,
wErrorFormat, vargs);
va_end(vargs);
return nRes;
}
int
CDECL
WKSP_VargsMsgBox(
PSTR pszTitle,
WORD wErrorFormat,
va_list vargs
)
{
return WKSP_VargsCustMsgBox(MB_OK | MB_ICONINFORMATION | MB_TASKMODAL, pszTitle,
wErrorFormat, vargs);
}
int
CDECL
WKSP_CustMsgBox(
UINT uStyle,
PSTR pszTitle,
WORD wErrorFormat,
...
)
{
int nRes;
va_list vargs;
va_start(vargs, wErrorFormat);
nRes = WKSP_VargsCustMsgBox(uStyle, pszTitle, wErrorFormat, vargs);
va_end(vargs);
return nRes;
}
int
CDECL
WKSP_VargsCustMsgBox(
UINT uStyle,
PSTR pszTitle,
WORD wErrorFormat,
va_list vargs
)
{
extern HINSTANCE g_hInst;
char szErrorFormat[MAX_MSG_TXT];
char szErrorText[MAX_VAR_MSG_TXT]; // size is as big as considered necessary
// load format string from resource file
Dbg(LoadString(g_hInst, wErrorFormat, (LPSTR)szErrorFormat, MAX_MSG_TXT));
vsprintf(szErrorText, szErrorFormat, vargs);
return MessageBox(NULL, szErrorText, pszTitle, uStyle);
}
BOOL
WKSP_RegKeyValueInfo(
HKEY hkey,
PDWORD pdwNumSubKeys,
PDWORD pdwNumValues,
PDWORD pdwMaxKeyNameLen,
PDWORD pdwMaxValueNameLen
)
{
Assert(hkey);
LONG lres;
lres = RegQueryInfoKey(hkey, // handle of key to query
NULL, // address of buffer for class string
NULL, // address of size of class string buffer
0, // reserved
pdwNumSubKeys, // address of buffer for number of subkeys
pdwMaxKeyNameLen, // address of buffer for longest subkey name length
NULL, // address of buffer for longest class string length
pdwNumValues, // address of buffer for number of value entries
pdwMaxValueNameLen, // address of buffer for longest value name length
NULL, // address of buffer for longest value data length
NULL, // address of buffer for security descriptor length
NULL // address of buffer for last write time);
);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
return ERROR_SUCCESS == lres;
}
BOOL
WKSP_RegGetKeyName(
HKEY hkey,
DWORD dwIndex,
PSTR pszName,
PDWORD pcbName
)
{
Assert(hkey);
LONG lres;
lres = RegEnumKeyEx(hkey,
dwIndex,
pszName,
pcbName,
0,
NULL,
NULL,
NULL
);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
return (ERROR_SUCCESS == lres);
}
BOOL
WKSP_GetValueName(
HKEY hkey,
DWORD dwIndex,
PSTR pszName,
PDWORD pcbName,
PDWORD pdwType
)
{
Assert(hkey);
LONG lres;
lres = RegEnumValue(hkey,
dwIndex,
pszName,
pcbName,
0,
pdwType,
NULL,
NULL
);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
return (ERROR_SUCCESS == lres);
}
BOOL
WKSP_RegEnumerate(
HKEY hkey,
TList< CRegEntry * > *plistRegKeys,
TList< CRegEntry * > *plistRegVals,
BOOL fOpenRegKeys
)
/*
Description
Enumerates all of the name of the key's values or sub-keys.
Arguments:
hkey - Can't be NULL. Must be an open registry key.
plistRegKeys - List where the enumerated key names will be kept
plistRegValues - List where the enumerated values names will be kept
fOpenRegKeys - TRUE open the handle to the reg key in the plistRegKeys
Returns:
TRUE - Success
FALSE - Error occured
--*/
{
Assert(hkey);
LONG lres;
DWORD dwKeys_Num;
DWORD dwKeys_MaxNameLen;
DWORD dwVals_Num;
DWORD dwVals_MaxNameLen;
PTSTR pszNameBuf;
DWORD dwIdx;
DWORD dwMaxIdx;
DWORD dwLen;
CRegEntry *pRegEntry;
int nFlag;
TList< CRegEntry * > * plist;
if ( !hkey ) {
return FALSE;
}
if ( !plistRegKeys && !plistRegVals ) {
return FALSE;
}
// Get the number of keys and values
if ( !WKSP_RegKeyValueInfo(hkey,
&dwKeys_Num,
&dwVals_Num,
&dwKeys_MaxNameLen,
&dwVals_MaxNameLen
)) {
return FALSE;
}
// Reserve space for the zero terminator
dwKeys_MaxNameLen++;
dwVals_MaxNameLen++;
pszNameBuf = (PTSTR) malloc( max( dwKeys_MaxNameLen, dwVals_MaxNameLen ) );
if ( !pszNameBuf ) {
return FALSE;
}
// nFlag signifies the following values
// 0 - Enumerate keys
// 1 - Enumerate values
// 2 - finished
for (nFlag=0; nFlag < 2; nFlag++) {
// If this is not set to something other
// than 0, then the for loop falls thru.
dwMaxIdx = 0;
// Figure out which list to fill
if (0 == nFlag && plistRegKeys) {
dwMaxIdx = dwKeys_Num;
plist = plistRegKeys;
} else if (1 == nFlag && plistRegVals) {
dwMaxIdx = dwVals_Num;
plist = plistRegVals;
}
for (dwIdx=0; dwIdx < dwMaxIdx; dwIdx++) {
dwLen = dwKeys_MaxNameLen;
WKSP_RegGetKeyName(hkey, dwIdx, pszNameBuf, &dwLen);
pRegEntry = new CRegEntry;
if ( !pRegEntry ) {
goto ERROR_CLEANUP;
}
pRegEntry->m_pszName = _strdup(pszNameBuf);
// Open reg key?
if (0 == nFlag && fOpenRegKeys) {
if (ERROR_SUCCESS != RegOpenKeyEx(hkey, pRegEntry->m_pszName, 0, KEY_ALL_ACCESS, &pRegEntry->m_hkey)) {
goto ERROR_CLEANUP;
}
}
plist->InsertTail( pRegEntry );
}
}
return TRUE;
ERROR_CLEANUP:
// Delete the list of keys
if (plistRegKeys) {
while ( !plistRegKeys->IsEmpty() ) {
pRegEntry = plistRegKeys->GetHeadData();
plistRegKeys->RemoveHead();
pRegEntry->CleanUp();
delete pRegEntry;
}
}
// Delete the list of values
if (plistRegVals) {
while ( !plistRegVals->IsEmpty() ) {
pRegEntry = plistRegVals->GetHeadData();
plistRegVals->RemoveHead();
pRegEntry->CleanUp();
delete pRegEntry;
}
}
return FALSE;
}
void
WKSP_RegDeleteValues(
HKEY hkey
)
/*
Routine Description:
Helper function. Deletes all of the values contained by a registry key.
Does not delete any keys or the specified key.
Arguments:
hkey - Cannot be NULL. Must point to an open registry key.
--*/
{
Assert(hkey);
LONG lres;
DWORD dwMaxNumValues;
DWORD dwMaxNameSize;
WKSP_RegKeyValueInfo(hkey, NULL, &dwMaxNumValues, NULL, &dwMaxNameSize);
// Include space for the null terminator.
dwMaxNameSize++;
PSTR pszBuffer = (PSTR) calloc(dwMaxNameSize, 1);
Assert(pszBuffer);
for (DWORD dwCounter = 0; dwCounter < dwMaxNumValues; dwCounter++) {
DWORD dwLen = dwMaxNameSize;
lres = WKSP_GetValueName(hkey, 0, pszBuffer, &dwLen, NULL);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
lres = RegDeleteValue(hkey, pszBuffer);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
}
free(pszBuffer);
}
void
WKSP_RegDeleteSubKeys(
HKEY hkey
)
/*
Routine Description:
Recursively deletes subkeys.
Helper function. Will only delete the subkeys within the specified key. The values
within the specified key will not be deleted.
The specified key is not deleted.
See docs for "RegDeleteKey".
Arguments:
hkey - Can't be NULL. Must be an open registry key.
--*/
{
Assert(hkey);
LONG lres;
DWORD dwMaxNameSize, dwMaxNumSubKeys;
WKSP_RegKeyValueInfo(hkey, &dwMaxNumSubKeys, NULL, &dwMaxNameSize, NULL);
// Include space for the null terminator.
dwMaxNameSize++;
PSTR pszBuffer = (PSTR) calloc(dwMaxNameSize, 1);
Assert(pszBuffer);
// Treat the reg keys as a list, by simply deleting the first key, the
// required amount of times.
for (DWORD dwCounter = 0; dwCounter < dwMaxNumSubKeys; dwCounter++) {
DWORD dwLen = dwMaxNameSize;
HKEY hkeyChild;
// Get the first subkey
WKSP_RegGetKeyName(hkey, 0, pszBuffer, &dwLen);
lres = RegOpenKeyEx(hkey, pszBuffer, 0, KEY_ALL_ACCESS, &hkeyChild);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
// Delete any subkeys it may have
WKSP_RegDeleteSubKeys(hkeyChild);
// Delete this subkey
lres = RegCloseKey(hkeyChild);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
lres = RegDeleteKey(hkey, pszBuffer);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
}
free(pszBuffer);
}
void
WKSP_RegDeleteContents(
HKEY hkey
)
/*
Routine Description:
Deletes all of the values within the specified key.
Recursively deletes all subkeys. However, the specified key is not deleted.
Arguments:
hkey - Can't be NULL. Must be an open registry key.
--*/
{
Assert(hkey);
WKSP_RegDeleteValues(hkey);
WKSP_RegDeleteSubKeys(hkey);
}
BOOL
WKSP_RegDeleteKey(
HKEY hkeyParent,
PSTR pszKeyName
)
/*
Routine Description:
Deletes the key specified byt pszKeyName and all of its children.
Does not matter if it contains values and subkeys.
Arguments:
hkey - Can't be NULL. Must be an open registry key.
pszKeyName - Name of subkey to delete
--*/
{
Assert(hkeyParent);
Assert(pszKeyName);
HKEY hkeyChild;
long lres;
lres = RegOpenKeyEx(hkeyParent, pszKeyName, 0, KEY_ALL_ACCESS, &hkeyChild);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
if (ERROR_SUCCESS != lres) {
return FALSE;
}
WKSP_RegDeleteContents(hkeyChild);
lres = RegCloseKey(hkeyChild);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
if (ERROR_SUCCESS != lres) {
return FALSE;
}
lres = RegDeleteKey(hkeyParent, pszKeyName);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
if (ERROR_SUCCESS != lres) {
return FALSE;
}
return TRUE;
}
BOOL
WKSP_RegKeyExist(
HKEY hkeyParent,
PCSTR pszKeyName
)
/*
Routine Description:
Queries the registry as to whether the key exists.
The query consists of simply trying to open the reg key. This
can fail even though the key exists, but the user has insufficient
rights.
Arguments:
hkeyParent - Can't be NULL. Must be an open registry key.
pszKeyName - Name of registry key to open.
Returns:
TRUE - if it was possible to open the reg key.
FALSE - if it was not possible to open the reg key.
--*/
{
Assert(hkeyParent);
Assert(pszKeyName);
HKEY hkeyResult;
long lres = RegOpenKeyEx(hkeyParent, pszKeyName, 0, KEY_ALL_ACCESS, &hkeyResult);
if (ERROR_SUCCESS == lres) {
lres = RegCloseKey(hkeyResult);
#ifdef DBG
if (ERROR_SUCCESS != lres) {
WKSP_DisplayLastErrorMsgBox();
}
#endif
}
return ERROR_SUCCESS == lres;
}
HKEY
WKSP_RegKeyOpenCreate(
HKEY hkeyParent,
PCSTR pszKeyName,
PBOOL pbRegKeyCreated
)
/*
Routine Description:
Queries the registry as to whether the key exists.
The query consists of simply trying to open the reg key. This
can fail even though the key exists, but the user has insufficient
rights.
Arguments:
hkeyParent - Can't be NULL. Must be an open registry key.
pszKeyName - Name of key that is to be created and or opened.
pbRegKeyCreated - Can be NULL. If not NULL, it is assigned TRUE if the
reg key was created, FALSE if it already existed.
Returns:
An HKEY to the newly opened/created reg key.
--*/
{
HKEY hkeyResult = 0;
long lresult = 0;
BOOL bExist;
bExist = WKSP_RegKeyExist(hkeyParent, pszKeyName);
if (bExist) {
lresult = RegOpenKeyEx(hkeyParent, pszKeyName, 0, KEY_ALL_ACCESS, &hkeyResult);
} else {
DWORD dwDisposition;
lresult = RegCreateKeyEx(hkeyParent, pszKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyResult, &dwDisposition);
}
if (ERROR_SUCCESS != lresult) {
MessageBox(NULL, "An error occurred while trying to write to registry. "
"Please make sure your user account has permission to modify it.",
NULL,
MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
);
}
if (pbRegKeyCreated) {
*pbRegKeyCreated = !bExist;
}
return hkeyResult;
}
BOOL
WKSP_CmpRegName(
const void * const pv,
CGenInterface_WKSP * pGenInt
)
{
Assert(pv);
Assert(pGenInt);
return 0 == strcmp( (PSTR) pv, pGenInt->m_pszRegistryName);
}
PSTR
WKSP_DynaLoadStringWithArgs(
HINSTANCE hInstance,
UINT uID,
...
)
{
va_list va_arg;
va_start(va_arg, uID);
__declspec( thread ) static char szBuffer[1024 * 10] = {0};
PSTR psz = WKSP_DynaLoadString(hInstance, uID);
Assert(psz);
if (0x7c == uID) {
if (strlen(psz) > 48) {
DebugBreak();
}
}
vsprintf(szBuffer, psz, va_arg) ;
va_end(va_arg);
free(psz);
Assert(strlen(szBuffer) < sizeof(szBuffer));
return _strdup(szBuffer);
}
PSTR
WKSP_DynaLoadString(
HINSTANCE hInstance,
UINT uID
)
{
HRSRC hrsrc = NULL;
DWORD dwSize = 0;
PSTR pszStr = NULL;
// The strings are stored in groups of 16
hrsrc = FindResource(hInstance, MAKEINTRESOURCE(uID/16 +1), RT_STRING);
Assert(hrsrc);
dwSize = SizeofResource(hInstance, hrsrc);
if (dwSize) {
PSTR pszTmp = (PSTR) calloc(dwSize, 1);
if (pszTmp) {
// +2 to include the null terminators if it is terminated with 2 zeros
int nCharsCopied = LoadString(hInstance, uID, pszTmp, dwSize) +2;
Assert(nCharsCopied);
pszStr = (PSTR) malloc(nCharsCopied);
memcpy(pszStr, pszTmp, nCharsCopied);
free(pszTmp);
}
}
return pszStr;
}
PTSTR
WKSP_FormatLastErrorMessage()
{
PTSTR pszRetString = NULL;
PTSTR pszMsgBuf = NULL;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(PTSTR) &pszMsgBuf,
0,
NULL)) {
pszRetString = _strdup(pszMsgBuf);
LocalFree(pszMsgBuf);
}
return pszRetString;
}
void
WKSP_AppendStrToMultiStr(
PTSTR & pszOriginal,
PTSTR pszNewStrToAppend
)
{
if (!pszOriginal) {
// Alocate space for the double terminator
pszOriginal = (PSTR) calloc(strlen(pszNewStrToAppend) +2, sizeof(TCHAR));
strcpy(pszOriginal, pszNewStrToAppend);
return;
}
// +1 need to include the space for the NULL
UINT uSize = WKSP_MultiStrSize(pszOriginal);
// terminator of the new string
PSTR pszNewBuf = (PSTR) realloc(pszOriginal,
(uSize + strlen(pszNewStrToAppend) +1) * sizeof(TCHAR) );
if (pszNewBuf) {
// Add the new string
pszOriginal = pszNewBuf;
if (uSize) {
// Move the pointer to the end
pszNewBuf += uSize -1;
}
strcpy(pszNewBuf, pszNewStrToAppend);
pszNewBuf += strlen(pszNewStrToAppend) +1;
*pszNewBuf = NULL;
}
}