Why is this SQlite3 query execution returning "SQLITE BUSY : Database is locked" and what it the likely solution - c++

This code keeps returning "SQLITE BUSY : Database is locked" even though I was not accessing it from another external thread or process and how can I resolve this?
The code uses CppSQLite3 C++ wrapper for SQLite.
int DepartmentAccess::SaveOrDeleteAccess(long long iDeptNameID,long long &iUserID,int &iAccessTypeID)
{
char szString[1000];
char chAccessTypeID[1000];
StringCbPrintfA(szString,sizeof(szString),"%d",iAccessTypeID);
EncryptString(szString,chAccessTypeID);
try
{
char szDatabaseFile[1000];
GetDatabaseA(szDatabaseFile,sizeof(szDatabaseFile));
CppSQLite3DB db;
db.open(szDatabaseFile);
CppSQLite3Statement stmt = db.compileStatement("SELECT AccessID FROM DepartmentAccess WHERE (InsututionID = ? AND DeptNameID = ? AND UserID = ? AND AccessType = ?)");
stmt.bind(1,m_iInsututionID);
stmt.bind(2,iDeptNameID);
stmt.bind(3,iUserID);
stmt.bind(4,chAccessTypeID);
CppSQLite3Query q = stmt.execQuery();
if(!q.fieldIsNull(0))
{
if(!m_iMode)
{
return -2;
}
}
if(!m_iMode)
{
StringCbCopyA(szString,sizeof(szString),"INSERT INTO DepartmentAccess(InsututionID,DeptNameID,UserID,AccessType) VALUES(?,?,?,?)");
}
else
{
StringCbCopyA(szString,sizeof(szString),"DELETE FROM DepartmentAccess WHERE (InsututionID = ? AND DeptNameID = ? AND UserID = ? AND AccessType = ?)");
}
CppSQLite3Statement stmt1 = db.compileStatement(szString);
int iPosition = 1;
stmt1.bind(iPosition++, m_iInsututionID);
stmt1.bind(iPosition++, iDeptNameID);
stmt1.bind(iPosition++, iUserID);
stmt1.bind(iPosition++, chAccessTypeID);
//Execution gets to this point
stmt1.execDML();
//Execution fails to get to this point
if(!m_iMode)
{
StringCbPrintfA(szString,sizeof(szString),"DELETE FROM DepartmentAccessRequest WHERE (InsututionID = ? AND DeptNameID = ? AND UserID = ? AND RequestedAccess = ?)");
CppSQLite3Statement stmt2 = db.compileStatement(szString);
int iPosition = 1;
stmt2.bind(iPosition++, m_iInsututionID);
stmt2.bind(iPosition++, iDeptNameID);
stmt2.bind(iPosition++, iUserID);
stmt2.bind(iPosition++, chAccessTypeID);
stmt2.execDML();
}
return 1;
}
catch(CppSQLite3Exception & e)
{
char szString[200];
StringCbPrintfA(szString,sizeof(szString),"Error Code: %d\n Error Mesage: %s",e.errorCode(),e.errorMessage());
MessageBoxA(NULL,szString,"Save Or Delete Access Error(Department Access)",MB_OK);
}
return 0;
}

Related

MariaDB Connector C, mysql_stmt_fetch_column() and memory corruption

I'm working on a wrapper for MariaDB Connector C. There is a typical situation when a developer doesn't know a length of a data stored in a field. As I figured out, one of the ways to obtain a real length of the field is to pass a buffer of lengths to mysql_stmt_bind_result and then to fetch each column by calling mysql_stmt_fetch_column. But I can't understand how the function mysql_stmt_fetch_column works because I'm getting a memory corruption and app abortion.
Here is how I'm trying to reach my goal
// preparations here
...
if (!mysql_stmt_execute(stmt))
{
int columnNum = mysql_stmt_field_count(stmt);
if (columnNum > 0)
{
MYSQL_RES* metadata = mysql_stmt_result_metadata(stmt);
MYSQL_FIELD* fields = mysql_fetch_fields(metadata);
MYSQL_BIND* result = new MYSQL_BIND[columnNum];
std::memset(result, 0, sizeof (MYSQL_BIND) * columnNum);
std::vector<unsigned long> lengths;
lengths.resize(columnNum);
for (int i = 0; i < columnNum; ++i)
result[i].length = &lengths[i];
if (!mysql_stmt_bind_result(stmt, result))
{
while (true)
{
int status = mysql_stmt_fetch(stmt);
if (status == 1)
{
m_lastError = mysql_stmt_error(stmt);
isOK = false;
break;
}
else if (status == MYSQL_NO_DATA)
{
isOK = true;
break;
}
for (int i = 0; i < columnNum; ++i)
{
my_bool isNull = true;
if (lengths.at(i) > 0)
{
result[i].buffer_type = fields[i].type;
result[i].is_null = &isNull;
result[i].buffer = malloc(lengths.at(i));
result[i].buffer_length = lengths.at(i);
mysql_stmt_fetch_column(stmt, result, i, 0);
if (!isNull)
{
// here I'm trying to read a result and I'm getting a valid result only from the first column
}
}
}
}
}
}
If I put an array to the mysql_stmt_fetch_column then I'm fetching the only first field valid, all other fields are garbage. If I put a single MYSQL_BIND structure to this function, then I'm getting an abortion of the app on approximately 74th field (funny thing that it's always this field). If I use another array of MYSQL_BIND then the situation is the same as the first case.
Please help me to understand how to use it correctly! Thanks
Minimal reproducible example

Can't get a value from LMDB

I'm trying to store and fetch some data from LMDB. Data seems to be stored, I can see the keys in my database, but it gives me MDB_NOTFOUND when I try to fetch the value with the same ID I have just stored it under.
Database opening
MDB_env* environment;
MDB_dbi main;
MDB_dbi order;
mdb_env_create(&environment);
mdb_env_set_maxdbs(environment, 2);
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
int rc;
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
mdb_dbi_open(txn, "main", MDB_CREATE, &main);
mdb_dbi_open(txn, "order", MDB_CREATE | MDB_INTEGERKEY, &order);
mdb_txn_commit(txn);
Insertion
void Core::Archive::addElement(const Shared::Message& message) {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
message.serialize(ds);
uint64_t stamp = message.getTime().toMSecsSinceEpoch();
const std::string& id = message.getId().toStdString();
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.size();
lmdbKey.mv_data = (uint8_t*)id.c_str();
lmdbData.mv_size = ba.size();
lmdbData.mv_data = (uint8_t*)ba.data();
MDB_txn *txn;
mdb_txn_begin(environment, NULL, 0, &txn);
int rc;
rc = mdb_put(txn, main, &lmdbKey, &lmdbData, 0);
if (rc == 0) {
MDB_val orderKey;
orderKey.mv_size = 8;
orderKey.mv_data = (uint8_t*) &stamp;
rc = mdb_put(txn, order, &orderKey, &lmdbKey, 0);
if (rc) {
mdb_txn_abort(txn);
} else {
rc = mdb_txn_commit(txn);
if (rc) {
qDebug() << "A transaction error: " << mdb_strerror(rc);
}
}
} else {
qDebug() << "An element couldn't been added to the archive, skipping" << mdb_strerror(rc);
mdb_txn_abort(txn);
}
}
Fetching
Shared::Message Core::Archive::getElement(const QString& id) {
MDB_val lmdbKey, lmdbData;
lmdbKey.mv_size = id.toStdString().size();
lmdbKey.mv_data = (uint8_t*)id.toStdString().c_str();
MDB_txn *txn;
int rc;
mdb_txn_begin(environment, NULL, MDB_RDONLY, &txn);
rc = mdb_get(txn, main, &lmdbKey, &lmdbData);
if (rc) {
qDebug() <<"Get error: " << mdb_strerror(rc);
mdb_txn_abort(txn);
throw NotFound(id.toStdString(), jid.toStdString());
} else {
//it never comes here
}
}
Testing code
Core::Archive ar();
ar.open("Test");
Shared::Message msg1;
msg1.generateRandomId();
msg1.setBody("oldest");
msg1.setTime(QDateTime::currentDateTime().addDays(-7));
Shared::Message msg2;
msg2.generateRandomId();
msg2.setBody("Middle");
msg2.setTime(QDateTime::currentDateTime().addDays(-4));
Shared::Message msg3;
msg3.generateRandomId();
msg3.setBody("newest");
msg3.setTime(QDateTime::currentDateTime());
ar.addElement(msg2);
ar.addElement(msg3);
ar.addElement(msg1);
Shared::Message d0 = ar.getElement(msg1.getId());
My logs show stored keys. I can see the required key, I can even compare it with the requested key if I use cursors to scroll over the whole storage, it even shows they are equal, but mdb_cursor_get or mdb_get constantly give me MDB_NOTFOUND. What am I doing wrong?
I got it. No matter what I put into database, I have to read it as a char*
Had to modify fetching code
lmdbKey.mv_data = (uint8_t*)id.toStdString().c_str();
I had to change it to
lmdbKey.mv_data = (char*)id.toStdString().c_str();
and it worked

Object reference not set to an instance Of Object

Good day to all,
Please I need somebody to help me have a look at my codes.I am having this error of** Object reference not set to an instance Of Object**.It appears the error is within this lines of codes
if (_scrollingTimer == null)
{
_scrollingTimer = new Timer()
{
Enabled = false,
Interval = 500,
Tag = (sender as TrackBar).Value
};
but unfortunately I was unable to resolve this error.I would be very glad if somebody could help me out.thank you for the usual support.best regards.
Firstoption.
Below are the remaining part of the codes.
byte[] data = new byte[5];
private Timer _scrollingTimer = null;
private void button3_Click(object sender, EventArgs e)
{
UInt32 numBytesWritten = 0;
data[0] = 1;
myFtdiDevice.Write(data, 1, ref numBytesWritten);
data[0] = 0x6A;
myFtdiDevice.Write(data, 1, ref numBytesWritten);
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
if(!backgroundWorker1.IsBusy)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
UInt32 numBytesWritten = 1;
string dataToWrite = "#0";
if (_scrollingTimer == null)
{
_scrollingTimer = new Timer()
{
Enabled = false,
Interval = 500,
Tag = (sender as TrackBar).Value
};
_scrollingTimer.Tick += (s, ea) =>
{
if (trackBar1.Value == (int)_scrollingTimer.Tag)
{
_scrollingTimer.Stop();
myFtdiDevice.Write(dataToWrite, dataToWrite.Length, ref numBytesWritten);
int percent = (int)(((double)trackBar1.Value / (double)trackBar1.Maximum) * 100);
label2.Text = (percent.ToString()) + "%";
data[0] = Convert.ToByte(percent);
data[1] = 0x6A;
myFtdiDevice.Write(data, 2, ref numBytesWritten);
_scrollingTimer.Dispose();
_scrollingTimer = null;
}
else
{
_scrollingTimer.Tag = trackBar1.Value;
}
};
_scrollingTimer.Start();
}
}
sender is not a TrackBar. Looks like it's probably backgroundWorker1.

Import a NPAPI DLL in a C++ application

I have to import a NPAPI DLL in a C++ application for my project.
I follow the excellent tutorial : http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/
However I have some trouble to access to the methods of the dll. (Note: in a browser the dll is completly functional). After calling the main functions : NP_GetEntryPoints and NP_Initialize and retrieving the ScriptableNPObject, the invocation of the methods return no value with no error. The property or method names are the same used in javascript in the browser (functional case).
For information, the property and method names and the mime-type have been replaced in this sample.
Anyone has an idea to invoke the methods of the dll by simulating what the browser does?
Here is a part of the main program:
if (hDLL == 0)
{
std::cout << "DLL failed to load!" << std::endl;
}
else
{
std::cout << "DLL loaded!" << std::endl;
//WRAP NP_GETENTRYPOINTS FUNCTION:
_GetEntryPointsFunc = (GetEntryPointsFunc)GetProcAddress(hDLL, "NP_GetEntryPoints");
if (_GetEntryPointsFunc)
{
std::cout << "Get NP_GetEntryPoints Function!" << std::endl;
status = _GetEntryPointsFunc(pFuncs);
}
//WRAP NP_INITIALIZE FUNCTION:
_InitializeFunc = (InitializeFunc)GetProcAddress(hDLL, "NP_Initialize");
if (_InitializeFunc)
{
std::cout << "Get NP_Initialize Function!" << std::endl;
status = _InitializeFunc(&sBrowserFuncs);
}
int32_t mode = NP_EMBED;
int32_t argc = 7;
static const char mimetype[] = "application/x-mime_type_of_my_plugin";
char * argn[] = {"param1", "param2", "param3", "param4", "param5", "param6", "param7"};
char * argv[] = { "value1", "value2", "value3", "value4", "value5", "value6", "value7" };
NPObject np_object;
uint16_t size;
char* descritpionString;
char* nameString;
instance = &(plugin_instance.mNPP);
status = pFuncs->newp((char*)mimetype, instance, (uint16_t)mode, argc, argn, argv, &saved);
status = pFuncs->version; //OK
status = pFuncs->getvalue(instance,NPPVpluginDescriptionString,&descritpionString); //OK
status = pFuncs->getvalue(instance,NPPVpluginNameString,&nameString); //OK
status = pFuncs->getvalue(instance,NPPVpluginScriptableNPObject,&np_object); //ISSUE STARTS HERE
std::cin.get();
}
Here is my create_object function called after getting the scriptable NPObject with the getvalue function:
NPObject* _createobject(NPP npp, NPClass* aClass)
{
if (!npp) {
return nullptr;
}
if (!aClass) {
return nullptr;
}
NPObject *npobj;
if (aClass->allocate) {
npobj = aClass->allocate(npp, aClass);
} else {
npobj = (NPObject *)malloc(sizeof(NPObject));
}
if (npobj) {
npobj->_class = aClass;
npobj->referenceCount = 1;
//TEST:
NPError status;
NPString url;
NPVariant result;
NPVariant variant;
NPIdentifier property = "existing_property";
NPIdentifier *arrayId;
uint32_t count = 2;
const char *str = "https://test_url.com";
url.UTF8Characters = str;//;
url.UTF8Length = 20;
variant.type = NPVariantType_String;
variant.value.stringValue = url;
NPVariant args[] = { variant };
status = 1; //GENERIC ERROR VALUE
status = npobj->_class->structVersion; //OK
status = npobj->_class->hasMethod(npobj,L"existing_set_function"); //STATUS OK
status = npobj->_class->enumerate(npobj, &arrayId, &count); //Privileged instruction ERROR
status = npobj->_class->hasProperty(npobj, property); //STATUS OK
status = npobj->_class->getProperty(npobj, property, &result); //STATUS OK BUT NO RESULT
status = npobj->_class->invoke(npobj,L"existing_set_function",args,1,&result); //STATUS OK
status = npobj->_class->invoke(npobj,L"existing_get_function",args,0,&result); //STATUS OK BUT NO RESULT
status = npobj->_class->invokeDefault(npobj,args,0,&result); //STATUS OK BUT NO RESULT
//END TEST
}
return npobj;
}
Finally, here is the plugin_instance methods to declare ndata and pdata:
nsNPAPIPluginInstance::nsNPAPIPluginInstance()
{
mNPP.pdata = NULL;
mNPP.ndata = this;
}
nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
{
}
Thanks in advance.
While it is unclear what "no result" means, a privileged instruction error suggests the function pointer is off.
I'd start with:
Checking that structVersion >= NP_CLASS_STRUCT_VERSION_ENUM (otherwise NPClass::enumerate is not available)
Using the proper npapi-sdk headers - your function pointer type names suggest you are not doing that
Using a simple test plugin to see what happens on the plugin side
Take care that the NPIdentifiers match up between your host application and the plugin, i.e. use a common string->NPIdentifier mapping for the host code and NPN_GetStringIdentifier() - as posted this can't work
Don't test the NPObject right in the creation function - the plugin may set things up to work properly only after NPN_CreateObject() returned

List of windows users remotely

I would like to know how to retrieve the list of users that are logged onto a Remote machine. I can do it with qwinsta /server:xxxx, but would like to do it in C#.
check out wmi in .net under system.management.
something like:
ConnectionOptions conn = new ConnectionOptions();
conn.Authority = "ntdlmdomain:NAMEOFDOMAIN";
conn.Username = "";
conn.Password = "";
ManagementScope ms = new ManagementScope(#"\\remotecomputer\root\cimv2", conn);
ms.Connect();
ObjectQuery qry = new ObjectQuery("select * from Win32_ComputerSystem");
ManagementObjectSearcher search = new ManagementObjectSearcher(ms, qry);
ManagementObjectCollection return = search.Get();
foreach (ManagementObject rec in return)
{
Console.WriteLine("Logged in user: " + rec["UserName"].ToString());
}
You may not need the ConnectionOptions...
I ended up using the qwinsta /server:server1 command from C# -- it was much easier
thanks Ken
All this checks all 8 servers at the same time -- I put the result in sql server
but you can do what ever you want
query_citrix.bat script
cd C:.......\bin\citrix_boxes
qwinsta -server:servername or ip > servername.txt
string sAppCitrixPath = Application.StartupPath.ToString() + "\\citrix_boxes\\";
//Run Script for current citrix boxes
Process proc = new Process();
ProcessStartInfo si = new ProcessStartInfo();
si.FileName = sAppCitrixPath + "query_citrix.bat";
proc.StartInfo = si;
proc.Start();
proc.WaitForExit();
int exitCode = proc.ExitCode;
proc.Close();
if (exitCode == 0)
{
//Execute update who is on the Citrix_Boxes Currently
DirectoryInfo dic = new DirectoryInfo(sAppCitrixPath);
FileInfo[] fic = dic.GetFiles("*.txt");
for (int i = 0; i < fic.Length; i++)
{
ParseQWinStaServerFile(fic[i].FullName.ToString(), fic[i].Name.ToString().ToUpper().Replace(".TXT",""));
File.Delete(fic[i].FullName.ToString());
}
}
private void ParseQWinStaServerFile(string sLocation,string sServer)
{
using (StreamReader sr = File.OpenText(sLocation))
{
string sRecord = String.Empty;
char[] cSep = new char[] {' '};
bool bFirst = true;
while ((sRecord = sr.ReadLine()) != null)
{
if (bFirst == false)
{
string[] items = sRecord.Split(cSep, StringSplitOptions.RemoveEmptyEntries);
//Make sure all columns are present on the split for valid records
if (sRecord.Substring(19, 1) != " ") // check position of user id to see if it's their
{
//Send the user id and server name where you want to.
//here is your user
id = items[1].ToString().ToLower().Trim()
//here is your server
};
}
else
{
bFirst = false;
}
}
}
}