VC Resource 관련

리소스 ID충돌을 피하기 위하여 다음과 같은 루틴을 사용하게 된다.

#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        263
#define _APS_NEXT_COMMAND_VALUE         33249
#define _APS_NEXT_CONTROL_VALUE         1152
#define _APS_NEXT_SYMED_VALUE           104
#endif
#endif

각각의 심볼의 의미는 다음과 같다.

_APS_NEXT_RESOURCE_VALUE is the next symbol value that will be used for a dialog resource, menu resource, and so on. The valid range for resource symbol values is 1 to 0x6FFF.


_APS_NEXT_COMMAND_VALUE is the next symbol value that will be used for a command identification. The valid range for command symbol values is 0x8000 to 0xDFFF.


_APS_NEXT_CONTROL_VALUE is the next symbol value that will be used for a dialog control. The valid range for dialog control symbol values is 8 to 0xDFFF.


_APS_NEXT_SYMED_VALUE is the next symbol value that will be issued when you manually assign a symbol value using the New command in the Symbol Browser.

여러개의 rc파일을 사용시 새로운 rc파일에서 리소스 추가 전에 충돌하지 않는 새로운 시작 ID를 할당한다. 너무 큰 숫자를 할당하게 되면 더이상 사용할 수 있는 리소스가 없어지므로 주의한다.

할당예)
#define _APS_NEXT_RESOURCE_VALUE  2000
#define _APS_NEXT_COMMAND_VALUE   42000
#define _APS_NEXT_CONTROL_VALUE   2000
#define _APS_NEXT_SYMED_VALUE     2000

Hooking과 VirtualAlloc을 통한 다른 프로그램의 ListView내용얻어오기

일반적으로 서로 다른 프로그램에서 Message전송만을 통한 Cotrol의 값의 복사가 가능하다. 하지만, 기본컨트롤이 아닌 다른 Cotrol에서 내용을 얻어오고자 할때는 Message와 VirtualAlloc을 이용해야 한다.

기본적인 순서는 다음과 같다.

1. 윈도우 핸들을 얻는다.
2. 차일드 윈도우목록에서 ListView의 핸들을 얻는다.
3. 메세지를 통해서 Item의 숫자를 얻는다.
4. ListView의 프로세스 id를 얻는다.
5. ListView의 프로세스에서 메모리를 할당한다.
6. 할당된 메모리와 Message를 이용하여 Item의 내용을 읽어온다.
7. 할당된 메모리를 해제

 다음의 예제는 어느 회사의 사용자를 검색하여 List에 출력하여 주는 간단한 델파일 프로그램을 후킹하여 사용자정보를 CSV파일로 저장하는 루틴이다.
리스트에 표현되는 정보는 순번,이름,직책,부서명,회사명,보직/담당업무,전화번호,핸드폰,이메일 이며 EnumChildWindows는 CallBack함수를 필요로한다.

HWND hFlatEdit;
HWND hListView;
CString filename;
int lineCount = 1;

BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lPara){


 HWND hEdit = ::FindWindowEx(hwnd,NULL, “TFlatEdit”,””);
 HWND hList = ::FindWindowEx(hwnd,NULL, “TListView”, “”);
 if(hList > 0){
  hListView = hList;
  //TRACE1(“List Handle : %d\n”, hList);
 }


 if(hEdit > 0){
  //TRACE1(“Edit Handle : %d\n”,hEdit);
  hFlatEdit = hEdit;  
 }
 return TRUE;
}

void Save()
{
 HWND hwnd = ::FindWindow(NULL,”사용자검색”);
 CWnd* cwnd = CWnd::FromHandle(hwnd);   
 HINSTANCE hInstance = (HINSTANCE)(::GetWindowLong(hwnd, GWL_HINSTANCE));
 

 if(cwnd == NULL || hInstance==0){
    MessageBox(“사용자 검색창을 열어주세요”,”사용자검색창”,MB_OK);
 } else {
 
  cwnd->SetForegroundWindow();
  ::EnumChildWindows(cwnd->GetSafeHwnd(), EnumChildProc,LPARAM(cwnd));
 
  int count=(int)::SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0);
  int i;
  LVITEM lvi, *_lvi;
  char item[512], subitem1[512],subitem2[512],subitem3[512],subitem4[512],subitem5[512],subitem6[512],subitem7[512],subitem8[512];
  char *_item, *_subitem1,*_subitem2,*_subitem3,*_subitem4,*_subitem5,*_subitem6,*_subitem7,*_subitem8;
  unsigned long pid;
  HANDLE process;


  GetWindowThreadProcessId(hListView, &pid);
  process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|
   PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, pid);


  _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM),
   MEM_COMMIT, PAGE_READWRITE);
  _item=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
 
  _subitem1=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem2=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem3=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem4=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem5=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem6=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem7=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);
  _subitem8=(char*)VirtualAllocEx(process, NULL, 512, MEM_COMMIT,
   PAGE_READWRITE);


  lvi.cchTextMax=512;


   
  CFileDialog fileOpen(FALSE, “CSV저장”,NULL,OFN_HIDEREADONLY,”CSV파일 (*.csv)|*.csv|”,cwnd);
  if(filename.GetLength() > 0 || fileOpen.DoModal() == IDOK){


   CString mode = “”;
   bool header = false;
   if(filename.GetLength() == 0){
    mode =”wt”;
    filename = fileOpen.GetPathName();
    header = true;
   } else {
    mode =”a”;
   }


   FILE * out = fopen(filename,mode);
   if(header == true){
    fprintf(out, “\”순번\”,\”이름\”,\”직책\”,\”부서명\”,\”회사명\”,\”보직/담당업무\”,\”전화번호\”,\”핸드폰\”,\”이메일\”\n”);
   }
     
   for(i=0; i<count; i++) {
    lvi.iSubItem=0;
    lvi.pszText=_item;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=1;
    lvi.pszText=_subitem1;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=2;
    lvi.pszText=_subitem2;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=3;
    lvi.pszText=_subitem3;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=4;
    lvi.pszText=_subitem4;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=5;
    lvi.pszText=_subitem5;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=6;
    lvi.pszText=_subitem6;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    lvi.iSubItem=7;
    lvi.pszText=_subitem7;
    ::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    ::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    //lvi.iSubItem=8;
    //lvi.pszText=_subitem8;
    //::WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
    //::SendMessage(hListView, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);


    ::ReadProcessMemory(process, _item, item, 512, NULL);
    ::ReadProcessMemory(process, _subitem1, subitem1, 512, NULL);
    ::ReadProcessMemory(process, _subitem2, subitem2, 512, NULL);
    ::ReadProcessMemory(process, _subitem3, subitem3, 512, NULL);
    ::ReadProcessMemory(process, _subitem4, subitem4, 512, NULL);
    ::ReadProcessMemory(process, _subitem5, subitem5, 512, NULL);
    ::ReadProcessMemory(process, _subitem6, subitem6, 512, NULL);
    ::ReadProcessMemory(process, _subitem7, subitem7, 512, NULL);
    //::ReadProcessMemory(process, _subitem8, subitem8, 512, NULL);



    char output[2048];
    sprintf(output, “\”%d\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\”,\”%s\””,lineCount,item,subitem1,subitem2,subitem3,subitem4,subitem5,subitem6,subitem7);
    fprintf(out,”%s\n”,output);
    lineCount++;
   }
   fclose(out);
  }


  ::VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _item, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem1, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem2, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem3, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem4, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem5, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem6, 0, MEM_RELEASE);
  ::VirtualFreeEx(process, _subitem7, 0, MEM_RELEASE);

 }
}