2010年11月30日

THTMLWriter

Nick HodgesさんがTHTMLWriterというHTMLを生成するライブラリを公開しています。

Nick Hodges | Announcing THTMLWriter
delphihtmlwriter - Project Hosting on Google Code

ライセンスはMPL 1.1となっています。Generics.Collectionsに依存しているのでDelphi 2009以降の対応になると思われます(開発そのものはDelphi 2010で行っているとのこと)。

2010年11月29日

Stuxnet

今年(2010年)の7月くらいからStuxnetと呼ばれるワーム(マルウェア)が話題になっていました。

W32.Temphid (ja) (Symantec)
Trojan-Dropper:W32/Stuxnet (F-Secure)
WORM_STUXNET.A - 概 要 (Trendmicro)
Stuxnet | ウイルス情報 | マカフィー (McAfee)
キヤノンITソリューションズ:ESET Smart Security & ESET NOD32アンチウイルス:Win32/Stuxnet.A (ESET)

Stuxnetはルートキットの特徴を持ち、複数の攻撃(感染)手段を用意していることに加え、シーメンスSiemens SimaticというPLC(いわゆるシーケンサ - シーケンサは三菱電機株式会社の登録商標ですので、たとえとしては適切ではないかもしれませんが)にアクセスしようとする、という特徴があり、色々な憶測がなされてきました。しかしここにきて多くのセキュリティ関係者の努力により、Stuxnetの正体がほぼ解明された模様です。

エフセキュアブログ : Stuxnetに関する質疑応答
Stuxnet: 画期的な解明 | Symantec Connect
エフセキュアブログ : 「Stuxnet」再び:質疑応答

これらの情報を信じる限り、Stuxnetは西側(おそらくイスラエル)の情報機関がイランの核物質精製施設(ウラン濃縮プラント)の運用を妨害するためのもの、ということのようです。Stuxnetの備える強力な感染力は外部から直接アプローチできない施設に対して間接的に浸透するための手段ということになります。まぁイスラエルはイラクの原子炉を稼動前に爆撃で破壊(Operation Opera)していたりしますから、信じられないこともない話ですが、Stuxnetによる攻撃を考案した人は相当な切れ者だと思われます(いわゆるコロンブスの卵、ですね)。

2011/01/19追記: New York Timesが記事にしたことでまた話題になっているようです。

エフセキュアブログ : 「Stuxnet」に関する新情報

2011/02/16追記: Stuxnetの解析は続いているようです。DoDやNSAからクレームがついたりはしないんでしょうか?

エフセキュアブログ : 「Stuxnet」再び
W32.Stuxnet 調査詳細の改定版を公開 | Symantec Connect

2011/02/21追記: 2011年02月10日にJPCERT/CCが主催して行われた制御システムセキュリティカンファレンス 2011でもStuxnetが取り上げられたようです。

「Stuxnet - 制御システムを狙った初のマルウエア」 - JPCERT/CC 情報流通対策グループ 小熊 信孝

2010年11月26日

Pulsar(Delphi x64)情報

Stack OverflowHow should I prepare my 32-bit Delphi programs for an eventual 64-bit compiler?(来るべき64bitコンパイラに備えて、32bit Delphiのプログラムでどのような準備をしておくべきでしょうか?)という質問に対してBarry Kellyさん非常に興味深い回答をしています。

てきとうな要約:
  • 注意書き: Barry KellyさんはEmbarcaderoに勤務していますが、Embarcaderoを代表した回答ではなく、また64bit版Delphiはこうあるべきであるという仮定に基づいたものであり、設計上異なる選択が行われることになるかもしれません。
  • NativeIntとNativeUIntというプラットフォームにより32bitまたは64bitとなる整数型が用意される。これ以外の整数型はターゲットプラットフォームによりサイズが変化することはない。
  • TComponent.Tagのように整数とポインタをキャストして使用するようなものはNativeInt/NativeUIntに置き換えられる。
  • NativeInt/NativeUIntはポインタとの相互変換を必要とする場合以外には使用するべきではない。これ以外の整数型の変数は従来通りのサイズのものでよい。参照やTHandle、HWNDのようなものだけにNativeInt/NativeUIntを使う。
  • 文字列や動的配列の(ヘッダデータのような)内部の詳細を当てにしてはいけない。
  • (RTLの)APIは可能な限り32bitと64bitの間で維持する、というのが原則になる。たとえばTListの最大要素数もMaxInt div SizeOf(Pointer)のままになる。
  • (RTLの)APIを64bitで拡張する場合、別のfunction/method/propertyでアクセスするようにする。たとえばLength()はそのままで、LongLength()を用意する、というように。
  • これに関連してサイズを縮小する方向の変換(64bitの戻値を32bit整数の変数に代入するような)に関するエラーチェックを強化する。
  • おそらく動的配列は64bitのインデックスをサポートする。
  • おそらく文字列は32bitでインデックスが制限される。実際に文字列が4GBを超える状況を想定できないため。
  • ほぼ確実にビルトインアセンブラ(BASM)はサポートされないが、オブジェクトファイル(.obj)のリンクはサポートされる。

おそらくNativeInt/NativeUIntはINT_PTR/UINT_PTR(Windows Data Types)のまともな名前バージョンです(INT_PTR/UINT_PTRはそのネーミングセンスのなさで有名)。またPulsar(64bit Delphi)でBASMがサポートされない件はフォーラムのDelphi x64 and no build-in ASM = troublesでも話題になりましたが、PulsarにBASMを間に合わせるのは困難だ、という話でした。

元ねたはNick HodgesさんFlotsam and Jetsam #15

2010年11月19日

InterBase 5/6からInterBase XEに移行するとシステムテーブルにアクセスできない問題

Support KB

no permission for read/select access to table RDB$XXXX by user SYSDBA

という記事がありました。興味深い。とりあえずメモ。

てきとうな要約: InterBase 6.5およびそれ以前のバージョンからInterBase XEにデータベースを移行するとSYSDBAでシステムテーブル(RDB$XXXX)にアクセスできない(パーミッションがない)、という問題が発生する。この問題を解決する1番目の方法はシステムテーブルへのアクセスをgrantするもので、InterBaseのインストールフォルダの下の"examples\security\readmeta.sql"をISQLかIBConsoleから実行する。2番目の方法はパフォーマンスモニタリングのためにシステムテンポラリテーブルにアクセスしたい場合のもので、通常はSYSDBAとデータベースのオーナにのみ許可されているシステムテンポラリテーブルへのアクセスを全てのユーザに公開するようなスクリプト(元記事の"create procedure granttmp as"以下の部分)を実行する。

2016/07/17追記: Support KBの記事の日本語訳が出ています。

データベースのリストア時に発生する unassigned code エラーについて

またdocwikiにも記述があります。

移行における問題 - InterBase

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

2010年11月15日

バイナリプランティングの防止

IPAからも注意喚起が行われていますが、最近バイナリプランティング("Binary planting"、あるいは"DLL planting"、"DLL preloading"とも表現されます)という攻撃手法が問題になっています。これは(いわゆる"Known DLLs"を除く)絶対パス指定ではないDLLを検索するパスに"カレントディレクトリ"が含まれていて、状況によってはその優先順位が高いために攻撃者の用意した不正なDLLが実行プログラムにバインドされてしまう(通常はDLLをロードして初期化するだけでDLLMainが実行されてしまいますから、この時点で攻撃成立です)、というものです(これがが狭義の"DLL planting")。また類似の状況として、絶対パス指定ではない実行ファイルをCreateProcess/CreateProcessAsUser/CreateProcessWithLogonW/CreateProcessWithTokenW/ShellExecute/ShellExecuteExなどで起動することでも同様の問題が生じます。さらに問題を複雑なものにする要因として、Windows Vista/7ではKnown DLLsに含まれるDwmapi.dllがWindows 2000/XPには存在しないにもかかわらず一部のフレームワークがWindowsのバージョンを考慮せずにDwmapi.dllをロードしようとするために、カレントディレクトリに攻撃用のDwmapi.dllを配置することでこれがバインドされてしまい攻撃が成立してしまう、というものがあります(幸いにもVCLや.NET Frameworkは該当しませんが、MFC(Visual Studio 2005/2008/2010)は該当するようです)。上記のいずれの状況でも攻撃用のDLL/EXEはカレントディレクトリに配置するのが攻撃成立の条件になります(例えばSystem32にそんなものを置かれるようではどんな攻撃も可能ですから)ので、カレントディレクトリが外部に設定されてプログラムが起動するような場合、つまりファイルをダブルクリックして関連付けでプログラムが起動するような場合が最も危険である、ということになります(ショートカットでもカレントディレクトリは設定できますが)。

バイナリプランティングをプログラム側から防ぐには、
  • リンクするDLLや起動する実行ファイルは可能な限り完全修飾パス名を使用する。
  • SetDllDirectoryで""(空文字列)を指定してDLLの検索パスからカレントディレクトリを削除する(Windows XP以降)。
  • DLL/実行ファイルを検索するのにSearchPath (ja)はなるべく使用しない。使用するときはSetSearchPathModeBASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODEを設定する(Windows Vista以降)。
  • Windowsの特定のバージョン以降で"Known DLLs"に追加されたDLLをLoadLibraryするときはWindowsのバージョンチェックを行うか、完全修飾パス名を使用する。
といった対策をとる必要があります。

ということでSetDllDirectoryを使用してDLLの検索パスからカレントディレクトリを削除するサンプルです。なるべく早い時点で設定するのが望ましいので、プロジェクトファイルの先頭で行います。またSetDllDirectoryはWindows XP SP1以降にしか存在しないので、エントリの存在を確認して呼び出すようにしています。
program Project1;

uses
  Windows,
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

type
  TSetDllDirectoryFunc = function (lpPathName: PChar): BOOL; stdcall;

const
{$IFDEF Unicode}
  CSetDllDirectory = 'SetDllDirectoryW';
{$ELSE}
  CSetDllDirectory = 'SetDllDirectoryA';
{$ENDIF}

var
  S: String;
  SetDllDirectory: TSetDllDirectoryFunc;
begin

  @SetDllDirectory := GetProcAddress(GetModuleHandle(kernel32),
  CSetDllDirectory);
  if Assigned(SetDllDirectory) = True then
  begin
    S := '#0';
    SetDllDirectory(PChar(S));
  end;

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

なおコンソールアプリケーションでグラスエフェクトを有効にするのサンプルコードもDwmapi.dllがWindows 2000/XPには存在しないことを利用したバイナリプランティングの影響を受けるため、修正してあります。

元ねたは以下の通り。

情報処理推進機構(IPA)マイクロソフトITpro(要登録)CodeZineNyaRuRuの日記

2010年11月13日

Delphi/C++Builder XE Update Pack 1

Delphi/C++Builder XEのUpdate Pack 1がリリースされています。Update Pack 1にはDelphi/C++Builder XEのUpdate 1、Help Update 1、Boost Update 1の3つが含まれています。

28116 Update Pack 1 for Delphi XE and C++Builder XE
リリース ノート: Delphi XE および C++Builder XE Update 1
List of Bug Fixes in Delphi and C++Builder XE Update 1

なおAndreas HausladenさんによるとUpdate 1を適用するとDDevExtensionsがcrackとみなされて動作しないとのことです。

XE Update 1 the death of DDevExtensions | Andy’s Blog and Tools

2010/11/14追記: Help Update 1を適用するとPSDKのコンテンツが削除される、という問題が報告されています。この場合はHelpそのものを一旦アンインストールし、ダウンロードして展開したHelp Update1のセットアップからPSDKを含めてインストールすることで回避できるようです。

2010/11/14追記: 今回のUpdate 1のリリース日についてですが、1年前のこの話はNickさんが辞めることでなかったことになってしまったのでしょうかね?国別ではなくワールドワイドで同時展開するにはよいポリシーだと思うのですが…。

2010/11/14追記: Update 1適用後にAndreas HausladenさんDDevExtensionsが動作しない件についてですが、原因が判明して問題を回避したDDevExtensions 2.1 for XE Update 1がリリースされています。

DDevExtensions for XE Update 1 resurrection | Andy’s Blog and Tools

2010/11/16追記: A7MさんによるとC++Builder XEにBoost Update 1を適用後にboost::tupleを使用している箇所がコンパイルエラーになるという問題があり、ソースコードを修正することで回避できるとのことです。

Update Pack 1 for C++Builder XEのBoost Update 1についてのちょっとした注意 - C++Builder好きの秘密基地

2010/11/17追記: Team Japanにも関連記事が出ています。

Team Japan » RAD Studio/C++Builder/Delphi XE Update 1

2010年11月12日

Firebird 2.xから2.5へのバージョンアップ時のユーザデータベースの移行

Firebird 2.xで運用しているシステムを2.5にバージョンアップするときにはユーザデータベース(security2.fdb)の移行に気をつけましょう、という記事。

Firebird News » Migrating users from FB 2.1 to FB 2.5

てきとうな要約: ユーザデータベースもまたFirebirdのデータベースなので、Firebirdのバージョンが異なるとODSのバージョンもまた異なる、という問題があるため、単にコピーしておいたsecurity2.fdbを上書きするようなやり方は無保証であり、gbakでバックアップ/リストアするのが望ましいけれども、この場合新しい"RDB$ADMIN"ロールとの関係で、ユーザ操作を行う新しいSQL(CREATE/ALTER/DROP USER)をSYSDBAを含む通常ユーザが実行できない、ということになる(Firebird 2.5.1にはこの問題を解決するスクリプトが含まれる予定)。結局現時点ではgsecを使って新しくユーザを登録しなおすのが最も望ましい解決方法、ということになる。

2010年11月11日

登録回数の上限をwebから変更できなくなった

以前はインストール数の上限に達したときはwebから上限を変更できましたが、つ4さんのとほほな日々 備忘録[Delphi] RAD XE インストールのトラブルのコメント欄や公式フォーラムのLicense bumping-What is the limit ?Jan Derkさんの発言にあるように、2010/10/05以降はwebからの変更(bump up)は動作しておらず、Support KBインストール・使用許諾にあるとおり、インストール・使用許諾から申請するように変更されています。

2010年11月10日

Microsoft Monthly Update 2010/11

今日はMicrosoftのセキュリティアップデートの日です。
MS10-087
MS10-088
MS10-089

2010年11月9日

Dependency Walker

実行ファイルが静的、動的にリンクしているDLLを確認するツールとしてはMicrosoft Visual Studioに付属している(た)Dependency Walkerが一般的ですが、Dependency Walkerが知らないうちにfreewareになっていました(現在はSteve P. Millerさんがメンテナのようです)。

Dependency Walker (depends.exe) Home Page

現時点の最新版は2.2.6000で、x86/x64/IA64版が用意されています。

またx86版については黒翼猫さんが日本語化パッチを作成してくださっています。

Dependency Walker 日本語化パッチ を作りました - Windows 2000 Blog

2010年11月8日

IDE Fix Pack 4.0 Beta版テスト中

Andreas HausladenさんのIDE Fix Pack 4.0とDelphiSpeedUp 3.0のBeta版が公開されています(Use it at your own risk.です)。

The IDEFixPack 4.0 BETA begins… | Andy’s Blog and Tools

Delphi 7はDelphiSpeedUp(3.0 Beta)のみ、Delphi 2007はDelphiSpeedUp(3.0 Beta)+IDE Fix Pack (4.0 Beta)、Delphi 2009/2010/XEはIDE Fix Pack(4.0 Beta)のみ、とちょっと複雑です。また結構な勢いで更新されていて、まだまだ安定しているとまではいえないようです(手元の環境でもエラーが出たり…)。

2010/11/16追記: Release Candidate 2まで進んでいます。

2010年11月5日

インストールされているDelphiのバージョンを調べる

RRUZ(Rodrigo Ruz)さんによるインストール済のDelphiのバージョンを調べる方法。レジストリのHKCUかHKLMのSoftware\Borland|CodeGear|Embarcadero\Delphi|BDS\の存在を見ればよい。それ以上何もないのでリンクのみメモ。

Detecting installed delphi versions. « The Road to Delphi – a Blog About Delphi Programming (mostly)

2010年11月4日

$WARNによる警告の制御

Delphiではコンパイラディレクティブ$WARNを使用して警告を有効/無効/エラーに昇格/デフォルトに戻すという指定をすることができます(エラーに昇格、デフォルトに戻すの2つはDelphi 2009以降の新機能)。

{$WARN identifier ON | OFF | ERROR | DEFAULT}
ONを指定するとその警告が有効に、OFFで無効に、ERRORでその警告をエラーに昇格、DEFAULTで指定をプロジェクトオプションで指定したものに戻す、という動作になります。

指定可能な警告とエラーコードは以下のとおりです。
SYMBOL_DEPRECATED
W1000 (ja)
SYMBOL_LIBRARY
W1001 (ja)
SYMBOL_PLATFORM
W1002 (ja)
SYMBOL_EXPERIMENTAL
W1003 (ja)
UNIT_LIBRARY
W1004 (ja)
UNIT_PLATFORM
W1005 (ja)
UNIT_DEPRECATED
W1006 (ja)
UNIT_EXPERIMENTAL
W1007 (ja)
HRESULT_COMPAT
W1008 (ja)
HIDING_MEMBER
W1009 (ja)
HIDDEN_VIRTUAL
W1010 (ja)
GARBAGE
W1011 (ja)
BOUNDS_ERROR
x1012 (ja)
ZERO_NIL_COMPAT
W1013 (ja)
STRING_CONST_TRUNCED
W1014 (ja)
FOR_LOOP_VAR_VARPAR
W1015 (ja)
TYPED_CONST_VARPAR
W1016 (ja)
ASG_TO_TYPED_CONST
W1017 (ja)
CASE_LABEL_RANGE
W1018 (ja)
FOR_VARIABLE
x1019 (ja)
CONSTRUCTING_ABSTRACT
x1020 (ja)
COMPARISON_FALSE
W1021 (ja)
COMPARISON_TRUE
W1022 (ja)
COMPARING_SIGNED_UNSIGNED
W1023 (ja)
COMBINING_SIGNED_UNSIGNED
W1024 (ja)
UNSUPPORTED_CONSTRUCT
x1025 (ja)
FILE_OPEN
x1026 (ja)
FILE_OPEN_UNITSRC
F1027 (ja)
BAD_GLOBAL_SYMBOL
x1028 (ja)
DUPLICATE_CTOR_DTOR
W1029 (ja)
INVALID_DIRECTIVE
x1030 (ja)
PACKAGE_NO_LINK
W1031 (ja)
PACKAGED_THREADVAR
W1032 (ja)
IMPLICIT_IMPORT
x1033 (ja)
HPPEMIT_IGNORED
W1034 (ja)
NO_RETVAL
W1035 (ja)
USE_BEFORE_DEF
W1036 (ja)
FOR_LOOP_VAR_UNDEF
W1037 (ja)
UNIT_NAME_MISMATCH
E1038 (ja)
NO_CFG_FILE_FOUND
W1039 (ja)
IMPLICIT_VARIANTS
W1040 (ja)
UNICODE_TO_LOCALE
W1041 (ja)
LOCALE_TO_UNICODE
W1042 (ja)
IMAGEBASE_MULTIPLE
W1043 (ja)
SUSPICIOUS_TYPECAST
W1044 (ja)
PRIVATE_PROPACCESSOR
W1045 (ja)
UNSAFE_TYPE
W1046 (ja)
UNSAFE_CODE
W1047 (ja)
UNSAFE_CAST
W1048 (ja)
OPTION_TRUNCATED
W1049 (ja)
WIDECHAR_REDUCED
W1050 (ja)
DUPLICATES_IGNORED
W1051 (ja)
UNIT_INIT_SEQ
W1052 (ja)
LOCAL_PINVOKE
W1053 (ja)
MESSAGE_DIRECTIVE
x1054 (ja)
TYPEINFO_IMPLICITLY_ADDED
W1055 (ja)
RLINK_WARNING
x1056 (ja)
IMPLICIT_STRING_CAST
W1057 (ja)
IMPLICIT_STRING_CAST_LOSS
W1058 (ja)
EXPLICIT_STRING_CAST
W1059 (ja)
EXPLICIT_STRING_CAST_LOSS
W1060 (ja)
CVT_WCHAR_TO_ACHAR
W1061 (ja)
CVT_NARROWING_STRING_LOST
W1062 (ja)
CVT_ACHAR_TO_WCHAR
W1063 (ja)
CVT_WIDENING_STRING_LOST
W1064 (ja)
NON_PORTABLE_TYPECAST
W1065 (ja)
LOST_EXTENDED_PRECISION
W1066 (ja)
LNKDFM_NOTFOUND
W1067 (ja)
IMMUTABLE_STRINGS
W1068 (ja)
MOBILE_DELPHI
W1069 (ja)
UNSAFE_VOID_POINTER
W1070 (ja)
IMPLICIT_INTEGER_CAST_LOSS
W1071 (ja)
IMPLICIT_CONVERSION_LOSS
W1072 (ja)
COMBINING_SIGNED_UNSIGNED64
W1073 (ja)
XML_WHITESPACE_NOT_ALLOWED
W1201 (ja)
XML_UNKNOWN_ENTITY
W1202 (ja)
XML_INVALID_NAME_START
W1203 (ja)
XML_INVALID_NAME
W1204 (ja)
XML_EXPECTED_CHARACTER
W1205 (ja)
XML_CREF_NO_RESOLVE
W1206 (ja)
XML_NO_PARM
W1207 (ja)
XML_NO_MATCHING_PARM
W1208 (ja)
元ねたはSource\ToolsAPI\DCCStrs.pas警告メッセージ(Delphi) - RAD Studio (en)、エラーと警告のメッセージ(Delphi) - RAD Studio (en)。

2016/04/28追記: Delphi 10.1 Berlinの情報を追加。

2017/04/04追記: Delphi 10.2 Tokyoで追加されたW1071/W1072/W1073の情報を追加。

2010年11月2日

第18回エンバカデロ・デベロッパーキャンプ開催決定

第18回エンバカデロ・デベロッパーキャンプは(かねてからの予告どおり)2010年12月07日に開催されます。

エンバカデロ・デベロッパーキャンプ

またT6セッション『ライトニングトーク「共有!みんなの開発事例、開発経験、 テクニック」』のスピーカを募集しています。

【募集】第18回 エンバカデロ・デベロッパーキャンプ - ライトニングトークスピーカー

2010/11/04追記: ライトニングトークに高橋さんが参戦するようです。

Team Japan » ライトニングトークで喋ってみませんか?

ん~。いいネタを思いつかないし、ネタから考えるには仕事が忙しい気がするし…。

2010/11/10追記: 今回はUStreamとLiveMeeting(事前登録はここから)の両方で中継するそうです。あれ、エンバカデロ本社の誰かがCodeRage 5の後で次回からLiveMeetingはやめて他のシステムを使うようなことをいっていたような(クロスプラットフォームといいながらMac/Linuxで見られないのはいかがなものかという話の流れで)。

2010/11/19追記: UStreamでMalcolm Grovesさん出演の事前放送が行われるとのことです。

2010/11/25 17:00-17:15(JST) 12月7日まで待てない!デベロッパーキャンプ事前放送 - 第1回
2010/11/26 12:00-12:15(JST) 12月7日まで待てない!デベロッパーキャンプ事前放送 - 第1回(再放送) (リンク先の日付が11/19になっていますが、11/26が正しいはず)

2010/11/27追記: Team Japanに関連アーティクルが出ています。

Team Japan » 12月7日は第18回 エンバカデロ・デベロッパーキャンプです

2010/11/30追記: UStreamでJason Tiretさん出演の事前放送が行われます。

2010/12/02 17:00-17:15(JST) 12月7日まで待てない!デベロッパーキャンプ事前放送 - 第2回
2010/12/03 12:00-12:15(JST) 12月7日まで待てない!デベロッパーキャンプ事前放送 - 第2回(再放送)

2010/12/02 追記: Team Japanに会場へのアクセスについてのアーティクルが出ています。

Team Japan » 第18回 エンバカデロ・デベロッパーキャンプ会場へのアクセス