ソースを参照

If db is on a network drive, or anything other than C: then wait for that db to come online

scott brogden 5 年 前
コミット
76ba9bbecf
15 ファイル変更495 行追加222 行削除
  1. 27 3
      CP_Main.cpp
  2. 3 0
      CP_Main.h
  3. 11 0
      CP_Main.rc
  4. 3 0
      CP_Main.vcxproj
  5. 3 0
      CP_Main.vcxproj.filters
  6. 20 0
      DatabaseUtilities.cpp
  7. 1 0
      DatabaseUtilities.h
  8. 2 0
      Debug/Language/English.xml
  9. 6 0
      MainFrm.cpp
  10. 1 0
      MainFrm.h
  11. 161 0
      NoDbFrameWnd.cpp
  12. 30 0
      NoDbFrameWnd.h
  13. 8 2
      Resource.h
  14. BIN
      res/Ditto2_NoDb.ico
  15. 219 217
      sqlite/CppSQLite3.h

+ 27 - 3
CP_Main.cpp

@@ -15,6 +15,7 @@
 #include "SendKeys.h"
 #include "MainTableFunctions.h"
 #include "ShowTaskBarIcon.h"
+#include "NoDbFrameWnd.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -133,6 +134,8 @@ CCP_MainApp::CCP_MainApp()
 	m_RemoteCF_HDROP = ::RegisterClipboardFormat(_T("Ditto Remote CF_HDROP"));
 	m_DittoFileData = ::RegisterClipboardFormat(_T("Ditto File Data"));
 	m_PNG_Format = GetFormatID(_T("PNG"));
+
+	m_pNoDbMainFrame = NULL;
 }
 
 CCP_MainApp::~CCP_MainApp()
@@ -317,18 +320,39 @@ BOOL CCP_MainApp::InitInstance()
 	int nRet = CheckDBExists(CGetSetOptions::GetDBPath());
 	if(nRet == FALSE)
 	{
-		AfxMessageBox(theApp.m_Language.GetString("Error_Opening_Database", "Error Opening Database."));
-		return FALSE;
+		m_pNoDbMainFrame = new CNoDbFrameWnd();
+		m_pMainWnd = m_pNoDbMainFrame;
+
+		m_pNoDbMainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
+		m_pNoDbMainFrame->ShowWindow(SW_SHOW);
+		m_pNoDbMainFrame->UpdateWindow();
+	}
+	else
+	{
+		CreateMainWnd();
 	}
 
+	return TRUE;
+}
+
+void CCP_MainApp::CreateMainWnd()
+{
 	CMainFrame* pFrame = new CMainFrame;
 	m_pMainWnd = m_pMainFrame = pFrame;
 
 	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
 	pFrame->ShowWindow(SW_SHOW);
 	pFrame->UpdateWindow();
+}
 
-	return TRUE;
+void CCP_MainApp::CloseNoDbWindow()
+{
+	if (m_pNoDbMainFrame != NULL)
+	{
+		m_pNoDbMainFrame->CloseWindow();
+		delete m_pNoDbMainFrame;
+		m_pNoDbMainFrame = NULL;
+	}
 }
 
 void CCP_MainApp::AfterMainCreate()

+ 3 - 0
CP_Main.h

@@ -44,6 +44,7 @@ public:
 // MainFrame
 	HWND m_MainhWnd;
 	CMainFrame*	m_pMainFrame;
+	CFrameWnd* m_pNoDbMainFrame;
 	void AfterMainCreate();  // called after main window creation
 	void BeforeMainClose();  // called before main window close
 
@@ -182,6 +183,8 @@ public:
 	void SetCopyReason(CopyReasonEnum::CopyReason copyReason);
 	CopyReasonEnum::CopyReason GetCopyReason();
 
+	void CreateMainWnd();
+	void CloseNoDbWindow();
 
 public:
 	virtual BOOL InitInstance();

+ 11 - 0
CP_Main.rc

@@ -72,6 +72,8 @@ IDR_CP_MAITYPE          ICON                    "res\\CP_MainDoc.ico"
 
 IDI_DITTO_NOCOPYCB      ICON                    "res\\Ditto2_NoCopyCb.ico"
 
+IDI_MAINFRAME_NO_DB     ICON                    "res\\Ditto2_NoDb.ico"
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -444,6 +446,15 @@ BEGIN
     END
 END
 
+IDR_MENU_NO_DB MENU
+BEGIN
+    POPUP "First"
+    BEGIN
+        MENUITEM "Options",                     ID_FIRST_OPTIONS
+        MENUITEM "Exit",                        ID_FIRST_EXIT_NO_DB
+    END
+END
+
 
 /////////////////////////////////////////////////////////////////////////////
 //

+ 3 - 0
CP_Main.vcxproj

@@ -495,6 +495,7 @@
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
+    <ClCompile Include="NoDbFrameWnd.cpp" />
     <ClCompile Include="CopyProperties.cpp">
       <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -1878,6 +1879,7 @@
     <ClInclude Include="ChaiScriptXml.h" />
     <ClInclude Include="ClipCompare.h" />
     <ClInclude Include="ClipFormatQListCtrl.h" />
+    <ClInclude Include="NoDbFrameWnd.h" />
     <ClInclude Include="CreateQRCodeImage.h" />
     <ClInclude Include="CustomFriendsHelper.h" />
     <ClInclude Include="DeleteClipData.h" />
@@ -2254,6 +2256,7 @@
     <Image Include="res\close_48.png" />
     <Image Include="res\close_52.png" />
     <Image Include="res\close_56.png" />
+    <Image Include="res\Ditto2_NoDb.ico" />
     <Image Include="res\down_16.png" />
     <Image Include="res\down_20.png" />
     <Image Include="res\down_24.png" />

+ 3 - 0
CP_Main.vcxproj.filters

@@ -462,6 +462,7 @@
       <Filter>source</Filter>
     </ClCompile>
     <ClCompile Include="SendMail.cpp" />
+    <ClCompile Include="NoDbFrameWnd.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="sqlite\CppSQLite3.h">
@@ -965,6 +966,7 @@
     </ClInclude>
     <ClInclude Include="SendMail.h" />
     <ClInclude Include="Slugify.h" />
+    <ClInclude Include="NoDbFrameWnd.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="CP_Main.rc">
@@ -1625,5 +1627,6 @@
     <Image Include="res\search_close_24.png" />
     <Image Include="res\search_close_28.png" />
     <Image Include="res\search_close_32.png" />
+    <Image Include="res\Ditto2_NoDb.ico" />
   </ItemGroup>
 </Project>

+ 20 - 0
DatabaseUtilities.cpp

@@ -11,6 +11,7 @@
 #include "InternetUpdate.h"
 #include <zlib.h>
 #include "Shared/TextConvert.h"
+using namespace nsPath;
 
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
@@ -95,6 +96,8 @@ CString GetDefaultDBName()
 
 BOOL CheckDBExists(CString csDBPath)
 {
+	CPath path(csDBPath);
+
 	//If this is the first time running this version then convert the old database to the new db
 	if(csDBPath.IsEmpty())
 	{
@@ -105,6 +108,18 @@ BOOL CheckDBExists(CString csDBPath)
 	BOOL bRet = FALSE;
 	if(FileExists(csDBPath) == FALSE)
 	{
+		//if the database is on a shared drive, network share or anything other than C:\ than don't create a new db
+		//Ditto will wait until that drive is available
+		int len = 0;
+		auto rootType = path.GetRootType(&len);
+		auto driveLetter = path.GetDriveLetter();
+
+		if (rootType == ERootType::rtServerShare ||
+			((rootType == ERootType::rtDriveCur || rootType == rtDriveRoot) && driveLetter >= 'A' && driveLetter != 'C'))
+		{
+			return FALSE;
+		}
+
 		//first try and create create a db at the same path that was selectd
 		bRet = CreateDB(csDBPath);
 
@@ -173,6 +188,11 @@ BOOL CheckDBExists(CString csDBPath)
 	return bRet;
 }
 
+BOOL IsDatabaseOpen()
+{
+	return theApp.m_db.IsDatabaseOpen();
+}
+
 BOOL OpenDatabase(CString csDB)
 {
 	try

+ 1 - 0
DatabaseUtilities.h

@@ -19,6 +19,7 @@ BOOL CreateBackup(CString csPath);
 CString GetDBName();
 CString GetDefaultDBName();
 BOOL OpenDatabase(CString csDB);
+BOOL IsDatabaseOpen();
 
 BOOL CheckDBExists(CString csDBPath);
 BOOL ValidDB(CString csPath, BOOL bUpgrade=TRUE);

+ 2 - 0
Debug/Language/English.xml

@@ -410,6 +410,8 @@
 		<Item English_Text = "BackupDbMsg" ID = "Backing up database"></Item>
 		<Item English_Text = "RestoreDbMsg" ID = "Restoring database"></Item>
 		
+		<Item English_Text = "Ditto was unable to open its database, waiting until it can be opened. Update the path in Options if needed. Path: " ID = "StartupNoDbMsg"></Item>
+		
 		
 		
 	</Ditto_String_Table>

+ 6 - 0
MainFrm.cpp

@@ -166,6 +166,7 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
     //SetTimer(CLOSE_WINDOW_TIMER, ONE_HOUR*24, 0);
 	SetTimer(REMOVE_OLD_TEMP_FILES, ONE_HOUR * 6, 0);
     SetTimer(REMOVE_OLD_ENTRIES_TIMER, ONE_MINUTE*15, 0);
+	SetTimer(CLOSE_NO_DB_WINDOW_TIMER, 10000, 0);
 
 	//found on some computers GetTickCount gettickcount returns a smaller value than other, can't explain
 	//check here to see if we need to make an adjustment
@@ -822,6 +823,11 @@ void CMainFrame::OnTimer(UINT_PTR nIDEvent)
 		}
 		break;
 
+		case CLOSE_NO_DB_WINDOW_TIMER:
+			KillTimer(CLOSE_NO_DB_WINDOW_TIMER);
+			theApp.CloseNoDbWindow();
+			break;
+
     }
 
     CFrameWnd::OnTimer(nIDEvent);

+ 1 - 0
MainFrm.h

@@ -24,6 +24,7 @@
 #define SCREEN_RESOLUTION_CHANGED		15
 #define DELAYED_SHOW_DITTO_TIMER		16
 #define SET_WINDOWS_THEME_TIMER			17
+#define CLOSE_NO_DB_WINDOW_TIMER        18
 
 class CMainFrame: public CFrameWnd
 {

+ 161 - 0
NoDbFrameWnd.cpp

@@ -0,0 +1,161 @@
+#include "stdafx.h"
+#include "NoDbFrameWnd.h"
+#include "resource.h"
+#include "OptionsSheet.h"
+#include "DatabaseUtilities.h"
+#include "Options.h"
+#include "CP_Main.h"
+#include "Misc.h"
+
+#define WM_TRAYNOTIFY WM_USER + 100
+
+#define TIMER_OPEN_DB 1
+#define TIMER_ERROR_MSG 2
+
+BEGIN_MESSAGE_MAP(CNoDbFrameWnd, CFrameWnd)
+	ON_WM_CREATE()
+	ON_COMMAND(ID_FIRST_OPTIONS, &CNoDbFrameWnd::OnFirstOptions)
+	ON_COMMAND(ID_FIRST_EXIT_NO_DB, &CNoDbFrameWnd::OnFirstExitNoDb)
+	ON_MESSAGE(WM_TRAYNOTIFY, &CNoDbFrameWnd::OnTrayNotification)
+	ON_MESSAGE(WM_OPTIONS_CLOSED, OnOptionsClosed)
+	ON_WM_TIMER()
+	ON_WM_HOTKEY()
+END_MESSAGE_MAP()
+
+CNoDbFrameWnd::CNoDbFrameWnd()
+{
+	m_pOptions = NULL;
+	m_pDittoHotKey = NULL;
+	m_pDittoHotKey2 = NULL;
+	m_pDittoHotKey3 = NULL;
+}
+
+int CNoDbFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	////Center the main window so message boxes are in the center
+	CRect rcScreen = DefaultMonitorRect();
+	CPoint cpCenter = rcScreen.CenterPoint();
+	MoveWindow(cpCenter.x, cpCenter.x, 1, 1);
+
+	SetWindowText(_T("Ditto"));
+
+	m_trayIcon.Create(this, IDR_MENU_NO_DB, _T("Ditto"), CTrayNotifyIcon::LoadIcon(IDI_MAINFRAME_NO_DB), WM_TRAYNOTIFY, 0, 1);
+	m_trayIcon.SetDefaultMenuItem(ID_FIRST_OPTIONS, FALSE);
+	m_trayIcon.MinimiseToTray(this);
+
+	SetTimer(TIMER_OPEN_DB, 15000, NULL);
+	SetTimer(TIMER_ERROR_MSG, 180000, NULL);
+
+	g_HotKeys.Init(m_hWnd);
+
+	m_pDittoHotKey = new CHotKey(CString("DittoHotKey"), 704); //704 is ctrl-tilda
+	m_pDittoHotKey2 = new CHotKey(CString("DittoHotKey2"));
+	m_pDittoHotKey3 = new CHotKey(CString("DittoHotKey3"));
+
+	g_HotKeys.RegisterAll();
+
+	return 0;
+}
+
+void CNoDbFrameWnd::OnFirstOptions()
+{
+	if (m_pOptions != NULL)
+	{
+		::SetForegroundWindow(m_pOptions->m_hWnd);
+	}
+	else
+	{
+		m_pOptions = new COptionsSheet(_T(""));
+
+		if (m_pOptions != NULL)
+		{
+			((COptionsSheet*)m_pOptions)->SetNotifyWnd(m_hWnd);
+			m_pOptions->Create();
+			m_pOptions->ShowWindow(SW_SHOW);
+		}
+	}
+}
+
+void CNoDbFrameWnd::OnFirstExitNoDb()
+{
+	this->SendMessage(WM_CLOSE, 0, 0);
+}
+
+LRESULT CNoDbFrameWnd::OnTrayNotification(WPARAM wParam, LPARAM lParam)
+{
+	m_trayIcon.OnTrayNotification(wParam, lParam);
+	return 0L;
+}
+
+void CNoDbFrameWnd::OnTimer(UINT_PTR nIDEvent)
+{
+	switch (nIDEvent)
+	{
+	case TIMER_OPEN_DB:
+		TryOpenDatabase();
+		break;
+	case TIMER_ERROR_MSG:
+		KillTimer(TIMER_ERROR_MSG);
+		ShowNoDbMessage();
+		break;
+	}
+
+	CFrameWnd::OnTimer(nIDEvent);
+}
+
+void CNoDbFrameWnd::ShowNoDbMessage()
+{
+	CString msg = theApp.m_Language.GetString(_T("StartupNoDbMsg"), _T("Ditto was unable to open its database, waiting until it can be opened. Update the path in Options if needed. Path: "));
+	msg += StrF(_T(" %s"), CGetSetOptions::GetDBPath());
+	m_trayIcon.SetBalloonDetails(msg, _T("Ditto"), CTrayNotifyIcon::BalloonStyle::Info, CGetSetOptions::GetBalloonTimeout());
+}
+
+void CNoDbFrameWnd::TryOpenDatabase()
+{
+	if (IsDatabaseOpen() ||
+		CheckDBExists(CGetSetOptions::GetDBPath()))
+	{
+		g_HotKeys.Remove(m_pDittoHotKey);
+		delete m_pDittoHotKey;
+		m_pDittoHotKey = NULL;
+
+		g_HotKeys.Remove(m_pDittoHotKey2);
+		delete m_pDittoHotKey2;
+		m_pDittoHotKey2 = NULL;
+
+		g_HotKeys.Remove(m_pDittoHotKey3);
+		delete m_pDittoHotKey3;
+		m_pDittoHotKey3 = NULL;
+
+		KillTimer(TIMER_OPEN_DB);
+		KillTimer(TIMER_ERROR_MSG);
+		m_trayIcon.Hide();
+
+		theApp.CreateMainWnd();
+	}
+}
+
+LRESULT CNoDbFrameWnd::OnOptionsClosed(WPARAM wParam, LPARAM lParam)
+{
+	delete m_pOptions;
+	m_pOptions = NULL;
+
+	TryOpenDatabase();
+
+	return TRUE;
+}
+
+void CNoDbFrameWnd::OnHotKey(UINT nHotKeyId, UINT nKey1, UINT nKey2)
+{
+	if (m_pDittoHotKey && nHotKeyId == m_pDittoHotKey->m_Atom ||
+		m_pDittoHotKey2 && nHotKeyId == m_pDittoHotKey2->m_Atom ||
+		m_pDittoHotKey3 && nHotKeyId == m_pDittoHotKey3->m_Atom)
+	{
+		ShowNoDbMessage();
+	}
+
+	CFrameWnd::OnHotKey(nHotKeyId, nKey1, nKey2);
+}

+ 30 - 0
NoDbFrameWnd.h

@@ -0,0 +1,30 @@
+#pragma once
+#include <afxwin.h>
+#include "NTray.h"
+#include "HotKeys.h"
+
+class CNoDbFrameWnd : public CFrameWnd
+{
+public:
+	DECLARE_MESSAGE_MAP()
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+
+public:
+	CNoDbFrameWnd();
+
+	CTrayNotifyIcon m_trayIcon;
+	CPropertySheet* m_pOptions;
+	CHotKey* m_pDittoHotKey; // activate ditto's qpaste window
+	CHotKey* m_pDittoHotKey2; // activate ditto's qpaste window
+	CHotKey* m_pDittoHotKey3; // activate ditto's qpaste window
+
+	afx_msg void OnFirstOptions();
+	afx_msg void OnFirstExitNoDb();
+	afx_msg LRESULT OnTrayNotification(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnTimer(UINT_PTR nIDEvent);
+	void ShowNoDbMessage();
+	void TryOpenDatabase();
+	LRESULT OnOptionsClosed(WPARAM wParam, LPARAM lParam);
+	afx_msg void OnHotKey(UINT nHotKeyId, UINT nKey1, UINT nKey2);
+};
+

+ 8 - 2
Resource.h

@@ -237,6 +237,9 @@
 #define search_close_28                 385
 #define IDB_PNG19                       386
 #define search_close_32                 386
+#define IDR_MENU_NO_DB                  387
+#define IDI_ICON3                       388
+#define IDI_MAINFRAME_NO_DB             388
 #define IDC_PATH                        1000
 #define IDC_GET_PATH                    1001
 #define IDC_SELECT_SOUND                1002
@@ -793,14 +796,17 @@
 #define ID_MENU_BACKUPDATABASE          32962
 #define ID_MENU_SDF                     32963
 #define ID_MENU_RESTOREDATABSAE         32964
+#define ID_FIRST_OPTIONS                32965
+#define ID_FIRST_EXIT32966              32966
+#define ID_FIRST_EXIT_NO_DB             32967
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_3D_CONTROLS                     1
-#define _APS_NEXT_RESOURCE_VALUE        387
-#define _APS_NEXT_COMMAND_VALUE         32965
+#define _APS_NEXT_RESOURCE_VALUE        389
+#define _APS_NEXT_COMMAND_VALUE         32968
 #define _APS_NEXT_CONTROL_VALUE         2173
 #define _APS_NEXT_SYMED_VALUE           104
 #endif

BIN
res/Ditto2_NoDb.ico


+ 219 - 217
sqlite/CppSQLite3.h

@@ -1,217 +1,219 @@
-////////////////////////////////////////////////////////////////////////////////
-// CppSQLite3 - A C++ wrapper around the SQLite3 embedded database library.
-//
-// Copyright (c) 2004 Rob Groves. All Rights Reserved. [email protected]
-// 
-// Permission to use, copy, modify, and distribute this software and its
-// documentation for any purpose, without fee, and without a written
-// agreement, is hereby granted, provided that the above copyright notice, 
-// this paragraph and the following two paragraphs appear in all copies, 
-// modifications, and distributions.
-//
-// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
-// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
-// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
-// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
-// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION
-// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-//
-// V3.0		03/08/2004	-Initial Version for sqlite3
-//
-// V3.1		16/09/2004	-Implemented getXXXXField using sqlite3 functions
-//						-Added CppSQLiteDB3::tableExists()
-////////////////////////////////////////////////////////////////////////////////
-#ifndef _CppSQLite3_H_
-#define _CppSQLite3_H_
-
-#include "sqlite3.h"
-#include <cstdio>
-#include <cstring>
-
-#define CPPSQLITE_ERROR 1000
-
-#ifdef _UNICODE
-	#define SQLITE3_ERRMSG(mpDB) const TCHAR* szError = (const TCHAR*)sqlite3_errmsg16(mpDB)
-#else							
-	#define SQLITE3_ERRMSG(mpDB) const TCHAR* szError = sqlite3_errmsg(mpDB)
-#endif		
-
-int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out);
-int sqlite3_decode_binary(const unsigned char *in, unsigned char *out);
-
-class CppSQLite3Exception
-{
-public:
-
-    CppSQLite3Exception(const int nErrCode,
-                    TCHAR* szErrMess,
-                    bool bDeleteMsg=true);
-
-    CppSQLite3Exception(const CppSQLite3Exception&  e);
-
-    virtual ~CppSQLite3Exception();
-
-    const int errorCode() { return mnErrCode; }
-
-    const TCHAR* errorMessage() { return mpszErrMess; }
-
-    static const TCHAR* errorCodeAsString(int nErrCode);
-
-private:
-
-    int mnErrCode;
-    TCHAR mpszErrMess[1000];
-};
-
-class CppSQLite3Query
-{
-public:
-
-    CppSQLite3Query();
-
-    CppSQLite3Query(const CppSQLite3Query& rQuery);
-
-    CppSQLite3Query(sqlite3* pDB,
-				sqlite3_stmt* pVM,
-                bool bEof,
-                bool bOwnVM=true);
-
-    CppSQLite3Query& operator=(const CppSQLite3Query& rQuery);
-
-    virtual ~CppSQLite3Query();
-
-    int numFields();
-
-    int fieldIndex(const TCHAR* szField);
-    const TCHAR* fieldName(int nCol);
-
-    const TCHAR* fieldDeclType(int nCol);
-    int fieldDataType(int nCol);
-
-    const TCHAR* fieldValue(int nField);
-    const TCHAR* fieldValue(const TCHAR* szField);
-
-    int getIntField(int nField, int nNullValue=0);
-    int getIntField(const TCHAR* szField, int nNullValue=0);
-
-    double getFloatField(int nField, double fNullValue=0.0);
-    double getFloatField(const TCHAR* szField, double fNullValue=0.0);
-
-    const TCHAR* getStringField(int nField, const TCHAR* szNullValue=_T(""));
-    const TCHAR* getStringField(const TCHAR* szField, const TCHAR* szNullValue=_T(""));
-
-    const unsigned char* getBlobField(int nField, int& nLen);
-    const unsigned char* getBlobField(const TCHAR* szField, int& nLen);
-
-	int getBlobFieldSize(const TCHAR* szField);
-	int getBlobFieldSize(int nField);
-
-    bool fieldIsNull(int nField);
-    bool fieldIsNull(const TCHAR* szField);
-
-    bool eof();
-
-    void nextRow();
-
-    void finalize();
-
-private:
-
-    void checkVM();
-
-	sqlite3* mpDB;
-    sqlite3_stmt* mpVM;
-    bool mbEof;
-    int mnCols;
-    bool mbOwnVM;
-};
-
-class CppSQLite3Statement
-{
-public:
-
-    CppSQLite3Statement();
-
-    CppSQLite3Statement(const CppSQLite3Statement& rStatement);
-
-    CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM);
-
-    virtual ~CppSQLite3Statement();
-
-    CppSQLite3Statement& operator=(const CppSQLite3Statement& rStatement);
-
-    int execDML();
-
-    CppSQLite3Query execQuery();
-
-    void bind(int nParam, const TCHAR* szValue);
-    void bind(int nParam, const int nValue);
-    void bind(int nParam, const double dwValue);
-    void bind(int nParam, const unsigned char* blobValue, int nLen);
-    void bindNull(int nParam);
-
-    void reset();
-
-    void finalize();
-
-private:
-
-    void checkDB();
-    void checkVM();
-
-    sqlite3* mpDB;
-    sqlite3_stmt* mpVM;
-};
-
-
-class CppSQLite3DB
-{
-public:
-
-    CppSQLite3DB();
-
-    virtual ~CppSQLite3DB();
-
-    void open(const TCHAR* szFile);
-
-    bool close();
-
-	bool tableExists(const TCHAR* szTable);
-
-	int execDMLEx(LPCTSTR szSQL,...);
-    int execDML(const TCHAR* szSQL);
-
-	CppSQLite3Query execQueryEx(LPCTSTR szSQL,...);
-    CppSQLite3Query execQuery(const TCHAR* szSQL);
-
-	int execScalarEx(LPCTSTR szSQL,...);
-    int execScalar(const TCHAR* szSQL);
-
-    CppSQLite3Statement compileStatement(const TCHAR* szSQL);
-
-    sqlite_int64 lastRowId();
-
-    void interrupt() { sqlite3_interrupt(mpDB); }
-
-    void setBusyTimeout(int nMillisecs);
-
-    static const TCHAR* SQLiteVersion() { return _T(SQLITE_VERSION); }
-
-private:
-
-    CppSQLite3DB(const CppSQLite3DB& db);
-    CppSQLite3DB& operator=(const CppSQLite3DB& db);
-
-    sqlite3_stmt* compile(const TCHAR* szSQL);
-
-    void checkDB();
-
-    sqlite3* mpDB;
-    int mnBusyTimeoutMs;
-};
-
-#endif
+////////////////////////////////////////////////////////////////////////////////
+// CppSQLite3 - A C++ wrapper around the SQLite3 embedded database library.
+//
+// Copyright (c) 2004 Rob Groves. All Rights Reserved. [email protected]
+// 
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without a written
+// agreement, is hereby granted, provided that the above copyright notice, 
+// this paragraph and the following two paragraphs appear in all copies, 
+// modifications, and distributions.
+//
+// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
+// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
+// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
+// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION
+// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+//
+// V3.0		03/08/2004	-Initial Version for sqlite3
+//
+// V3.1		16/09/2004	-Implemented getXXXXField using sqlite3 functions
+//						-Added CppSQLiteDB3::tableExists()
+////////////////////////////////////////////////////////////////////////////////
+#ifndef _CppSQLite3_H_
+#define _CppSQLite3_H_
+
+#include "sqlite3.h"
+#include <cstdio>
+#include <cstring>
+
+#define CPPSQLITE_ERROR 1000
+
+#ifdef _UNICODE
+	#define SQLITE3_ERRMSG(mpDB) const TCHAR* szError = (const TCHAR*)sqlite3_errmsg16(mpDB)
+#else							
+	#define SQLITE3_ERRMSG(mpDB) const TCHAR* szError = sqlite3_errmsg(mpDB)
+#endif		
+
+int sqlite3_encode_binary(const unsigned char *in, int n, unsigned char *out);
+int sqlite3_decode_binary(const unsigned char *in, unsigned char *out);
+
+class CppSQLite3Exception
+{
+public:
+
+    CppSQLite3Exception(const int nErrCode,
+                    TCHAR* szErrMess,
+                    bool bDeleteMsg=true);
+
+    CppSQLite3Exception(const CppSQLite3Exception&  e);
+
+    virtual ~CppSQLite3Exception();
+
+    const int errorCode() { return mnErrCode; }
+
+    const TCHAR* errorMessage() { return mpszErrMess; }
+
+    static const TCHAR* errorCodeAsString(int nErrCode);
+
+private:
+
+    int mnErrCode;
+    TCHAR mpszErrMess[1000];
+};
+
+class CppSQLite3Query
+{
+public:
+
+    CppSQLite3Query();
+
+    CppSQLite3Query(const CppSQLite3Query& rQuery);
+
+    CppSQLite3Query(sqlite3* pDB,
+				sqlite3_stmt* pVM,
+                bool bEof,
+                bool bOwnVM=true);
+
+    CppSQLite3Query& operator=(const CppSQLite3Query& rQuery);
+
+    virtual ~CppSQLite3Query();
+
+    int numFields();
+
+    int fieldIndex(const TCHAR* szField);
+    const TCHAR* fieldName(int nCol);
+
+    const TCHAR* fieldDeclType(int nCol);
+    int fieldDataType(int nCol);
+
+    const TCHAR* fieldValue(int nField);
+    const TCHAR* fieldValue(const TCHAR* szField);
+
+    int getIntField(int nField, int nNullValue=0);
+    int getIntField(const TCHAR* szField, int nNullValue=0);
+
+    double getFloatField(int nField, double fNullValue=0.0);
+    double getFloatField(const TCHAR* szField, double fNullValue=0.0);
+
+    const TCHAR* getStringField(int nField, const TCHAR* szNullValue=_T(""));
+    const TCHAR* getStringField(const TCHAR* szField, const TCHAR* szNullValue=_T(""));
+
+    const unsigned char* getBlobField(int nField, int& nLen);
+    const unsigned char* getBlobField(const TCHAR* szField, int& nLen);
+
+	int getBlobFieldSize(const TCHAR* szField);
+	int getBlobFieldSize(int nField);
+
+    bool fieldIsNull(int nField);
+    bool fieldIsNull(const TCHAR* szField);
+
+    bool eof();
+
+    void nextRow();
+
+    void finalize();
+
+private:
+
+    void checkVM();
+
+	sqlite3* mpDB;
+    sqlite3_stmt* mpVM;
+    bool mbEof;
+    int mnCols;
+    bool mbOwnVM;
+};
+
+class CppSQLite3Statement
+{
+public:
+
+    CppSQLite3Statement();
+
+    CppSQLite3Statement(const CppSQLite3Statement& rStatement);
+
+    CppSQLite3Statement(sqlite3* pDB, sqlite3_stmt* pVM);
+
+    virtual ~CppSQLite3Statement();
+
+    CppSQLite3Statement& operator=(const CppSQLite3Statement& rStatement);
+
+    int execDML();
+
+    CppSQLite3Query execQuery();
+
+    void bind(int nParam, const TCHAR* szValue);
+    void bind(int nParam, const int nValue);
+    void bind(int nParam, const double dwValue);
+    void bind(int nParam, const unsigned char* blobValue, int nLen);
+    void bindNull(int nParam);
+
+    void reset();
+
+    void finalize();
+
+private:
+
+    void checkDB();
+    void checkVM();
+
+    sqlite3* mpDB;
+    sqlite3_stmt* mpVM;
+};
+
+
+class CppSQLite3DB
+{
+public:
+
+    CppSQLite3DB();
+
+    virtual ~CppSQLite3DB();
+
+    void open(const TCHAR* szFile);
+
+    bool close();
+
+	bool tableExists(const TCHAR* szTable);
+
+	int execDMLEx(LPCTSTR szSQL,...);
+    int execDML(const TCHAR* szSQL);
+
+	CppSQLite3Query execQueryEx(LPCTSTR szSQL,...);
+    CppSQLite3Query execQuery(const TCHAR* szSQL);
+
+	int execScalarEx(LPCTSTR szSQL,...);
+    int execScalar(const TCHAR* szSQL);
+
+    CppSQLite3Statement compileStatement(const TCHAR* szSQL);
+
+    sqlite_int64 lastRowId();
+
+    void interrupt() { sqlite3_interrupt(mpDB); }
+
+    void setBusyTimeout(int nMillisecs);
+
+    static const TCHAR* SQLiteVersion() { return _T(SQLITE_VERSION); }
+
+    bool IsDatabaseOpen() { return mpDB != NULL; }
+
+private:
+
+    CppSQLite3DB(const CppSQLite3DB& db);
+    CppSQLite3DB& operator=(const CppSQLite3DB& db);
+
+    sqlite3_stmt* compile(const TCHAR* szSQL);
+
+    void checkDB();
+
+    sqlite3* mpDB;
+    int mnBusyTimeoutMs;
+};
+
+#endif