2008/10/30
Microsoft CryptoAPI 를 이용한 데이터 암호화
SQLite 에는 기본적으로 지원하는 암호화 기능이 없다. 별도의 비용을 지불 해야만 암호화 기능을 사용할 수 있다.
그래서 이전에 포스팅한 자료(2008/10/30 - [Dev Story/Tips] - Microsoft CryptoAPI 를 이용한 데이터 암호화
)를 바탕으로 데이터를 암호화 하는 사용자 함수를 만들어 보았다.
Original Post : http://neodreamer-dev.tistory.com/196
그래서 이전에 포스팅한 자료(2008/10/30 - [Dev Story/Tips] - Microsoft CryptoAPI 를 이용한 데이터 암호화
)를 바탕으로 데이터를 암호화 하는 사용자 함수를 만들어 보았다.
//------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "uMain.h"
//------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//------------------------------------------------------------------------
#define ENCRYPT_ALGORITHM CALG_RC4
#define KEYLENGTH 0x00800000
static void EncryptFunc(sqlite3_context *context,
int argc, sqlite3_value **argv)
{
if (argc == 0)
sqlite3_result_error(context, "Error: No Data)", -1);
else if (argc == 1)
sqlite3_result_error(context, "Error: No Password", -1);
else if (argc != 2)
sqlite3_result_error(context, "Error: Invalid param count", -1);
else
{
const unsigned char *pwd;
pwd = (const unsigned char *)sqlite3_value_text(argv[1]);
const unsigned char *src;
src = (const unsigned char *)sqlite3_value_blob(argv[0]);
if ( strlen( pwd ) > 0 )
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHash = NULL;
// Get the Handle to the default provider
if ( !CryptAcquireContext( &hCryptProv,
NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0 ) )
{
if ( GetLastError() == NTE_BAD_KEYSET )
{
if (!CryptAcquireContext(&hCryptProv,
NULL, MS_DEF_PROV,
PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
// CryptAcquireContext() failed.
sqlite3_result_error(
context,
"Error: CryptAcquireContext()",
-1);
return;
}
}
else
{
// CryptAcquireContext() failed.
sqlite3_result_error(
context,
"Error: CryptAcquireContext()",
-1);
return;
}
}
// Create Hash object
if ( !CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash ) )
{
// Error during CryptCreateHash()
sqlite3_result_error(
context,
"Error: CryptCreateHash()",
-1);
return;
}
// Hash the password
if ( !CryptHashData( hHash, pwd, strlen(pwd), 0 ) )
{
// Error during CryptHashData
sqlite3_result_error(
context,
"Error: CryptHashData()",
-1);
return;
}
// Derive a session key from the hash object
if ( !CryptDeriveKey( hCryptProv, ENCRYPT_ALGORITHM,
hHash, KEYLENGTH, &hKey ) )
{
// Error during CryptDeriveKey
sqlite3_result_error(
context,
"Error: CryptDeriveKey()",
-1);
return;
}
// Encrypt
unsigned long length = strlen(src);
unsigned char *dst = (unsigned char *)malloc(length + 1);
memcpy(dst, src, length + 1 );
if ( !CryptEncrypt( hKey, NULL, TRUE, 0, dst, &length, length ) )
{
// Error during CryptEncrypt
sqlite3_result_error(
context,
"Error: CryptEncrypt()",
-1);
free( dst );
return;
}
sqlite3_result_blob(
context,
dst,
strlen( dst ),
SQLITE_TRANSIENT );
free( dst );
}
}
}
//------------------------------------------------------------------------
static void DecryptFunc(sqlite3_context *context,
int argc, sqlite3_value **argv)
{
if (argc == 0)
sqlite3_result_error(context, "Error: No Data)", -1);
else if (argc == 1)
sqlite3_result_error(context, "Error: No Password", -1);
else if (argc != 2)
sqlite3_result_error(context, "Error: Invalid param count", -1);
else
{
const unsigned char *src;
src = (const unsigned char *)sqlite3_value_blob(argv[0]);
const unsigned char *pwd;
pwd = (const unsigned char *)sqlite3_value_text(argv[1]);
if ( strlen( pwd ) > 0 )
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHash = NULL;
// Get the Handle to the default provider
if ( !CryptAcquireContext( &hCryptProv, NULL,
MS_ENHANCED_PROV, PROV_RSA_FULL, 0 ) )
{
if ( GetLastError() == NTE_BAD_KEYSET )
{
if (!CryptAcquireContext(&hCryptProv, NULL,
MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
// CryptAcquireContext() failed.
sqlite3_result_error(
context,
"Error: CryptAcquireContext()",
-1);
return;
}
}
else
{
// CryptAcquireContext() failed.
sqlite3_result_error(
context,
"Error: CryptAcquireContext())",
-1);
return;
}
}
// Create Hash object
if ( !CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash ) )
{
// Error during CryptCreateHash()
sqlite3_result_error(
context,
"Error: CryptCreateHash()",
-1);
return;
}
// Hash the password
if ( !CryptHashData( hHash, pwd, strlen( pwd ), 0 ) )
{
// Error during CryptHashData
sqlite3_result_error(
context,
"Error: CryptHashData()",
-1);
return;
}
// Derive a session key from the hash object
if ( !CryptDeriveKey( hCryptProv, ENCRYPT_ALGORITHM,
hHash, KEYLENGTH, &hKey ) )
{
// Error during CryptDeriveKey
sqlite3_result_error(
context,
"Error: CryptDeriveKey()",
-1);
return;
}
// Decrypt
unsigned long length = strlen(src);
unsigned char *dst = (unsigned char *)malloc(length + 1);
memcpy(dst, src, length + 1 );
if ( !CryptDecrypt( hKey, NULL, TRUE, 0, dst, &length ) )
{
// Error during CryptEncrypt
sqlite3_result_error(
context,
"Error: CryptDecrypt()",
-1);
return;
}
sqlite3_result_blob(
context,
dst,
strlen( dst ),
SQLITE_TRANSIENT );
free( dst );
}
}
}
//------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
m_pDB = NULL;
}
//------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
if ( m_pDB )
sqlite3_close( m_pDB );
}
//------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
int nRst = sqlite3_open( "test.db", &m_pDB );
if ( nRst != SQLITE_OK )
{
ShowMessage("Cannot open database.");
return;
}
int nResult;
nResult = sqlite3_create_function(m_pDB, "Encrypt", -1,
SQLITE_UTF8, NULL, &EncryptFunc, NULL, NULL);
nResult = sqlite3_create_function(m_pDB, "Decrypt", -1,
SQLITE_UTF8, NULL, &DecryptFunc, NULL, NULL);
sqlite3_stmt* pStmt = NULL;
const char* szChar;
String strTemp;
String strQuery;
strQuery = "SELECT Encrypt('test', '123')";
if ( sqlite3_prepare( m_pDB, strQuery.c_str(),
strQuery.Length(), &pStmt, &szChar ) == SQLITE_OK )
{
int nRow = sqlite3_data_count( pStmt );
int nCol = sqlite3_column_count( pStmt );
const char* col1name = sqlite3_column_name( pStmt, 0 );
int nRowCnt = 0;
if ( sqlite3_step( pStmt ) == SQLITE_ROW )
{
++nRowCnt;
const unsigned char* col1 = sqlite3_column_text( pStmt, 0 );
String strMsg;
strMsg.sprintf(
"ROW %d: %s => %s",
nRowCnt, col1name, col1
);
strTemp.sprintf( "%s", col1 );
ShowMessage( strMsg );
}
}
sqlite3_finalize( pStmt );
strQuery = "SELECT Decrypt('" + strTemp + "', '123')";
if ( sqlite3_prepare( m_pDB, strQuery.c_str(),
strQuery.Length(), &pStmt, &szChar ) == SQLITE_OK )
{
int nRow = sqlite3_data_count( pStmt );
int nCol = sqlite3_column_count( pStmt );
const char* col1name = sqlite3_column_name( pStmt, 0 );
int nRowCnt = 0;
if ( sqlite3_step( pStmt ) == SQLITE_ROW )
{
++nRowCnt;
const unsigned char* col1 = sqlite3_column_text( pStmt, 0 );
String strMsg;
strMsg.sprintf(
"ROW %d: %s => %s",
nRowCnt, col1name, col1
);
ShowMessage( strMsg );
}
}
sqlite3_finalize( pStmt );
}
//------------------------------------------------------------------------
Original Post : http://neodreamer-dev.tistory.com/196
Labels:
C++
,
CryptoAPI
,
Cryptography
,
TistoryOldPost
,
암호화
2008/10/27
TortoiseSVN-1.5.5.14361 Released!!
갑자기 업데이트 주기가 빨라진 것 같다.
얼마전 1.5.4버전으로 업데이트 되었는데 곧바로 1.5.5버전이 나왔다.
이번 버전에서 바뀐점
Version 1.5.5
- BUG: The properties dialog would show the url with backward slashes when
started from the repository browser. (Stefan)
TortoiseSVN Homepage
TortoiseSVN-1.5.5.14361-win32-svn-1.5.4.msi
TortoiseSVN-1.5.5.14361-x64-svn-1.5.4.msi
Original Post : http://neodreamer-dev.tistory.com/190
2008/10/18
TortoiseSVN-1.5.4.14259 Released!!
1.5.4 버전에서 바뀐점.
- CHG: OpenSSL 0.9.8i with capieng enabled
- BUG: Applying a patch where a context line had UTF-BOMs
in it failed. (Stefan)
- BUG: Checking out multiple folders from the repository browser failed
to unescape the target folder. (Stefan)
- BUG: If an url had special chars which needed escaping below the
repository root, showing the log did not always work. (Stefan)
- BUG: Comparing two revisions sometimes did not work if the url didn't
exist anymore in HEAD. (Stefan)
- BUG: Diffing/Blaming from TortoiseBlame on merged revisions did not
work in certain situations. (Stefan)
- BUG: Unescape the target paths when exporting the changed files from
the file diff dialog. (Stefan)
- BUG: the 'unversioned' overlay for folders didn't show up for some
unversioned folders. (Stefan)
- BUG: After a "mine before theirs" or "theirs before mine" resolving
action on the right pane in TortoiseMerge, the Undo would not
undo correctly. (Stefan)
- BUG: Failures, even GPF in blame and log dialogs when specifying a
revision range and a peg revision outside that range. (Stefan Fuhrmann)
- BUG: TortoiseMerge sometimes wrongly detected the encoding of files. (Stefan)
- BUG: If a merge conflicted due to added items the progress dialog did not
count these correctly and the context menu missed items. (Tobias Sch�fer)
- BUG: TortoiseMerge could crash if the font size was set smaller than
8 pixels. (Stefan)
- BUG: When a cleanup failed, the error message didn't include the svn
error string. (Stefan)
- BUG: /closeonend was ignored for the (un)lock command. (Stefan)
- BUG: The 'rename' context menu was not available for added files. (Stefan)
- BUG: Entering an URL before non-ascii text in the commit dialog corrupted
the first chars of the non-ascii text. (Stefan)
- BUG: Blame from the repository browser ignored the diff options. (Stefan)
TortoiseSVN Homepage
TortoiseSVN-1.5.4.14259-win32-svn-1.5.3.msi
TortoiseSVN-1.5.4.14259-x64-svn-1.5.3.msi
LanguagePack_1.5.4.14259-win32-ko.msi
LanguagePack_1.5.4.14259-x64-ko.msi
Original Post : http://neodreamer-dev.tistory.com/189
2008/10/15
강력한 무료 로컬 데이터베이스 시스템 - SQLite 3.6.4 Released!
3.6.4 버전에서 변경된 사항
- Add option support for LIMIT and ORDER BY clauses on DELETE and UPDATE statements. Only works if SQLite is compiled with SQLITE_ENABLE_UPDATE_DELETE_LIMIT.
- Added the sqlite3_stmt_status() interface for performance monitoring.
- Add the INDEXED BY clause.
- The LOCKING_STYLE extension is now enabled by default on Mac OS-X
- Added the TRUNCATE option to PRAGMA journal_mode
- Performance enhancements to tree balancing logic in the B-Tree layer.
- Added the source code and documentation for the genfkey program for automatically generating triggers to enforce foreign key constraints.
- Added the SQLITE_OMIT_TRUNCATE_OPTIMIZATION compile-time option.
- The SQL language documentation is converted to use syntax diagrams instead of BNF.
- Other minor bug fixes
SQLite Release note
SQLite Download page
C++ Builder 용 SQLite3.lib
Visual C++ 용 SQLite3.lib
Labels:
SQLite
,
SQLite for C++ Builder
,
SQLite for Visual C++
,
SQLite library
,
TistoryOldPost
무료 SVN Server - VisualSVN Server 1.6.1 Released
심각한 버그가 있었나 보다. 1.6 버전을 릴리즈 한지 얼마 되지 않아 1.6.1 버전을 릴리즈 하였다.
2008/06/19 - [Dev Story/Tips] - 그림으로 보는 간단한 개발서버 구축하기
2008/06/19 - [Dev Story/Tips] - VisualSVN Server 와 TortoiseSVN을 이용하기
1.6.1 버전에서 바뀐점
- SVNPathAuthz short_circuit option is disabled (serious
authorization problems are encountered).
- Fixed: installation doesn't recognize the folder where
the previous version is installed.
VisualSVN Official website
VisualSVN Server page
VisualSVN Server Download
Original Post : http://neodreamer-dev.tistory.com/187
Labels:
Subversion
,
SVN Server
,
TistoryOldPost
,
VisualSVN Server
2008/10/14
Visual Studio 를 위한 무료 SVN plugin - AnkhSVN
Visual Studio IDE에서 SubVersion 을 사용할 수 있게 해주는 Open source plugin 이다.
프로젝트가 오픈 소스로 진행이 되고 Dialy Build 도 지원하여 매일매일 패치되는 버전을 받을 수도 있다.
Visual Studio의 솔루션 탐색기에 포함되어 파일 아이콘에 변경된 내용이 반영되어 쉽게 버전 관리를 할 수 있다.
- AnkhSVN Homepage
- AnkhSVN 2.0 Roadmap
- AnkhSVN 2.0 Screenshots
- AnkhSVN 2.0 Online Documentation
- AnkhSVN 2.0 Download
Original Post : http://neodreamer-dev.tistory.com/186
Labels:
AnkhSVN
,
Subversion
,
svn
,
TistoryOldPost
,
Visual Studio
,
VisualStudio
무료 SVN Server - VisualSVN Server 1.6 Released
버전관리 프로그램의 하나인 Subversion 를 윈도우 상에서 간단하게 서버 구성할 수 있는 VisualSVN Server가 버전업을 하였다.
2008/06/19 - [Dev Story/Tips] - 그림으로 보는 간단한 개발서버 구축하기
2008/06/19 - [Dev Story/Tips] - VisualSVN Server 와 TortoiseSVN을 이용하기
1.6 버전에서 바뀐점
- New: Certificate Management.
- New: Advanced server binding configuration.
- New: Simple email notifications hook.
- New: Subverison hook for checking filename case-sensitivity.
- New: Logging to the Event Log.
- New: Commands to create/delete folder in repository.
- New: Server name configuration.
- Updated to Subversion 1.5.3. For further details please see:
http://svn.collab.net/repos/svn/tags/1.5.3/CHANGES - mod_auth_digest Apache module is removed from installation.
- Fixed: VisualSVN Server crashes on folders with chinese characters.
- Maximize button is available in the hook edit window.
- Improved error message is logged when service has failed to start during installation.
- Installation process is continued even if firewall configuration is failed.
- Do not reset firewall settings on upgrade.
- Firewall configuration is improved on Windows Vista and Windows Server 2008.
- Installation of an older version over the newer one is prohibited.
- Apache and Subversion package versions are displayed during the installation.
- Existing hooks are marked by bold lines in the Properties/Hooks window.
- VisualSVN Server properties dialog splited into separate pages
- SVNPathAuthz short_circuit option is enabled (improve performance on authorization
intensive operations)
VisualSVN Official website
VisualSVN Server page
VisualSVN Server Download Page
Original Post : http://neodreamer-dev.tistory.com/185
Labels:
Subversion
,
TistoryOldPost
,
VisualSVN Server
,
버전관리
,
버전관리시스템
2008/10/13
MFC 에서 간단하게 DAO 사용하기
MFC 프로그래밍에서 간단하게 DAO를 사용하는 코드이다.
예전에는 자주 사용했지만 현재는 로컬데이터베이스 시스템을 이용할 경우에는 MS-Access 보다는 SQLite를 사용한다.
예전에는 자주 사용했지만 현재는 로컬데이터베이스 시스템을 이용할 경우에는 MS-Access 보다는 SQLite를 사용한다.
// For Database
#include <atlbase.h>
#include <afxoledb.h>
#include <atlplus.h>
#include <afxdao.h> // For MDB
////////////////////////////////////////////////////////////////////////////
// Header
#pragma once
#pragma warning(disable: 4995)
class CLibDB
{
public:
CLibDB(void);
virtual ~CLibDB(void);
private:
LPCTSTR strBOOL(BOOL bFlag);
CString strVARIANT(const COleVariant& var, char *pBuf = NULL);
void DisplayDaoException(CDaoException* e);
BOOL IsExistentTable(CDaoDatabase *pDatabase, CString strTableName);
public:
CDaoDatabase* m_pDB;
CString m_strDBName;
CString m_strModulePath;
enum ERROR_CODE
{
ERROR_NULL_DB = -100,
ERROR_DB_NOT_OPEN = -101,
ERROR_DB_DATA_NOT_FOUNT = -102,
ERROR_DB_DUP_INDEX_FIDLE = -103,
ERROR_MEMORY_EXCEPTION = -1000
};
int InitDB(void);
int CheckDB(void);
bool CreateDB(CString strDBName);
bool CreateTable(CDaoDatabase* pDB);
};
////////////////////////////////////////////////////////////////////////////
// Source
#include "StdAfx.h"
#include "libdb.h"
CLibDB::CLibDB(void)
{
m_pDB = NULL;
// Get Module Path
m_strModulePath = _T("");
char sfilename[255];
GetModuleFileName(NULL, sfilename, sizeof(sfilename));
char Drive[255];
char Path[255];
char Filename[255];
char Ext[255];
_splitpath(sfilename, Drive, Path, Filename, Ext);
m_strModulePath.Format(_T("%s%s"), Drive, Path);
m_strDBName = m_strModulePath + _T("\MyMDB.mdb");
}
CLibDB::~CLibDB(void)
{
if(m_pDB)
{
if(m_pDB->IsOpen())
m_pDB->Close();
delete m_pDB;
}
}
LPCTSTR CLibDB::strBOOL(BOOL bFlag)
{
return bFlag ? _T("TRUE") : _T("FALSE");
}
CString CLibDB::strVARIANT(const COleVariant& var, char *pBuf /*= NULL*/)
{
CString strRet;
strRet = _T("UNKNOWN");
switch(var.vt){
case VT_EMPTY:
case VT_NULL:
strRet = _T("NULL");
break;
case VT_I2:
strRet.Format(_T("%hd"),V_I2(&var));
break;
case VT_I4:
strRet.Format(_T("%d"),V_I4(&var));
break;
case VT_R4:
strRet.Format(_T("%f"),(double)V_R4(&var));
break;
case VT_R8:
strRet.Format(_T("%f"),V_R8(&var));
break;
case VT_CY:
strRet = COleCurrency(var).Format();
break;
case VT_DATE:
strRet = COleDateTime(var).Format(_T("%m %d %y"));
break;
case VT_BSTR:
strRet = V_BSTRT(&var);
break;
case VT_DISPATCH:
strRet = _T("VT_DISPATCH");
break;
case VT_ERROR:
strRet = _T("VT_ERROR");
break;
case VT_BOOL:
return strBOOL(V_BOOL(&var));
case VT_VARIANT:
strRet = _T("VT_VARIANT");
break;
case VT_UNKNOWN:
strRet = _T("VT_UNKNOWN");
break;
case VT_I1:
strRet = _T("VT_I1");
break;
case VT_UI1:
strRet.Format(_T("0x%02hX"),(unsigned short)V_UI1(&var));
break;
case VT_UI2:
strRet = _T("VT_UI2");
break;
case VT_UI4:
strRet = _T("VT_UI4");
break;
case VT_I8:
strRet = _T("VT_I8");
break;
case VT_UI8:
strRet = _T("VT_UI8");
break;
case VT_INT:
strRet = _T("VT_INT");
break;
case VT_UINT:
strRet = _T("VT_UINT");
break;
case VT_VOID:
strRet = _T("VT_VOID");
break;
case VT_HRESULT:
strRet = _T("VT_HRESULT");
break;
case VT_PTR:
strRet = _T("VT_PTR");
break;
case VT_SAFEARRAY:
strRet = _T("VT_SAFEARRAY");
break;
case VT_CARRAY:
strRet = _T("VT_CARRAY");
break;
case VT_USERDEFINED:
strRet = _T("VT_USERDEFINED");
break;
case VT_LPSTR:
strRet = _T("VT_LPSTR");
break;
case VT_LPWSTR:
strRet = _T("VT_LPWSTR");
break;
case VT_FILETIME:
strRet = _T("VT_FILETIME");
break;
case VT_BLOB:
strRet = _T("VT_BLOB");
break;
case VT_STREAM:
strRet = _T("VT_STREAM");
break;
case VT_STORAGE:
strRet = _T("VT_STORAGE");
break;
case VT_STREAMED_OBJECT:
strRet = _T("VT_STREAMED_OBJECT");
break;
case VT_STORED_OBJECT:
strRet = _T("VT_STORED_OBJECT");
break;
case VT_BLOB_OBJECT:
strRet = _T("VT_BLOB_OBJECT");
break;
case VT_CF:
strRet = _T("VT_CF");
break;
case VT_CLSID:
strRet = _T("VT_CLSID");
break;
}
WORD vt = var.vt;
if(vt & VT_ARRAY){
#pragma warning(disable : 4244)
vt = vt & ~VT_ARRAY;
#pragma warning(default : 4244)
strRet = _T("Array of ");
}
if(vt & VT_BYREF){
#pragma warning(disable : 4244)
vt = vt & ~VT_BYREF;
#pragma warning(default : 4244)
strRet += _T("Pointer to ");
}
if(vt != var.vt){
switch(vt){
case VT_EMPTY:
strRet += _T("VT_EMPTY");
break;
case VT_NULL:
strRet += _T("VT_NULL");
break;
case VT_I2:
strRet += _T("VT_I2");
break;
case VT_I4:
strRet += _T("VT_I4");
break;
case VT_R4:
strRet += _T("VT_R4");
break;
case VT_R8:
strRet += _T("VT_R8");
break;
case VT_CY:
strRet += _T("VT_CY");
break;
case VT_DATE:
strRet += _T("VT_DATE");
break;
case VT_BSTR:
strRet += _T("VT_BSTR");
break;
case VT_DISPATCH:
strRet += _T("VT_DISPATCH");
break;
case VT_ERROR:
strRet += _T("VT_ERROR");
break;
case VT_BOOL:
strRet += _T("VT_BOOL");
break;
case VT_VARIANT:
strRet += _T("VT_VARIANT");
break;
case VT_UNKNOWN:
strRet += _T("VT_UNKNOWN");
break;
case VT_I1:
strRet += _T("VT_I1");
break;
case VT_UI1:
strRet += _T("VT_UI1");
break;
case VT_UI2:
strRet += _T("VT_UI2");
break;
case VT_UI4:
strRet += _T("VT_UI4");
break;
case VT_I8:
strRet += _T("VT_I8");
break;
case VT_UI8:
strRet += _T("VT_UI8");
break;
case VT_INT:
strRet += _T("VT_INT");
break;
case VT_UINT:
strRet += _T("VT_UINT");
break;
case VT_VOID:
strRet += _T("VT_VOID");
break;
case VT_HRESULT:
strRet += _T("VT_HRESULT");
break;
case VT_PTR:
strRet += _T("VT_PTR");
break;
case VT_SAFEARRAY:
strRet += _T("VT_SAFEARRAY");
break;
case VT_CARRAY:
strRet += _T("VT_CARRAY");
break;
case VT_USERDEFINED:
strRet += _T("VT_USERDEFINED");
break;
case VT_LPSTR:
strRet += _T("VT_LPSTR");
break;
case VT_LPWSTR:
strRet += _T("VT_LPWSTR");
break;
case VT_FILETIME:
strRet += _T("VT_FILETIME");
break;
case VT_BLOB:
strRet += _T("VT_BLOB");
break;
case VT_STREAM:
strRet += _T("VT_STREAM");
break;
case VT_STORAGE:
strRet += _T("VT_STORAGE");
break;
case VT_STREAMED_OBJECT:
strRet += _T("VT_STREAMED_OBJECT");
break;
case VT_STORED_OBJECT:
strRet += _T("VT_STORED_OBJECT");
break;
case VT_BLOB_OBJECT:
strRet += _T("VT_BLOB_OBJECT");
break;
case VT_CF:
strRet += _T("VT_CF");
break;
case VT_CLSID:
strRet += _T("VT_CLSID");
break;
}
}
if (pBuf != NULL)
{
int nChar = strRet.GetLength();
#ifdef _UNICODE
WideCharToMultiByte( CP_ACP, 0, strRet, -1,
pBuf, nChar, NULL, NULL );
#else
strcpy(pBuf, (LPCSTR)(LPCTSTR)strRet);
#endif
pBuf[nChar] = '\0';
}
return strRet;
}
void CLibDB::DisplayDaoException(CDaoException* e)
{
CString strMsg;
if (e->m_pErrorInfo != NULL)
{
strMsg.Format(
_T("%s (%d)"),
(LPCTSTR)e->m_pErrorInfo->m_strDescription,
e->m_pErrorInfo->m_lErrorCode);
AfxMessageBox(strMsg);
}
else
{
strMsg.Format(
_T("ERROR:CDaoException\n\n")
_T("SCODE_CODE =%d\n")
_T("SCODE_FACILITY =%d\n")
_T("SCODE_SEVERITY =%d\n")
_T("ResultFromScode =%d\n"),
SCODE_CODE (e->m_scode),
SCODE_FACILITY (e->m_scode),
SCODE_SEVERITY (e->m_scode),
ResultFromScode (e->m_scode));
AfxMessageBox(strMsg);
}
}
BOOL CLibDB::IsExistentTable(CDaoDatabase *pDatabase, CString strTableName)
{
CDaoDatabase *pDB = NULL;
BOOL bDuplicateTableName = TRUE;
if (pDatabase == NULL)
pDB = m_pDB;
else
pDB = pDatabase;
if (pDB == NULL)
return FALSE;
CDaoTableDefInfo tableInfo; // only needed for the call
TRY
{
pDatabase->GetTableDefInfo(strTableName, tableInfo);
}
CATCH (CDaoException, e)
{
if (e->m_pErrorInfo->m_lErrorCode == 3265)
bDuplicateTableName = FALSE;
}
AND_CATCH (CMemoryException, e)
{
// do nothing
;
}
END_CATCH
return bDuplicateTableName;
}
int CLibDB::InitDB()
{
if (m_pDB)
{
if (m_pDB->IsOpen())
m_pDB->Close();
delete m_pDB;
m_pDB = NULL;
}
m_pDB = new CDaoDatabase;
CheckDB();
return 0;
}
int CLibDB::CheckDB(void)
{
CFileStatus fileStatus;
if (CFile::GetStatus( m_strDBName, fileStatus ))
{
CDaoDatabase* pDB = new CDaoDatabase;
CString strQuery;
pDB->Open(m_strDBName);
if (pDB->IsOpen())
{
if (IsExistentTable(pDB, "MYGROUP") == FALSE ||
IsExistentTable(pDB, "MEMBER") == FALSE)
{
AfxMessageBox("Database damaged. Recreate database");
CreateTable(pDB);
}
}
if(pDB)
{
if(pDB->IsOpen())
pDB->Close();
delete pDB;
}
// Find DB File
}
else
{
// DB File Not Found
AfxMessageBox("DB Not Found!!\n\nCreate database.");
CreateDB(m_strDBName);
}
return 0;
}
bool CLibDB::CreateDB(CString strDBName)
{
CDaoDatabase* pDB = new CDaoDatabase;
pDB->Create(strDBName);
if(!pDB)
{
TRACE("Fail to Create Database");
return false;
}
else
{
CreateTable(pDB);
if(pDB->IsOpen())
pDB->Close();
delete pDB;
}
return true;
}
bool CLibDB::CreateTable(CDaoDatabase* pDB)
{
if (!pDB)
return false;
if (!pDB->IsOpen())
return false;
CString strQuery;
TRY {
// Create Comopnent Table
strQuery.Format(
"CREATE TABLE MYGROUP ("
" GROUPID INTEGER PRIMARY KEY"
", ALIAS VARCHAR(50)"
", MEMBERS INTEGER"
")"
);
pDB->Execute(strQuery);
}
CATCH (CDaoException, e)
{
DisplayDaoException(e);
}
END_CATCH
TRY {
// Create Address
CDaoTableDef Table(pDB);
CDaoFieldInfo Field;
Table.Create("MEMBER");
Field.m_strName = "NAME";
Field.m_nType = dbText;
Field.m_lSize = 50;
Field.m_lAttributes = dbVariableField;
Field.m_bRequired = TRUE;
Field.m_bAllowZeroLength = FALSE;
Field.m_lCollatingOrder = dbSortGeneral;
Table.CreateField(Field);
Table.CreateField("GROUPID", dbInteger, 4);
Table.CreateField("NAME", dbText, 80);
Table.CreateField("AGE", dbInteger, 4);
Table.CreateField("HEIGHT", dbSingle, 4);
Table.CreateField("WEIGHT", dbSingle, 4);
Field.m_nType = dbBoolean;
Field.m_lSize = 1;
Field.m_lAttributes = dbFixedField | dbUpdatableField;
Field.m_bRequired = TRUE;
Field.m_bAllowZeroLength = FALSE;
Field.m_strDefaultValue = "1";
Field.m_strName = "Gender";
Table.CreateField(Field);
Field.m_strName = "IsAdult";
Table.CreateField(Field);
Table.Append();
}
CATCH (CDaoException, e)
{
DisplayDaoException(e);
}
END_CATCH
return true;
}
Original Post : http://neodreamer-dev.tistory.com/184
Labels:
C++
,
DAO
,
Local Database
,
MDB
,
MFC
,
MS Access
,
TistoryOldPost
,
로컬 데이터베이스
MFC MDI 에서 초기 자식창 생성 막기
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Don't display a new MDI child window during startup
if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew)
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
if (!ProcessShellCommand(cmdInfo))
return FALSE;
Original Post : http://neodreamer-dev.tistory.com/183
Dialog 위에 ScrollView 올리기
////////////////////////////////////////////////////////////////////////
//On View
//header
public:
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName
, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd
, UINT nID, CCreateContext* pContext = NULL);
//source
BOOL CSampleView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName
, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd
, UINT nID, CCreateContext* pContext)
{
return CWnd::Create(lpszClassName, lpszWindowName,
dwStyle, rect, pParentWnd, nID, pContext);
}
int CSampleView::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest
, UINT message)
{
return MA_ACTIVATE;
//return CScrollView::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
////////////////////////////////////////////////////////////////////////
//On Dialog
CRect rt;
GetClientRect(rt);
m_pScrollView = new CSampleView();
m_pScrollView->Create (NULL, NULL, WS_VISIBLE | WS_CHILD,
rt, this, 10000, NULL);
CSize sizeTotal;
sizeTotal.cx = sizeTotal.cy = 100;
m_pScrollView->SetScrollSizes(MM_TEXT, sizeTotal);
Original Post : http://neodreamer-dev.tistory.com/182
Labels:
C++
,
dialog
,
MFC
,
ScrollView
,
TistoryOldPost
2008/10/08
비어있지 않은 레지스트리 키 지우기 - SHDeleteKey
#include <Shlwapi.h>
DWORD Result = SHDeleteKey(HKEY_CURRENT_USER, "Software\Microsoft\...");
switch(Result)
{
case ERROR_SUCCESS:
// Registry Deleted
break;
case ERROR_FILE_NOT_FOUND:
// Registry key not found
break;
default:
break;
}
Original Post : http://neodreamer-dev.tistory.com/181
Labels:
C++
,
registry
,
SHDeleteKey
,
TistoryOldPost
,
레지스트리
Folder 선택하기 SHBrowseForFolder
char m_szWorkPath[MAX_PATH];
LPITEMIDLIST pidlBrowse;
BROWSEINFO info;
info.hwndOwner = this->GetSafeHwnd(); // 부모 윈도우의 핸들
info.pidlRoot = NULL;
info.pszDisplayName = m_szWorkPath;
info.lpszTitle = "Select Directory";
info.ulFlags = BIF_RETURNONLYFSDIRS;
info.lpfn = NULL;
info.lParam = 0; //m_szWorkPath;
pidlBrowse = SHBrowseForFolder(&info); // 다이얼로그를 띄운다.
if(pidlBrowse != NULL)
{
SHGetPathFromIDList(pidlBrowse, m_szWorkPath); // 패스를 얻어온다.
}
Original Post : http://neodreamer-dev.tistory.com/180
2008/10/07
굿모닝팝스 MP3 다운로더 v7.0.0.36
이번 버전에 바뀐 점
- 파일 열기 기능 추가
- 다운로드 받은 후 재생기능 추가
다운로드 속도가 너무 느려 실시간 듣기는 의미가 없어 보인다. 다운로드 속도를 개선하지 않는 한 다음 업그레이드는 없을 듯하다.
Original Post : http://neodreamer-dev.tistory.com/179
2008/10/04
굿모닝팝스 MP3 다운로더 v7.0.0.32
단팥 사이트가 부분 유료화가 되어버리면서 다운 받기도 어려워졌고 다운로드 속도 또한 많이 느려졌다. 예전에 굿모닝 팝스 MP3 재생기라는 프로그램이름을 달고 만들었는데 다운로드가 너무 느려지는 바람에 실시간 재생은 큰 의미를 잃어 버리게 되었다. 다운로드 또한 많이 느려진 탓에 이 프로그램을 통한 다운로드도 크게 의미를 잃었다.
프로그램을 만들은 본인도 많이 애용하고 있는 프로그램이였는데 이제는 MP3 URL 을 복사하는 용도로 밖에 사용하지 않는다. URL을 복사해서 FlashGet 같은 다운로드 전용 프로그램을 통해 다운 받는 것이 보다 빠르게 다운 받을 수 있기 때문이다.
이번 버전에서는 최종으로 다운로드 받은 경로를 기억하는 기능과 다운로드 창을 조금 개선하였다.
다음 버전은 다운로드 완료 후 다운로드 받은 파일을 재생하는 기능을 넣을 예정이다. (일정은 미정)
Original Post : http://neodreamer-dev.tistory.com/178
Delphi Distiller v1.51 released
델파이툴(5/6/7/2006/2007/2009)의 여러가지 트윅을 설정 할 수 있는 프로그램이다.
Delphi Distiller v1.51 지원 기능
- Choose what packages and experts are loaded by Delphi 5/6/7/2006/2007/2009.
- File associations manager for Delphi 5/6/7/2006/2007/2009.
- Delphi 5 tweaks:
- Don't create .~bpl files.
- Don't create .cfg files.
- Use Tahoma font by default.
- Don't show splash screen.
- Customize editor colors.
- Trial to Retail conversion.
- Delphi 6 tweaks:
- Don't create .~bpl files.
- Don't create .ddp files.
- Don't create .cfg files.
- Use Tahoma font by default.
- Don't show splash screen.
- Delphi 7 tweaks:
- Don't create .~bpl files.
- Don't create .ddp files.
- Don't create .cfg files.
- Use Tahoma font by default.
- Don't show splash screen.
- Delphi 2006 tweaks:
- Don't create .~bpl files.
- Don't create .local files.
- Don't create .cfg files.
- Remove toolbar gradients.
- Fix TabStop bug in TFrame's.
- Don't show splash screen.
- Delphi 2007 tweaks:
- Don't create .~bpl files.
- Don't create .local files.
- Don't check for updates when the IDE starts.
- Avoid loading of additional .NET crap by delphicoreide100.bpl.
- Remove toolbar gradients.
- Don't show splash screen.
- Delphi 2009 tweaks:
- Don't create .~bpl files.
- Don't create .local files.
- Don't check for updates when the IDE starts.
- Avoid loading of additional .NET crap by delphicoreide120.bpl.
- Don't show splash screen.
Tip. Ctrl + Alt + L 을 누르면 멋진 걸 볼 수 있다.
홈페이지
Original Post : http://neodreamer-dev.tistory.com/177
Delphi Distiller v1.51 지원 기능
- Choose what packages and experts are loaded by Delphi 5/6/7/2006/2007/2009.
- File associations manager for Delphi 5/6/7/2006/2007/2009.
- Delphi 5 tweaks:
- Don't create .~bpl files.
- Don't create .cfg files.
- Use Tahoma font by default.
- Don't show splash screen.
- Customize editor colors.
- Trial to Retail conversion.
- Delphi 6 tweaks:
- Don't create .~bpl files.
- Don't create .ddp files.
- Don't create .cfg files.
- Use Tahoma font by default.
- Don't show splash screen.
- Delphi 7 tweaks:
- Don't create .~bpl files.
- Don't create .ddp files.
- Don't create .cfg files.
- Use Tahoma font by default.
- Don't show splash screen.
- Delphi 2006 tweaks:
- Don't create .~bpl files.
- Don't create .local files.
- Don't create .cfg files.
- Remove toolbar gradients.
- Fix TabStop bug in TFrame's.
- Don't show splash screen.
- Delphi 2007 tweaks:
- Don't create .~bpl files.
- Don't create .local files.
- Don't check for updates when the IDE starts.
- Avoid loading of additional .NET crap by delphicoreide100.bpl.
- Remove toolbar gradients.
- Don't show splash screen.
- Delphi 2009 tweaks:
- Don't create .~bpl files.
- Don't create .local files.
- Don't check for updates when the IDE starts.
- Avoid loading of additional .NET crap by delphicoreide120.bpl.
- Don't show splash screen.
버전 히스토리 보기
v1.51
+ New: Secret feature updated.
v1.50
+ New: Delphi 5 Trial to Retail conversion.
v1.44
+ New: Supports Delphi 2009 RTM v12.0.3170.16989.
v1.43
+ New: Supports Embarcadelphi 2009 v12.0.3170.16986.
v1.42
+ New: Supports Embarcadelphi 2009 v12.0.3168.16957.
v1.41
+ New: Supports Embarcadelphi 2009 v12.0.3163.16897.
v1.40
+ New: Supports Embarcadelphi 2009 RTM v12.0.3155.16733.
v1.36
* Fix: The Delphi 2009 option in File associations tab was enabled even for
machines where Delphi 2009 wasn't installed.
v1.35
+ New: Supports Embarcadelphi 2009 Prerelease v12.0.3128.15596.
v1.34
+ New: Adjust Delphi 5 palette luminosity more easily.
* Fixed bug concerning packages that have the same description.
* A few cosmetic changes.
- Removed option "Don't create __history folders", which is unnecessary because
Delphi already has the option "Create backup files".
v1.33
+ New: Support for Delphi 2007 April'08 Update.
v1.32
+ New: Don't show Delphi splash screen.
v1.31
+ New: Support for Delphi 2007 December'07 Update.
NOTE: The December Update is a patcher. This means that the update will
probably fail if your current D2007 has been modified by Delphi Distiller. To
avoid any issues, prior to installing the December Update, run Delphi
Distiller and uncheck all the tweaks. Then install the update and run Delphi
Distiller again to tweak it to your taste.
v1.30
+ New: An important hack for our beloved Delphi 5: Total flexibility to change
the editor colors.
* Fix: Works OK on displays with high DPI configurations.
v1.24
* Fix: Packages and experts with duplicate descriptions are supported.
v1.23
+ New: Supports Delphi 2006 Hotfix Rollup 1.
* Fix: If a version of Delphi was installed in the past, sometimes Distiller
believed that this version was still installed.
v1.22
+ New: Supports Delphi 2007 Update 3.
v1.21
+ New: Automatically open the tab for the currently installed Delphi.
v1.20
+ New: Button to save changes and start Delphi automatically.
v1.17
+ New: Support for D2007 Update 2 (actually, no changes were needed, but it is
now explicit that Update 2 is supported).
* Fix: Small glitch in "Don't check for updates" check box.
* Fix: D2006/2007 file associations didn't work.
v1.10
+ New: File associations manager.
+ New: Tooltip on packages and experts status bar.
* Fix: Dummy registry keys were created even for Delphi versions that were not
installed.
* A few cosmetic changes.
v1.00
+ First release.
+ New: Secret feature updated.
v1.50
+ New: Delphi 5 Trial to Retail conversion.
v1.44
+ New: Supports Delphi 2009 RTM v12.0.3170.16989.
v1.43
+ New: Supports Embarcadelphi 2009 v12.0.3170.16986.
v1.42
+ New: Supports Embarcadelphi 2009 v12.0.3168.16957.
v1.41
+ New: Supports Embarcadelphi 2009 v12.0.3163.16897.
v1.40
+ New: Supports Embarcadelphi 2009 RTM v12.0.3155.16733.
v1.36
* Fix: The Delphi 2009 option in File associations tab was enabled even for
machines where Delphi 2009 wasn't installed.
v1.35
+ New: Supports Embarcadelphi 2009 Prerelease v12.0.3128.15596.
v1.34
+ New: Adjust Delphi 5 palette luminosity more easily.
* Fixed bug concerning packages that have the same description.
* A few cosmetic changes.
- Removed option "Don't create __history folders", which is unnecessary because
Delphi already has the option "Create backup files".
v1.33
+ New: Support for Delphi 2007 April'08 Update.
v1.32
+ New: Don't show Delphi splash screen.
v1.31
+ New: Support for Delphi 2007 December'07 Update.
NOTE: The December Update is a patcher. This means that the update will
probably fail if your current D2007 has been modified by Delphi Distiller. To
avoid any issues, prior to installing the December Update, run Delphi
Distiller and uncheck all the tweaks. Then install the update and run Delphi
Distiller again to tweak it to your taste.
v1.30
+ New: An important hack for our beloved Delphi 5: Total flexibility to change
the editor colors.
* Fix: Works OK on displays with high DPI configurations.
v1.24
* Fix: Packages and experts with duplicate descriptions are supported.
v1.23
+ New: Supports Delphi 2006 Hotfix Rollup 1.
* Fix: If a version of Delphi was installed in the past, sometimes Distiller
believed that this version was still installed.
v1.22
+ New: Supports Delphi 2007 Update 3.
v1.21
+ New: Automatically open the tab for the currently installed Delphi.
v1.20
+ New: Button to save changes and start Delphi automatically.
v1.17
+ New: Support for D2007 Update 2 (actually, no changes were needed, but it is
now explicit that Update 2 is supported).
* Fix: Small glitch in "Don't check for updates" check box.
* Fix: D2006/2007 file associations didn't work.
v1.10
+ New: File associations manager.
+ New: Tooltip on packages and experts status bar.
* Fix: Dummy registry keys were created even for Delphi versions that were not
installed.
* A few cosmetic changes.
v1.00
+ First release.
Tip. Ctrl + Alt + L 을 누르면 멋진 걸 볼 수 있다.
홈페이지
Original Post : http://neodreamer-dev.tistory.com/177
Labels:
Delphi Distiller
,
Delphi Tweak
,
TistoryOldPost
2008/10/01
드디어 GExperts 1.33 Beta for Delphi 2009 가 공개되었다.
Delphi 와 C++ Builder 의 IDE Plugin 인 Gexperts 가 드디어 RAD Studio 2009 용 버전을 공개하였다. 비록 아직은 Beta버전 이지만 요긴하게 사용할 수 있을 것 같다.
Gexperts Official Website
Gexperts README.txt
Gexperts Download
Original Post : http://neodreamer-dev.tistory.com/176
Subscribe to:
Posts
(
Atom
)