2010年11月16日

ダミーのDwmapi.dllを作成する

前回のアーティクルでも触れましたが、Visual Studioで作成したプログラムがWindows Vista以降で"Known DLLs"となったDwmapi.dllをWindows 2000/XPでもLoadLibraryしてしまいバイナリプランティングを引き起こしてしまう件(およびDelphiで作成したプログラムにこの問題が存在しない件)について、これを検証するためのダミーのDwmapi.dllを作成してみました(当然Windows 2000/XP用です)。

まずはプロジェクトファイルです。DLLを新規作成し、DWMAPIという名前にします。
library DWMAPI;

uses
  Windows,
  SysUtils,
  Classes,
  _DWMAPI in '_DWMAPI.pas';

exports
  DwmDefWindowProc,
  DwmEnableBlurBehindWindow,
  DwmEnableComposition,
  DwmEnableMMCSS,
  DwmExtendFrameIntoClientArea,
  DwmGetColorizationColor,
  DwmGetCompositionTimingInfo,
  DwmGetWindowAttribute,
  DwmIsCompositionEnabled,
  DwmModifyPreviousDxFrameDuration,
  DwmQueryThumbnailSourceSize,
  DwmRegisterThumbnail,
  DwmSetDxFrameDuration,
  DwmSetPresentParameters,
  DwmSetWindowAttribute,
  DwmUnregisterThumbnail,
  DwmUpdateThumbnailProperties;

{$R *.res}

begin
end.
さらに新規作成でユニットを追加し、_DWMAPI.pasとします。
unit _DWMAPI;

interface

uses
  Types;

type
  DWORD = Types.DWORD;
  {$EXTERNALSYM DWORD}
  BOOL = LongBool;
  {$EXTERNALSYM BOOL}
  UINT = LongWord;
  {$EXTERNALSYM UINT}

  HRGN = type LongWord;
  {$EXTERNALSYM HRGN}

  LONGLONG = Int64;
  {$EXTERNALSYM LONGLONG}

  ULONGLONG = UInt64;
  {$EXTERNALSYM ULONGLONG}
  ULARGE_INTEGER = record
    case Integer of
    0: (
        LowPart: DWORD;
        HighPart: DWORD);
    1: (
        QuadPart: LONGLONG);
  end;
  {$EXTERNALSYM ULARGE_INTEGER}
  PULargeInteger = ^TULargeInteger;
  TULargeInteger = ULARGE_INTEGER;

  HWND = type LongWord;
  {$EXTERNALSYM HWND}

  WPARAM = Longint;
  {$EXTERNALSYM WPARAM}
  LPARAM = Longint;
  {$EXTERNALSYM LPARAM}
  LRESULT = Longint;
  {$EXTERNALSYM LRESULT}

  {$EXTERNALSYM PDWM_BLURBEHIND}
  PDWM_BLURBEHIND = ^DWM_BLURBEHIND;
  {$EXTERNALSYM DWM_BLURBEHIND}
  DWM_BLURBEHIND = packed record
    dwFlags: DWORD;
    fEnable: BOOL;
    hRgnBlur: HRGN;
    fTransitionOnMaximized: BOOL;
  end;
  _DWM_BLURBEHIND = DWM_BLURBEHIND;
  TDWMBlurBehind = DWM_BLURBEHIND;
  PDWMBlurBehind = ^TDWMBlurBehind;

  _MARGINS = record
    cxLeftWidth: Integer;
    cxRightWidth: Integer;
    cyTopHeight: Integer;
    cyBottomHeight: Integer;
  end;
  {$EXTERNALSYM _MARGINS}
  MARGINS = _MARGINS;
  {$EXTERNALSYM MARGINS}
  PMARGINS = ^MARGINS;
  {$EXTERNALSYM PMARGINS}
  TMargins = MARGINS;

  {$EXTERNALSYM PDWM_THUMBNAIL_PROPERTIES}
  PDWM_THUMBNAIL_PROPERTIES = ^DWM_THUMBNAIL_PROPERTIES;
  {$EXTERNALSYM DWM_THUMBNAIL_PROPERTIES}
  DWM_THUMBNAIL_PROPERTIES = packed record
    dwFlags: DWORD;
    rcDestination: TRect;
    rcSource: TRect;
    opacity: Byte;
    fVisible: BOOL;
    fSourceClientAreaOnly: BOOL;
  end;
  _DWM_THUMBNAIL_PROPERTIES = DWM_THUMBNAIL_PROPERTIES;
  TDWMThumbnailProperties = DWM_THUMBNAIL_PROPERTIES;
  PDWMThumbnailProperties = ^TDWMThumbnailProperties;

  {$EXTERNALSYM DWM_FRAME_COUNT}
  DWM_FRAME_COUNT = ULONGLONG;
  {$EXTERNALSYM QPC_TIME}
  QPC_TIME = ULONGLONG;

  {$EXTERNALSYM UNSIGNED_RATIO}
  UNSIGNED_RATIO = packed record
    uiNumerator: Cardinal;
    uiDenominator: Cardinal;
  end;
  _UNSIGNED_RATIO = UNSIGNED_RATIO;
  TUnsignedRatio = UNSIGNED_RATIO;
  PUnsignedRatio = ^TUnsignedRatio;

  {$EXTERNALSYM DWM_TIMING_INFO}
  DWM_TIMING_INFO = packed record
    cbSize: Cardinal;
    rateRefresh: UNSIGNED_RATIO;
    qpcRefreshPeriod: QPC_TIME;
    rateCompose: UNSIGNED_RATIO;
    qpcVBlank: QPC_TIME;
    cRefresh: DWM_FRAME_COUNT;
    cDXRefresh: UINT;
    qpcCompose: QPC_TIME;
    cFrame: DWM_FRAME_COUNT;
    cDXPresent: UINT;
    cRefreshFrame: DWM_FRAME_COUNT;
    cFrameSubmitted: DWM_FRAME_COUNT;
    cDXPresentSubmitted: UINT;
    cFrameConfirmed: DWM_FRAME_COUNT;
    cDXPresentConfirmed: UINT;
    cRefreshConfirmed: DWM_FRAME_COUNT;
    cDXRefreshConfirmed: UINT;
    cFramesLate: DWM_FRAME_COUNT;
    cFramesOutstanding: UINT;
    cFrameDisplayed: DWM_FRAME_COUNT;
    qpcFrameDisplayed: QPC_TIME;
    cRefreshFrameDisplayed: DWM_FRAME_COUNT;
    cFrameComplete: DWM_FRAME_COUNT;
    qpcFrameComplete: QPC_TIME;
    cFramePending: DWM_FRAME_COUNT;
    qpcFramePending: QPC_TIME;
    cFramesDisplayed: DWM_FRAME_COUNT;
    cFramesComplete: DWM_FRAME_COUNT;
    cFramesPending: DWM_FRAME_COUNT;
    cFramesAvailable: DWM_FRAME_COUNT;
    cFramesDropped: DWM_FRAME_COUNT;
    cFramesMissed: DWM_FRAME_COUNT;
    cRefreshNextDisplayed: DWM_FRAME_COUNT;
    cRefreshNextPresented: DWM_FRAME_COUNT;
    cRefreshesDisplayed: DWM_FRAME_COUNT;
    cRefreshesPresented: DWM_FRAME_COUNT;
    cRefreshStarted: DWM_FRAME_COUNT;
    cPixelsReceived: ULONGLONG;
    cPixelsDrawn: ULONGLONG;
    cBuffersEmpty: DWM_FRAME_COUNT;
  end;
  _DWM_TIMING_INFO = DWM_TIMING_INFO;
  TDWMTimingInfo = DWM_TIMING_INFO;
  PDWMTimingInfo = ^TDWMTimingInfo;

  {$EXTERNALSYM HTHUMBNAIL}
  HTHUMBNAIL = THandle;
  {$EXTERNALSYM PHTHUMBNAIL}
  PHTHUMBNAIL = ^HTHUMBNAIL;

  {$EXTERNALSYM DWM_PRESENT_PARAMETERS}
  DWM_PRESENT_PARAMETERS = packed record
    cbSize: Cardinal;
    fQueue: BOOL;
    cRefreshStart: DWM_FRAME_COUNT;
    cBuffer: UINT;
    fUseSourceRate: BOOL;
    rateSource: UNSIGNED_RATIO;
    cRefreshesPerFrame: UINT;
    eSampling: UINT;
  end;
  _DWM_PRESENT_PARAMETERS = DWM_PRESENT_PARAMETERS;
  TDWMPresentParameters = DWM_PRESENT_PARAMETERS;
  PDWMPresentParameters = ^TDWMPresentParameters;

function DwmDefWindowProc(hWnd: HWND; msg: UINT; wParam: WPARAM; lParam: LPARAM; var plResult: LRESULT): BOOL; stdcall;
function DwmEnableBlurBehindWindow(hWnd: HWND; const pBlurBehind: TDWMBlurBehind): HResult; stdcall;
function DwmEnableComposition(uCompositionAction: UINT): HResult; stdcall;
function DwmEnableMMCSS(fEnableMMCSS: BOOL): HResult; stdcall;
function DwmExtendFrameIntoClientArea(hWnd: HWND; const pMarInset: TMargins): HResult; stdcall;
function DwmGetColorizationColor(out pcrColorization: DWORD; out pfOpaqueBlend: BOOL): HResult; stdcall;
function DwmGetCompositionTimingInfo(hwnd: HWND; out pTimingInfo: TDWMTimingInfo): HResult; stdcall;
function DwmGetWindowAttribute(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HResult; stdcall;
function DwmIsCompositionEnabled(out pfEnabled: BOOL): HResult; stdcall;
function DwmModifyPreviousDxFrameDuration(hwnd: HWND; cRefreshes: Integer; fRelative: BOOL): HResult; stdcall;
function DwmQueryThumbnailSourceSize(hThumbnail: HTHUMBNAIL; pSize: PSIZE): HResult; stdcall;
function DwmRegisterThumbnail(hwndDestination: HWND; hwndSource: HWND; out phThumbnailId: HTHUMBNAIL): HResult; stdcall;
function DwmSetDxFrameDuration(hwnd: HWND; cRefreshes: Integer): HResult; stdcall;
function DwmSetPresentParameters(hwnd: HWND; var pPresentParams: TDWMPresentParameters): HResult; stdcall;
function DwmSetWindowAttribute(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HResult; stdcall;
function DwmUnregisterThumbnail(hThumbnailId: HTHUMBNAIL): HResult; stdcall;
function DwmUpdateThumbnailProperties(hThumbnailId: HTHUMBNAIL; const ptnProperties: TDWMThumbnailProperties): HResult; stdcall;

implementation

function DwmDefWindowProc(hWnd: HWND; msg: UINT; wParam: WPARAM; lParam: LPARAM; var plResult: LRESULT): BOOL;
begin
  Result := False;
end;

function DwmEnableBlurBehindWindow(hWnd: HWND; const pBlurBehind: TDWMBlurBehind): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmEnableComposition(uCompositionAction: UINT): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmEnableMMCSS(fEnableMMCSS: BOOL): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmExtendFrameIntoClientArea(hWnd: HWND; const pMarInset: TMargins): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmGetColorizationColor(out pcrColorization: DWORD; out pfOpaqueBlend: BOOL): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmGetCompositionTimingInfo(hwnd: HWND; out pTimingInfo: TDWMTimingInfo): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmGetWindowAttribute(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmIsCompositionEnabled(out pfEnabled: BOOL): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmModifyPreviousDxFrameDuration(hwnd: HWND; cRefreshes: Integer; fRelative: BOOL): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmQueryThumbnailSourceSize(hThumbnail: HTHUMBNAIL; pSize: PSIZE): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmRegisterThumbnail(hwndDestination: HWND; hwndSource: HWND; out phThumbnailId: HTHUMBNAIL): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmSetDxFrameDuration(hwnd: HWND; cRefreshes: Integer): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmSetPresentParameters(hwnd: HWND; var pPresentParams: TDWMPresentParameters): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmSetWindowAttribute(hwnd: HWND; dwAttribute: DWORD; pvAttribute: Pointer; cbAttribute: DWORD): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmUnregisterThumbnail(hThumbnailId: HTHUMBNAIL): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

function DwmUpdateThumbnailProperties(hThumbnailId: HTHUMBNAIL; const ptnProperties: TDWMThumbnailProperties): HResult; stdcall;
begin
  Result := E_NOTIMPL;
end;

end.
(Dwmapi.dll関係の各種定義はDwmApi.pasなどから借りてきました)。これでビルドしたDwmapi.dllをWindows 2000/XPでSystem32あたりに配置しておきます。この状態から問題のありそうなプログラムを実行してDependency WalkerWindows SysInternalsのProcess Explorerなどを使ってDwmapi.dllのロード状況を確認することができます。確かにDelphiで作成したプログラムは問題ないようですね。念のためにVCLのソースで確認してみると、DWMのデスクトップコンポジションを使用できるかどうかを調べるDwmApiユニットのDwmCompositionEnabled関数(ヘルプにはエントリがありませんが)の実装が
function DwmCompositionEnabled: Boolean;
var
  LEnabled: BOOL;
begin
  Result := (Win32MajorVersion >= 6) and (DwmIsCompositionEnabled(LEnabled) = S_OK) and LEnabled;
end;
(Delphi 20007のDwmApi.pasの795行目から)となっており、Windows Vista以降かどうかの確認を正しく行っていることがわかります。

元ねたはVS2010 でコンパイルされた全ての単体 MFC アプリケーションに脆弱性が存在 - スラッシュドット・ジャパンVS2010でコンパイルされたすべてのMFCアプリに脆弱性ってのは過小報告? - Windows 2000 Blog

0 件のコメント: