一般的なアプリケーション互換性について

要約

このホワイト ペーパーでは、Windows XP ベータ 2 (以後「Windows XP」) でアプリケーションをインストールおよび実行する際に発生する、一般的な互換性の問題について説明します。また、より信頼性の高いプラットフォームに進化させるためにWindows プラットフォームに加えられた新機能についても解説します。これら互換性の問題や新機能は、Windows XP 用のアプリケーションに影響を及ぼす可能性があるため、Windows XP 向けの新しいアプリケーションを設計する際には、これらの点について考慮してください。

トピック

はじめに
Windows XP の新機能
セットアップとインストール
場所の変更とハードコード パス
ファイルとフォルダ
セキュリティ
ネットワーク
メモリ管理
シェル
ドライバ
DirectX
GDI
入力デバイス
その他のハードウェア
その他
参考資料

はじめに

このホワイトペーパーでは、Windows XP Professional および Windows XP Home でアプリケーションをインストールおよび実行する際に発生する互換性の問題について説明します。Windows XP には、より便利で信頼性の高いプラットフォームに進化するための変更が加えられています。これらの変更によってアプリケーションの実行に影響が及ぼされる可能性があるため、Windows XP 向けの新しいアプリケーションを設計する際には考慮する必要があります。このホワイトペーパーは、新たな互換性問題の発見に応じて更新されます。

Windows XP の新機能

Windows XP には数々の新機能が導入されていますが、この文書では、アプリケーションの互換性に関連するいくつかの機能についてのみ説明します。新機能の完全なリストは、https://www.microsoft.com/japan/windowsxp/default.mspx にあります。

Windows XP の共有環境

Windows XP はパーソナルシステムです。同時に複数のユーザーが単一のコンピュータを使用することができます。XP では、複数のアカウントを使用でき、ユーザの簡易切り替えやリモートデスクトップなどの機能が提供されます。これらの機能と、それによって生じる可能性のある問題およびその解決方法を以下に説明します。

複数のアカウント

Windows XP では、各ユーザーが個別の Windows XP アカウントを持ちます。アカウントはセットアップ時に作成されますが、後でコントロールパネルを使って作成することもできます。アカウントは Windows 2000 プロファイルを基盤としています。このインフラストラクチャは、ユーザーデータ、ユーザー設定、およびコンピュータ設定の状態分離をサポートしています。

ユーザの簡易切り替え

Windows XP の新機能の 1 つは、ユーザの簡易切り替えです。この機能により、コンピュータの現在のユーザーがログオフしなくても、別のユーザーがログオンできるようになりました。1 つのコンピュータに同時に複数のユーザーがログオンでき、ユーザーはアカウントを切り替えることができます。各ユーザーのネットワーク接続、個人データ、および実行中のタスクは、ユーザーが再度ログオンするまで保持されます。

リモート デスクトップ

Windows XP に備えられたリモートデスクトップ機能を使って、ユーザーは、ほかのコンピュータからデータやアプリケーションにアクセスすることができます。ユーザの簡易切り替えもリモートデスクトップも、ターミナルサービス技術を使用しています。この技術は、ほとんどの Microsoft Win32 アプリケーションの場合、アプリケーションを修正しなくても協調して動作することができます。

ターミナルサーバーの詳細については、https://msdn.microsoft.com/library/en-us/dnwts/html/tsappdev.asp (英語) を参照して下さい。

共有環境で起こり得る問題

Windows 2000 プロファイルインフラストラクチャを正しく使用するアプリケーションでは、共有環境で問題が発生することはありません。デザインの優れたアプリケーションの場合、ユーザーが作成したデータはデフォルトで My Documents に格納されるよう設計されており、アプリケーションデータを正しく分類および格納できるため、"アクセスが拒否されました" というメッセージをうまく避けることができます。

マップされたファイルは、ユーザープロファイルの下に作成してください。SHGetFolderLocation() または SHGetFolderPath() API を使用して、ファイルの適切な格納場所を決定してください。

データの分類と格納の詳細については、https://www.microsoft.com/japan/winlogo/software/downloads.mspx を参照してください。

通常は、セッションの切り替えについてアプリケーションに通知する必要はありません。しかし、アプリケーションのデスクトップが現在有効であるかまたは共有リソース (シリアルポートなど) を使用しているかをアプリケーション側で認知する必要がある場合は、セッションの切り替えを通知するよう登録することができます。

通知を登録するには、以下の API を使用します。

BOOL WINAPI 
WTSRegisterConsoleNotification( 
HWND hWnd,         // Window handle 
DWORD dwFlags      // Flags 
);

セッションが切り替わると、オペレーティングシステムが WM_WTSSESSION_CHANGE メッセージを発行します。登録された HWND はこのメッセージを受け取ります。

dwFlagsには、以下のフラグを使用できます。

NOTIFY_FOR_THIS_SESSION - ウィンドウは、そのウィンドウが属するセッションに影響を及ぼすセッション切り替えイベントについてのみ通知されます。

NOTIFY_FOR_ALL_SESSIONS - ウィンドウは、すべてのセッション切り替えイベントについて通知されます。

セッションで行われているアクションは wParamコードにあり、以下のフラグのいずれかが含まれます。

WTS_CONSOLE_CONNECT

WTS_CONSOLE_DISCONNECT

WTS_REMOTE_CONNECT

WTS_REMOTE_DISCONNECT

lParamには、影響が及ぼされるセッションの sessionId が含まれます。

プロセスがこれらの通知を必要としなくなった場合、または終了する場合は、以下の API を使用して、通知の登録を解除する必要があります。

BOOL WINAPI 
WTSUnRegisterConsoleNotification( 
HWND hWnd      // window handle. 
);

これら 2 つの API に渡される HWND 値は参照カウントされるため、それぞれ同じ回数呼び出す必要があります。

サーバーがクライアントプロセスから要求を受け取ってクライアントトークンを取得しなければならない、などの特定の状況では、システムサービスの相互動作について検討する必要があります。

Windows XP のテーマ

アプリケーションは、動作に支障なくWindows XP のテーマをサポートしなければなりません。テーマ対応には、COMCTL32.DLLバージョン 6のユーザーエクスペリエンスコントロールを使用します。COMCTL32.DLLバージョン 6ではuxtheme.dll を用いて画面のレンダリングを行いますが、このときにuxtheme.dllが設定されたテーマに応じてレンダリングの仕方を変えることでテーマ対応するわけです。

新しいバージョンの COMCTL32.DLL を使用したときに(新バージョンに対応していない)アプリケーションが動作しなくらないように、この DLL は、バージョン 5 と一緒に共有アセンブリとしてインストールされます。どちらの DLL も Windows XP に含まれており、System32 ディレクトリにインストールされます。アプリケーション側では、COMCTL32.DLL バージョン 6 が必要であることを示すマニフェストファイルを提供せねばなりません。そうしないと、COMCTL32.DLL バージョン 5 が使用されます。この仕掛けをサイドバイサイドコンポーネントといい、詳しくは後述します。

新しいユーザーエクスペリエンス (User Experience)、別名テーママネージャ (Theme Manager) API を使用するには、レンダリングおよびメトリックスのため、カスタムコントロールを修正する必要があります。コントロールは、アプリケーションでなく、uxtheme.dll を使用して作成しなければなりません。

カスタムウィンドウクラスまたはコントロールを作成する場合や、標準的なウィンドウまたはコントロールの通常の動作を変更する場合は、テーマがサポートされている必要があります。

XP以外のの Windows オペレーティングシステムでも動作するアプリケーションでは、COMCTL32. DLLバージョン 6 の使用を前提とすべきでなく、また COMCTL32. DLLバージョン 6 でのみ利用可能な機能を使用すべきではありません。引数の検証が向上しており、アプリケーションは、COMCTL32.DLL の以前の動作に依存すべきではありません。

Advanced Computer Power Interface (ACPI)

アプリケーションは、電源オン/オフの状況を処理できるように設計する必要があります。システムのユーザーは、コンピュータを低電力状態で動作させる場合があります。これらは、スタンバイ、ハイバネーション、スリープなどと呼ばれます。デザインの優れたアプリケーションは、データを保存し、ファイルを閉じ、サウンドやゲームのプレイを一旦停止し、アプリケーションが変更を加えたドライバを初期状態に復元できなければなりません。

スリープとウェイクを正しく処理できるアプリケーションとは、アプリケーションがビジー状態であることをシステムに通知し、スリープ要求に応答し、スリープ通知を処理し、ノーマルスリープおよびクリティカルスリープからのウェイク通知を処理できるアプリケーションです。

PC がアイドル状態でも引き続き実行されなければならないアプリケーションの場合は、SetThreadExecutionState() API を ES_SYSTEM_REQUIRED フラグ付きで呼び出す必要があります。詳細については Microsoft プラットフォーム SDK を参照してください。

システムは、実行中のアプリケーションに対して、WM_POWERBROADCASTメッセージに wParamPBT_APMQUERYSUSPEND を付けて送信することで、電源を停止しようとしていることを通知します。

すべてのアプリケーションがスリープ要求を受諾すると、システムは WM_POWERBROADCASTメッセージに wParamPBT_APMSUSPEND を付けて送信します。このときアプリケーションは、ハードウェアがシステムの電源を停止する前に、すべてのデータを保存し、開いているファイルを閉じ、サウンドとゲームのプレイを一旦停止し、ドライバを初期状態に戻す必要があります。

オペレーティングシステムがウェイクすると、WM_POWERBROADCASTメッセージに wParamPBT_APMRESUMESUSPEND を付けて送信します。システムがスリープ状態になったときに開いていたアプリケーションは、このメッセージを受けて開きます。このときアプリケーションは、すべてのコンテキストを、コンピュータがスリープになる前の状態に戻さなければなりません。

クリティカル スリープは、非常事態への対応としてシステムが即座にシャットダウンする場合に発生します。このような電源停止の発生源は、バッテリーが少なくなったハードウェアや、ユーザーなどです。アプリケーションがクリティカルスリープ状態からウェイクする場合、データが保存されていないのは仕方ありませんが、少なくとも安定した状態でウェイクする必要があります。

詳細については、https://www.microsoft.com/japan/windowsserver2003/partners/isvs/cfw.mspx を参照してください。

セットアップとインストール

バージョン確認

Windows XP でのアプリケーション互換性問題で最も大きなものは、バージョンコードです。当社がテストを行ったアプリケーションの多くは、**GetVersionEx()**を呼び出し、特定のバージョンが返された場合のみ実行されました。Windows XP は、新しいメジャーバージョン番号 (5) を返すため、これらのアプリケーションでは取り扱うことができません。

新しいアプリケーションは、現在およびそれ以降のいずれのバージョンが返されたときでも実行できるよう設計されなければなりません。

正しいバージョン コードを以下に示します。

BOOL bIsWindowsVersionOK(   DWORD dwWin9xMajor, DWORD dwWin9xMinor, 
DWORD dwWinNTMajor, DWORD dwWinNTMinor, WORD wWinNTSPMajor ) 
{ 
OSVERSIONINFO           osvi; 
// Initialize the OSVERSIONINFO structure. 
ZeroMemory( &osvi, sizeof( osvi ) ); 
osvi.dwOSVersionInfoSize = sizeof( osvi ); 
GetVersionEx( &osvi );  // Assume this function succeeds. 
// Split code paths for NT and Win9x 
if( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) 
{ 
// Check the major version. 
if( osvi.dwMajorVersion > dwWin9xMajor ) 
return TRUE; 
else if( osvi.dwMajorVersion == dwWin9xMajor ) 
{ 
// Check the minor version. 
if( osvi.dwMinorVersion >= dwWin9xMinor ) 
return TRUE; 
} 
} 
else if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) 
{ 
// Check the major version. 
if( osvi.dwMajorVersion > dwWinNTMajor ) 
return TRUE; 
else if( osvi.dwMajorVersion == dwWinNTMajor ) 
{ 
// Check the minor version. 
if( osvi.dwMinorVersion > dwWinNTMinor ) 
return TRUE; 
else if( osvi.dwMinorVersion == dwWinNTMinor ) 
{ 
// Check the service pack. 
DWORD dwServicePack = 0; 
if( osvi.szCSDVersion ) 
{ 
_stscanf(   osvi.szCSDVersion, 
_T("Service Pack %d"), 
&dwServicePack ); 
} 
return ( dwServicePack >= wWinNTSPMajor ); 
} 
} 
} 
return FALSE; 
}