mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:03:03 +01:00
Fixed CORE-1031 : fb_lock_print.exe fails on windows 2003 R2 / XP SP 2
and CORE-1133 : XNET (IPC) communication protocol does not work across sessions
This commit is contained in:
parent
8201690ecd
commit
c0989bce8b
@ -30,7 +30,7 @@
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../../jrd/isc_proto.h"
|
||||
|
||||
// config_file works with OS case-sensitivity
|
||||
typedef Firebird::PathName string;
|
||||
@ -53,6 +53,8 @@ const char* AmNative = "native";
|
||||
const char* AmTrusted = "trusted";
|
||||
const char* AmMixed = "mixed";
|
||||
|
||||
char defIpcName[MAXPATHLEN];
|
||||
|
||||
const ConfigImpl::ConfigEntry ConfigImpl::entries[] =
|
||||
{
|
||||
{TYPE_STRING, "RootDirectory", (ConfigValue) 0},
|
||||
@ -97,7 +99,7 @@ const ConfigImpl::ConfigEntry ConfigImpl::entries[] =
|
||||
{TYPE_STRING, "RemoteServiceName", (ConfigValue) FB_SERVICE_NAME},
|
||||
{TYPE_INTEGER, "RemoteServicePort", (ConfigValue) 0},
|
||||
{TYPE_STRING, "RemotePipeName", (ConfigValue) FB_PIPE_NAME},
|
||||
{TYPE_STRING, "IpcName", (ConfigValue) FB_IPC_NAME},
|
||||
{TYPE_STRING, "IpcName", (ConfigValue) defIpcName},
|
||||
#ifdef WIN_NT
|
||||
{TYPE_INTEGER, "MaxUnflushedWrites", (ConfigValue) 100},
|
||||
{TYPE_INTEGER, "MaxUnflushedWriteTime", (ConfigValue) 5},
|
||||
@ -182,6 +184,11 @@ ConfigImpl::ConfigImpl(MemoryPool& p) : ConfigRoot(p)
|
||||
string val_sep = ",";
|
||||
file.setConfigFilePath(getConfigFilePath());
|
||||
|
||||
strncpy(defIpcName, FB_IPC_NAME, sizeof(defIpcName));
|
||||
#ifdef WIN_NT
|
||||
ISC_prefix_object_name(defIpcName, sizeof(defIpcName));
|
||||
#endif
|
||||
|
||||
/* Iterate through the known configuration entries */
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
|
175
src/jrd/isc.cpp
175
src/jrd/isc.cpp
@ -1132,5 +1132,178 @@ LPSECURITY_ATTRIBUTES ISC_get_security_desc()
|
||||
return &security_attr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool validateProductSuite (LPSTR lpszSuiteToValidate);
|
||||
bool isTerminalServicesEnabled();
|
||||
|
||||
// hvlad: begins from Windows 2000 we can safely add 'Global\' prefix for
|
||||
// names of all kernel objects we use. For Win9x we must not add this prefix.
|
||||
// Win NT will accept such names only if Terminal Server is installed.
|
||||
// Check OS version carefully and add prefix if we can add it
|
||||
|
||||
void ISC_prefix_object_name(char* name, size_t bufsize)
|
||||
{
|
||||
static bool bTSEnabled = false;
|
||||
static bool bInitDone = false;
|
||||
|
||||
if (!bInitDone)
|
||||
{
|
||||
bTSEnabled = isTerminalServicesEnabled();
|
||||
bInitDone = true;
|
||||
}
|
||||
|
||||
if (bTSEnabled)
|
||||
{
|
||||
const char *prefix = "Global\\";
|
||||
const size_t len_prefix = strlen(prefix);
|
||||
const size_t len_name = strlen(name) + 1;
|
||||
|
||||
// if name and prefix can't fit in name's buffer than we must
|
||||
// not overwrite end of name because it contains object type
|
||||
const int move_prefix = (len_name + len_prefix > bufsize) ?
|
||||
(bufsize - len_name) : len_prefix;
|
||||
|
||||
memmove(name + move_prefix, name, len_name);
|
||||
memmove(name, prefix, move_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
// hvlad: two functions below got from
|
||||
// http://msdn2.microsoft.com/en-us/library/aa380797.aspx
|
||||
// and slightly adapted for our coding style
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Note that the validateProductSuite and IsTerminalServices
|
||||
// functions use ANSI versions of the functions to maintain
|
||||
// compatibility with Windows Me/98/95.
|
||||
// -------------------------------------------------------------
|
||||
|
||||
bool isTerminalServicesEnabled()
|
||||
{
|
||||
DWORD dwVersion = GetVersion();
|
||||
|
||||
// Is Windows NT running?
|
||||
if (!(dwVersion & 0x80000000))
|
||||
{
|
||||
// Is it Windows 2000 or greater?
|
||||
if (LOBYTE(LOWORD(dwVersion)) > 4)
|
||||
{
|
||||
return true;
|
||||
|
||||
// hvlad: for now we don't need such complex check but i
|
||||
// preserved code in case we will need it later
|
||||
|
||||
/***
|
||||
// On Windows 2000 and later, use the VerifyVersionInfo and
|
||||
// VerSetConditionMask functions. Don't static link because
|
||||
// it won't load on earlier systems.
|
||||
|
||||
HMODULE hmodNtDll = GetModuleHandleA("ntdll.dll");
|
||||
if (hmodNtDll)
|
||||
{
|
||||
typedef ULONGLONG (WINAPI *PFnVerSetCondition) (ULONGLONG, ULONG, UCHAR);
|
||||
typedef BOOL (WINAPI *PFnVerifyVersionA) (POSVERSIONINFOEXA, DWORD, DWORDLONG);
|
||||
|
||||
PFnVerSetCondition pfnVerSetCondition =
|
||||
(PFnVerSetCondition) GetProcAddress(hmodNtDll, "VerSetConditionMask");
|
||||
|
||||
if (pfnVerSetCondition != NULL)
|
||||
{
|
||||
DWORDLONG dwlCondition =
|
||||
(*pfnVerSetCondition) (dwlCondition, VER_SUITENAME, VER_AND);
|
||||
|
||||
// Get a VerifyVersionInfo pointer.
|
||||
HMODULE hmodK32 = GetModuleHandleA( "KERNEL32.DLL" );
|
||||
if (hmodK32)
|
||||
{
|
||||
PFnVerifyVersionA pfnVerifyVersionA =
|
||||
(PFnVerifyVersionA) GetProcAddress(hmodK32, "VerifyVersionInfoA") ;
|
||||
|
||||
if (pfnVerifyVersionA != NULL)
|
||||
{
|
||||
OSVERSIONINFOEXA osVersion;
|
||||
|
||||
ZeroMemory(&osVersion, sizeof(osVersion));
|
||||
osVersion.dwOSVersionInfoSize = sizeof(osVersion);
|
||||
osVersion.wSuiteMask = VER_SUITE_TERMINAL;
|
||||
|
||||
return (*pfnVerifyVersionA) (&osVersion, VER_SUITENAME, dwlCondition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
***/
|
||||
}
|
||||
else // This is Windows NT 4.0 or earlier.
|
||||
{
|
||||
return validateProductSuite("Terminal Server");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// validateProductSuite function
|
||||
//
|
||||
// Terminal Services detection code for systems running
|
||||
// Windows NT 4.0 and earlier.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
bool validateProductSuite (LPSTR lpszSuiteToValidate)
|
||||
{
|
||||
bool fValidated = false;
|
||||
HKEY hKey = NULL;
|
||||
DWORD dwType = 0;
|
||||
DWORD dwSize = 0;
|
||||
|
||||
// Open the ProductOptions key.
|
||||
LONG lResult = RegOpenKeyA(HKEY_LOCAL_MACHINE,
|
||||
"System\\CurrentControlSet\\Control\\ProductOptions", &hKey);
|
||||
if (lResult != ERROR_SUCCESS)
|
||||
goto exit;
|
||||
|
||||
// Determine required size of ProductSuite buffer.
|
||||
lResult = RegQueryValueExA(hKey, "ProductSuite", NULL, &dwType, NULL, &dwSize);
|
||||
if (lResult != ERROR_SUCCESS || !dwSize)
|
||||
goto exit;
|
||||
|
||||
// Allocate buffer.
|
||||
LPSTR lpszProductSuites = (LPSTR) LocalAlloc(LPTR, dwSize);
|
||||
if (!lpszProductSuites)
|
||||
goto exit;
|
||||
|
||||
// Retrieve array of product suite strings.
|
||||
lResult = RegQueryValueExA(hKey, "ProductSuite", NULL, &dwType,
|
||||
(LPBYTE) lpszProductSuites, &dwSize);
|
||||
if (lResult != ERROR_SUCCESS || dwType != REG_MULTI_SZ)
|
||||
goto exit;
|
||||
|
||||
// Search for suite name in array of strings.
|
||||
LPSTR lpszSuite = lpszProductSuites;
|
||||
while (*lpszSuite)
|
||||
{
|
||||
if (lstrcmpA(lpszSuite, lpszSuiteToValidate) == 0)
|
||||
{
|
||||
fValidated = true;
|
||||
break;
|
||||
}
|
||||
lpszSuite += (lstrlenA( lpszSuite ) + 1);
|
||||
}
|
||||
|
||||
exit:
|
||||
if (lpszProductSuites) {
|
||||
LocalFree(lpszProductSuites);
|
||||
}
|
||||
|
||||
if (hKey) {
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
return fValidated;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,7 @@ void ISC_wake_init(void);
|
||||
#ifdef WIN_NT
|
||||
bool ISC_is_WinNT();
|
||||
struct _SECURITY_ATTRIBUTES* ISC_get_security_desc(void);
|
||||
void ISC_prefix_object_name(char*, size_t);
|
||||
/* Disabled. Not found anywhere.
|
||||
TEXT* ISC_prefix_interbase(TEXT*, TEXT*);
|
||||
*/
|
||||
|
@ -196,7 +196,7 @@ static BOOLEAN mutex_test(MTX);
|
||||
#endif
|
||||
|
||||
#if defined(WIN_NT)
|
||||
static void make_object_name(TEXT*, const TEXT*, const TEXT*);
|
||||
static void make_object_name(TEXT*, size_t, const TEXT*, const TEXT*);
|
||||
#endif
|
||||
|
||||
#if defined FREEBSD || defined NETBSD || defined DARWIN
|
||||
@ -1197,7 +1197,7 @@ int ISC_event_init_shared(
|
||||
|
||||
TEXT event_name[MAXPATHLEN], type_name[16];
|
||||
sprintf(type_name, "_event%d", type);
|
||||
make_object_name(event_name, name, type_name);
|
||||
make_object_name(event_name, sizeof(event_name), name, type_name);
|
||||
if (!
|
||||
(lcl_event->event_handle =
|
||||
CreateEvent(ISC_get_security_desc(), TRUE, FALSE,
|
||||
@ -2589,7 +2589,7 @@ UCHAR* ISC_map_file(
|
||||
/* Create an event that can be used to determine if someone has already
|
||||
initialized shared memory. */
|
||||
|
||||
make_object_name(expanded_filename, filename, "_event");
|
||||
make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_event");
|
||||
if (!ISC_is_WinNT())
|
||||
event_handle =
|
||||
CreateMutex(ISC_get_security_desc(), TRUE, expanded_filename);
|
||||
@ -2688,7 +2688,7 @@ UCHAR* ISC_map_file(
|
||||
/* Create a file mapping object that will be used to make remapping possible.
|
||||
The current length of real mapped file and its name are saved in it. */
|
||||
|
||||
make_object_name(expanded_filename, filename, "_mapping");
|
||||
make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_mapping");
|
||||
|
||||
HANDLE header_obj = CreateFileMapping ((HANDLE) -1,
|
||||
ISC_get_security_desc(),
|
||||
@ -3378,7 +3378,7 @@ int ISC_mutex_init(MTX mutex, const TEXT* mutex_name)
|
||||
**************************************/
|
||||
char name_buffer[MAXPATHLEN];
|
||||
|
||||
make_object_name(name_buffer, mutex_name, "_mutex");
|
||||
make_object_name(name_buffer, sizeof(name_buffer), mutex_name, "_mutex");
|
||||
mutex->mtx_handle =
|
||||
CreateMutex(ISC_get_security_desc(), FALSE, name_buffer);
|
||||
|
||||
@ -4163,6 +4163,7 @@ static BOOLEAN mutex_test(MTX mutex)
|
||||
#ifdef WIN_NT
|
||||
static void make_object_name(
|
||||
TEXT* buffer,
|
||||
size_t bufsize,
|
||||
const TEXT* object_name,
|
||||
const TEXT* object_type)
|
||||
{
|
||||
@ -4178,7 +4179,8 @@ static void make_object_name(
|
||||
*
|
||||
**************************************/
|
||||
char hostname[64];
|
||||
sprintf(buffer, object_name, ISC_get_host(hostname, sizeof(hostname)));
|
||||
_snprintf(buffer, bufsize, object_name, ISC_get_host(hostname, sizeof(hostname)));
|
||||
buffer[bufsize - 1] = 0;
|
||||
|
||||
char* p;
|
||||
char c;
|
||||
@ -4190,9 +4192,11 @@ static void make_object_name(
|
||||
// hvlad: windows file systems use case-insensitive file names
|
||||
// while kernel objects such as events use case-sensitive names.
|
||||
// Since we use root directory as part of kernel objects names
|
||||
// we must user lower (or upper) register for object name to avoid
|
||||
// we must use lower (or upper) register for object name to avoid
|
||||
// misunderstanding between processes
|
||||
strlwr(buffer);
|
||||
|
||||
ISC_prefix_object_name(buffer, bufsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -372,8 +372,15 @@ int CLIB_ROUTINE main( int argc, char *argv[])
|
||||
if ((LOCK_header->lhb_version != SS_LHB_VERSION) &&
|
||||
(LOCK_header->lhb_version != CLASSIC_LHB_VERSION))
|
||||
{
|
||||
FPRINTF(outfile, "\tUnable to read lock table version %d.\n",
|
||||
if (LOCK_header->lhb_type == 0 && LOCK_header->lhb_version == 0)
|
||||
{
|
||||
FPRINTF(outfile, "\tLock table is empty.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
FPRINTF(outfile, "\tUnable to read lock table version %d.\n",
|
||||
LOCK_header->lhb_version);
|
||||
};
|
||||
exit(FINI_OK);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user