2010년 11월 14일 일요일

파일 버전 정보

펌) 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;

}


 

댓글 없음:

댓글 쓰기