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 );
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;
        }
}
// 상수 정의
#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);
// !!! 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);
}
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);
#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 라이브러리 추가
프로세스를 실행시키고.. 해당프로세스의 작업이 완료되었는지 기다린뒤  다음 코드를 수행하는 루틴

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를 내부적으로 호출
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 컨트롤 테스트 인증서

밑에 글(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 컨트롤 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);
}

출처 : 미친병아리