home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Borland
/
Cplus45
/
BC45
/
OCT_REG.PAK
/
REGISTER.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-29
|
10KB
|
285 lines
//----------------------------------------------------------------------------
// ObjectComponents - (C) Copyright 1994 by Borland International
// Tool to load, register, unregister, and debug OLE2 inproc servers and EXEs.
// Reads its command line to determine action, suggestion: use progman icons.
// Does no registration itself, simply invokes functions in the OC component.
// Brings up help dialog on empty command line; refer to that for usage info.
//----------------------------------------------------------------------------
#include <ocf/ocreg.h>
#include <string.h>
#include "register.rh"
#include <shellapi.h>
#define DLLENTRY "DllRegisterCommand"
#define REGISTER32 "REGIST32.EXE"
//
// Error handling facility using local exception object
//
struct TLocalError { // local exception object for this program
TLocalError(const char* title, const char* message)
: Title(title), Message(message) {}
const char* Title;
const char* Message;
};
static void Error(const char* title, const char* message)
{
throw TLocalError(title, message);
}
static inline void ErrorIf(int error, const char* title, int resId)
{
if (error)
Error(title, (char*)resId);
}
static inline void ErrorIf(int error, int resId, const char* message)
{
if (error)
Error((char*)resId, message);
}
static inline void ErrorIf(int error, const char* title, const char* message)
{
if (error)
Error(title,message);
}
//
// File type determination
//
const int ftExists = 1;
const int ftModule = 2;
const int ftLibrary = 4;
const int ft32Bit = 8;
int GetFileType(const char far* fileName)
{
HFILE hdl = _lopen(fileName, OF_READ);
if (hdl == HFILE_ERROR)
return 0;
int type = ftExists;
char buf[64];
if (_lread(hdl, buf, sizeof(buf)) == sizeof(buf) &&
*(short*)(buf+0x00) == 0x5A4D && // check if executable image
*(short*)(buf+0x18) == 0x0040) { // check if NEWEXE type, not just DOS
long offset = *(long*)(buf+0x3C);
if (_llseek(hdl, offset, 0) != HFILE_ERROR &&
_lread(hdl, buf, sizeof(buf)) == sizeof(buf)) {
if (*(short*)(buf+0x00) == 0x454E) { // check if 16-bit module
type |= ftModule;
if (*(short*)(buf+0x0C) & 0x8000)
type |= ftLibrary;
} else if (*(short*)(buf+0x00) == 0x4550) { // check if 32-bit module
type |= (ftModule | ft32Bit);
if (*(short*)(buf+0x16) & 0x2000)
type |= ftLibrary;
}
}
}
_lclose(hdl);
return type;
}
//
// DLL loading and entry point management class
//
struct TDllData {
TDllData() : Lib(0) {::OleInitialize(0);}
~TDllData() {FreeLib(); ::OleUninitialize();}
bool LoadLib(const char* name);
void FreeLib() {if (Lib) ::FreeLibrary(Lib); Lib = 0;}
bool GetEntry();
HRESULT CallEntry(const char far* cmdLine);
HINSTANCE Lib;
union {
TDllRegisterCommand DllRegisterCommand;
FARPROC DllRegProc;
};
};
bool TDllData::LoadLib(const char* name)
{
DllRegProc = 0;
FreeLib();
if ((Lib=::LoadLibrary(name)) >= (HINSTANCE)HINSTANCE_ERROR)
return true;
Lib = 0;
return false;
}
bool TDllData::GetEntry()
{
return (DllRegProc = ::GetProcAddress(Lib, DLLENTRY)) != 0;
}
HRESULT TDllData::CallEntry(const char far* cmdLine)
{
return (*DllRegisterCommand)(cmdLine);
}
//
// Command option state flags
//
const int rfDone = 1; // force break from loop
const int rfNoValue = 2; // no value allowed for option
const int rfReqValue = 4; // value required for option
const int rfOptValue = 8; // optional value for option
const int rfDebug = 16; // special test for debug option
const int rfTypeLib = 32; // check for typelib generation errors
const int rfRegServer=64; // check for registration errors
const int rfQuietReg=128; // suppress registry error reporting
//
// Command option table
//
struct {
char* String;
int Flags;
} table[] = {
{"Language", rfOptValue },
{"RegServer", rfOptValue | rfRegServer },
{"UnregServer",rfNoValue },
{"TypeLib", rfOptValue | rfTypeLib },
{"Debug", rfNoValue | rfDebug },
{"QuietReg", rfQuietReg | rfNoValue },
};
const int tableCount = sizeof(table)/sizeof(table[0]);
#define MAX_CMD_LINE 256
bool CALLBACK __export
HelpProc(HWND hDlg, UINT msg, WPARAM /*wParam*/, LPARAM /*lParam*/)
{
if (msg != WM_COMMAND)
return msg == WM_INITDIALOG;
::EndDialog(hDlg, TRUE);
return true;
}
int PASCAL
WinMain(HINSTANCE hInst, HINSTANCE/*hPrev*/, char far* cmdLine, int/*show*/)
{
TCmdLine cmd(cmdLine);
TDllData dll;
int optFlags;
int curFlags;
char cmdbuf[MAX_CMD_LINE + sizeof(REGISTER32)]; // complete command line
char modName[MAX_CMD_LINE]; // copy of module name only, including file path
char* execmd; // command line for EXE, include module path
char* regcmd; // command line for DLL, no file path
char* cmdptr;
int tblIndex;
char regBuf[80]; // holds error string from registry
try {
if (cmd.NextToken() != TCmdLine::Name)
return ::DialogBox(hInst, MAKEINTRESOURCE(IDD_HELP), 0,(DLGPROC)HelpProc);
do { // module loop
optFlags = 0;
curFlags = rfNoValue;
strcpy(cmdbuf, REGISTER32); // set up to spawn 32-bit tool from 16-bit
execmd = cmdbuf + strlen(cmdbuf);
*execmd++ = ' '; // start of command line for EXE
memcpy(execmd, cmd.Token, cmd.TokenLen);
cmdptr = execmd + cmd.TokenLen;
*cmdptr = 0; // temp. terminate for strchr and strcpy
if ((regcmd = strchr(execmd, '+')) != 0) // test for "tdw+module.exe"
*regcmd++ = ' ';
else
regcmd = execmd;
strcpy(modName, regcmd);
*cmdptr++ = ' ';
regcmd = cmdptr; // reg options only, for DLL, no pathname
strcpy(cmdptr, "/QuietReg ");
cmdptr += strlen(cmdptr);
do {
switch (cmd.NextToken()) {
case TCmdLine::Name:
case TCmdLine::Done:
ErrorIf(!optFlags, modName, IDS_NOOPTIONS);
curFlags |= rfDone; // break out of loop
continue;
case TCmdLine::Option:
tblIndex = 0;
while (strnicmp(cmd.Token, table[tblIndex].String, cmd.TokenLen))
ErrorIf(++tblIndex == tableCount, IDS_UNKNOWNOPT, cmd.Token);
curFlags = table[tblIndex].Flags;
optFlags |= curFlags;
if (curFlags & rfQuietReg)
break;
*cmdptr++ = '/'; // use slash for option, dash needs leading space
strcpy(cmdptr, table[tblIndex].String);
cmdptr += strlen(table[tblIndex].String);
break;
case TCmdLine::Value:
ErrorIf((curFlags & rfNoValue), cmd.Token, IDS_MISSINGOPT);
curFlags = rfNoValue; // prevent another value without option
*cmdptr++ = '=';
memcpy(cmdptr, cmd.Token, cmd.TokenLen);
cmdptr += cmd.TokenLen;
break;
}
} while (!(curFlags & rfDone));
*cmdptr = 0;
int fileType = GetFileType(modName);
ErrorIf(!(fileType & ftExists), IDS_NOFINDMOD, modName);
ErrorIf(!(fileType & ftModule), IDS_INVALIDMOD, modName);
if (fileType & ftLibrary) {
#ifdef __WIN32__
ErrorIf(!(fileType&ft32Bit),IDS_CANTLOAD16,modName);
{
#else
if (fileType & ft32Bit) {
uint execStat = ::WinExec(cmdbuf, SW_SHOW);
ErrorIf(execStat < (uint)HINSTANCE_ERROR, IDS_CANTLOAD32, modName);
} else {
#endif
ErrorIf(!dll.LoadLib(modName), IDS_NOLOADMOD, modName);
ErrorIf(!dll.GetEntry(), IDS_NOENTRYPNT, DLLENTRY);
ErrorIf(dll.CallEntry(regcmd) != NOERROR, IDS_REGFAILURE, execmd);
if (optFlags & rfDebug)
::MessageBox(0, "Press OK to unload when debugging is finished",
"DLL loaded for debugging", MB_OK);
}
} else {
uint execStat = ::WinExec(execmd, SW_HIDE);
ErrorIf(execStat < (uint)HINSTANCE_ERROR, IDS_NOLOADMOD, modName);
}
if (optFlags & rfQuietReg) // ignore errors if spawned from another app
continue;
long buflen = sizeof(regBuf);
if ((optFlags & rfRegServer) && ERROR_SUCCESS ==
::RegQueryValue(HKEY_CLASSES_ROOT,"OcErr_RegServer", regBuf,&buflen)){
::RegDeleteKey(HKEY_CLASSES_ROOT, "OcErr_RegServer");
Error((char*)IDS_REGFAILURE, regBuf);
}
if ((optFlags & rfTypeLib) && ERROR_SUCCESS ==
::RegQueryValue(HKEY_CLASSES_ROOT, "OcErr_Typelib", regBuf,&buflen)){
::RegDeleteKey(HKEY_CLASSES_ROOT, "OcErr_Typelib");
Error((char*)IDS_TYPELIBERR, regBuf);
}
} while (cmd.Kind != TCmdLine::Done);
return 0;
}
catch (TLocalError& xcpt) {
char msgbuf[80];
const char ** pmsg;
if ( *(pmsg = &xcpt.Message) <= (const char*)IDS_MAX ||
*(pmsg = &xcpt.Title) <= (const char*)IDS_MAX) {
::LoadString(hInst, *(unsigned*)pmsg, msgbuf, sizeof(msgbuf));
*pmsg = msgbuf;
}
::MessageBox(0, xcpt.Message, xcpt.Title, MB_OK);
}
catch (xmsg& xcpt) { // should not occur, but check anyway while catching
::MessageBox(0, xcpt.why().c_str(), "Exception", MB_OK);
}
return 1;
}