8
0
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:
hvlad 2007-02-19 13:05:27 +00:00
parent 8201690ecd
commit c0989bce8b
5 changed files with 203 additions and 11 deletions

View File

@ -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++)

View File

@ -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

View File

@ -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*);
*/

View File

@ -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

View File

@ -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);
}