You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1746 lines
50 KiB
1746 lines
50 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// iasmdbtool.cpp
|
|
//
|
|
// Abstract:
|
|
//
|
|
// dump the "Properties" table from ias.mdb to a text format
|
|
// and also restore ias.mdb from such dump
|
|
// saves and restore the reg keys too.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
#include "stdafx.h"
|
|
|
|
#include <string>
|
|
#include <shlwapi.h>
|
|
#include "datastore2.h"
|
|
|
|
using namespace std;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASExpandString(const wchar_t* pInputString, wchar_t** ppOutputString);
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef DEBUG
|
|
#define CHECK_CALL_HRES(expr) \
|
|
hres = expr; \
|
|
if (FAILED(hres)) \
|
|
{ \
|
|
wprintf(L"### %S returned 0x%X ###\n", ## #expr, hres); \
|
|
return hres; \
|
|
}
|
|
|
|
#define CHECK_CALL_HRES_NO_RETURN(expr) \
|
|
hres = expr; \
|
|
if (FAILED(hres)) \
|
|
{ \
|
|
wprintf(L"### %S returned 0x%X ###\n", ## #expr, hres); \
|
|
}
|
|
#define CHECK_CALL_HRES_BREAK(expr) \
|
|
hres = expr; \
|
|
if (FAILED(hres)) \
|
|
{ \
|
|
wprintf(L"### %S returned 0x%X ###\n", ## #expr, hres); \
|
|
break; \
|
|
}
|
|
#else //no printf, only the error code return if needed
|
|
#define CHECK_CALL_HRES(expr) \
|
|
hres = expr; \
|
|
if (FAILED(hres)) \
|
|
{ \
|
|
return hres; \
|
|
}
|
|
|
|
#define CHECK_CALL_HRES_NO_RETURN(expr) \
|
|
hres = expr;
|
|
|
|
#define CHECK_CALL_HRES_BREAK(expr) \
|
|
hres = expr; \
|
|
if (FAILED(hres)) break;
|
|
|
|
#endif //DEBUG
|
|
|
|
|
|
#define celems(_x) (sizeof(_x) / sizeof(_x[0]))
|
|
|
|
#ifdef DBG
|
|
#define IgnoreVariable(v) { (v) = (v); }
|
|
#else
|
|
#define IgnoreVariable(v)
|
|
#endif
|
|
|
|
namespace
|
|
{
|
|
const int SIZELINEMAX = 512;
|
|
const int SIZE_LONG_MAX = 33;
|
|
// Number of files generated
|
|
// here one: backup.mdb
|
|
const int MAX_FILES = 1;
|
|
const int EXTRA_CHAR_SPACE = 32;
|
|
|
|
// file order
|
|
const int BACKUP_NB = 0;
|
|
const int BINARY_NB = 100;
|
|
|
|
// that's a lot
|
|
const int DECOMPRESS_FACTOR = 100;
|
|
const int FILE_BUFFER_SIZE = 1024;
|
|
|
|
struct IASKEY
|
|
{
|
|
const wchar_t* c_wcKey;
|
|
const wchar_t* c_wcValue;
|
|
DWORD c_dwType;
|
|
} IAS_Key_Struct;
|
|
|
|
IASKEY c_wcKEYS[] =
|
|
{
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
|
|
L"Allow SNMP Set",
|
|
REG_DWORD
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RasMan\\PPP\\ControlProtocols\\BuiltIn",
|
|
L"DefaultDomain",
|
|
REG_SZ
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
|
|
L"MaxDenials",
|
|
REG_DWORD
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
|
|
L"ResetTime (mins)",
|
|
REG_DWORD
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"Allow LM Authentication",
|
|
REG_DWORD
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"Default User Identity",
|
|
REG_SZ
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"User Identity Attribute",
|
|
REG_DWORD
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"Override User-Name",
|
|
REG_DWORD
|
|
},
|
|
{
|
|
L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
|
|
L"Ping User-Name",
|
|
REG_SZ
|
|
},
|
|
};
|
|
|
|
const wchar_t c_wcKEYS_FILE[] = L"%TEMP%\\";
|
|
|
|
#ifdef _WIN64
|
|
const wchar_t c_wcIAS_MDB_FILE_NAME[] =
|
|
L"%SystemRoot%\\SysWow64\\ias\\ias.mdb";
|
|
const wchar_t c_wcIAS_OLD[] = L"%SystemRoot%\\SysWow64\\ias\\iasold.mdb";
|
|
|
|
#else
|
|
const wchar_t c_wcIAS_MDB_FILE_NAME[] =
|
|
L"%SystemRoot%\\System32\\ias\\ias.mdb";
|
|
|
|
const wchar_t c_wcIAS_OLD[] = L"%SystemRoot%\\System32\\ias\\iasold.mdb";
|
|
#endif
|
|
|
|
const wchar_t c_wcFILE_BACKUP[] = L"%TEMP%\\Backup.mdb";
|
|
|
|
const wchar_t c_wcSELECT_PROPERTIES_INTO[] =
|
|
L"SELECT * "
|
|
L"INTO Properties IN "
|
|
L"\"%TEMP%\\Backup.mdb\" "
|
|
L"FROM Properties;";
|
|
|
|
const wchar_t c_wcSELECT_OBJECTS_INTO[] =
|
|
L"SELECT * "
|
|
L"INTO Objects IN "
|
|
L"\"%TEMP%\\Backup.mdb\" "
|
|
L"FROM Objects;";
|
|
|
|
const wchar_t c_wcSELECT_VERSION_INTO[] =
|
|
L"SELECT * "
|
|
L"INTO Version IN "
|
|
L"\"%TEMP%\\Backup.mdb\" "
|
|
L"FROM Version;";
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// WideToAnsi
|
|
//
|
|
// CALLED BY:everywhere
|
|
//
|
|
// PARAMETERS: lpStr - destination string
|
|
// lpWStr - string to convert
|
|
// cchStr - size of dest buffer
|
|
//
|
|
// DESCRIPTION:
|
|
// converts unicode lpWStr to ansi lpStr.
|
|
// fills in unconvertable chars w/ DPLAY_DEFAULT_CHAR "-"
|
|
//
|
|
//
|
|
// RETURNS: if cchStr is 0, returns the size required to hold the string
|
|
// otherwise, returns the number of chars converted
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
int WideToAnsi(char* lpStr,unsigned short* lpWStr, int cchStr)
|
|
{
|
|
BOOL bDefault;
|
|
|
|
// use the default code page (CP_ACP)
|
|
// -1 indicates WStr must be null terminated
|
|
return WideCharToMultiByte(GetConsoleOutputCP(),0,lpWStr,-1,lpStr,cchStr,"-",&bDefault);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASEnableBackupPrivilege
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASEnableBackupPrivilege()
|
|
{
|
|
LONG lResult = ERROR_SUCCESS;
|
|
HANDLE hToken = NULL;
|
|
do
|
|
{
|
|
if ( ! OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES,
|
|
&hToken
|
|
))
|
|
{
|
|
lResult = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
|
|
LUID luidB;
|
|
if ( ! LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &luidB))
|
|
{
|
|
lResult = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
|
|
LUID luidR;
|
|
if ( ! LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &luidR))
|
|
{
|
|
lResult = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
|
|
TOKEN_PRIVILEGES tp;
|
|
tp.PrivilegeCount = 1;
|
|
tp.Privileges[0].Luid = luidB;
|
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
if ( ! AdjustTokenPrivileges(
|
|
hToken,
|
|
FALSE,
|
|
&tp,
|
|
sizeof(TOKEN_PRIVILEGES),
|
|
NULL,
|
|
NULL
|
|
) )
|
|
{
|
|
lResult = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
|
|
tp.PrivilegeCount = 1;
|
|
tp.Privileges[0].Luid = luidR;
|
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
if ( ! AdjustTokenPrivileges(
|
|
hToken,
|
|
FALSE,
|
|
&tp,
|
|
sizeof(TOKEN_PRIVILEGES),
|
|
NULL,
|
|
NULL
|
|
) )
|
|
{
|
|
lResult = ERROR_CAN_NOT_COMPLETE;
|
|
break;
|
|
}
|
|
} while (false);
|
|
|
|
if ( hToken )
|
|
{
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASSaveRegKeys
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASSaveRegKeys()
|
|
{
|
|
ASSERT(celems(c_wcKEYS) != 0);
|
|
|
|
////////////////////////////
|
|
// Enable backup privilege.
|
|
////////////////////////////
|
|
HRESULT hres;
|
|
CHECK_CALL_HRES (IASEnableBackupPrivilege());
|
|
|
|
wchar_t* completeFile;
|
|
CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE, &completeFile));
|
|
size_t c_NbKeys = celems(c_wcKEYS);
|
|
|
|
for ( int i = 0; i < c_NbKeys; ++i )
|
|
{
|
|
DWORD dwType = 0;
|
|
DWORD cbData = SIZELINEMAX / 2;
|
|
|
|
LPVOID pvData = CoTaskMemAlloc(sizeof(wchar_t) * SIZELINEMAX);
|
|
if (!pvData)
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
DWORD lResult = SHGetValueW(
|
|
HKEY_LOCAL_MACHINE,
|
|
c_wcKEYS[i].c_wcKey,
|
|
c_wcKEYS[i].c_wcValue,
|
|
&dwType,
|
|
pvData,
|
|
&cbData
|
|
);
|
|
|
|
//
|
|
// Try to allocate more memory if cbData returned the size needed
|
|
//
|
|
if ((lResult != ERROR_SUCCESS) && (cbData > SIZELINEMAX))
|
|
{
|
|
CoTaskMemFree(pvData);
|
|
pvData = CoTaskMemAlloc(sizeof(wchar_t) * cbData);
|
|
if ( !pvData )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
lResult = SHGetValue(
|
|
HKEY_LOCAL_MACHINE,
|
|
c_wcKEYS[i].c_wcKey,
|
|
c_wcKEYS[i].c_wcValue,
|
|
&dwType,
|
|
pvData,
|
|
&cbData
|
|
);
|
|
if ( lResult != ERROR_SUCCESS )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
CoTaskMemFree(pvData);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create the file (in all situations)
|
|
//
|
|
wstring sFileName(completeFile);
|
|
wchar_t buffer[SIZE_LONG_MAX];
|
|
|
|
_itow(i, buffer, 10); // 10 means base 10
|
|
sFileName += buffer;
|
|
sFileName += L".txt";
|
|
|
|
HANDLE hFile = CreateFileW(
|
|
sFileName.c_str(),
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
|
|
if ( hFile == INVALID_HANDLE_VALUE )
|
|
{
|
|
hres = E_FAIL;
|
|
CoTaskMemFree(pvData);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// lResult = result of SHGetValue
|
|
// and might be an error but not
|
|
// a memory problem
|
|
//
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// Wrong data type
|
|
//
|
|
if ( dwType != c_wcKEYS[i].c_dwType )
|
|
{
|
|
hres = E_FAIL;
|
|
CoTaskMemFree(pvData);
|
|
CloseHandle(hFile);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Save the value to the file
|
|
//
|
|
BYTE* bBuffer = static_cast<BYTE*>(VirtualAlloc
|
|
(
|
|
NULL,
|
|
(cbData > FILE_BUFFER_SIZE)?
|
|
cbData:FILE_BUFFER_SIZE,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
));
|
|
if ( !bBuffer )
|
|
{
|
|
CoTaskMemFree(pvData);
|
|
CloseHandle(hFile);
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
memset(bBuffer, '\0', (cbData > FILE_BUFFER_SIZE)?
|
|
cbData:FILE_BUFFER_SIZE);
|
|
|
|
if ( REG_SZ == c_wcKEYS[i].c_dwType )
|
|
{
|
|
wcscpy((wchar_t*)bBuffer, (wchar_t*)pvData);
|
|
}
|
|
else
|
|
{
|
|
memcpy(bBuffer, pvData, cbData);
|
|
}
|
|
|
|
CoTaskMemFree(pvData);
|
|
|
|
DWORD NumberOfBytesWritten;
|
|
|
|
BOOL bResult = WriteFile(
|
|
hFile,
|
|
bBuffer,
|
|
(cbData > FILE_BUFFER_SIZE)?
|
|
cbData:FILE_BUFFER_SIZE,
|
|
&NumberOfBytesWritten,
|
|
NULL
|
|
);
|
|
|
|
VirtualFree(
|
|
bBuffer,
|
|
(cbData > FILE_BUFFER_SIZE)?
|
|
cbData:FILE_BUFFER_SIZE,
|
|
MEM_RELEASE
|
|
); // ignore result
|
|
CloseHandle(hFile);
|
|
if ( bResult )
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// create an empty file
|
|
BYTE bBuffer[FILE_BUFFER_SIZE];
|
|
memset(bBuffer, '#', (cbData > FILE_BUFFER_SIZE)?
|
|
cbData:FILE_BUFFER_SIZE);
|
|
|
|
DWORD NumberOfBytesWritten;
|
|
BOOL bResult = WriteFile(
|
|
hFile,
|
|
&bBuffer,
|
|
FILE_BUFFER_SIZE,
|
|
&NumberOfBytesWritten,
|
|
NULL
|
|
);
|
|
|
|
CoTaskMemFree(pvData);
|
|
CloseHandle(hFile);
|
|
|
|
if ( bResult == TRUE )
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
////////////
|
|
// Clean
|
|
////////////
|
|
CoTaskMemFree(completeFile);
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// KeyShouldBeRestored
|
|
//
|
|
// maps the reg keys to the netsh tokens
|
|
/*
|
|
L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
|
|
L"Allow SNMP Set",
|
|
server
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RasMan\\PPP\\ControlProtocols\\BuiltIn",
|
|
L"DefaultDomain",
|
|
rap
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
|
|
L"MaxDenials",
|
|
server
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\AccountLockout",
|
|
L"ResetTime (mins)",
|
|
server
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"Allow LM Authentication",
|
|
rap
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"Default User Identity",
|
|
rap
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"User Identity Attribute",
|
|
rap
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy",
|
|
L"Override User-Name",
|
|
rap
|
|
|
|
L"SYSTEM\\CurrentControlSet\\Services\\IAS\\Parameters",
|
|
L"Ping User-Name",
|
|
server
|
|
*/
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
bool KeyShouldBeRestored(size_t keyIndex, IAS_SHOW_TOKEN_LIST configType)
|
|
{
|
|
// keyIndex maps to the index of the key in the array of keys
|
|
// configType is the token to use.
|
|
bool retVal = false;
|
|
switch(configType)
|
|
{
|
|
case CONFIG:
|
|
{
|
|
// true for everything
|
|
retVal = true;
|
|
break;
|
|
}
|
|
case SERVER_SETTINGS:
|
|
{
|
|
if ( (keyIndex == 0) ||
|
|
(keyIndex == 2) ||
|
|
(keyIndex == 3) ||
|
|
(keyIndex == 8)
|
|
)
|
|
{
|
|
retVal = true;
|
|
}
|
|
break;
|
|
}
|
|
case REMOTE_ACCESS_POLICIES:
|
|
{
|
|
if ( (keyIndex == 1) ||
|
|
(keyIndex == 4) ||
|
|
(keyIndex == 5) ||
|
|
(keyIndex == 6) ||
|
|
(keyIndex == 7)
|
|
)
|
|
{
|
|
retVal = true;
|
|
}
|
|
break;
|
|
}
|
|
case CONNECTION_REQUEST_POLICIES:
|
|
case CLIENTS:
|
|
case LOGGING:
|
|
default:
|
|
{
|
|
retVal = false;
|
|
break;
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASRestoreRegKeys
|
|
//
|
|
// if something cannot be restored because of an empty
|
|
// backup file (no key saved), that's not an error
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASRestoreRegKeys(/*in*/ IAS_SHOW_TOKEN_LIST configType)
|
|
{
|
|
ASSERT(celems(c_wcKEYS) != 0);
|
|
|
|
////////////////////////////
|
|
// Enable backup privilege.
|
|
// and sets hres
|
|
////////////////////////////
|
|
HRESULT hres;
|
|
CHECK_CALL_HRES (IASEnableBackupPrivilege());
|
|
|
|
wchar_t* completeFile;
|
|
CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE, &completeFile));
|
|
|
|
size_t c_NbKeys = celems(c_wcKEYS);
|
|
for (size_t i = 0; i < c_NbKeys; ++i )
|
|
{
|
|
if (!KeyShouldBeRestored(i, configType))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
wstring sFileName(completeFile);
|
|
wchar_t buffer[SIZE_LONG_MAX];
|
|
DWORD dwDisposition;
|
|
|
|
_itow(i, buffer, 10); // 10 means base 10
|
|
sFileName += buffer;
|
|
sFileName += L".txt";
|
|
|
|
// open the file
|
|
HANDLE hFile = CreateFileW(
|
|
sFileName.c_str(),
|
|
GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
// maybe some reg keys were not saved in that file.
|
|
// for instance Ping User-Name wasn't saved.
|
|
continue;
|
|
}
|
|
|
|
// check the type of data expected
|
|
LPVOID lpBuffer = NULL;
|
|
DWORD SizeToRead;
|
|
if (REG_SZ == c_wcKEYS[i].c_dwType)
|
|
{
|
|
lpBuffer = CoTaskMemAlloc(sizeof(wchar_t) * FILE_BUFFER_SIZE);
|
|
SizeToRead = FILE_BUFFER_SIZE;
|
|
}
|
|
else if (REG_DWORD == c_wcKEYS[i].c_dwType)
|
|
{
|
|
lpBuffer = CoTaskMemAlloc(sizeof(DWORD));
|
|
SizeToRead = sizeof(DWORD);
|
|
}
|
|
else
|
|
{
|
|
// unknown
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
if (!lpBuffer)
|
|
{
|
|
CloseHandle(hFile);
|
|
hres = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
memset(lpBuffer,'\0',SizeToRead);
|
|
|
|
// read the file
|
|
DWORD NumberOfBytesRead;
|
|
BOOL b = ReadFile(
|
|
hFile,
|
|
lpBuffer,
|
|
SizeToRead,
|
|
&NumberOfBytesRead,
|
|
NULL
|
|
); // ignore return value. uses NumberOfBytesRead
|
|
// to determine success condition
|
|
IgnoreVariable(b);
|
|
CloseHandle(hFile);
|
|
|
|
// check if the file contains ####
|
|
if ( NumberOfBytesRead == 0 )
|
|
{
|
|
// problem
|
|
CoTaskMemFree(lpBuffer);
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
BYTE TempBuffer[sizeof(DWORD)];
|
|
memset(TempBuffer, '#', sizeof(DWORD));
|
|
|
|
if (0 == memcmp(lpBuffer, TempBuffer, sizeof(DWORD)))
|
|
{
|
|
// no key saved, delete existing key if any
|
|
HKEY hKeyToDelete = NULL;
|
|
if (ERROR_SUCCESS == RegOpenKeyW(
|
|
HKEY_LOCAL_MACHINE,
|
|
c_wcKEYS[i].c_wcKey,
|
|
&hKeyToDelete
|
|
))
|
|
{
|
|
if (ERROR_SUCCESS != RegDeleteValueW
|
|
(
|
|
hKeyToDelete,
|
|
c_wcKEYS[i].c_wcValue
|
|
))
|
|
{
|
|
// delete existing key failed\n");
|
|
}
|
|
RegCloseKey(hKeyToDelete);
|
|
}
|
|
//
|
|
// else do nothing: key doesn't exist
|
|
//
|
|
}
|
|
else
|
|
{
|
|
// key saved: restore value
|
|
// what if the value is bigger than
|
|
// the buffer size?
|
|
|
|
HKEY hKeyToUpdate;
|
|
LONG lResult = RegCreateKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
c_wcKEYS[i].c_wcKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE |
|
|
REG_OPTION_BACKUP_RESTORE ,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKeyToUpdate,
|
|
&dwDisposition
|
|
);
|
|
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
lResult = RegCreateKeyW(
|
|
HKEY_LOCAL_MACHINE,
|
|
c_wcKEYS[i].c_wcKey,
|
|
&hKeyToUpdate
|
|
);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
RegCloseKey(hKeyToUpdate);
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (REG_SZ == c_wcKEYS[i].c_dwType)
|
|
{
|
|
// nb of
|
|
NumberOfBytesRead = (
|
|
( wcslen((wchar_t*)lpBuffer)
|
|
+ 1 // for /0
|
|
) * sizeof(wchar_t)
|
|
);
|
|
};
|
|
|
|
//
|
|
// Key created or key existing
|
|
// both can be here (error = break)
|
|
//
|
|
if (ERROR_SUCCESS != RegSetValueExW(
|
|
hKeyToUpdate,
|
|
c_wcKEYS[i].c_wcValue,
|
|
0,
|
|
c_wcKEYS[i].c_dwType,
|
|
(BYTE*)lpBuffer,
|
|
NumberOfBytesRead
|
|
))
|
|
{
|
|
RegCloseKey(hKeyToUpdate);
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
RegCloseKey(hKeyToUpdate);
|
|
hres = S_OK;
|
|
}
|
|
|
|
CoTaskMemFree(lpBuffer);
|
|
}
|
|
}
|
|
|
|
/////////
|
|
// Clean
|
|
/////////
|
|
CoTaskMemFree(completeFile);
|
|
return hres;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASExpandString
|
|
//
|
|
// Expands strings containing %ENV_VARIABLE%
|
|
//
|
|
// The output string is allocated only when the function succeed
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
IASExpandString(const wchar_t* pInputString, /*in/out*/ wchar_t** ppOutputString)
|
|
{
|
|
_ASSERTE(pInputString);
|
|
_ASSERTE(pppOutputString);
|
|
|
|
HRESULT hres;
|
|
|
|
*ppOutputString = static_cast<wchar_t*>(CoTaskMemAlloc(
|
|
SIZELINEMAX
|
|
* sizeof(wchar_t)
|
|
));
|
|
|
|
if ( ! *ppOutputString )
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
if ( ExpandEnvironmentStringsForUserW(
|
|
NULL,
|
|
pInputString,
|
|
*ppOutputString,
|
|
SIZELINEMAX
|
|
)
|
|
)
|
|
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
else
|
|
{
|
|
CoTaskMemFree(*ppOutputString);
|
|
hres = E_FAIL;
|
|
}
|
|
}
|
|
#ifdef DEBUG // DEBUG
|
|
wprintf(L"#ExpandString: %s\n", *ppOutputString);
|
|
#endif //DEBUG
|
|
|
|
return hres;
|
|
};
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DeleteTemporaryFiles()
|
|
//
|
|
// delete the temporary files if any
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT DeleteTemporaryFiles()
|
|
{
|
|
HRESULT hres;
|
|
wchar_t* sz_FileBackup;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcFILE_BACKUP,
|
|
&sz_FileBackup
|
|
)
|
|
);
|
|
|
|
DeleteFile(sz_FileBackup); //return value not checked
|
|
CoTaskMemFree(sz_FileBackup);
|
|
|
|
wchar_t* TempPath;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE, &TempPath));
|
|
|
|
int c_NbKeys = celems(c_wcKEYS);
|
|
for ( int i = 0; i < c_NbKeys; ++i )
|
|
{
|
|
wstring sFileName(TempPath);
|
|
wchar_t buffer[SIZE_LONG_MAX];
|
|
_itow(i, buffer, 10); // 10 means base 10
|
|
sFileName += buffer;
|
|
sFileName += L".txt";
|
|
|
|
DeleteFile(sFileName.c_str()); //return value not checked
|
|
}
|
|
|
|
CoTaskMemFree(TempPath);
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASCompress
|
|
//
|
|
// Wrapper for RtlCompressBuffer
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASCompress(
|
|
PUCHAR pInputBuffer,
|
|
ULONG* pulFileSize,
|
|
PUCHAR* ppCompressedBuffer
|
|
)
|
|
{
|
|
ULONG size, ignore;
|
|
|
|
NTSTATUS status = RtlGetCompressionWorkSpaceSize(
|
|
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
|
|
&size,
|
|
&ignore
|
|
);
|
|
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
#ifdef DEBUG
|
|
printf("RtlGetCompressionWorkSpaceSize returned 0x%08X.\n", status);
|
|
#endif //DEBUG
|
|
return E_FAIL;
|
|
}
|
|
|
|
PVOID workSpace;
|
|
workSpace = RtlAllocateHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
size
|
|
);
|
|
if ( !workSpace )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
size = *pulFileSize;
|
|
|
|
// That's a minimum buffer size that can be used
|
|
if ( size < FILE_BUFFER_SIZE )
|
|
{
|
|
size = FILE_BUFFER_SIZE;
|
|
}
|
|
|
|
*ppCompressedBuffer = static_cast<PUCHAR>(RtlAllocateHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
size
|
|
));
|
|
|
|
if ( !*ppCompressedBuffer )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
status = RtlCompressBuffer(
|
|
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
|
|
pInputBuffer,
|
|
size,
|
|
*ppCompressedBuffer,
|
|
size,
|
|
0,
|
|
&size,
|
|
workSpace
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
if (STATUS_BUFFER_TOO_SMALL == status)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("STATUS_BUFFER_TOO_SMALL\n");
|
|
printf("RtlCompressBuffer returned 0x%08X.\n", status);
|
|
#endif //DEBUG
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
printf("RtlCompressBuffer returned 0x%08X.\n", status);
|
|
#endif //DEBUG
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pulFileSize = size;
|
|
|
|
RtlFreeHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
workSpace
|
|
);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASUnCompress
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASUnCompress(
|
|
PUCHAR pInputBuffer,
|
|
ULONG* pulFileSize,
|
|
PUCHAR* ppDeCompressedBuffer
|
|
)
|
|
{
|
|
ULONG size, ignore;
|
|
|
|
NTSTATUS status = RtlGetCompressionWorkSpaceSize(
|
|
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
|
|
&size,
|
|
&ignore
|
|
);
|
|
|
|
|
|
if ( !NT_SUCCESS(status) )
|
|
{
|
|
#ifdef DEBUG
|
|
printf("RtlGetCompressionWorkSpaceSize returned 0x%08X.\n", status);
|
|
#endif //DEBUG
|
|
return E_FAIL;
|
|
}
|
|
|
|
size = *pulFileSize;
|
|
|
|
if( FILE_BUFFER_SIZE >= size)
|
|
{
|
|
size = FILE_BUFFER_SIZE;
|
|
}
|
|
|
|
*ppDeCompressedBuffer = static_cast<PUCHAR>(RtlAllocateHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
size * DECOMPRESS_FACTOR
|
|
));
|
|
if ( !*ppDeCompressedBuffer )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
ULONG UncompressedSize;
|
|
|
|
status = RtlDecompressBuffer(
|
|
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
|
|
*ppDeCompressedBuffer,
|
|
size * DECOMPRESS_FACTOR,
|
|
pInputBuffer,
|
|
*pulFileSize ,
|
|
&UncompressedSize
|
|
);
|
|
|
|
if ( !NT_SUCCESS(status) )
|
|
{
|
|
#ifdef DEBUG
|
|
printf("RtlUnCompressBuffer returned 0x%08X.\n", status);
|
|
#endif //DEBUG
|
|
|
|
switch (status)
|
|
{
|
|
case STATUS_INVALID_PARAMETER:
|
|
#ifdef DEBUG
|
|
printf("STATUS_INVALID_PARAMETER");
|
|
#endif //DEBUG
|
|
break;
|
|
|
|
case STATUS_BAD_COMPRESSION_BUFFER:
|
|
#ifdef DEBUG
|
|
printf("STATUS_BAD_COMPRESSION_BUFFER ");
|
|
printf("size = %d %d",pulFileSize,UncompressedSize);
|
|
|
|
#endif //DEBUG
|
|
break;
|
|
case STATUS_UNSUPPORTED_COMPRESSION:
|
|
#ifdef DEBUG
|
|
printf("STATUS_UNSUPPORTED_COMPRESSION ");
|
|
#endif //DEBUG
|
|
break;
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
*pulFileSize = UncompressedSize;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASFileToBase64
|
|
//
|
|
// Compress then encode to Base64
|
|
//
|
|
// BSTR by Allocated IASFileToBase64, should be freed by the caller
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
IASFileToBase64(const wchar_t* pFileName, /*out*/ BSTR* pOutputBSTR)
|
|
{
|
|
_ASSERTE(pFileName);
|
|
_ASSERTE(pppOutputString);
|
|
|
|
HRESULT hres;
|
|
|
|
HANDLE hFileHandle = CreateFileW(
|
|
pFileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if ( hFileHandle == INVALID_HANDLE_VALUE )
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"#filename = %s",pFileName);
|
|
wprintf(L"### INVALID_HANDLE_VALUE ###\n");
|
|
#endif //DEBUG
|
|
|
|
hres = E_FAIL;
|
|
return hres;
|
|
}
|
|
|
|
// safe cast from DWORD to ULONG
|
|
ULONG ulFileSize = (ULONG) GetFileSize(
|
|
hFileHandle, // file for which to get size
|
|
NULL// high-order word of file size
|
|
);
|
|
|
|
if (0xFFFFFFFF == ulFileSize)
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### GetFileSize Failed ###\n");
|
|
#endif //DEBUG
|
|
|
|
hres = E_FAIL;
|
|
return hres;
|
|
}
|
|
|
|
|
|
HANDLE hFileMapping = CreateFileMapping(
|
|
hFileHandle, // handle to file to map
|
|
NULL, // optional security attributes
|
|
PAGE_READONLY, // protection for mapping object
|
|
0, // high-order 32 bits of object size
|
|
0, // low-order 32 bits of object size
|
|
NULL // name of file-mapping object
|
|
);
|
|
|
|
if (NULL == hFileMapping)
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### CreateFileMapping Failed ###\n");
|
|
#endif //DEBUG
|
|
|
|
hres = E_FAIL;
|
|
return hres;
|
|
}
|
|
|
|
LPVOID pMemoryFile = MapViewOfFile(
|
|
hFileMapping, // file-mapping object to map into
|
|
// address space
|
|
FILE_MAP_READ, // access mode
|
|
0, // high-order 32 bits of file offset
|
|
0, // low-order 32 bits of file offset
|
|
0 // number of bytes to map
|
|
);
|
|
|
|
if (NULL == pMemoryFile)
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### MapViewOfFile Failed ###\n");
|
|
#endif //DEBUG
|
|
|
|
hres = E_FAIL;
|
|
return hres;
|
|
}
|
|
|
|
|
|
/////////////////////////////
|
|
// NOW compress
|
|
/////////////////////////////
|
|
|
|
wchar_t* pCompressedBuffer;
|
|
|
|
CHECK_CALL_HRES (IASCompress((PUCHAR) pMemoryFile,
|
|
/*IN OUT*/(ULONG *) &ulFileSize,
|
|
/*IN OUT*/(PUCHAR*) &pCompressedBuffer));
|
|
|
|
/////////////////////
|
|
// Encode to Base64
|
|
/////////////////////
|
|
|
|
CHECK_CALL_HRES (ToBase64(
|
|
pCompressedBuffer,
|
|
(ULONG) ulFileSize,
|
|
pOutputBSTR
|
|
)
|
|
);
|
|
|
|
/////////////////////////////
|
|
// Clean
|
|
/////////////////////////////
|
|
|
|
RtlFreeHeap(
|
|
RtlProcessHeap(),
|
|
0,
|
|
pCompressedBuffer
|
|
);
|
|
|
|
BOOL bResult = UnmapViewOfFile(
|
|
pMemoryFile// address where mapped view begins
|
|
);
|
|
if (FALSE == bResult)
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### UnmapViewOfFile Failed ###\n");
|
|
#endif //DEBUG
|
|
|
|
hres = E_FAIL;
|
|
}
|
|
|
|
CloseHandle(hFileMapping);
|
|
CloseHandle(hFileHandle);
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASDumpConfig
|
|
//
|
|
// Dump the configuration to some temporary files, then indidually
|
|
// compress then encode them.
|
|
// one big string is created from those multiple Base64 strings.
|
|
//
|
|
// Remarks: IASDumpConfig does a malloc and allocates memory for
|
|
// *ppDumpString. The calling function will have to free that memory
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
IASDumpConfig(/*inout*/ wchar_t **ppDumpString, /*inout*/ ULONG *ulSize)
|
|
{
|
|
_ASSERTE(ppDumpString);
|
|
_ASSERTE(ulSize);
|
|
|
|
HRESULT hres;
|
|
|
|
///////////////////////////////////////
|
|
// delete the temporary files if any
|
|
///////////////////////////////////////
|
|
CHECK_CALL_HRES (DeleteTemporaryFiles());
|
|
|
|
////////////////////////////////////////////////////
|
|
// Save the Registry keys. that creates many files
|
|
////////////////////////////////////////////////////
|
|
CHECK_CALL_HRES (IASSaveRegKeys());
|
|
|
|
//////////////////////
|
|
// connect to the DB
|
|
//////////////////////
|
|
wchar_t* sz_DBPath;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcIAS_MDB_FILE_NAME, &sz_DBPath));
|
|
|
|
CComPtr<IIASNetshJetHelper> JetHelper;
|
|
CHECK_CALL_HRES (CoCreateInstance(
|
|
__uuidof(CIASNetshJetHelper),
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
__uuidof(IIASNetshJetHelper),
|
|
(PVOID*) &JetHelper
|
|
));
|
|
|
|
CComBSTR DBPath(sz_DBPath);
|
|
if ( !DBPath ) { return E_OUTOFMEMORY; }
|
|
CHECK_CALL_HRES (JetHelper->OpenJetDatabase(DBPath, TRUE));
|
|
|
|
//////////////////////////////////////
|
|
// Create a new DB named "Backup.mdb"
|
|
//////////////////////////////////////
|
|
wchar_t* sz_FileBackup;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcFILE_BACKUP,
|
|
&sz_FileBackup
|
|
)
|
|
);
|
|
|
|
CComBSTR BackupDb(sz_FileBackup);
|
|
if ( !BackupDb ) { return E_OUTOFMEMORY; }
|
|
CHECK_CALL_HRES (JetHelper->CreateJetDatabase(BackupDb));
|
|
|
|
|
|
//////////////////////////////////////////////////////////
|
|
// exec the sql statements (to export)
|
|
// the content into the temp database
|
|
//////////////////////////////////////////////////////////
|
|
wchar_t* sz_SelectProperties;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcSELECT_PROPERTIES_INTO,
|
|
&sz_SelectProperties
|
|
)
|
|
);
|
|
|
|
CComBSTR SelectProperties(sz_SelectProperties);
|
|
if ( !SelectProperties ) { return E_OUTOFMEMORY; }
|
|
CHECK_CALL_HRES (JetHelper->ExecuteSQLCommand(SelectProperties));
|
|
|
|
wchar_t* sz_SelectObjects;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcSELECT_OBJECTS_INTO,
|
|
&sz_SelectObjects
|
|
)
|
|
);
|
|
|
|
CComBSTR SelectObjects(sz_SelectObjects);
|
|
if ( !SelectObjects ) { return E_OUTOFMEMORY; }
|
|
CHECK_CALL_HRES (JetHelper->ExecuteSQLCommand(SelectObjects));
|
|
|
|
wchar_t* sz_SelectVersion;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcSELECT_VERSION_INTO,
|
|
&sz_SelectVersion
|
|
)
|
|
);
|
|
|
|
CComBSTR SelectVersion(sz_SelectVersion);
|
|
if ( !SelectVersion ) { return E_OUTOFMEMORY; }
|
|
CHECK_CALL_HRES (JetHelper->ExecuteSQLCommand(SelectVersion));
|
|
|
|
/////////////////////////////////////////////
|
|
// transform the file into Base64 BSTR
|
|
/////////////////////////////////////////////
|
|
|
|
BSTR FileBackupBSTR;
|
|
|
|
CHECK_CALL_HRES (IASFileToBase64(
|
|
sz_FileBackup,
|
|
&FileBackupBSTR
|
|
)
|
|
);
|
|
|
|
int NumberOfKeyFiles = celems(c_wcKEYS);
|
|
|
|
BSTR pFileKeys[celems(c_wcKEYS)];
|
|
|
|
wchar_t* sz_FileRegistry;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE,
|
|
&sz_FileRegistry
|
|
)
|
|
);
|
|
|
|
for ( int i = 0; i < NumberOfKeyFiles; ++i )
|
|
{
|
|
|
|
wstring sFileName(sz_FileRegistry);
|
|
wchar_t buffer[SIZE_LONG_MAX];
|
|
_itow(i, buffer, 10); // 10 means base 10
|
|
sFileName += buffer;
|
|
sFileName += L".txt";
|
|
|
|
CHECK_CALL_HRES (IASFileToBase64(
|
|
sFileName.c_str(),
|
|
&pFileKeys[i]
|
|
)
|
|
);
|
|
|
|
}
|
|
CoTaskMemFree(sz_FileRegistry);
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
// alloc the memory for full the Base64 string
|
|
///////////////////////////////////////////////
|
|
|
|
*ulSize = SysStringByteLen(FileBackupBSTR)
|
|
+ EXTRA_CHAR_SPACE;
|
|
|
|
for ( int j = 0; j < NumberOfKeyFiles; ++j )
|
|
{
|
|
*ulSize += SysStringByteLen(pFileKeys[j]);
|
|
*ulSize += 2; // extra characters
|
|
}
|
|
|
|
*ppDumpString = (wchar_t *) calloc(
|
|
*ulSize ,
|
|
sizeof(wchar_t)
|
|
);
|
|
|
|
//////////////////////////////////////////////////
|
|
// copy the different strings into one big string
|
|
//////////////////////////////////////////////////
|
|
if (*ppDumpString)
|
|
{
|
|
wcsncpy(
|
|
(wchar_t*) *ppDumpString,
|
|
(wchar_t*) FileBackupBSTR,
|
|
SysStringLen(FileBackupBSTR)
|
|
);
|
|
|
|
for ( int k = 0; k < NumberOfKeyFiles; ++k )
|
|
{
|
|
wcscat(
|
|
(wchar_t*) *ppDumpString,
|
|
L"*\\\n"
|
|
);
|
|
|
|
wcsncat(
|
|
(wchar_t*) *ppDumpString,
|
|
(wchar_t*) pFileKeys[k],
|
|
SysStringLen(pFileKeys[k])
|
|
);
|
|
}
|
|
|
|
wcscat(
|
|
(wchar_t*) *ppDumpString,
|
|
L"QWER * QWER\\\n"
|
|
);
|
|
|
|
*ulSize = wcslen(*ppDumpString);
|
|
}
|
|
else
|
|
{
|
|
hres = E_OUTOFMEMORY;
|
|
#ifdef DEBUG
|
|
wprintf(L"### calloc failed ###\n");
|
|
#endif //DEBUG
|
|
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// delete the temporary files if any
|
|
///////////////////////////////////////
|
|
CHECK_CALL_HRES (DeleteTemporaryFiles());
|
|
|
|
/////////////////////////////////////////////
|
|
// Clean
|
|
/////////////////////////////////////////////
|
|
|
|
for ( int k = 0; k < NumberOfKeyFiles; ++k )
|
|
{
|
|
SysFreeString(pFileKeys[k]);
|
|
}
|
|
|
|
CoTaskMemFree(sz_SelectVersion);
|
|
CoTaskMemFree(sz_SelectProperties);
|
|
CoTaskMemFree(sz_SelectObjects);
|
|
CoTaskMemFree(sz_FileBackup);
|
|
CoTaskMemFree(sz_DBPath);
|
|
SysFreeString(FileBackupBSTR);
|
|
CHECK_CALL_HRES (JetHelper->CloseJetDatabase());
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IASSaveToFile
|
|
//
|
|
// Remark: if a new table has to be saved, an "entry" for that should be
|
|
// created in that function to deal with the filemname
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASSaveToFile(
|
|
/* in */ int Index,
|
|
/* in */ wchar_t* pContent,
|
|
DWORD lSize = 0
|
|
)
|
|
{
|
|
HRESULT hres;
|
|
wstring sFileName;
|
|
|
|
switch (Index)
|
|
{
|
|
case BACKUP_NB:
|
|
{
|
|
wchar_t* sz_FileBackup;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcIAS_OLD,
|
|
&sz_FileBackup
|
|
)
|
|
);
|
|
sFileName = sz_FileBackup;
|
|
|
|
CoTaskMemFree(sz_FileBackup);
|
|
break;
|
|
}
|
|
|
|
///////////
|
|
// binary
|
|
///////////
|
|
default:
|
|
{
|
|
///////////////////////////////////
|
|
// i + BINARY_NB is the parameter
|
|
///////////////////////////////////
|
|
wchar_t* sz_FileRegistry;
|
|
|
|
CHECK_CALL_HRES (IASExpandString(c_wcKEYS_FILE,
|
|
&sz_FileRegistry
|
|
)
|
|
);
|
|
|
|
sFileName = sz_FileRegistry;
|
|
wchar_t buffer[SIZE_LONG_MAX];
|
|
|
|
_itow(Index - BINARY_NB, buffer, 10); // 10 means base 10
|
|
sFileName += buffer;
|
|
sFileName += L".txt";
|
|
|
|
CoTaskMemFree(sz_FileRegistry);
|
|
break;
|
|
}
|
|
}
|
|
|
|
HANDLE hFile = CreateFileW(
|
|
sFileName.c_str(),
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
DWORD NumberOfBytesWritten;
|
|
BOOL bResult = WriteFile(
|
|
hFile,
|
|
(LPVOID) pContent,
|
|
lSize,
|
|
&NumberOfBytesWritten,
|
|
NULL
|
|
);
|
|
|
|
if (bResult)
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IASRestoreConfig
|
|
//
|
|
// Clean the DB first, then insert back everything.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IASRestoreConfig(
|
|
/*in*/ const wchar_t *pRestoreString,
|
|
/*in*/ IAS_SHOW_TOKEN_LIST configType
|
|
)
|
|
{
|
|
_ASSERTE(pRestoreString);
|
|
|
|
bool bCoInitialized = false;
|
|
HRESULT hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
|
|
if (FAILED(hres))
|
|
{
|
|
if (RPC_E_CHANGED_MODE == hres)
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
else
|
|
{
|
|
return hres;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bCoInitialized = true;
|
|
}
|
|
|
|
BSTR bstr = NULL;
|
|
do
|
|
{
|
|
///////////////////////////////////////
|
|
// delete the temporary files if any
|
|
///////////////////////////////////////
|
|
CHECK_CALL_HRES_BREAK (DeleteTemporaryFiles());
|
|
|
|
CComPtr<IIASNetshJetHelper> JetHelper;
|
|
CHECK_CALL_HRES_BREAK (CoCreateInstance(
|
|
__uuidof(CIASNetshJetHelper),
|
|
NULL,
|
|
CLSCTX_SERVER,
|
|
__uuidof(IIASNetshJetHelper),
|
|
(PVOID*) &JetHelper
|
|
));
|
|
|
|
bstr = SysAllocStringLen(
|
|
pRestoreString,
|
|
wcslen(pRestoreString) + 2
|
|
);
|
|
|
|
if (bstr == NULL)
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### IASRestoreConfig->SysAllocStringLen failed\n");
|
|
#endif //DEBUG
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
int RealNumberOfFiles = MAX_FILES + celems(c_wcKEYS);
|
|
|
|
for ( int i = 0; i < RealNumberOfFiles; ++i )
|
|
{
|
|
BLOB lBlob;
|
|
|
|
lBlob.cbSize = 0;
|
|
lBlob.pBlobData = NULL;
|
|
// split the files and registry info
|
|
// uncompress (in memory ?)
|
|
|
|
CHECK_CALL_HRES_BREAK (FromBase64(bstr, &lBlob, i));
|
|
|
|
ULONG ulSize = lBlob.cbSize;
|
|
PUCHAR pDeCompressedBuffer;
|
|
|
|
if (ulSize == 0)
|
|
{
|
|
// file with less sections than expected
|
|
// for instance before the number of reg keys increased
|
|
// ignore
|
|
continue;
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// decode and decompress the base64
|
|
////////////////////////////////////
|
|
|
|
CHECK_CALL_HRES_BREAK (IASUnCompress(
|
|
lBlob.pBlobData,
|
|
&ulSize,
|
|
&pDeCompressedBuffer
|
|
))
|
|
|
|
if ( i >= MAX_FILES )
|
|
{
|
|
/////////////////////////////////////
|
|
// Binary; i + BINARY_NB used here
|
|
/////////////////////////////////////
|
|
IASSaveToFile(
|
|
i - MAX_FILES + BINARY_NB,
|
|
(wchar_t*)pDeCompressedBuffer,
|
|
(DWORD) ulSize
|
|
);
|
|
}
|
|
else
|
|
{
|
|
IASSaveToFile(
|
|
i,
|
|
(wchar_t*)pDeCompressedBuffer,
|
|
(DWORD) ulSize
|
|
);
|
|
}
|
|
|
|
////////////
|
|
// Clean
|
|
////////////
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pDeCompressedBuffer);
|
|
|
|
CoTaskMemFree(lBlob.pBlobData);
|
|
}
|
|
|
|
///////////////////////////////////////////////////
|
|
// Now Upgrade the database (That's transactional)
|
|
///////////////////////////////////////////////////
|
|
hres = JetHelper->MigrateOrUpgradeDatabase(configType);
|
|
|
|
if ( SUCCEEDED(hres) )
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### IASRestoreConfig->DB stuff successful\n");
|
|
#endif //DEBUG
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Now restore the registry.
|
|
////////////////////////////////////////////////////////
|
|
hres = IASRestoreRegKeys(configType);
|
|
if ( FAILED(hres) )
|
|
{
|
|
#ifdef DEBUG
|
|
wprintf(L"### IASRestoreConfig->restore reg keys failed\n");
|
|
#endif //DEBUG
|
|
}
|
|
}
|
|
// delete the temporary files
|
|
DeleteTemporaryFiles(); // do not check the result
|
|
} while (false);
|
|
|
|
SysFreeString(bstr);
|
|
|
|
if (bCoInitialized)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
return hres;
|
|
}
|