DEVMODE stMode ;
ZeroMemory(&stMode, sizeof(DEVMODE));
stMode.dmSize = sizeof(DEVMODE);
stMode.dmBitsPerPel = 16; // 16비트 칼라로 변경
stMode.dmPelsWidth = 1024; // 프로그램 실행위한 최소 가로 해상도
stMode.dmPelsHeight = 768; // 프로그램 실행위한 최소 세로 해상도
stMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
ChangeDisplaySettings(&stMode, CDS_FULLSCREEN );
분류 전체보기
- 해상도 변경 2009.02.13
- IAMStreamConfig 인터페이스 사용 예 2009.02.13
- 투명 윈도우 만들기 2009.02.13
- 프레임 정보(수,크기) 조절하기 2009.02.13
- 현재 모듈의 실행경로 얻어오기 2009.02.13
- DMO 필터 사용하기 2009.02.13
- 프로세스 실행시키고 작업이 완료되기까지 기다리기 2009.02.13
- 한글인지 영문인지 한자인지... 2009.02.13
- ActiveX 컨트롤 테스트 인증서 2009.02.13
- ActiveX에서 IObjectSafety 구현하기(MFC) 2009.02.13
해상도 변경
2009. 2. 13. 10:43
IAMStreamConfig 인터페이스 사용 예
2009. 2. 13. 10:42
IEnumPins *pEnumPins;
pFilterMP3Encoder->EnumPins(&pEnumPins);
IPin *pPin;
PIN_DIRECTION PinDir;
while(pEnumPins->Next(1, &pPin, 0)==S_OK) {
pPin->QueryDirection(&PinDir);
if(PinDir == PINDIR_OUTPUT) {
CComQIPtr pAMSC (pPin);
int iCount, iSize;
AUDIO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmt;
pAMSC->GetNumberOfCapabilities(&iCount, &iSize);
if (sizeof(scc) != iSize)
{
// This is not the structure we were expecting.
return E_FAIL;
}
// Get the first format.
hr = pAMSC->GetStreamCaps(0, &pmt, reinterpret_cast<byte*>(&scc));
if (hr == S_OK)
{
if (pmt->formattype == FORMAT_WaveFormatEx &&
pmt->subtype == FORMAT_DYNA_MPEG3)
{
// Modify the format block.
WAVEFORMATEX *wave =
reinterpret_cast<waveformatex*>(pmt->pbFormat);
wave->nSamplesPerSec = 22050;
// Now set the format.
hr = pAMSC->SetFormat(pmt);
if (FAILED(hr))
{
AfxMessageBox("SetFormat Failed");
}
DeleteMediaType(pmt);
}
}
break;
}
}
투명 윈도우 만들기
2009. 2. 13. 10:40
// 상수 정의
#ifndef WS_EX_LAYERED
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
#endif
// USER32.DLL 에서 import할 함수형
typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
// 멤버변수로 보관
lpfnSetLayeredWindowAttributes m_pSetLayeredWindowAttributes;
// 이제부터 코드 추가 부분...
// USER32.DLL로부터 함수를 import한다.
HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
m_pSetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes)GetProcAddress(hUser32, "SetLayeredWindowAttributes");
// import가 제대로 됐는지 체크한다.
if (NULL == m_pSetLayeredWindowAttributes)
return FALSE;
// 다이얼로그의 현재 상태를 체크하고 WS_EX_LAYERED 속성을 추가한다.
SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
// 윈도우를 70% 가시화
m_pSetLayeredWindowAttributes(m_hWnd, 0, (255 / 70) * 100, LWA_ALPHA);
프레임 정보(수,크기) 조절하기
2009. 2. 13. 10:38
// !!! What if this interface isnt supported?
// we use this interface to set the frame rate and get the capture size
if (hr != NOERROR)
{
hr = m_pCapBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, m_pVCapFilter,
IID_IAMStreamConfig, (void **)&m_pVStreamConfig);
if (hr != NOERROR)
{
// this means we cant set frame
rate (non-DV only)
ErrMsg("Error %x: Cannot find VCapture:IAMStreamConfig", hr);
return hr;
}
}
AM_MEDIA_TYPE *pmt;
// default capture format
if (m_pVStreamConfig && m_pVStreamConfig->GetFormat(&pmt) == S_OK)
{
// DV capture does not use a VIDEOINFOHEADER
if (pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
if(pmt->subtype == MEDIASUBTYPE_RGB24)
{
pmt->lSampleSize = (LONG)(_DEFAULT_CAP_WIDTH * _DEFAULT_CAP_HEIGHT * 3); // sample size calc
pvi->bmiHeader.biSizeImage = pmt->lSampleSize;
}
/// 프레임 조절
pvi->AvgTimePerFrame = (LONGLONG)(10000000 / m_fFramerate); // frames
pvi->bmiHeader.biWidth = _DEFAULT_CAP_WIDTH; // frame width
pvi->bmiHeader.biHeight = _DEFAULT_CAP_HEIGHT; // frame height
// resize our window to the default capture size
// ResizeWindow(HEADER(pmt->pbFormat)->biWidth,
// ABS(HEADER(pmt->pbFormat)->biHeight));
m_pVStreamConfig->SetFormat(pmt);
}
DeleteMediaType(pmt);
}
// we use this interface to set the frame rate and get the capture size
if (hr != NOERROR)
{
hr = m_pCapBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, m_pVCapFilter,
IID_IAMStreamConfig, (void **)&m_pVStreamConfig);
if (hr != NOERROR)
{
// this means we cant set frame
rate (non-DV only)
ErrMsg("Error %x: Cannot find VCapture:IAMStreamConfig", hr);
return hr;
}
}
AM_MEDIA_TYPE *pmt;
// default capture format
if (m_pVStreamConfig && m_pVStreamConfig->GetFormat(&pmt) == S_OK)
{
// DV capture does not use a VIDEOINFOHEADER
if (pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *)pmt->pbFormat;
if(pmt->subtype == MEDIASUBTYPE_RGB24)
{
pmt->lSampleSize = (LONG)(_DEFAULT_CAP_WIDTH * _DEFAULT_CAP_HEIGHT * 3); // sample size calc
pvi->bmiHeader.biSizeImage = pmt->lSampleSize;
}
/// 프레임 조절
pvi->AvgTimePerFrame = (LONGLONG)(10000000 / m_fFramerate); // frames
pvi->bmiHeader.biWidth = _DEFAULT_CAP_WIDTH; // frame width
pvi->bmiHeader.biHeight = _DEFAULT_CAP_HEIGHT; // frame height
// resize our window to the default capture size
// ResizeWindow(HEADER(pmt->pbFormat)->biWidth,
// ABS(HEADER(pmt->pbFormat)->biHeight));
m_pVStreamConfig->SetFormat(pmt);
}
DeleteMediaType(pmt);
}
현재 모듈의 실행경로 얻어오기
2009. 2. 13. 10:25
char szProgrampath[_MAX_PATH], szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
GetModuleFileName( NULL, szProgrampath, _MAX_PATH);
_splitpath(szProgrampath, szDrive, szDir, NULL, NULL);
// 멤버변수 m_strPath에 담는다.
m_strPath.Format("%s%s", szDrive, szDir);
DMO 필터 사용하기
2009. 2. 13. 10:19
#include <Dmodshow.h>
IBaseFilter *pFilter;
hr = CoCreateInstance(CLSID_DMOWrapperFilter, NULL,
CLSCTX_INPROC_SERVER, IID_IBaseFilter,
reinterpret_cast(&pFilter));
if (SUCCEEDED(hr))
{
// Query for IDMOWrapperFilter.
IDMOWrapperFilter *pDmoWrapper;
hr = pFilter->QueryInterface(IID_IDMOWrapperFilter,
reinterpret_cast<void**>(&pDmoWrapper));
if (SUCCEEDED(hr))
{
// Initialize the filter.
hr = pDmoWrapper->Init(CLSID_DYNA_MPEG43DMO, CLSID_LegacyAmFilterCategory);
pDmoWrapper->Release();
if (SUCCEEDED(hr))
{
// Add the filter to the graph.
hr = m_pGB->AddFilter(pFilter, L"Mpeg43 Decoder DMO");
}
}
pFilter->Release();
}
// Dmoguids.lib 라이브러리 추가프로세스 실행시키고 작업이 완료되기까지 기다리기
2009. 2. 13. 10:15
프로세스를 실행시키고.. 해당프로세스의 작업이 완료되었는지 기다린뒤 다음 코드를 수행하는 루틴
CString strDir;
char szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
_splitpath(g_strFilePath.GetBuffer(g_strFilePath.GetLength()),szDrive,szDir,NULL,NULL);
strDir.Format("%s%s",szDrive,szDir);
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof (SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = "open";
sei.lpFile = g_strFilePath;
sei.lpDirectory = strDir.GetBuffer(strDir.Length());
sei.lpParameter = "test.txt -t.."
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteEx (&sei))
{
WaitForSingleObject (sei.hProcess, INFINITE);
}
// 익스플로러 띄우기..
ShellExecute(NULL, "open", "iexplore.exe", "http://dynaforce.tistory..com", NULL, SW_SHOWNORMAL);
////////////////////////////////////////////////////////////////////////////////////////////
WaitForSingleObject앞에
WaitForInputIdle(sei.hProcess, INFINITE);//해당프로그램이 초기화완료될때까지 대기
프로그램의 초기화 시간이 긴 경우 사용
ps. ShellExecuteEx안에서 CreateProcess를 내부적으로 호출
CString strDir;
char szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
_splitpath(g_strFilePath.GetBuffer(g_strFilePath.GetLength()),szDrive,szDir,NULL,NULL);
strDir.Format("%s%s",szDrive,szDir);
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof (SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = "open";
sei.lpFile = g_strFilePath;
sei.lpDirectory = strDir.GetBuffer(strDir.Length());
sei.lpParameter = "test.txt -t.."
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteEx (&sei))
{
WaitForSingleObject (sei.hProcess, INFINITE);
}
// 익스플로러 띄우기..
ShellExecute(NULL, "open", "iexplore.exe", "http://dynaforce.tistory..com", NULL, SW_SHOWNORMAL);
////////////////////////////////////////////////////////////////////////////////////////////
WaitForSingleObject앞에
WaitForInputIdle(sei.hProcess, INFINITE);//해당프로그램이 초기화완료될때까지 대기
프로그램의 초기화 시간이 긴 경우 사용
ps. ShellExecuteEx안에서 CreateProcess를 내부적으로 호출
한글인지 영문인지 한자인지...
2009. 2. 13. 10:10
0x80은 DBCS를 알수 있게 해주는 Mask입니다.
char character;
WORD chDBCS;
if (character & 0x80) {
// DBCS
if ( ( chDBCS = (character << 8) ) > 0xCAA0) {
// Hanja character
}
// Hangeul character
} else {
// SBCS
if (character < 0x41) {
// Symbol..
if (character < 0x20) {
// System Char
} else if (character >= '0' && character <='9') {
// Numeric characters..
} else {
// Symbol
}
} else if (character >= 0x5B && character <= 0x60) {
// Symbol 2..
} else if (character > 0x7A) {
// Symbol 3..
} else {
// Alphabet.
}
}
ActiveX 컨트롤 테스트 인증서
2009. 2. 13. 10:05
ActiveX 컨트롤 테스트 인증서
밑에 글(ActiveX 컨트롤에서 IObjectSafety 구현하기)에서 개인개발자나 시험용으로 만든 ActiveX 컨트롤을 컨테이너(IE)에서 사용할 때, 인증문제에 대한 것이 있었다.
이 파일은 그 문제를 잠시나마 해결하기 위해 ActiveX컨트롤에 인증서를 포함하여 Cab파일을 작성하게 하는 프로그램이다.
테스트 인증서 작성 -> Cab 작성 -> SignCode -> Check 등의 작업이 배치파일(sign50.bat)로 작성되어 있다.
inf파일을 문법에 맞게 구성한 후, sign50.bat를 실행하면 작성된다.
Test.html은 웹페이지에서 ActiveX 컨트롤을 사용하는 예제이고, 이 압축파일은 미니프로제트를 수행했을때 만들었던 ActiveX 컨트롤을 포함하고 있다.
--------------------------------------------------------------------------
배포
1) ActiveX 컨트롤을 각 PC에 복사
2) 그 컨트롤을 레지스트리에 등록
3) 필요한 DLL이 있다면 복사
=> 자동으로...
Cab 파일을 통해 위의 내용들을 자동화 시켜줌...
1) .inf 파일 작성
2) .ocx 파일과 .inf 파일을 .cab 파일로 압축
3) .cab 파일을 서명
4) .cab 파일을 웹페이지에 등록
//
1) .inf 파일 생성
=> VC 6.0 제공이 안됨...
=> 배포될 .ocx및 dll의 정보를 담고 있다...
2) .cab 파일 생성
=> cabarc.exe 유틸리티를 통해 생성...
cabarc.exe N test.cab test.ocx test.inf (step1.bat)
=> test.cab 파일 생성( 압축파일..)
3) .cab 서명
makecert -sv "mycert.pvk" -n "CN=TEST ActiveX" mycert.cer
=> 대화상자 생성 => 암호 입력 => 개인 키 파일(mycert.pvk, mycert.cer)
생성
cert2spec mycert.cer mycert.spc
=> mycert.cer로부터 mycert.spc를 생성 ( makespc.bat 사용)
컨트롤 서명
signcode -v mycert.pvk -spc mycert.spc test.cab
=> test용 .cab 파일을 인증하는 코드
인증기관에서 제대로된 인증을 받으려면 위 명령줄에 -t 인증기관 URL을 추가
setreg -q 1 TRUE
=> test용 인증서가 인식되도록 설정
chktrust test.cab
=> CAB 파일이 올바르게 서명되었는지 확인...(step2.bat..)
밑에 글(ActiveX 컨트롤에서 IObjectSafety 구현하기)에서 개인개발자나 시험용으로 만든 ActiveX 컨트롤을 컨테이너(IE)에서 사용할 때, 인증문제에 대한 것이 있었다.
이 파일은 그 문제를 잠시나마 해결하기 위해 ActiveX컨트롤에 인증서를 포함하여 Cab파일을 작성하게 하는 프로그램이다.
테스트 인증서 작성 -> Cab 작성 -> SignCode -> Check 등의 작업이 배치파일(sign50.bat)로 작성되어 있다.
inf파일을 문법에 맞게 구성한 후, sign50.bat를 실행하면 작성된다.
Test.html은 웹페이지에서 ActiveX 컨트롤을 사용하는 예제이고, 이 압축파일은 미니프로제트를 수행했을때 만들었던 ActiveX 컨트롤을 포함하고 있다.
--------------------------------------------------------------------------
배포
1) ActiveX 컨트롤을 각 PC에 복사
2) 그 컨트롤을 레지스트리에 등록
3) 필요한 DLL이 있다면 복사
=> 자동으로...
Cab 파일을 통해 위의 내용들을 자동화 시켜줌...
1) .inf 파일 작성
2) .ocx 파일과 .inf 파일을 .cab 파일로 압축
3) .cab 파일을 서명
4) .cab 파일을 웹페이지에 등록
//
1) .inf 파일 생성
=> VC 6.0 제공이 안됨...
=> 배포될 .ocx및 dll의 정보를 담고 있다...
2) .cab 파일 생성
=> cabarc.exe 유틸리티를 통해 생성...
cabarc.exe N test.cab test.ocx test.inf (step1.bat)
=> test.cab 파일 생성( 압축파일..)
3) .cab 서명
makecert -sv "mycert.pvk" -n "CN=TEST ActiveX" mycert.cer
=> 대화상자 생성 => 암호 입력 => 개인 키 파일(mycert.pvk, mycert.cer)
생성
cert2spec mycert.cer mycert.spc
=> mycert.cer로부터 mycert.spc를 생성 ( makespc.bat 사용)
컨트롤 서명
signcode -v mycert.pvk -spc mycert.spc test.cab
=> test용 .cab 파일을 인증하는 코드
인증기관에서 제대로된 인증을 받으려면 위 명령줄에 -t 인증기관 URL을 추가
setreg -q 1 TRUE
=> test용 인증서가 인식되도록 설정
chktrust test.cab
=> CAB 파일이 올바르게 서명되었는지 확인...(step2.bat..)
ActiveX에서 IObjectSafety 구현하기(MFC)
2009. 2. 13. 09:57
보안문제 해결하기
ActiveX 컨트롤 IE에서 보여주기 위해 사용하는 경우에 보안관련 메세지 박스들이 나타나게 된다. 이 컨트롤 자체가 신뢰할 수 있는 제작사 또는 개발자에 의해서 개발된 것인가 하는 것과 ActiveX 컨트롤에 매개변수를 넘기는 경우와 같이 ActiveX 스크립트를 사용하는 경우에는 안전한 스크립트인지 확인하라는 경우이다.
전자는 code signing을 통해 보장받을 수 있으며, 후자의 경우는 IObjectSafefy 인터페이스를 구현함으로써 보장받을 수 있다.
전자의 경우는 VeriSign에서 몇백달러를 지불하는데, 시험용이나 개인개발자들은 시험용 인증서를 만들어서 사용할 수 있다.
지금 여기서는 후자의 경우 해결방안에 대해서 기술하고자 한다.
Test라는 이름으로 구현해보자!
cathelp.cpp와 cathelp.h를 프로젝트에 포함시킨 후,
DllRegisterServer()를 다음과 같이 수정한다.
STDAPI DllRegisterServer(void)
{
HRESULT hr = NOERROR;
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);
hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable");
if (FAILED(hr))
{
;// OutputDebugString("Failed to create component category (scriptable)!n");
}
hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data");
if (FAILED(hr))
{
;// OutputDebugString("Failed to create component category (persistence)!n");
}
hr = RegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForScripting);
if (FAILED(hr))
{
;// OutputDebugString("Failed to register control as safe for scripting!n");
}
hr = RegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForInitializing);
if (FAILED(hr))
{
;// OutputDebugString("Failed to register control as safe for initializing!n");
}
return NOERROR;
}
DllUnregisterServer()를 아래와 같이 수정한다.
STDAPI DllUnregisterServer(void)
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
HRESULT hr = NOERROR;
hr = UnRegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForScripting);
hr = UnRegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForInitializing);
return NOERROR;
}
컨트롤이름ctrl.h 파일에 objsafe.h을 include한다.
그리고, 아래와 같이 추가한다.
class CTestCtrl : public COleControl
{
DECLARE_DYNCREATE(CTestCtrl)
BEGIN_INTERFACE_PART(ObjectSafety, IObjectSafety)
STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions);
STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions);
END_INTERFACE_PART(ObjectSafety)
DECLARE_INTERFACE_MAP();
마지막으로 cpp파일에 다음을 추가하면 된다.
STDMETHODIMP CTestCtrl::XObjectSafety::GetInterfaceSafetyOptions(
REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions)
{
METHOD_PROLOGUE_EX(CTestCtrl, ObjectSafety)
if (!pdwSupportedOptions || !pdwEnabledOptions)
{
return E_POINTER;
}
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
*pdwEnabledOptions = 0;
if (NULL == pThis->GetInterface(&riid))
{
;// TRACE("Requested interface is not supported.n");
return E_NOINTERFACE;
}
// What interface is being checked out anyhow?
OLECHAR szGUID[39];
int i = StringFromGUID2(riid, szGUID, 39);
if (riid == IID_IDispatch)
{
// Client wants to know if object is safe for scripting
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
return S_OK;
}
else if (riid == IID_IPersistPropertyBag
|| riid == IID_IPersistStreamInit
|| riid == IID_IPersistStorage
|| riid == IID_IPersistMemory)
{
// Those are the persistence interfaces COleControl derived controls support
// as indicated in AFXCTL.H
// Client wants to know if object is safe for initializing from persistent data
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
return S_OK;
}
else
{
// Find out what interface this is, and decide what options to enable
;// TRACE("We didn't account for the safety of this interface, and it's one we support...n");
return E_NOINTERFACE;
}
}
STDMETHODIMP CTestCtrl::XObjectSafety::SetInterfaceSafetyOptions(
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions)
{
METHOD_PROLOGUE_EX(CTestCtrl, ObjectSafety)
OLECHAR szGUID[39];
// What is this interface anyway?
// We can do a quick lookup in the registry under HKEY_CLASSES_ROOTInterface
int i = StringFromGUID2(riid, szGUID, 39);
if (0 == dwOptionSetMask && 0 == dwEnabledOptions)
{
// the control certainly supports NO requests through the specified interface
// so it's safe to return S_OK even if the interface isn't supported.
return S_OK;
}
// Do we support the specified interface?
if (NULL == pThis->GetInterface(&riid))
{
TRACE1("%s is not support.n", szGUID);
return E_FAIL;
}
if (riid == IID_IDispatch)
{
;// TRACE("Client asking if it's safe to call through IDispatch.n");
;// TRACE("In other words, is the control safe for scripting?n");
if (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask && INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions)
{
return S_OK;
}
else
{
return E_FAIL;
}
}
else if (riid == IID_IPersistPropertyBag
|| riid == IID_IPersistStreamInit
|| riid == IID_IPersistStorage
|| riid == IID_IPersistMemory)
{
;// TRACE("Client asking if it's safe to call through IPersist*.n");
;// TRACE("In other words, is the control safe for initializing from persistent data?n");
if (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask && INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions)
{
return NOERROR;
}
else
{
return E_FAIL;
}
}
else
{
TRACE1("We didn't account for the safety of %s, and it's one we support...n", szGUID);
return E_FAIL;
}
}
STDMETHODIMP_(ULONG) CTestCtrl::XObjectSafety::AddRef()
{
METHOD_PROLOGUE_EX_(CTestCtrl, ObjectSafety)
return (ULONG)pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CTestCtrl::XObjectSafety::Release()
{
METHOD_PROLOGUE_EX_(CTestCtrl, ObjectSafety)
return (ULONG)pThis->ExternalRelease();
}
STDMETHODIMP CTextCtrl::XObjectSafety::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(CTestCtrl, ObjectSafety)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
출처 : 미친병아리
ActiveX 컨트롤 IE에서 보여주기 위해 사용하는 경우에 보안관련 메세지 박스들이 나타나게 된다. 이 컨트롤 자체가 신뢰할 수 있는 제작사 또는 개발자에 의해서 개발된 것인가 하는 것과 ActiveX 컨트롤에 매개변수를 넘기는 경우와 같이 ActiveX 스크립트를 사용하는 경우에는 안전한 스크립트인지 확인하라는 경우이다.
전자는 code signing을 통해 보장받을 수 있으며, 후자의 경우는 IObjectSafefy 인터페이스를 구현함으로써 보장받을 수 있다.
전자의 경우는 VeriSign에서 몇백달러를 지불하는데, 시험용이나 개인개발자들은 시험용 인증서를 만들어서 사용할 수 있다.
지금 여기서는 후자의 경우 해결방안에 대해서 기술하고자 한다.
Test라는 이름으로 구현해보자!
cathelp.cpp와 cathelp.h를 프로젝트에 포함시킨 후,
DllRegisterServer()를 다음과 같이 수정한다.
STDAPI DllRegisterServer(void)
{
HRESULT hr = NOERROR;
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);
hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable");
if (FAILED(hr))
{
;// OutputDebugString("Failed to create component category (scriptable)!n");
}
hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data");
if (FAILED(hr))
{
;// OutputDebugString("Failed to create component category (persistence)!n");
}
hr = RegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForScripting);
if (FAILED(hr))
{
;// OutputDebugString("Failed to register control as safe for scripting!n");
}
hr = RegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForInitializing);
if (FAILED(hr))
{
;// OutputDebugString("Failed to register control as safe for initializing!n");
}
return NOERROR;
}
DllUnregisterServer()를 아래와 같이 수정한다.
STDAPI DllUnregisterServer(void)
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
HRESULT hr = NOERROR;
hr = UnRegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForScripting);
hr = UnRegisterCLSIDInCategory(CTestCtrl::guid, CATID_SafeForInitializing);
return NOERROR;
}
컨트롤이름ctrl.h 파일에 objsafe.h을 include한다.
그리고, 아래와 같이 추가한다.
class CTestCtrl : public COleControl
{
DECLARE_DYNCREATE(CTestCtrl)
BEGIN_INTERFACE_PART(ObjectSafety, IObjectSafety)
STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD __RPC_FAR *pdwSupportedOptions, DWORD __RPC_FAR *pdwEnabledOptions);
STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions);
END_INTERFACE_PART(ObjectSafety)
DECLARE_INTERFACE_MAP();
마지막으로 cpp파일에 다음을 추가하면 된다.
STDMETHODIMP CTestCtrl::XObjectSafety::GetInterfaceSafetyOptions(
REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions)
{
METHOD_PROLOGUE_EX(CTestCtrl, ObjectSafety)
if (!pdwSupportedOptions || !pdwEnabledOptions)
{
return E_POINTER;
}
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
*pdwEnabledOptions = 0;
if (NULL == pThis->GetInterface(&riid))
{
;// TRACE("Requested interface is not supported.n");
return E_NOINTERFACE;
}
// What interface is being checked out anyhow?
OLECHAR szGUID[39];
int i = StringFromGUID2(riid, szGUID, 39);
if (riid == IID_IDispatch)
{
// Client wants to know if object is safe for scripting
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
return S_OK;
}
else if (riid == IID_IPersistPropertyBag
|| riid == IID_IPersistStreamInit
|| riid == IID_IPersistStorage
|| riid == IID_IPersistMemory)
{
// Those are the persistence interfaces COleControl derived controls support
// as indicated in AFXCTL.H
// Client wants to know if object is safe for initializing from persistent data
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
return S_OK;
}
else
{
// Find out what interface this is, and decide what options to enable
;// TRACE("We didn't account for the safety of this interface, and it's one we support...n");
return E_NOINTERFACE;
}
}
STDMETHODIMP CTestCtrl::XObjectSafety::SetInterfaceSafetyOptions(
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions)
{
METHOD_PROLOGUE_EX(CTestCtrl, ObjectSafety)
OLECHAR szGUID[39];
// What is this interface anyway?
// We can do a quick lookup in the registry under HKEY_CLASSES_ROOTInterface
int i = StringFromGUID2(riid, szGUID, 39);
if (0 == dwOptionSetMask && 0 == dwEnabledOptions)
{
// the control certainly supports NO requests through the specified interface
// so it's safe to return S_OK even if the interface isn't supported.
return S_OK;
}
// Do we support the specified interface?
if (NULL == pThis->GetInterface(&riid))
{
TRACE1("%s is not support.n", szGUID);
return E_FAIL;
}
if (riid == IID_IDispatch)
{
;// TRACE("Client asking if it's safe to call through IDispatch.n");
;// TRACE("In other words, is the control safe for scripting?n");
if (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask && INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions)
{
return S_OK;
}
else
{
return E_FAIL;
}
}
else if (riid == IID_IPersistPropertyBag
|| riid == IID_IPersistStreamInit
|| riid == IID_IPersistStorage
|| riid == IID_IPersistMemory)
{
;// TRACE("Client asking if it's safe to call through IPersist*.n");
;// TRACE("In other words, is the control safe for initializing from persistent data?n");
if (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask && INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions)
{
return NOERROR;
}
else
{
return E_FAIL;
}
}
else
{
TRACE1("We didn't account for the safety of %s, and it's one we support...n", szGUID);
return E_FAIL;
}
}
STDMETHODIMP_(ULONG) CTestCtrl::XObjectSafety::AddRef()
{
METHOD_PROLOGUE_EX_(CTestCtrl, ObjectSafety)
return (ULONG)pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CTestCtrl::XObjectSafety::Release()
{
METHOD_PROLOGUE_EX_(CTestCtrl, ObjectSafety)
return (ULONG)pThis->ExternalRelease();
}
STDMETHODIMP CTextCtrl::XObjectSafety::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE_EX_(CTestCtrl, ObjectSafety)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
출처 : 미친병아리