Subject bug, in embedded firebird versions, handling the conn string (full path to DB)
Author lucipl77
Hi,
My configuration: Firebird 2.0.3.12981 embedded release ( or
2.1.1.17910 embedded release) on Windows XP x64 SP2 , Intel CPU,
IBPP, Visual C++ Visual Studio 2005.

I want to open a firebird database from the local computer and it
doesn't work if the database path contains unicode characters.
I tried several aproaches to convert the path from a widechar string
to ansi string:
- converting the path to MBCS using WideCharToMultiByte API, with
the CP_THREAD_ACP, CP_ACP.
- converting the path to 8.3 format using GetShortPathName API.

The error:
when isc_attach_database is executed it returns with the following
error description:

Engine Code : 335544344
Engine Message :
I/O error for file "D:\Temp\CHINES~1\test.FDB"
Error while trying to open file
The filename, directory name, or volume label syntax is incorrect.


I'd say this is a bug because the full path to DB file provided by the
user is certainly tampered with and not passed as it is to the :
CreateFile(...) win API used in:

jrd_file* PIO_open(Database* dbb, const Firebird::PathName& string,
bool trace_flag, const Firebird::PathName& file_name, bool
share_delete) (jrd\os\win32\winnt.cpp)

The proof of this is the following simple code (VC++ MS VStudio ):

CStringW strWDatabasePath = _T("D:\\Temp\\Chinese 壇\\test.FDB");

// we split the path and the filename, we want to convert the path to
// 8.3 format that is always composed only of ansi chars
CString szPath;
int iPos = strWDatabasePath.ReverseFind(_T('\\'));
szPath = strWDatabasePath.Left(iPos);
CString szFilename;
szFilename = strWDatabasePath.Mid(iPos);

// filename to ansi chars
CStringA szAFilename;
szAFilename.Format("%S", szFilename);

// converting to 8.3
CStringW szShortDatabase;
int iSize = GetShortPathName(szPath, NULL, 0);
GetShortPathName(szPath, szShortDatabase.GetBuffer(iSize), iSize);
szShortDatabase.ReleaseBuffer();
szShortDatabase += szFilename;

// converting to MBCS, anyway in this case will contain only
// ansi chars because of the 8.3 format
CStringA strDatabasePath;
int nLength=WideCharToMultiByte(CP_THREAD_ACP, 0, szShortDatabase, -1,
NULL, 0, NULL, NULL);
int a = WideCharToMultiByte(CP_THREAD_ACP, 0,szShortDatabase,-1,
strDatabasePath.GetBuffer(nLength + 2),nLength + 2,NULL,NULL);
bool share_delete = FALSE;


// the test of opening the file using the 8.3 path and the win API
// function used in firebird, file is opened and closed succesfully
HANDLE desc = CreateFileA(strDatabasePath.GetString(),
GENERIC_READ |GENERIC_WRITE,
g_dwShareFlags | (share_delete ? FILE_SHARE_DELETE : 0),
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | g_dwExtraFlags, 0);
CloseHandle(desc);


// using it in firebird embedded through IBPP wrappers (i've checked
// nothing happens to the string in IBPP till is passed to
// 'isc_attach_database' in firebird engine )

db1 = IBPP::DatabaseFactory("", strDatabasePath.GetString(), "SYSDBA",
"masterkey");
try
{
db1->Connect();
}catch(ibpp_internals::SQLExceptionImpl ex)
{
printf("Error: %s \n", ex.what());
}

// Connect throws exception, actually 'isc_attach_database' inside
IBPP, reported at the beginning of the post.