#include <windows.h>
#include "secure.hxx"
extern "C" {
#include "cci_debugging.h"
}
CcOsLock SecureClient::s_lock;
DWORD SecureClient::s_refcount = 0;
DWORD SecureClient::s_error = 0;
HANDLE SecureClient::s_hToken = 0;
#include "util.h"
#define SC "SecureClient::"
DWORD
SecureClient::Attach(
)
{
CcAutoLock AL(s_lock);
if (s_hToken) {
s_refcount++;
return 0;
}
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
&s_hToken)) {
s_refcount++;
s_error = 0;
} else {
s_hToken = 0;
s_error = GetLastError();
}
return s_error;
}
DWORD
SecureClient::Detach(
)
{
CcAutoLock AL(s_lock);
s_refcount--;
if (s_refcount) return 0;
if (!s_hToken) return 0;
DWORD error = 0;
if (!CloseHandle(s_hToken))
error = GetLastError();
s_hToken = 0;
s_error = 0;
return error;
}
DWORD SecureClient::Token(HANDLE& hToken) {
CcAutoLock AL(s_lock);
hToken = 0;
if (!s_hToken) {
cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error);
return s_error ? s_error : ERROR_INVALID_HANDLE;
}
else {
DWORD status = 0;
if (!DuplicateHandle(GetCurrentProcess(), s_hToken,
GetCurrentProcess(), &hToken, 0, FALSE,
DUPLICATE_SAME_ACCESS)) {
status = GetLastError();
cci_debug_printf(" Could not duplicate handle (%u)", status);
}
return status;
}
}
void
SecureClient::Start(SecureClient*& s) {
s = new SecureClient;
}
void
SecureClient::Stop(SecureClient*& s) {
delete s;
s = 0;
}
SecureClient::SecureClient():
m_Error(0),
m_hToken(0),
m_NeedRestore(false) {
HANDLE hThread = GetCurrentThread();
HANDLE hThDuplicate;
int status = DuplicateHandle( GetCurrentProcess(),
hThread,
GetCurrentProcess(),
&hThDuplicate,
TOKEN_ALL_ACCESS,
FALSE,
0);
if (!status) return;
if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) {
m_Error = GetLastError();
return;
}
if (SetThreadToken(&hThDuplicate, NULL)) {
m_NeedRestore = true;
} else {
m_Error = GetLastError();
}
CloseHandle(hThDuplicate);
}
SecureClient::~SecureClient() {
if (m_NeedRestore) {
HANDLE hThread = GetCurrentThread();
if (!SetThreadToken(&hThread, m_hToken)) {
m_Error = cci_check_error(GetLastError());
}
}
if (m_hToken) {
if (!CloseHandle(m_hToken)) {
m_Error = cci_check_error(GetLastError());
}
}
}
DWORD SecureClient::Error() {
return m_Error;
}