OpenFileDialog->DialogShow() results cause errors in SQLite - c++

I have a program that accesses a database using SQLite. When I open a OpenFileDialog or a SaveFileDialog before I do the SQLite call:
result = sqlite3_prepare_v2(databaseConnection,converted,10000,&stmt,&strptr);
and choose "Cancel", everything works okay (result == SQLITE_OK) but when I choose "Open", even if I don't do anything with the dialog's return file, it breaks (result == SQLITE_ERROR). Do you have any idea why this might be happening?
Thanks so much for your time!
EDIT: Here is the code I am using:
OpenFileDialog^ openFileDialog1 = gcnew OpenFileDialog;
openFileDialog1->ShowDialog();
sqlite3_stmt * stmt;
const char * strptr;
sqlite3 * databaseConnection;
int result = sqlite3_open("virtualpatient_chat.db", &databaseConnection);
if (result != SQLITE_OK) return;
result = sqlite3_prepare_v2(databaseConnection,"SELECT * from mappings;",10000,&stmt,&strptr);
if (result != SQLITE_OK) return;
Strangely, it won't work in my current project but I copied and pasted it into a brand new project and the error doesn't repeat. Now I'm just trying to figure out what the problem in my surrounding code could be...

There's no hope to diagnose the source of the problem from the question. Just some pointers.
Start by setting the OpenFileDialog's RestoreDirectory to True. This ensures that clicking Open doesn't change the program's working directory. If that works then there's a rather mysterious dependency on the current directory in the query.
Next thing to worry about are the DLLs that are getting loaded when you use the dialog. Project + Properties, Debug tab, tick "Enable unmanaged code debugging". Check out the Output window when you open the dialog, it shows a list of the DLLs getting injected. These are shell extensions, one of them might conflict with SQLite. No real clue what such an extension might do beyond maybe corrupting memory or using SQLite itself. You can temporarily disable shell extension with the SysInternals' AutoRuns utility. Start with the ones not written by Microsoft.

I finally figured out how to fix it. Under the Properties for my dialog box, I had to set the RestoreDirectory property to true. I'm not quite sure how that fixed it unless somehow by changing the directory it made SQLite not be able to find my database file.
Thanks for your help!

Related

Reading a saved EVTX file in the given path

I am currently working on a project where I need to read windows events .
I am using OpenEventLog() and ReadEventLog() from Win API. I can read the events from system using the typename of the event.
But I need to specify the file name or file path of the .evtx file that I have saved from the EventViewer.I tried the below code,
HANDLE logHandle = OpenEventLog(NULL, "C:\\Users\\MyAccount\\Documents\\myevents.evtx");
DWORD status = GetLastError();
if(logHandle == NULL){
cerr<<"NO HANDLE GENERATED!!!"<<endl;
}else if(status == ERROR_INVALID_HANDLE){
cerr<<"INVALID HANDLE!!!"<<endl;
}else if(status!=0){
cout<<"OPENEVENTLOG ERROR STATUS::>"<<status<<endl;
}
But it does not find the specified file and switches over to default Application Events. Can anyone please tell me what the problem could be? or if there is anything to be changed in the code?
PS: I even tried placing the file in project folder and specifying just the filename(myevents.evtx) , but still doesn't work.I also tried reading the evtx directly as shown in "Reading .evt/.evtx files directly" , but later I found this can't be done. Apparently there is no way to read them directly without win API or without writing a whole bunch of parser code.
Thanks in advance.
Well, it turns out OpenEventLog() is not meant for opening saved .evtx files.
I should've been using OpenBackupEventLog() for that.

C++ MFC VC 6.0 to VS2013 lStreamReturn = GetRichEditCtrl().StreamIn(SF_RTF, es);

Found an issue when converting the Tool from the VC++ 6.0 to VS2013. The error is not an actual error in the code as the code compiles with no "errors" and it works just fine. The program has been adjusted minimally, almost no real change to the code, to allow the program to run and function correctly in VS2013, or so I thought. When we tested the code to read from a external memory device, it displayed the RichText tree in the left pane of the application which seemed to work or function with what seemed to be all the data present, but the Rich Text we are so used to visually seeing was not present in the Right pane of the main application. What peaked my interest was the fact that in the original program you couldn't edit the text, but in our newest compiled program, you could see that the area had not changed from its original state. Almost as if that the data was getting to the application, but for some odd reason was getting dismissed or deleted right before displaying to the pane.
So here's the problem, when the WCARichEdit.cpp does this
"
EDITSTREAM es;
es.dwError=0;
es.dwCookie = (DWORD) &Report;
es.pfnCallback = CBStreamIn;
lStreamReturn = GetRichEditCtrl().StreamIn(SF_RTF, es);
GetRichEditCtrl().SetReadOnly(TRUE);
"
It breaks or throws the error 0 unless SF_RTF is changed to SF_TEXT. The code then generates all the data, but the formatting is read into the stream of text. One giant stream that is. We are under some assumption that the formatting in this code is the culprit as to why the text is not showing up when we compile our code. So when the SplitterFrame.CPP does this
"
Void CSplitterFrame::DisplayReport(CString Report)
{
CWcaRichEdit*RichEditView = (CWcaRichEdit*) m_wndSplitter.GetPane(0,1);
CH1_MainteanceToolDoc*pDoc = (CH1_MainteanceToolDoc*)
((CMainFrame *)AfxGetMainWnd())->GetActiveDocument();
RichEditView->DisplayReport(pDoc, Report);
}
"
The RichEditView->DisplayReport(pDoc, Report) doesn't seem to be getting any code as it just gets zeroed out. This is confirmed by the dwError=0 displaying no change when SF_RTF is left unchanged.
Any Thoughts as to how to get this Rich Text to display?
During troubleshooting this code below was written to push the string to a text file.
#if
DWORD dwError;
CFile testfile;
if (0 == testfile.Open ("C:\\...rtftestfile.txt", CFile::modeCreate | CFile:modeWrite | CFile::shareDenyNone))
{
dwError = GetLastError();
{
testfile.Write((LPCTSTR) Report, Report.GetLength());
testfile.Close();
#endif
The file was created successfully, and out of a whim, the decision was made to save the file after opening the .text file in WordPad. We then saved the file as a new .rtf file extension. Oddly enough the program didn't view all of our formatting but rather added some code in the mix as the size of the wordpad file and the text file varied by size. We then took each file and "Drag and Drop" 'ed them into the notepad program for further review. Strangely enough a "\rtf1" was added to the beginning of our gigantic string. Odd, why would WordPad add that...wait. The realization came and we went back and changed our code from
const char RTF_Header[] = "{\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fontbl{\\f0\\fnil\\fcharset0 Courier New;}}\\viewkind4\\uc1\\pard\\fs17 ";
to
const char RTF_Header[] = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fontbl{\\f0\\fnil\\fcharset0 Courier New;}}\\viewkind4\\uc1\\pard\\fs17 ";
The learning point is this, if you know your formatting is breaking your code, print that giant string to a file to see what it's doing and push it into something that will place the rtf formatting where it is missing.
The other option is to have someone on hand that loves to utilize the awesome power of Rich Text and can remember all the ways to format it.
Also here is the Microsoft Forum discussion if you want to brave it:
Microsoft Forum GetRichEditCtrl().StreamIn breaks on formating

MFC C++ Reference INI file in application folder after deployment

Hoping for some help here, as I am tearing my hair out!I'm using Visual Studio 2010.
I have an MFC C++ application to deploy. I have a config.ini file that I'd like referenced when the exe starts. At the moment the user cannot double click on a *.myfile and it open, because the application does not "start in" the application folder (where I am installing the ini file to), and so cannot find the ini. I've tried the following
I tried finding info on setting the "start in" folder for the &Open action, but cannot find anything.
I can't find any info on setting a registry value of the ini file at installation, since this would be a relative reference depending on the user's choice, and so this doesn't apply.
It is unmanaged so the C++/CLI app.config solution doesn't apply.
Using the Application Data folder, but this gives me the wrong path - I'm using Windows 7, this is probably why, but I want my deployment to work on Windows XP ++.
Reading the app path at start up (from here) (put this in CMyApp::InitInstance().
Code:
CString strPath;
TCHAR* pstrExePath = strPath.GetBuffer (MAX_PATH);
::GetModuleFileName (0, pstrExePath, MAX_PATH);
strPath.ReleaseBuffer();
int pos = strPath.ReverseFind('\\');
strPath = strPath.Left(pos);
strPath += "\\config.ini";
This is the closest, but in debug mode there is a weird "\.\" in the path invalidating it. I could use a #ifdebug but this is messy surely?
Really appreciate any help - thanks!
EDIT:
Using this:
TCHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)))
{
MessageBox(NULL,szPath, "MyApp", MB_OK|MB_ICONWARNING);
}
I get: "C:\ProgramData" as the szPath. Maybe this is right for debug mode? Or the development machine?
Thanks for all the input and prompts. It helped me get to this solution. Hopefully it helps some others to have the info in one place. This solution is a very simple one and probably not for full commercial deployment!
In VS2010 in the FileSystem (Setup)
put the config file in the User's
Application Data Folder \ Productname
Set InstallAllUsers to false, so that
you don't need conditionals on where
your config file is located, based on
the user's installation choice
In the InitInstance() function add
something like the following:
[listbreaker]
TCHAR szPath[MAX_PATH] = {0};
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,NULL,SHGFP_TYPE_CURRENT,szPath)))
{
PathAppend(szPath, "\\MyApp\\");
// Can check to create the directory here
//if (!PathFileExists(szPath))
// CreateDirectory(szPath, NULL);
PathAppend(szPath, TEXT("MyApp.ini"));
// can check to create default file here if removed by user
//if (!PathFileExists(szPath))
//g_ConfigData.write_default() // be nice if it could write itself
//MessageBox(NULL,szPath, "MyApp", MB_OK|MB_ICONWARNING);
}
if (!g_ConfigData.ReadData( szPath ) )
MessageBox(NULL,"Configuration file cannot be read", "MyApp", MB_OK|MB_ICONWARNING);
Some useful links that really helped me on this are:
How to get the %AppData% folder in C?
http://msdn.microsoft.com/en-us/library/206sadcd.aspx
http://www.vbforums.com/showthread.php?t=491920
http://jedej.com/2011/02/22/constant-special-item-id-list-windows-special-folders/
http://www.codeproject.com/Messages/2623871/using-CSIDL_APPDATA-or-CSIDL_COMMON_APPDATA.aspx
I'd appreciate any further help on this, as I'm sure there are more refined and flexible solutions (e.g. handling "All Users" choice on installation).

Why does my code fail to create a directory in "C:\Program Files" under Windows 7?

I am using Windows 7 and I have to run one program in that windows but that program working in Windows XP. This is a Visual C++ program and I am using Visual Studio 2008 for this. When I am running my application, it does not throw any errors, but it does not create a directory in "c:\program files\". So can anyone help me to create directory and exe file?
This is the code I am using:
char szAppPath[MAX_PATH];
char szFileName[MAX_PATH];
DWORD dwResult;
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
dwResult = ExpandEnvironmentStrings( NULL, szAppPath, MAX_PATH); // "%ProgramFiles%"
// do same for NSim directory
strcat(szAppPath,"\\NSim");
hFind = FindFirstFile(szAppPath, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
//Directory Does't Exists create New
if(!CreateDirectory(szAppPath,NULL)) //Throw Error
{
MessageBox("Unable to Create N-SIM directory","NSim Installer");
return ;
}
}
else
{
//check if is directory or not
if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
MessageBox("Can't Create N-SIM directory\n Another file with same name exists","NSim Installer");
return ;
}
FindClose(hFind);
}
//***************************************N-SIM Application****************************
strcpy(szFileName, szAppPath);
HRSRC hRes;
if( bRegister == FALSE)
{
strcat(szFileName,"\\NSim.exe"); //make same name of the Client & Server in program file
hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_LANSIMSERVER),RT_RCDATA);
if(flagUpgrade ==0)
{
CString trial = installationDate(); //----- Detemine Expiry Date -----
setRegistry(trial);
}
}
It's a file permissions issue, plain and simple. Programs can't just go rooting around system directories in Windows 7. That's why it works "properly" in Windows XP, but not in newer versions.
I can't tell for sure, but it looks like you're trying to write an installer. If so, why are you reinventing the wheel? There are tons of great setup utilities availableā€”Visual Studio provides a setup project that you can customize to your needs, or look into Inno Setup, my personal favorite. A Google search will turn up plenty of other options that have already solved this problem for you, and innumerable others.
If this isn't an installer, and you're just trying to store application and/or user data in the Program Files folder, I highly recommend that you look elsewhere. You weren't supposed to shove data into the app folder under earlier versions of Windows, and Windows 7 just cuts you off at the knees if you do this. Your best bet is to follow the recommendations that existed from the beginning: Investigate the user and common Application Data folders carefully. Use the SHGetKnownFolderPath function to retrieve the full path to a known folder using its KNOWNFOLDERID. A couple of suggestions:
FOLDERID_ProgramData (a shared program data directory for all users)
FOLDERID_LocalAppData (a per-user program data directory, non-roaming)
FOLDERID_RoamingAppData (a per-user program data directory, roaming)
Alternatively, you can try running the application as an Administrator. You might want to look into creating a manifest that indicates the application requires administrator-level permissions to execute.
[edit] I edited the code in the question for readability and removed the commented out code (to see the wood for the trees). It is now obvious that nothing initialises szAppPath before calling strcat(), and calling ExpandEnvironmentStrings with NULL as the first argument is undefined (and certainly useless). Calling strcat() on an unitialised string is not likely to have the desired result. This may be an artefact of not posting the real code, or even of other peoples edits (including mine).
CreateDirectory sets the system error code on error; if you want to know what went wrong, check it! Any answer you get here will be an educated guess.
if(!CreateDirectory(szAppPath,NULL)) //Throw Error
{
DWORD errorcode = GetLastError();
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL );
MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK);
return ;
}
If you just want to get the error code and look it up manually, then a complete directory of codes is available on MSDN, here, I would guess that ERROR_ACCESS_DENIED
(5) is most probable. A more elaborate example of error code display is given here.
windows7?
Ok, the problem is not with your program. Its with the file system permissions in Windows 7. User programs cannot create files there.
I think the problem is lack of privileges. You can debug your project to see whether the CreateDirectory function sets an error as ERROR_ACCESS_DENIED, if it does, you should make your program run with an administrator privilege. Add manifest in your project to do so.
It is intended to protect your computer against attack. Well maybe. Or Microsoft deciding to tell you what you are and not allowed to do on your own computer.
In any case you can change your UAC settings if you really have to write there in that way although that obviously exposes you to risk.
Otherwise play nice and do things the Microsoft way, using a proper installer.

How to find if an document can be OPENed via ShellExecute?

I want to check if a particular file can be successfully "OPEN"ed via ShellExecute, so I'm attempting to use AssocQueryString to discover this.
Example:
DWORD size = 1024;
TCHAR buff[1024]; // fixed size as dirty hack for testing
int err = AssocQueryString(0, ASSOCSTR_EXECUTABLE, ".mxf", NULL ,buff , &size);
openAction->Enabled = ((err == S_OK) || (err == S_FALSE)) && (size > 0);
Now, this almost works. If there's a registered application, I get the string.
But, there's a catch: On Vista, even if there is no registered application, It returns that the app c:\Windows\System32\shell32.dll is associated, which is the thing that brings up the 100% useless "Windows cannot open this file: Use the Web service to find the correct program?" dialog.
Obviously I want to hide that peice of cr*p from end users, but simply comparing the returned string to a constant seems like an ugly, brute-force and fragile way of doing it.
Also, hacking the registry to totally disable this dialog isn't a great idea.
What's a better option?
I always use FindExecutable() to get the registered application for a given document.
There is another way to do this, using the ASSOCF_INIT_IGNOREUNKNOWN option flag with AssocQueryString().
int err = AssocQueryString(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, ".mxf", NULL ,buff , &size);
This has a couple of important advantages over using FindExecutable()
It can work with just the file extension, while FindExecutable needs a full path to an existing file of the specified type.
Because it's not accessing the file, it's much faster with Samba and other network storage. Calling FindExecutable() on one file in a directory containing ~3000 files via Samba took > 1 second in my tests.