Modificato il meccanismo di chiamata delle applicazioni

git-svn-id: svn://10.65.10.50/trunk@3031 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
alex 1996-06-20 13:53:24 +00:00
parent 28bf34a56a
commit 74035b375e
2 changed files with 167 additions and 52 deletions

View File

@ -6,6 +6,17 @@
#include <utility.h>
#include <mask.h>
#if XVT_OS == XVT_OS_WIN
#include <windows.h>
#include <string.h>
#include <ctype.h>
#pragma hdrstop
#include "prochook.h"
#define MAX_PATH 260 // This really should be in WINDOWS.H, but is
// inexplicably hard-coded into the data structures
int MungeModuleHeader( HINSTANCE hInstance, BOOL fMunge );
#endif
#if XVT_OS == XVT_OS_SCOUNIX
extern "C" { long nap(long period); }
#endif
@ -55,56 +66,156 @@ BOOLEAN CAMPI_SCAVATI = FALSE;
const word WM_WAKEUP = RegisterWindowMessage("WAKEUP");
// By Matt Pietrek
bool allow_another_instance()
//########################################################################
// Code that does the real work
//########################################################################
//
// Central function that modifies a module table to trick the loader
// into letting a second instance of a multiple data segment program run.
//
int MungeModuleHeader( HINSTANCE hInstance, BOOL fMunge )
{
// Convert the HINSTANCE to an HMODULE
HINSTANCE hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE);
LPCSTR sModuleName = (LPCSTR)MAKELP(0, hInstance);
HMODULE hModule = GetModuleHandle(sModuleName);
void FAR* mem_handle = GlobalLock(hModule);
HMODULE hModuleSel = (HMODULE)SELECTOROF(mem_handle);
if (hModuleSel == 0) // Make sure we succeeded.
return FALSE;
// Make pointers to the resident names table and the OFSTRUCT
LPSTR moduleName = (LPSTR)MAKELP( hModuleSel, *(WORD FAR *)MAKELP(hModuleSel, 0x26));
LPSTR fileName = (LPSTR)MAKELP( hModuleSel, *(WORD FAR *)MAKELP(hModuleSel, 0x0A));
// Get the module name length, and advance to the actual string
BYTE cbModuleName = *moduleName++; // First byte is a length byte
// Convert the first uppercase letter of the modulename to lowercase
while ( cbModuleName )
{
if ( isupper(*moduleName) )
{
*moduleName = tolower(*moduleName); break;
}
cbModuleName--; moduleName++;
}
if ( cbModuleName == 0 ) // Make sure we succeeded
return FALSE;
// Position to the end of the filename. First byte is a length byte
fileName += *fileName - 1;
// Find the first uppercase letter in the filename. Convert to lowercase
while ( TRUE )
{
// Stop when we come to a directory separator or colon
if ( (*fileName=='\\') || (*fileName=='/') || (*fileName==':') )
return FALSE;
HMODULE hModuleSel;
LPSTR lpszModName, lpszFileName;
BYTE cbModuleName;
static BOOL fResidentNamesMunged = FALSE;
if ( isupper(*fileName) )
hModuleSel = SELECTOROF( // Convert the HINSTANCE to an HMODULE
GlobalLock(GetModuleHandle((LPSTR)MAKELP(0,hInstance))));
if ( hModuleSel == 0 ) // Make sure we succeeded.
return 0;
//
// First, we'll take care of the resident names table
//
if ( FALSE == fResidentNamesMunged )
{
*fileName = tolower(*fileName); break;
// Make pointers to the module name in the resident names table
lpszModName = (LPSTR)MAKELP(hModuleSel,
*(WORD FAR *)MAKELP(hModuleSel, 0x26) );
// Get the module name length, and advance to the actual string
cbModuleName = *lpszModName++; // First byte is a length byte
// Convert the first uppercase letter of the modulename to lowercase
while ( cbModuleName )
{
if ( isupper(*lpszModName) )
{
*lpszModName = tolower(*lpszModName); break;
}
cbModuleName--; lpszModName++;
}
if ( cbModuleName == 0 ) // Make sure we succeeded
return 0;
// Remember that we've done this, so that we don't bother doing
// it in the future.
fResidentNamesMunged = TRUE;
}
fileName--;
}
//
// Now, we'll turn our attention to the module file name in the OFSTRUCT
//
lpszFileName = (LPSTR)MAKELP(hModuleSel,
*(WORD FAR *)MAKELP(hModuleSel, 0x0A));
// Position to the end of the filename. First byte is a length byte
lpszFileName += *lpszFileName - 1;
// If we're munging, added 0x30 to the last character value, otherwise
// subtract 0x30. 0x30 is chosen completely at random.
if ( fMunge )
*lpszFileName += 0x30;
else
*lpszFileName -= 0x30;
return 1;
}
//########################################################################
// This section watches calls to LoadModule and munges the EXE's module
// database as needed.
//########################################################################
HIDDEN NPHOOKCHILD npHookLoadModule = 0;
HIDDEN char szOurFileName[MAX_PATH];
HIDDEN HINSTANCE HInstance;
HINSTANCE
WINAPI
__export MultInst95LoadModule( LPCSTR lpszModuleName,
LPVOID lpvParameterBlock )
{
HINSTANCE retValue;
// Uppercase the name of the module name that was passed to LoadModule
char szNewFileName[MAX_PATH];
lstrcpy( szNewFileName, lpszModuleName );
strupr( szNewFileName );
// Compare the incoming filename to our EXE's module name. If they
// don't match, we don't need to bother munging the module database
BOOL fSecondInstance = strstr(szOurFileName, szNewFileName) ? TRUE:FALSE;
// Unhook our LoadModule hook so that we can call the real LoadModule
ProcUnhook( npHookLoadModule );
// Munge module database if needed
if ( fSecondInstance )
MungeModuleHeader( HInstance, TRUE );
// Call the original LoadModule code
retValue = LoadModule( lpszModuleName, lpvParameterBlock );
// Unmunge module database if needed
if ( fSecondInstance )
MungeModuleHeader( HInstance, FALSE );
// Reinstall our LoadModule hook so that we see future loads
ProcHook( npHookLoadModule );
return retValue;
}
BOOL deny_another_instance()
{
if ( !npHookLoadModule )
return FALSE;
SetProcRelease( npHookLoadModule );
npHookLoadModule = 0;
return TRUE;
}
BOOL allow_another_instance()
{
if ( npHookLoadModule )
return TRUE;
// Get the EXE's filename into a global string variable and uppercase it
GetModuleFileName( HInstance, szOurFileName, sizeof(szOurFileName) );
strupr( szOurFileName );
// Create a MakeProcInstance thunk so that our callback function
// will always be using the correct DS selector
FARPROC lpfnMPI
= MakeProcInstance( (FARPROC)MultInst95LoadModule, HInstance );
if ( !lpfnMPI )
return FALSE;
// Call PROCHOOK.DLL to hook calls to LoadModule
npHookLoadModule = SetProcAddress( (FARPROC)LoadModule,
lpfnMPI, FALSE );
return (BOOL)npHookLoadModule;
}
static BOOLEAN event_hook(HWND hwnd,
UINT msg,
UINT wparam,
@ -122,9 +233,10 @@ static BOOLEAN event_hook(HWND hwnd,
WINDOW win = cur_win();
if (win != NULL_WIN)
{
TWindow* w = (TWindow*)xvt_vobj_get_data(win);
// TWindow* w = (TWindow*)xvt_vobj_get_data(win);
const KEY key = toupper(wparam)+K_CTRL;
w->on_key(key);
// w->on_key(key);
dispatch_e_char(win, key);
}
}
break;
@ -502,11 +614,10 @@ void customize_controls(
#if XVT_OS == XVT_OS_WIN
xvt_vobj_set_attr(NULL_WIN,ATTR_EVENT_HOOK, (long)event_hook);
xvt_vobj_set_attr(NULL_WIN,ATTR_ERRMSG_HANDLER, (long)error_hook);
allow_another_instance();
HINSTANCE hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE);
Ctl3dRegister(hInstance);
Ctl3dAutoSubclass(hInstance);
HInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE);
Ctl3dRegister(HInstance);
Ctl3dAutoSubclass(HInstance);
#endif
customize_colors();
init_controls();
@ -514,8 +625,9 @@ void customize_controls(
else
{
#if XVT_OS == XVT_OS_WIN
HINSTANCE _hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE);
Ctl3dUnregister(_hInstance);
// HINSTANCE _hInstance = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE);
Ctl3dUnregister(HInstance);
deny_another_instance();
#endif
free_controls();
}

View File

@ -29,6 +29,9 @@ WINDOW xvt_create_window
long app_data
);
int allow_another_instance();
int deny_another_instance();
WINDOW xvt_create_statbar();
void xvt_statbar_set(const char* text, bool def = FALSE);
void xvt_statbar_refresh();