시리얼 포트 오픈

시리얼 포트는 파일처럼 다룬다.
시리얼 포트를 오븐 하기위해서는 CreateFile()을 사용한다.

HANDLE CreateFile(
  LPCTSTR lpFileName,         // 포트 이름을 가르키는 버퍼의 포인터
  DWORD dwDesiredAccess,       // 억세스모드(READ, WRITE)
  DWORD dwShareMode,          // 포트의 공유 방법 비정(공유 불가: 0으로 설정)
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 시큐리티 속성
  DWORD dwCreationDisposition,  // 포트 여는 방법 지정(OPEN_EXISTING로 기존 파일 지정)
  DWORD dwFlagsAndAttributes,   // 포트의 속성 지정
  HANDLE hTemplateFile          // 템플레이트 파일의 핸들(항상 NULL로 지정)
 );


인수:

lpFileName: COM1이나 COM2등의 시리얼 포트 이름을 지정한다.
(LPT1같은 프린터 포트도 지정할 수 있다.)

dwDesiredAccess: 이하의 읽기 모드를 단독 또는 OR로 지정한다.

의미
0 디바이스의 속성을 묻는다.
GENERIC_READ 읽기 억세스.
읽기 쓰기를 할때는 GENERIC_WRITE를 조합해서 지정
GENERIC_WRITE 쓰기 억세스.
쓰기 쓰기를 할때는 GENERIC_READ를 조합해서 지정

일반적으로 시리얼 포트는 입출력이 가능하기 때문에 GENERIC_READ | GENERIC_WRITE로 설정한다.

dwShareMode : 포트의 공유모드로 이하의 값을 단독이나 OR로 지정한다.
0을 지정하면 공유하지 않는다.
 
 
의미
FILE_SHARE_DELETE Windows NT 일 경우만 : 
후속의 오픈 조작으로 삭제 억세스가 요구될 때, 그 오픈을 허가
FILE_SHARE_READ 후속의 호픈 조작으로 읽기 억세스가 요구될 때 그 오픈을 허가
FILE_SHARE_WRITE 후속의 호픈 조작으로 쓰기 억세스가 요구될 때 그 오픈을 허가

 
 포트는 파일과 달리 공유할수 없기 때문에 0으로 지정한다. 이 경우는 이미 오픈 되어진 포트를 다른 프로세스가 오픈 하려고 하면 CreateFile()은 에러가 된다. 하지만 같은 프로세스의 복수 스레드는 CraeteFile()로 반환된 핸들을 공유할 수 있다.

lpSecurityAttributes : 시큐리티 속성으로 SECURITY_ATTRIBUTES 구조체의 포인터이다.
NULL을 설정하면 핸들은 자식 프로세스에 계승되어지지않는다.

dwCreationDisposition : 파일이 존재할 때 또는 존재하지 않을 때, 각각의 동작을 지정한다.
시리얼 포트는 기존 파일 이외에 있을 수 없기 때문에 OPEN_EXISTING을 지정한다.

dwFlagsAndAttributes : 파일의 속성 및 플래그를 지정한다.
시리얼 포트에서 사용할만한 플래그는 FILE_FLAG_OVERLAPPED 뿐이다.

의미
FILE_FLAG_OVERLAPPED 시간이 걸리는 처리에 있어서 ERROR_IO_PENDING을 반환하도록 한다. 처리가 끝나면 이벤트가 시그널 상태로 설정된다.
이 플래그를 지정했을 때는 ReadFile 함수나 WriteFile 함수로 OVERLAPPED 구조체를 지정해야만 된다.


hTemplateFile : 시리얼 포트에 관계없기 때문에 NULL을 지정한다.


시리얼 포트 클로즈

클로즈는 CreateFile()이 반환하는 핸들을 인수로 하여 CloseHandle을 호출한다.

BOOL CloseHandle( HANDLE hObject );


반환값 : 성공하면 0 이외의 값, 실패하면 0을 반환한다.

시리얼 포트 상태 정보 얻기

자신의 컴퓨터에 시리얼 포트는 어느 정도의 성능인지 등 보통은 신경쓰지않지만 디바이스 드라이버를 포함한 시리얼 포트의 성능을 앎으로 서포트 하지않는 보레이트를 잘못해서 설정했을 때의 부정한 설정을 막아준다.

시리얼 포트에 관한 정보는 GetCommProperties()의 호출로 COMPROC 구조체 변수를 읽어온다.

BOOL GetCommProperties (HANDLE hFile, LPCOMMPROP lpCommProp );


인수 :

hFile : 통신 디바이스의 핸들
CreateFile함수가 반환하는 핸들

lpCommProp : 통신 특성 정보가 반환되어 COMPROC 구조체의 포인터

반환값 : 함수가 성공하면 0 이외의 값, 실패하면 0을 반환한다.

LPCOMMPROP 구조체는 이하의 구성의 시리얼 포트 정보를 가진다.

typedef struct _COMMPROP{
  WORD wPacketLength;     // 구조체 사이즈
  WORD wPacketVersion;    // 구조체 버젼
  DWORD dwServiceMask;    // 실행된 서비스
  DWORD dwReserved1;      // 예약
  DWORD dwMaxTxQueue;    // 바이트 단위의 최대 송신 버퍼 사이즈
  DWORD dwMaxRxQueue;    // 바이트 단위의 최대 수신 버퍼 사이즈
  DWORD dwMaxBaud;      // 보레이트 최대값
  DWORD dwProvSubType;       // 특정 프로바이더 타입
  DWORD dwProvCapabilities;     // 서포트된 함수
  DWORD dwSettableParams;      // 변경 가능 파라미터
  DWORD dwSettableBaud;     // 허가된 보레이트
  WORD wSettableData;        // 허가된 바이트 사이즈
  WORD wSettableStopParity;      // 스탑 비트 / 패리티 허가
  DWORD dwCurrentTxQueue;     // Tx 버퍼 사이즈
  DWORD dwCurrentRxQueue;     // Rx 버퍼 사이즈
  DWORD dwProvSpec1;       // 프로바이더 특정 데이터
  DWORD dwProvSpec2;       // 프로바이더 특정 데이터
  WCHAR wcProvChar[1];       // 프로바이더 특정 데이터
}COMMPROP;

dwServiceMask : 시링러 포트의 경우는 항상 SP_SERIALCOMM이다.
dwReserved1 : 미사용
dwMaxTxQueue : 출력 버퍼의 최대값(바이트), 0을 설정하면 무제한
dwMaxRxQueue : 입력 버퍼의 최대값(바이트), 0을 설정하면 무제한
dwMaxBaud : 이하의 상수로 설장 가능한 보레이트의 최대값

의미
BAUD_075 75 bps
BAUD_110 110 bps
BAUD_134_5 134.5 bps
BAUD_150 150 bps
BAUD_300 300 bps
BAUD_600 600 bps
BAUD_1200 1200 bps
BAUD_1800 1800 bps
BAUD_2400 2400 bps
BAUD_4800 4800 bps
BAUD_7200 7200 bps
BAUD_9600 9600 bps
BAUD_14400 14400 bps
BAUD_19200 19200 bps
BAUD_38400 38400 bps
BAUD_56K 56K bps
BAUD_57600 57600 bps
BAUD_115200 115200 bps
BAUD_128K 128K bps
BAUD_USER 유저 설정

dwProvSubType : 이하의 상수로 CreateFile()에 의해 작성된 통신 디바이스가 무엇을 서포트하는지를 알려준다. 시리얼 포트의 경우는 PST_RS232가 된다.

의미
PST_FAX 팩스
PST_LAT LAT 프로토콜
PST_MODEM 모뎁
PST_NETWORK_BRIDGE 미정의 네트워크 브릿지
PST_PARALLELPORT 패럴렐 포트
PST_RS232 RS-232 시리얼 포트
PST_RS422 RS-422 포트
PST_RS423 RS-423 포트
PST_RS449 RS-449 포트
PST_SCANNER 스캐너
PST_TCPIP_TELNET TCP/IP TelnetR 프로토콜
PST_UNSPECIFIED 미정의
PST_X25 X.25 스탠다드


dwProvCapabilities : 이하의 상수로 시리얼 포트가 서포트 하는 기능을 보여준다.
통산의 리리얼 포트 드라이버는 PCF_16BITMODE와 PCF_SPECIALCHARS 이외는 대체적으로 서포트한다.

의미
PCF_16BITMODE 특별한 16비트 모드를 서포트
PCF_DTRDSR DTR/DSR 서포트
PCF_INTTIMEOUTS 인터벌 타임아웃을 서포트
PCF_PARITY_CHECK 패리티 체크 서포트
PCF_RLSD RLSD(CD) 서포트
PCF_RTSCTS RTS/CTS 서포트
PCF_SETXCHAR 설정 가능한 XON/XOFF 서포트
PCF_SPECIALCHARS 설정 가능한 특수문자 서포트
PCF_TOTALTIMEOUTS 토탈 타임아웃 서포트
PCF_XONXOFF XON/XOFF 플로 제어 서포트

dwSettableParams : 이하의 상수로 설정 변경 가능한 파라미터를 나타낸다.

의미
SP_BAUD 보레이트
SP_DATABITS 1케릭터의 비트수
SP_HANDSHAKING 핸드 쉐이크 방식(플로 제어)
SP_PARITY 패리티 비트 수
SP_PARITY_CHECK 패리티 체크의 유무
SP_RLSD RLSD(CD)
SP_STOPBITS 스톱 비트 수

dwSettableBaud : 설정 가능한 모든 보레이트의 종류를 dwMaxBaud의 항목으로 정의된 상수값으로 OR한 값을 나타낸다.

wSettableData : 이하의 상수의 OR로 설정 가능한 1 케릭터의 비트 수를 나타낸다.
시리얼 포트에서는 5~8이 서포트 된다.

의미
DATABITS_5 5 data bits
DATABITS_6 6 data bits
DATABITS_7 7 data bits
DATABITS_8 8 data bits
DATABITS_16 16 data bits
DATABITS_16X 시리얼 회선을 사용한 특수한 와이드 버스

wSettableStopParity : 이항의 상수의 OR로 설정 가능한 스톱 비트 수와 패리티를 나타낸다.

의미
STOPBITS_10 1  스톱 비트
STOPBITS_15 1.5 스톱 비트
STOPBITS_20 2 스톱 비트
PARITY_NONE 패리티 없음
PARITY_ODD 홀수 패리티
PARITY_EVEN 짝수 패리티
PARITY_MARK 마크  패리티
PARITY_SPACE         스페이스 패리티


dwCurrentTxQueue : 현재 송신 버퍼 사이즈를 나타낸다.

dwCurrentRxQueue : 현재 수신 버퍼 사이즈를 나타낸다.

시리얼 포트의 상태를 얻기 예제

COMMPROP구조체의 주요 내용을 표시하는 프로퍼티 시트 예제

이 예제는 컴포트1에서 4까지를 고정으로 오픈한다.
(요즘 기본적으로 컴포트가 없는 컴퓨터가 많아서 USB를 쓰는 사람은
컴포트를 1에서 읽는 것을 좀 수정할 필요가 있다.
USB 컴포트가 3이나 4로 잡히면 그냥 실행시켜도 문제없다.)

컴포트 1에서 4를 열어 각 포트의 시리얼 포트 상태와
각 포트에 설정 가능값을 표시한다.


Posted by 띠리
설명은 따로 필요없을 것같다.
그냥 밑에 소스를 보면....

void main()

{

    int    nDec = 0;

    char szHex[16];


    // 16진수를 10진수로


    sprintf(szHex, "FF");


    nDec = (int)strtol(szHex, NULL, 16);


    printf(" %s -> %d \n", szHex, nDec);


    nDec = nDec - 0xF;


    // 10진수를 16진수로


    sprintf(szHex, "%X", nDec);


    printf("%d -> %s \n", nDec, szHex);


}



실행한 결과

 FF -> 255
240 -> F0


strtol 함수를 알면 16진수를 10진수로 바꾸는 것을 한줄에 끝낼 수 있는데
저 함수를 모르면...

sprintf의 포멧에서 %X를 쓰느냐 %x를 쓰느냐에
따라서 16진수의 영문자(A~F)가 대문자로 표시되느냐
소문자로 표시되느냐가 결정되어진다.
Posted by 띠리
MFC에서 컨트롤의 탭 순서 바꾸기

탭 순서는 Tab키를 눌렀을 때 선택된 커트롤에서 다음 컨트롤로 이동하는 순서이다.
VB에서는 프러퍼티에서 TabIndex를 바꾸면 각 컨트롤의 탭순서를 바꿀수 있다.
각 컨트롤에서 Tab으로 이동할찌 안할찌는 Tabstop속성으로 정한다.

탭순서를 MFC에서 변경할 때는 탭 순서를 지정할 다이알로그를 선택하고

    메뉴의 서식에서 탭순서를 선택하거나
    Ctrl + D를 누른다.

그러면 아래의 그림처럼 표시되어진다.

사용자 삽입 이미지

저렇게 표시된 숫자를 클릭한 순서대로 순서가 바뀌어진다.
Posted by 띠리
VB랑 다르게MFC에서는 에디트 박스를 쓰는게 좀 귀찮다.

프로젝트를 MFC 응용프로그램으로 선택해서 만들고
응용 프로그램 종류에서 대화 상자 기반을 선택하여 프로젝트를 만든다.

프로젝트를 만든후, 리소스 뷰에서 Dialog 밑에 다이알로그 박스를 선택한다.
도구 상자에서 다이알로그에 에디트 컨트롤을 두개 만든다.

만든 에디트 컨트롤을 선택하여 속성창을 열어 ID를 변경한다.

솔루션 탐색기에서 자동으로 만들어진 헤더파일(EditBoxDlg.h : 프로젝트 명을 어떻게 주느냐에 따라 헤더 파일 이름이 달라진다.)에 에디트 컨트롤 변수를 public에 추가한다.

// EditBoxDlg.h : 헤더 파일

//


#pragma once



// CEditBoxDlg 대화 상자

class CEditBoxDlg : public CDialog

{

// 생성입니다.

public:

    CEditBoxDlg(CWnd* pParent = NULL);    // 표준 생성자입니다.


// 대화 상자 데이터입니다.

    enum { IDD = IDD_EDITBOX_DIALOG };


    protected:

    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.



// 구현입니다.

protected:

    HICON m_hIcon;


    // 생성된 메시지 맵 함수

    virtual BOOL OnInitDialog();

    afx_msg void OnPaint();

    afx_msg HCURSOR OnQueryDragIcon();

    DECLARE_MESSAGE_MAP()


public:

    CEdit    m_EditIn;

    CEdit    m_EditOut;


};


다이알로그 소스를 열어 DoDataExchange를 찾는다.

void CEditBoxDlg::DoDataExchange(CDataExchange* pDX)

{

    CDialog::DoDataExchange(pDX);


    DDX_Control(pDX, IDC_EDIT_IN, m_EditIn);

    DDX_Control(pDX, IDC_EDIT_OUT, m_EditOut);

}


이렇게 다이알로그 박스에 만든 에디트 컨트롤과
다이알로그의 CEdit 으로 정의한 맴버 변수를 관련지어준다.
이렇게 관련지어주면 에디트 컨트롤에 데이터를 넣고 빼기를 간단하게 할 수 있다.

리소스의 다이알로그에서 확인 버튼을 더블클릭하면
아래와 같이 void CEditBoxDlg::OnBnClickedOk() 함수가 만들어진다.
그 함수에 CEdit으로 정의한 변수를 쳐넣고(m_EditIn)
"."을 누르면 에디트 컨트롤의 프라퍼티가 표시되어진다.
GetWindowText는 에디트 컨트롤의 문자열을 문자열 파라미터에 대입시키고
SetWindowText는 문자열 파라미터의 값을 에디트 컨트롤에 표시한다.

void CEditBoxDlg::OnBnClickedOk()

{

    CString        strTest;


    // 에디트 컨트롤에 입력된 문자열을 CString에 대입

    m_EditIn.GetWindowText(strTest);


    // CString의 문자열을 에디트 컨트롤에 입력

    m_EditOut.SetWindowText(strTest);


    // 에디트 컨트롤에 문자열 입력

    m_EditIn.SetWindowText("");


    //OnOK();

}


이렇게  MFC에서는 좀 번거롭게
컨트롤과 리소스를 짝을 지어주어야만이 쓸수있다.
VB를 하던 사람이라면 정말 번거럽게만 느껴진다. ^^;



 

Posted by 띠리
C/C++ 분산 어플리케이션 및 side-by-side 어셈블리 트러블 슈팅
(Troubleshooting C/C++ Isolated Applications and Side-by-side Assemblies)

의존하는 Visual C++ 라이브러리가 발견되지않는 겨우는 C/C++ 어플리케이션의 읽어들이기에 실해하는 경우가 있다. 발생하는 가능성이 있는 런타임 에러의 일람에 관해서는 "Visual C++파일의 재배포"를 참조하면 된다.
이 섹션에서는 C/C++ 어플리케이션의 읽어들이기에 실패하는 가장 일반적인 이유에 대해서 문제해결의 방법을 알아본다.

Visual C++가 인스톨되어 있지 않은 컴퓨터에 어플리케이션을 카피하고 "Visual c++파일 재배포"에 열거되어진 에러 메세지로 어플리케이션이 크래쉬한 경우, 몇개의 포인트를 확인하여 에러의 원인을 찾아내야 된다.

1. "Visual c++ 어플리케이션의 의존관계의 이해"의 순서에 따른다. Dependency Walker에는 특정의 어플로케이션 또는 DLL의 대부분의 의존관계를 표시할 수 있다. 표시되어져 있지않은 DLL이 있는 경우는 어플리케이션을 실행하는 컴퓨터에 그 DLL을 인스톨한다.

2. 오퍼레이팅 시스템 로더는 메니페스트를 사용하여 어플리케이션이 의존하는 어셈블리를 읽어들인다. 메니페스트는 리소스로서 바이너리에 넣는 것도 외부 파일로서 어플리케이션의 모컬 폴더에 보전하는 것도 가능하다.
메니페스트가 바이너리 안에 들어가 있는지를 확인하기 위해서는 Visual Studio에서 바이너리를 열어 이 바이너리 리소스를 조사하면된다. 들어가 있는 경우에는 RT_MANIFEST라고 하는 리소스를 볼수있다. 바이너리에 넣어진 메니페스트가 없을때는 <binary_name>.<extension>.manifest와 같은 이름의 외부 파일을 찾는다.

3. 메니패스트가 없는 경우는 링커에 프로젝트의 메니페스트를 만들어야된다. 이 프로젝트의 "프로젝트 속성" 다이얼로그의 링커의 메니페스트의 생성 옵션을 예로 한다.

메모
메니패스트가 생성하지 않는 Visual C++ 프로젝트의 빌터는 서포트하지 않는다.
Visual C++ 2005에서 빌드되어지는 C/C++프로그램은 모두 Visual C++ 라이브러리에의 의존 관계를 기술한 메니패스트를 포함해야된다.

4. 메니페스트가 라이브러리안에 들어있는 경우는 RT_MANIFEST의  ID가 그 타입의 바이너리에 적절한 ID인지를 확인한다. 어플리케이션의 경우는 ID를 1로, 또는 거의 DLL의 경우는 ID를 2로  해야된다. 메니페스트가 외부 파일의 경우는 XML에디터나 텍스트 에디터를 열어서 메니페스트 및 배치의 룰의 상에 대해서는 "Manifests"를 참조한다.

메모
Windows XP에서는 외부 메니페스트가 어플리케이션의 로컬 폴더에 있는 경우, 오퍼레이팅 시스템 로더는 바이너리에 넣어진 메니페스트를 이용하지않고 이 외부 메니페스트를 사용한다.
Windows Server 2003 및 이 이후의 버젼의 Windows에서는 이 우선 순위가 바뀌어 바이너리에 넣어진 메니페스트가 있는 경우 그것을 이용하고 외부 메니페스트는 무시한다.

5 모든 DLL이 바이너리로 넣어진 메니페스트를 갖는 것을 권장한다.
DLL이 LoadLibrary 호출로 읽어지는 경우 외부 메니페스트는 무시되어진다.
자세한 내용은 "Assembly manifests"를 참조 바람.

6. 메니페스트에 열거되어진 모든 어셈블리가 컴퓨터에 바르게 인스톨되어져 있는지를 확인한다.
각 어셈블리는 이름, 버젼번호, 및 프로세스 아키텍쳐로 메니페스트에 지정한다. 어플리케이션은 side-by-side 어셈블리에 의존하고 있는 경우 이것들은 어셈블리가 컴퓨터에 적절하게 인스톨되어 오퍼레이팅 시스템 로더로 검출할 수 있는 것을 "Assembly Searching Sequnce"로 지정되어있는 순서를 사용해서 확인한다. 64비트 어셈블리는 32비트 프로세스로 읽어들이거나 32비트 오퍼레이팅 시스템으로 실행할 수 없는 것에 주의한다.

--------------------------------------------------

http://msdn2.microsoft.com/ja-jp/library/ms235342(VS.80).aspx

이 글은 위 글을 번역한 것
이해가 잘 안온다. -.-;;
메니페스트 개념도 잘 모르겠고
밥통같은 Visual C++ 2005는 DLL을 따로 카피해야되는건가?
Posted by 띠리
파일을 암호화 . 복호화하기

윈도우즈 API를 이용하여 파일 암호화하기

#include <io.h>                // 파일관련

#include <WinCrypt.h>        // 암호화


      :

// 암호화 버튼을 클릭했을 때

void CCiperFileDlg::OnBnClickedEncode()

{


    BYTE    *bBuff;

    DWORD    dwFileLen;

    CString    csFile;

    FILE    *pFile;


    m_File.GetWindowText(csFile);


    // 선택한 파일을 바이너리 형식으로 열기

    pFile = fopen(csFile, "rb");

    if(!pFile)

    {

        AfxMessageBox("파일읽을때 에러났어");

        return;

    }


    dwFileLen = _filelength(fileno(pFile));

    bBuff = new BYTE [dwFileLen];


    // 파일 읽어서 버퍼에 저장

    fread(bBuff, 1, dwFileLen, pFile);

    fclose(pFile);


    HCRYPTPROV    hProv;

    HCRYPTHASH    hHash;

    HCRYPTKEY    hKey;

    CString        csPass;


    m_Pass.GetWindowText(csPass);


    // CSP(Crystographic Service Provider) 핸들 얻기

    if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))

    {

        if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))

        {

            AfxMessageBox("암호화 실패야");

            return;

        }

    }


    // 해쉬 만들기

    CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);

    // 해쉬 값 계산

    CryptHashData(hHash, (BYTE*)(LPCTSTR)csPass, csPass.GetLength(), 0);

    // 키 만들기\tab

    CryptDeriveKey(hProv, CALG_RC4, hHash, 0x0080*0x10000, &hKey);

    // 암호화\tab

    CryptEncrypt(hKey, 0, TRUE, 0, bBuff, &dwFileLen, dwFileLen);

    // 해쉬 없애기

    CryptDestroyHash(hHash);

    // CSP 핸들 풀어주기

    CryptReleaseContext(hProv, 0);


    csFile += ".CPR";


    // 파일저장 윈도우 표시

    CFileDialog    fDlg(FALSE, "", csFile);


    if(fDlg.DoModal() == IDOK)

    {

        // 암호화된 파일 저장하기

        pFile = fopen(fDlg.GetPathName(), "wb");

        fwrite(bBuff, 1, dwFileLen, pFile);

        fclose(pFile);

    }


    // 버퍼 삭제

    delete [] bBuff;

}



윈도우즈 API를 이용하여 파일 복호화하기

// 복호화 버튼을 클릭했을 때

void CCiperFileDlg::OnBnClickedDecode()

{

    BYTE    *bBuff;

    DWORD    dwFileLen;

    CString    csFile;

    FILE    *pFile;


    m_File.GetWindowText(csFile);


    // 선택한 파일을 바이너리 형식으로 열기

    pFile = fopen(csFile, "rb");

    if(!pFile)

    {

        AfxMessageBox("파일읽을때 에러났어");

        return;

    }


    dwFileLen = _filelength(fileno(pFile));

    bBuff = new BYTE [dwFileLen];


    // 파일 읽어서 버퍼에 저장

    fread(bBuff, 1, dwFileLen, pFile);

    fclose(pFile);


    HCRYPTPROV    hProv;

    HCRYPTHASH    hHash;

    HCRYPTKEY    hKey;

    CString        csPass;


    m_Pass.GetWindowText(csPass);


    // CSP(Crystographic Service Provider) 핸들 얻기

    if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))

    {

        if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))

        {

            AfxMessageBox("복호화 실패야");

            return;

        }

    }


    // 해쉬 만들기

    CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);

    // 해쉬 값 계산

    CryptHashData(hHash, (BYTE*)(LPCTSTR)csPass, csPass.GetLength(), 0);

    // 키 만들기\tab

    CryptDeriveKey(hProv, CALG_RC4, hHash, 0x0080*0x10000, &hKey);

    // 복호화

    CryptDecrypt(hKey, 0, TRUE, 0, bBuff, &dwFileLen);

    // 해쉬 없애기

    CryptDestroyHash(hHash);

    // CSP 핸들 풀어주기

    CryptReleaseContext(hProv, 0);


    // 파일저장 윈도우 표시

    CFileDialog    fdlg(FALSE, "", csFile);


    if(fdlg.DoModal() == IDOK)

    {

        // 복호화된 파일 저장하기

        pFile = fopen(fdlg.GetPathName(), "wb");

        fwrite(bBuff, 1, dwFileLen, pFile);

        fclose(pFile);

    }


    // 버퍼 삭제

    delete [] bBuff;

}


이 프로젝트는 MFC 응용 프로그램의 다이알로그 형식으로 만들었다.
여기서 텍스트박스나 버튼에 대한 설명은 안한다.

VS2005가 깔려있으면 밑의 집파일을 다운받아서 CiperFile.sln을 더블클릭하여
빌드하면 바로 테스트를 해볼수 있다.

invalid-file

Visual Studio 2005로 만든 프로젝트 파일




Posted by 띠리
msado15.dll을 import하여 MFC로 DLL을 만들때 빌드하면
아래와 같은 형식 재정의 에러가 뜬다.

오류 1 error C2011: 'LockTypeEnum' : 'enum' 형식 재정의 d:\data\source\adll\adll\debug\msado15.tlh 228
오류 2 error C2011: 'DataTypeEnum' : 'enum' 형식 재정의 d:\data\source\adll\adll\debug\msado15.tlh 276
오류 3 error C2011: 'FieldAttributeEnum' : 'enum' 형식 재정의 d:\data\source\adll\adll\debug\msado15.tlh 321
오류 4 error C2011: 'EditModeEnum' : 'enum' 형식 재정의 d:\data\source\adll\adll\debug\msado15.tlh 343
오류 5 error C2011: 'RecordStatusEnum' : 'enum' 형식 재정의 d:\data\source\adll\adll\debug\msado15.tlh 352
오류 6 error C2011: 'ParameterDirectionEnum' : 'enum' 형식 재정의 d:\data\source\adll\adll\debug\msado15.tlh 616
오류 7 error C2065: 'adLockReadOnly' : 선언되지 않은 식별자입니다. d:\data\source\adll\adll\adll.cpp 101

위와 같은 에러가 뜨면 주저말고 stdafx.h 파일에 밑의 코드를 찾는다.

#ifndef _AFX_NO_DAO_SUPPORT

#include <afxdao.h>            // MFC DAO 데이터베이스 클래스입니다.

#endif // _AFX_NO_DAO_SUPPORT


위의 코드를 밑의 코드처럼 커맨트 처리하고 다시 리빌드하면 재정의 에러는 없어진다.
afxdao.h에도 같은 정의가 되어있나보다.

//#ifndef _AFX_NO_DAO_SUPPORT

//#include <afxdao.h>            // MFC DAO 데이터베이스 클래스입니다.

//#endif // _AFX_NO_DAO_SUPPORT






Posted by 띠리
msado15.dll을 이용해서 MFC에서 ADO로 데이테베이스 억세스하기
여기서 데이터베이스는 MySQL을 썼다.
다른 데이터베이스를 쓸때는 접속 문자열을 바꾸어 주면 될 것같다.

예제는 hong 데이터베이스의 animal 테이블의 필드명과
데이터를 직접 실행 창에 출력하는 예제이다.

TRACE함수는 MFC의 함수라는 것을 이번에 처음 알았다. -.-;;


 



#include "stdafx.h"

#include "stdio.h"

#include "io.h"


// ADO DLL 임포트

#import "C:\Program files\Common Files\System\Ado\msado15.dll" no_namespace rename("EOF", "ADOEOF")


int main()

{

    HRESULT    hr;


    // COM 라이브러리 초기화

    CoInitialize(NULL);


    try {


        _ConnectionPtr    pConn;

        _RecordsetPtr    pRs;


        hr = pConn.CreateInstance(__uuidof(Connection));

        hr = pRs.CreateInstance(__uuidof(Recordset));       


        pConn->CursorLocation = adUseClient;


        // MySQL ODBC 접속 문자열

        _bstr_t strConn("DRIVER={MySQL ODBC 3.51 Driver};SERVER = localhost;DATABASE = hong;UID = hong; PWD = hong;");


        // 데이터베이스 접속

        hr = pConn->Open(strConn, "", "", adConnectUnspecified);


        // 레코드셋 설정

        hr = pRs->Open("select * from animal", pConn.GetInterfacePtr(), adOpenForwardOnly, adLockReadOnly, adCmdText);



        _variant_t    vtColumn;

        _variant_t    vtNull;


        vtNull.ChangeType(VT_NULL);


        TCHAR    strDisp[MAX_PATH+1];

        short    i;

        long    nRow = pRs->Fields->Count;    // 레코드수 취득


        // 필드명 표시

        for (i = 0; i < nRow; i++)

        {

            // 필드명 취득

            vtColumn = pRs->Fields->GetItem(i)->Name;


            vtColumn.ChangeType(VT_BSTR);

            lstrcpyn(strDisp, (_bstr_t)vtColumn, MAX_PATH);


            if (i == nRow - 1) {

                TRACE("%s\n", strDisp);

            } else {

                TRACE("%s,", strDisp);

            }

        }


        pRs->MoveFirst();


        // 필드값 표시

        if(!pRs->ADOEOF)

        {

            while(!pRs->ADOEOF)

            {

                for (i = 0; i < nRow; i++)

                {

                    vtColumn = pRs->GetCollect(i);


                    // 데이터가 NULL이면 ""을 대입

                    if (vtColumn == vtNull) {

                        vtColumn = _variant_t("");

                    } else {

                        vtColumn.ChangeType(VT_BSTR);

                    }

                    lstrcpyn( strDisp, (_bstr_t)vtColumn, MAX_PATH );


                    if (i == nRow - 1) {

                        TRACE("%s\n", (LPCSTR)strDisp);

                    } else {

                        TRACE("%s,", (LPCSTR)strDisp);

                    }

                }


                pRs->MoveNext();

            }

        }


        hr = pRs->Close();



    } catch(_com_error &e) {

        _bstr_t bstrSource(e.Source());

        _bstr_t bstrDescription(e.Description());

        printf("Error:%s\n", (LPCSTR) bstrDescription);

    }

}





Posted by 띠리
char에서 CString으로 바꾸기

char에서 CString으로 바꿀때는 아래 소스와 같이
그냥 char 변수의 데이터를 CString 변수에 대입하면 된다.
그러면 CString은 "="연산자를 오버로드하여 실제로는 memcpy를 한다.

        char    szTemp[8] = "TEST!!!";

        CString    csTemp;


        csTemp = szTemp;



CString에서 Char로 바꾸기

그냥 strcpy를 써서 문자열을 카피하면된다.
단 CString에서 char 문자열에 카피할때는
char의 크기가 CString의 크기보다 반드시 커야한다.

그래서 아래와 같이 new를 쓰면 가변적으로 문자열에 카피할 수 있다.
new를 쓸때는 반드시 delete를 해야하는 것을 잊지말자.


        CString    csTemp;

        char*    pszTemp = new char[csTemp.GetLength() + 1];


        strcpy(pszTemp, csTemp);


        delete [] pszTemp;





Posted by 띠리

프로젝트를 단일문서로 만든다.

프로젝트를 안일문서로 만들때, 사용자 인터페이스 기능에서 도구모음에서 없음을 선택한다.
초기상태 표시줄은 필요에 따라 체크를 넣는다.

사용자 삽입 이미지

SDI를 다이얼로그 처럼 쓰기위해서 가장 중요한 작업은 아래 그림의 화면(생선된 클래스)에서 기본 클래스를 CFormView로 선택하는 것이다.

사용자 삽입 이미지


CFormView를 선택하면 리소스에 Dialog에 IDD_SDICTRL_FORM가 생겨 여기에 컨트롤을 추가할 수있다.
이렇게 SDI로 다이얼로그처럼 만들어 쓰면 좋은 것이 크기를 변경할 수 있다는 것이 좋은 것같다.
하기야 다이알로그의 크기가 바뀌며 그 안에 컨트롤들의 바꾸기위해서는 공부를 더 해야겠지만...

그리고 이렇게 프로젝트를 만들면 메뉴가 모이기 때문에 메뉴를 없애기 위해서는 C***App클래스의 InitInstance()함수에서 밑의 노랑색을 추가하면 메뉴가 보이지않게 된다.


BOOL CSDICtrlApp::InitInstance()

{

    // 생략

    // 메뉴를 표시하지않음

    m_pMainWnd->SetMenu(NULL);

    // 창 하나만 초기화되었으므로 이를 표시하고 업데이트합니다.

    m_pMainWnd->ShowWindow(SW_SHOW);

    m_pMainWnd->UpdateWindow();


    return TRUE;

}



Posted by 띠리
BLOG main image
프로그래밍 공부하면서 써가는 개인 노트 (따라서 여기에 씌여있는 소스의 신빙성을 보장 못함 -.-;;) 이 블로그 보면서 틀린 점이 있으면 꼬옥 알려주세요. by 띠리

공지사항

카테고리

분류 전체보기 (323)
Win32 SDK 초보 (27)
통신관련 (11)
MFC TIP (20)
C/C++ TIP (10)
개발기타 (10)
링크 (2)
견물생심 (24)
이것저것 (8)
용어메모 (3)
데이터베이스 (32)
비주얼 베이직 (10)
하드웨어 (3)
C# (42)
Xcode (3)
델파이 (82)
홈페이지 (5)
MindStorm (0)
낙서 (5)
스크래치 (0)
기타 (6)
아두이노 (1)
라즈베리파이 (2)
안드로이드 (6)
파이썬 (0)
WEB (2)
Total : 964,050
Today : 65 Yesterday : 370