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:
parent
28bf34a56a
commit
74035b375e
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user