ChangeWindowMessageFilter – Vista 에서 메시지(WM_COPYDATA등) 보내기

비스타에서는 UAC가 동작하고 있을때 권한이 낮은 어플리케이션에서 높은 어플리케이션으로 메시지가 전달이 안된다.

여러 사이트 검색결과 ChangeWindowMessageFilter를 이용하면 된다는 것을 알게되었다.

typedef BOOL (WINAPI *CHANGEWINDOWMESSAGEFILTER)(
  UINT message,
  DWORD dwFlag
);

를 선언부에 선언하고,

HANDLE popapi;
    CHANGEWINDOWMESSAGEFILTER ChangeWindowMessageFilter;


    popapi = LoadLibrary("USER32.DLL");
    ChangeWindowMessageFilter=(CHANGEWINDOWMESSAGEFILTER)GetProcAddress((HINSTANCE)popapi,"ChangeWindowMessageFilter");
    ChangeWindowMessageFilter(WM_COPYDATA,1);

하면 됩니다.

ChangeWindowMessageFilter에서 MSGFLT_ADD를 사용하면 해당메세지를 받아들이게 되고,
REMOVE를 사용하면 해당 메세지가 블록된다.
이렇게 하면 UAC를 멈추지 않고 각 프로그램간에 메세제를 주고 받을 수 있다.

 

* 참고

WM_DROPFILES 메시지를 받기 위해서는 아래와 같이 0x0049 메시지도 같이 등록해 줘야지 메시지가 수신됨을 확인할 수 있다.

   pChangeWindowMessageFilterFunc(0x0049, 1);

   pChangeWindowMessageFilterFunc(WM_DROPFILES, 1);

 

Vista 에서 Low Level 권한으로 Process 를 생성시키는 방법

출처 : http://rodream.tistory.com/45

BOOL bRet;
HANDLE hToken;
HANDLE hNewToken;

// Notepad is used as an example
WCHAR wszProcessName[MAX_PATH] = L"C:\\Windows\\System32\\Notepad.exe";

// Low integrity SID
WCHAR wszIntegritySid[20] = L"S-1-16-4096";

PSID pIntegritySid = NULL;

TOKEN_MANDATORY_LABEL TIL = {0};
PROCESS_INFORMATION ProcInfo = {0};
STARTUPINFO StartupInfo = {0};
ULONG ExitCode = 0;

if (OpenProcessToken(GetCurrentProcess(),MAXIMUM_ALLOWED, &hToken))
{
if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation, TokenPrimary, &hNewToken))
{
if (ConvertStringSidToSid(wszIntegritySid, &pIntegritySid))
{
TIL.Label.Attributes = SE_GROUP_INTEGRITY;
TIL.Label.Sid = pIntegritySid;

if (SetTokenInformation(hNewToken, TokenIntegrityLevel, &TIL,
sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid)))
{
// Create the new process at Low/High integrity
bRet = CreateProcessAsUser(hNewToken, NULL,
wszProcessName, NULL, NULL, FALSE,
0, NULL, NULL, &StartupInfo, &ProcInfo);
}

Vista에서 알려진 경로를 구하는 방법…

기존 XP에서는 SHGetFolderPath 함수를 이용하면 가능했지만 Vista에서는 SHGetKnownFolderPath 함수를 사용해야 한다. 아직 Compatibility를 위해서 기존 함수도 지원한다고 하지만 Recommand가 아니니 바꿔야 잠재된 문제를 앱앨 수 있겠죠.소스 1.
if (_isVista) {
    WCHAR   *pSavePath = NULL;
    HMODULE shell32module = GetModuleHandle("shell32.dll");
        
    // Defined in the platform SDK for Vista
    const DWORD KF_FLAG_CREATE = 0x00008000;
    const GUID FOLDERID_LocalAppData ={0xF1B32785, 0x6FBA,  0x4FCF,
                       {0x9D, 0x55, 0x7B, 0x8E, 0x7F, 0x15, 0x70, 0x91}};
SHGetKnownFolderPathProc SHGKFPfunction =   reinterpret_cast<SHGetKnownFolderPathProc>(
    GetProcAddress(shell32module, "SHGetKnownFolderPath"));
    HRESULT hr = SHGKFPfunction(FOLDERID_LocalAppData,     KF_FLAG_CREATE, NULL, &pSavePath);
}[/CODE]

소스 2.
[CODE]#include <strsafe.h>
typedef UINT (CALLBACK* LPFNDLLFUNC)(GUID& rfid,DWORD dwFlags,HANDLE hToken,PWSTR* ppszPath);
TCHAR pathBuf[MAX_PATH] = _T("");
HRESULT hr;
size_t len;
PWSTR