반응형
screenvideocapture

Screen Capture (Video)

PC 화면의 일부를 캡쳐하는 방법은 많이 있는데…
PC 화면의 일부나 특정 윈도우를 간단하게 영상을 캡쳐하고 싶을 때는 어떻게 해야 할까? 무료 유틸리티를 사용하고 싶다.

먼저 Free License 유틸리티로 동영상 처리 관련된 강력한 프로그램인 ffmpeg를 권장한다.
물론 사용 방법은 커맨드 등을 익혀야 되서 복잡할 수 있지만, 여기서는 이것을 dos batch script로 만들어서 한 번만 만들어 두면 이후에 공짜로 편하게 사용할 수 있다.

  1. 프로그램 설치

구글에서 ffmpeg windows download 라고 검색해서 설치한다.
잘 모르겠으면 윈도우 패키지 링크 주소는
ffmpeg windows 64 bit binary download
다운 받은 파일을 열어 압축을 풀면 bin 폴더가 있다. bin 폴더의 파일들을 c:\windows에 복사하자. (별도 유틸리티 폴더를 만들고, 환경설정으로 PATH에 설정해 두는 것이 좋긴하지만 귀찮으면 위와 같이 한다.)
이제 DOS 커맨드 창에서 ffmpeg라고 실행해서 잘 되는지 확인한다.
image

  1. 스크립트 작성

스크립트1: 특정 윈도우 창만 캡쳐하기
ffmpeg_videocap.bat “윈도우제목” "파일명"
파일명.mp4로 파일이 생성됨.

@echo off
if "%1"=="" goto usage

:: by crazyj7@gmail.com
:: famerate ; 24, 30. 60 
:: 파일 확장자는 mp4, avi, mpg 등 
:: drawmouse : 마우스 커서를 보여줄지 여부 (1/0)

ffmpeg -y -rtbufsize 100M -f gdigrab -framerate 30 -probesize 10M -draw_mouse 0 -i title="%1" -c:v libx264 -r 30  -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" "%2.mp4"

goto:eof

:usage
echo Usage)
echo %0 "window title" "filename"
goto:eof

스크립트2: 전체 화면 동영상 캡쳐하기 (모니터가 2개면 둘 다 캡쳐된다.)
ffmpeg_videocap_fullscreen.bat "파일명"

파일명.mp4 파일 생성됨.

@echo off
if "%1"=="" goto usage
 
:: crazyj7@gmail.com 
:: famerate ; 24, 30. 60 
:: 파일 확장자는 mp4, avi, mpg 등 
:: drawmouse : 마우스 커서를 보여줄지 여부 (1/0)
 
ffmpeg -y -rtbufsize 100M -f gdigrab -framerate 30 -probesize 10M -draw_mouse 1 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p "%1.mp4"
 
goto:eof
  
:usage
echo Usage)
echo %0 "filename"
goto:eof

스크립트3: 전체 화면 동영상 캡쳐하기. (모니터2개인경우 모니터1만)
주의! 모니터1의 해상도 값으로 코드를 바꿔줘야 한다. (1280x1080 예이다.)
특정 영역 캡쳐하기도 된다. (offset과 크기 조정)
ffmpeg_videocap_full1280x1080.bat “파일명”

@echo off
if "%1"=="" goto usage

:: crazyj7@gmail.com
:: famerate ; 24, 30. 60 
:: 파일 확장자는 mp4, avi, mpg 등 
:: drawmouse : 마우스 커서를 보여줄지 여부 (1/0)

ffmpeg -y -rtbufsize 100M -f gdigrab -framerate 30 -probesize 10M -draw_mouse 1 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p "%1.mp4"

goto:eof

:usage
echo Usage)
echo %0 "filename"
goto:eof

  1. 실행
  • 커맨드 실행 종료 (녹화 종료)는 q 또는 ^c(컨트롤c)

특정 윈도우만 동영상 캡쳐를 하려면 아래와 같이 한다.
윈도우 타이틀은 창의 상단에 타이틀바에 기록된 스트링이다. (없거나 못 찾을 경우는 화면 일부영역 캡쳐를 참고하기 바란다.)

c:\temp> ffmpeg_videocap “stackedit” “aaa”
"stackedit"란 제목의 창을 찾아 aaa.mp4 동영상 파일을 생성한다.
aaa

전체화면 동영상 캡쳐
c:\temp> ffmpeg_videofullscreen “full”
전체 화면을 녹화하여 full.mp4 파일이 생성된다. (모니터가 2개면 둘 다 나온다.)
full

모니터1만 캡쳐 또는 일부 영역만 캡쳐
(일부 영역을 지정하려면 스크립트를 수정하여 offset과 size를 조정하면 된다.)
c:\temp> ffmpeg_videofullscreen_1920_1080 “full2”
모니터1만 (1920x1080 해상도) 녹화하여 full2.mp4 동영상 파일을 생성한다.
full2

  1. 보너스 (동영상을 gif로)

생성한 동영상 파일을 움직이는 gif 파일로 변환하기
ffmpeg -i aaa.mp4 aaa.gif
브라우저에 aaa.gif 파일을 드래그드롭하면 움직이는 gif 파일이 재생된다. (웹에 올리기 편하다.)

image

Written with StackEdit.

'Develop > Windows' 카테고리의 다른 글

DOS Batch Script  (0) 2019.10.06
curl 사용법/HTTP 테스트  (0) 2019.10.01
windows 10 kernel structure  (0) 2015.08.28
윈도우8/8.1에서 visual studio 2008 설치실패시 / .net framework 설치  (1) 2015.08.20
64비트 프로그래밍  (2) 2015.06.05
반응형


windows 10 64bit


윈도우 10에서 사용되는 커널 자료 구조를 알려면....


1. 일단 디버거. windbg를 설치해야 되는데, 

https://msdn.microsoft.com/ko-kr/windows/hardware/dn913721.aspx

위 사이트로 가서 WDM 10 설치하면 디버거가 깔린다.


2. 필요한 심볼..

https://msdn.microsoft.com/en-us/windows/hardware/gg463028.aspx

위 사이트 가서 필요한 심볼 압축파일을 받아 설치한다.

3. 디버거에 심볼 설정.

ctrl+s 하고 심볼 경로에 아래 기록. e:\symbols는 본인이 설치한 심볼 경로로 변경.

SRV*e:\symbols*http://msdl.microsoft.com/download/symbols

reload 체크하여 확인.


4. 메뉴에서 중요하지 않은 프로세스나 attach하여 심볼 확인.

F6 - 중요하지 않은 임의의 프로세스(notepad.exe 등) 선택


5. 필요한 자료구조 조회


주의!!! build 1511에서 약간 변경변경되에 뒤에 추가하였음


0:032> dt _EPROCESS

ntdll!_EPROCESS

   +0x000 Pcb              : _KPROCESS

   +0x2d8 ProcessLock      : _EX_PUSH_LOCK

   +0x2e0 RundownProtect   : _EX_RUNDOWN_REF

   +0x2e8 UniqueProcessId  : Ptr64 Void

   +0x2f0 ActiveProcessLinks : _LIST_ENTRY

   +0x300 Flags2           : Uint4B

   +0x300 JobNotReallyActive : Pos 0, 1 Bit

   +0x300 AccountingFolded : Pos 1, 1 Bit

   +0x300 NewProcessReported : Pos 2, 1 Bit

   +0x300 ExitProcessReported : Pos 3, 1 Bit

   +0x300 ReportCommitChanges : Pos 4, 1 Bit

   +0x300 LastReportMemory : Pos 5, 1 Bit

   +0x300 ForceWakeCharge  : Pos 6, 1 Bit

   +0x300 CrossSessionCreate : Pos 7, 1 Bit

   +0x300 NeedsHandleRundown : Pos 8, 1 Bit

   +0x300 RefTraceEnabled  : Pos 9, 1 Bit

   +0x300 DisableDynamicCode : Pos 10, 1 Bit

   +0x300 EmptyJobEvaluated : Pos 11, 1 Bit

   +0x300 DefaultPagePriority : Pos 12, 3 Bits

   +0x300 PrimaryTokenFrozen : Pos 15, 1 Bit

   +0x300 ProcessVerifierTarget : Pos 16, 1 Bit

   +0x300 StackRandomizationDisabled : Pos 17, 1 Bit

   +0x300 AffinityPermanent : Pos 18, 1 Bit

   +0x300 AffinityUpdateEnable : Pos 19, 1 Bit

   +0x300 PropagateNode    : Pos 20, 1 Bit

   +0x300 ExplicitAffinity : Pos 21, 1 Bit

   +0x300 ProcessExecutionState : Pos 22, 2 Bits

   +0x300 DisallowStrippedImages : Pos 24, 1 Bit

   +0x300 HighEntropyASLREnabled : Pos 25, 1 Bit

   +0x300 ExtensionPointDisable : Pos 26, 1 Bit

   +0x300 ForceRelocateImages : Pos 27, 1 Bit

   +0x300 ProcessStateChangeRequest : Pos 28, 2 Bits

   +0x300 ProcessStateChangeInProgress : Pos 30, 1 Bit

   +0x300 DisallowWin32kSystemCalls : Pos 31, 1 Bit

   +0x304 Flags            : Uint4B

   +0x304 CreateReported   : Pos 0, 1 Bit

   +0x304 NoDebugInherit   : Pos 1, 1 Bit

   +0x304 ProcessExiting   : Pos 2, 1 Bit

   +0x304 ProcessDelete    : Pos 3, 1 Bit

   +0x304 ControlFlowGuardEnabled : Pos 4, 1 Bit

   +0x304 VmDeleted        : Pos 5, 1 Bit

   +0x304 OutswapEnabled   : Pos 6, 1 Bit

   +0x304 Outswapped       : Pos 7, 1 Bit

   +0x304 FailFastOnCommitFail : Pos 8, 1 Bit

   +0x304 Wow64VaSpace4Gb  : Pos 9, 1 Bit

   +0x304 AddressSpaceInitialized : Pos 10, 2 Bits

   +0x304 SetTimerResolution : Pos 12, 1 Bit

   +0x304 BreakOnTermination : Pos 13, 1 Bit

   +0x304 DeprioritizeViews : Pos 14, 1 Bit

   +0x304 WriteWatch       : Pos 15, 1 Bit

   +0x304 ProcessInSession : Pos 16, 1 Bit

   +0x304 OverrideAddressSpace : Pos 17, 1 Bit

   +0x304 HasAddressSpace  : Pos 18, 1 Bit

   +0x304 LaunchPrefetched : Pos 19, 1 Bit

   +0x304 Background       : Pos 20, 1 Bit

   +0x304 VmTopDown        : Pos 21, 1 Bit

   +0x304 ImageNotifyDone  : Pos 22, 1 Bit

   +0x304 PdeUpdateNeeded  : Pos 23, 1 Bit

   +0x304 VdmAllowed       : Pos 24, 1 Bit

   +0x304 ProcessRundown   : Pos 25, 1 Bit

   +0x304 ProcessInserted  : Pos 26, 1 Bit

   +0x304 DefaultIoPriority : Pos 27, 3 Bits

   +0x304 ProcessSelfDelete : Pos 30, 1 Bit

   +0x304 SetTimerResolutionLink : Pos 31, 1 Bit

   +0x308 CreateTime       : _LARGE_INTEGER

   +0x310 ProcessQuotaUsage : [2] Uint8B

   +0x320 ProcessQuotaPeak : [2] Uint8B

   +0x330 PeakVirtualSize  : Uint8B

   +0x338 VirtualSize      : Uint8B

   +0x340 SessionProcessLinks : _LIST_ENTRY

   +0x350 ExceptionPortData : Ptr64 Void

   +0x350 ExceptionPortValue : Uint8B

   +0x350 ExceptionPortState : Pos 0, 3 Bits

   +0x358 Token            : _EX_FAST_REF

   +0x360 WorkingSetPage   : Uint8B

   +0x368 AddressCreationLock : _EX_PUSH_LOCK

   +0x370 PageTableCommitmentLock : _EX_PUSH_LOCK

   +0x378 RotateInProgress : Ptr64 _ETHREAD

   +0x380 ForkInProgress   : Ptr64 _ETHREAD

   +0x388 CommitChargeJob  : Ptr64 _EJOB

   +0x390 CloneRoot        : _RTL_AVL_TREE

   +0x398 NumberOfPrivatePages : Uint8B

   +0x3a0 NumberOfLockedPages : Uint8B

   +0x3a8 Win32Process     : Ptr64 Void

   +0x3b0 Job              : Ptr64 _EJOB

   +0x3b8 SectionObject    : Ptr64 Void

   +0x3c0 SectionBaseAddress : Ptr64 Void

   +0x3c8 Cookie           : Uint4B

   +0x3d0 WorkingSetWatch  : Ptr64 _PAGEFAULT_HISTORY

   +0x3d8 Win32WindowStation : Ptr64 Void

   +0x3e0 InheritedFromUniqueProcessId : Ptr64 Void

   +0x3e8 LdtInformation   : Ptr64 Void

   +0x3f0 OwnerProcessId   : Uint8B

   +0x3f8 Peb              : Ptr64 _PEB

   +0x400 Session          : Ptr64 Void

   +0x408 AweInfo          : Ptr64 Void

   +0x410 QuotaBlock       : Ptr64 _EPROCESS_QUOTA_BLOCK

   +0x418 ObjectTable      : Ptr64 _HANDLE_TABLE

   +0x420 DebugPort        : Ptr64 Void

   +0x428 Wow64Process     : Ptr64 Void

   +0x430 DeviceMap        : Ptr64 Void

   +0x438 EtwDataSource    : Ptr64 Void

   +0x440 PageDirectoryPte : Uint8B

   +0x448 ImageFileName    : [15] UChar

   +0x457 PriorityClass    : UChar

   +0x458 SecurityPort     : Ptr64 Void

   +0x460 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO

   +0x468 JobLinks         : _LIST_ENTRY

   +0x478 HighestUserAddress : Ptr64 Void

   +0x480 ThreadListHead   : _LIST_ENTRY

   +0x490 ActiveThreads    : Uint4B

   +0x494 ImagePathHash    : Uint4B

   +0x498 DefaultHardErrorProcessing : Uint4B

   +0x49c LastThreadExitStatus : Int4B

   +0x4a0 PrefetchTrace    : _EX_FAST_REF

   +0x4a8 LockedPagesList  : Ptr64 Void

   +0x4b0 ReadOperationCount : _LARGE_INTEGER

   +0x4b8 WriteOperationCount : _LARGE_INTEGER

   +0x4c0 OtherOperationCount : _LARGE_INTEGER

   +0x4c8 ReadTransferCount : _LARGE_INTEGER

   +0x4d0 WriteTransferCount : _LARGE_INTEGER

   +0x4d8 OtherTransferCount : _LARGE_INTEGER

   +0x4e0 CommitChargeLimit : Uint8B

   +0x4e8 CommitCharge     : Uint8B

   +0x4f0 CommitChargePeak : Uint8B

   +0x4f8 Vm               : _MMSUPPORT

   +0x5f0 MmProcessLinks   : _LIST_ENTRY

   +0x600 ModifiedPageCount : Uint4B

   +0x604 ExitStatus       : Int4B

   +0x608 VadRoot          : _RTL_AVL_TREE

   +0x610 VadHint          : Ptr64 Void

   +0x618 VadCount         : Uint8B

   +0x620 VadPhysicalPages : Uint8B

   +0x628 VadPhysicalPagesLimit : Uint8B

   +0x630 AlpcContext      : _ALPC_PROCESS_CONTEXT

   +0x650 TimerResolutionLink : _LIST_ENTRY

   +0x660 TimerResolutionStackRecord : Ptr64 _PO_DIAG_STACK_RECORD

   +0x668 RequestedTimerResolution : Uint4B

   +0x66c SmallestTimerResolution : Uint4B

   +0x670 ExitTime         : _LARGE_INTEGER

   +0x678 InvertedFunctionTable : Ptr64 _INVERTED_FUNCTION_TABLE

   +0x680 InvertedFunctionTableLock : _EX_PUSH_LOCK

   +0x688 ActiveThreadsHighWatermark : Uint4B

   +0x68c LargePrivateVadCount : Uint4B

   +0x690 ThreadListLock   : _EX_PUSH_LOCK

   +0x698 WnfContext       : Ptr64 Void

   +0x6a0 Spare0           : Uint8B

   +0x6a8 SignatureLevel   : UChar

   +0x6a9 SectionSignatureLevel : UChar

   +0x6aa Protection       : _PS_PROTECTION

   +0x6ab HangCount        : UChar

   +0x6ac Flags3           : Uint4B

   +0x6ac Minimal          : Pos 0, 1 Bit

   +0x6ac ReplacingPageRoot : Pos 1, 1 Bit

   +0x6ac DisableNonSystemFonts : Pos 2, 1 Bit

   +0x6ac AuditNonSystemFontLoading : Pos 3, 1 Bit

   +0x6ac Crashed          : Pos 4, 1 Bit

   +0x6ac JobVadsAreTracked : Pos 5, 1 Bit

   +0x6ac VadTrackingDisabled : Pos 6, 1 Bit

   +0x6ac AuxiliaryProcess : Pos 7, 1 Bit

   +0x6ac SubsystemProcess : Pos 8, 1 Bit

   +0x6ac IndirectCpuSets  : Pos 9, 1 Bit

   +0x6ac InPrivate        : Pos 10, 1 Bit

   +0x6b0 DeviceAsid       : Int4B

   +0x6b8 SvmData          : Ptr64 Void

   +0x6c0 SvmProcessLock   : _EX_PUSH_LOCK

   +0x6c8 SvmLock          : Uint8B

   +0x6d0 SvmProcessDeviceListHead : _LIST_ENTRY

   +0x6e0 LastFreezeInterruptTime : Uint8B

   +0x6e8 DiskCounters     : Ptr64 _PROCESS_DISK_COUNTERS

   +0x6f0 PicoContext      : Ptr64 Void

   +0x6f8 TrustletIdentity : Uint8B

   +0x700 KeepAliveCounter : Uint4B

   +0x704 NoWakeKeepAliveCounter : Uint4B

   +0x708 HighPriorityFaultsAllowed : Uint4B

   +0x710 EnergyValues     : Ptr64 _PROCESS_ENERGY_VALUES

   +0x718 VmContext        : Ptr64 Void

   +0x720 Silo             : Ptr64 _ESILO

   +0x728 SiloEntry        : _LIST_ENTRY

   +0x738 SequenceNumber   : Uint8B

   +0x740 CreateInterruptTime : Uint8B

   +0x748 CreateUnbiasedInterruptTime : Uint8B

   +0x750 TotalUnbiasedFrozenTime : Uint8B

   +0x758 LastAppStateUpdateTime : Uint8B

   +0x760 LastAppStateUptime : Pos 0, 61 Bits

   +0x760 LastAppState     : Pos 61, 3 Bits

   +0x768 SharedCommitCharge : Uint8B

   +0x770 SharedCommitLock : _EX_PUSH_LOCK

   +0x778 SharedCommitLinks : _LIST_ENTRY

   +0x788 AllowedCpuSets   : Uint8B

   +0x790 DefaultCpuSets   : Uint8B

   +0x788 AllowedCpuSetsIndirect : Ptr64 Uint8B

   +0x790 DefaultCpuSetsIndirect : Ptr64 Uint8B

------------------------------------------------------------------------
Windows 10 x64, build 1511 버전에서는 위 커널 자료구조가 약간 바뀌었다.

---------

kd> dt _EPROCESS
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   +0x2e0 RundownProtect   : _EX_RUNDOWN_REF
   +0x2e8 UniqueProcessId  : Ptr64 Void
   +0x2f0 ActiveProcessLinks : _LIST_ENTRY
   +0x300 Flags2           : Uint4B
   +0x300 JobNotReallyActive : Pos 0, 1 Bit
   +0x300 AccountingFolded : Pos 1, 1 Bit
   +0x300 NewProcessReported : Pos 2, 1 Bit
   +0x300 ExitProcessReported : Pos 3, 1 Bit
   +0x300 ReportCommitChanges : Pos 4, 1 Bit
   +0x300 LastReportMemory : Pos 5, 1 Bit
   +0x300 ForceWakeCharge  : Pos 6, 1 Bit
   +0x300 CrossSessionCreate : Pos 7, 1 Bit
   +0x300 NeedsHandleRundown : Pos 8, 1 Bit
   +0x300 RefTraceEnabled  : Pos 9, 1 Bit
   +0x300 DisableDynamicCode : Pos 10, 1 Bit
   +0x300 EmptyJobEvaluated : Pos 11, 1 Bit
   +0x300 DefaultPagePriority : Pos 12, 3 Bits
   +0x300 PrimaryTokenFrozen : Pos 15, 1 Bit
   +0x300 ProcessVerifierTarget : Pos 16, 1 Bit
   +0x300 StackRandomizationDisabled : Pos 17, 1 Bit
   +0x300 AffinityPermanent : Pos 18, 1 Bit
   +0x300 AffinityUpdateEnable : Pos 19, 1 Bit
   +0x300 PropagateNode    : Pos 20, 1 Bit
   +0x300 ExplicitAffinity : Pos 21, 1 Bit
   +0x300 ProcessExecutionState : Pos 22, 2 Bits
   +0x300 DisallowStrippedImages : Pos 24, 1 Bit
   +0x300 HighEntropyASLREnabled : Pos 25, 1 Bit
   +0x300 ExtensionPointDisable : Pos 26, 1 Bit
   +0x300 ForceRelocateImages : Pos 27, 1 Bit
   +0x300 ProcessStateChangeRequest : Pos 28, 2 Bits
   +0x300 ProcessStateChangeInProgress : Pos 30, 1 Bit
   +0x300 DisallowWin32kSystemCalls : Pos 31, 1 Bit
   +0x304 Flags            : Uint4B
   +0x304 CreateReported   : Pos 0, 1 Bit
   +0x304 NoDebugInherit   : Pos 1, 1 Bit
   +0x304 ProcessExiting   : Pos 2, 1 Bit
   +0x304 ProcessDelete    : Pos 3, 1 Bit
   +0x304 ControlFlowGuardEnabled : Pos 4, 1 Bit
   +0x304 VmDeleted        : Pos 5, 1 Bit
   +0x304 OutswapEnabled   : Pos 6, 1 Bit
   +0x304 Outswapped       : Pos 7, 1 Bit
   +0x304 FailFastOnCommitFail : Pos 8, 1 Bit
   +0x304 Wow64VaSpace4Gb  : Pos 9, 1 Bit
   +0x304 AddressSpaceInitialized : Pos 10, 2 Bits
   +0x304 SetTimerResolution : Pos 12, 1 Bit
   +0x304 BreakOnTermination : Pos 13, 1 Bit
   +0x304 DeprioritizeViews : Pos 14, 1 Bit
   +0x304 WriteWatch       : Pos 15, 1 Bit
   +0x304 ProcessInSession : Pos 16, 1 Bit
   +0x304 OverrideAddressSpace : Pos 17, 1 Bit
   +0x304 HasAddressSpace  : Pos 18, 1 Bit
   +0x304 LaunchPrefetched : Pos 19, 1 Bit
   +0x304 Background       : Pos 20, 1 Bit
   +0x304 VmTopDown        : Pos 21, 1 Bit
   +0x304 ImageNotifyDone  : Pos 22, 1 Bit
   +0x304 PdeUpdateNeeded  : Pos 23, 1 Bit
   +0x304 VdmAllowed       : Pos 24, 1 Bit
   +0x304 ProcessRundown   : Pos 25, 1 Bit
   +0x304 ProcessInserted  : Pos 26, 1 Bit
   +0x304 DefaultIoPriority : Pos 27, 3 Bits
   +0x304 ProcessSelfDelete : Pos 30, 1 Bit
   +0x304 SetTimerResolutionLink : Pos 31, 1 Bit
   +0x308 CreateTime       : _LARGE_INTEGER
   +0x310 ProcessQuotaUsage : [2] Uint8B
   +0x320 ProcessQuotaPeak : [2] Uint8B
   +0x330 PeakVirtualSize  : Uint8B
   +0x338 VirtualSize      : Uint8B
   +0x340 SessionProcessLinks : _LIST_ENTRY
   +0x350 ExceptionPortData : Ptr64 Void
   +0x350 ExceptionPortValue : Uint8B
   +0x350 ExceptionPortState : Pos 0, 3 Bits
   +0x358 Token            : _EX_FAST_REF
   +0x360 WorkingSetPage   : Uint8B
   +0x368 AddressCreationLock : _EX_PUSH_LOCK
   +0x370 PageTableCommitmentLock : _EX_PUSH_LOCK
   +0x378 RotateInProgress : Ptr64 _ETHREAD
   +0x380 ForkInProgress   : Ptr64 _ETHREAD
   +0x388 CommitChargeJob  : Ptr64 _EJOB
   +0x390 CloneRoot        : _RTL_AVL_TREE
   +0x398 NumberOfPrivatePages : Uint8B
   +0x3a0 NumberOfLockedPages : Uint8B
   +0x3a8 Win32Process     : Ptr64 Void
   +0x3b0 Job              : Ptr64 _EJOB
   +0x3b8 SectionObject    : Ptr64 Void
   +0x3c0 SectionBaseAddress : Ptr64 Void
   +0x3c8 Cookie           : Uint4B
   +0x3d0 WorkingSetWatch  : Ptr64 _PAGEFAULT_HISTORY
   +0x3d8 Win32WindowStation : Ptr64 Void
   +0x3e0 InheritedFromUniqueProcessId : Ptr64 Void
   +0x3e8 LdtInformation   : Ptr64 Void
   +0x3f0 OwnerProcessId   : Uint8B
   +0x3f8 Peb              : Ptr64 _PEB
   +0x400 Session          : Ptr64 Void
   +0x408 AweInfo          : Ptr64 Void
   +0x410 QuotaBlock       : Ptr64 _EPROCESS_QUOTA_BLOCK
   +0x418 ObjectTable      : Ptr64 _HANDLE_TABLE
   +0x420 DebugPort        : Ptr64 Void
   +0x428 WoW64Process     : Ptr64 _EWOW64PROCESS
   +0x430 DeviceMap        : Ptr64 Void
   +0x438 EtwDataSource    : Ptr64 Void
   +0x440 PageDirectoryPte : Uint8B
   +0x448 ImageFilePointer : Ptr64 _FILE_OBJECT
   +0x450 ImageFileName    : [15] UChar
   +0x45f PriorityClass    : UChar
   +0x460 SecurityPort     : Ptr64 Void
   +0x468 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x470 JobLinks         : _LIST_ENTRY
   +0x480 HighestUserAddress : Ptr64 Void
   +0x488 ThreadListHead   : _LIST_ENTRY
   +0x498 ActiveThreads    : Uint4B
   +0x49c ImagePathHash    : Uint4B
   +0x4a0 DefaultHardErrorProcessing : Uint4B
   +0x4a4 LastThreadExitStatus : Int4B
   +0x4a8 PrefetchTrace    : _EX_FAST_REF
   +0x4b0 LockedPagesList  : Ptr64 Void
   +0x4b8 ReadOperationCount : _LARGE_INTEGER
   +0x4c0 WriteOperationCount : _LARGE_INTEGER
   +0x4c8 OtherOperationCount : _LARGE_INTEGER
   +0x4d0 ReadTransferCount : _LARGE_INTEGER
   +0x4d8 WriteTransferCount : _LARGE_INTEGER
   +0x4e0 OtherTransferCount : _LARGE_INTEGER
   +0x4e8 CommitChargeLimit : Uint8B
   +0x4f0 CommitCharge     : Uint8B
   +0x4f8 CommitChargePeak : Uint8B
   +0x500 Vm               : _MMSUPPORT
   +0x5f8 MmProcessLinks   : _LIST_ENTRY
   +0x608 ModifiedPageCount : Uint4B
   +0x60c ExitStatus       : Int4B
   +0x610 VadRoot          : _RTL_AVL_TREE
   +0x618 VadHint          : Ptr64 Void
   +0x620 VadCount         : Uint8B
   +0x628 VadPhysicalPages : Uint8B
   +0x630 VadPhysicalPagesLimit : Uint8B
   +0x638 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x658 TimerResolutionLink : _LIST_ENTRY
   +0x668 TimerResolutionStackRecord : Ptr64 _PO_DIAG_STACK_RECORD
   +0x670 RequestedTimerResolution : Uint4B
   +0x674 SmallestTimerResolution : Uint4B
   +0x678 ExitTime         : _LARGE_INTEGER
   +0x680 InvertedFunctionTable : Ptr64 _INVERTED_FUNCTION_TABLE
   +0x688 InvertedFunctionTableLock : _EX_PUSH_LOCK
   +0x690 ActiveThreadsHighWatermark : Uint4B
   +0x694 LargePrivateVadCount : Uint4B
   +0x698 ThreadListLock   : _EX_PUSH_LOCK
   +0x6a0 WnfContext       : Ptr64 Void
   +0x6a8 Spare0           : Uint8B
   +0x6b0 SignatureLevel   : UChar
   +0x6b1 SectionSignatureLevel : UChar
   +0x6b2 Protection       : _PS_PROTECTION
   +0x6b3 HangCount        : UChar
   +0x6b4 Flags3           : Uint4B
   +0x6b4 Minimal          : Pos 0, 1 Bit
   +0x6b4 ReplacingPageRoot : Pos 1, 1 Bit
   +0x6b4 DisableNonSystemFonts : Pos 2, 1 Bit
   +0x6b4 AuditNonSystemFontLoading : Pos 3, 1 Bit
   +0x6b4 Crashed          : Pos 4, 1 Bit
   +0x6b4 JobVadsAreTracked : Pos 5, 1 Bit
   +0x6b4 VadTrackingDisabled : Pos 6, 1 Bit
   +0x6b4 AuxiliaryProcess : Pos 7, 1 Bit
   +0x6b4 SubsystemProcess : Pos 8, 1 Bit
   +0x6b4 IndirectCpuSets  : Pos 9, 1 Bit
   +0x6b4 InPrivate        : Pos 10, 1 Bit
   +0x6b4 ProhibitRemoteImageMap : Pos 11, 1 Bit
   +0x6b4 ProhibitLowILImageMap : Pos 12, 1 Bit
   +0x6b4 SignatureMitigationOptIn : Pos 13, 1 Bit
   +0x6b8 DeviceAsid       : Int4B
   +0x6c0 SvmData          : Ptr64 Void
   +0x6c8 SvmProcessLock   : _EX_PUSH_LOCK
   +0x6d0 SvmLock          : Uint8B
   +0x6d8 SvmProcessDeviceListHead : _LIST_ENTRY
   +0x6e8 LastFreezeInterruptTime : Uint8B
   +0x6f0 DiskCounters     : Ptr64 _PROCESS_DISK_COUNTERS
   +0x6f8 PicoContext      : Ptr64 Void
   +0x700 TrustletIdentity : Uint8B
   +0x708 KeepAliveCounter : Uint4B
   +0x70c NoWakeKeepAliveCounter : Uint4B
   +0x710 HighPriorityFaultsAllowed : Uint4B
   +0x718 EnergyValues     : Ptr64 _PROCESS_ENERGY_VALUES
   +0x720 VmContext        : Ptr64 Void
   +0x728 SequenceNumber   : Uint8B
   +0x730 CreateInterruptTime : Uint8B
   +0x738 CreateUnbiasedInterruptTime : Uint8B
   +0x740 TotalUnbiasedFrozenTime : Uint8B
   +0x748 LastAppStateUpdateTime : Uint8B
   +0x750 LastAppStateUptime : Pos 0, 61 Bits
   +0x750 LastAppState     : Pos 61, 3 Bits
   +0x758 SharedCommitCharge : Uint8B
   +0x760 SharedCommitLock : _EX_PUSH_LOCK
   +0x768 SharedCommitLinks : _LIST_ENTRY
   +0x778 AllowedCpuSets   : Uint8B
   +0x780 DefaultCpuSets   : Uint8B
   +0x778 AllowedCpuSetsIndirect : Ptr64 Uint8B
   +0x780 DefaultCpuSetsIndirect : Ptr64 Uint8B





반응형


윈도우 8/8.1 에서 visual studio 2008 설치하려는데

에러가 발생함.

.NET Framework 3.5 installation error: 0x800F0906, 0x800F081F, 0x800F0907


.net framework 3.5가 설치가 안된다. 인터넷 연결 실패 오류가 뜬다. 실제 인터넷은 연결되어 있는데. ㅡ.ㅡ;;

어쨋거나. 오프라인 설치 방법이 있다.


You can use the Windows installation media as the file source when you enable the .NET Framework 3.5 feature. To do this, follow these steps:

  1. Insert the Windows installation media.
  2. At an elevated command prompt, run the following command:
    Dism /online /enable-feature /featurename:NetFx3 /All /Source:<drive>:\sources\sxs /LimitAccess
    Note In this command, <drive> is a placeholder for the drive letter for the DVD drive or for the Windows 8 installation media. For example, you run the following command:
    Dism /online /enable-feature /featurename:NetFx3 /All /Source:D:\sources\sxs /LimitAccess


https://support.microsoft.com/en-us/kb/2734782


'Develop > Windows' 카테고리의 다른 글

DOS Batch Script  (0) 2019.10.06
curl 사용법/HTTP 테스트  (0) 2019.10.01
화면/윈도우 동영상 녹화 (mp4, gif)  (0) 2019.09.23
windows 10 kernel structure  (0) 2015.08.28
64비트 프로그래밍  (2) 2015.06.05
반응형

제가 2004년도에 윈도우 64비트 프로그래밍을 시작할 때 작성했던 글인데, 우연히 발견하게 되어서 올립니다.

요 약

윈도우즈 운영체제가 32비트에서 64비트로 확장함에 따라 처리 속도 및 효율성 측면에서 성능이 많이 좋아졌다. 그러나, 그 성능을 제대로 발휘하기 위해 대부분 기존의 32비트 프로그램을 64비트로 포팅해야 한다. 그러나 주소 지정 방식이 과거 32비트에서 64비트로 확장됨에 따라 포팅시 고려해야 할 사항들을 정확히 알아야지만, 성공적으로 진행할 수 있을 것이다. 여기서는 윈도우 운영체제의 과거 32비트에서 64비트 플랫폼으로 마이그레이션할 수 있는 포팅 테크닉을 소개한다.

27, Feb, 2004

Written by 크레이지제이

I. 서론

윈도우즈 64비트 운영체제는 개발은 몇 년 전에 되었지만, 아직 베타 테스트 중이다. 앞으로 상용화가 얼마나 잘 이루어질지 모르지만, 사용하는 곳이 많아진다면 소프트웨어나 하드웨어 관련 업체는 모두 적지 않은 영향을 받을 것이다.

64비트 운영체제에서 기존의 32비트 어플리케이션을 지원한다고는 하지만 32비트 레이어를 통해서 내부적으로 64비트 연산 작업이 이루어지기 때문에 속도가 저하될 가능성이 크다. (즉, 주소 자동 변환 과정을 한 번 더 통과해야 한다.) 따라서 64비트 어플리케이션으로 포팅을 하면 별도의 레이어를 통하지 않고, 바로 명령이 수행되기 때문에 높은 성능을 발휘할 것이다.

본 페이퍼에서는 32비트 윈도우 어플리케이션 및 디바이스 드라이버를 64비트로 포팅하기 위한 테크닉 및 Know-How를 기술하는데, 주된 목적은 어떻게 하면 보다 기존의 소스를 그대로 유지하여 32비트, 64비트를 모두 지원하는 방면을 찾는 것이다. 이로 하여금 개발자들의 소스 관리를 편하게 하여, 버그의 발생을 줄일 수 있으며 형상 관리에도 도울을 줄 수 있을 것이다.

II. 윈도우 64비트 운영체제

마이크로소프트에서 현재 64비트를 지원하는 운영체제는 Windows 2003 Enterprise Edition 64-bit, Windows 2003 Datacenter Edition 64-bit, Windows XP 64-bit 가 있다. 아직 국내에는 제대로된 64비트 윈도우 운영체제가 출시되지는 않았다.

윈도우즈 32비트 운영체제에서는 4기가까지의 물리적인 메모리를 지원하나 64비트 운영체제에서는 16 테라 바이트까지 지원할 수 있다. 이로 인해 어플리케이션은 다음과 같은 장점이 생긴다.

메모리 확장으로 인해 어플리케이션에서 더 많은 사용자를 지원할 수 있으며, 보다 높은 성능을 내고, 데이터를 저장 또는 가공 시 더 많은 메모리를 할당할 수 있어 DiskIO가 적게 발생한다.

 

 

III. 64비트 포팅시 주의 사항

64비트 포팅을 위해서는 새로운 데이터 타입이나 Helper 함수들을 사용하기 위해 Platform SDK를 설치해야 한다. Visual Studio 개발도구나 Makefile에서는 Include 디렉토리의 우선 순위를 일반 VC의 include보다 Platform SDK의 include가 높게 해야 한다. (같은 헤더 파일명이 존재할 시, 먼저 참조되도록 해야 한다.)

다음은 32비트 프로그래밍과 64비트 프로그래밍을 하는 경우에 자료구조나 프로그램 구조의 변화나 고려해야될 사항들을 설명하였다.

 

1. 데이터 타입

 

- 과거 데이터 타입 ; 대부분은 변하지 않았으나, 포인터 타입이 64비트로 확장되었다.

* 사이즈가 변경되지 않은 데이터 타입

- char/uchar=8bit, short/ushort=16bits,

- long/ulong=32bits

- LONG과 ULONG = (32 bits)

- INT, UINT, DWORD = (32bits)

- LONGLONG, ULONGLONG = (64bits)

 

* 사이즈가 변경된 데이터 타입

- pointer(char*, PDEVICE_OBJECT... ) = 32bits에서 64bits로 확장되었다.

 

- 새로운 데이터 타입 ; ULONG_PTR, LONG_PTR 타입은 32비트 컴파일러로 컴파일하면 32비트 사이즈로 인식되며, 64비트 컴파일러로 컴파일하면 64비트 사이즈로 인식된다.

 

- 다른 64비트 윈도우 플랫폼과는 달리 AMD64에서는 자료 구조의 "natural" alignment의 실패 (즉, ULONG은 32bit boundary, ULONGLONG은 64비트 boundary로 align하지 못한다.) 가 침형적 에러를 발생시키지 않는다. -> 따라서 이점을 유의하지 않으면, AMD64에서 죽지 않던 것이 다른 곳에서는 블루 스크린을 띄울 수 있다.

 

- 포인터의 정상 사용은 걱정할 필요 없다. 운영체제에 따라 32비트 또는 64비트로 자동으로 인식되기 때문이다.

 

2. 파라미터

 

- 파라미터로 패싱되는 포인터의 자동 인식 ; 32비트 어플리케이션에 의한 포인터 파라미터가 자동으로 64비트로 변경되어 처리된다.

예를 들어 32비트 또는 64비트 어플리케이션에 의한 함수 호출에 관계없이 드라이버에서는 Irp-> UserData 포인터가 64비트로 자동으로 인식될 것이다.

 

3. 버퍼 내 포인터

 

- IOCTL Buffers에 임베디드된 포인터 ;

몇 몇 드라이버들은 주의해야 될 사항이다. IOCTL 버퍼에 포인터가 포함되어 있는 경우, 드라이버는 호출자가 32비트 또는 64비트 어플리케이션 중 어떤 것인지 주의해야만 한다. IOCTL_IN_BUFFER과 OUT_ BUFFER를 가리키는 포인터는 윈도우에 의해 자동으로 변환된다. 그러나, 이 버퍼의 내용에 포인터를 포함하고 있다면, 포팅시 32비트 포인터를 64비트 사이즈로 확장해 주어야 한다.

 

4. 기타

- In-Line Assembler, MMX, 3DNow, and X87 FP 명령어는 지원하지 않는다!!! embedded assembler, MMX, 3DNow, X87 floating pointer는 쓰지 말아라. 다행히 SSE, SSE/2 명령어는 지원한다.

 

간단히 쉽게 정리하자면, 임베디드 어셈블러를 사용하지 말고, IOCTL 버퍼 내에 포인터를 사용하지 않고,(사용하면 64비트로 확장) ULONG을 ULONG_PTR 타입으로 변경(포인터와 관련있다면)하고 컴파일한다.

 

IV. 64비트 포팅 적용

1. 적절한 데이터 타입

 

- 자료 구조에서 포인터를 명시적으로 ULONG타입으로 캐스트하는 경우이다. 컴파일러에 따라 포인터의 사이즈가 달라지기 때문이다. 따라서 이 부분은 ULONG_PTR 타입으로 바꿔주어야 한다.

 

ULONG currentMdl ;

ULONG MdlPointers[10] ;

devExt->MdlPointers[currentMdl++] =

(ULONG) Irp->MdlAddress ;

 

위의 코드는 64비트에서는 작동하지 않는다. 다음과 같이 수정하면 32비트, 64비트가 컴파일러에 따라 모두 적절히 작동된다.

ULONG_PTR MdlPointers[10] ;

devExt->MdlPointers[currentMdl++] =

(ULONG_PTR) Irp->MdlAddress ;

또는

PMDL MdlPointers[10] ;

devExt->MdlPointers[currentMdl++] = (PMDL)

Irp->MdlAddress ;

- Align pointer precision 자료 구조

 

강제로 alignment를 변경하는 pragma는 편할 수 도 있지만 꼭 필요한 경우가 아니면 쓰지 말자.

// #pragma pack(4) // 4 바이트 단위로 정렬

ULONG ulTest ;

ULONG_PTR pTest ;

// #pragma pack() // 해제 (디폴트 단위로..., natural boundary)

구조체에서 필드들의 사이즈는 alignment 단위로 맞춰지기 때문에 자신도 모르게 dummy 메모리가 할당이 된다.

위의 구조체의 크기는 64비트 컴파일러에서 8 byte단위로 alignment가 맞춰지기 때문에 16바이트가 할당이 된다. (32비트 컴파일러에서도 ULONG_PTR대신 64비트 자료형을 써주면 최대 크기인 8바이트 단위로 alignment가 설정된다.) ulTest뒤에 4바이트의 메모리가 더미로 존재하고 8바이트의 pTest가 할당이 되기 때문이다. 강제로 alignment를 4바이트로 설정하는 pragma pack(4) 를 적용하면 12바이트가 되는 것이다.

따라서 명시적으로 dummy 필드를 써 주는 것이 나중을 위해서 좋다. 다음과 같이 구조체 필드를 만들어 확실히 16바이트라는 것을 인지한다.

ULONG ulTest ;

ULONG dummy0; // dummy 추가

ULONG_PTR pTest ;

 

2. The Pointer in DataBuffer

 

전에 설명했던 것과 같이, 64비트 윈도우는 파라미터로 패싱된 포인터를 32비트에서 64비트로 자동 변환한다. 그러나, 전달된 드라이버의 자료구조의 데이터 버퍼 안에 포인터가 존재한다면 어떻게 다뤄야 하는가?

그러한 예는 다음과 같다.

typedef struct _myBuffer {

ULONG Count ;

PUCHAR SecondaryBuffer ;

ULONG SecondaryBufferSize ;

UCHAR Buffer[BUF_SIZE] ;

} MY_BUFFER, *PMY_BUFFER ;

 

32비트 어플리케이션에서 다음과 같은 코드로 작성하였다.

MY_BUFFER buf ;

buf.Count = CharPassed ;

StringCchCopy(buf.Buffer, BUF_SIZE, DataSource, buf.Count) ;

buf.SecondaryBufferSize = OtherBufferSize ;

buf.SecondaryBuffer = PointerToOtherBuffer ;

worked = DeviceIOControl(hDev,

IOCTL_MYDRV_SEND_BUFFER, &buf,

sizeof(MY_BUFFER), NULL, 0,

&byteReturned, NULL) ;

64비트로 포팅하려면 어떻게 해야될 것이다.

 

+ 방법 1

&buf는 자동으로 64비트로 자동으로 인식될 것이다. (thunk buf 포인터 자동 변환)

그러나, 윈도우는 호출자의 IN_BUFFER안에 포인터가 포함되어 있는 줄 모른다.

(SecondaryBuffer) 32비트 또는 64비트 어플리케이션에서 같은 IOCTL을 보낼 때, 버퍼의 적절한 길이와 포인터의 사이즈가 변한다.

어떻게 해결할까? -> 포인터를 없앤다.

typedef struct _myNEWBuffer {

ULONG Count ;

UCHAR Buffer[BUF_SIZE] ;

} MY_NEW_BUFFER, *PMY_NEW_BUFFER ;

secondary buffer는 OUT_BUFFER 파라미터를 이용하여 다음과 같이 할 수 있다.

MY_NEW_BUFFER buf ;

buf.Count = CharsPassed ;

StringCchCopy(buf.Buffer, BUF_SIZE, DataSource, buf.Count) ;

worked = DeviceIOControl(hDev,

IOCTL_MYDRV_SEND_BUFFER, &buf,

sizeof(MY_BUFFER), PointerToOtherBuffer,

OtherBufferSize, &byteReturned, NULL) ;

소스코드와 자료구조가 깨끗해졌다.

위의 방식은 32비트 어플리케이션이 32비트, 64비트 OS 모두 사용할 수 있다. (단, 어떠한 경우라도 드라이버는 32, 64비트용으로 각 각 만들어야 한다.)

 

물론 이러한 방법은 이런 IOCTL 코드를 쓰는 모든 어플리케이션에서 IOCTL 포맷을 새롭게 바꾸고, 모두 다시 컴파일해야 하는 단점이 있다.

 

+ 방법 2

OUT_BUFFER를 사용하지 않고, IN_BUFFER 내에 포인터를 포함시킬 수 있는 방법이다.

 

A 구조체

// Structure version used by all app (and for 64-bit app in Driver)

typedef struct _myBuffer {

ULONG Count ;

PUCHAR SecondaryBuffer ;

ULONG SecondaryBufferSize ;

UCHAR Buffer[BUF_SIZE] ;

} MY_BUFFER, *PMY_BUFFER ;

B 구조체

// Structure version used exclusively by driver when

// getting data from 32-bit apps.

typedef struct _myBuffer_32 {

ULONG Count ;

PUCHAR POINTER_32 SecondaryBuffer ;

ULONG SecondaryBufferSize ;

UCHAR Buffer[BUF_SIZE] ;

} MY_BUFFER_32, *PMY_BUFFER_32 ;

A 구조체는 원본(포팅 전)과 같다.

SecondaryBuffer 포인터가 구조체 내부에 숨겨진 형태로 32비트 어플리케이션에서는 OS에 관계없이 32비트, 64비트 어플리케이션은 64비트 포인터로 인식이 된다. 따라서 32비트용 어플리케이션과 32비트용 드라이버로 컴파일 하고, 64비트용 어플리케이션과 64비트용 드라이버로 컴파일하여 따로 사용할 수 있다.

따라서 운영체제의 커널 비트에 따른 어플리케이션이 별도로 존재해야 하는 단점이 있다.

 

B 구조체는 64비트 윈도우를 위해 만들어진 구조체로써 드라이버가 사용할 것이다. 그러나 32비트 어플리케이션과도 호환된다. 드라이버에서는 호출자가 32비트 어플리케이션 인지 64비트인지를 IoIs32bitProcess()를 통해 확인하여 결정한다.

case IOCTL_MYDRV_SEND_BUFFER:

#ifdef _WIN64

// if it's a 32-bit caller, we validate the size of the 32-bit structure

if (IoIs32bitProcess(Irp))

{

if (ios->Parameters.DeviceIoControl.InputBufferLength >= sizeof(MY_BUFFER_32) )

{..... }

} else

#endif

{

if (ios->Parameters.DeviceIOControl.InputBufferLength

>= sizeof(MY_BUFFER) )

{....}

}

이러한 방식은 32비트 어플리케이션을 위한 구조체를 따로 둠으로써, 64비트 드라이버에서 32, 64비트 어플리케이션을 모두 사용 가능하도록 한다. 그러나 구조체를 각각 관리해야하고, 드라이버에서 32비트를 포인터를 위한 처리를 따로 해 주어야 하는 단점이 있다.

 

3. Inline Assembler, etc...

 

여기서 별도로 다루지는 않겠다. 보다 자세한 정보를 원한다면, Hector가 쓴 OSR Online back in June. 기사를 보면 알 수 있을 것이다.

https://www.osronline.com/article.cfm?id=244

AMD64 컴파일러는 inline assembler code를 지원하지 않는다!!!

또한 윈도우 64비트의 커널모드에서는 MMX, 3DNow, X87 floating point를 지원하지 않는다. !!!

 

 

4. New 3 Class Data Types

 

64비트 프로그래밍을 위해 다음의 세가지 클래스 데이터 타입이 추가되었다.

 

+ Fixed Precision ; 데이터 타입의 사이즈가 고정 길이

DWORD32, DWORD64, INT32, INT64, LONG32, LONG64, UINT32, UINT64, ULONG32, ULONG64

 

+ Pointer Precision ; 포인터 연산을 할 때 사용하면 좋다. 32비트 또는 64비트 윈도우즈에 따라 사이즈가 바뀐다.

DWORD_PTR, HALF_PTR (포인터의 반 크기), INT_PTR, LONG_PTR, SIZE_T, SSIZE_T, UHALF_PTR, UINT_PTR, UINT_PTR, ULONG_PTR

 

+ Specific Pointer-Precision Types

포인터의 사이즈를 명시적으로 선언한다.

POINTER_32 ; 32비트 포인터. 32비트 윈도우에서는 native pointer이지만 64비트에서는 64비트 포인터를 반으로 자른 것이다.

POINTER_64 ; 64비트 포인터. 64비트 윈도우에서는 native pointer이다. 32비트에서는 32비트 포인터를 64비트로 확장시킨 것 임.

 

 

5. Helper Functions (basetsd.h)

 

+ Predefined Macro

_WIN64 ; 64비트 플랫폼

_WIN32 ; 32비트 플랫폼

_WIN16 ; 16비트 플랫폼

 

_M_IA64 ; 64비트 인텔 플랫폼

_M_IX86 ; 32비트 인텔 플랫폼

 

가능하면 위에 있는 _WIN64, _WIN32를 사용하고, 아키텍쳐와 관련된 것을 제외하고는 _M_IA64, _M_IX86 매크로를 쓰지 마라.

 

아래의 API들은 64비트 프로그래밍시 데이터 타입 형 변환에 도움을 준다. 그러나, 꼭 필요한 경우에만 사용해야 한다. 그렇지 않으면 컴파일시 경고나, 에러가 발생하지 않기 때문에 디버깅이 어려워질 수도 있다.

 

unsigned long HandleToUlong( const void *h )

long HandleToLong( const void *h )

void *LongToHandle( const long h )

unsigned long PtrToUlong( const void *p )

unsigned int PtrToUint( const void *p )

unsigned short PtrToUshort( const void *p )

long PtrToLong( const void *p )

int PtrToInt( const void *p )

short PtrToShort( const void *p )

void * IntToPtr( const int i )

void * UIntToPtr( const unsigned int ui )

void * LongToPtr( const long l )

void * ULongToPtr( const unsigned long ul )

 

 

6. 64비트 포인터 사용 규칙

 

- int, long, ULONG, DWORD로 포인터를 타입 캐스팅하면 안 된다.

이 경우 ULONG_PTR 타입을 사용한다.

HANDLE은 void*로 정의되어 있다. 따라서 ULONG으로 캐스팅하면 안 될 것이다.

 

- 필요한 경우 PtrToLong, PtrToUlong을 사용하여 포인터를 truncate시켜라. (helper function)

포인터를 32비트 값으로 자를 때 사용한다.(상위 32비트가 날라간다.) 편하지만 경고가 발생하지 않기 때문에, 디버깅하기가 어려우므로 조심히 사용해야한다.

 

- OUT 파라미터로 사용 시 주의해야 한다.

void func(OUT PULONG *PointerToUlong) ; 이런 함수가 있다고 가정하고...

ULONG ul ;

PULONG lp ;

func((PULONG *)&ul) ;

lp = (PULONG) ul ;

위와 같이 사용하는 경우, func의 두 번째 파라미터는 이중 포인터 타입이다. 64비트인 경우, *PointerToUlong (PULONG)도 64비트이므로 ul (ULONG)과는 사이즈가 다르다.

 

위의 코드를 아래와 같이 수정해야 한다.

PULONG lp ;

func(&lp) ;

- 다중 인터페이스를 조심해야 한다.

(polymorphic interfaces)

다양한 파라미터를 받기 위해 주소 값 또는 정수 등의 값을 DWORD 파라미터를 사용하였다면, UINT_PTR이나 PVOID로 바꿔라.

 

- 새로운 윈도우 클래스 함수를 사용하라.

GetClassLongPtr, GetWindowLongPtr,

SetClassLongPtr, SetWindowLongPtr

GWL_* 대신 GWLP_*를 사용하라.

(winuser.h)

SetWindowLong(hWnd, GWL_WNDPROC,

(LONG)MyWndProc) ;

위의 코드를 다음과 같이 수정하라.

SetWindowLongPtr(hWnd, GWLP_WNDPROC,

(LONG_PTR)MyWndProc) ;

- 모든 윈도우와 클래스 데이터에 접근시 FIELD_OFFSET을 사용하라.

두 번째 포인터가 항상 옵셋 4라고 생각하지 마라. 32비트에서만 유효하다.

 

- LPARAM, WPARAM, LRESULT 타입은 플랫폼에 따라 사이즈가 변하므로 주의해야 한다.

 

7. 기타 정보

 

- 64비트 어플리케이션은 유저 모드 주소 영역이 8테라 바이트이다. 그러나, 다음과 같은 조건의 프로그램은 유저 모드 주소를 2기가 이하에서만 작동하게 할 수 있다.

> 2기가 주소 영역이면 충분하다.

> 많은 pointer truncation 경고가 많다.

> 포인터와 정수형이 마구 섞여 쓰고 있다.

> 32비트 데이터 타입을 쓰는 polymorphism이 코드에 있다.

이러한 경우 아래와 같은 링커 옵션을 준다.

/LARGEADDRESSAWARE:NO

조심할 점은 DLL을 이 옵션으로 만들었다면, 이 DLL을 사용하는 모든 프로그램도 같은 옵션으로 만들어져야만 된다. (이 DLL이 주소를 32비트로 자르기 때문이다.)

 

- Process interoperability

 

64비트 윈도우에서 32비트 어플리케이션을 에뮬레이션 모드에서 돌릴 수 있다. 그러나, 64비트 프로세스는 32비트 DLL을 로드할 수 없다. 그 반대도 마찬가지다.

64비트와 32비트 프로세스 사이의 RPC 통신이 COM 서버를 이용하는 방법이 있긴 하다.

 

- Driver

드라이버를 64비트로 포팅할 경우 다음의 사항을 고려해야 한다.

> 4G 이상을 지원하고 싶다면, Mm64BitPh ysicalAddresses를 사용하여 64비트 주소가 필요한 경우 사용한다. 또한 DEVICE_DESCRIPTI ON 구조체의 Dma64BitAddresses 멤버를 설정하여 64비트 어드레싱을 할 수 있다.

> IO status block은 ULONG_PTR이다.

> IRP stack location은 ULONG_PTR이다.

 

 

- 64비트 프로그래밍 경고 및 에러

warning C4311: 'type cast' : pointer truncation from 'unsigned char *' to 'unsigned long' -> 이러한 에러는 다음과 같은 예에서 발생한다.

buffer = (PUCHAR)srbControl;

(ULONG)buffer += srbControl->HeaderLength;

위의 코드를 아래처럼 수정하라.

buffer = (PUCHAR)srbControl;

(ULONG_PTR)buffer += srbControl->HeaderLength;

- 64-bit Compiler Switches and Warnings

 

컴파일러가 LLP64 데이터 모델인 경우

LLP64로 포팅하는데 -Wp64 -W3 경고 옵션이 도움을 줄 것이다.

C4305: Truncation warning. For example, "return": truncation from "unsigned int64" to "long."

C4311: Truncation warning. For example, "type cast": pointer truncation from "int*_ptr64" to "int"

C4312: Conversion to bigger-size warning. For example, "type cast": conversion from "int" to "int*_ptr64" of greater size.

C4318: Passing zero length. For example, passing constant zero as the length to the memset function.

C4319: Not operator. For example, "~": zero extending "unsigned long" to "unsigned _int64" of greater size.

C4313: Calling the printf family of functions with conflicting conversion type specifiers and arguments. For example, "printf": "%p" in format string conflicts with argument 2 of type "_int64." Another example is the call printf("%x", pointer_value); this causes a truncation of the upper 32 bits. The correct call is printf("%p", pointer_value).

C4244: Same as the existing warning C4242. For example, "return": conversion from "_int64" to "unsigned int," possible loss of data.

 

 V. 결론

이로써 32비트 어플리케이션 및 드라이버를 64비트로 포팅하는데 있어서 주의해야 될 사항들과 어떻게 포팅해야 할 지에 대한 소스코드 예를 몇 가지 살펴보았다.

크게는 별로 변한 게 없는 듯(포인터 사이즈 하나가 변했다고) 하지만, 실제 소스 레벨로 가서 보면 발생할 수 있는 제 2, 제 3의 문제가 연쇄적으로 발생할 수 있음을 알 수 있다. 다른 프로그램과의 통신, 구조체의 사이즈 변형, 포인터 연산, Alignment 등 생각할 것도 많고, 소스코드를 32비트, 64비트 머신 모두에게 돌아갈 수 있도록 유지할 수 있게 고뇌해야할 것이다.



참 고

 

 

1. Rock On With 64-bit Windows -- Porting Windows Drivers To AMD64 ;

http://www.osronline.com/article.cfm?id=265

 

2. Platform SDK: 64-bit Windows Programming

http://www.msdn.microsoft.com/library/default.asp?url=/library/en-us/win64/win64/changing_an_existing_interface.asp

 

 

+ Recent posts