929 lines
19 KiB
C++
929 lines
19 KiB
C++
/*++
|
|
|
|
Copyright (c) 1999-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
RemoteDesktopUtils
|
|
|
|
Abstract:
|
|
|
|
Misc. RD Utils
|
|
|
|
Author:
|
|
|
|
Tad Brockway 02/00
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifdef TRC_FILE
|
|
#undef TRC_FILE
|
|
#endif
|
|
|
|
#define TRC_FILE "_rdsutl"
|
|
|
|
|
|
#include <winsock2.h>
|
|
#include <RemoteDesktop.h>
|
|
#include "RemoteDesktopUtils.h"
|
|
#include "base64.h"
|
|
//#include "RemoteDesktopDBG.h"
|
|
|
|
int
|
|
GetClientmachineAddressList(
|
|
OUT CComBSTR& clientmachineAddressList
|
|
)
|
|
/*++
|
|
|
|
|
|
--*/
|
|
{
|
|
char hostname[MAX_PATH+1];
|
|
int errCode = 0;
|
|
|
|
struct hostent* pHostEnt;
|
|
|
|
if( gethostname(hostname, sizeof(hostname)) != 0 ) {
|
|
errCode = WSAGetLastError();
|
|
}
|
|
else {
|
|
|
|
pHostEnt = gethostbyname( hostname );
|
|
if( NULL != pHostEnt ) {
|
|
clientmachineAddressList = pHostEnt->h_name;
|
|
}
|
|
else {
|
|
errCode = WSAGetLastError();
|
|
}
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
|
|
BSTR
|
|
CreateConnectParmsString(
|
|
IN DWORD protocolType,
|
|
IN CComBSTR &machineAddressList,
|
|
IN CComBSTR &assistantAccount,
|
|
IN CComBSTR &assistantAccountPwd,
|
|
IN CComBSTR &helpSessionID,
|
|
IN CComBSTR &helpSessionName,
|
|
IN CComBSTR &helpSessionPwd,
|
|
IN CComBSTR &protocolSpecificParms
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a connect parms string. Format is:
|
|
|
|
"protocolType,machineAddressList,assistantAccount,assistantAccountPwd,helpSessionName,helpSessionPwd,protocolSpecificParms"
|
|
|
|
Arguments:
|
|
|
|
protocolType - Identifies the protocol type.
|
|
See RemoteDesktopChannels.h
|
|
machineAddressList - Identifies network address of server machine.
|
|
assistantAccountName - Account name for initial log in to server
|
|
machine, ignore for Whistler
|
|
assistantAccountNamePwd - Password for assistantAccountName
|
|
helpSessionID - Help session identifier.
|
|
helpSessionName - Help session name.
|
|
helpSessionPwd - Password to help session once logged in to server
|
|
machine.
|
|
protocolSpecificParms - Parameters specific to a particular protocol.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
CComBSTR result;
|
|
WCHAR buf[256];
|
|
|
|
UNREFERENCED_PARAMETER(assistantAccount);
|
|
|
|
//
|
|
// Add a version stamp for our connect parm.
|
|
wsprintf(buf, TEXT("%ld"), SALEM_CURRENT_CONNECTPARM_VERSION);
|
|
result = buf;
|
|
result += TEXT(",");
|
|
|
|
wsprintf(buf, TEXT("%ld"), protocolType);
|
|
result += buf;
|
|
result += TEXT(",");
|
|
result += machineAddressList;
|
|
result += TEXT(",");
|
|
result += assistantAccountPwd;
|
|
result += TEXT(",");
|
|
result += helpSessionID;
|
|
result += TEXT(",");
|
|
result += helpSessionName;
|
|
result += TEXT(",");
|
|
result += helpSessionPwd;
|
|
|
|
if (protocolSpecificParms.Length() > 0) {
|
|
result += TEXT(",");
|
|
result += protocolSpecificParms;
|
|
}
|
|
|
|
return result.Detach();
|
|
}
|
|
|
|
DWORD
|
|
ParseHelpAccountName(
|
|
IN BSTR helpAccount,
|
|
OUT CComBSTR& machineAddressList,
|
|
OUT CComBSTR& AccountName
|
|
)
|
|
/*++
|
|
|
|
HelpAccount in connection parameter is <machineAddressList>\HelpAssistant.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("ParseHelpAccountName");
|
|
BSTR tmp;
|
|
WCHAR *tok;
|
|
DWORD result = ERROR_SUCCESS;
|
|
DWORD len;
|
|
|
|
//
|
|
// Make a copy of the input string so we can parse it.
|
|
//
|
|
tmp = SysAllocString(helpAccount);
|
|
if (tmp == NULL) {
|
|
TRC_ERR((TB, TEXT("Can't allocate parms string.")));
|
|
result = ERROR_OUTOFMEMORY;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
machineAddressList = L"";
|
|
AccountName = L"";
|
|
|
|
//
|
|
// Machine Name
|
|
//
|
|
tok = wcstok(tmp, L"\\");
|
|
if (tok != NULL) {
|
|
machineAddressList = tok;
|
|
}
|
|
else {
|
|
//
|
|
// for backward compatible.
|
|
//
|
|
machineAddressList = L"";
|
|
AccountName = helpAccount;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Actual help assistant account name.
|
|
//
|
|
len = wcslen(helpAccount);
|
|
if (tok < (tmp + len)) {
|
|
tok += wcslen(tok);
|
|
tok += 1;
|
|
if (*tok != L'\0') {
|
|
AccountName = tok;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Help Assistant accout name must be in the string or
|
|
// this is critical error.
|
|
//
|
|
if( AccountName.Length() == 0 ) {
|
|
result = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
if (tmp != NULL) {
|
|
SysFreeString(tmp);
|
|
}
|
|
|
|
DC_END_FN();
|
|
return result;
|
|
}
|
|
|
|
DWORD
|
|
ParseConnectParmsString(
|
|
IN BSTR parmsString,
|
|
OUT DWORD* pdwConnParmVersion,
|
|
OUT DWORD *protocolType,
|
|
OUT CComBSTR &machineAddressList,
|
|
OUT CComBSTR &assistantAccount,
|
|
OUT CComBSTR &assistantAccountPwd,
|
|
OUT CComBSTR &helpSessionID,
|
|
OUT CComBSTR &helpSessionName,
|
|
OUT CComBSTR &helpSessionPwd,
|
|
OUT CComBSTR &protocolSpecificParms
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse a connect string created by a call to CreateConnectParmsString.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS on success. Otherwise, an error code is returned.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("ParseConnectParmsString");
|
|
BSTR tmp;
|
|
WCHAR *tok;
|
|
DWORD result = ERROR_SUCCESS;
|
|
DWORD len;
|
|
DWORD dwVersion = 0;
|
|
|
|
UNREFERENCED_PARAMETER(assistantAccount);
|
|
|
|
//
|
|
// Make a copy of the input string so we can parse it.
|
|
//
|
|
tmp = SysAllocString(parmsString);
|
|
if (tmp == NULL) {
|
|
TRC_ERR((TB, TEXT("Can't allocate parms string.")));
|
|
result = ERROR_OUTOFMEMORY;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Retrieve connect parm version stamp, Whistler beta 1
|
|
// connect parm does not have version stamp, bail out,
|
|
// sessmgr/termsrv will wipe out pending help.
|
|
//
|
|
tok = wcstok(tmp, L",");
|
|
if (tok != NULL) {
|
|
dwVersion = _wtol(tok);
|
|
}
|
|
else {
|
|
result = ERROR_INVALID_USER_BUFFER;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
if( dwVersion < SALEM_FIRST_VALID_CONNECTPARM_VERSION ) {
|
|
//
|
|
// connect parm is whistler beta 1
|
|
//
|
|
result = ERROR_NOT_SUPPORTED;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
*pdwConnParmVersion = dwVersion;
|
|
|
|
//
|
|
// We have no use for version at this time,
|
|
// future update on connect parm should
|
|
// take make the necessary change
|
|
//
|
|
|
|
//
|
|
// Protocol.
|
|
//
|
|
tok = wcstok(NULL, L",");
|
|
if (tok != NULL) {
|
|
*protocolType = _wtoi(tok);
|
|
}
|
|
|
|
//
|
|
// Machine Name
|
|
//
|
|
tok = wcstok(NULL, L",");
|
|
if (tok != NULL) {
|
|
machineAddressList = tok;
|
|
}
|
|
else {
|
|
result = ERROR_INVALID_USER_BUFFER;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Assistant Account Password
|
|
//
|
|
tok = wcstok(NULL, L",");
|
|
if (tok != NULL) {
|
|
assistantAccountPwd = tok;
|
|
}
|
|
else {
|
|
result = ERROR_INVALID_USER_BUFFER;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Help Session ID
|
|
//
|
|
tok = wcstok(NULL, L",");
|
|
if (tok != NULL) {
|
|
helpSessionID = tok;
|
|
}
|
|
else {
|
|
result = ERROR_INVALID_USER_BUFFER;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Help Session Name
|
|
//
|
|
tok = wcstok(NULL, L",");
|
|
if (tok != NULL) {
|
|
helpSessionName = tok;
|
|
}
|
|
else {
|
|
result = ERROR_INVALID_USER_BUFFER;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Help Session Password
|
|
//
|
|
tok = wcstok(NULL, L",");
|
|
if (tok != NULL) {
|
|
helpSessionPwd = tok;
|
|
}
|
|
else {
|
|
result = ERROR_INVALID_USER_BUFFER;
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Protocol-Specific Parms
|
|
//
|
|
len = wcslen(parmsString);
|
|
if (tok < (tmp + len)) {
|
|
tok += wcslen(tok);
|
|
tok += 1;
|
|
if (*tok != L'\0') {
|
|
protocolSpecificParms = tok;
|
|
}
|
|
else {
|
|
protocolSpecificParms = L"";
|
|
}
|
|
}
|
|
else {
|
|
protocolSpecificParms = L"";
|
|
}
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
if (result != ERROR_SUCCESS) {
|
|
TRC_ERR((TB, TEXT("Error parsing %s"), parmsString));
|
|
}
|
|
|
|
if (tmp != NULL) {
|
|
SysFreeString(tmp);
|
|
}
|
|
|
|
DC_END_FN();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
BSTR
|
|
ReallocBSTR(
|
|
IN BSTR origStr,
|
|
IN DWORD requiredByteLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Realloc a BSTR
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
The realloc'd string on success. Otherwise, NULL is returned.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("ReallocBSTR");
|
|
|
|
BSTR tmp;
|
|
DWORD len;
|
|
DWORD origLen;
|
|
|
|
//
|
|
// Allocate the new string.
|
|
//
|
|
tmp = SysAllocStringByteLen(NULL, requiredByteLen);
|
|
if (tmp == NULL) {
|
|
TRC_ERR((TB, TEXT("Failed to allocate %ld bytes."), requiredByteLen));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
//
|
|
// Copy data from the original string.
|
|
//
|
|
origLen = SysStringByteLen(origStr);
|
|
len = origLen <= requiredByteLen ? origLen : requiredByteLen;
|
|
memcpy(tmp, origStr, len);
|
|
|
|
//
|
|
// Release the old string.
|
|
//
|
|
SysFreeString(origStr);
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
DC_END_FN();
|
|
|
|
return tmp;
|
|
}
|
|
|
|
DWORD
|
|
CreateSystemSid(
|
|
PSID *ppSystemSid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a SYSTEM SID.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS on success. Otherwise, an error code is returned.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("CreateSystemSid");
|
|
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
PSID pSid;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
TRC_ASSERT(ppSystemSid != NULL, (TB, L"ppSystemSid != NULL"));
|
|
|
|
if( TRUE == AllocateAndInitializeSid(
|
|
&SidAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&pSid
|
|
) )
|
|
{
|
|
*ppSystemSid = pSid;
|
|
}
|
|
else
|
|
{
|
|
dwStatus = GetLastError();
|
|
}
|
|
|
|
DC_END_FN();
|
|
return dwStatus;
|
|
}
|
|
|
|
BOOL
|
|
IsSystemToken(
|
|
HANDLE TokenHandle,
|
|
PSID pSystemSid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns whether the current token is running under SYSTEM security.
|
|
|
|
Arguments:
|
|
|
|
TokenHandle - Param1 Thread or process token
|
|
pSystemSid - System SID.
|
|
|
|
Return Value:
|
|
|
|
TRUE if System token. FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("IsSystemToken");
|
|
|
|
BOOL Result = FALSE;
|
|
ULONG ReturnLength, BufferLength;
|
|
DWORD dwStatus;
|
|
PTOKEN_USER pTokenUser = NULL;
|
|
|
|
TRC_ASSERT(NULL != pSystemSid, (TB, L"NULL != pSystemSid"));
|
|
|
|
// Get user SID.
|
|
ReturnLength = 0;
|
|
Result = GetTokenInformation(
|
|
TokenHandle,
|
|
TokenUser,
|
|
NULL,
|
|
0,
|
|
&ReturnLength
|
|
);
|
|
|
|
if( ReturnLength == 0 )
|
|
{
|
|
TRC_ERR((TB, L"GetTokenInformation: %08X", GetLastError()));
|
|
Result = FALSE;
|
|
CloseHandle( TokenHandle );
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
BufferLength = ReturnLength;
|
|
|
|
pTokenUser = (PTOKEN_USER)LocalAlloc( LPTR, BufferLength );
|
|
if( pTokenUser == NULL )
|
|
{
|
|
TRC_ERR((TB, L"LocalAlloc: %08X", GetLastError()));
|
|
Result = FALSE;
|
|
CloseHandle( TokenHandle );
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
Result = GetTokenInformation(
|
|
TokenHandle,
|
|
TokenUser,
|
|
pTokenUser,
|
|
BufferLength,
|
|
&ReturnLength
|
|
);
|
|
|
|
CloseHandle( TokenHandle );
|
|
|
|
if( TRUE == Result ) {
|
|
Result = EqualSid( pTokenUser->User.Sid, pSystemSid);
|
|
}
|
|
else {
|
|
TRC_ERR((TB, L"GetTokenInformation: %08X", GetLastError()));
|
|
}
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
if( pTokenUser )
|
|
{
|
|
LocalFree( pTokenUser );
|
|
}
|
|
|
|
DC_END_FN();
|
|
return Result;
|
|
}
|
|
|
|
BOOL
|
|
IsCallerSystem(
|
|
PSID pSystemSid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns whether the current thread is running under SYSTEM security.
|
|
|
|
NOTE: Caller should be impersonated prior to invoking this function.
|
|
|
|
Arguments:
|
|
|
|
pSystemSid - System SID.
|
|
|
|
Return Value:
|
|
|
|
TRUE if System. FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("IsCallerSystem");
|
|
BOOL Result;
|
|
HANDLE TokenHandle;
|
|
|
|
//
|
|
// Open the thread token and check if System token.
|
|
//
|
|
Result = OpenThreadToken(
|
|
GetCurrentThread(),
|
|
TOKEN_QUERY,
|
|
FALSE, // Use impersonation
|
|
&TokenHandle
|
|
);
|
|
|
|
if( TRUE == Result ) {
|
|
//
|
|
// This token should not be released. This function does not leak
|
|
// handles.
|
|
//
|
|
Result = IsSystemToken(TokenHandle, pSystemSid);
|
|
}
|
|
else {
|
|
TRC_ERR((TB, L"OpenThreadToken: %08X", GetLastError()));
|
|
}
|
|
DC_END_FN();
|
|
return Result;
|
|
}
|
|
|
|
|
|
void
|
|
AttachDebugger(
|
|
LPCTSTR pszDebugger
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Attach debugger to our process or process hosting our DLL.
|
|
|
|
Parameters:
|
|
|
|
pszDebugger : Debugger command, e.g. ntsd -d -g -G -p %d
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
Note:
|
|
|
|
Must have "-p %d" since we don't know debugger's parameter for process.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Attach debugger
|
|
//
|
|
if( !IsDebuggerPresent() ) {
|
|
|
|
TCHAR szCommand[256];
|
|
PROCESS_INFORMATION ProcessInfo;
|
|
STARTUPINFO StartupInfo;
|
|
|
|
//
|
|
// ntsd -d -g -G -p %d
|
|
//
|
|
wsprintf( szCommand, pszDebugger, GetCurrentProcessId() );
|
|
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
|
|
StartupInfo.cb = sizeof(StartupInfo);
|
|
|
|
if (!CreateProcess(NULL, szCommand, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo)) {
|
|
return;
|
|
}
|
|
else {
|
|
|
|
CloseHandle(ProcessInfo.hProcess);
|
|
CloseHandle(ProcessInfo.hThread);
|
|
|
|
while (!IsDebuggerPresent())
|
|
{
|
|
Sleep(500);
|
|
}
|
|
}
|
|
} else {
|
|
DebugBreak();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
AttachDebuggerIfAsked(HINSTANCE hInst)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check if debug enable flag in our registry HKLM\Software\Microsoft\Remote Desktop\<module name>,
|
|
if enable, attach debugger to running process.
|
|
|
|
Parameter :
|
|
|
|
hInst : instance handle.
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CRegKey regKey;
|
|
DWORD dwStatus;
|
|
TCHAR szModuleName[MAX_PATH+1];
|
|
TCHAR szFileName[MAX_PATH+1];
|
|
CComBSTR bstrRegKey(_TEXT("Software\\Microsoft\\Remote Desktop\\"));
|
|
TCHAR szDebugCmd[256];
|
|
DWORD cbDebugCmd = sizeof(szDebugCmd)/sizeof(szDebugCmd[0]);
|
|
|
|
dwStatus = GetModuleFileName( hInst, szModuleName, MAX_PATH+1 );
|
|
if( 0 == dwStatus ) {
|
|
//
|
|
// Can't attach debugger with name.
|
|
//
|
|
return;
|
|
}
|
|
|
|
_tsplitpath( szModuleName, NULL, NULL, szFileName, NULL );
|
|
bstrRegKey += szFileName;
|
|
|
|
//
|
|
// Check if we are asked to attach/break into debugger
|
|
//
|
|
dwStatus = regKey.Open( HKEY_LOCAL_MACHINE, bstrRegKey );
|
|
if( 0 != dwStatus ) {
|
|
return;
|
|
}
|
|
|
|
dwStatus = regKey.QueryValue( szDebugCmd, _TEXT("Debugger"), &cbDebugCmd );
|
|
if( 0 != dwStatus || cbDebugCmd > 200 ) {
|
|
// 200 chars is way too much for debugger command.
|
|
return;
|
|
}
|
|
|
|
AttachDebugger( szDebugCmd );
|
|
return;
|
|
}
|
|
|
|
DWORD
|
|
HashSecurityData(
|
|
IN PBYTE const pbData,
|
|
IN DWORD cbData,
|
|
OUT CComBSTR& bstrHashedData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Hash a blob of data and return hased data in BSTR
|
|
|
|
Parameters:
|
|
|
|
pbData : Pointer to data to be hashed.
|
|
cbData : Size of data to be hashed.
|
|
bstrHashedData : Return hashed data in BSTR form.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS or error code.
|
|
|
|
--*/
|
|
{
|
|
DC_BEGIN_FN("HashSecurityData");
|
|
|
|
DWORD dwStatus;
|
|
LPSTR pbEncodedData = NULL;
|
|
DWORD cbEncodedData = 0;
|
|
|
|
PBYTE pbHashedData = NULL;
|
|
DWORD cbHashedData = 0;
|
|
DWORD dwSize;
|
|
|
|
HCRYPTPROV hCryptProv = NULL;
|
|
HCRYPTHASH hHash = NULL;
|
|
|
|
BOOL bSuccess;
|
|
|
|
bSuccess = CryptAcquireContext(
|
|
&hCryptProv,
|
|
NULL,
|
|
NULL,
|
|
PROV_RSA_FULL,
|
|
CRYPT_VERIFYCONTEXT
|
|
);
|
|
|
|
if( FALSE == bSuccess ) {
|
|
dwStatus = GetLastError();
|
|
TRC_ERR((TB, L"CryptAcquireContext: %08X", dwStatus));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
bSuccess = CryptCreateHash(
|
|
hCryptProv,
|
|
CALG_SHA1,
|
|
0,
|
|
0,
|
|
&hHash
|
|
);
|
|
|
|
if( FALSE == bSuccess ) {
|
|
dwStatus = GetLastError();
|
|
TRC_ERR((TB, L"CryptCreateHash: %08X", dwStatus));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
|
|
bSuccess = CryptHashData(
|
|
hHash,
|
|
pbData,
|
|
cbData,
|
|
0
|
|
);
|
|
|
|
if( FALSE == bSuccess ) {
|
|
dwStatus = GetLastError();
|
|
TRC_ERR((TB, L"CryptHashData: %08X", dwStatus));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
|
|
dwSize = sizeof( cbHashedData );
|
|
bSuccess = CryptGetHashParam(
|
|
hHash,
|
|
HP_HASHSIZE,
|
|
(PBYTE)&cbHashedData,
|
|
&dwSize,
|
|
0
|
|
);
|
|
|
|
if( FALSE == bSuccess ) {
|
|
dwStatus = GetLastError();
|
|
TRC_ERR((TB, L"CryptGetHashParam with HP_HASHSIZE : %08X", dwStatus));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
pbHashedData = (PBYTE)LocalAlloc(LPTR, cbHashedData);
|
|
if( NULL == pbHashedData ) {
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
bSuccess = CryptGetHashParam(
|
|
hHash,
|
|
HP_HASHVAL,
|
|
pbHashedData,
|
|
&cbHashedData,
|
|
0
|
|
);
|
|
|
|
if( FALSE == bSuccess ) {
|
|
dwStatus = GetLastError();
|
|
TRC_ERR((TB, L"CryptGetHashParam with HP_HASHVAL : %08X", dwStatus));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
|
|
//
|
|
// Hash data and convert to string form.
|
|
//
|
|
dwStatus = LSBase64EncodeA(
|
|
pbHashedData,
|
|
cbHashedData,
|
|
NULL,
|
|
&cbEncodedData
|
|
);
|
|
|
|
if( ERROR_SUCCESS != dwStatus ) {
|
|
TRC_ERR((TB, L"LSBase64EncodeA : %08X", dwStatus));
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
pbEncodedData = (LPSTR) LocalAlloc( LPTR, cbEncodedData+1 );
|
|
if( NULL == pbEncodedData ) {
|
|
dwStatus = GetLastError();
|
|
goto CLEANUPANDEXIT;
|
|
}
|
|
|
|
dwStatus = LSBase64EncodeA(
|
|
pbHashedData,
|
|
cbHashedData,
|
|
pbEncodedData,
|
|
&cbEncodedData
|
|
);
|
|
|
|
if( ERROR_SUCCESS == dwStatus ) {
|
|
|
|
//
|
|
// Base64 encoding always add '\r', '\n' at the end,
|
|
// remove it
|
|
//
|
|
if( pbEncodedData[cbEncodedData - 1] == '\n' &&
|
|
pbEncodedData[cbEncodedData - 2] == '\r' )
|
|
{
|
|
pbEncodedData[cbEncodedData - 2] = 0;
|
|
cbEncodedData -= 2;
|
|
}
|
|
|
|
bstrHashedData = pbEncodedData;
|
|
}
|
|
else {
|
|
TRC_ERR((TB, L"LSBase64EncodeA : %08X", dwStatus));
|
|
}
|
|
|
|
CLEANUPANDEXIT:
|
|
|
|
if( NULL != pbEncodedData ) {
|
|
LocalFree( pbEncodedData );
|
|
}
|
|
|
|
if( NULL != pbHashedData ) {
|
|
LocalFree( pbHashedData );
|
|
}
|
|
|
|
if( NULL != hHash ) {
|
|
CryptDestroyHash( hHash );
|
|
}
|
|
|
|
if( NULL != hCryptProv ) {
|
|
CryptReleaseContext( hCryptProv, 0 );
|
|
}
|
|
|
|
DC_END_FN();
|
|
return dwStatus;
|
|
}
|