빌드 시 에러

"~~~ fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?"

VC++외의 컴파일러에서 빌드하였거나 다른 스타일(obj c같은 경우?)로 작성된 라이브러리를 링크하면 위와 같은 건방지고 친절한(?) 에러가 발생하는 경우가 있다.

빠른 빌드를 위한 PCH (precompiled header)가 없어서 난다는데,

안내문대로 "stdafx.h"를 include 해주거나

project property -> Configuration Properties -> C/C++ -> Precompiled headers -> Create/Use Precompiled header 를
Not Using Precompiled Headers로 바꿔주면 된다.
(그전에는 아마 Use Precompiled Header (/Yu) 로 되어있을 것이다.)
Posted by freezn
개발 중 간혹 에뮬레이터와 ActiveSync를 시키고 싶을 수 있다.

이럴 때 유용한 내용. (아놔.. 나만 몰랐나보다)

ActiveSync의 연결설정에서 허용항목을 "DMA"로 선택하고,
Visual Studio 2005의 Tools -> Device Emulator Manager 에서 해당장치에 Cradle 명령을 준다.

Posted by freezn
Visual Studio 2005에서 Windows CE용 애플리케이션을 개발할 때 소스에는 오류가 없는데도 에러가 발생 할 경우가 있다.

이럴 때 이 놈을 의심 해본다.

기본 스택사이즈가 무려 64KB (65536 Byte)로 되어있다.

부족하다면 늘려주자.



디버그모드로는 잘되는데 릴리즈로 하면 실행하자마자 뻗어서 보니 디버그모드에만 설정해놨던 1인..orz
Posted by freezn

io control 은 장치를 file처럼 다루는 read, write, seek 등으로는 부족함을 느낄 때 사용하는 부분.

귀찮으면 그냥 read/write에 첫바이트는 기능 구분.. 나머지는 데이터... 뭐 이런 무식한 꽁수를 써도 문제는 없을 듯.

대략 초보용.

리눅스의 ioctl과 같은 기능임.

---

디바이스 드라이버

XXX_IOControl() 함수 머리

BOOL XXX_IOControl(
  DWORD dwInst, // 써본 적 없음. ISR handler 의 인스턴스라는데 -_-a
  DWORD dwIoControlCode, // IO Control 코드. 기능들로 분기 시키기 위한 코드.
  LPVOID lpInBuf, // 어플리케이션에서 넘겨주는 데이터 버퍼
  DWORD nInBufSize, // 그 크기
  LPVOID lpOutBuf, // 드라이버가 어플리케이션에게 건네줄 데이터 버퍼
  DWORD nOutBufSize, // 그 크기
  LPDWORD lpBytesReturned // 써본 적 없음. 오류 처리용인가보다 -_-;
)

일단 머리가 저렇게 생겼고 각 파라미터들의 용도는 저렇다. 아직 모르는건? 우짜나 -_-;

XXX_IOControl 함수 내용

 switch(dwIoControlCode)
 {
 case IOCTL_XXX_CMD_A :
  memcpy(myTemp, lpInBuf, nInBufSize);

  break;
 case IOCTL_XXX_CMD_B :
  memcpy(lpOutBuf, myTemp, nOutBufSize);
  break;

 case IOCTL_XXX_CMD_C :
  myFunc();
  break;

 default:
  RETAILMSG(1,(TEXT("XXX : unknown io control code! \n\r")));
  break;

}


보다시피 IOCTL_XXX_CMD_A, IOCTL_XXX_CMD_B, IOCTL_XXX_CMD_C 를 사용했다.

각각
IOCTL_XXX_CMD_A 는 어플리케이션이 주는 데이터를 myTemp 라는 임시공간에 저장하고,
IOCTL_XXX_CMD_B 는 myTemp에 있는 데이터를 어플리케이션에게 건네주는 기능이며,
IOCTL_XXX_CMD_C 는 다 필요없고 그냥 myFunc()라는 함수를 호출한다..

물론 실제 구현은 단순히 메모리를 복사하는 내용으로 끝나진 않겠지만 나머지 부분은 사용자의 목적에 맞게 구현하면 된다.

그럼 대체 이 switch case분기용 IOCTL_XXX_CMD_X 는 어떻게 만든 걸까?
여기서는 CTL_CODE라는 매크로가 사용된다.

CTL_CODE 는
#define CTL_CODE(DeviceType, Function, Method, Access) (
  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
)

이렇게 생겨먹었는데..
이건 각 기능에 대한 고유 ioctl번호를 생성하기 위한 매크로다.
[DeviceType][Access][Function][Method] 형태로 unsigned 4byte 짜리 숫자를 생성한다.
결과물이 어떤 값인지 알아도 좋지만 별로 알 필요는 없다. 매크로는 바뀌거나 바꿀 수도 있으므로 그냥 쓰면 된다.

CTL_CODE(DeviceType, Function, Method, Access) 이다.

DeviceType :
리눅스에서도 비슷한게 있다. 장치에 대한 번호다.
MSDN - CTL_CODE 페이지나 {winceroot}\public\common\oak\inc\windev.h 를 열어보면 명세들이 있다.
FILE_DEVICE_XXX 시리즈가 사용된다.
근데... MSDN을 잘보면 0~0x7FFF 까지는 지네거란다 ㅡ.ㅡ
우리같은 OEM들은 MS규격 장치의 드라이버를 만드는게 아니라면
0x8000 ~ 0xFFFF 를 쓰면 된단다.
저 중에 하나 정하자.

Function :
장치의 기능들에 대한 부분이다. 여기서도 0~0x7FF 는 MS에서 쓸거라니까
0x800 ~ 0xFFF 중에 구현할 장치의 기능 만큼 골라 쓰자 -_-;

Method :
이거 이제 안쓴단다. 무조건 METHOD_BUFFERED 만 쓰란다.
데스크탑용 Windows에서는 좀 다르니까 주의하란다.

Access :
읽기를 할까? FILE_READ_ACCESS
쓰기를 할까? FILE_WRITE_ACCESS
둘다할까? FILE_ANY_ACCESS
복잡하고 별로 무의미하니 걍 FILE_ANY_ACCESS 쓰면 될 것 같다.

그래서 내가 선언한 선언부는 이렇다. (드라이버 소스 시작단에 넣었다.)

#define MYDEVICE 0x8001
#define MYDEVICE_FUNC 0x800
#define IOCTL_XXX_CMD_A  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_B  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_C  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+3, METHOD_BUFFERED, FILE_ANY_ACCESS)


첫번째 DeviceType은 OEM용 장치타입 코드 영역인 0x8000~0xFFFF 중에 0x8001 을 골라썼고 (이건 장치마다)
두번째 Function 역시 OEM용 기능구분 코드 영역 0x800 ~ 0xFFF 에서 순서대로 0x801~0x803를 썼다. (이건 기능마다 달라야한다.)

그럼 이제 CTL_CODE도 만들었고, 드라이버 소스도 작성했으니 어플리케이션으로...

---

어플리케이션

어플리케이션에서도 CTL_CODE를 알아야한다. (저 매크로의 결과값을 옮겨도 되겠지만)
그러니 코드를 생성하는 매크로 부분을 어플리케이션 소스에도 복사한다. (혹은 같은 헤더파일로 공유한다.)

#define MYDEVICE 0x8001
#define MYDEVICE_FUNC 0x800
#define IOCTL_XXX_CMD_A  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_B  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_XXX_CMD_C  CTL_CODE(MYDEVICE, MYDEVICE_FUNC+3, METHOD_BUFFERED, FILE_ANY_ACCESS)

어플리케이션의 헤더에 붙여넣고 자신만만하게 컴파일 시키면
CTL_CODE, METHOD_BUFFERED, FILE_ANY_ACCESS 가 정의된 적 없다고 컴파일러가 외친다.
여기서 나는 PB에서 제공하는 windev.h의 내용을 복사해다 붙여버릴까... 하는 충동을 느꼈지만 (실제로 그렇게 해보기도 했다.)
무식하게 하지 말자고 충동을 억누르고 어플리케이션에서 참조하는 SDK의 헤더를 뒤져봤다. (라고 쓰고 'editplus의 여러파일찾기'라고 읽는다.)

아싸. winioctl.h 에 다~~포함되어있다.
#include <winioctl.h> 을 CTL_CODE 정의부 위에 추가한다.

이제 DeviceIoControl 함수를 사용할 때 가 되었다.

BOOL DeviceIoControl(
  HANDLE hDevice, // 열어놓은 XXX 장치의 핸들
  DWORD dwIoControlCode, // 호출할 CTL_CODE
  LPVOID lpInBuffer, // 드라이버에게 넘겨줄 데이터 버퍼
  DWORD nInBufferSize,  // 그 크기
  LPVOID lpOutBuffer,  // 드라이버에게서 넘겨 받을 데이터 버퍼
  DWORD nOutBufferSize, // 그 크기
  LPDWORD lpBytesReturned, // XXX_IOControl에서의 lpBytesReturned 와 연결되는 놈이다. 난 몰라~~ -_-;
  LPOVERLAPPED lpOverlapped // 무시된다. NULL로 세팅할 것.
);

모양새는 저렇게 생겨먹었고,
사용해보자. (아래의 내용은 위 드라이버의 소스와 맞춰가며 보면 좋다.)

// lpBytesReturned 용이다. 난 안쓰는데 필요로 하길래 지정해줬다. 쳇 -_-;
DWORD bytes;

// IOCTL_XXX_CMD_A 를 호출한다.
// pWritrBuf 의 내용을 pWriteBuf의 크기만큼 드라이버에게 넘겨준다.
// 이 내용은 디바이스 드라이버의 XXX_IOControl 이 받아서,
// IOCTL_XXX_CMD_A 분기로 들어가고,
// myTemp에 여기서 건네주는 pWriteBuf의 데이터를 pWriteBuf의 크기만큼 memcpy하게 된다.
DeviceIoControl(hDev, IOCTL_XXX_CMD_A, pWriteBuf, sizeof(pWriteBuf), NULL, 0, &bytes, NULL);

// IOCTL_XXX_CMD_B 를 호출한다.
// pReadBuf 의 내용을 pReadBuf의 크기만큼 드라이버에게 넘겨준다.
// 이 내용은 디바이스 드라이버의 XXX_IOControl 이 받아서,
// IOCTL_XXX_CMD_B 분기로 들어가고,
// 디바이스 드라이버가 갖고 있던 myTemp의 내용을 pReadBuf에 pReadBuf의 크기만큼 memcpy 해준다.
// 그럼 드라이버에서 값을 가져왔으니 맘대로 쓰면 된다.
DeviceIoControl(hDev, IOCTL_XXX_CMD_B, NULL, 0, pReadBuf, sizeof(pReadBuf), &bytes, NULL);

// IOCTL_XXX_CMD_C 를 호출한다.
// 디바이스드라이버에  데이터 주고 받는 것 없이 명령을 내리는 거다.
// XXX_IOControl의 IOCTL_XXX_CMD_C 분기로 들어가서 myFunc(); 함수를 호출한다.
DeviceIoControl(hDev, IOCTL_XXX_CMD_C, NULL, 0, NULL, 0, &bytes, NULL);

---

이후의 의문

CTL_CODE 매크로 없이 IOControl Code를 0x01, 0x02 뭐 이런식으로 쓰면 안될까?
-> 되더라 -_-a 별 문제 없던데...
그럼 Function Code는?
-> 되더라 -_-a 이것도 별 문제 없던데... 귀찮게 스리 뭘 그리 정의 해놓고 그런건지.. ㅠㅠ
그럼 Method나 Access도 NULL 로 줘버리면?
-> 되더라 -_-a

위 내용으로 미루어봤을 때, CTL_CODE는 정말 단순히 충돌예방을 위해 각기능에 대한 고유번호를 매기는 매크로일 뿐이다.
사실 각 장치를 열어서 호출하는 것이니 만큼 충돌 날 일도 없을 걸로 예상되는데,
디버깅용으로 필요할 것 같다.

그래도 저렇게 하라고 msdn에 적어놨으니 귀찮지만 맞춰서 써주자.

---

- 끝 -

Posted by freezn
익스플로러 외에 브라우져의 접근이 차단되어있거나 세션등으로 막은 경우 헤더조작이 까다로울 수 있습니다.

저 같은 경우 첫페이지에서 세션에 어떤 값을 넣어 첫페이지를 접근한 후 접속한 것이 아닌 사용자를 차단하는 사이트에서 소스를 얻을 필요가 있었는데요.

빨리 테스트해봐야해서 C#으로 웹브라우져 컴포넌트를 동원해서 작업하는 등 별 삽질을 다 했었습니다.

그.런.데

PHP에서 COM을 이용할 수 있는 함수가 있음을 알고 좌절했습니다. OTL

간단히 함수로 정리했습니다.
자... 보시죠(...)


예제 :
function getHTMLSrc( $url ) {
    // alloc COM (IE)
    $ie = new COM("InternetExplorer.Application");
    $ie->Visible = false;

    $ie->Navigate($url);
    while($ie->readyState!=4); // Loading Complete 확인
   
    $srcHTML = $ie->Document->documentElement->outerHTML;

    // free object
    $ie->Quit();
    unset($ie);

    return $srcHTML;
}


필요사항은

PHP5 이상 Windows version.
.Net 컴포넌트는 PHP5 와 .Net runtime.

뭐 결국 윈도우에 PHP5를 깔고 닷넷컴포넌트는 닷넷프레임워크만 깔아주면 된다는 거죠.

VB나 C#에서 사용하는 것이나 진배없는 속성들에 심하게 당황했습니다. PHP개발자들 대단하네요 -_-;;

COM클래스를 사용하게 되면...
MS Word, MS Excel, mdb 을 비롯한 상용 COM등 COM으로 만들어진 대부분의 처리가 가능한 것 같습니다 OTL

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

예전에 써놨던 포스팅을 이사하면서 실수로 날렸었는데 "체리필터"님의 블로그에서 발견하고 역수입 -_-;;

다만 경험상 저렇게 ie object를 가져다 쓰고 해제해버리면 apache를 restart 시킬때까지 다시 살아나질 않았었다.
해서 최대한 해제하지 않고 한번 생성해서 우려먹었던 기억이...
Posted by freezn
관련 함수
OALArgsQuery

관련 구조체
BSP_ARGS

관련 상수
IMAGE_SHARE_ARGS_ 시리즈 : 부트로더와 커널이 공유할 메모리(램) 영역의 주소
BSP_ARGS_QUERY_ 시리즈 : OALArgsQuery 에 넘겨줄 인자. BSP_ARGS 구조체의 내용에서 선택할 항목

버전
Windows Embedded CE 6.0 (R2아님)

----------------
작업 사유:
이더넷 칩셋에 보드마다 고유의 MAC Address 를 부여해야함.
하지만 eep rom이 달려있지 않음. (있어야 하는데 -_-)
사용 중인 플래시는 NAND.

고민1 : '그러면 이더넷 드라이버에 NAND에 엑세스 하는 라이브러리의 내용을 추가해야할까?'
(NOR였다면 별다른 고민을 하지 않았겠지만,)
거부 사유1-1 : '작업할 게 너무 많아진다.'
거부 사유1-2 : '이더넷 드라이버의 최종 사이즈가 너무 커진다.'

고민2 : '그러면 어차피 부트로더에서 세팅하는 mac addr을 바로 커널에게 전달해주면?'
- 오.. 이거 될 것 같다.
- 리눅스에서는 "부트파라미터"로 사용한다고 함.
- 플래시에는 부트로더에서 기록하고 부팅시에 부트로더가 읽어놓은 내용을 커널로 전달하게 된다.

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

작업 내용:
- BSP_ARGS_QUERY_ 시리즈가 있는 헤더파일을 찾아서, 상수 BSP_ARGS_QUERY_ETHMAC 를 추가
- BSP_ARGS 구조체를 찾아서 저장할 내용 변수 추가. (ex. unsigned char   ethMac[6]; )
- OALArgsQuery 함수 구현부를 찾아서 switch case 내용에 BSP_ARGS_QUERY_ETHMAC 항목을 추가.
  case BSP_ARGS_QUERY_ETHMAC:
   pData = &pArgs->ethMac;
- 부트로더 main.c 에서 전역변수 unsigned char g_ethMac; 추가.
   OEMPlatformInit 함수에 g_ethMac = (unsigned char *)OALArgsQuery( BSP_ARGS_QUERY_ETHMAC); 추가
   OEMLaunch 에서 g_ethMac[0]~[5] 에 mac 저장
- 이더넷 드라이버
   #include <bsp_args.h>
   #include <image_cfg.h>
   #include "Oal_args.h"
- init 에서
   = BSP_ARGS *pArgs = (BSP_ARGS*)IMAGE_SHARE_ARGS_UA_START;
   = unsigned char* pMac = (unsigned char*)&pArgs->ethMac;
   = 이더넷 칩의 mac addr 레지스터에 pMac 의 값 기록.

- 끝 -


도움받은 곳 : W.E.E.G. http://cafe.naver.com/wincepro/12019

Posted by freezn
http://blog.naver.com/wizard412.do?Redirect=Log&logNo=140048570456

일단 wizard412님의 방법으로 올리니 간단... (한걸 한참 헤멨다 OTL)

레퍼런스보드에 PowerButton과 인터럽트가 공유되는 문제가 있다...
이더넷 인터럽트를 쓰던 파워버튼 인터럽트를 쓰던 둘중 하나만 된다.

nand에서 부트로더에서 지정한 맥어드레스 사용하도록 수정 중...

작업 끝나면 마저 정리해서 올려야겠다.

이놈에 건 PXA시리즈랑 뭐 이리 다른 건지 -_-;

역시 디버깅은 printf, fprintf, retailmsg 등등이 짱!
Posted by freezn


 BITMAPFILEHEADER bmFileHeader;
 BITMAPINFOHEADER bmInfoHeader;

 // BMP 헤더
 bmFileHeader.bfSize  = sizeof(BITMAPFILEHEADER);
 bmFileHeader.bfType  = 0x4D42;
 bmFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 
 bmInfoHeader.biSize    = sizeof(BITMAPINFOHEADER);
 bmInfoHeader.biWidth   = 320; // 너비
 bmInfoHeader.biHeight   = 240; // 높이
 bmInfoHeader.biPlanes   = 1;
 bmInfoHeader.biBitCount   = 24; // 색상 비트
 bmInfoHeader.biCompression = 0;
 bmInfoHeader.biSizeImage = bmInfoHeader.biWidth * bmInfoHeader.biHeight * (bmInfoHeader.biBitCount/8);

 bmInfoHeader.biXPelsPerMeter = 0;
 bmInfoHeader.biYPelsPerMeter = 0;
 bmInfoHeader.biClrUsed = 0;
 bmInfoHeader.biClrImportant = 0;

 // BMP는 아래에서 위로 저장되는 형식이기 때문에 순서대로 저장하면 뒤집히므로 파일로 저장할 데이터를 뒤집기
 SPixel* rgbTemp = new SPixel[BUFSIZE]; // 파일저장할 데이터를 보관할 임시공간
 for(int i=0; i<BUFSIZE; i++) {
  rgbTemp[i].r = g_rgb[BUFSIZE-1-i].r;
  rgbTemp[i].g = g_rgb[BUFSIZE-1-i].g;
  rgbTemp[i].b = g_rgb[BUFSIZE-1-i].b;
 }

 // 파일로 저장
 CFile file;
 file.Open(_T("파일명"), CFile::modeNoTruncate | CFile::modeCreate | CFile::modeReadWrite );
 file.Write(&bmFileHeader, sizeof(BITMAPFILEHEADER));
 file.Write(&bmInfoHeader, sizeof(BITMAPINFOHEADER));
 file.Write(rgbTemp, bmInfoHeader.biSizeImage);
 file.Close();
 
 delete rgbTemp;

 AfxMessageBox(strFilename + _T("\nwas saved"));

Posted by freezn

void Conv16bit565_TO_24bitRGB(USHORT rgb565, BYTE *r, BYTE *g, BYTE *b)
{
 // 16비트로 RGB를 표현하는 RGB 565에서 R,G,B값을 각각 분리해낸다.
 // 각 비트를보면 다음과 같이 되어있다.
 // RRRRRGGGGGGBBBBB (R: Red, G: Green, B: Blue)

 BYTE red = (rgb565 & 0xF800) >> 11;
 BYTE green = (rgb565 & 0x7E0) >> 5;
 BYTE blue = (rgb565 & 0x1F);

 *r = red << 3;
 *g = green << 2;
 *b = blue << 3;
}

그러므로 24bit -> 16bit -> 24bit 식으로 변환해보면 red, green, blue에서 각각 3,2,3 비트씩 손실이 일어나는 것임을 알 수 있다.
(이렇게 단순히 비트를 죽이는 방법 말고 다른 방법을 쓴다면 조금 더 살릴 수 있을 진 모르겠다.)
RRRRRRRRGGGGGGGGBBBBBBBB 에서
XXXRRRRRXXGGGGGGXXXBBBBB 으로


16bit rgb 555 에서는?

XRRRRRGGGGGBBBBB 이렇게 16bit를 구성 (X는 더미비트)

32bit XRGB 에서는?
XXXXXXXXRRRRRRRRGGGGGGGGBBBBBBBB

Posted by freezn
상황은 AFX DLL 을 사용하는 EXE에서 문자열을 리턴받고 싶을 때 이다.

Want :
// EXE에서 이런 형태로 사용하고 싶었다.
CString str = myDllClass.ToString();
//or... 좀 번거롭지만 이렇게라도 굳이 쓰고 싶었다.
CString str;
myDllClass.ToString(str);

So I Was : (Wrong)
CString ToString()
{
    return _T("merong~");
}
// and
void ToString(CString& str)
{
    str = _T("merong~");
}


이렇게도 해봤는데

릴리즈모드로 빌드한 EXE를 실행시 에러가 나지 않지만 디버그모드로 빌드한 EXE에서는
 
Error on Excute :
dbgheap.c
Line: 1044
Expression : _CrtlsValidHeapPointer(pUserData)
...

뭐 이런 에러가 나더라

찾아보니까 빌드시 DLL 의 CString 과 EXE의 CString 이 다르기 때문(자세한건 에러로 구글링해보면 나온다.) 이라는 결론이 나왔다.

곧 죽어도 CString 을 LPSTR로 변환시켜서 쓰고 싶진 않았던 터라 (그러기 싫어서 굳이 CString 따위를 사용했다)
const 도 여기저기 붙여보는 뻘짓을 했다.

CString 은 묵시적으로 LPCTSTR 로 변환이 가능하지?

그럼 굳이 const 인 LPCTSTR 을 LPSTR로 변환하지 않고도 사용할 수 있는건데...

결국 결론은 간단했다.

Right :
// AFX DLL 에서의 선언:
LPCTSTR ToString() {
    return _T("merong~");
}

// EXE 에서의 사용
CString str = myDllClass.ToString();



만세.

이걸 해결 못해서 하루 종일 낑낑댄 나는.... OTL

오늘의 교훈.
절대로 CString 을 써야만 하는 상황이 아니면 이따위것 쓰지 말자.
Posted by freezn