'As a developer/C/C++'에 해당되는 글 37건

  1. 2018.03.08 MS Service base code
  2. 2013.06.12 side by side 구성 오류
  3. 2013.05.16 디지털서명 정보 읽기
  4. 2013.03.14 TTF Font name table detail - MS
  5. 2013.03.14 TTF font name table parsing
  6. 2013.03.14 FileVersionInfo 정보
  7. 2013.03.11 [STL] 유니코드 저장/읽기
  8. 2013.03.07 lnk2001 __argc
  9. 2013.03.05 STL 유니코드 파일 저장
  10. 2013.01.10 MIDL error: 'annotation'

MS Service base code

https://code.msdn.microsoft.com/windowsapps/CppWindowsService-cacf4948


side by side 구성 오류

sxstrace로 확인

cmd창에서

sxstrace trace -logfile:log.etl

명령으로 로그파일 생성

sxstrace parse -logfile:log.etl -outfile:log.txt

명령으로 로그파일 파싱

디지털서명 정보 읽기

http://www.idrix.fr/Root/Samples/VerifyExeSignature.cpp

한 줄로 되어 있던 소스 정리...

 

/*
* An example of file signature verification using WinTrust API
* Derived from the sample vertrust.cpp in the Platform SDK
*
* Copyright (c) 2009 Mounir IDRASSI . All rights reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
#define _WIN32_WINNT 0x0500
#define WINVER 0x0500
#include
#include
#include
#include
#include
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "Wintrust.lib")
LPTSTR GetCertificateDescription(PCCERT_CONTEXT pCertCtx)
{
 DWORD dwStrType;
 DWORD dwCount;
 LPTSTR szSubjectRDN = NULL;
 dwStrType = CERT_X500_NAME_STR;
 dwCount = CertGetNameString(pCertCtx, CERT_NAME_RDN_TYPE, 0, &dwStrType, NULL, 0);
 if (dwCount)
 {
  szSubjectRDN = (LPTSTR) LocalAlloc(0, dwCount * sizeof(TCHAR));
  CertGetNameString(pCertCtx, CERT_NAME_RDN_TYPE, 0, &dwStrType, szSubjectRDN, dwCount);
 }
 return szSubjectRDN;
}
int _tmain(int argc, _TCHAR* argv[])
{
 GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
 WINTRUST_FILE_INFO sWintrustFileInfo;
 WINTRUST_DATA sWintrustData;
 HRESULT hr;
 if (argc != 2)
 {
  _tprintf(_T("Usage: VerifyExeSignature file_name\n"));
  return -1;
 }
 memset((void*)&sWintrustFileInfo, 0x00, sizeof(WINTRUST_FILE_INFO));
 memset((void*)&sWintrustData, 0x00, sizeof(WINTRUST_DATA));
 sWintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
 sWintrustFileInfo.pcwszFilePath = argv[1];
 sWintrustFileInfo.hFile = NULL;
 sWintrustData.cbStruct = sizeof(WINTRUST_DATA);
 sWintrustData.dwUIChoice = WTD_UI_NONE;
 sWintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
 sWintrustData.dwUnionChoice = WTD_CHOICE_FILE;
 sWintrustData.pFile = &sWintrustFileInfo;
 sWintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
 hr = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);
 if (TRUST_E_NOSIGNATURE == hr)
 {
  _tprintf(_T("No signature found on the file.\n"));
 }
 else if (TRUST_E_BAD_DIGEST == hr)
 {
  _tprintf(_T("The signature of the file is invalid\n"));
 }
 else if (TRUST_E_PROVIDER_UNKNOWN == hr)
 {
  _tprintf(_T("No trust provider on this machine can verify this type of files.\n"));
 }
 else if (S_OK != hr)
 {
  _tprintf(_T("WinVerifyTrust failed with error 0x%.8X\n"), hr);
 }
 else
 {
  _tprintf(_T("File signature is OK.\n"));
  // retreive the signer certificate and display its information
  CRYPT_PROVIDER_DATA const *psProvData = NULL;
  CRYPT_PROVIDER_SGNR *psProvSigner = NULL;
  CRYPT_PROVIDER_CERT *psProvCert = NULL;
  FILETIME localFt;
  SYSTEMTIME sysTime;
  psProvData = WTHelperProvDataFromStateData(sWintrustData.hWVTStateData);
  if (psProvData)
  {
   psProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)psProvData, 0 , FALSE, 0);
   if (psProvSigner)
   {
    FileTimeToLocalFileTime(&psProvSigner->sftVerifyAsOf, &localFt);
    FileTimeToSystemTime(&localFt, &sysTime);
    _tprintf(_T("Signature Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"),
     sysTime.wDay, sysTime.wMonth,sysTime.wYear, sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
    psProvCert = WTHelperGetProvCertFromChain(psProvSigner, 0);
    if (psProvCert)
    {
     LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
     if (szCertDesc)
     {
      _tprintf(_T("File Signer = %s\n"), szCertDesc);
      LocalFree(szCertDesc);
     }
    }
    if (psProvSigner->csCounterSigners)
    {
     _tprintf(_T("\n"));
     // Timestamp information
     FileTimeToLocalFileTime(&psProvSigner->pasCounterSigners[0].sftVerifyAsOf, &localFt);
     FileTimeToSystemTime(&localFt, &sysTime);
     _tprintf(_T("Timestamp Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"),
      sysTime.wDay, sysTime.wMonth,sysTime.wYear, sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
     psProvCert = WTHelperGetProvCertFromChain(&psProvSigner->pasCounterSigners[0], 0);
     if (psProvCert)
     {
      LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
      if (szCertDesc)
      {
       _tprintf(_T("Timestamp Signer = %s\n"), szCertDesc);
       LocalFree(szCertDesc);
      }
     }
    }
   }
  }
 }
 sWintrustData.dwUIChoice = WTD_UI_NONE;
 sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
 WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);
 return 0;
}

TTF Font name table detail - MS

TTF font name table parsing

FileVersionInfo 정보

[STL] 유니코드 저장/읽기

저장

wofstream 을 사용해 유니코드 문자열 저장시 멀티바이트로 컨버팅이 발생한다.(디폴트)

왜 컨버팅을 하는지는

http://stackoverflow.com/questions/1509277/why-does-wide-file-stream-in-c-narrow-written-data-by-default/

를 참조해 보면 되겠고 (명확한 답은 없지만 생각해 볼 여지는 있음)

컨버팅을 원하지 않으면

class Unicodecvt : public std::codecvt<wchar_t, char, mbstate_t>
{
protected:
	virtual bool do_always_noconv() const
	{
		return true;
	}
};


};

클래스를 정의해 놓고 아래처럼 wof에 속성을 추가로 부여한다.

std::ios_base::binary 옵션을 꼭 지정하자!

std::wofstream wof(szPath, std::ios_base::binary);
wof.imbue( std::locale(std::locale(""), new Unicodecvt) );
if( wof.is_open() )
{
	wof << WCHAR(0xFEFF);
	wof << WriteBuffer...;
	wof.close();
}

결과를 보면 유니코드로 변환없이 저장이 되어있다.

 

읽기

유니코드 파일을 wifstream 을 통해 읽으면 문자열 버퍼를 멀티바이트로 인식해 유니코드로 변환이 일어난다.

쓰기와 마찬가지로 변환 옵션을 꺼 주고 바이너리 형태로 읽어야 한다.

std::wifstream in_stream(szPath, std::ios_base::binary);
in_stream.imbue( std::locale(std::locale(""), new Unicodecvt) );
if(!in_stream)
{
     // err
}
std::wstring strBuf;
if( in_stream.is_open() )
{
     in_stream.seekg(2);
     while( !in_stream.eof() )
     {
        WCHAR buf[2048] = {0,};
        in_stream.getline((WCHAR*)buf, _countof(buf));
        // output buf
     }
     in_stream.close();
}

 

참조

http://golbenge.wordpress.com/2009/12/24/stl%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-unicode-%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%8C%8C%EC%9D%BC-%EC%B6%9C%EB%A0%A5/

 

 

추가

vs2013 에서는 오류가 난다.

new 대신 ::new 사용..

http://stackoverflow.com/questions/9538114/utf-8-locale-in-visual-c-2010

lnk2001 __argc

외부 라이브러리 사용중 libcmtd.lib 충돌 발생하여 해당 라이브러리 무시 후 발생

디버그 모드는 라이브러리 무시 제거하고 공유DLL로 컴파일 후 해결.

릴리즈 모드는 그냥 충돌 라이브러리 무시 후 정적DLL 컴파일

그리고 메인 헤더에

_CRTIMP int __argc;
_CRTIMP char** __argv;
_CRTIMP wchar_t** __wargv;

p.s. lib 런타임 라이브러리, lib 가져다 쓰는 프로젝트 런타임 라이브러리 동일한지 까먹지 말자!!

STL 유니코드 파일 저장

http://blog.naver.com/PostView.nhn?blogId=ships95&logNo=120102532486

 

아무리 훌륭한 디버거가 있더라도 모든 경우에 디버거를 사용할 수 있는 것은 아닙니다. 특히 윈도우 서비스를 만들 때에는 디버거를 사용하기 꽤 까다롭죠? 한 가지 방법이 있다면 서비스 프로세스가 생성된 다음에 디버거에 연결해서 디버깅할 수 있는데 만일 프로세스 생성과정에서 일어나는 것에 대한 디버깅은 역시 어렵게 됩니다. 이럴 때 보통 이벤트 뷰어를 사용하게 되는데 개발 과정에서 이벤트를 뷰어를 사용하는 것도 여간 번거로운 일이 아닙니다. 보통 이런 상황에서는 원시적이긴 하지만 로그 파일을 사용하는 것이 일반적이 방법입니다.
최근 다국어 환경을 염두해 두고 개발을 하고 있는데 로그 파일을 시스템에 독립적인 유니코드를 사용하면 다국화 환경을 지원하는 데 좀 더 편리하겠다는 생각에 프로그램 내부 문자열을 모두 wchar_t를 사용하여 유니코드로 변경하고 STL의 wfstream(또는 wofstream)을 사용하여 로그 파일을 출력하려고 했습니다. 하지만 STL의 wfstream이 기본적으로 wchar_t형의 문자열을 유니코드로 출력을 하지 않는다는 것이 이제야 알게 되었습니다. 표준화는 접어 두고라도 출력 연산자(<<)의 유혹에 wfstream으로 유니코드 출력하는 방법을 알아 보게 되었습니다.

STL의 입출력 스트림(Input/Output Stream)을 통한 입출력 방식은 시스템에 설정된 언어 문화적 환경에 의해 방식이 바뀌게 되어 있습니다. 예를 들어 한국어를 사용하는 환경에서 날짜는 주로 “2009년 12월 12일 토요일”로 표기하지만, 영어를 사용하는 환경에서는 주로 “Tuesday, December 15, 2009″라고 표기합니다. 이런 언어 문화적 환경을 결정하는 것을 로켈(locale)이라고 합니다.
이러한 로켈은 숫자(Numeric), 시간/날짜(Time/Date), 화폐(Monetary), 문자(Character Type), 문자열 비교(Collation), 메시지(Message) 등 여섯 개 범주로 언어 환경을 지정하게 됩니다. 이 여섯 개의 범주는 다시 패싯(Facet)이라는 것을 통해 실제 구현됩니다. 이제 프로그래머는 응용 프로그램에서 사용할 여섯 개의 범주의 패싯을 로켈에 설정하고 이 로켈을 입출력 스트림에 적용하면 프로그램 내부와 외부 사이의 입출력을 제어할 수 있게 되는 것입니다. 입출력 스트림, 로켈, 패싯의 관계를 그림으로 보면 다음과 같습니다.

패싯 작성, 로케일의 생성 및 입출력 스트림에 적용하는 방법은 어렵지 않으니 STL 문서를 참고하시기 바랍니다. (그렇다고 그다지 쉬운 것은 아닙니다. ^^)
제가 관심있는 부분은 유니코드를 출력하는 부분인데 이 부분은 문자 범주에 속합니다. 문자 관련 언어 환경이란 대소문자, 숫자, 부호 등을 구분하는 방식과 문자의 이진수 표현 방식 즉 문자 부호화 또는 인코딩(Character Encoding)을 지정하는 것입니다. 유니코드라는 것이 문자열을 이진수로 표현하는 인코딩 방법이기 때문에 문자 인코딩 관련 패싯을 잘 만들어서 로켈에 적용하고 이를 입출력 스트림에 적용하면 되는 것입니다.
다행인 것은 현재 개발 중에 있는 대부분(사실 모든) 프로젝트는 프로그램 내부에서는 유니코드를 사용하고 있기 때문에 내부 인코딩 상태를 그대로 내보내는 패싯을 만들기만 하면 된다는 것입니다. 즉 아무런 변환 없이 그대로 내보내면 된다는 것입니다. 앞서 이야기한 대로 STL에 기본 구현된 codecvt 패싯은 wchar_t를 다중 바이트 문자열로 변환을 하도록 되어 있어 유니코드 문자열을 그대로 출력할 수 없는 것입니다.
인코딩 패싯을 처음부터 만들려면 인코딩 구현뿐만 아니라 패싯이 가져야 할 다양한 기능을 구현해야 하는데 쉬운 일이 아닙니다. 따라서, STL이 기본적으로 구현해 놓은 codecvt를 적절히 확장해서 쉽게 구현할 수 있습니다.
아래 예는 비주얼 C++과 함께 제공되는 STL codecvt를 사용하였지만 다른 STL 구현도 크게 차이가 없을 것으로 보입니다.

1 class Unicodecvt : public std::codecvt<wchar_t, char, mbstate_t>
2 {
3 protected:
4 virtual bool do_always_noconv() const
5 {
6 return true;
7 }
8 };

위의 Unicodecvt는 사실은 유니코드로 변환하는 패싯이 아니라 wchar_t를 아무 변환없이 출력하는 패싯이기 때문에 진정한 의미의 유니코드 패싯이라고 할 수 없지만 앞서 언급한 것처럼 내부 코드를 유니코드를 사용하고 있다면 가장 간단히 구현할 수 있는 패싯이라고 생각됩니다. 이 패싯을 이용해서 유니코드로 출력하는 예는 아래와 같습니다.

01 #include <fstream>
02 void main(void)
03 {
04 std::wofstream log(L"test.log", std::ios_base::binary);
05 log.imbue(std::locale(std::locale(""), new Unicodecvt));
06 wchar_t* msg = L"오류가 발생했습니다.";
07 int error_no = 1;
08 log << wchar_t(0xFEFF);
09 log << msg << L" 오류번호: " << error_no << std::endl;
10 }

위의 예에서 4번째 줄에 std::ios_base::binary를 사용한 이유는 앞에서 정의한 Unicodecvt를 사용하게 되면 fstream<< 연산자가 wchar_t형의 문자를 출력할 때 내부적으로 fputwc라는 C 표준 함수를 사용하는데 이 함수가 파일을 일반 모드로 파일을 열게 되면 오류를 발생시키기 때문입니다. 다른 STL 구현에서는 어떻게 되는지 아직 확인하지 못했습니다. 또한 8번째 줄에 0xFEFF를 파일 처음에 출력(파일에는 FFFE 순으로 저장됨)하는데 이것을 바이트 순서 표시(Byte Order Mark, BOM)라고 합니다. 이것은 파일이 16바이트 유니코드 인코딩을 사용해 만들어졌다는 것을 의미하는 것으로 메모장과 같은 대부분의 텍스트 파일 편집기가 이것을 해석하여 파일의 내용을 옳바르게 보여주게 됩니다.

비주얼 C++의 STL을 사용해서 유니코드 텍스트 파일 출력에 대해서 간단히 알아봤는데 C++의 표준 입출력 스트림의 국제화에 대한 좀 더 자세한 내용은 니콜라이 조슈티스(Nicolai M. Josuttis)The C++ Standard Library14장 국제화(Chapter 14 Internationalization)을 참고하시기 바랍니다.

MIDL error: 'annotation'

MIDL error: 'annotation'

에러 발생할 경우 MIDL의 SDK 헤더파일하고 실행파일 버전이 맞지 않아서 발생한 문제임

VS 디렉토리 설정에서 Include 폴더만 SDK 보게 하지 말고 실행파일도 SDK의 bin 파일 보도록 수정

 

http://blogs.msdn.com/b/mikewasson/archive/2006/10/02/midl-error_3a00_-_2700_annotation_2700_.aspx

prev 1 2 3 4 next