MSIMERG.CPP

#pragma message("Merge Database Utility.  Copyright 1997 - 1998 Microsoft Corp.") 
#if 0 // makefile definitions, to build: %vcbin%\nmake -fMsiMerg.cpp
DESCRIPTION = Merge Database Utility
MODULENAME = MsiMerg
SUBSYSTEM = console
FILEVERSION = Msi
LINKLIBS = OLE32.lib
!include <MsiTool.Mak>
!if 0 #nmake skips the rest of this file
#endif // end of makefile definitions

#define W32DOWS_LEAN_AND_MEAN // faster compile
#define W32
#define MSI

#include <windows.h>
#ifndef RC_INVOKED // start of source code
#include <tchar.h> // define UNICODE=1 on nmake command line to build UNICODE
#include "MsiQuery.h" // MSI API

//________________________________________________________________________________
//
// Constants and globals
//________________________________________________________________________________

const TCHAR szHelp[] = TEXT("Msi Merge Tool --- Merge Two Databases\n\nMsiMerg(d).exe {base db} {ref db}\n");
const TCHAR szTable[] = TEXT("_MergeErrors");

const int cchDisplayBuf = 4096;
HANDLE g_hStdOut;
TCHAR g_rgchBuffer[4096];

//________________________________________________________________________________
//
// Function prototypes
//________________________________________________________________________________

void Display(LPCTSTR szMessage);
void ErrorExit(UINT iError, LPCTSTR szMessage);
void CheckError(UINT iError, LPCTSTR szMessage);
void Merge(TCHAR* szBaseDb, TCHAR* szRefDb);

//_____________________________________________________________________________________________________
//
// main
//_____________________________________________________________________________________________________

extern "C" int __cdecl _tmain(int argc, TCHAR* argv[])
{
// Determine handle
g_hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (g_hStdOut == INVALID_HANDLE_VALUE)
g_hStdOut = 0; // non-zero if stdout redirected or piped

if (argc == 2 && ((_tcscmp(argv[1], TEXT("-?")) == 0) || (_tcscmp(argv[1], TEXT("/?")) == 0)))
ErrorExit( 0, szHelp);

// Check for enough arguments and valid options
CheckError(argc != 3, TEXT("msimerg(d).exe {base db} {ref db}"));
Merge(argv[1], argv[2]);
ErrorExit(0, TEXT("Done"));
return 0;
}


//________________________________________________________________________________
//
// Merge function
// Merge(...);
//________________________________________________________________________________

void Merge(TCHAR* szBaseDb, TCHAR* szRefDb)
{
PMSIHANDLE hBaseDb = 0;
PMSIHANDLE hRefDb = 0;

CheckError(MSI::MsiOpenDatabase(szBaseDb, MSIDBOPEN_TRANSACT, &hBaseDb), TEXT("Error Opening Base Database"));
CheckError(MSI::MsiOpenDatabase(szRefDb, MSIDBOPEN_READONLY, &hRefDb), TEXT("Error Opening Reference Databaes"));
UINT uiError = MSI::MsiDatabaseMerge(hBaseDb, hRefDb, szTable);
CheckError(MSI::MsiDatabaseCommit(hBaseDb), TEXT("Error Saving Database"));
CheckError(uiError, TEXT("Error Merging Database, Check _MergeErrors Table for Merge conflicts"));
}

//________________________________________________________________________________
//
// Error handling and Display functions:
// Display(...);
// ErrorExit(...);
// CheckError(...);
//
//________________________________________________________________________________

void Display(LPCTSTR szMessage)
{
if (szMessage)
{
int cbOut = _tcsclen(szMessage);;
if (g_hStdOut)
{
#ifdef UNICODE
char rgchTemp[cchDisplayBuf];
if (W32::GetFileType(g_hStdOut) == FILE_TYPE_CHAR)
{
W32::WideCharToMultiByte(CP_ACP, 0, szMessage, cbOut, rgchTemp, sizeof(rgchTemp), 0, 0);
szMessage = (LPCWSTR)rgchTemp;
}
else
cbOut *= 2; // write Unicode if not console device
#endif
DWORD cbWritten;
W32::WriteFile(g_hStdOut, szMessage, cbOut, &cbWritten, 0);
}
else
W32::MessageBox(0, szMessage, W32::GetCommandLine(), MB_OK);
}
}


void ErrorExit(UINT iError, LPCTSTR szMessage)
{
if (szMessage)
{
int cbOut;
TCHAR szBuffer[256]; // errors only, not used for display output
if (iError == 0)
cbOut = lstrlen(szMessage);
else
{
LPCTSTR szTemplate = (iError & 0x80000000L)
? TEXT("Error 0x%X. %s\n")
: TEXT("Error %i. %s\n");
cbOut = wsprintf(szBuffer, szTemplate, iError, szMessage);
szMessage = szBuffer;
}
if (g_hStdOut)
{
#ifdef UNICODE
char rgchTemp[cchDisplayBuf];
if (W32::GetFileType(g_hStdOut) == FILE_TYPE_CHAR)
{
W32::WideCharToMultiByte(CP_ACP, 0, szMessage, cbOut, rgchTemp, sizeof(rgchTemp), 0, 0);
szMessage = (LPCWSTR)rgchTemp;
}
else
cbOut *= 2; // write Unicode if not console device
#endif // UNICODE
DWORD cbWritten;
W32::WriteFile(g_hStdOut, szMessage, cbOut, &cbWritten, 0);
}
else
W32::MessageBox(0, szMessage, W32::GetCommandLine(), MB_OK);
}
MSI::MsiCloseAllHandles();
W32::ExitProcess(szMessage != 0);
}

void CheckError(UINT iError, LPCTSTR szMessage)
{
if (iError != ERROR_SUCCESS)
ErrorExit(iError, szMessage);
}

#else // RC_INVOKED, end of source code, start of resources
#endif // RC_INVOKED
#if 0
!endif // makefile terminator
#endif