|
|
//****************************************************************************
//
// Copyright (c) 1993, Microsoft Corp.
//
// File: DOMDLGS.H
//
// Implementation file for registry management classes
//
// History:
// Scott V. Walker 10/5/94
//
//****************************************************************************
#include "stdafx.h"
#include "portable.h"
#include "regkey.h"
BOOL g_bLostConnection = FALSE;
//****************************************************************************
//
// CRegistryValue Implementation
//
//****************************************************************************
IMPLEMENT_DYNAMIC(CRegistryValue, CObject)
//****************************************************************************
//
// CRegistryValue::CRegistryValue
//
//****************************************************************************
CRegistryValue::CRegistryValue() { m_dwType = REG_NONE; m_dwDataLength = 0; m_pData = NULL; }
//****************************************************************************
//
// CRegistryValue::CRegistryValue
//
//****************************************************************************
CRegistryValue::CRegistryValue(LPCTSTR pszName, DWORD dwType, DWORD dwDataLength, LPBYTE pData) { Set(pszName, dwType, dwDataLength, pData); }
//****************************************************************************
//
// CRegistryValue::~CRegistryValue
//
//****************************************************************************
CRegistryValue::~CRegistryValue() { Empty(); }
//****************************************************************************
//
// CRegistryValue::Set
//
// Sets the value data fields. The data pointed to by pData is COPIED!
//
//****************************************************************************
void CRegistryValue::Set(LPCTSTR pszName, DWORD dwType, DWORD dwDataLength, LPBYTE pData) { Empty();
m_sName = pszName; m_dwType = dwType; m_dwDataLength = dwDataLength; if (dwDataLength == 0 || pData == NULL) m_pData = NULL; else { m_pData = new BYTE[dwDataLength]; memcpy(m_pData, pData, dwDataLength); } }
//****************************************************************************
//
// CRegistryValue::Get
//
// Gets the value data fields. The data pointed to by m_pData is COPIED
// into the buffer pointed to by pData... this buffer better be big enough!
// If pData is NULL, no copy is performed.
//
//****************************************************************************
void CRegistryValue::Get(CString &sName, DWORD &dwType, DWORD &dwDataLength, LPBYTE pData) { sName = m_sName; dwType = m_dwType; dwDataLength = m_dwDataLength; if (dwDataLength != 0 && pData != NULL) memcpy(pData, m_pData, m_dwDataLength); }
//****************************************************************************
//
// CRegistryValue::Empty
//
// Clear the value data and deletes its data buffer.
//
//****************************************************************************
void CRegistryValue::Empty() { m_sName.Empty(); m_dwType = REG_NONE; m_dwDataLength = 0; if (m_pData != NULL) delete m_pData; m_pData = NULL; }
//****************************************************************************
//
// CRegistryValue::operator=
//
// Assignment operator. Copies CRegistryValue object.
//
//****************************************************************************
const CRegistryValue& CRegistryValue::operator=(CRegistryValue &other) { Set(other.m_sName, other.m_dwType, other.m_dwDataLength, other.m_pData);
return *this; }
//****************************************************************************
//
// CRegistryKey Implementation
//
//****************************************************************************
IMPLEMENT_DYNAMIC(CRegistryKey, CObject)
//****************************************************************************
//
// CRegistryKey::CRegistryKey
//
//****************************************************************************
CRegistryKey::CRegistryKey() { // The lost connection status is initialized only once so that if a connection
// is ever lost we won't waste any time trying to close keys.
Initialize(); }
//****************************************************************************
//
// CRegistryKey::Initialize
//
//****************************************************************************
void CRegistryKey::Initialize() { m_bConnected = FALSE; m_bOpen = FALSE; m_bLocal = TRUE; m_bDirty = FALSE;
m_hkeyConnect = NULL; m_hkeyRemote = NULL; m_hkeyOpen = NULL; m_Sam = 0;
m_dwSubKeys = 0; m_dwMaxSubKey = 0; m_dwMaxClass = 0; m_dwValues = 0; m_dwMaxValueName = 0; m_dwMaxValueData = 0; m_dwSecurityDescriptor = 0;
m_ftLastWriteTime.dwLowDateTime = 0; m_ftLastWriteTime.dwHighDateTime = 0;
m_lResult = ERROR_SUCCESS; }
//****************************************************************************
//
// CRegistryKey::~CRegistryKey
//
// Destructor.
//
//****************************************************************************
CRegistryKey::~CRegistryKey() { if (g_bLostConnection) { // If we lost the registry connection, it will be useless to do anything.
return; }
// If we're currently open, then close.
if (m_bOpen) Close(TRUE);
// If we're currently connected, then disconnect.
if (m_bConnected) Disconnect(TRUE); }
//****************************************************************************
//
// CRegistryKey::Connect
//
//****************************************************************************
LONG CRegistryKey::Connect(LPCTSTR pszComputer, HKEY hkey) { if (g_bLostConnection) { return RPC_S_SERVER_UNAVAILABLE; }
TCHAR szName[MAX_COMPUTERNAME_LENGTH + 1]; CString sComputer; HKEY hkeyRemote; DWORD dwNumChars;
m_lResult = ERROR_SUCCESS;
if (m_bConnected) { m_lResult = Disconnect(TRUE); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult; }
// Is this the local machine?
dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
sComputer = pszComputer; GetComputerName(szName, &dwNumChars); if (sComputer.IsEmpty() || !lstrcmpi(pszComputer, szName)) { // Local
m_bLocal = TRUE; hkeyRemote = NULL; } else { // Remote
m_bLocal = FALSE; m_lResult = RegConnectRegistry(pszComputer, hkey, &hkeyRemote);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult; lstrcpy(szName, pszComputer); }
m_bConnected = TRUE; m_hkeyConnect = hkey; m_hkeyRemote = hkeyRemote; m_sComputer = szName;
return ERROR_SUCCESS; }
//****************************************************************************
//
// CRegistryKey::Disconnect
//
//****************************************************************************
LONG CRegistryKey::Disconnect(BOOL bForce) { m_lResult = ERROR_SUCCESS;
if (m_bConnected) { // Close the open key
if (m_bOpen) { m_lResult = Close(bForce); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (!bForce && m_lResult != ERROR_SUCCESS) return m_lResult; }
// Close the remote connection
if (!g_bLostConnection) { if (!m_bLocal) { m_lResult = RegCloseKey(m_hkeyRemote); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (!bForce && m_lResult != ERROR_SUCCESS) return m_lResult; } } }
Initialize();
return ERROR_SUCCESS; }
//****************************************************************************
//
// CRegistryKey::Create
//
//****************************************************************************
LONG CRegistryKey::Create(LPCTSTR pszKeyName, DWORD &dwDisposition, LPCTSTR pszClass, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecAttr) { if (g_bLostConnection) { return RPC_S_SERVER_UNAVAILABLE; } HKEY hkeyOpen, hkey;
m_lResult = ERROR_SUCCESS; dwDisposition = 0;
if (m_bOpen) { m_lResult = Close(TRUE); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult; }
// If not connected, default to \\Local_Machine\HKEY_LOCAL_MACHINE
if (!m_bConnected) { m_lResult = Connect(); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult; }
// Attempt to create the specified subkey
if (m_bLocal) hkey = m_hkeyConnect; else hkey = m_hkeyRemote;
m_lResult = RegCreateKeyEx(hkey, pszKeyName, 0, (LPTSTR)pszClass, REG_OPTION_NON_VOLATILE, samDesired, lpSecAttr, &hkeyOpen, &dwDisposition); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult;
m_lResult = RegCloseKey(hkeyOpen); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; return m_lResult; }
return Open(pszKeyName, samDesired); }
//****************************************************************************
//
// CRegistryKey::Open
//
//****************************************************************************
LONG CRegistryKey::Open(LPCTSTR pszKeyName, REGSAM samDesired) { if (g_bLostConnection) { return RPC_S_SERVER_UNAVAILABLE; }
HKEY hkeyOpen, hkey; CString sWork; int nPos;
m_lResult = ERROR_SUCCESS;
if (m_bOpen) { m_lResult = Close(TRUE); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult; }
// If not connected, default to \\Local_Machine\HKEY_LOCAL_MACHINE
if (!m_bConnected) { m_lResult = Connect(); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult; }
// Attempt to open the specified subkey
if (m_bLocal) hkey = m_hkeyConnect; else hkey = m_hkeyRemote; m_lResult = RegOpenKeyEx(hkey, pszKeyName, 0, samDesired, &hkeyOpen); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } if (m_lResult != ERROR_SUCCESS) return m_lResult;
// Attempt to get info about this key.
TCHAR szBuffer[1024 + 1]; DWORD dwClass, dwSubKeys, dwMaxSubKey, dwMaxClass, dwValues; DWORD dwMaxValueName, dwMaxValueData, dwSecurityDescriptor; FILETIME ftLastWriteTime;
dwClass = 1024 + 1; m_lResult = RegQueryInfoKey(hkeyOpen, szBuffer, &dwClass, 0, &dwSubKeys, &dwMaxSubKey, &dwMaxClass, &dwValues, &dwMaxValueName, &dwMaxValueData, &dwSecurityDescriptor, &ftLastWriteTime); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; return m_lResult; }
if (m_lResult != ERROR_SUCCESS) { RegCloseKey(hkeyOpen); return m_lResult; }
// Success! save all the data.
m_sFullName = pszKeyName; nPos = m_sFullName.ReverseFind('\\'); if (nPos >= 0) m_sKeyName = m_sFullName.Mid(nPos + 1); else m_sKeyName = m_sFullName;
m_hkeyOpen = hkeyOpen; m_bOpen = TRUE; m_Sam = samDesired; m_sClass = szBuffer; m_dwSubKeys = dwSubKeys; m_dwMaxSubKey = dwMaxSubKey; m_dwMaxClass = dwMaxClass; m_dwValues = dwValues; m_dwMaxValueName = dwMaxValueName; m_dwMaxValueData = dwMaxValueData; m_dwSecurityDescriptor = dwSecurityDescriptor; m_ftLastWriteTime = ftLastWriteTime;
return ERROR_SUCCESS; }
//****************************************************************************
//
// CRegistryKey::Close
//
//****************************************************************************
LONG CRegistryKey::Close(BOOL bForce) { if (!g_bLostConnection) {
m_lResult = ERROR_SUCCESS;
if (!m_bOpen) return ERROR_SUCCESS;
if (m_bDirty) { m_lResult = RegFlushKey(m_hkeyOpen); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (!bForce && m_lResult != ERROR_SUCCESS) return m_lResult; }
if (!g_bLostConnection) { m_lResult = RegCloseKey(m_hkeyOpen); if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (!bForce && m_lResult != ERROR_SUCCESS) return m_lResult; } }
m_bDirty = FALSE;
m_hkeyOpen = NULL; m_bOpen = FALSE; m_sFullName.Empty(); m_sClass.Empty(); m_Sam = 0;
m_dwSubKeys = 0; m_dwMaxSubKey = 0; m_dwMaxClass = 0; m_dwValues = 0; m_dwMaxValueName = 0; m_dwMaxValueData = 0; m_dwSecurityDescriptor = 0;
m_ftLastWriteTime.dwLowDateTime = 0; m_ftLastWriteTime.dwHighDateTime = 0;
if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return RPC_S_SERVER_UNAVAILABLE; } else { m_lResult = ERROR_SUCCESS; return ERROR_SUCCESS; } }
//****************************************************************************
//
// CRegistryKey::EnumValues
//
// Returns NULL if unsuccessful, returns empty array if successful but open
// key has no values.
// NOTE: Caller is responsible for deleting returned string array.
//
//****************************************************************************
CStringArray* CRegistryKey::EnumValues() { if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return NULL; } TCHAR szBuffer[1024 + 1]; DWORD dwLength; CStringArray *pArr; int i;
m_lResult = ERROR_SUCCESS;
if (!m_bOpen || g_bLostConnection) return NULL;
// Enumerate all the values into a string array
pArr = new CStringArray; i = 0; m_lResult = ERROR_SUCCESS; while (TRUE) { dwLength = 1024 + 1; m_lResult = RegEnumValue(m_hkeyOpen, i, szBuffer, &dwLength, NULL, NULL, NULL, NULL);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) break; if (dwLength > 0) pArr->Add(szBuffer); i++; }
// Did we find a normal end condition?
if (m_lResult == ERROR_NO_MORE_ITEMS) return pArr;
delete pArr; return NULL; }
//****************************************************************************
//
// CRegistryKey::EnumSubKeys
//
// Returns NULL if unsuccessful, returns empty array if successful but open
// key has no values.
// NOTE: Caller is responsible for deleting returned string array.
//
//****************************************************************************
CStringArray* CRegistryKey::EnumSubKeys() { if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return NULL; }
TCHAR szBuffer[1024 + 1]; DWORD dwLength; CStringArray *pArr; int i;
m_lResult = ERROR_SUCCESS;
if (!m_bOpen) return NULL;
// Enumerate all the subkeys into a string array
pArr = new CStringArray; i = 0;
while (TRUE) { dwLength = 1024 + 1; m_lResult = RegEnumKeyEx(m_hkeyOpen, i, szBuffer, &dwLength, NULL, NULL, NULL, NULL);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) break; if (dwLength > 0) pArr->Add(szBuffer); i++; }
// Did we find a normal end condition?
if (m_lResult == ERROR_NO_MORE_ITEMS) return pArr;
delete pArr; return NULL; }
//****************************************************************************
//
// CRegistryKey::GetValue
//
// Note: regval is always emptied regardless of success/failure
//
//****************************************************************************
BOOL CRegistryKey::GetValue(LPCTSTR pszValue, CRegistryValue ®val) {
DWORD dwLength, dwType; BYTE *pBuffer;
regval.Empty();
if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return FALSE; }
if (!m_bOpen) { m_lResult = ERROR_INVALID_FUNCTION; return FALSE; }
// Find out how big the data is
m_lResult = RegQueryValueEx(m_hkeyOpen, (LPTSTR)pszValue, NULL, NULL, NULL, &dwLength);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE;
if (dwLength == 0) return TRUE;
// Now make a buffer big enough for it.
pBuffer = new BYTE[dwLength]; if (pBuffer == NULL) return FALSE;
m_lResult = RegQueryValueEx(m_hkeyOpen, (LPTSTR)pszValue, NULL, &dwType, pBuffer, &dwLength);
if (m_lResult == ERROR_SUCCESS) regval.Set(pszValue, dwType, dwLength, pBuffer);
delete pBuffer;
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE;
return TRUE; }
//****************************************************************************
//
// CRegistryKey::SetValue
//
//****************************************************************************
BOOL CRegistryKey::SetValue(CRegistryValue ®val) { if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return FALSE; }
if (!m_bOpen) { m_lResult = ERROR_INVALID_FUNCTION; return FALSE; } if (regval.m_sName.IsEmpty()) { m_lResult = ERROR_INVALID_DATA; return FALSE; }
m_lResult = RegSetValueEx(m_hkeyOpen, regval.m_sName, 0, regval.m_dwType, regval.m_pData, regval.m_dwDataLength);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE;
m_bDirty = TRUE;
return TRUE; }
//****************************************************************************
//
// CRegistryKey::GetSubKey
//
// Note: If successful, regkey is returned connected and open on the
// specified key. If failure, regkey is returned disconnected.
//
//****************************************************************************
BOOL CRegistryKey::GetSubKey(LPCTSTR pszSubKey, CRegistryKey ®key) { if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return FALSE; }
CString sSubKey;
m_lResult = ERROR_SUCCESS;
if (!m_bOpen) return FALSE;
m_lResult = regkey.Disconnect(TRUE);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE;
// Try to connect and open same key
m_lResult = regkey.Connect(m_sComputer, m_hkeyConnect);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE; sSubKey = pszSubKey; m_lResult = regkey.Open(m_sFullName + "\\" + sSubKey, m_Sam);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) { regkey.Disconnect(TRUE); return FALSE; }
return TRUE; }
//****************************************************************************
//
// CRegistryKey::CreateSubKey
//
// Note: If successful, regkey is returned connected and open on the
// new key; if the key already existed, it is simply opened. If failure,
// regkey is returned disconnected.
//
//****************************************************************************
BOOL CRegistryKey::CreateSubKey( LPCTSTR pszSubKey, CRegistryKey ®key, LPCTSTR pszClass, LPSECURITY_ATTRIBUTES lpSecAttr, BOOL bIsVolatile) { if (g_bLostConnection) { m_lResult = RPC_S_SERVER_UNAVAILABLE; return FALSE; } CString sSubKey, sClass; HKEY hkeyOpen; DWORD dwDisposition;
m_lResult = ERROR_SUCCESS;
if (!m_bOpen) return FALSE;
m_lResult = regkey.Disconnect(TRUE);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE;
// Try to connect and open same key
m_lResult = regkey.Connect(m_sComputer, m_hkeyConnect);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE; sSubKey = pszSubKey; sClass = pszClass; DWORD dwRegOptions = bIsVolatile ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE; m_lResult = RegCreateKeyEx(m_hkeyOpen, sSubKey, 0, (LPTSTR)(LPCTSTR)sClass, dwRegOptions, m_Sam, lpSecAttr, &hkeyOpen, &dwDisposition);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) { regkey.Disconnect(TRUE); return FALSE; } m_lResult = RegCloseKey(hkeyOpen);
if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
if (m_lResult != ERROR_SUCCESS) return FALSE;
m_lResult = regkey.Open(m_sFullName + "\\" + sSubKey, m_Sam);
if (m_lResult != ERROR_SUCCESS) { if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; }
regkey.Disconnect(TRUE); return FALSE; }
m_bDirty = TRUE; if (dwDisposition == REG_CREATED_NEW_KEY) regkey.m_bDirty = TRUE;
return TRUE; }
//****************************************************************************
//
// CRegistryKey::DeleteSubKey
//
//****************************************************************************
BOOL CRegistryKey::DeleteSubKey(LPCTSTR pszSubKey) { if (g_bLostConnection) { return FALSE; }
CString sSubKey; CRegistryKey subkey; int i;
m_lResult = ERROR_SUCCESS; sSubKey = pszSubKey;
if (!m_bOpen) return FALSE;
if (!GetSubKey(sSubKey, subkey)) return FALSE;
// Delete all subkeys of the specified subkey (RegDeleteKey limitation)
CStringArray *parr = subkey.EnumSubKeys(); for (i=0; i<parr->GetSize(); i++) { if (!subkey.DeleteSubKey(parr->GetAt(i))) return FALSE; } delete parr;
subkey.Close(TRUE);
m_lResult = RegDeleteKey(m_hkeyOpen, sSubKey); if (m_lResult != ERROR_SUCCESS) { if ((m_lResult == RPC_S_SERVER_UNAVAILABLE) || (m_lResult == RPC_S_CALL_FAILED)) { g_bLostConnection = TRUE; } return FALSE; }
return TRUE; }
|