- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
502 lines
16 KiB
C++
502 lines
16 KiB
C++
// BDE - (C) Copyright 1994 by Borland International
|
|
|
|
#include "query.h"
|
|
|
|
//===============================================================
|
|
// Name: QueryGetStandardConnection(void)
|
|
//
|
|
// Input: None
|
|
//
|
|
// Return: returns handle to standard database if successful,
|
|
// zero otherwise
|
|
//
|
|
// Description:
|
|
// Opens a standard (Paradox & dBase) database.
|
|
//================================================================
|
|
hDBIDb
|
|
QueryGetStandardConnection(void)
|
|
{
|
|
hDBIDb hDb; // Handle to the database
|
|
|
|
// Open the standard database
|
|
DBIErr(DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbiOPENSHARED,
|
|
NULL, 0, NULL, NULL, &hDb));
|
|
|
|
// Point to the sample tables
|
|
DBIErr(DbiSetDirectory(hDb, szTblDirectory));
|
|
|
|
return hDb;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QueryQExec(hDb, eQryLang, szQuery, szOutputErrorString,
|
|
// phCur)
|
|
//
|
|
// Input: hDb - Handle to the database
|
|
// eQryLang - Query language (SQL or QBE)
|
|
// szQuery - Query string
|
|
// phCur - Pointer to a cursor handle to the result
|
|
// set
|
|
//
|
|
// Return: DBIERR_NONE if successful, otherwise error encountered
|
|
//
|
|
// Description:
|
|
// Prepares and executes an SQL or QBE query.
|
|
//================================================================
|
|
DBIResult
|
|
QueryQExec (hDBIDb hDb, DBIQryLang eQryLang, char* szQuery,
|
|
char *szOutputErrorString, phDBICur phCur)
|
|
{
|
|
DBIResult rslt; // Return Value from Engine functions
|
|
hDBIStmt hStmt; // Handle to the returned Statment (query)
|
|
|
|
// Set up the query.
|
|
if ((rslt = DbiQPrepare(hDb, eQryLang, szQuery, &hStmt))
|
|
!= DBIERR_NONE)
|
|
{
|
|
GetErrorInformation(szOutputErrorString);
|
|
return rslt;
|
|
}
|
|
|
|
// Execute the query.
|
|
rslt = DbiQExec(hStmt, phCur);
|
|
|
|
// Check if query failed.
|
|
if (rslt != DBIERR_NONE)
|
|
{
|
|
GetErrorInformation(szOutputErrorString);
|
|
DBIErr(DbiQFree(&hStmt));
|
|
return rslt;
|
|
}
|
|
|
|
// Free memory associated with the query.
|
|
DBIErr(DbiQFree(&hStmt));
|
|
|
|
return rslt;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QueryDBIInit(void)
|
|
//
|
|
// Input: None.
|
|
//
|
|
// Return: Result of attempt to use DbiInit.
|
|
//
|
|
// Description:
|
|
// Calls DbiInit, notifies user if problem.
|
|
//================================================================
|
|
DBIResult
|
|
QueryDbiInit (void)
|
|
{
|
|
DBIResult rslt; // Return value from IDAPI functions.
|
|
pCHAR pszMessage = NULL;
|
|
|
|
// Initialize IDAPI.
|
|
if (DBIErr(DbiInit(NULL)) != DBIERR_NONE)
|
|
{
|
|
return GlobalDBIErr;
|
|
}
|
|
|
|
// Enable trace info if the debugging layer is enabled.
|
|
DbiDebugLayerOptions(DEBUGON | OUTPUTTOFILE, "QUERY.INF");
|
|
|
|
// Set the directory to use for temporary files.
|
|
rslt = DbiSetPrivateDir(szPrivDirectory);
|
|
if (rslt == DBIERR_DIRBUSY)
|
|
{
|
|
pszMessage = (pCHAR)malloc(((DBIMAXMSGLEN * 3) + 1) * sizeof(char));
|
|
if (pszMessage)
|
|
{
|
|
sprintf(pszMessage, "Directory is busy. Make certain no .LCK"
|
|
" files exist in the %s directory and that the IDAPI"
|
|
" DLLs are unloaded (Reboot Windows).",
|
|
szPrivDirectory);
|
|
MessageBox(NULL, pszMessage, "SetPrivateDir Error",
|
|
MB_OK | MB_ICONHAND);
|
|
free(pszMessage);
|
|
}
|
|
return rslt;
|
|
}
|
|
|
|
return DBIERR_NONE;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QueryDbiExit(void)
|
|
//
|
|
// Input: None
|
|
//
|
|
// Return: Result of attempt to use DbiExit.
|
|
//
|
|
// Descrption:
|
|
// Calls DbiExit, notifies user if problem.
|
|
//================================================================
|
|
DBIResult
|
|
QueryDbiExit (void)
|
|
{
|
|
// Turn off debugging (if Debug layer DLL selected).
|
|
DbiDebugLayerOptions(0, NULL);
|
|
|
|
// Close the engine.
|
|
return DBIErr(DbiExit());
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QueryDbiCloseDatabase(phDb);
|
|
//
|
|
// Input: phDb -- pointer to database handle to close
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// Calls DbiCloseDatabase, displays error message if
|
|
// DBI error is encountered and bDisplayError is TRUE.
|
|
//================================================================
|
|
void
|
|
QueryDbiCloseDatabase (phDBIDb phDb)
|
|
{
|
|
// Close the standard database.
|
|
DBIErr(DbiCloseDatabase(phDb));
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QueryResetConnectDialog(hWnd, dbarray, iSelected);
|
|
//
|
|
// Input: hWnd - Handle to the connect dialog
|
|
// dbarray - The array of database handles, which is used
|
|
// to fill the connection listbox
|
|
// iSelected - Currently selected database
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// Resets the "connect to the database" dialog on
|
|
// during initialization or based on the current
|
|
// driver selected.
|
|
//================================================================
|
|
void
|
|
QueryResetConnectDialog (HWND hWnd, const DBStructArray dbarray,
|
|
const int iSelected)
|
|
{
|
|
hDBICur hList;
|
|
DBDesc DbData;
|
|
int i;
|
|
|
|
// Reset default connection static control.
|
|
SendDlgItemMessage(hWnd, IDS_SELECTED_CONNECTION,
|
|
WM_SETTEXT, 0,
|
|
(LPARAM) dbarray[iSelected].szDatabaseName);
|
|
|
|
// Reset alias listbox.
|
|
if (DBIErr(DbiOpenDatabaseList(&hList)) == DBIERR_NONE)
|
|
{
|
|
while (DbiGetNextRecord(hList, dbiNOLOCK, (pBYTE) &DbData,
|
|
NULL) == DBIERR_NONE)
|
|
{
|
|
SendDlgItemMessage(hWnd, IDC_LB_ALIASES, LB_INSERTSTRING,
|
|
0, (LPARAM) DbData.szName);
|
|
}
|
|
DBIErr(DbiCloseCursor(&hList));
|
|
}
|
|
|
|
// Reset connections listbox.
|
|
SendDlgItemMessage(hWnd, IDC_LB_CONNECTIONS, LB_RESETCONTENT, 0, 0);
|
|
for (i = 0; i < MAX_DATABASE_HANDLES; i++)
|
|
{
|
|
if (dbarray[i].hdb == 0)
|
|
{
|
|
break;
|
|
}
|
|
SendDlgItemMessage(hWnd, IDC_LB_CONNECTIONS, LB_INSERTSTRING, i,
|
|
(LPARAM) dbarray[i].szDatabaseName);
|
|
}
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QueryConnectToDatabase(hWnd);
|
|
//
|
|
// Input: hWnd - Handle to the connect dialog
|
|
//
|
|
// Return: Handle to the database, or zero if connection cannot
|
|
// be established
|
|
//
|
|
// Description:
|
|
// Try to connect to a database based on the data
|
|
// selected in the connection dialog box; display
|
|
// result in the static control.
|
|
//================================================================
|
|
hDBIDb
|
|
QueryConnectToDatabase (HWND hWnd)
|
|
{
|
|
hDBIDb hDb;
|
|
WORD ListIndex;
|
|
pCHAR Msg;
|
|
pCHAR Driver;
|
|
pCHAR Alias;
|
|
pCHAR Password;
|
|
DBIErrInfo ErrInfo;
|
|
|
|
// Init the strings.
|
|
Alias = (pCHAR)malloc(DBIMAXSCFLDLEN);
|
|
Driver = (pCHAR)malloc(DBIMAXSCFLDLEN);
|
|
Password = (pCHAR)malloc(DBIMAXSCFLDLEN);
|
|
Msg = (pCHAR)malloc((DBIMAXMSGLEN + 1) * 4);
|
|
if ((Alias == NULL) || (Driver == NULL) || (Password == NULL) ||
|
|
(Msg == NULL))
|
|
{
|
|
hDb = 0;
|
|
if (Msg) free(Msg);
|
|
if (Alias) free(Alias);
|
|
if (Driver) free(Driver);
|
|
if (Password) free(Password);
|
|
sprintf(Msg, "Unable to connect: Out of memory!");
|
|
SendDlgItemMessage(hWnd, IDC_STATIC_STATUS, WM_SETTEXT, 0,
|
|
(LPARAM) Msg);
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
return hDb;
|
|
}
|
|
|
|
Alias[0] = '\0';
|
|
Driver[0] = '\0';
|
|
Password[0] = '\0';
|
|
|
|
// SQL database needs the alias & password.
|
|
ListIndex = (WORD)SendDlgItemMessage(hWnd, IDC_LB_ALIASES, LB_GETCURSEL, 0,
|
|
0);
|
|
SendDlgItemMessage(hWnd, IDC_LB_ALIASES, LB_GETTEXT, (WPARAM)
|
|
ListIndex, (LPARAM) Alias);
|
|
SendDlgItemMessage(hWnd, IDC_EDIT_PASSWORD, WM_GETTEXT, 80,
|
|
(LPARAM) Password);
|
|
|
|
// Try to open the database.
|
|
hDb = 0;
|
|
SendDlgItemMessage(hWnd, IDL_RESULTS, LB_RESETCONTENT, 0, 0);
|
|
|
|
// Establish connection to the database
|
|
if ((DbiOpenDatabase(Alias, Driver, dbiREADWRITE, dbiOPENSHARED,
|
|
Password, 0, NULL, NULL, &hDb))
|
|
== DBIERR_NONE)
|
|
{
|
|
SendDlgItemMessage(hWnd, IDC_STATIC_STATUS, WM_SETTEXT, 0,
|
|
(LPARAM) "Connection is available!");
|
|
}
|
|
else
|
|
{
|
|
// Failed to connect
|
|
hDb = 0;
|
|
DbiGetErrorInfo(TRUE, &ErrInfo);
|
|
|
|
sprintf(Msg, "Unable to connect: Cat:Code = [%xh:%xh]"
|
|
"\r\n %s"
|
|
"\r\n %s"
|
|
"\r\n %s"
|
|
"\r\n %s"
|
|
"\r\n %s",
|
|
ErrCat(ErrInfo.iError), ErrCode(ErrInfo.iError),
|
|
ErrInfo.szErrCode, ErrInfo.szContext1, ErrInfo.szContext2,
|
|
ErrInfo.szContext3, ErrInfo.szContext4);
|
|
SendDlgItemMessage(hWnd, IDC_STATIC_STATUS, WM_SETTEXT, 0,
|
|
(LPARAM) Msg);
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
// Clean up.
|
|
|
|
free(Msg);
|
|
free(Alias);
|
|
free(Driver);
|
|
free(Password);
|
|
|
|
return hDb;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: QuerySaveResultSet(hCur, hDb, szFileName);
|
|
//
|
|
// Input: hCur - Handle to source cursor
|
|
// hDb - Handle to database
|
|
// szFileName - Filename to use in saving the result set
|
|
//
|
|
// Return: TRUE if result set was saved
|
|
// FALSE otherwise
|
|
//
|
|
// Description:
|
|
// Saves the result set of the last successful query.
|
|
// IMPORTANT NOTE: since this function is called from the
|
|
// common dialog box, and is only called after the user
|
|
// has confirmed that an existing file should be
|
|
// over-written, if the file exists this function
|
|
// deletes the file before saving it.
|
|
//================================================================
|
|
BOOL
|
|
QuerySaveResultSet (hDBICur hCur, hDBIDb hDb, char* szFileName)
|
|
{
|
|
OFSTRUCT ofstruct;
|
|
BATTblDesc BatTblDesc = {
|
|
NULL,
|
|
"",
|
|
szPARADOX,
|
|
{ NULL },
|
|
{ NULL }
|
|
};
|
|
|
|
// Delete the file if it exists.
|
|
OpenFile(szFileName, &ofstruct, OF_DELETE);
|
|
|
|
BatTblDesc.hDb = hDb;
|
|
strcpy(BatTblDesc.szTblName, szFileName);
|
|
|
|
DBIErr(DbiSetToBegin(hCur));
|
|
|
|
// Save the result set to the hard disk.
|
|
if (DBIErr(DbiBatchMove(NULL, hCur, &BatTblDesc, NULL, batCOPY, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, TRUE, TRUE,
|
|
NULL, TRUE)) != DBIERR_NONE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: GetWorkingDirectory(hDb, szDirectory)
|
|
//
|
|
// Input: hDb - Handle to the database
|
|
// szDirectory - Working directory
|
|
//
|
|
// Return: Handle to the database, or zero if connection cannot
|
|
// be established.
|
|
//
|
|
// Description:
|
|
// Try to connect to a database based on the data
|
|
// selected in the connection dialog box; display
|
|
// result in the static control.
|
|
//================================================================
|
|
DBIResult
|
|
GetWorkingDirectory (hDBIDb hDb, pCHAR szDirectory)
|
|
{
|
|
return DBIErr(DbiGetDirectory(hDb, FALSE, szDirectory));
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: SetWorkingDirectory(hDb, szDirectory)
|
|
//
|
|
// Input: hDb - Handle to the Database
|
|
// szDirectory - path to the directory
|
|
//
|
|
// Return: DBIResult - Success of the opperation
|
|
//
|
|
// Description:
|
|
// This function is used to set the working directory of the
|
|
// database.
|
|
//================================================================
|
|
DBIResult
|
|
SetWorkingDirectory (hDBIDb hDb, pCHAR szDirectory)
|
|
{
|
|
return DBIErr(DbiSetDirectory(hDb, szDirectory));
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: RegisterCallBack(hCur, ecbType, iClientData, iCbBufLen,
|
|
// pCbBuf, pfCb);
|
|
//
|
|
// Input: hCur - Handle to the cursor
|
|
// ecbType - Type of the callback
|
|
// iClientData - Client Data
|
|
// iCbBufLen - Length of the buffer
|
|
// pCbBuf - CallBack buffer
|
|
// pfCb - Callback function
|
|
//
|
|
// Return: Success of registering the callback
|
|
//
|
|
// Description:
|
|
// This function is used to initialize callback functions.
|
|
//================================================================
|
|
DBIResult
|
|
RegisterCallBack (hDBICur hCur, CBType ecbType, UINT32 iClientData,
|
|
UINT16 iCbBufLen, pVOID pCbBuf, pfDBICallBack pfCb)
|
|
{
|
|
DBIResult rslt; // Return value of IDAPI functions.
|
|
|
|
rslt = DbiRegisterCallBack(hCur, ecbType, iClientData, iCbBufLen,
|
|
pCbBuf, pfCb);
|
|
return rslt;
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: GetErrorInformation(szOutputErrorString);
|
|
//
|
|
// Input: szOutputErrorString - Sting to contain the error string
|
|
//
|
|
// Return: None
|
|
//
|
|
// Description:
|
|
// This function will return information about an IDAPI error.
|
|
// Not that this needs to be called imediately after the error
|
|
// occurs.
|
|
//================================================================
|
|
void
|
|
GetErrorInformation (char *szOutputErrorString)
|
|
{
|
|
DBIErrInfo ErrInfo; // Error information.
|
|
|
|
DbiGetErrorInfo(TRUE, &ErrInfo);
|
|
|
|
sprintf(szOutputErrorString, " ERROR - Cat:Code = [%xh:%xh]"
|
|
"\r\n %s",
|
|
ErrCat(ErrInfo.iError), ErrCode(ErrInfo.iError),
|
|
ErrInfo.szErrCode);
|
|
|
|
if (strcmp(ErrInfo.szContext1, ""))
|
|
{
|
|
strcat(szOutputErrorString, "\r\n ");
|
|
strcat(szOutputErrorString, ErrInfo.szContext1);
|
|
}
|
|
if (strcmp(ErrInfo.szContext2, ""))
|
|
{
|
|
strcat(szOutputErrorString, "\r\n ");
|
|
strcat(szOutputErrorString, ErrInfo.szContext2);
|
|
}
|
|
if (strcmp(ErrInfo.szContext3, ""))
|
|
{
|
|
strcat(szOutputErrorString, "\r\n ");
|
|
strcat(szOutputErrorString, ErrInfo.szContext3);
|
|
}
|
|
if (strcmp(ErrInfo.szContext4, ""))
|
|
{
|
|
strcat(szOutputErrorString, "\r\n ");
|
|
strcat(szOutputErrorString, ErrInfo.szContext4);
|
|
}
|
|
}
|
|
|
|
//===============================================================
|
|
// Name: CleanUpAnswer(hCur)
|
|
//
|
|
// Input: hCur - Handle to the cursor
|
|
//
|
|
// Return: Success of closing the cursor
|
|
//
|
|
// Description:
|
|
// Close the cursor to the answer table and set the cursor
|
|
// to 0.
|
|
//================================================================
|
|
DBIResult
|
|
CleanUpAnswer (hDBICur *hCur)
|
|
{
|
|
DBIResult rslt; // Return value from IDAPI functions
|
|
|
|
if (*hCur)
|
|
{
|
|
rslt = DbiCloseCursor(hCur);
|
|
if (rslt == DBIERR_NONE)
|
|
{
|
|
*hCur = 0;
|
|
}
|
|
}
|
|
|
|
return rslt;
|
|
}
|
|
|