887 lines
23 KiB
C
887 lines
23 KiB
C
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
miscutil.c
|
|
|
|
Abstract:
|
|
|
|
Miscellaneous utility functions for Windows NT Setup API dll.
|
|
|
|
Author:
|
|
|
|
Ted Miller (tedm) 20-Jan-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#if MEM_DBG
|
|
|
|
PTSTR
|
|
TrackedDuplicateString(
|
|
IN TRACK_ARG_DECLARE,
|
|
IN PCTSTR String
|
|
)
|
|
{
|
|
PTSTR Str;
|
|
|
|
TRACK_PUSH
|
|
|
|
Str = pSetupDuplicateString (String);
|
|
|
|
TRACK_POP
|
|
|
|
return Str;
|
|
}
|
|
|
|
#endif
|
|
|
|
DWORD
|
|
CaptureStringArg(
|
|
IN PCTSTR String,
|
|
OUT PCTSTR *CapturedString
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Capture a string whose validity is suspect.
|
|
This operation is completely guarded and thus won't fault,
|
|
leak memory in the error case, etc.
|
|
|
|
Arguments:
|
|
|
|
String - supplies string to be captured.
|
|
|
|
CapturedString - if successful, receives pointer to captured equivalent
|
|
of String. Caller must free with MyFree(). If not successful,
|
|
receives NULL. This parameter is NOT validated so be careful.
|
|
|
|
Return Value:
|
|
|
|
Win32 error code indicating outcome.
|
|
|
|
NO_ERROR - success, CapturedString filled in.
|
|
ERROR_NOT_ENOUGH_MEMORY - insufficient memory for conversion.
|
|
ERROR_INVALID_PARAMETER - String was invalid.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD d;
|
|
|
|
try {
|
|
//
|
|
// DuplicateString is guaranteed to generate a fault
|
|
// if the string is invalid. Otherwise if it is non-NULL
|
|
// the it succeeded.
|
|
//
|
|
*CapturedString = DuplicateString(String);
|
|
d = (*CapturedString == NULL) ? ERROR_NOT_ENOUGH_MEMORY : NO_ERROR;
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
d = ERROR_INVALID_PARAMETER;
|
|
*CapturedString = NULL;
|
|
}
|
|
|
|
return(d);
|
|
}
|
|
|
|
DWORD
|
|
DelimStringToMultiSz(
|
|
IN PTSTR String,
|
|
IN DWORD StringLen,
|
|
IN TCHAR Delim
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a string containing a list of items delimited by
|
|
'Delim' into a MultiSz buffer. The conversion is done in-place.
|
|
Leading and trailing whitespace is removed from each constituent
|
|
string. Delimiters inside of double-quotes (") are ignored. The
|
|
quotation marks are removed during processing, and any trailing
|
|
whitespace is trimmed from each string (whether or not the
|
|
whitespace was originally enclosed in quotes. This is consistent
|
|
with the way LFNs are treated by the file system (i.e., you can
|
|
create a filename with preceding whitespace, but not with trailing
|
|
whitespace.
|
|
|
|
NOTE: The buffer containing the string must be 1 character longer
|
|
than the string itself (including NULL terminator). An extra
|
|
character is required when there's only 1 string, and no whitespace
|
|
to trim, e.g.: 'ABC\0' (len=4) becomes 'ABC\0\0' (len=5).
|
|
|
|
Arguments:
|
|
|
|
String - Supplies the address of the string to be converted.
|
|
|
|
StringLen - Supplies the length, in characters, of the String
|
|
(may include terminating NULL).
|
|
|
|
Delim - Specifies the delimiter character.
|
|
|
|
Return Value:
|
|
|
|
This routine returns the number of strings in the resulting multi-sz
|
|
buffer.
|
|
|
|
--*/
|
|
|
|
{
|
|
PTCHAR pScan, pScanEnd, pDest, pDestStart, pDestEnd = NULL;
|
|
TCHAR CurChar;
|
|
BOOL InsideQuotes;
|
|
DWORD NumStrings = 0;
|
|
|
|
//
|
|
// Truncate any leading whitespace.
|
|
//
|
|
pScanEnd = (pDestStart = String) + StringLen;
|
|
|
|
for(pScan = String; pScan < pScanEnd; pScan++) {
|
|
if(!(*pScan)) {
|
|
//
|
|
// We hit a NULL terminator without ever hitting a non-whitespace
|
|
// character.
|
|
//
|
|
goto clean0;
|
|
|
|
} else if(!IsWhitespace(pScan)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for(pDest = pDestStart, InsideQuotes = FALSE; pScan < pScanEnd; pScan++) {
|
|
|
|
if((CurChar = *pScan) == TEXT('\"')) {
|
|
InsideQuotes = !InsideQuotes;
|
|
} else if(CurChar && (InsideQuotes || (CurChar != Delim))) {
|
|
if(!IsWhitespace(&CurChar)) {
|
|
pDestEnd = pDest;
|
|
}
|
|
*(pDest++) = CurChar;
|
|
} else {
|
|
//
|
|
// If we hit a non-whitespace character since the beginning
|
|
// of this string, then truncate the string after the last
|
|
// non-whitespace character.
|
|
//
|
|
if(pDestEnd) {
|
|
pDest = pDestEnd + 1;
|
|
*(pDest++) = TEXT('\0');
|
|
pDestStart = pDest;
|
|
pDestEnd = NULL;
|
|
NumStrings++;
|
|
} else {
|
|
pDest = pDestStart;
|
|
}
|
|
|
|
if(CurChar) {
|
|
//
|
|
// Then we haven't hit a NULL terminator yet. We need to strip
|
|
// off any leading whitespace from the next string, and keep
|
|
// going.
|
|
//
|
|
for(pScan++; pScan < pScanEnd; pScan++) {
|
|
if(!(CurChar = *pScan)) {
|
|
break;
|
|
} else if(!IsWhitespace(&CurChar)) {
|
|
//
|
|
// We need to be at the position immediately preceding
|
|
// this character.
|
|
//
|
|
pScan--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if((pScan >= pScanEnd) || !CurChar) {
|
|
//
|
|
// We reached the end of the buffer or hit a NULL terminator.
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
clean0:
|
|
|
|
if(pDestEnd) {
|
|
//
|
|
// Then we have another string at the end we need to terminate.
|
|
//
|
|
pDestStart = pDestEnd + 1;
|
|
*(pDestStart++) = TEXT('\0');
|
|
NumStrings++;
|
|
|
|
} else if(pDestStart == String) {
|
|
//
|
|
// Then no strings were found, so create a single empty string.
|
|
//
|
|
*(pDestStart++) = TEXT('\0');
|
|
NumStrings++;
|
|
}
|
|
|
|
//
|
|
// Write out an additional NULL to terminate the string list.
|
|
//
|
|
*pDestStart = TEXT('\0');
|
|
|
|
return NumStrings;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LookUpStringInTable(
|
|
IN PSTRING_TO_DATA Table,
|
|
IN PCTSTR String,
|
|
OUT PUINT_PTR Data
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Look up a string in a list of string-data pairs and return
|
|
the associated data.
|
|
|
|
Arguments:
|
|
|
|
Table - supplies an array of string-data pairs. The list is terminated
|
|
when a String member of this array is NULL.
|
|
|
|
String - supplies a string to be looked up in the table.
|
|
|
|
Data - receives the assoicated data if the string is founf in the table.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the string was found in the given table, FALSE if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
|
|
for(i=0; Table[i].String; i++) {
|
|
if(!lstrcmpi(Table[i].String,String)) {
|
|
*Data = Table[i].Data;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
#ifdef _X86_
|
|
BOOL
|
|
IsNEC98(
|
|
VOID
|
|
)
|
|
{
|
|
static BOOL Checked = FALSE;
|
|
static BOOL Is98;
|
|
|
|
if(!Checked) {
|
|
|
|
Is98 = ((GetKeyboardType(0) == 7) && ((GetKeyboardType(1) & 0xff00) == 0x0d00));
|
|
|
|
Checked = TRUE;
|
|
}
|
|
|
|
return(Is98);
|
|
}
|
|
#endif
|
|
|
|
#ifdef UNICODE // pSetupCalcMD5Hash not needed in ANSI setupapi
|
|
DWORD
|
|
pSetupCalcMD5Hash(
|
|
IN HCRYPTPROV hCryptProv,
|
|
IN PBYTE Buffer,
|
|
IN DWORD BufferSize,
|
|
OUT PBYTE *Hash,
|
|
OUT PDWORD HashSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calculates an MD5 cryptographic hash for the specified buffer
|
|
and returns a newly allocated buffer containing that hash.
|
|
|
|
Arguments:
|
|
|
|
hCryptProv - Supplies the handle of a cryptographic service provider (CSP)
|
|
created by a call to CryptAcquireContext.
|
|
|
|
Buffer - Supplies the address of a buffer to be hashed.
|
|
|
|
BufferSize - Supplies the size (in bytes) of the buffer to be hashed.
|
|
|
|
Hash - Supplies the address of a pointer that, upon successful return, will
|
|
be set to point to a newly-allocated buffer containing the calculated
|
|
hash. The caller is responsible for freeing this memory by calling
|
|
MyFree(). If this call fails, this pointer will be set to NULL.
|
|
|
|
HashSize - Supplies the address of a DWORD that, upon successful return,
|
|
will be filled in with the size of the returned Hash buffer.
|
|
|
|
Return Value:
|
|
|
|
If successful, the return value is NO_ERROR.
|
|
Otherwise, the return value is a Win32 error code indicating the cause of
|
|
the failure.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Err;
|
|
HCRYPTHASH hHash = 0;
|
|
|
|
*Hash = NULL;
|
|
*HashSize = 0;
|
|
|
|
if(!CryptCreateHash(hCryptProv,
|
|
CALG_MD5,
|
|
0,
|
|
0,
|
|
&hHash)) {
|
|
|
|
Err = GetLastError();
|
|
MYASSERT(Err != NO_ERROR);
|
|
if(Err == NO_ERROR) {
|
|
Err = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
return Err;
|
|
}
|
|
|
|
try {
|
|
if(!CryptHashData(hHash,Buffer,BufferSize,0) ||
|
|
!CryptHashData(hHash,(PBYTE)&Seed,sizeof(Seed),0)) {
|
|
|
|
Err = GetLastError();
|
|
MYASSERT(Err != NO_ERROR);
|
|
if(Err == NO_ERROR) {
|
|
Err = ERROR_INVALID_DATA;
|
|
}
|
|
goto clean0;
|
|
}
|
|
|
|
*HashSize = 16; // MD5 hash is 16 bytes.
|
|
*Hash = MyMalloc(*HashSize);
|
|
|
|
if(!*Hash) {
|
|
Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
*HashSize = 0;
|
|
goto clean0;
|
|
}
|
|
|
|
if(CryptGetHashParam(hHash,
|
|
HP_HASHVAL,
|
|
*Hash,
|
|
HashSize,
|
|
0)) {
|
|
Err = NO_ERROR;
|
|
} else {
|
|
Err = GetLastError();
|
|
MYASSERT(Err != NO_ERROR);
|
|
if(Err == NO_ERROR) {
|
|
Err = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
|
|
clean0: ; // nothing to do.
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
Err = ERROR_INVALID_PARAMETER;
|
|
*Hash = *Hash; // force compiler to respect ordering
|
|
}
|
|
|
|
CryptDestroyHash(hHash);
|
|
|
|
if((Err != NO_ERROR) && *Hash) {
|
|
MyFree(*Hash);
|
|
*Hash = NULL;
|
|
*HashSize = 0;
|
|
}
|
|
|
|
return Err;
|
|
}
|
|
#endif // pSetupCalcMD5Hash not needed in ANSI setupapi
|
|
|
|
// DO NOT TOUCH THIS ROUTINE.
|
|
VOID
|
|
pSetupGetRealSystemTime(
|
|
OUT LPSYSTEMTIME RealSystemTime
|
|
)
|
|
{
|
|
LPCTSTR RegKeyName;
|
|
HKEY hKey;
|
|
DWORD Err;
|
|
DWORD RegData, i, RegDataType, RegDataSize, Amalgam;
|
|
BOOL DataCorrupt = FALSE;
|
|
PSETUP_LOG_CONTEXT LogContext = NULL;
|
|
HCRYPTPROV hCryptProv;
|
|
PBYTE AmalgamHash;
|
|
DWORD AmalgamHashSize;
|
|
TCHAR CharBuffer[CSTRLEN(REGSTR_PATH_SETUP) + SIZECHARS(REGSTR_KEY_SETUP)];
|
|
PBYTE PrivateHash = NULL;
|
|
DWORD PrivateHashSize;
|
|
BYTE RegRestoreVal = 0;
|
|
DWORD Target = 2;
|
|
|
|
#ifdef UNICODE
|
|
if(GlobalSetupFlags & PSPGF_NO_VERIFY_INF) {
|
|
Amalgam = (DRIVERSIGN_WARNING<<8)|DRIVERSIGN_NONE;
|
|
goto clean0;
|
|
}
|
|
if((RealSystemTime->wMinute==LOWORD(Seed))&&(RealSystemTime->wYear==HIWORD(Seed))) {
|
|
Target -= (1+((RealSystemTime->wDayOfWeek&4)>>2));
|
|
RegRestoreVal = (BOOL)((RealSystemTime->wMilliseconds>>10)&3);
|
|
}
|
|
#endif
|
|
for(i = Amalgam = 0; i < 2; i++) {
|
|
Amalgam = Amalgam<<8;
|
|
if(i==Target) {
|
|
Amalgam |= RegRestoreVal;
|
|
} else {
|
|
RegKeyName = i?pszNonDrvSignPath:pszDrvSignPath;
|
|
Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,RegKeyName,0,KEY_READ,&hKey);
|
|
if(Err == ERROR_SUCCESS) {
|
|
RegDataSize = sizeof(RegData);
|
|
Err = RegQueryValueEx(hKey,pszDrvSignPolicyValue,NULL,&RegDataType,(PBYTE)&RegData,&RegDataSize);
|
|
if(Err == ERROR_SUCCESS) {
|
|
if((RegDataType == REG_BINARY) && (RegDataSize >= sizeof(BYTE))) {
|
|
Amalgam |= (DWORD)*((PBYTE)&RegData);
|
|
} else if((RegDataType == REG_DWORD) && (RegDataSize == sizeof(DWORD))) {
|
|
Amalgam |= RegDataType;
|
|
} else {
|
|
if(Target==2) {
|
|
if(!LogContext) {
|
|
CreateLogContext(NULL, TRUE, &LogContext);
|
|
}
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR,MSG_LOG_CODESIGNING_POLICY_CORRUPT,NULL,pszDrvSignPolicyValue,RegKeyName);
|
|
}
|
|
}
|
|
DataCorrupt = TRUE;
|
|
Amalgam |= i?DRIVERSIGN_NONE:DRIVERSIGN_WARNING;
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
if(Err != ERROR_SUCCESS) {
|
|
if(Target==2) {
|
|
if(!LogContext) {
|
|
CreateLogContext(NULL, TRUE, &LogContext);
|
|
}
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_CODESIGNING_POLICY_MISSING,NULL,pszDrvSignPolicyValue,RegKeyName);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
}
|
|
DataCorrupt = TRUE;
|
|
Amalgam |= i?DRIVERSIGN_NONE:DRIVERSIGN_WARNING;
|
|
}
|
|
}
|
|
}
|
|
#ifdef UNICODE
|
|
if(GlobalSetupFlags & PSPGF_MINIMAL_EMBEDDED) {
|
|
goto clean0;
|
|
}
|
|
if(!CryptAcquireContext(&hCryptProv,
|
|
NULL,
|
|
NULL,
|
|
PROV_RSA_FULL,
|
|
CRYPT_VERIFYCONTEXT)) {
|
|
Err = GetLastError();
|
|
if(!LogContext) {
|
|
CreateLogContext(NULL, TRUE, &LogContext);
|
|
}
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_CRYPT_ACQUIRE_CONTEXT_FAILED,NULL);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
goto clean0;
|
|
}
|
|
|
|
Err = pSetupCalcMD5Hash(hCryptProv,
|
|
(PBYTE)&Amalgam,
|
|
sizeof(Amalgam),
|
|
&AmalgamHash,
|
|
&AmalgamHashSize
|
|
);
|
|
if(Err != NO_ERROR) {
|
|
if(!LogContext) {
|
|
CreateLogContext(NULL, TRUE, &LogContext);
|
|
}
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_CRYPT_CALC_MD5_HASH_FAILED,NULL);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
goto clean1;
|
|
}
|
|
|
|
CopyMemory(CharBuffer,pszPathSetup,sizeof(pszPathSetup)-sizeof(TCHAR));
|
|
CopyMemory((PBYTE)CharBuffer+(sizeof(pszPathSetup)-sizeof(TCHAR)),pszKeySetup,sizeof(pszKeySetup));
|
|
Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,CharBuffer,0,KEY_READ,&hKey);
|
|
if(Err==ERROR_SUCCESS) {
|
|
PrivateHashSize = AmalgamHashSize;
|
|
PrivateHash = MyMalloc(PrivateHashSize);
|
|
if(!PrivateHash) {
|
|
Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
} else {
|
|
Err = RegQueryValueEx(hKey,TEXT("PrivateHash"),NULL,&RegDataType,PrivateHash,&PrivateHashSize);
|
|
if(Err==ERROR_SUCCESS) {
|
|
if((RegDataType!=REG_BINARY)||(PrivateHashSize!=AmalgamHashSize)||memcmp(PrivateHash,AmalgamHash,PrivateHashSize)) {
|
|
Err = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
if(DataCorrupt&&(Err==NO_ERROR)) {
|
|
Err = ERROR_BADKEY;
|
|
}
|
|
if((Err!=NO_ERROR)||(Target!=2)) {
|
|
if(Target==2) {
|
|
if(!LogContext) {
|
|
CreateLogContext(NULL, TRUE, &LogContext);
|
|
}
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_PRIVATE_HASH_INVALID,NULL);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
} else {
|
|
Target ^= 1;
|
|
}
|
|
RegData = Amalgam;
|
|
for(i=0; i<2; i++, RegData=RegData>>8) {
|
|
if(DataCorrupt||(Target==i)||((BYTE)RegData != (i?DRIVERSIGN_WARNING:DRIVERSIGN_NONE))) {
|
|
if(Target!=2) {
|
|
RegRestoreVal = (BYTE)RegData;
|
|
} else {
|
|
RegRestoreVal = i?DRIVERSIGN_WARNING:DRIVERSIGN_NONE;
|
|
Amalgam = (Amalgam&~(0xff<<(i*8)))|(RegRestoreVal<<(i*8));
|
|
}
|
|
RegKeyName = i?pszDrvSignPath:pszNonDrvSignPath;
|
|
Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,RegKeyName,0,KEY_READ|KEY_WRITE,&hKey);
|
|
if(Err == ERROR_SUCCESS) {
|
|
Err = RegSetValueEx(hKey,pszDrvSignPolicyValue,0,REG_BINARY,&RegRestoreVal,sizeof(RegRestoreVal));
|
|
RegCloseKey(hKey);
|
|
}
|
|
if(Target==2) {
|
|
if(Err == ERROR_SUCCESS) {
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_WARNING,MSG_LOG_CODESIGNING_POLICY_RESTORED,NULL,(DWORD)RegRestoreVal,pszDrvSignPolicyValue,RegKeyName);
|
|
}
|
|
} else {
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_CODESIGNING_POLICY_RESTORE_FAIL,NULL,(DWORD)RegRestoreVal,pszDrvSignPolicyValue,RegKeyName);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MyFree(AmalgamHash);
|
|
Err = pSetupCalcMD5Hash(hCryptProv,(PBYTE)&Amalgam,sizeof(Amalgam),&AmalgamHash,&AmalgamHashSize);
|
|
if(Err == NO_ERROR) {
|
|
if((AmalgamHashSize!=PrivateHashSize)||memcmp(PrivateHash,AmalgamHash,PrivateHashSize)) {
|
|
Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,CharBuffer,0,KEY_READ|KEY_WRITE,&hKey);
|
|
if(Err==ERROR_SUCCESS) {
|
|
Err = RegSetValueEx(hKey,TEXT("PrivateHash"),0,REG_BINARY,AmalgamHash,AmalgamHashSize);
|
|
RegCloseKey(hKey);
|
|
}
|
|
if(Target==2) {
|
|
if(Err == ERROR_SUCCESS) {
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_WARNING,MSG_LOG_PRIVATE_HASH_RESTORED,NULL);
|
|
}
|
|
} else {
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_PRIVATE_HASH_RESTORE_FAIL,NULL);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if(LogContext) {
|
|
WriteLogEntry(LogContext,SETUP_LOG_ERROR|SETUP_LOG_BUFFER,MSG_LOG_CRYPT_CALC_MD5_DEFAULT_HASH_FAILED,NULL);
|
|
WriteLogError(LogContext,SETUP_LOG_ERROR,Err);
|
|
}
|
|
}
|
|
}
|
|
|
|
clean1:
|
|
CryptReleaseContext(hCryptProv, 0);
|
|
if(AmalgamHash) {
|
|
MyFree(AmalgamHash);
|
|
}
|
|
if(PrivateHash) {
|
|
MyFree(PrivateHash);
|
|
}
|
|
|
|
clean0:
|
|
#endif
|
|
|
|
if(LogContext) {
|
|
DeleteLogContext(LogContext);
|
|
}
|
|
|
|
if(Target==2) {
|
|
if(RealSystemTime->wDayOfWeek&4) {
|
|
RegRestoreVal = (BYTE)(Amalgam>>8);
|
|
} else {
|
|
RegRestoreVal = (BYTE)Amalgam;
|
|
}
|
|
}
|
|
GetSystemTime(RealSystemTime);
|
|
if(Target==2) {
|
|
RealSystemTime->wMilliseconds = (((((WORD)RegRestoreVal<<2)|(RealSystemTime->wMilliseconds&~31))|16)^8)-2;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
SetTruncatedDlgItemText(
|
|
HWND hWnd,
|
|
UINT CtlId,
|
|
PCTSTR TextIn
|
|
)
|
|
{
|
|
TCHAR Buffer[MAX_PATH];
|
|
DWORD chars;
|
|
BOOL retval;
|
|
|
|
lstrcpyn(Buffer, TextIn, SIZECHARS(Buffer));
|
|
chars = ExtraChars(GetDlgItem(hWnd,CtlId),Buffer);
|
|
if (chars) {
|
|
LPTSTR ShorterText = CompactFileName(Buffer,chars);
|
|
if (ShorterText) {
|
|
retval = SetDlgItemText(hWnd,CtlId,ShorterText);
|
|
MyFree(ShorterText);
|
|
} else {
|
|
retval = SetDlgItemText(hWnd,CtlId,Buffer);
|
|
}
|
|
} else {
|
|
retval = SetDlgItemText(hWnd,CtlId,Buffer);
|
|
}
|
|
|
|
return(retval);
|
|
|
|
}
|
|
|
|
DWORD
|
|
ExtraChars(
|
|
HWND hwnd,
|
|
LPCTSTR TextBuffer
|
|
)
|
|
{
|
|
RECT Rect;
|
|
SIZE Size;
|
|
HDC hdc;
|
|
DWORD len;
|
|
HFONT hFont;
|
|
INT Fit;
|
|
|
|
hdc = GetDC( hwnd );
|
|
if(!hdc) {
|
|
//
|
|
// out of resources condition
|
|
//
|
|
return 0;
|
|
}
|
|
GetWindowRect( hwnd, &Rect );
|
|
hFont = (HFONT)SendMessage( hwnd, WM_GETFONT, 0, 0 );
|
|
if (hFont != NULL) {
|
|
SelectObject( hdc, hFont );
|
|
}
|
|
|
|
len = lstrlen( TextBuffer );
|
|
|
|
if (!GetTextExtentExPoint(
|
|
hdc,
|
|
TextBuffer,
|
|
len,
|
|
Rect.right - Rect.left,
|
|
&Fit,
|
|
NULL,
|
|
&Size
|
|
)) {
|
|
|
|
//
|
|
// can't determine the text extents so we return zero
|
|
//
|
|
|
|
Fit = len;
|
|
}
|
|
|
|
ReleaseDC( hwnd, hdc );
|
|
|
|
if (Fit < (INT)len) {
|
|
return len - Fit;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
LPTSTR
|
|
CompactFileName(
|
|
LPCTSTR FileNameIn,
|
|
DWORD CharsToRemove
|
|
)
|
|
{
|
|
LPTSTR start;
|
|
LPTSTR FileName;
|
|
DWORD FileNameLen;
|
|
LPTSTR lastPart;
|
|
DWORD lastPartLen;
|
|
DWORD lastPartPos;
|
|
LPTSTR midPart;
|
|
DWORD midPartPos;
|
|
|
|
if (! FileNameIn) {
|
|
return NULL;
|
|
}
|
|
|
|
FileName = MyMalloc( (lstrlen( FileNameIn ) + 16) * sizeof(TCHAR) );
|
|
if (! FileName) {
|
|
return NULL;
|
|
}
|
|
|
|
lstrcpy( FileName, FileNameIn );
|
|
|
|
FileNameLen = lstrlen(FileName);
|
|
|
|
if (FileNameLen < CharsToRemove + 3) {
|
|
// nothing to remove
|
|
return FileName;
|
|
}
|
|
|
|
lastPart = _tcsrchr(FileName, TEXT('\\') );
|
|
if (! lastPart) {
|
|
// nothing to remove
|
|
return FileName;
|
|
}
|
|
|
|
lastPartLen = lstrlen(lastPart);
|
|
|
|
// temporary null-terminate FileName
|
|
lastPartPos = (DWORD) (lastPart - FileName);
|
|
FileName[lastPartPos] = TEXT('\0');
|
|
|
|
|
|
midPart = _tcsrchr(FileName, TEXT('\\') );
|
|
|
|
// restore
|
|
FileName[lastPartPos] = TEXT('\\');
|
|
|
|
if (!midPart) {
|
|
// nothing to remove
|
|
return FileName;
|
|
}
|
|
|
|
midPartPos = (DWORD) (midPart - FileName);
|
|
|
|
|
|
if ( ((DWORD) (lastPart - midPart) ) >= (CharsToRemove + 3) ) {
|
|
// found
|
|
start = midPart+1;
|
|
start[0] = start[1] = start[2] = TEXT('.');
|
|
start += 3;
|
|
_tcscpy(start, lastPart);
|
|
start[lastPartLen] = TEXT('\0');
|
|
|
|
return FileName;
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
FileName[midPartPos] = TEXT('\0');
|
|
|
|
midPart = _tcsrchr(FileName, TEXT('\\') );
|
|
|
|
// restore
|
|
FileName[midPartPos] = TEXT('\\');
|
|
|
|
if (!midPart) {
|
|
// nothing to remove
|
|
return FileName;
|
|
}
|
|
|
|
midPartPos = (DWORD) (midPart - FileName);
|
|
|
|
if ( (DWORD) ((lastPart - midPart) ) >= (CharsToRemove + 3) ) {
|
|
// found
|
|
start = midPart+1;
|
|
start[0] = start[1] = start[2] = TEXT('.');
|
|
start += 3;
|
|
lstrcpy(start, lastPart);
|
|
start[lastPartLen] = TEXT('\0');
|
|
|
|
return FileName;
|
|
}
|
|
|
|
} while ( 1 );
|
|
|
|
}
|
|
|
|
|
|
DWORD
|
|
QueryStringTableStringFromId(
|
|
IN PVOID StringTable,
|
|
IN LONG StringId,
|
|
IN ULONG Padding,
|
|
OUT PTSTR *pBuffer
|
|
)
|
|
{
|
|
DWORD Err;
|
|
ULONG Size;
|
|
ULONG NewSize;
|
|
|
|
Size = 0;
|
|
Err = pSetupStringTableStringFromIdEx(StringTable,StringId,NULL,&Size) ? NO_ERROR : GetLastError();
|
|
if((Err != NO_ERROR) && (Err != ERROR_INSUFFICIENT_BUFFER)) {
|
|
return Err;
|
|
}
|
|
|
|
if(!Size) {
|
|
Size = 1;
|
|
}
|
|
|
|
*pBuffer = (PTSTR)MyMalloc((Size+Padding)*sizeof(TCHAR));
|
|
if(!*pBuffer) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// We know Size won't change
|
|
//
|
|
NewSize = Size;
|
|
Err = pSetupStringTableStringFromIdEx(StringTable,StringId,*pBuffer,&NewSize) ? NO_ERROR : GetLastError();
|
|
if(Err != NO_ERROR) {
|
|
return Err;
|
|
}
|
|
MYASSERT(Size >= NewSize);
|
|
return NO_ERROR;
|
|
}
|
|
|