2010년 11월 25일 목요일

File version resource

/// 버전 리소스 사이즈 얻기

DWORD dwHandle = 0;

DWORD dwSize = ::GetFileVersionInfoSize(szFilePath, &dwHandle);

 

/// 버전 리소스 정보 얻기

LPBYTE lpBuffer = new BYTE[dwSize];

::ZeroMemoty(lpBuffer, dwSize);

::GetFileVersionInfo(szFilePath, 0, dwSize, lpBuffer);

 

/// 리소스 핸들 얻기

HANDLE hResource = ::BeginUpdateResource(szFilePath, FALSE);

 

/// 리소스 정보 갱신

::UpdateResource(hResource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), wTanslationL/*LCID*/, lpBuffer, dwSize);

 

::EndUpdateResource(hResource, FALSE);

 

/// 버전 스트링 정보 읽기

::VerQueryValue(lpVSVersionInfo, szPath, &lpInfo/*out*/, &dwInfoLen/*out*/)

CString strData = (TCHAR*)lpInfo;

 

/// Translate code 구성

LCID, Code Page

lcid 와 code page 를 이용해 스트링 정보의 주소를 추출한다.

 

정보를 읽을때는 API 를 이용하여 읽기가 가능하지만 버전 정보의 추가 삭제 변경을 위해서는

데이터의 앞에 자신이 가진 Value의 길이 값이 들어가기 때문에 버퍼 클래스가 필요하다.

 

버퍼클래스는 아래의 코드에서 vs_version.h 부분 을 참고 하면 된다.

http://www.codeproject.com/KB/install/VerPatch.aspx 

2010년 11월 23일 화요일

strsafe.h

펌) http://www.jiniya.net/lecture/techbox/strsafe.html

 

C언어 표준에 포함된 문자열 함수들 중에 일부는 매우 위험하다. 대표적인 함수가 strcpy와 sprintf함수다. 이 두 함수의 경우 출력 값으로 문자열 포인터를 전송한다. 하지만 출력 문자열 포인터의 크기를 입력 받지 않기 때문에 버퍼 오버런의 위험을 가지고 있다. 버퍼 오버런의 경우 보안상 취약점이 될 수 있다. 따라서 견고한 프로그램을 작성하기 위해서는 되도록 이 함수들을 사용하지 않는 것이 좋다.

버퍼 오버런

버퍼 오버런이란 프로그램 내부에서 사용하는 메모리 공간을 프로그래머가 기존에 의도했던 것을 넘어서서 덮어 쓰는 것을 말한다. 스택 공간을 침범하는 것을 스택 오버런, 힙 공간을 침범하는 것을 힙 오버런이라 한다. 아래 코드는 어떻게 스택 오버런이 발생하는 지 보여준다.

  1. TCHAR   *src = TEXT("123456789");  
  2. TCHAR   dest[5];  
  3. _tcscpy(dest, src);  

위의 코드를 살펴보면 dest는 최대 4글자를 저장할 수 있다. 왜냐하면 C언어의 경우 끝을 알리기 위해서 NULL 종료 문자를 사용하기 때문이다. 하지만 실제로 복사를 하고자 하는 소스 문자열은 4글자보다 큰 문자다. 따라서 프로그래머가 잡아둔 메모리 공간을 침범해서 덮어쓰게 된다. 이렇게 될 경우 스택이 깨지고 코드가 엉뚱한 곳으로 리턴되는 결과를 만들 수 있다.

Windows에서는 이러한 보안상 취약한 함수들을 대체할 새로운 안전한 함수들을 작성해서 Platform SDK를 통해서 배포하고 있다. 이 함수들은 strsafe.h에 들어있다. 우선 간략하게 어떠한 함수들이 들어 있는지 살펴보도록 하자.

기존함수 대체 함수
strcpy StringCbCopy, StringCbCopyEx
StringCchCopy, StringCchCopyEx
strncpy StringCbCopyN, StringCbCopyNEx
StringCchCopyN, StringCchCopyNEx
strcat StringCbCat, StringCbCatEx
StringCchCat, StringCchCatEx
strncat StringCbCatN, StringCbCatNEx
StringCchCatN, StringCchCatNEx
sprintf StringCbPrintf, StringCbPrintfEx
StringCchPrintf, StringCchPrintfEx
vsprintf StringCbVPrintf, StringCbVPrintfEx
StringCchVPrintf, StringCchVPrintfEx
gets StringCbGets, StringCbGetsEx
StringCchGets, StringCchGetsEx
strlen StringCbLength
StringCchLength

함수 이름이 규칙적으로 지어진 덕분에 함수의 종류를 한눈에 파악할 수 있다. 전체적으로 을 네 가지 종류의 함수가 있다. Cb, Cch계열과 일반 함수와 Ex 함수가 그것이다. Cb계열의 함수는 버퍼 크기를 인자로 받는다. 즉, 버퍼가 몇 바이트 크기를 가지느냐 하는 것을 기준으로 삼는다. 반면에 Cch계열 함수들은 버퍼의 길이를 인자로 받는다. 몇 글자를 저장할 수 있느냐 하는 것을 기준으로 삼는다. Ex 함수는 일반 함수의 기능에 버퍼의 잘림과 패딩을 다루는 추가적인 기능을 가진 함수들이다.

일반 함수의 경우 표준 함수와 동일한 인자를 받도록 되어 있다. 단지 추가적으로 버퍼의 크기를 하나 더 받는다. 따라서 여기서는 StringCbCopy와 StringCchPrintf의 사용법만 살펴보도록 하겠다. 다른 함수들의 자세한 사용방법을 알고 싶다면 MSDN을 참고하도록 하자.

  1. HRESULT StringCbCopy(        
  2.     LPTSTR pszDest,  
  3.     size_t cbDest,  
  4.     LPCTSTR pszSrc  
  5. );  

StringCbCopy 함수의 원형이다. 이 함수는 strcpy와 동일한 기능을 한다. pszDest에는 복사될 버퍼 포인터를, cbDest에는 pszDest의 크기를, 그리고 pszSrc에는 복사할 문자열 포인터를 넣어주면 된다. cbDest를 제외하면 strcpy와 동일한 의미의 인자가 순서대로 입력된다는 것을 알 수 있다. 결과 값은 함수의 성공 여부다. 성공한 경우 S_OK를 리턴 한다. 위에 나열된 모든 String계열 함수의 리턴 값은 HRESULT다. COM에 사용되는 것과 동일한 타입이기 때문에 FAILED, SUCCEEDED매크로를 사용하면 손쉽게 에러 여부를 체크할 수 있다. StringCbCopy함수를 사용해 간단한 문자열을 복사하는 과정은 아래와 같다.

  1. TCHAR dest[6];  
  2. TCHAR *src = "Hello World!";  
  3.  
  4. if(FAILED(StringCbCopy(dest, sizeof(dest), src)))  
  5.     printf(TEXT("실패\n"));  
  6.  
  7. printf(dest);  

위의 코드를 실행해 보면 왜 StringCbCopy가 안전한지를 알 수 있다. 위 프로그램을 실행하면 dest값으로 Hello가 출력된다. 왜냐하면 dest의 크기인 6이 StringCbCopy함수 내부로 들어갔기 때문에 거기까지만 복사가 진행된 것이다. 더 이상 복사할 경우 버퍼 오버런이 발생하기 때문이다.

  1. HRESULT StringCchPrintf(  
  2.     LPTSTR pszDest,  
  3.     size_t cchDest,  
  4.     LPCTSTR pszFormat,  
  5.      ...  
  6. );  

StringCbPrintf 함수의 원형이다. 이 함수는 sprintf와 동일한 기능을 한다. pszDest에는 출력될 버퍼를, cchDest에는 pszDest에 저장할 수 있는 글자 수를, 끝으로 pszFormat에는 포맷 문자열을 넣으면 된다. 아래와 같이 사용할 수 있다.

  1. TCHAR buffer[MAX_PATH];  
  2. StringCchPrintf(buffer, MAX_PATH, "%s", TEXT("Hello World"));  

문자열을 다루는 일은 프로그래밍 과정에서 광범위 하게 사용된다. 일부 프로그램은 문자열 처리 과정이 프로그램의 전부이기도 하다. 이처럼 문자열 처리 작업은 많이 사용되는 만큼 가장 많은 버그와 보안 허점이 나오는 곳이기도 하다. 이러한 문제를 해결하는 가장 좋은 방법은 기존의 불완전한 함수들을 사용하지 않는 것이다. 이런 이유 때문에 strsafe.h를 프로젝트에 포함시키게 되면 표준 문자열 함수를 사용하는 부분에서는 deprecated 경고가 발생한다. 하지만 deprecated 경고를 강제로 무시하고 싶은 상황도 있다. 어쩔 수 없이 써야 하는 라이브러리 코드 등에서 표준 문자열 함수를 사용한 경우가 대표적이다. 이럴 때 경고를 강제로 끄기 위해서는 strsafe.h를 포함시키는 부분 앞에 STRSAFE_DEPRECATE를 정의해주면 된다. 아래와 같이 include를 시키면 표준 문자열 함수에 대한 경고가 발생하지 않는다.

  1. #define STRSAFE_DEPRECATE  
  2. #include <strsafe.h> 

String 계열의 함수가 안전하고 좋은 것임은 사실이다. 하지만 기존의 ANSI C/C++ 의 표준 문자열 함수들로 작성된 프로젝트를 String 계열의 함수로 교체하는 작업은 신중하게 결정해야 한다. 언뜻 보기에는 함수명을 바꾸는 간단한 작업처럼 보이지만 실상은 그렇지 않다. 기존 라이브러리 함수들을 사용하는 대부분의 코드의 경우 함수로 출력 버퍼의 크기를 전송하지 않기 때문에 호출하는 쪽과 함수 코드를 전체적으로 수정해야 한다. 이런 이유로 대부분의 경우 String계열로 코드를 고침으로써 얻는 보안 효과보다 더 많은 버그가 수정 도중에 발생한다. 따라서 기존의 프로젝트 코드를 변경하는 일은 신중히 검토한 후 결정하도록 하자.

말은 쓰는 사람의 혼을 담는 그릇이라고 한다. 이와 마찬가지로 코드는 프로그래머의 혼을 담는 그릇이 될 수 있다. 앞으로 새롭게 작성하는 프로젝트에는 안전한 문자열 함수를 쓰고 문자열 포인터가 전달되는 곳으로는 항상 크기를 같이 전달하도록 하자. 이보다 좀 더 좋은 방법은 되도록 직접적인 문자열 포인터의 사용을 줄이고 string이나 CString등의 C++ 클래스를 사용하는 것이다.

2010년 11월 22일 월요일

Operator Keyword for ~

Operator ~ 는 자료형의 최대값을 기준으로

값을 반전 시켜준다.

 

예를 들어

USHORT wSource = 0xFFFF;

wSource = ~wSource ;

 

이렇게 하였을때 Operator~ 를 적용하기 전인 wSource 의 값이 최대값 65535이기 때문에

현재 wSource 의 값은 0 이다.

 

다시 이야기 하면 wSource + ~wSource 의 값은 자료형의 최대값이다.

 

2010년 11월 14일 일요일

FileExist

BOOL FileExist(LPCTSTR lpszFileName)
{
 HANDLE hFile = CreateFile(lpszFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
 
 if(hFile != INVALID_HANDLE_VALUE)
 {
  CloseHandle(hFile);
  return TRUE;
 }

 return FALSE;
}

파일 버전 정보

펌) http://psmon.x-y.net/maniwiki/doku.php

기타 파일 버전 관련 소스) http://www.codeproject.com/KB/install/VerPatch.aspx

MSDN)

http://msdn.microsoft.com/en-us/library/ms647003.aspx :: GetFileVersionInfo

http://msdn.microsoft.com/en-us/library/ms647005(VS.85).aspx :: GetFileVersionInfoSize

http://msdn.microsoft.com/en-us/library/ms647464(VS.85).aspx :: VerQueryValue

http://msdn.microsoft.com/en-us/library/ms646997.aspx :: VS_FIXEDFILEINFO

http://msdn.microsoft.com/en-us/library/ms647001(VS.85).aspx :: VS_VERSIONINFO

 

 

#pragma once


#include <Version.h>
#pragma comment(lib,"version")

struct VS_VERSIONINFO
{
 WORD                wLength;
 WORD                wValueLength;
 WORD                wType;
 WCHAR               szKey[1];
 WORD                wPadding1[1];
 VS_FIXEDFILEINFO    Value;
 WORD                wPadding2[1];
 WORD                wChildren[1];
};

struct
{
 WORD wLanguage;
 WORD wCodePage;
} *lpTranslate;


struct Vs_info
{
 DWORD high;
 DWORD low;

};

void CreschangerDlg::SetVersionInfo(char *cfilename,char *cfileversion,char *cproductversion,char *ccomment)
{
 UpdateData(TRUE);

 PS_PRJINFO edit_one;
 edit_one.exefullname = cfilename;
 edit_one.fileversion=cfileversion;
 edit_one.productversion=cproductversion;
 edit_one.comment=ccomment;
 edit_one.filename=m_strFileName.GetBuffer(0);

 m_prj.EditPrj(&edit_one);


 //버젼 유효성검사
 if(false == validversiondata(PVER_FILEVERSION,cfileversion) )
 {
  MessageBox(m_verLastError);
  return;

 }


 if(false == validversiondata(PVER_PRODUCTVERSION,cproductversion) )
 {
  MessageBox(m_verLastError);
  return;

 }


 if(false == validversiondata(PVER_COMMENT,ccomment) )
 {
  MessageBox(m_verLastError);
  return;

 }

 

 VS_VERSIONINFO      *pVerInfo;

 

 LPBYTE     pOffsetBytes;
 VS_FIXEDFILEINFO    *pFixedInfo;
 LPCTSTR     lpszFile = _T(cfilename);

 DWORD     dwHandle, dwSize, dwResult = 0 ;


 LPBYTE lpBuffer;

 // determine the size of the resource information
 dwSize = GetFileVersionInfoSize(lpszFile, &dwHandle);
 if (0 < dwSize)
 {
  lpBuffer = new BYTE[dwSize];

  memset(lpBuffer,0,dwSize);

  if (GetFileVersionInfo(lpszFile, 0, dwSize, lpBuffer) != FALSE)
  {
   // these macros help to align on r-byte boundaries (thanks Ted Peck)
#define roundoffs(a,b,r) (((BYTE *) (b) - (BYTE *) (a) + ((r) - 1)) & ~((r) - 1))
#define roundpos(a,b,r) (((BYTE *) (a)) + roundoffs(a,b,r))

   // 'point to' the start of the version information block
   pVerInfo = (VS_VERSIONINFO *) lpBuffer;

   // the fixed section starts right after the 'VS_VERSION_INFO' string
   pOffsetBytes = (BYTE *) &pVerInfo->szKey[16];

   //int x = _tcslen((char*)pVerInfo->szKey);


   pFixedInfo = (VS_FIXEDFILEINFO *) roundpos(pVerInfo, pOffsetBytes, 4);

   // increment the numbers!


   int left = 0;
   int right = 0;

 

   left = GetDigtFromVerString(cfileversion,0);
   right = GetDigtFromVerString(cfileversion,1);
   pFixedInfo->dwFileVersionMS    = (0x00010000 * left) + (0x00000001 * right);

   left = GetDigtFromVerString(cfileversion,2);
   right = GetDigtFromVerString(cfileversion,3);
   pFixedInfo->dwFileVersionLS    = (0x00010000 * left) + (0x00000001 * right);

 

   left = GetDigtFromVerString(cproductversion,0);
   right = GetDigtFromVerString(cproductversion,1);
   pFixedInfo->dwProductVersionMS = (0x00010000 * left) + (0x00000001 * right);


   left = GetDigtFromVerString(cproductversion,2);
   right = GetDigtFromVerString(cproductversion,3);
   pFixedInfo->dwProductVersionLS = (0x00010000 * left) + (0x00000001 * right);

 


   LPVOID lpInfo;
   UINT  unInfoLen;

   if (VerQueryValue(lpBuffer, _T("\\"), &lpInfo, &unInfoLen))
   {
    //ASSERT(unInfoLen == sizeof(m_FileInfo));
    //if (unInfoLen == sizeof(m_FileInfo))
    // memcpy(&m_FileInfo, lpInfo, unInfoLen);
   }

   // find best matching language and codepage
   VerQueryValue(lpBuffer, _T("\\VarFileInfo\\Translation"), &lpInfo, &unInfoLen);

   DWORD dwLangCode = 0;

 

   if (GetTranslationId(lpInfo, unInfoLen, MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL), dwLangCode, TRUE))
    dwLangCode = *((DWORD*)lpInfo);

   if(dwLangCode < 1 )
   {
    MessageBox("영문버젼정보가 있질않습니다. 리소스의 국가설정을 확인하세요!");
    delete [] lpBuffer;
    return;

   }

 


   CString m_strProductName;
   CString strSubBlock;

 

   HANDLE hResource = BeginUpdateResource(lpszFile, FALSE);
   if (NULL != hResource)
   {
    UINT uTemp;

    wchar_t tt[128];

 

    char xx[128];    

    char* w_version;
    w_version= new char[dwSize];

    for(int i=0;i<dwSize;i++)
    {
     w_version[i] = lpBuffer[i];

    }


    bool  is_lenok = true;

    LPVOID p_fileVer;

    memset(&tt[0],0,sizeof(wchar_t) * 128 );
    p_fileVer = SearchText(w_version,"FileVersion",dwSize);
    strcpy(xx,cfileversion);
    for(int i=0;i<strlen(xx);i++)
    {
     tt[i]=std::wcout.widen(xx[i]);

    }
    strSubBlock.Format(_T("\\StringFileInfo\\%04X%04X\\FileVersion"), dwLangCode&0x0000FFFF, (dwLangCode&0xFFFF0000)>>16);
    if (VerQueryValue(lpBuffer, (LPTSTR)(LPCTSTR)(strSubBlock), (LPVOID *) &pValueBuffer, &unInfoLen))
    {

     m_strProductName = CString((LPCTSTR)pValueBuffer);

     if(strlen(xx) <= m_strProductName.GetLength())
     {
      ZeroMemory(p_fileVer, m_strProductName.GetLength() * sizeof(wchar_t));
      wcscpy((wchar_t*)p_fileVer,   &tt[0] );

     }
     else
     {
      is_lenok =false;

     }

    }
    else
    {
     is_lenok =false;

    }


    memset(&tt[0],0,sizeof(wchar_t) * 128 );
    p_fileVer = SearchText(w_version,"ProductVersion",dwSize);
    strcpy(xx,cproductversion);
    for(int i=0;i<strlen(xx);i++)
    {
     tt[i]=std::wcout.widen(xx[i]);

    }
    strSubBlock.Format(_T("\\StringFileInfo\\%04X%04X\\ProductVersion"), dwLangCode&0x0000FFFF, (dwLangCode&0xFFFF0000)>>16);
    if (VerQueryValue(lpBuffer, (LPTSTR)(LPCTSTR)(strSubBlock), (LPVOID *) &pValueBuffer, &unInfoLen))
    {

     m_strProductName = CString((LPCTSTR)pValueBuffer);

     if(strlen(xx) <= m_strProductName.GetLength())
     {
      ZeroMemory(p_fileVer, m_strProductName.GetLength() * sizeof(wchar_t));
      wcscpy((wchar_t*)p_fileVer,   &tt[0] );

     }
     else
     {
      is_lenok =false;

     }

    }
    else
    {
     is_lenok =false;

    }

 

    memset(&tt[0],0,sizeof(wchar_t) * 128 );
    p_fileVer = SearchText(w_version,"Comments",dwSize);
    strcpy(xx,ccomment);
    for(int i=0;i<strlen(xx);i++)
    {
     tt[i]=std::wcout.widen(xx[i]);

    }
    strSubBlock.Format(_T("\\StringFileInfo\\%04X%04X\\Comments"), dwLangCode&0x0000FFFF, (dwLangCode&0xFFFF0000)>>16);
    if (VerQueryValue(lpBuffer, (LPTSTR)(LPCTSTR)(strSubBlock), (LPVOID *) &pValueBuffer, &unInfoLen))
    {

     m_strProductName = CString((LPCTSTR)pValueBuffer);

     if(strlen(xx) <= m_strProductName.GetLength())
     {
      ZeroMemory(p_fileVer, m_strProductName.GetLength() * sizeof(wchar_t));
      wcscpy((wchar_t*)p_fileVer,   &tt[0] );

     }
     else
     {
      is_lenok =false;

     }

    }
    else
    {
     is_lenok =false;

    }

 


    memcpy(lpBuffer,w_version,dwSize); 
    delete [] w_version;


    if(!is_lenok)
    {
     delete [] lpBuffer;
     MessageBox("바꾸려는 버젼정보문자열이, Original버젼의 문자열길이를 초과하거나 없습니다..");
     return;

    }


    // could probably just use LANG_NEUTRAL/SUBLANG_NEUTRAL
    if (UpdateResource(hResource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), dwLangCode&0x0000FFFF, lpBuffer, dwSize) != FALSE)    
    {
     // 언어한글 강제..업데이트
     //UpdateResource(hResource, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), 1042, lpBuffer, dwSize);

     if (EndUpdateResource(hResource, FALSE) == FALSE)
      dwResult = GetLastError();
    }
    else
     dwResult = GetLastError();

 


   }
   else
    dwResult = GetLastError();


   delete [] lpBuffer;

  }
  else
  {
   dwResult = GetLastError();
   delete [] lpBuffer;
  }
 }
 else
  dwResult = GetLastError();


 if(dwResult != 0)
 {
  sprintf(m_verLastError,"VerChanger Failed Reason:%d",dwResult);
  MessageBox(m_verLastError);
 }
 else
 {
  MessageBox("버젼업이 성공했습니다.");

 }

 

}


BOOL CreschangerDlg::GetTranslationId(LPVOID lpData, UINT unBlockSize, WORD wLangId, DWORD &dwId, BOOL bPrimaryEnough/*= FALSE*/)
{
 for (LPWORD lpwData = (LPWORD)lpData; (LPBYTE)lpwData < ((LPBYTE)lpData)+unBlockSize; lpwData+=2)
 {
  if (*lpwData == wLangId)
  {
   dwId = *((DWORD*)lpwData);
   return TRUE;
  }
 }

 if (!bPrimaryEnough)
  return FALSE;

 for (lpwData = (LPWORD)lpData; (LPBYTE)lpwData < ((LPBYTE)lpData)+unBlockSize; lpwData+=2)
 {
  if (((*lpwData)&0x00FF) == (wLangId&0x00FF))
  {
   dwId = *((DWORD*)lpwData);
   return TRUE;
  }
 }

 return FALSE;
}


LPVOID CreschangerDlg::SearchText(char* Search,char* findstring,int maxlen)
{
 int comlen = strlen(findstring);

 bool b_ser=false;

 int comcount=0;

 for(int i=0;i<maxlen ; i++)
 {
  comcount=0;

  for(int x=0;x<comlen;x++)
  {


   char cur = Search[i];  

   if(cur == findstring[x])
   {
    comcount++;
    i = i + 2;
   }
   else
   {
    break;
   }


   if(comcount == comlen)
   {
    int xxx=999;
    if(0 ==strcmp("ProductVersion",findstring))
    {
     return (LPVOID)(&Search[i+2]);

    }

    if(0 == strcmp("Comments",findstring))
    {
     return (LPVOID)(&Search[i+2]);

    }

    return (LPVOID)(&Search[i+4]);
   }

  }

 

 }

 return NULL;

}

bool CreschangerDlg::validversiondata(int ntype,char* verstring)
{


 int i_verlen = strlen(verstring);

 if( (COMMENT_MAX < i_verlen) && (i_verlen < 1) )
 {
  strcpy(m_verLastError,"Comment의 Rev이 지정된 길이를 초과했거나, 1보다 작습니다.");
  return false;
 }

 if(ntype == PVER_COMMENT)
 {
  strcpy(m_verLastError,"Comment의 유효성 통과");
  return true;
 }

 if( VERSION_MAX < i_verlen)
 {
  strcpy(m_verLastError,"Version정보가 제한된 길이를 초과했습니다.");
  return false;
 }

 int comCount = 0;

 for(int i=0 ;i<i_verlen;i++)
 {

  // ,의 개수를 카운팅한다.
  if(verstring[i] == ',' || verstring[i] == '.')
  {
   if(i > 0)
   {
    if(verstring[i-1] == ',' || verstring[i-1] == '.')
    {
     strcpy(m_verLastError,"버젼 구분자사이에 값이 없습니다.");
     return false;
    }

   }

   comCount++;
   continue;
  }

  //버젼정보에 해당하는 문자열값이 숫자인지 체크
  if(  (NUM_START < verstring[i]) && (NUM_END > verstring[i])  )
  {

  }
  else
  {
   strcpy(m_verLastError,"Version정보에 ,를 제외한 문자가 들어올수 없습니다.");
   return false;
  }


 }


 if(COMA_COUNT != comCount )
 {
  strcpy(m_verLastError,"Version정보에 ,의 카운트는 3이어야합니다.");
  return false;

 }

 strcpy(m_verLastError,"Version정보 유효성 통과");

 return true;

}


 

2010년 11월 11일 목요일

SHELL32.DLL API

Activate_RunDLL
AppCompat_RunDLLW
CDefFolderMenu_Create
CDefFolderMenu_Create2
CallCPLEntry16
CheckEscapesA
CheckEscapesW
CommandLineToArgvW
Control_FillCache_RunDLL
Control_FillCache_RunDLLA
Control_FillCache_RunDLLW
Control_RunDLL
Control_RunDLLA
Control_RunDLLAsUserW
Control_RunDLLW
DAD_AutoScroll
DAD_DragEnterEx
DAD_DragEnterEx2
DAD_DragLeave
DAD_DragMove
DAD_SetDragImage
DAD_ShowDragImage
DllCanUnloadNow
DllGetClassObject
DllGetVersion
DllInstall
DllRegisterServer
DllUnregisterServer
DoEnvironmentSubstA
DoEnvironmentSubstW
DragAcceptFiles
DragFinish
DragQueryFile
DragQueryFileA
DragQueryFileAorW
DragQueryFileW
DragQueryPoint
DriveType
DuplicateIcon
ExtractAssociatedIconA
ExtractAssociatedIconExA
ExtractAssociatedIconExW
ExtractAssociatedIconW
ExtractIconA
ExtractIconEx
ExtractIconExA
ExtractIconExW
ExtractIconResInfoA
ExtractIconResInfoW
ExtractIconW
ExtractVersionResource16W
FindExeDlgProc
FindExecutableA
FindExecutableW
FreeIconList
GetFileNameFromBrowse
ILAppendID
ILClone
ILCloneFirst
ILCombine
ILCreateFromPath
ILCreateFromPathA
ILCreateFromPathW
ILFindChild
ILFindLastID
ILFree
ILGetNext
ILGetSize
ILIsEqual
ILIsParent
ILLoadFromStream
ILRemoveLastID
ILSaveToStream
InternalExtractIconListA
InternalExtractIconListW
IsLFNDrive
IsLFNDriveA
IsLFNDriveW
IsNetDrive
IsUserAnAdmin
OpenAs_RunDLL
OpenAs_RunDLLA
OpenAs_RunDLLW
OpenRegStream
Options_RunDLL
Options_RunDLLA
Options_RunDLLW
PathCleanupSpec
PathGetShortPath
PathIsExe
PathIsSlowA
PathIsSlowW
PathMakeUniqueName
PathProcessCommand
PathQualify
PathResolve
PathYetAnotherMakeUniqueName
PickIconDlg
PifMgr_CloseProperties
PifMgr_GetProperties
PifMgr_OpenProperties
PifMgr_SetProperties
PrintersGetCommand_RunDLL
PrintersGetCommand_RunDLLA
PrintersGetCommand_RunDLLW
ReadCabinetState
RealDriveType
RealShellExecuteA
RealShellExecuteExA
RealShellExecuteExW
RealShellExecuteW
RegenerateUserEnvironment
RestartDialog
RestartDialogEx
SHAddFromPropSheetExtArray
SHAddToRecentDocs
SHAlloc
SHAllocShared (forwarded to shlwapi.SHAllocShared)
SHAppBarMessage
SHBindToParent
SHBrowseForFolder
SHBrowseForFolderA
SHBrowseForFolderW
SHCLSIDFromString
SHChangeNotification_Lock
SHChangeNotification_Unlock
SHChangeNotify
SHChangeNotifyDeregister
SHChangeNotifyRegister
SHChangeNotifySuspendResume
SHCloneSpecialIDList
SHCoCreateInstance
SHCreateDirectory
SHCreateDirectoryExA
SHCreateDirectoryExW
SHCreateFileExtractIconW
SHCreateLocalServerRunDll
SHCreateProcessAsUserW
SHCreatePropSheetExtArray
SHCreateQueryCancelAutoPlayMoniker
SHCreateShellFolderView
SHCreateShellFolderViewEx
SHCreateShellItem
SHCreateStdEnumFmtEtc
SHDefExtractIconA
SHDefExtractIconW
SHDestroyPropSheetExtArray
SHDoDragDrop
SHEmptyRecycleBinA
SHEmptyRecycleBinW
SHEnableServiceObject
SHEnumerateUnreadMailAccountsW
SHExtractIconsW
SHFileOperation
SHFileOperationA
SHFileOperationW
SHFindFiles
SHFind_InitMenuPopup
SHFlushClipboard
SHFlushSFCache
SHFormatDrive
SHFree
SHFreeNameMappings
SHFreeShared (forwarded to shlwapi.SHFreeShared)
SHGetAttributesFromDataObject
SHGetDataFromIDListA
SHGetDataFromIDListW
SHGetDesktopFolder
SHGetDiskFreeSpaceA
SHGetDiskFreeSpaceExA
SHGetDiskFreeSpaceExW
SHGetFileInfo
SHGetFileInfoA
SHGetFileInfoW
SHGetFolderLocation
SHGetFolderPathA
SHGetFolderPathAndSubDirA
SHGetFolderPathAndSubDirW
SHGetFolderPathW
SHGetIconOverlayIndexA
SHGetIconOverlayIndexW
SHGetImageList
SHGetInstanceExplorer
SHGetMalloc
SHGetNewLinkInfo
SHGetNewLinkInfoA
SHGetNewLinkInfoW
SHGetPathFromIDList
SHGetPathFromIDListA
SHGetPathFromIDListW
SHGetRealIDL
SHGetSetFolderCustomSettingsW
SHGetSetSettings
SHGetSettings
SHGetShellStyleHInstance
SHGetSpecialFolderLocation
SHGetSpecialFolderPathA
SHGetSpecialFolderPathW
SHGetUnreadMailCountW
SHHandleUpdateImage
SHHelpShortcuts_RunDLL
SHHelpShortcuts_RunDLLA
SHHelpShortcuts_RunDLLW
SHILCreateFromPath
SHInvokePrinterCommandA
SHInvokePrinterCommandW
SHIsFileAvailableOffline
SHLimitInputEdit
SHLoadInProc
SHLoadNonloadedIconOverlayIdentifiers
SHLoadOLE
SHLockShared (forwarded to shlwapi.SHLockShared)
SHMapIDListToImageListIndexAsync
SHMapPIDLToSystemImageListIndex
SHMultiFileProperties
SHObjectProperties
SHOpenFolderAndSelectItems
SHOpenPropSheetW
SHParseDisplayName
SHPathPrepareForWriteA
SHPathPrepareForWriteW
SHPropStgCreate
SHPropStgReadMultiple
SHPropStgWriteMultiple
SHQueryRecycleBinA
SHQueryRecycleBinW
SHReplaceFromPropSheetExtArray
SHRestricted
SHRunControlPanel
SHSetInstanceExplorer
SHSetLocalizedName
SHSetUnreadMailCountW
SHShellFolderView_Message
SHSimpleIDListFromPath
SHStartNetConnectionDialogW
SHTestTokenMembership
SHUnlockShared (forwarded to shlwapi.SHUnlockShared)
SHUpdateImageA
SHUpdateImageW
SHUpdateRecycleBinIcon
SHValidateUNC
SheChangeDirA
SheChangeDirExA
SheChangeDirExW
SheChangeDirW
SheConvertPathW
SheFullPathA
SheFullPathW
SheGetCurDrive
SheGetDirA
SheGetDirExW
SheGetDirW
SheGetPathOffsetW
SheRemoveQuotesA
SheRemoveQuotesW
SheSetCurDrive
SheShortenPathA
SheShortenPathW
ShellAboutA
ShellAboutW
ShellExec_RunDLL
ShellExec_RunDLLA
ShellExec_RunDLLW
ShellExecuteA
ShellExecuteEx
ShellExecuteExA
ShellExecuteExW
ShellExecuteW
ShellHookProc
ShellMessageBoxA
ShellMessageBoxW
Shell_GetCachedImageIndex
Shell_GetImageLists
Shell_MergeMenus
Shell_NotifyIcon
Shell_NotifyIconA
Shell_NotifyIconW
SignalFileOpen
StrChrA
StrChrIA
StrChrIW
StrChrW
StrCmpNA
StrCmpNIA
StrCmpNIW
StrCmpNW
StrCpyNA
StrCpyNW
StrNCmpA
StrNCmpIA
StrNCmpIW
StrNCmpW
StrNCpyA
StrNCpyW
StrRChrA
StrRChrIA
StrRChrIW
StrRChrW
StrRStrA
StrRStrIA
StrRStrIW
StrRStrW
StrStrA
StrStrIA
StrStrIW
StrStrW
WOWShellExecute
Win32DeleteFile
WriteCabinetState
[NONAME] (forwarded to shlwapi.PathBuildRootW)
[NONAME] (forwarded to shlwapi.PathCombineW)
[NONAME] (forwarded to shlwapi.PathIsUNCW)
[NONAME] (forwarded to shlwapi.PathIsRelativeW)
[NONAME] (forwarded to shlwapi.PathGetDriveNumberW)

파일의 현재 인코딩 상태 알아오기

StreamReader file = File.OpenText(@"D:\11.txt");

 byte[] b = file.CurrentEncoding.GetPreamble();

 

위와 같이 오픈한 해당 파일의

 

"byte-order mark" 를 가져온 뒤

byte배열에 들어있는 값을

아래표와 비교하시면 됨

 

=========

 

Encoding Representation (hexadecimal) Representation (decimal)
UTF-8 EF BB BF 239 187 191
UTF-16 (BE) FE FF 254 255
UTF-16 (LE) FF FE 255 254
UTF-32 (BE) 00 00 FE FF 0 0 254 255
UTF-32 (LE) FF FE 00 00 255 254 0 0
UTF-7 2B 2F 76, and one of the following bytes: [ 38 | 39 | 2B | 2F ] 43 47and one of the following bytes: [ 56 | 57 | 43 | 47 ]
UTF-1 F7 64 4C 247 100 76
UTF-EBCDIC DD 73 66 73 221 115 102 115
SCSU 0E FE FF 14 254 255
BOCU-1 FB EE 28 optionally followed by FF 251 238 40 optionally followed by 255