8
0
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:
robocop 2008-10-21 06:17:03 +00:00
parent 3d97a35be5
commit d50c65a3d9
3 changed files with 91 additions and 54 deletions

View File

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

View File

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

View File

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