Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 Q&A
Delphi Programming Q&A
[14714] Re: COM 코드 어셈블러로 작성한 것임
지나다가 [] 2334 읽음    2013-06-20 08:43
엠바카데로의 터보 어셈블러가 버그가 있어서, MS사의 매크로 어셈블러로 작성한 것임.
TASM으로는 64bit Structured Exception Handling 코드도 작성할 수 없음.

엠바 애들 물건을 이런 식으로 개판으로 만들면서 돈 받고 팔아 먹는거 보면 신기함 ㅋ

다음은 MS 매크로 어셈블러로 작성한 소스코드임.

	
	.686P
	.XMM
	.model	flat

	EXTRN	_setlocale:PROC
	EXTRN	_PKEY_Device_FriendlyName:BYTE
	EXTRN	__imp__PropVariantClear@4:PROC
	EXTRN	__imp__CoInitialize@4:PROC
	EXTRN	_printf:PROC
	EXTRN	_atoi:PROC
	EXTRN	__imp__CoCreateInstance@20:PROC

STATICDATA	SEGMENT

__GUID_f8679f50_850a_41cf_9c72_430f290290c8 DD 0f8679f50H
	DW	0850aH
	DW	041cfH
	DB	09cH
	DB	072H
	DB	043H
	DB	0fH
	DB	029H
	DB	02H
	DB	090H
	DB	0c8H

__GUID_a95664d2_9614_4f35_a746_de8db63617e6 DD 0a95664d2H
	DW	09614H
	DW	04f35H
	DB	0a7H
	DB	046H
	DB	0deH
	DB	08dH
	DB	0b6H
	DB	036H
	DB	017H
	DB	0e6H

__GUID_bcde0395_e52f_467c_8e3d_c4579291692e DD 0bcde0395H
	DW	0e52fH
	DW	0467cH
	DB	08eH
	DB	03dH
	DB	0c4H
	DB	057H
	DB	092H
	DB	091H
	DB	069H
	DB	02eH

__GUID_870af99c_171d_4f9e_af0d_e63df40c2bc9 DD 0870af99cH
	DW	0171dH
	DW	04f9eH
	DB	0afH
	DB	0dH
	DB	0e6H
	DB	03dH
	DB	0f4H
	DB	0cH
	DB	02bH
	DB	0c9H

sLocale DB 'kor', 00H
sDevN DB 'Device Number[%d]: %ws', 0aH, 00H

sCurDev DB 0aH, 'Current Default Device: %ws', 0aH, 0aH, 00H
STATICDATA	ENDS

PUBLIC	_main
_TEXT	SEGMENT
_devConfig@@ = -4		

myChangeInternalDevice PROC	

	push	ecx
	push	esi

	lea	eax, DWORD PTR _devConfig@@[esp+8]
	push	eax
	push	OFFSET __GUID_f8679f50_850a_41cf_9c72_430f290290c8
	push	23				
	push	0
	push	OFFSET __GUID_870af99c_171d_4f9e_af0d_e63df40c2bc9
	mov	esi, ecx
	call	DWORD PTR __imp__CoCreateInstance@20

	test	eax, eax
	js	SHORT @@noAction

	mov	eax, DWORD PTR _devConfig@@[esp+8]
	push	1
	mov	ecx, DWORD PTR [eax]
	push	esi
	push	eax
	call	DWORD PTR [ecx+52]

	mov	ecx, DWORD PTR _devConfig@@[esp+8]
	push	ecx
	mov	edx, DWORD PTR [ecx]
	mov	esi, eax
	call	DWORD PTR [edx+8]

@@noAction:

	pop	esi
	pop	ecx
	ret	
myChangeInternalDevice ENDP	


_Device@@ = -28		
_Store@@ = -24			
_friendlyName@@ = -20	

myPrintDefaultDevice PROC

	sub	esp, 28	

	mov	eax, DWORD PTR [ecx]
	lea	edx, DWORD PTR _Device@@[esp+28]
	push	edx
	push	1
	push	0
	push	ecx
	mov	DWORD PTR _Device@@[esp+44], 0
	call	DWORD PTR [eax+16]

	mov	eax, DWORD PTR _Device@@[esp+28]
	lea	edx, DWORD PTR _Store@@[esp+28]
	push	edx
	mov	DWORD PTR _Store@@[esp+32], 0
	mov	ecx, DWORD PTR [eax]
	push	0
	push	eax
	call	DWORD PTR [ecx+16]

	mov	eax, DWORD PTR _Device@@[esp+28]
	push	eax
	mov	ecx, DWORD PTR [eax]
	call	DWORD PTR [ecx+8]

	mov	eax, DWORD PTR _Store@@[esp+28]
	lea	edx, DWORD PTR _friendlyName@@[esp+28]
	xorps	xmm0, xmm0
	push	edx
	movq	QWORD PTR _friendlyName@@[esp+32], xmm0
	movq	QWORD PTR _friendlyName@@[esp+40], xmm0
	mov	ecx, DWORD PTR [eax]
	push	OFFSET _PKEY_Device_FriendlyName
	push	eax
	call	DWORD PTR [ecx+20]

	mov	eax, DWORD PTR _Store@@[esp+28]
	push	eax
	mov	ecx, DWORD PTR [eax]
	call	DWORD PTR [ecx+8]

	push	DWORD PTR _friendlyName@@[esp+36]
	push	OFFSET sCurDev
	call	_printf
	add	esp, 8

	lea	eax, DWORD PTR _friendlyName@@[esp+28]
	push	eax
	call	DWORD PTR __imp__PropVariantClear@4

	add	esp, 28			
	ret
myPrintDefaultDevice ENDP


_Device$$ = -44	
_Enum$$ = -40		
_Store$$ = -36		
_loopCount$$ = -32	
_Devices$$ = -28	
_Param$$ = -24		
_devID$$ = -20		
_friendlyName$$ = -16	

_main	PROC
	push	ebp
	mov	ebp, esp

	and	esp, 0fffffff0H
	sub	esp, 56	
	push	esi
	push	edi

	push	OFFSET sLocale
	push	0
	call	_setlocale
	add	esp, 8

	cmp	DWORD PTR [ebp+8], 2
	mov	DWORD PTR _Param$$[esp+64], -1
	jne	SHORT @@skipParam
	mov	eax, DWORD PTR [ebp+12]
	push	DWORD PTR [eax+4]
	call	_atoi
	add	esp, 4
	mov	DWORD PTR _Param$$[esp+64], eax

@@skipParam:

	push	0
	call	DWORD PTR __imp__CoInitialize@4
	mov	esi, eax

	mov	DWORD PTR _Enum$$[esp+64], 0

	test	esi, esi
	js	@@fail

	lea	eax, DWORD PTR _Enum$$[esp+64]
	push	eax
	push	OFFSET __GUID_a95664d2_9614_4f35_a746_de8db63617e6
	push	23		
	push	0
	push	OFFSET __GUID_bcde0395_e52f_467c_8e3d_c4579291692e
	call	DWORD PTR __imp__CoCreateInstance@20
	mov	esi, eax

	test	esi, esi
	js	@@fail

	mov	eax, DWORD PTR _Enum$$[esp+64]
	lea	edx, DWORD PTR _Devices$$[esp+64]
	mov	ecx, DWORD PTR [eax]
	push	edx
	push	1
	push	0
	push	eax
	call	DWORD PTR [ecx+12]
	mov	esi, eax

	test	esi, esi
	js	@@fail

	mov	eax, DWORD PTR _Devices$$[esp+64]
	lea	edx, DWORD PTR _loopCount$$[esp+64]
	mov	DWORD PTR _loopCount$$[esp+64], 0
	mov	ecx, DWORD PTR [eax]
	push	edx
	push	eax
	call	DWORD PTR [ecx+12]

	xor	edi, edi
	cmp	DWORD PTR _loopCount$$[esp+64], edi
	jbe	@@fail

@@loop:

	mov	eax, DWORD PTR _Devices$$[esp+64]
	lea	edx, DWORD PTR _Device$$[esp+64]
	push	edx
	mov	DWORD PTR _Device$$[esp+68], 0
	mov	ecx, DWORD PTR [eax]
	push	edi
	push	eax
	call	DWORD PTR [ecx+16]
	mov	esi, eax

	test	esi, esi
	js	@@skip

	mov	eax, DWORD PTR _Device$$[esp+64]
	lea	edx, DWORD PTR _devID$$[esp+64]
	mov	DWORD PTR _devID$$[esp+64], 0
	mov	ecx, DWORD PTR [eax]
	push	edx
	push	eax
	call	DWORD PTR [ecx+20]
	mov	esi, eax

	test	esi, esi
	js	@@skip

	mov	eax, DWORD PTR _Device$$[esp+64]
	lea	edx, DWORD PTR _Store$$[esp+64]
	push	edx
	mov	DWORD PTR _Store$$[esp+68], 0
	mov	ecx, DWORD PTR [eax]
	push	0
	push	eax
	call	DWORD PTR [ecx+16]
	mov	esi, eax

	test	esi, esi
	js	SHORT @@skip

	mov	eax, DWORD PTR _Device$$[esp+64]
	push	eax
	mov	ecx, DWORD PTR [eax]
	call	DWORD PTR [ecx+8]

	mov	eax, DWORD PTR _Store$$[esp+64]
	lea	edx, DWORD PTR _friendlyName$$[esp+64]
	push	edx
	xorps	xmm0, xmm0
	movdqa	XMMWORD PTR _friendlyName$$[esp+68], xmm0
	mov	ecx, DWORD PTR [eax]
	push	OFFSET _PKEY_Device_FriendlyName
	push	eax
	call	DWORD PTR [ecx+20]
	mov	esi, eax

	test	esi, esi
	js	SHORT @@skip

	mov	eax, DWORD PTR _Store$$[esp+64]
	push	eax
	mov	ecx, DWORD PTR [eax]
	call	DWORD PTR [ecx+8]

	push	DWORD PTR _friendlyName$$[esp+72]
	push	edi
	push	OFFSET sDevN
	call	_printf
	add	esp, 12	

	lea	eax, DWORD PTR _friendlyName$$[esp+64]
	push	eax
	call	DWORD PTR __imp__PropVariantClear@4

	cmp	edi, DWORD PTR _Param$$[esp+64]
	jne	SHORT @@skip

	mov	ecx, DWORD PTR _devID$$[esp+64]
	call	myChangeInternalDevice 

@@skip:

	inc	edi
	cmp	edi, DWORD PTR _loopCount$$[esp+64]
	jb	@@loop

@@fail:

	mov	eax, DWORD PTR _Devices$$[esp+64]
	push	eax
	mov	ecx, DWORD PTR [eax]
	call	DWORD PTR [ecx+8]

	mov	ecx, DWORD PTR _Enum$$[esp+64]
	call	myPrintDefaultDevice

	mov	eax, DWORD PTR _Enum$$[esp+64]
	push	eax
	mov	ecx, DWORD PTR [eax]
	call	DWORD PTR [ecx+8]

	pop	edi
	mov	eax, esi
	pop	esi
	mov	esp, ebp
	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
	END


Visual Studio 개발환경 Command Prompt 창 열어 놓고, 아래와 같이 build.bat을 실행하면 컴파일/링크가 될 것임.




파라미터 없이 다음과 같이 test.exe 를 실행하면, 현재 PC에 있는 Audio Endpoint Device 들이 출력될 것임.
내컴엔 메인보드 내장형의 리얼텍과 사운드 블라스트가 같이 설치되어 있고, 기본 사운드 장치로 사블의 SPDIF가
선택되어 있는 상태임.




이 상태에서 "test 2"로 Device Number가 2인 장치를 선택하도록 파라미터를 넘겨주면 다음과 같이 기본 사운드 장치가 바뀌게 됨.




COM을 프로그래밍 해본 경험이 있다면, 작성된 소스 코드를 이해하는데 별 어려움이 없을 것임. 파일도 같이 첨부함.

사족으로 낼모레면 환갑인 사람도 이렇게 닭짓을 하는데, 젊은 사람이 그렇게 노력 없이 거저 먹으려고 하는 건 ㅋ






하두고 님이 쓰신 글 :
: 로그인을 안했더니 이름 없이 답변이 올라가네요.
: 버그인가? 아니면 마음씨 좋은 관리자님의 배려?
:
: 힌트를 주셔서 감사하구요.
:
: 너무 거저 먹으려 해서 죄송 한데요.
: 혹시 테스트했던 자료가 남아 있으면 주실 수 없는지요?
:
:  님이 쓰신 글 :
: : 헐....
: : 그 어려운걸 저보고 하라니요....
: : 나 이제 죽었다....
: :
: : 그래도 캄캄했는데 힌트라도 주시니 감사합니다.
: :
: : 지나다가 님이 쓰신 글 :
: : : COM 오브젝트를 인젝션해서 분석해 보면 답이 나옴 ㅋ.
: : :
: : : 기본 사운드 장치 선택은 rundll32.exe 라는 호스트 프로세스에 의해서 로드 되는 mmsys.cpl 이라는
: : : Control Panel Applet에 의해서 선택되게 되어있고,
: : :
: : : class GUID가 870af99c_171d_4f9e_af0d_e63df40c2bc9 인 COM 객체를 통해서,
: : : GUID가 f8679f50_850a_41cf_9c72_430f290290c8 인 Interface 를 취하고 있음.
: : :
: : : MS사에서 이와 관련한 COM Interface에 대한 헤더파일을 제공하고 있지 않기 때문에 Interface 이름에 대해선 알수 없지만
: : : 내부적으로 사용하는 이름이 SetDefaultEndpointDevice? 정도가 아닐까 하는 추론이 가능함.
: : :
: : : GUID가 f8679f50_850a_41cf_9c72_430f290290c8 인 COM Interface의 Virtual Method Table을 분석해 보면
: : : 도합 12개의 Virtual Method를 정의해서 사용하고 있는 것을 알수 있는데,
: : :
: : : 이중 0 기준으로 10번째 인덱스로 정의 되어 있는 인터페이스 버추얼 메소드가 사운드 기본장치를 선택하는데 사용되고 있음
: : :
: : : IMMDeviceEnumerator 로 얻은 스트롱 네임의 Endpoint Device ID 중에 하나를 파라미터로 이 인터페이스에 Dummy 값 하나와
: : : 같이 넘겨주면 제어판 경유 없이, 다이렉트로 프로그래밍 방법으로 강제적으로 원하는 기본 사운드 장치를 선택할 수 있음.
: : :
: : : 테스트 해보니까 Win7, Win8 다 먹힘 ㅋ
: : :
: : :
: : :
: : :
: : :
: : :
: : :
: : :
: : : 하두고 님이 쓰신 글 :
: : : : 그냥 제어판의 사운드창을 백그라운드에 띄워놓고
: : : : 창에 나열된 사운드 장치 정보를 읽어서
: : : : 선택한 후 [기본장치]버튼을 눌러주도록 해서 처리했습니다.
: : : : 뭐 간단하게 해결되네요.
: : : :
: : : : 하지만 문제는 사운드 장치 이름만 읽어오고
: : : : 장치 이름 아래 있는 설명을 읽어올 수 없어 사운드 장치가 모두 "스피커"라고 표시되서
: : : : 도데체 어느 스피커가 어떤 사운드 장치의 스피커인지 알 수가 없네요.
: : : :
: : : : 리버스엔지니어링 님이 쓰신 글 :
: : : : : 윈도우에서 디폴트 사운드 장치를 선택하는 방법은 제어판을 통한 방법 밖에 없습니다
: : : : : MS에서 그런 API를 제공했다간 사운드카드 만드는 회사들이 경쟁적으로 자기들 카드를 디폴트 사운드장치로
: : : : : 설정하려는 사태가 벌어지겠죠. 여러 사운드장치 중 하나로 웨이브 데이타가 출력되게 할수는 있어도 시스템 디폴트
: : : : : 사운드장치를 선택해주는 API는 없습니다.
: : : : :
: : : : : 해결 방법은 비스타 이후 COM으로 바뀐 윈도우 오디오 아키텍쳐를 리버스엔지니어링으로 해킹하는 방법 밖에는 없습니다.
: : : : : COM은 일반적인 API처럼 노출되는게 아니라 해킹하기도 쉽지 않습니다. 그럼에도 불구하고 정 필요하고 패이 조건이 맞으면
: : : : : 리버스엔지니어링으로 해킹해 드릴 수는 있습니다
: : : : :
: : : : :
: : : : :
: : : : : 하두고 님이 쓰신 글 :
: : : : : : 앞에서 했던 질문인데 시원한 답변이 없어 여기 저기 돌아다니며  찾은 소스코드입니다.
: : : : : : 아래 소스코드는 피시에 장착된 사운드장치를 나열하는 소스코드인데요.
: : : : : :
: : : : : : 아래 소스에서 나열된 사운드장치를 선택하여 더블클릭하면
: : : : : : 해당 사운드장치가 윈도우 기본 사운드장치로 바뀌게 하고 싶은데요.
: : : : : :
: : : : : : 기본 사운드 장치를 바꾸는 방법을 모르겠습니다.
: : : : : :
: : : : : : procedure TForm1.EnumAudioDevices;
: : : : : : var
: : : : : :   dsCreateDevEnum  : ICreateDevEnum;
: : : : : :   EnumDevice       : IEnumMoniker;
: : : : : :   DeviceMoniker    : IMoniker;
: : : : : :   Data             : Integer;
: : : : : :   DevicePropBag    : IPropertyBag;
: : : : : :   DeviceName       : OLEVariant;
: : : : : : begin
: : : : : :   If CoCreateInstance(CLSID_SystemDeviceEnum,nil,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,dsCreateDevEnum) = S_OK then
: : : : : :   Begin
: : : : : :     If dsCreateDevEnum.CreateClassEnumerator(CLSID_AudioRendererCategory,EnumDevice,0) = S_OK then
: : : : : :     Begin
: : : : : :       EnumDevice.Reset;
: : : : : :       While EnumDevice.Next(1,DeviceMoniker,@Data) = S_OK do
: : : : : :       Begin
: : : : : :         If DeviceMoniker.BindToStorage(nil,nil,IID_IPropertyBag,DevicePropBag) = NOERROR then
: : : : : :         Begin
: : : : : :           If DevicePropBag.Read('FriendlyName',DeviceName,nil) = NOERROR then
: : : : : :              IF Copy(DeviceName, 1, Length('DirectSound')) = 'DirectSound' Then
: : : : : :                 ListBox1.Items.Add(Copy(DeviceName, Length('DirectSound: ') + 1, Length(DeviceName) - Length('DirectSound: ')));
: : : : : :           DevicePropBag := nil;
: : : : : :         End;
: : : : : :         DeviceMoniker := nil;
: : : : : :       End;
: : : : : :       EnumDevice := nil;
: : : : : :     End;
: : : : : :     dsCreateDevEnum := nil;
: : : : : :   End;
: : : : : : End;

+ -

관련 글 리스트
14707 사운드장치 리스트 소스코드입니다. 여기서 기본 사운드장치 설정 방법 좀 알려주세요. 하두고 2657 2013/06/14
14709     Re: 뭔가 착각하고 있나 보네요 리버스엔지니어링 2117 2013/06/17
14710         Re:Re: 뭔가 착각하고 있나 보네요 하두고 2078 2013/06/17
14711             Re: COM 오브젝트를 인젝션해서 분석해보면 답이 나옴 지나다가 2230 2013/06/19
14712                 Re:Re: COM 오브젝트를 인젝션해서 분석해보면 답이 나옴 2072 2013/06/19
14713                     Re:Re:Re: COM 오브젝트를 인젝션해서 분석해보면 답이 나옴 하두고 1971 2013/06/19
14714                         Re: COM 코드 어셈블러로 작성한 것임 지나다가 2334 2013/06/20
14718                             Re:Re: COM을 어셈블러로 코딩하시다니 헐~ 델파이 2194 2013/06/22
14716                             Re:Re: 인젝션이 안 걸리는데요? 궁금이 1932 2013/06/20
14717                                 Re:Re:Re: 인젝션이 안 걸리는데요? 지나다가 2206 2013/06/20
14715                             Re:Re: 어셈코드 올려서 약올리는거 같아서 ... Lyn 2221 2013/06/20
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.