2011年2月21日

TFileStreamのコンストラクタで指定するアクセスモードについて

Delphiでファイルを扱うときによく使うTFileStream (ja)のコンストラクタCreate (ja)の第2パラメータModeと、WindowsのAPIであるCreateFile (ja)の第2パラメータdwDesiredAccess、第3パラメータdwShareMode、第5パラメータdwCreationDispositionの関係を調べてみました。

まずModeに指定できる値としてfm...の定義値を調べてみます。fmCreateのみがClasses.pasに
  fmCreate = $FFFF;
(Classes.pasの53行目)(Delphi 2007の場合、以下同じ)

と定義され、その他の値はSysUtils.pasに
  fmOpenRead       = $0000;
  fmOpenWrite      = $0001;
  fmOpenReadWrite  = $0002;

  fmShareCompat    = $0000 platform; // DOS compatibility mode is not portable
  fmShareExclusive = $0010;
  fmShareDenyWrite = $0020;
  fmShareDenyRead  = $0030 platform; // write-only not supported on all platforms
  fmShareDenyNone  = $0040;
(SysUtils.pasの44行目付近)

と定義されています。…fmCreateが0xFFFFで他の定義値が16bitの定数ということは、ModeにfmCreateを指定した場合、その他の指定は一切意味を持たない、ということになりますね。実際にTFileStream.Createを見てみると、
constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
  begin
  if Mode = fmCreate then
  begin
  ...
  end
  else
  begin
  ...
  end;
  FFileName := AFileName;
end;
(Classes.pasの5474行目付近)

と、確かにModeがfmCreateかそれ以外かで完全に処理が分けられてしまっています。ではfmCreateのケースをさらに追ってみます。
inherited Create(FileCreate(AFileName, Rights));
(Classes.pasの5478行目)

とSysUtils.pas上のFileCreate (ja)を呼び出しています(inherited CreateはTFileStreamの派生元であるTHandleStream (ja)のコンストラクタ呼び出しです)。FileCreateは
Result := Integer(CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE,
    0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
(SysUtils.pasの5259行目付近)

という実装であり、結果としてfmCreateの場合、dwDesiredAccessはGENERIC_READ or GENERIC_WRITE、dwShareModeは0(Prevents other processes from opening a file or device if they request delete, read, or write access.=他の処理からは削除、読み込み、書き込みアクセスできない)、dwCreationDispositionはCREATE_ALWAYS(新しいファイルを作成します。指定したファイルが既に存在している場合、そのファイルを上書きし、既存の属性を消去します。)と、これらの値が固定的に指定される、ということになります。

一方fmOpen...の場合、
inherited Create(FileOpen(AFileName, Mode));
(Classes.pasの5484行目)

とSysUtils.pas上のFileOpen (ja)を呼び出しています。FileOpenは
const
  AccessMode: array[0..2] of LongWord = (
    GENERIC_READ,
    GENERIC_WRITE,
    GENERIC_READ or GENERIC_WRITE);
  ShareMode: array[0..4] of LongWord = (
    0,
    0,
    FILE_SHARE_READ,
    FILE_SHARE_WRITE,
   FILE_SHARE_READ or FILE_SHARE_WRITE);
  ...
  Result := Integer(CreateFile(PChar(FileName), AccessMode[Mode and 3],
    ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0));
(SysUtils.pasの5196行目付近)

という実装で、dwDesiredAccessはfmOpenRead→GENERIC_READ、fmOpenWrite→GENERIC_WRITE、fmOpenReadWrite→GENERIC_READ or GENERIC_WRITEとマップされ、dwShareModeはfmShareCompat/fmShareExclusive→0(他の処理からは削除、読み込み、書き込みアクセスできない)、fmShareDenyWrite→FILE_SHARE_READ(他の処理からは読み込みアクセスのみ許可)、fmShareDenyRead→FILE_SHARE_WRITE(他の処理からは書き込みアクセスのみ許可)、fmShareDenyNone→FILE_SHARE_READ or FILE_SHARE_WRITE(他の処理からは読み込み、書き込みアクセスとも許可)とマップされ、dwCreationDispositionはOPEN_EXISTING(ファイルを開きます。指定したファイルが存在していない場合、この関数は失敗します。)が固定的に指定される、ということになります。

これ以外の組み合わせ、たとえば書き込みのために新規にファイルを作成(存在していたら上書き)し、そのファイルに読み込みアクセスのみ許可する、というような場合(dwDesiredAccess = GENERIC_READ or GENERIC_WRITE、dwShareMode = FILE_SHARE_READ、dwCreationDisposition = CREATE_ALWAYS)はTFileStreamを使用するのではなく、直接Windows APIのCreateFileをこれらのパラメータで呼び出し、取得したファイルハンドルでTHandleStreamを作成する、という処理が必要になります。例えばこんな感じでしょうか。
procedure HandleStreamSample(const AFilename: String);
var
  FileHandle: Integer;
  Stream: THandleStream;
begin

  FileHandle := CreateFile(PChar(AFilename),GENERIC_READ or GENERIC_WRITE,
                           FILE_SHARE_READ,nil,CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,0);
  if FileHandle < 0 then
  begin
    raise EFCreateError.CreateResFmt(@SFCreateErrorEx,[ExpandFileName(AFileName),
                                     SysErrorMessage(GetLastError)]);
  end;

  Stream := THandleStream.Create(FileHandle);
  try
    { Streamに対する処理 }

  finally
    Stream.Free;
  end;

end;
あるいはCreateFileの他のパラメータ、例えば第6パラメータにFILE_FLAG_...を指定したいような場合などもこのようなコーディングが必要になります。

2011年2月18日

RAD Studio/Delphi/C++Builder XE付属のFinalBuilder/AQtimeのアップデート

RAD Studio/Delphi/C++Builder XEにバンドルされているFinalBuilderとAQtimeがアップデートされ、FinalBuilder Embarcadero Edition(Ent/Arc SKUのみ)が7.0.0.992に、AQtime 7 Standard for Embarcadero RAD Studio XE(Pro/Ent/Arc SKUのみ)が7.10になっています。

AQtime and FinalBuilder Updates for Delphi XE, C++Builder XE and RAD Studio XE
28231 FinalBuilder for Delphi, C++Builder and RAD Studio XE
28230 AQtime 7.1 Standard for Delphi, C++Builder and RAD Studio XE

FinalBuilder 7 Version History

Bug Fixes in AQtime 7.10
New Features in AQtime 7.10

2011年2月16日

Project "Cooper"

2011年02月08日からLas Vegasで行われたDeveloper Solutions Conference (DSConf)でRemObjectsがJava版のDelphi Prism(Oxygene)ともいえるProject "Cooper"を発表しています。

DSConf in Review « RemObjects Blogs

現在RAD Studioに含まれているDelphi Prism("Oxygene")は.NET上で動作するObject Pascal環境ですが、Project "Cooper"はJava(JVM)/Android(Dalvik)上で動作するObject Pascal環境、ということのようです。開発環境はVisual StudioかMonoDevelopに統合されます。詳しくはプレビュービデオで。

YouTube - Project "Cooper" Preview

ただしOxygeneのいくつかの機能、例えば(.NETに強く依存する)LINQのようなものは含まれません。リリースは今年(2011年)で、それ以上のことは今は言えない(That's all we can really say,for now)、とのことです。

ちなみにYouTubeのビデオの最初に出てきますが、"Cooper"は懐かしのツイン・ピークスのクーパー特別捜査官(FBI Special agent Dale Cooper)から取られたそうです。

元ねたはフォーラムのThread: Cooper

関係ありませんが、ここ1日くらいフォーラムのサーバ(forums.embarcadero.com)が不安定のような気がします。

2011年2月14日

Delphiの特定バージョン以前/以後の判定を行う

ライブラリや共通コードを記述していると、DelphiのコンパイラやRTL/VCLの特定の機能が実装されているかどうかを判定して処理を分けたい、ということがよくあります。Delphi 2009のUnicode対応を示す標準条件シンボルの"UNICODE"のように
{$IFDEF UNICODE}
// String = UnicodeString (Delphi 2009 or later)
{$ELSE}
// String = AnsiString (Delphi 2007 or earlier)
{$ENDIF}
とできれば簡単なのですが、Windows.pasのTTokenInformationClassの新しい定義無名メソッド (ja)のサポートのように実装を示す標準条件シンボルの定義が存在しないものは単純に$IFDEFで判定できません。そこでDelphi 6で導入されたCONDITIONALEXPRESSIONSとRTLVersion/CompilerVersionを組み合わせて判定してみます。

Windows.pasにおけるTTokenInformationClassの定義はDelphi 2009(Ver20)で拡張されました。これはRTLの問題ですから、
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (RTLVersion < 20.0)}
// Delphi 2-5 or 6-2007
{$ELSE}
// Delphi 2009 or later
{$IFEND}
で判定可能です(判定を逆にしたい場合はドモルガンの法則により
{$IF (DEFINED(CONDITIONALEXPRESSIONS)) AND (RTLVersion >= 20.0)}
とする)。

一方、Delphi 2010(Ver21)で言語仕様に追加されたクラスコンストラクタとクラスデストラクタについてはコンパイラの問題ですから、
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (CompilerVersion < 21.0)}
// Class constructor/destructor is invalid
{$ELSE}
// Class constructor/destructor is valid
{$IFEND}
として判定することで、Delphi 2009およびそれ以前ではクラスコンストラクタ (ja)/クラスデストラクタ (ja)の代わりにinitialization部 (ja)/finalization部 (ja)で処理を処理を行う、といったことが可能になります。

なお$IFDEF$ENDIFで閉じますが、$IF$IFENDで閉じる、という点に注意が必要です。

2011年2月10日

UAC(User Account Control)の状態を取得する

Windows Vistaで導入されたUAC(User Account Control)が有効になっているかどうかはレジストリのHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\SystemEnableLUA(DWORD値)が0かどうかで判断できます(0はUAC無効、1はUAC有効)。一方でUACが有効のときにそのプロセスが管理者権限に昇格しているかどうかはOpenProcessToken (ja)でカレントプロセスのハンドルからアクセストークンを取得し、GetTokenInformation (ja)でTokenInformationClassにTokenElevationを指定して取得したTOKEN_ELEVATION構造体のTokenIsElevatedが0かどうかで判断できます(0は昇格していない、非0は昇格している)。

まずプロセスが管理者権限に昇格しているかどうかを判定する処理です。Windows.pasのTTokenInformationClassのTokenElevationやTOKEN_ELEVATION構造体の定義はDelphi 2009で追加されたものなので、それ以前のバージョンでは独自に定義する必要があります。
{$IF (NOT DEFINED(CONDITIONALEXPRESSIONS)) OR (RTLVersion < 20.0)}
type
  TTokenInformationClass = (TokenUser = 1,
                            TokenGroups,
                            TokenPrivileges,
                            TokenOwner,
                            TokenPrimaryGroup,
                            TokenDefaultDacl,
                            TokenSource,
                            TokenType,
                            TokenImpersonationLevel,
                            TokenStatistics,
                            TokenRestrictedSids,
                            TokenSessionId,
                            TokenGroupsAndPrivileges,
                            TokenSessionReference,
                            TokenSandBoxInert,
                            TokenAuditPolicy,
                            TokenOrigin,
                            TokenElevationType,
                            TokenLinkedToken,
                            TokenElevation,
                            TokenHasRestrictions,
                            TokenAccessInformation,
                            TokenVirtualizationAllowed,
                            TokenVirtualizationEnabled,
                            TokenIntegrityLevel,
                            TokenUIAccess,
                            TokenMandatoryPolicy,
                            TokenLogonSid,
                            MaxTokenInfoClass);
  {$EXTERNALSYM TTokenInformationClass}

  PTokenElevation = ^TTokenElevation;
  _TOKEN_ELEVATION = record
    TokenIsElevated: DWORD;
  end;
  {$EXTERNALSYM _TOKEN_ELEVATION}
  TTokenElevation = _TOKEN_ELEVATION;
  TOKEN_ELEVATION = _TOKEN_ELEVATION;
  {$EXTERNALSYM TOKEN_ELEVATION}

function GetTokenInformation(TokenHandle: THandle;
                             TokenInformationClass: TTokenInformationClass;
                             TokenInformation: Pointer;
                             TokenInformationLength: DWORD;
                             var ReturnLength: DWORD): BOOL; stdcall;
  external advapi32 name 'GetTokenInformation';
{$EXTERNALSYM GetTokenInformation}
{$IFEND}

function IsProcessTokenElevated(ProcessHandle: THandle): Boolean;
var
  TokenHandle: THandle;
  TE: TOKEN_ELEVATION;
  dwLength: DWORD;
begin

  Result := False;

  if OpenProcessToken(ProcessHandle,TOKEN_QUERY,TokenHandle) = False then
  begin
    Exit;
  end;

  try
    if GetTokenInformation(TokenHandle,TokenElevation,
                           @TE,SizeOf(TE),dwLength) = False then
    begin
      Exit;
    end;

  finally
    CloseHandle(TokenHandle);
  end;

  Result := (TE.TokenIsElevated <> 0);

end;
これを使用して、レジストリの値をチェックし、UACが有効ならIsProcessTokenElevatedで管理者権限に昇格しているかどうかを確認します。
type
  TUACStatus = (usNoUAC,           // UAC is not implemented
                usUACDisabled,     // UAC is disabled
                usUACEnabled,      // UAC is enabled
                usUACRunAsAdmin);  // UAC is enabled and process token is elevated

function GetUACStatus: TUACStatus;
var
  ReadValue: Integer;
begin

  Result := usNoUAC;

  if CheckWin32Version(6,0) = False then
  begin
    // Windows 2000 or XP: UAC is not implemented
    Exit;
  end;

  with TRegistry.Create do
  begin
    try
      RootKey := HKEY_LOCAL_MACHINE;
      if OpenKeyReadOnly('\Software\Microsoft\Windows\CurrentVersion\Policies\System') = False then
      begin
        raise ERegistryException.Create('Error: Cannot open registry key.');
      end;

      try
        ReadValue := ReadInteger('EnableLUA');
        if ReadValue = 0 then
        begin
          Result := usUACDisabled;
        end
        else
        begin
          Result := usUACEnabled;
        end;

      finally
        CloseKey;
      end;

    finally
      Free;
    end;
  end;

  if Result = usUACEnabled then
  begin
    if IsProcessTokenElevated(GetCurrentProcess) = True then
    begin
      Result := usUACRunAsAdmin;
    end;
  end;

end;
GetUACStatusの戻値がusUACEnabledの場合、REGEDITのように実行時に管理者権限を要求するプロセスを起動するときにUACの確認ダイアログが開くことになります(usNoUAC/usUACDisabledならUACは動作せず、usUACRunAsAdminなら既に昇格済なので確認されない)。

UACが有効かどうかとプロセスが昇格しているかは別々に取得するようにしたほうがいいのかもしれませんが、UAC有効でなければプロセスの昇格も起きないので、ここでは1つにまとめました。

元ねたはDisplay UAC Status - Sysinternals Forums - Page 1EternalWindowsセキュリティ / セキュリティコンテキスト / UAC

2011年2月9日

2011年2月8日

モーダルなフォームのOnShowイベントでそのフォームを閉じる

プログラム的に必要な設定が行われていないなど、何らかの理由でShowModalされた(モーダルな)フォームのOnShowイベントで当該フォームを閉じたい、ということがたまにあります。ところがOnShowイベントで
procedure TForm2.FormShow(Sender: TObject);
begin

  Close;

end;
としてもそのフォームを閉じることはできません。これはTCustomForm.Closeの実装が
procedure TCustomForm.Close;
var
  CloseAction: TCloseAction;
begin
  if fsModal in FFormState then
    ModalResult := mrCancel
  else
    ...
(Delphi 2007のForms.pasの5589行目付近より)
とモーダルなフォームではModalResultをmrCancelに設定するだけで、一方TCustomForm.ShowModalは
function TCustomForm.ShowModal: Integer;
  ...
  try
    Show;
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      ModalResult := 0;
      repeat
        Application.HandleMessage;
        if Application.Terminated then ModalResult := mrCancel else
        if ModalResult <> 0 then CloseModal;
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      Hide;
    end;
  ...
end;
(Delphi 2007のForms.pasの5816行目付近より)
となっており、Showの内部でCloseを呼び出してModalResultをmrCancel(など0以外の値)に変更しても、Showから戻ってきてから0に戻されてしまい、"ModalResult <> 0"という終了条件を満たさないためです。

これを回避するには例えばTTimerを使う方法も考えられますが、お手軽な解決として
procedure TForm2.FormShow(Sender: TObject);
begin

  PostMessage(Handle,WM_CLOSE,0,0);

end;
と自分(モーダルなフォーム)にWM_CLOSEメッセージをpost(sendではない)するという方法があります。PostされたWM_CLOSEメッセージはメッセージキューの最後に追加され、repeat-untilループの内部のApplication.HandleMessageでディスパッチされてTCustomForm.WMCloseから最終的にCloseが呼び出されることでModalResultが0以外の値になり、終了条件を満たしてフォームが閉じる、という仕組みです。

2011年2月7日

KSDevをエンバカデロが買収

先日のqadramに続き、エンバカデロ・テクノロジーズがVGSceneDXSceneの開発元であるKSDevのIPを買収し、KSDevのEugene Kryukovさんが"次世代フレームワーク"チームに加わった、とのことです。

Welcome - KSDev - Adobe AIR or WPF like components, 3D in Delphi, Delphi skin, Flash control, Visio like diagram drawing
I am excited to announce that I have joined Embaracadero’s next gen frameworks team leading a very exciting project.
I am working on a very exciting next generation App Development project that will go beyond what the KSDev products were providing. It is safe to say that similar functionality of these frameworks will be made available in future Embarcadero development products. I believe it will be well worth the wait.

というわけで現在のTFormを中心としたフレームワークを置き換える、おそらくはプラットフォーム非依存の新しいフレームワークが計画されている、ということのようです。

元ねたはEmbarcadero purchase KSDev « Delphi Haven

[書籍]プログラミング .NET Framework 第3版

同じくMARUZEN&ジュンク堂書店 渋谷店

プログラミング .NET Framework 第3版 (amazon)/Jeffrey Richter著/藤原雄介訳/日経BP/ISBN 978-4-82229-416-8/7,350円

を購入。

[書籍]C#ルールブック

MARUZEN&ジュンク堂書店 渋谷店

C#ルールブック ~読みやすく効率的なコードの原則 (amazon)/向山隆行、片山優司、阿部順一、寺田和朗、畑中良平著/電通国際情報サービス監修/技術評論社/ISBN 978-4-7741-4502-0/2,604円

を購入。

2011年2月6日

JCL 2.3.0.374/JVCL 3.41 Binary Installer for XEリリース

Delphi /C++Builder XE Starter SKUにコマンドラインコンパイラDCC32が付属していないため、JCL/JVCLのようにインストーラがDCC32を使用してコンパイルを行うタイプのライブラリをStarter SKUにインストールできない、という問題がありましたが、この問題を回避するJCL/JVCLのコンパイル済バイナリのインストーラがCodeCentralにアップロードされています。

28222 Jedi Code Library 2.3.0.374 Binary Installer for XE
28223 Jedi Visual Component Library 3.41 Binary Installer for XE

JVCLのBinary InstallerでJVCLをインストールする場合は、事前にJCLもBinary Installerでインストールしておく必要があるとのことです。

元ねたはJCL and JVCL Binary Installer for XE and Starter Edition | Andy’s Blog and Tools

2011年2月5日

DDevExtensions 2.3リリース

Andreas HausladenさんDDevExtensionsがアップデートされてVersion 2.3になっています。Delphi 2007用の"Set Version Info"の問題を含め、いくつかの不具合が修正され、Delphi 2009/2010/XE用のものが1つのパッケージに統合されています。

DDevExtensions 2.3 available | Andy’s Blog and Tools

2011年2月4日

Firebird 2.1.4 Release Candidate 1リリース

Firebird 2.1.4 Release Candidate 1がリリースされました。いくつかの機能追加と多数の不具合修正が行われています。

Firebird File Repositories (download)
Firebird 2.1.4 Release Candidate 1 Release Notes

2011年2月3日

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

第19回エンバカデロ・デベロッパーキャンプは以前からの予告どおり2011年03月30日に開催されます。

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

今回はエンバカデロ・テクノロジーズ チーフサイエンティストのAllen Bauerさんが来日、Pulsarのx64サポートやRAD Studio XEについてのディープなセッションが用意されています。また今回もG6セッションでライトニングトーク「共有!みんなの開発事例、開発経験、テクニック」があります。

CFPは頂きましたが、ネタは熟慮中です…。

2011年2月2日

Open Tools APIを使用してIDEのアドオンを作る

A7MさんによるOpen Tools API(OTA)を使用したadd-onの作り方。興味深い。

Open Tools API その0:概要 - C++Builder好きの秘密基地
Open Tools API その1:"Hello,World!"を表示してみる - C++Builder好きの秘密基地
Open Tools API その2:メニューの差し替えとノーティファイアインターフェース - C++Builder好きの秘密基地
Open Tools API その3:ソースエディタへのアクセス - C++Builder好きの秘密基地
Open Tools API その4:続・ソースエディタへのアクセス ソースエディタの「中身」をいじる - C++Builder好きの秘密基地

関連してGnosticeのGirish PatilさんによるCodeRage 5のOTA関係のセッションのリプレイビデオ(約35分)。

Video: Open Tools API を使用して Delphi IDE をより効果的にする方法を探る (英語)

Girish Patilさんによるセッションのデモコードは

Gnostice @ CodeRage Virtual Conference

からダウンロードできます。またOTAについてはGExperts

Erik's Open Tools API FAQ

も参考になるとのことです。

さらにUwe SchusterさんによるRAD Studio XEにおけるOTAの拡張、修正点に関する解説。

RAD Studio XE: Open Tools API changes highlighted Part#1 | Uwe's Delphi blog

2011/02/05追記: その3のリンクを追加。あとは次回のデベロッパーキャンプのA3セッションで。

2011/02/12追記: その4のリンクを追加。

2011年2月1日

エンバカデロ・デベロッパーキャンプツアー・イン名古屋/大阪 2011

以前から予告されていたミニキャンプことデベロッパーキャンプツアーの開催が正式に発表されています。

エンバカデロ・デベロッパーキャンプツアー・イン名古屋 2011
2011年03月02日(水曜日) 13:30-17:00 愛知県産業労働センター

エンバカデロ・デベロッパーキャンプツアー・イン大阪 2011
2011年03月03日(木曜日) 13:30-17:00 大阪ビジネスパーク

いずれも海外担当副社長兼ジェネラルマネージャーのNigel BrownさんがジェネラルセッションとQ&Aセッションを行うようです。

Delphi/C++Builder XE Starterの機能制限

Delphi/C++Builder Starter SKUで動作する機能、動作しない機能に関する情報です(主にIDE関係)。

○ コード補完 ([Ctrl]+[Space])
○ ブロック補完 ("begin"[Enter]で"end;")
× クラス補完 ([Ctrl]+[Shift]+[C])
× ライブテンプレート ("for"[TAB]で"I := 0 to List.Count - 1 do" や "fo"[Ctrl]+[J]で"for"/"forb"/"forin"/"forr"を選択)
× デバッグ中のツールチップヘルプによる値の表示
× デバッグ中のローカル変数ウィンドウ
× コード参照/定義の検索 ([Ctrl]+Click)
○ InterBase Express (IBX)
○ Borland Database Engine (BDE)
× Database Express (DBX), DataSnap, TClinetDataSet
× VCL/RTLソースコード
○ サードパーティコンポーネントのインストール
○ Open Tools API (OTA)

元ねたはフォーラムのEmbarcadero Discussion Forums: Starter Edition is there

2011/02/03追記: Starter SKUにはコマンドラインコンパイラDCC32が含まれないため、DevExpressやJCL/JVCLのようにインストール時にコマンドラインコンパイラを使用するものはインストールに失敗する、という問題が公式フォーラムやjedi newsgroupに報告されています。

Embarcadero Discussion Forums: DevExpress Controls Won't Install in Delphi Startee Edition

とりあえずStrater用にコンパイル済バイナリを同梱するか、ファイル展開後にIDEで.dpkを開いてインストールするか、というのが解決方法でしょうか。

Delphi/C++Builder XE Starter日本語情報

日本語のリリースが公開されています。

エンバカデロ、C++Builder StarterとDelphi Starterを本日より販売開始

Delphi XE Starter Edition
機能一覧 (PDF)

C++Builder XE Starter Edition
機能一覧 (PDF)

Delphi XE Starter Edition / C++Builder XE Starter Edition - Q&A

Starter SKUはESD(Electronic Software Distribution)版のみで価格は18,900円、アップグレードの場合は14,700円になります(いずれも消費税込み)。

"1,000USDルール"はライセンスの追加条項で
Starter エディションに適用される追加条項
お客様が Starter エディションのライセンスを取得された場合には、以下の条項が適用されます。第 2 条第 1 項の権利付与と矛盾する範囲においては、この条項が優先するものとします。お客様は本製品を使用して、(i)お客様が直接または間接に料金を請求せず、ライセンス料金、サービス料金、開発料金、コンサルティング料金、サブスクリプション料金、サポート料金、ホスト設定料金などの報酬を受け取らないソフトウェア、および、(ii)お客様が請求する料金(ライセンス料金、サービス料金、開発料金、コンサルティング料金、サブスクリプション料金、サポート料金、ホスト設定料金など)が年間の累積で 1000 US ドルを超えないソフトウェアを、開発することができます。企業(営利か非営利かを問いません)がソフトウェアの使用権を付与する場合には、(i)企業全体の収益が 1000 US ドルを超えてはならず、(ii)配置する Starter エディション ライセンスの総数が 5 ライセンスを超えてはなりません。
ということになっています。また教育目的にはStarter SKUは適していないので、アカデミックライセンスを検討してほしいとのことです。

ITpro(要登録)、IT Leaders、ZDNet Japanにも記事が出ています。

DelphiとC++ Builderの廉価版が登場、1万4700円から - ニュース:ITpro
エンバカデロ、C++/DelphiのIDEに1万8000円の廉価版、条件は年間収益1000ドル | IT Leaders
エンバカデロ、商用利用も可能なC++BuilderとDelphiの低価格版 - builder by ZDNet Japan

2011年1月31日

Delphi/C++Builder XE Starterエディション公式ページ

またもフライング気味ですが、Delphi/C++Builder XE Starterエディションの公式ページが出現しています(いまのところ英語のみ)。

Delphi XE Starter Edition
Delphi XE Starter Edition and C++Builder XE Starter Edition FAQs
Feature Matrix (PDF)

C++Builder XE Starter Edition
Feature Matrix (PDF)

Starter SKUで何ができてどの機能が使えなくなったのかはPDFのFeature Matrixで確認できます。

元ねたは公式フォーラムのThread: Starter Edition is thereAndreano LanusseさんDelphi XE and C++Builder XE Starter Editions – Officially announced

日本語の情報は明日になる模様です。

2011/02/01追記: 公式なリリースが出ています。

Embarcadero Introduces Starter Editions of C++Builder and Delphi Rapid Application Development Environments

またプロダクトマネージャのMichael Rozlogさん、プロダクトマーケティングマネージャのTim Del Chiaroさんのblogにも記事が出ています。

Michael Rozlog » Blog Archive » Starter Edition Finally Here!!!
Delphi Insider: Delphi XE Starter and C++Builder XE Starter Now Available

2011年1月28日

Delphi/C++Builder Starter Edition

DelphiとC++BuilderのStarter Editionが発表された、という記事がSDTimesに出ています。とりあえず速報ということで。

Embarcadero Introduces Starter Editions of C++Builder and Delphi Rapid Application Development Environments - SD Times: Software Development News

この記事の注目ポイントとしては、特に機能に関する制限は明示されていないものの、1つのネットワークで5ライセンス以内で、それを超える場合やその開発で1,000USD以上の収入がある場合、あるいはDBX/DataSnapを使う場合は上位のSKUにアップグレードしなければならない、というあたりでしょうか。Starter Editionの価格は199USDで、以前のTurbo Editionや他の競合製品のユーザは149USDでアップグレード可能です。

あとは正式発表待ちです。

元ねたは公式フォーラムのThread: Delphi Starter Edition

1,000USDの件は、Users may sell any applications or components developed with these tools until the annual license or service revenue exceeds $1,000 USD or their micro organization exceeds $1,000 in revenue overall.ですので、個人、学生は年間で、組織の場合は累計で、ということになります。

2011/01/29追記: DEKOさんも指摘しています DEKOさんも指摘していますが、SD Timesの記事は予定稿だったはずで、公開時期が来ていない記事が"http://www.sdtimes.com/link/35223"とかいう"ありふれた方法"で見えちゃうのはまずいですよね。いずれにせよプロダクトマーケティングマネージャのTim Del Chiaroさんによると正式発表は来週前半(2011/02/01)に予定されており、(おそらくESDで)購入も可能になるようです。

2011年1月27日

TortoiseSVNの導入 その1

RAD Studio XEではVersion Insight (ja)という形でバージョン管理システムのクライアント機能がIDEに統合され、Apache Subversion (wikipedia)のクライアントとなることができるようになりました(Version InsightそのものはSubversionに限定されるものではなく、将来的にはGit (wikipedia)やMercurial (wikipedia)などにも対応してゆくとのこと)。またDemoもSourceforgeでホストされるようになりました。しかし2010以前のユーザはこの恩恵を受けられません。そこでSubversionのWindowsにおける最も一般的なクライアントであるTortoiseSVN (日本語ミラーサイト)を導入してみるテストです。

まずはTortoiseSVNのインストールですが、Version 1.5以降ではなぜかインストーラがGDI+を必要とします。このためWindows 2000の場合は

Download details: Platform SDK Redistributable: GDI+

からWindowsXP-KB975337-x86-ENU.exeをダウンロードし、展開(実行)して、<展開先>\asms\10\msft\windows\gdiplusのgdiplus.dllをsystem32にコピーします。

次に公式サイトまたは日本語ミラーサイトから最新版(2011/01/26現在で1.6.12)のアプリケーションと日本語パッケージ(Langugage Packsの"ja")のインストーラをダウンロードします(どちらもx86とx64で別のファイルになっているので注意が必要です)。あとはアプリケーション、日本語パッケージの順にインストールし、[スタート]→[プログラム]→[TortoiseSVN]→[Settings]で設定画面を表示して、General(一般)ページのTortoiseSVNのLanguage(言語)を"日本語"に変更して適用すれば準備は完了です。TortoiseSVNのインストールについては

Subversion/TortoiseSVNのインストール - ピノキヲ IT Wiki

が参考になります。ちなみに日本語のオンラインヘルプは

TortoiseSVN

にあります([スタート]→[プログラム]→[TortoiseSVN]→[Help]と同じものです)。ひととおり目を通しておくべきでしょう。

さて、準備は完了といっても、いきなりSubversionのサーバを立てて、というのはいささかハードルが高いので、Nick HodgesさんThe Best way to Get TSmiley, or…. A Subversion Primerに従ってTSmileyをチェックアウトしてみることにしましょう。

まずTSmileyをチェックアウトするフォルダを用意します(ここでは"D:\SVN\TSMILEY"とします)。エクスプローラからこのフォルダを右クリックし、コンテキストメニューから"SVNチェックアウト"を選択します。チェックアウトダイアログでリポジトリのURLを"https://tsmiley.svn.sourceforge.net/svnroot/tsmiley"、チェックアウトディレクトリは"D:\SVN\TSMILEY"のままとして[OK]をクリックするとチェックアウトが始まります。チェックアウトが終了したらエクスプローラで"D:\SVN\TSMILEY"を見てみましょう。確かにTSmileyのファイルがチェックアウトされています。

とりあえずここまで。

2011年1月26日

DDevExtensions 2.2.1リリース

Andreas HausladenさんDDevExtensionsのVersion 2.2の"Use Unit"に問題があったということでVersion 2.2.1がリリースされています。

Bugfix DDevExtensions 2.2.1 | Andy’s Blog and Tools

2011/02/03追記: Delphi 2007用のDDevExtensions 2.2/2.2.1は"Set Version Info"機能が正常に動作しないという不具合が確認されています。この機能が必要な場合は1.6.1または2.0 snapshotまで戻る必要があります。

2011年1月25日

DDevExtensions 2.2リリース

Andreas HausladenさんDDevExtensionsがアップデートされてVersion 2.2になっています。Delphi 7/2007も最新の2.2でサポートされるようになりました。

DDevExtension 2.2 released | Andy’s Blog and Tools

第19回エンバカデロ・デベロッパーキャンプの日程調整中

次回(第19回)のデベロッパーキャンプはエンバカデロのチーフサイエンティストのAllen Bauerさんアジアツアーに合わせる形で2011年03月30日に開催する方向で調整中とのことです。日本的には年度末ですが、Allen Bauerさんが日本に来るのは(多分)4年ぶりで、これを逃すと次の機会はまた5年後くらいになりそう(藤井さん談)なので、ということです。正式なアナウンスは近日中にあると思われます(フライング気味ではありますが、忙しい時期ですのでまずは事前情報ということで)。またその前の2011年03月02日~03日ぐらいに大阪、名古屋でもミニキャンプを行う予定とのことです。このデベロッパーキャンプ、ミニキャンプの日程を含め、しばらくは最新情報に注目、です。

2011/01/26追記: ミニキャンプは名古屋が2011年03月02日、大阪が2011年03月03日で確定した模様です。

2011/02/01追記: 大阪、名古屋のミニキャンプが正式に発表されています。

2011年1月18日

DelphiでKinect

もうあちこちで既出ですが、IT Security LabのAleksさんによる、DelphiでKinectを扱うデモ。とても興味深い。とりあえずメモ。

Having Fun with Kinect and Delphi (examples of 2D and 3D visualization) « IT Security Lab
More 3D Fun with Kinect and Delphi. You can grab and save still 3D frames! « IT Security Lab

Kinectの制御はSimon StuartさんによるTKinect for Delphiを使用しています(TKinect for Delphiには別途Code LaboratoriesCL NUI SDKが必要とのこと)。

元ねたはAmazing demo of TKinect component for Delphi | Andreano Lanusse Blog

2011年1月17日

Visual Studio 2010の新しい"Help3"システム

Visual Studioでは2002以降で(Delphiでも使用している)Document ExplorerによるMicrosoft Help 2(.hxs)形式のヘルプシステムを採用していましたが、やはり不評だったようで、VS2010では新たに"Help3"と呼ばれるヘルプシステムを開発しました。この"Help3"作成の経緯などをMicrosoftのLibrary EXperience (LEX)チームのJeff Braatenさんが明らかにしています。

The Story of Help in Visual Studio 2010
The Story of Help in Visual Studio 2010 (Part 2)
The Story of Help in Visual Studio 2010 (Part 3)

"Help3"はヘルプシステムのパフォーマンス改善、オフライン/オンラインの切替、MSDNとの共存、ローカライズ、適切な内容のヘルプの表示、といった問題を解決するべく開発が行われました。ただ"Help3"は例によって"早すぎた"ようで、Visual Studio 2010 SP1でHelp Viewerも更新される予定です(既にベータ版が利用可能になっています)。

上記のアーティクルでも考察されていますが、現在Windows上で使用できるヘルプシステムは
の事実上4種類です。今後Delphiのヘルプシステムはどうなっていくのでしょう?

2011/01/18追記: "Help3"についてはこんなページもありました。

XLsoft エクセルソフト : Helpware Group - FAR HTML ヘルプ作成ツール - 日本語ホーム
MS Help Viewer 1.0

旧形式からのマイグレーションツールビュアー、対応オーサリングツールもあるようです。

2011年1月14日

日本語文字列照合順番(JIS X 4061:1996)

初めて知ったのですが、日本語の並び替え(いわゆる『五十音順』『電話帳順』)にはJIS規格が存在しています。JIS X 4061:1996の『日本語文字列照合順番 (Collation of Japanese character string)』です。

JSA Web Store - JIS X 4061:1996 日本語文字列照合順番
日本語文字列照合順番 - Wikipedia

この規格では照合順番として"単純照合"、"読み・表記照合"、"代表読み照合"の3種類が定義されています。ただ実装はどれもそれなりに複雑になりそうです。

規格票はJISC 日本工業標準調査会日本工業標準調査会:データベース検索-JIS検索から閲覧することができます(冊子あるいはPDF形式のものは上記のJSA Web Storeや書店で購入することもできますが、たった33ページで1785円です)。

元ねたは中村正三郎さんの乳の詫び状の2011/01/14分の記事。

2011年1月12日

Microsoft Monthly Update 2011/01

今日はMicrosoftのセキュリティアップデートの日です。
MS11-001
MS11-002

2011年1月11日

RadPHPと開発チームをエンバカデロが買収

いまのところEmbarcadero Technologiesqadram softwareのどちらからも公式な発表は行われていませんが、Marco Cantuさん

Embarcadero Buys Quadram (and Hires Jose Leon)

によるとEmbarcaderoがqadramからRadPHP(Delphi for PHP)とその開発チームを買収したようです。Jose Leonさんのタイトルは"Director of Engineering and Branch Director at Embarcadero Technologies"となっており、そのままRadPHP開発チームのディレクタになったようです。

2011/01/25追記: qadram softwareはRadPHPチームとなり、エンバカデロの一部となったようです(完全買収ということ)。

2011年1月6日

InterBase XE日本語版リリース

英語版のみのリリースとなっていたInterBase XEですが、日本語版がリリースされたようです。

エンバカデロ、軽量・ハイパフォーマンスデータベースの最新版InterBase XE日本語版を発表

バージョンはWindows(x86/x64)が10.0.1.335、Linux、Solaris、Macが10.0.0.305となっています(Update 1ということです)。

次期版WindowsはARMをサポート

信頼できない噂として昨年末から語られていた次期版Windows(Windows 8)におけるARMサポートですが、現在行われている2011 International CESでこの噂が本当であり、次期版のWindowsではIntel、AMD(x86/x64)に加えてARMとこれらのSoCをサポートする、というニュースが飛び込んできました。

Next Version of Windows Will Run on System on a Chip (SoC) Architectures from Intel, AMD and ARM: Q&A: In a technology preview at CES, Microsoft demonstrates Windows running on new SoC x86 and ARM-based systems. Microsoftによる公式発表。

2011 International CES:次期版WindowsはARMアーキテクチャをサポート - ITmedia News
MS、次期WindowsでのSoCサポートを明らかに--CES - CNET Japan
マイクロソフト、次期WindowsのARMサポートを正式発表
Microsoft、WindowsをSoCに拡大 - ARMシステムもサポート | パソコン | マイコミジャーナル
[CES2011]Microsoft、次期版WindowsでARMアーキテクチャーをサポートへ - ニュース:ITpro
【PC Watch】 Microsoft、次期WindowsでARMアーキテクチャをサポート
【PC Watch】 【CES 2010レポート】Microsoft基調講演レポート ~次期WindowsのSoCサポートを明言

NVIDIA、Qualcomm、Texas Instrumentsが開発しているARMをベースとしたSoC上でWindowsを動作させることができるようになる模様です(NVIDIAがすんなりとIntelのチップセットから撤退したのはこれがあったからかもしれませんね)。CESでは実際にARM上でWindowsとOfficeが動作しているデモが行われたようです。

Live from Microsoft's CES 2011 keynote -- Engadgetの7:36PMから7:43PMにかけてがARM/SoCサポート関係の発表の実況です。

2011/01/14追記: もう少し詳細な情報が出てきているようです。

【笠原一輝のユビキタス情報局】 Microsoft ダレン・ヒューストン副社長に聞く、ARM版Windowsの正体
CES2011: ARM対応版次期Windowsはどうなる? MS幹部インタビュー

どうやらバイナリ互換性はなく、ネイティブアプリケーションはx86とx64のようにARM用のバイナリを用意する必要がありそうです(.NET Frameworkはおそらくそのまま動くのでしょうけれども)。ロードマップのCommodoreでARMサポートが計画されていることと関連があるのでしょうか…?

2010年12月27日

[書籍]土木建築エンジニアのプログラミング入門

オンラインの日経BP書店

土木建築エンジニアのプログラミング入門/フォーラムエイト著/日経BP/ISBN 978-4-8222-6621-9/2,940円

を購入。この間のデベロッパーキャンプでフォーラムエイトの宮本さんが『近日中にAmazonでも扱いが始まるはずです』といっていましたが、待つのも面倒なので…。全ページ多色刷り、CD-ROM付きで豪華です。

2010年12月22日

Windowsのテストに便利なツールとその使用法

Windows 7/Server 2008 R2上でテストを行うためのツール類とその使用方法を紹介するドキュメントをMicrosoftが公開しています。

Windows のテストに便利なツールとその使用法

紹介されているツールとその使用方法(要約):
  • システムイメージの作成と復元: Windows Automated Installation Kit (WAIK)
  • デバイスのプラグアンドプレイ(PnP)関連のテスト: Plug and Play Driver test (Pnpdtest.exe) (WDKに付属)
  • システムのスリープ・レジュームの移行を自動的に繰り返し実行: Power Management Test Tool (Pwrtest.exe) (WDKに付属)
  • アプリケーションの動作を検証: Application Verifier
  • ネットワークパケットを監視・分析: Network Monitor
  • Windowsポータブルデバイス(WPD)の動作をモニタ: WPD Monitor (WPDMon.exe) (WDK)
  • 問題の再現手順を簡単に記録: 問題ステップ記録ツール (Problem Steps Recorder) (Windows標準)
  • マネージアプリケーションの例外とコールスタックを取得: WinDBG (Windows SDK)
  • カーネルモードドライバ内のエラーを検出: Driver Verifier (Windows標準)
  • ブルースクリーンの問題を調査: Debugging Tools for Windows (Windows SDK)

紹介されているツールのダウンロードリンク:

2010年12月21日

[書籍]デザインのためのデザイン

ジュンク堂書店の吉祥寺店

デザインのためのデザイン (amazon)/Frederick P. Brooks, Jr.著/松田晃一、小沼千絵訳/ピアソン桐原/ISBN 978-4864010047/3,780円

を購入。

2010年12月17日

InterBaseのバックアップ、ジャーナル機能

かなり前になりますが、InterBase 2007以降の新機能の物理バックアップ、ジャーナル関係の興味深いアーティクルがいくつか。

InterBaseのバックアップ機能について
InterBaseのジャーナル機能について
InterBase 2007稼働中にシステム時間を変更した場合の影響について

てきとうな要約:
  • InterBase 2007以降では
    • 従来のフルバックアップ("gbak -b"でODS非依存のバックアップファイルが作成される)
    • 物理バックアップ("gbak -d"で現状の.IBのコピーが作成され、"gbak -d"毎に変更のあったページのみがインクリメンタルに更新される)
    の2種類のバックアップが可能。物理バックアップしたファイルは読み込み専用の状態になっており、"gfix –mode read_write"で書き込み可能(つまりオリジナルと同等)になる。
  • 一方InterBase 2007以降のジャーナルはデータベースに対して"CREATE JOURNAL"とすることでジャーナルファイルが作成されるようになる。更に"CREATE JOURNAL ARCHIVE"とすることでジャーナルアーカイブ機能が有効になり、この状態で"gbak –archive_journals"でジャーナルアーカイブファイルが、"gbak –archive_database"でアーカイブデータベースダンプファイルが、それぞれ作成される。このジャーナルアーカイブファイルとアーカイブデータベースダンプファイルを使用して"gbak –archive_recover"とすることでデータベースを復旧することができる。ジャーナル関係のファイルはバックアップ関係のファイルとは異なりプラットフォーム依存。
  • 運用中にシステム時刻が変更された場合、物理バックアップのインクリメンタルな更新やジャーナルに影響を及ぼすので要注意。

InterBase Serverサービスを停止しなくても"gbak -d"で安全にコピーが取れるようになったということですね。

2010年12月16日

BDE Alternatives Guide

先日のデベロッパーキャンプでも再三BDEはやめましょう、という話が出ていましたが、こんなページがありました。

Data Access for Delphi

BAG="The BDE Alternatives Guide"ですね。

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

2010年12月15日

Microsoft Monthly Update 2010/12

今日はMicrosoftのセキュリティアップデートの日です。
MS10-090
MS10-091
MS10-092
MS10-093
MS10-094
MS10-095
MS10-096
MS10-097
MS10-098
MS10-099
MS10-100
MS10-101
MS10-102
MS10-103
MS10-104
MS10-105
MS10-106

月間17件、年間106件とも過去最多の数字になります。攻撃手法の進化はあるにせよ、Microsoftの"新しいOSはセキュア"といういつもの主張はお題目に過ぎないことがわかります。頑張っていることはわからないでもないのですけれども…。

2010年12月14日

Delphi/C++Builder初学者のための資料

Delphi-MLや先日のデベロッパーキャンプでも話が出ていましたが、これからDelphi/C++Builderを始めようとすると、入門書の類いはほとんどなく、またヘルプにもチュートリアル的な内容(に限りませんけどね…)がろくに存在しないため、系統的にDelphi/C++Builderを学ぶのが意外に難しい、というのが今の状況です。そこでこのような人のために、入手可能性がそれなりな情報を集めてみました。ただし環境がTurboだったり2007だったり2009だったり、あるいは書籍はもっと古かったりしますが、そこは適当にスルーということで。またデータベース関係についてはDBXのもの以外は軽く読み飛ばしてしまって構いません(いまさらですから)。

EDN(Embarcadero Developer Network): エンバカデロ・テクノロジーズの運営する開発者向情報サイト。過去に入門的な内容のアーティクルがいくつか掲載されました。

EDN/Delphi/ナッキーの「Turbo Delphiはじめて奮戦記」
ナッキーの「Turbo Delphiはじめて奮戦記」(全24回)

EDN/Delphi/ナッキーの「Delphiでビジネスアプリ奮闘記」
第1回 CSVファイルをデータベースへ移行する その1
第2回 CSVファイルをデータベースへ移行する その2
第3回 データベースのレコードを編集する
第4回 データベースのレコードをCSVファイルに保存する

EDN/C++Builder/石原高のオレ流C++独学塾
第1回 オレ流Hello World
第2回 C言語の知識で挑むC++Builder
第3回 CSVファイルを処理してみる
第4回 長い処理をスレッドで実行する

EDN/C++Builder/C++Builder 2009 ファーストガイド
第一回 「C++Builder 2009のインストールと使用許諾」
第二回 「C++Builder2009の起動と終了」
第三回「総合開発環境(IDE)の説明」
第四回「プログラミング手順(前編)」
第五回「プログラミング手順(後編)」
第六回「C++基礎知識(前編)」
第七回「C++基礎知識(後編)」
第八回 「コンポーネント」
第九回「コンポーネントの作成」
第十回「データベースアプリケーションの作成」

書籍: 昨今の出版不況の影響でDelphi/C++Builderの新しい書籍が出ることは考えにくい状況ですが、古本という形でなら入手可能なものもあるようです。このうちオフィシャルコースウェアはどれか一つあれば十分かなと思います(そういう意味ではDelphi 7のものを入手できればいいかと)。また『ナッキーのDelphiはじめて奮戦記』は上記のEDNの記事の書籍化ですが、まとまっている分読みやすいのではないかと思います。

書籍/オフィシャルコースウェア
Borland Delphi4オフィシャルコースウェア 入門編 (amazon)/服部誠著/インプライズ監修/アスキー/1999年/ISBN978-4756130242/
Borland Delphi 4オフィシャルコースウェア (システム開発編) (amazon)/加藤大受著/アスキー/1999年/ISBN978-4756130259/5,040円
Borland Delphi4オフィシャルコースウェア クライアントサーバシステム構築編 (amazon)/真木保著/インプライズ監修/アスキー/1999年/ISBN978-4756131379/5,460円
Borland Delphi 5オフィシャルコースウェア (基礎編) (amazon)/服部誠著/アスキー/1999年/ISBN978-4756132772/2,940円
Borland Delphi 5オフィシャルコースウェア (応用編) (amazon)/井上勉著/アスキー/2000年/ISBN978-4756133236/
Borland Delphi6オフィシャルコースウェア 基礎編 (amazon)/服部誠著/ボーランド監修/アスキー/2002年/ISBN978-4756140029/
Borland Delphi 6オフィシャルコースウェア 応用編 (amazon)/井上勉著/ボーランド監修/アスキー/2002年/ISBN978-4756140036/
Borland Delphi7オフィシャルコースウェア 基礎編 (amazon)/服部誠著/ボーランド監修/アスキー/2003年/ISBN978-4756142283/2,940円
Borland Delphi7オフィシャルコースウェア 応用編 (amazon)/井上勉著/ボーランド監修/アスキー/2003年/ISBN978-4756142290/5,040円

書籍/一般解説書
Delphiの奇跡―普通のプログラマのための真面目な入門書 (amazon)/吉田弘一郎著/技術評論社/1995年/ISBN978-4774102160/
ナッキーのDelphiはじめて奮戦記 (amazon)/佐竹那月著/カットシステム/2007年/ISBN978-4877831332/
Delphi 4プログラミングバイブル (amazon)/Marco Cantu著/篠原慶訳/インプレス/1999年/ISBN978-4844312734/
Delphi 6 プログラミングバイブル (amazon)/Marco Cantu著/篠原慶、光田秀訳/2002年/ISBN978-4844316343/
Turbo DelphiではじめるWindowsプログラミング (amazon)/日経ソフトウエア編/日経BP/2007年/ISBN978-4-8222-2842-2/2,520円

その他
Seventh Delphi Delphi 入門/旧 Delphi 入門/Delphi FAQ

オフィシャルコースウェアあたりは古い内容そのままで構わないんでPDFにでもして配ってくれませんかね…?

2010/12/15追記: RANさんからコメントを頂いたSeventh Delphiさんのリンクを追加しました(Bloggerはコメントが読みにくいので)。

2010年12月10日

浮動小数点数についての解説

Rudy VelthuisさんによるDelphiにおける浮動小数点数(公式には"実数型")の扱いに関する詳細な解説。興味深い。

Rudy's Delphi Corner - Floating point numbers

元ねたは公式フォーラムのEmbarcadero Discussion Forums: Float operations

2010年12月9日

CONDITIONALEXPRESSIONS

CONDITIONALEXPRESSIONSはVER140(Delphi 6, C++Builder 6, Kylix 1/2/3)以降で使用可能な標準条件シンボルで、$IFに対して値に関する条件を記述できることを示しています(CONDITIONALEXPRESSIONSが未定義なら$IFDEF/$IFNDEFで条件シンボルが定義されているかどうかの判定しかできませんが、定義されていれば値を"="、"<"、"<="、">"、">="、"<>"で比較できます)。

このときに使用できるRTLVersion/CompilerVersion/FireMonkeyVersionは定数で、RTLVersion(System.pasで定義)はVER140以降で使用可能、CompilerVersion(コンパイラがSystem.pasをコンパイルするときに設定)はVER140以降のKylix 1以外で使用可能、FireMonkeyVersion(FMX.Types.pasで定義)はDelphi XE2 Update 2以降のFireMonkeyアプリケーションで使用可能です。

各バージョンにおけるRTLVersion、CompilerVersion、FireMonkeyVersionの値は以下のようになっています。

Kylix 1
RTLVersion=14.00
(未定義)
Delphi 6 (Gold)
RTLVersion=14.10
CompilerVersion=14.01
Delphi 6 (Update Pack 1)
RTLVersion=14.11
CompilerVersion=14.01
Delphi 6 (Update Pack 2)
RTLVersion=14.20
CompilerVersion=14.01
C++Builder 6
RTLVersion=14.20
CompilerVersion=14.01
Kylix 2
RTLVersion=14.20
CompilerVersion=14.10
Kylix 3
RTLVersion=14.50
CompilerVersion=14.50
Delphi 7
RTLVersion=15.00
CompilerVersion=15.00
Delphi 8 for .NET
RTLVersion=16.00
CompilerVersion=16.00
Delphi 2005
RTLVersion=17.00
CompilerVersion=17.00
Delphi 2006
RTLVersion=18.00
CompilerVersion=18.00
Delphi 2007
RTLVersion=18.00
CompilerVersion=18.50
Delphi 2007 for .NET
RTLVersion=19.00
CompilerVersion=19.00
Delphi/C++Builder 2009
RTLVersion=20.00
CompilerVersion=20.00
Delphi/C++Builder 2010
RTLVersion=21.00
CompilerVersion=21.00
Delphi/C++Builder XE
RTLVersion=22.00
CompilerVersion=22.00
Delphi/C++Builder XE2
RTLVersion=23.00
CompilerVersion=23.00
FireMonkeyVersion=16.1(Update 2), 16.2(Update 3), 16.3(Update 4)
Delphi/C++Builder XE3
RTLVersion=24.00
CompilerVersion=24.00
FireMonkeyVersion=17.0
Delphi/C++Builder XE4
RTLVersion=25.00
CompilerVersion=25.00
FireMonkeyVersion=18.0
Delphi/C++Builder XE5
RTLVersion=26.00
CompilerVersion=26.00
FireMonkeyVersion=19.0
Delphi/C++Builder XE6
RTLVersion=27.00
CompilerVersion=27.00
FireMonkeyVersion=20.0
Delphi/C++Builder XE7
RTLVersion=28.00
CompilerVersion=28.00
FireMonkeyVersion=21.0
Delphi/C++Builder XE8
RTLVersion=29.00
CompilerVersion=29.00
FireMonkeyVersion=22.0
Delphi/C++Builder 10 Seattle
RTLVersion=30.00 *
CompilerVersion=30.00
FireMonkeyVersion=23.0
Delphi/C++Builder 10.1 Berlin
RTLVersion=31.00 *
CompilerVersion=31.00
FireMonkeyVersion=240 **
Delphi/C++Builder 10.2 Tokyo
RTLVersion=32.00 *
CompilerVersion=32.00
FireMonkeyVersion=250 **
Delphi/C++Builder 10.3 Rio
RTLVersion=33.00 *
CompilerVersion=33.00
FireMonkeyVersion=260 **
Delphi/C++Builder 10.4 Sydney
RTLVersion=34.00 *
CompilerVersion=34.00
FireMonkeyVersion=270 **
Delphi/C++Builder 11 Alexandria
RTLVersion=35.00 *
CompilerVersion=35.00
FireMonkeyVersion=270 ** ***
Delphi/C++Builder 12 Athens
RTLVersion=36.00 *
CompilerVersion=36.00
FireMonkeyVersion=290 **
Delphi/C++Builder 13 Florence
RTLVersion=37.00 *
CompilerVersion=37.00
FireMonkeyVersion=290 ****
  • [*] C++Builder 10 Seattle以降のClangベースの新しいC++コンパイラ(#if defined(__clang__))ではRTLVersionではなくRTLVersionCを使用する必要がある→Clang 拡張 C++ コンパイラと旧世代の C++ コンパイラの違いを参照。
  • [**] Delphi/C++Builder 10.1 Berlin以降ではFireMonkeyVersion(FMX.Typesユニット)の定義がComp型からInteger型となり、値も240(0xF0)のように10倍になっているため、注意が必要です。
  • [***] Delphi/C++Builder 11 AlexandriaでFireMonkeyVersionが10.4 Sydneyと同じ270と定義されています(不具合と思われます)。
  • [****] Delphi/C++Builder 13 FlorenceでFireMonkeyVersionが12 Athensと同じ290と定義されています(不具合と思われます)。

注意しなければならないのは、RTLVersion(C)、CompilerVersion、FireMonkeyVersion(10 Seattleおよびそれ以前)のいずれも実数型の値なので、小数点以下を含むもの(Delphi/C++Builder 6の14.xあたり)は丸めによる誤差を考慮して評価する必要がある、という点です。

実際の使い道としては
  • Kylixのバージョン判定(いまさら)
  • ジェネリクス、無名関数といった新機能のサポート状況の判定
くらいでしょうか(UpdateやHotfixの適用状況がわかるように、もう少し真面目に値を変えてほしいところです)。

StringがAnsiStringかUnicodeStringかは標準条件シンボルUNICODEを使用して
{$IFDEF UNICODE}
// StringはUnicodeString
{$ELSE}
// StringはAnsiString
{$ENDIF}

で判定できますが、ジェネリクス/無名関数が使用できるかどうかは
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion >= 20.0}
// ジェネリクス/無名関数使用可能(Delphi 2009以降)
{$ELSE}
// ジェネリクス/無名関数使用不可(Delphi 6-2007)
{$ENDIF}
{$ELSE}
// ジェネリクス/無名関数使用不可(Delphi 5以前)
{$ENDIF}

このように判定することができます。

またFireMonkeyVersionはVER230でもRTM/Update 1では定義されていないため、
{$IF Declared(FireMonkeyVersion) and (FireMonkeyVersion > 16.0)}
...
{$IFEND}

のように定義済かどうかの確認も必要です。

元ねたはDelphi Tips - 0086あたりとDelphi XE - Q&A (Internet Archive)。標準条件シンボルと同様に、有効な情報が(ヘルプを含め)あまりないのは改善をお願いしたいところです。

2011/09/02追記: Delphi/C++Builder XE2関係を追加。
2012/09/02追記: Delphi/C++Builder XE3関係およびFireMonkeyVersionに関する記述を追加。
2013/09/12追記: Delphi/C++Builder XE4/XE5関係を追加。
2014/04/15追記: Delphi/C++Builder XE6関係を追加。
2014/09/02追記: Delphi/C++Builder XE7関係を追加。
2015/04/07追記: Delphi/C++Builder XE8関係を追加。
2015/09/01追記: Delphi/C++Builder 10 Seattle関係を追加。
2016/04/20追記: Delphi/C++Builder 10.1 Berlin関係を追加。
2017/03/23追記: Delphi/C++Builder 10.2 Tokyo関係を追加。
2018/11/26追記: Delphi/C++Builder 10.3 Rio関係を追加。
2020/06/01追記: Delphi/C++Builder 10.4 Sydney関係を追加。
2021/09/10追記: Delphi/C++Builder 11 Alexandria関係を追加。
2023/11/09追記: Delphi/C++Builder 12 Athens関係を追加。
2026/03/22追記: Delphi/C++Builder 13 Florence関係を追加。

2010年12月8日

FreeAdhocUDF version adhoc 20101206リリース

第18回エンバカデロ・デベロッパーキャンプのT6セッションの木村さんのライトニングトークの"UPPERはあってもLOWERがない"ネタで触れられていたFreeadhocUDFの最新版(20101206)がリリースされていました。

元ねたはFirebird News » New version of FreeAdhocUDF released

2010年12月7日

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

会場(池袋のシアターグリーン)へのアクセスについてはTeam Japan » 第18回 エンバカデロ・デベロッパーキャンプ会場へのアクセスを参照のこと。普通は池袋駅からのルートがわかりやすくてよいのでは。
また今回はUStreamとLiveMeeting(要登録)でライブ中継が行われます。

うーん、微妙に狭いのとやはり机がほしいかな…姿勢が不自然で丸一日だと結構疲れます(机がなく常に後傾なのと見下ろしになることの相乗効果で)。電源はありがたいですね(使っている人は他にはあまりいませんでしたが)。

G1:「エンバカデロ・プロダクトアドレス」
  • InterBase XEの日本語版はまもなくリリース予定。
  • Delphiのx64コンパイラのプレビューリリースはクローズドベータなので、参加希望者はエンバカデロにコンタクトしてくださいとのこと。
  • PulsarのIDEはWindows x86のまま(x64ではWOW64で動作)。

T2:「アプリケーション開発者のためのDBべからず集からパフォーマンスチューニングまで」
  • BDEはもうやめましょう。4GB超のドライブに対応していないし。
  • 開発環境は仮想化すると便利。検証とか。
  • Pro SKUでDBX/DataSnapはローカル接続のみ(ライセンス的に)。Ent SKUでDBXにするか、Pro SKUならIBXで。
  • マルチティア化するのにはDataSnapが便利(Ent SKUで)。
  • T*Tableコンポーネントは使わない。T*Queryで結果セットを極力絞り込みましょう(T*Tableは基本的に全件転送します)。
  • データベースアクセスはUIとは分離してDatamoduleに置きましょう。
  • データベーステーブル上のデータをなんでも表示するとパフォーマンスに影響するので、必要なものだけにしましょう。Lookup系の動作にも気をつけて。
  • データベースエンジンそのものの評価も忘れずに。AccessやParadoxはやめましょう、とりあえず。
  • 主キー/外部キー、インデックスは正しく使いましょう。PLANの確認も忘れずに。
  • 追加、変更、削除を繰り返すデータベースはメンテナンスを。バージョンニングを採用しているInterBase/Firebird/PostgreSQLは削除レコードの影響でインデクシングが遅くなる。
  • JOINするときは十分に注意を払って。結果セットのサイズとかOUTER JOINによるNULL値とか。
  • 移行は計画的に。お金、期間は十分ですか?

T3:「つながる!!PHP拡張の極意 - PHPからWebサービスにアクセス」
  • DatasnapではなくREST/JSON/SOAPなどの業界標準でも簡単接続できる。
  • Delphi/C++BuilderでSOAPサーバをコンソール/GUIアプリケーションとして簡単に作成できる(ウィザードあり)。

T4:「開発者の疑問に答える!徹底Q&A」
  • 初学者向の書籍や資料があまりない。古本で探せば安く済ますことができる(内容はある程度そのまま適用可能なので)。→こちらに関連アーティクルを用意しました。
  • 新しいバージョンへのマイグレーションはDEKOさんとことか過去のデベロッパーキャンプのセッションなどを参考に。
  • 新しいDelphi/C++Builderに移行するときは一旦2007にマイグレーションして文字コード(Unicode関連)以外の修正点(データベース関係とかVisualStyleとか)をクリアしてから2009/2010/XEにステップアップしましょう(問題点を局限するために)。その際はプロジェクトだけは作成し直しをお勧め(ライブラリパスが古いものを引きずるとかApplication.MainFormOnTaskBar := True;の行が入らないとか構造体アライメントが1(デフォルトは8)になってしまうとか原因不明な問題を避けるため)。
  • マイグレーションしたら警告がががが、は頑張って消しましょう。大多数はANSI/Unicodeの暗黙的変換についてのものだと思われますが、$WARNで抑止するのは最小限の範囲で。
  • いまどきの開発環境はWindows 7(Pro/Ent/Ult)でvmware/VPC/Hyper-Vなどの仮想環境を利用するのが便利(OSのライセンスには気をつけて)。

T5:「Delphi言語『再』入門 - ビギナーからエキスパートまで!意外と知らない言語機能や落とし穴 」
T6:「共有!みんなの開発事例、開発経験、テクニック 」
懇親会
  • この時期に外は寒い。ストーブで暖まる。
  • ToolCloudそのもの(ライセンス管理システム)も今後OEM的に出していきたい、というかその準備に1年かかった。
  • NTTデータさんは(ライセンス的にもお金的にも)すごい。

無事(?)終了。関係者、参加者の皆さん、おつかれさまでした。

2010/12/09追記: 米澤さんがTwitterのまとめを作ってくれました。

Togetter - 「第18回デベロッパーキャンプ」

2010/12/13追記: なんとなく記憶にあるもの、Togetterられているものについて内容を追記しました。

2010/12/15追記: セッション資料がダウンロードできるようになっています。これに基づいて追記。ただT4とT6の分はありません。UStreamのリプレイがほしいですね…。

第18回 エンバカデロ・デベロッパーキャンプ - セッション資料ダウンロード

2010/12/16追記: T4/T6のリプレイが公開されています(セッション資料ダウンロードページからリンクされています)。

第18回 エンバカデロ・デベロッパーキャンプ「開発者の疑問に答える!徹底Q&A」 - channel-e.embarcadero.com
第18回 エンバカデロ・デベロッパーキャンプ ライトニングトーク 「共有!みんなの開発事例、開発経験、テクニック 」 - channel-e.embarcadero.com

2012/05/14追記: T6のリプレイがYouTubeにアップロードされています。

2010年12月6日

Delphiで自己展開アーカイブを作成

RRUZ(Rodrigo Ruz)さんによるDelphiでSFX(Self Extracting Archives)を作成する方法。興味深い。とりあえずメモ。

Create a SFX File with delphi (Self Extracting Archives) « The Road to Delphi – a Blog About Delphi Programming (mostly)

このアーティクルのコードでは実行ファイルにリソースを格納するのにWin32APIのBeginUpdateResource (ja)、UpdateResource (ja)、EndUpdateResource (ja)を、実行ファイルで格納されているリソースを検索するのにFindResource (ja)を使用しています。

2010年12月3日

CanTools Wizards

Delphiのマスタリング/ハンドブックシリーズでおなじみのMarco CantuさんがCanTools Wizardsというウィザードセットを公開しています。

CanToolsW on marcocantu.com

上記のページからDelphi 6(CanToolsW6.bpl)/Delphi 7(CanToolsW7.bpl)/Delphi 7 + Update 1(CanToolsW71.bpl)/Delphi 2007(cantools_2007.bpl)/Delphi 2009(cantools_2009.bpl)/Delphi 2010(cantools_2010.bpl)/Delphi XE(cantools_xe.bpl)のパッケージライブラリ(bpl)がダウンロードできます。

CanTools Wizardsには以下の機能が含まれています。
  • List Wizard
  • OOP Form Wizard
  • Object Inspector Font
  • Rebuild Wizard
  • Clip History Viewer
  • VCL Hierarchy
  • DB Form Wizard
  • No ".net safe" warnings
  • Bookmark list
  • Palette Info
  • Add to project manager for .ini
  • ShowDebug Inspector
  • Publish Project
…試してみましたが微妙な感じですね。

元ねたはMarco CantuさんのCantools Wizards for Delphi XE

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)