mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 15:23:02 +01:00
Close some of my favorite B.O.'s since FB1. To be reviewed by Vlad.
This commit is contained in:
parent
3d97a35be5
commit
d50c65a3d9
@ -70,7 +70,7 @@ char* copy_terminate(char* dest, const char* src, size_t bufsize)
|
||||
**************************************/
|
||||
if (!bufsize) // Was it a joke?
|
||||
return dest;
|
||||
|
||||
|
||||
--bufsize;
|
||||
strncpy(dest, src, bufsize);
|
||||
dest[bufsize] = 0;
|
||||
@ -295,7 +295,7 @@ int snprintf(char* buffer, size_t count, const char* format...)
|
||||
// However, there are several usages through fb_utils::get_passwd(char* arg);
|
||||
char* cleanup_passwd(char* arg)
|
||||
{
|
||||
if (! arg)
|
||||
if (! arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
@ -304,7 +304,7 @@ char* cleanup_passwd(char* arg)
|
||||
char* savePass = (char*) gds__alloc(lpass + 1);
|
||||
if (! savePass)
|
||||
{
|
||||
// No clear idea, how will it work if there is no memory
|
||||
// No clear idea, how will it work if there is no memory
|
||||
// for password, but let others think. As a minimum avoid AV.
|
||||
return arg;
|
||||
}
|
||||
@ -319,12 +319,12 @@ char* cleanup_passwd(char* arg)
|
||||
static bool validateProductSuite (LPCSTR lpszSuiteToValidate);
|
||||
static bool isGlobalKernelPrefix();
|
||||
|
||||
// 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.
|
||||
// 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 prefix_kernel_object_name(char* name, size_t bufsize)
|
||||
bool prefix_kernel_object_name(char* name, size_t bufsize)
|
||||
{
|
||||
static bool bGlobalPrefix = false;
|
||||
static bool bInitDone = false;
|
||||
@ -335,8 +335,8 @@ void prefix_kernel_object_name(char* name, size_t bufsize)
|
||||
bInitDone = true;
|
||||
}
|
||||
|
||||
// Backwards compatibility feature with Firebird 2.0.3 and earlier.
|
||||
// If the name already contains some prefix (specified by the user, as was
|
||||
// Backwards compatibility feature with Firebird 2.0.3 and earlier.
|
||||
// If the name already contains some prefix (specified by the user, as was
|
||||
// recommended in firebird.conf) additional prefix is not added
|
||||
if (bGlobalPrefix && !strchr(name, '\\'))
|
||||
{
|
||||
@ -344,14 +344,19 @@ void prefix_kernel_object_name(char* name, size_t bufsize)
|
||||
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
|
||||
// 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);
|
||||
memcpy(name, prefix, move_prefix);
|
||||
// CVC: Unfortunately, things like Glob instead of Global\\ do not achieve the objective
|
||||
// of telling the NT kernel the object is global and hence I consider them failures.
|
||||
//return move_prefix > 0; // Soft version of the check
|
||||
return move_prefix == len_prefix; // Strict version of the check.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -382,7 +387,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
// hvlad: two functions below got from
|
||||
// hvlad: two functions below got from
|
||||
// http://msdn2.microsoft.com/en-us/library/aa380797.aspx
|
||||
// and slightly adapted for our coding style
|
||||
|
||||
@ -390,18 +395,18 @@ private:
|
||||
// Note that the validateProductSuite and isTerminalServices
|
||||
// functions use ANSI versions of the functions to maintain
|
||||
// compatibility with Windows Me/98/95.
|
||||
// -------------------------------------------------------------
|
||||
// -------------------------------------------------------------
|
||||
|
||||
bool isGlobalKernelPrefix()
|
||||
bool isGlobalKernelPrefix()
|
||||
{
|
||||
// The strategy of this function is as follows: use Global\ kernel namespace
|
||||
// for engine objects if we can. This can be prevented by either lack of OS support
|
||||
// The strategy of this function is as follows: use Global\ kernel namespace
|
||||
// for engine objects if we can. This can be prevented by either lack of OS support
|
||||
// for the feature (Win9X) or lack of privileges (Vista, Windows 2000/XP restricted accounts)
|
||||
|
||||
const DWORD dwVersion = GetVersion();
|
||||
|
||||
// Is Windows NT running?
|
||||
if (!(dwVersion & 0x80000000))
|
||||
if (!(dwVersion & 0x80000000))
|
||||
{
|
||||
if (LOBYTE(LOWORD(dwVersion)) <= 4) // This is Windows NT 4.0 or earlier.
|
||||
return validateProductSuite("Terminal Server");
|
||||
@ -410,25 +415,25 @@ bool isGlobalKernelPrefix()
|
||||
// version of Windows from Windows 2000 and up
|
||||
// Check if we have enough privileges to create global handles.
|
||||
// If not fall back to creating local ones.
|
||||
// The API for that is the NT thing, so we have to get addresses of the
|
||||
// The API for that is the NT thing, so we have to get addresses of the
|
||||
// functions dynamically to avoid troubles on Windows 9X platforms
|
||||
|
||||
DynLibHandle hmodAdvApi(LoadLibrary("advapi32.dll"));
|
||||
|
||||
|
||||
if (!hmodAdvApi) {
|
||||
gds__log("LoadLibrary failed for advapi32.dll. Error code: %lu", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
typedef BOOL (WINAPI *PFnOpenProcessToken) (HANDLE, DWORD, PHANDLE);
|
||||
typedef BOOL (WINAPI *PFnLookupPrivilegeValue) (LPCSTR, LPCSTR, PLUID);
|
||||
typedef BOOL (WINAPI *PFnPrivilegeCheck) (HANDLE, PPRIVILEGE_SET, LPBOOL);
|
||||
|
||||
PFnOpenProcessToken pfnOpenProcessToken =
|
||||
PFnOpenProcessToken pfnOpenProcessToken =
|
||||
(PFnOpenProcessToken) GetProcAddress(hmodAdvApi, "OpenProcessToken");
|
||||
PFnLookupPrivilegeValue pfnLookupPrivilegeValue =
|
||||
PFnLookupPrivilegeValue pfnLookupPrivilegeValue =
|
||||
(PFnLookupPrivilegeValue) GetProcAddress(hmodAdvApi, "LookupPrivilegeValueA");
|
||||
PFnPrivilegeCheck pfnPrivilegeCheck =
|
||||
PFnPrivilegeCheck pfnPrivilegeCheck =
|
||||
(PFnPrivilegeCheck) GetProcAddress(hmodAdvApi, "PrivilegeCheck");
|
||||
|
||||
if (!pfnOpenProcessToken || !pfnLookupPrivilegeValue || !pfnPrivilegeCheck) {
|
||||
@ -464,7 +469,7 @@ bool isGlobalKernelPrefix()
|
||||
|
||||
CloseHandle(hToken);
|
||||
|
||||
return checkResult;
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -523,7 +528,7 @@ void NTRegQuery::close()
|
||||
{
|
||||
if (m_hKey)
|
||||
RegCloseKey(m_hKey);
|
||||
|
||||
|
||||
m_hKey = NULL;
|
||||
}
|
||||
|
||||
@ -578,7 +583,7 @@ inline bool NTLocalString::allocated() const
|
||||
return m_string != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// validateProductSuite function
|
||||
//
|
||||
@ -587,7 +592,7 @@ inline bool NTLocalString::allocated() const
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
bool validateProductSuite (LPCSTR lpszSuiteToValidate)
|
||||
bool validateProductSuite (LPCSTR lpszSuiteToValidate)
|
||||
{
|
||||
NTRegQuery query;
|
||||
|
||||
@ -610,7 +615,7 @@ bool validateProductSuite (LPCSTR lpszSuiteToValidate)
|
||||
return false;
|
||||
|
||||
query.close(); // explicit but redundant.
|
||||
|
||||
|
||||
// Search for suite name in array of strings.
|
||||
bool fValidated = false;
|
||||
LPCSTR lpszSuite = lpszProductSuites.c_str();
|
||||
|
@ -91,8 +91,8 @@ namespace fb_utils
|
||||
}
|
||||
|
||||
#ifdef WIN_NT
|
||||
void prefix_kernel_object_name(char* name, size_t bufsize);
|
||||
#endif
|
||||
bool prefix_kernel_object_name(char* name, size_t bufsize);
|
||||
#endif
|
||||
|
||||
Firebird::PathName get_process_name();
|
||||
SLONG genUniqueId();
|
||||
|
@ -703,7 +703,7 @@ int Sys5Semaphore::getId()
|
||||
#endif // UNIX
|
||||
|
||||
#if defined(WIN_NT)
|
||||
static void make_object_name(TEXT*, size_t, const TEXT*, const TEXT*);
|
||||
static bool make_object_name(TEXT*, size_t, const TEXT*, const TEXT*);
|
||||
#endif
|
||||
|
||||
#if defined FREEBSD || defined NETBSD || defined DARWIN || defined HPUX
|
||||
@ -2413,6 +2413,7 @@ UCHAR* ISC_map_file(
|
||||
bool trunc_flag = true;
|
||||
if (length < 0) {
|
||||
length = -length;
|
||||
fb_assert(length > 0); // Was someone so crazy as to pass a bigger value than MAX_SLONG?
|
||||
trunc_flag = false;
|
||||
}
|
||||
|
||||
@ -2438,14 +2439,20 @@ UCHAR* ISC_map_file(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if file already exists */
|
||||
// Check if file already exists
|
||||
|
||||
const bool file_exists = (GetLastError() == ERROR_ALREADY_EXISTS);
|
||||
|
||||
/* Create an event that can be used to determine if someone has already
|
||||
initialized shared memory. */
|
||||
// Create an event that can be used to determine if someone has already
|
||||
// initialized shared memory.
|
||||
|
||||
if (!make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_event"))
|
||||
{
|
||||
error(status_vector, "make_object_name", GetLastError());
|
||||
CloseHandle(file_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_event");
|
||||
event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, expanded_filename);
|
||||
if (!event_handle) {
|
||||
error(status_vector, "CreateEvent", GetLastError());
|
||||
@ -2453,7 +2460,7 @@ UCHAR* ISC_map_file(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool init_flag = (GetLastError() != ERROR_ALREADY_EXISTS);
|
||||
const bool init_flag = (GetLastError() != ERROR_ALREADY_EXISTS);
|
||||
|
||||
if (init_flag && !init_routine) {
|
||||
CloseHandle(event_handle);
|
||||
@ -2523,7 +2530,13 @@ 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, sizeof(expanded_filename), filename, "_mapping");
|
||||
if (!make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_mapping"))
|
||||
{
|
||||
error(status_vector, "make_object_name", GetLastError());
|
||||
CloseHandle(event_handle);
|
||||
CloseHandle(file_handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HANDLE header_obj = CreateFileMapping ((HANDLE) -1,
|
||||
ISC_get_security_desc(),
|
||||
@ -2550,7 +2563,7 @@ UCHAR* ISC_map_file(
|
||||
goto retry;
|
||||
}
|
||||
|
||||
SLONG* header_address = (SLONG*) MapViewOfFile(header_obj, FILE_MAP_WRITE, 0, 0, 0);
|
||||
SLONG* const header_address = (SLONG*) MapViewOfFile(header_obj, FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
if (header_address == NULL) {
|
||||
error(status_vector, "MapViewOfFile", GetLastError());
|
||||
@ -2572,9 +2585,8 @@ UCHAR* ISC_map_file(
|
||||
|
||||
/* Create the real file mapping object. */
|
||||
|
||||
TEXT* p;
|
||||
for (p = expanded_filename; *p; p++);
|
||||
sprintf(p, "%"SLONGFORMAT, header_address[1]);
|
||||
TEXT mapping_filename[sizeof(expanded_filename) + 15]; // enough for int32 as text
|
||||
sprintf(mapping_filename, "%s%"SLONGFORMAT, expanded_filename, header_address[1]);
|
||||
|
||||
HANDLE file_obj =
|
||||
CreateFileMapping(file_handle,
|
||||
@ -2582,7 +2594,7 @@ UCHAR* ISC_map_file(
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
length,
|
||||
expanded_filename);
|
||||
mapping_filename);
|
||||
if (file_obj == NULL) {
|
||||
error(status_vector, "CreateFileMapping", GetLastError());
|
||||
UnmapViewOfFile(header_address);
|
||||
@ -2592,7 +2604,7 @@ UCHAR* ISC_map_file(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UCHAR* address = (UCHAR*) MapViewOfFile(file_obj, FILE_MAP_WRITE, 0, 0, 0);
|
||||
UCHAR* const address = (UCHAR*) MapViewOfFile(file_obj, FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
if (address == NULL) {
|
||||
error(status_vector, "MapViewOfFile", GetLastError());
|
||||
@ -2604,8 +2616,6 @@ UCHAR* ISC_map_file(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*p = 0;
|
||||
|
||||
shmem_data->sh_mem_address = address;
|
||||
shmem_data->sh_mem_length_mapped = length;
|
||||
|
||||
@ -2628,9 +2638,7 @@ UCHAR* ISC_map_file(
|
||||
if (init_flag) {
|
||||
FlushViewOfFile(address, 0);
|
||||
SetEvent(event_handle);
|
||||
if (SetFilePointer
|
||||
(shmem_data->sh_mem_handle, length, NULL,
|
||||
FILE_BEGIN) == 0xFFFFFFFF
|
||||
if (SetFilePointer(shmem_data->sh_mem_handle, length, NULL, FILE_BEGIN) == 0xFFFFFFFF
|
||||
|| !SetEndOfFile(shmem_data->sh_mem_handle)
|
||||
|| !FlushViewOfFile(shmem_data->sh_mem_address, 0))
|
||||
{
|
||||
@ -3474,10 +3482,12 @@ int ISC_mutex_init(struct mtx* mutex, const TEXT* mutex_name)
|
||||
**************************************/
|
||||
char name_buffer[MAXPATHLEN];
|
||||
|
||||
make_object_name(name_buffer, sizeof(name_buffer), mutex_name, "_mutex");
|
||||
if (!make_object_name(name_buffer, sizeof(name_buffer), mutex_name, "_mutex"))
|
||||
{
|
||||
return FB_FAILURE;
|
||||
}
|
||||
|
||||
return !initializeFastMutex(&mutex->mtx_fast,
|
||||
ISC_get_security_desc(), FALSE, name_buffer);
|
||||
return !initializeFastMutex(&mutex->mtx_fast, ISC_get_security_desc(), FALSE, name_buffer);
|
||||
}
|
||||
|
||||
|
||||
@ -4121,7 +4131,7 @@ static SLONG find_key(ISC_STATUS* status_vector, const TEXT* filename)
|
||||
|
||||
|
||||
#ifdef WIN_NT
|
||||
static void make_object_name(
|
||||
static bool make_object_name(
|
||||
TEXT* buffer,
|
||||
size_t bufsize,
|
||||
const TEXT* object_name,
|
||||
@ -4139,8 +4149,15 @@ static void make_object_name(
|
||||
*
|
||||
**************************************/
|
||||
char hostname[64];
|
||||
_snprintf(buffer, bufsize, object_name, ISC_get_host(hostname, sizeof(hostname)));
|
||||
buffer[bufsize - 1] = 0;
|
||||
const int rc = snprintf(buffer, bufsize, object_name, ISC_get_host(hostname, sizeof(hostname)));
|
||||
if (rc == bufsize || rc <= 0)
|
||||
{
|
||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
char& limit = buffer[bufsize - 1];
|
||||
limit = 0;
|
||||
|
||||
char* p;
|
||||
char c;
|
||||
@ -4149,6 +4166,14 @@ static void make_object_name(
|
||||
if (c == '/' || c == '\\' || c == ':')
|
||||
*p = '_';
|
||||
}
|
||||
|
||||
// We either append the full object type or produce failure.
|
||||
if (p >= &limit || p + strlen(object_type) > &limit)
|
||||
{
|
||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
strcpy(p, object_type);
|
||||
|
||||
// hvlad: windows file systems use case-insensitive file names
|
||||
@ -4158,6 +4183,13 @@ static void make_object_name(
|
||||
// misunderstanding between processes
|
||||
strlwr(buffer);
|
||||
|
||||
fb_utils::prefix_kernel_object_name(buffer, bufsize);
|
||||
// CVC: I'm not convinced that if this call has no space to put the prefix,
|
||||
// we can ignore that fact, hence I changed that signature, too.
|
||||
if (!fb_utils::prefix_kernel_object_name(buffer, bufsize))
|
||||
{
|
||||
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // WIN_NT
|
||||
|
Loading…
Reference in New Issue
Block a user