Posts filed under 'OS のコンフィグレーション'

OS の起動時間短縮(2/2)~ビルトインのデバイスドライバを遅延ロード

■はじめに
昨年9月のエントリで、「今回と次回は、WEC の起動時間を短縮する方策を、二つ紹介します。」と述べて一つめの方策を書いた後、一年近く時間が空いてしまいましたが、二つめの方策を書きます。

前回紹介した方策では、RAM レジストリを永続化した構成において、RAM レジストリの初期化時間を短縮する、というものでした。今回紹介するのは、ビルトインのデバイスドライバのうち、起動直後ないし起動中に動作していることが必須ではないものを、OS 起動中にはロードされないようにする(必要になった時点で後からロードする、つまり遅延ロードする)、という方策です。

この方策により、WEC が起動して初期画面(標準シェルを組み込んだ場合は、デスクトップ画面)が表示されるまでの時間を若干短縮することが可能です。短縮される時間は、遅延ロードするドライバ群の初期化処理に要する時間の合計です。従って、初期化処理に要する時間が長いドライバがあれば、遅延ロードさせる対象の候補となります。

注意:WEC 2013 には、標準シェル(explorer.exe)は付属しません。代わりに、最少機能のミニシェルを使う必要があります。

もちろん、遅延ロードさせるドライバは、WEC の起動直後ないし起動中に動作していなくても構わないものに限られます。たとえば、ディスプレイドライバは、WEC のウィンドウシステムである GWES が必要としますので、遅延ロードさせるわけにはいきません。また、LCD ディスプレイを接続した端末であれば、LCD バックライトのドライバも、WEC の起動中に動作を開始しなければいけません(そうでないと、LCD の画面が真っ暗で、初期画面が表示されませんからね)。逆に、USB や SD のホストコントローラのドライバは、遅延ロード対象の候補になるでしょう。

USB や SD の、対向デバイスごとのドライバ、つまりクラスドライバは、対向デバイスが接続された時点で初めてロードされる Plug & Play ドライバですが、それらをロードするホストドライバを遅延ロードさせても、問題ないケースは多いでしょう。他の候補としては、バッテリードライバも挙げられます。これら、ビルトインのデバイスドライバ(※USB や SD のクラスドライバのような Plug & Play ドライバではなく、OS の起動時にロードされるドライバ)のうち、遅延ロード可能なものを洗い出して遅延ロードさせることにより、WEC が起動して初期画面が表示されるまでの時間を、数10[ms]~数100[ms]、場合によっては数秒程度短縮できるかも知れません。

ビルトインのデバイスドライバを遅延ロードさせることによる、WEC の初期画面が表示されるまでの時間の短縮は、OS のコンフィグレーションや、遅延ロードさせるドライバが初期化時に行う処理内容、及びドライバが制御するハードウェアに依存します。つまり、どれくらいの時間が短縮されるかは、ケースバイケースです。そのため、ここでは具体値には触れず、上記の定性的な説明に留めます。

なお、今回の説明に通じる内容は、WEC 2013 のディベロッパーガイドでも触れられています。興味のある方は、MSDN にある、次のページもご覧になってみて下さい。

 Optimize Driver Load Time (Compact 2013)
 https://msdn.microsoft.com/en-us/library/dn194541.aspx

■ビルトインのデバイスドライバ
さて、遅延ロードの手順について説明する前に、ビルトインのデバイスドライバとは何を指すのかを、明らかにしておきましょう。上で、ビルトインのデバイスドライバを「OS の起動時にロードされるドライバ」と書きましたが、OS の起動時にロードされるかどうかは、レジストリ設定で決まります。具体的には、ドライバのレジストリキーが
 [HKEY_LOCAL_MACHINE\Drivers\BuiltIn]
の下に設定されていると、OS の起動時にロードされるのです。このことは、WEC 2013 のディベロッパーガイドの次のページで説明されています:

 Device Manager (Compact 2013)
 https://msdn.microsoft.com/en-us/library/jj659831.aspx

上のページの中ほどにある、”Registry Settings” という項をご覧ください。ここに、デバイスドライバのレジストリ項目の説明もあります。

■デバイスドライバのロード防止設定
上述したように、レジストリキーを [HKEY_LOCAL_MACHINE\Drivers\BuiltIn] の下に配置したデバイスドライバは、OS の起動時に自動的にロードされます。この設定を変え、”BuiltIn” ではなく、他のキーの下にレジストリキーを配置すると、OS の起動時にはロードされません。そのような場合は、ActivateDevice[Ex]() を使って明示的にロードしない限り、ロードされることはありません。

たとえば、バッテリドライバのレジストリキーは
 [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Battery]
ですが、これを変更し、
 [HKEY_LOCAL_MACHINE\Drivers\AddOn\Battery]
にすると、起動時にロードされなくなります。つまり、ビルトインのデバイスドライバを OS の起動時に自動ロードされないようにするいは、そのレジストリキーを変更し、[HKEY_LOCAL_MACHINE\Drivers\BuiltIn] の下ではない階層に移せばよいのです。

ただし、バッテリドライバのように、WEC 標準のデバイスドライバのレジストリキーを変更してしまうと、不都合を生む場合があります。そのドライバに対するレジストリ設定が、複数の .reg ファイルに分割して記述されている場合です。実際、端末が違っても変わらない共通的な設定は WEC 付属の共通設定を記述した .reg ファイル(%_WINCEROOT%/public/common/oak/files/common.reg)に記述し、端末ごとに変わる設定を、OS Design プロジェクトの .reg ファイルや、あるいは、BSP の .reg ファイルに記述する、ということは珍しくありません。その際、WEC 標準で決まっているレジストリキーを変更してしまうと、不整合が起きてしまう危険があります(※当該ドライバに対する、全ての .reg ファイルに記載された設定を変更できず、一部は BuiltIn 配下のままになってしまう、というケースが考えられます)。その危険を回避するには、レジストリキーは標準設定のまま(※つまり、ビルトインのデバイスドライバのレジストリキーは、 BuiltIn の下に配置する設定のまま)で、自動ロードされるかどうかだけを変更することが必要です。そして、そのためのレジストリ項目があるのです。

デバイスドライバの自動ロードは、Flags というレジストリ項目の設定値で防止できます。上で紹介したページの、”Registry Settings” という項にある表を見て下さい。表の4行目にある、DEVFLAGS_NOLOAD というフラグが、そうです。デバイスドライバのレジストリ設定で、Flags の値が DEVFLAGS_NOLOAD (0×00000004) を含むと、そのドライバはロードされません。つまり、BuiltIn の下にレジストリキーが配置されていても、OS の起動時に自動ロードされません。ただし、OS の起動時に限らず、ActivateDevice[Ex]() を使ってもロードできません。

■ビルトインのデバイスドライバの遅延ロード手順
デバイスドライバのレジストリ設定において、Flags に DEVFLAGS_NOLOAD (0×00000004) を含む値を設定することにより、ビルトインのデバイスドライバであっても、OS の起動時に自動的にロードされるのを防ぐことができるのは分かりました。しかし、そのままでは、ActivateDevice[Ex]() を使ってもロードできず、ロードできないままになってしまいます。では、どうすればよいのでしょうか?

解決方法は、簡単です。ドライバをロードする時に、レジストリ設定を一時的に変更すればよいのです。つまり、ActivateDevice[Ex]() を呼び出す前に、レジストリの Flags の値から DEVFLAGS_NOLOAD フラグを取り除き、ActivateDevice[Ex]() の呼び出しが終わったら、再度 DEVFLAGS_NOLOAD フラグを加えればよいのです。

つまり、ビルトインのデバイスドライバを遅延ロードするために必要な手順は、次の通りです:

1.) OS Design のレジストリ設定ファイル(OSDesign.reg)において、遅延ロード対象のデバイスドライバの Flags の値を、DEVFLAGS_NOLOAD (0×00000004) を含むものに設定するよう記述を追加する(※common.reg などで Flags が設定されていれば、OSDesign.reg で上書き設定する)。

2.) 必要になった時点で、次の処理を実行する:
 2-1.) RegSetValueEx() を使って、そのドライバのレジストリの Flags の値を変更する(DEVFLAGS_NOLOAD を含まない値に変更する)。
 2-2.) そのドライバのレジストリキーを指定して ActivateDevice[Ex]() を呼び出す。
 2-3.) 再び RegSetValueEx() を使って、Flags の値を変更前のものに戻す。

上の手順のうち、(2) は、WEC の起動後に自動実行されるようにするのが簡単でしょう。遅延ロード対象のデバイスドライバ群に対して (2) を実行するアプリケーションを作り、そのアプリケーションを、/Windows/Startup/ ディレクトリに配置すれば、WEC が起動して、標準シェルのデスクトップ画面が表示された直後に、遅延ロード対象のデバイスドライバ群がロードされて動作開始します。この時、画面表示を見ているユーザにとっては、それらのデバイスドライバが起動時に自動ロードされる場合よりも起動時間が短縮されたように見えるでしょう。

■おまけ
/Windows/Startup/ ディレクトリに配置されたアプリケーションを自動起動する処理は、標準シェルのソースコード(※WEC 2013 には付属しません)でいうと、
 %_WINCEROOT%/public/shell/oak/hpc/explorer/main/explorer.cpp
で実装されている ProcessStartupFolder() で行われます。この関数が、SHGetSpecialFolderPath() で Startup ディレクトリのパス(つまり、/Windows/Startup/)を取得して、その中に入っている実行ファイル全てに対して順次 ShellExecuteEx() を呼び出す、という仕組みです。ProcessStartupFolder() は、DoStartupTasks() を介して、標準シェル(explorer.exe)のメインルーチンである WinMain() から呼び出されます。

explorer.exe の WinMain() では、標準シェルの初期化動作を行った後、CDesktopWnd クラスのインスタンスを生成して Create() を呼び出し、デスクトップ画面を表示します。さらに、CreateTaskBar() を実行するスレッドを生成・始動して、タスクバーを表示します。それらが済んだ後で、DoStartupTasks() を呼び出すようになっています。従って、遅延ロード対象のデバイスドライバをロードする処理は、/Windows/Startup/ に配置したアプリケーションで行うようにしておけば、標準シェルの初期画面が表示された後で遅延ロードが実行されるので、遅延ロードのぶん、初期画面が表示されるまでの時間が短縮される、というわけです。

標準シェルを使わず、カスタムシェルを使う場合(WEC 2013 のミニシェルを使う場合など)も、同じような方策で対応できるでしょう。WEC 7 をお持ちで、興味のある方は、explorer.cpp の内容を眺めてみると、面白いかも知れません。

Add comment 2015/09/16 koga

IE 7 での日本語表示と AC3 フォント圧縮

2012/07/13 に書いたエントリ(「WEC 7 の Meiryo フォント」)で、「Meiryo フォントを OS イメージに組み込む場合は、カタログ項目の “Monotype Imaging AC3 Font Compression” を選択しては、いけません。」と書きました。この Monotype Imaging AC3 Font Compression は、Meiryo フォントを組み込まない場合にも注意が必要なケースのあることが分かりました。それは、IE 7 を組み込む場合です。

Monotype Imaging AC3 Font Compression を組み込んだ OS イメージで IE 7 を動かすと、日本語ページを表示する際に、IE 7 内部で例外送出が繰り返し発生し、表示までに長い時間を要したり、あるいは、日本語テキストが表示されない場合もある、という問題があるのです。この問題は、少なくとも ARMv5 と ARMv7 のプロセッサでは発生することを確認しています。僕自身は確認していませんが、x86 では発生しないようです。

IE 7 で日本語ページを表示する際、Monotype Imaging AC3 Font Compression を組み込んだ OS イメージでは、次のようなログが繰り返し出力されます:


  48706 PID:5d80026 TID:5de002e Exception 'Raised Exception' (0xe06d7363): Thread-Id=05de002e(pth=c04a20c0), Proc-Id=05d80026(pprc=c049c8b8) 'iesample.exe', VM-active=05d80026(pprc=c049c8b8) 'iesample.exe'
  48706 PID:5d80026 TID:5de002e PC=400512c8(coredll.dll+0x000412c8) RA=800956f0(kernel.dll+0x0000e6f0) SP=00148ad0, BVA=00148b0c

IE 7 で日本語ページを表示する際に、繰り返し例外送出が起きて表示に時間を要する、という問題は、以前にも経験していたのですが、その時は、原因が分からず、対策をとっていませんでした。先日、この問題に取り組む必要が生じ、あらためて追ってみたところ、ようやく、AC3 フォント圧縮(Monotype Imaging AC3 Font Compression)との因果関係が分かったのです。この問題に以前遭遇した際に、カーネルデバッガで追ってみた時の記憶では、上記の例外送出は、IE 7 内部で、フォントの表示幅を算出する処理で起きているようです。

以前に調べた時の記憶が正しければ、フォントの表示幅を算出する処理で例外送出が起きていますので、フォントデータへのアクセスで例外送出が起きている可能性があります。このことと、ARM プロセッサでは症状が発生し、x86 プロセッサでは症状が発生しないようだ、ということを考え合わせると、フォントデータへのアクセスで word alignment のとれていないデータ読み出しを行っている箇所があり、そこで例外送出が起きる、ということなのかも知れません。全くの憶測にすぎませんが、AC3 フォント圧縮されたフォントファイル(非圧縮の .ttc ではなく、圧縮版の .ac3)内のデータをアクセスする際に、圧縮によって word alignment のとれていないフィールドがあり、そこに対して整数値の読み出しを行おうとして例外送出が起きている、ということなのかも知れません。

なお、このような症状は、WinCE 6.0 では発生していませんでした。従って、WinCE 6.0 から WEC 7 への変更点の中に、要因があるのではないかと思われます。WinCE 6.0 から WEC 7 への変更点の中に、ARM コンパイラの強化があります。WinCE 6.0 までは、ARMv4 アーキテクチャの命令しか出力できなかったのが、WEC 7 では、ARMv5, ARMv6, ARMv7 をサポートしています(※最新メジャー版の WEC 2013 では、ARM コンパイラが再び変更され、ARMv7 のみのサポートとなったのは、皆さんご存知の通りです)。WEC 7 での ARM コンパイラの強化には、この他に、memcpy() や memset() が Intrinsic Function となった、というものがあります。これは、ARM コンパイラだけではなく、x86, ARM, MIPS 共通です。

memcpy() や memset() が Intrisic Function となった結果、これらの関数に渡す実引数の型次第では、byte 単位ではなく、word 単位でのアクセスが行われるようです。これは、一般的には高速化に役立ちますが、[unsigned ]short や [unsigned ]long、[unsigned ]int のポインタが実引数として渡され、かつ、実際には、そのポインタ値が、word alignment がとれていない場合(つまり、short のポインタ値が 2Byte 単位のアドレス境界に揃っていなかったり、long のポインタ値が 4Byte 単位のアドレス境界に揃っていない場合)、ARM プロセッサでは、例外送出が起きてしまいます。x86 では、例外送出は起きません。このような状況は、たとえば、可変長のヘッダを持つ通信パケットがあり、そのペイロードを構造体にキャストしてアクセスする場合に起こり得ます。もしかすると、IE 7 が AC3 フォント圧縮されたフォントファイル内のデータをアクセスする際に、そのようなことが起きているの *かも* 知れません。

WinCE 6.0 から WEC 7 への変更点には、コンパイラの強化の他に、IE の変更もあり、レンダリングエンジンの強化も行われていますから、コンパイラの違いが要因ではなく、レンダリングエンジンの変更が要因である可能性もあります。IE 7 のレンダリングエンジンのソースコードは開示されていませんので、真相は、Microsoft で調べてもらわなければ分かりません。

ともあれ、少なくとも現時点では、Meiryo フォントに加え、IE 7 とも、Monotype Imaging AC3 Font Compression を共存させてはいけない、ということが言えます。IE 7 と日本語フォントを OS イメージに組み込まれる方は、ご留意下さい。

■おまけ
WEC 7 のコンパイラの Intrinsic Function のうち、CPU アーキテクチャ共通のものについては、リファレンスの次のセクションに記載されています:

 Compiler Intrinsic Functions (Compact 7)
 http://msdn.microsoft.com/en-us/library/ee480143(v=winembedded.70).aspx

memcpy() や memset() は、次のページに載っています:

 Intrinsic Forms of CRT Functions (Compact 7)
 http://msdn.microsoft.com/en-us/library/ee479418(v=winembedded.70).aspx

Add comment 2014/08/25 koga

WEC 7 の WMP サンプルアプリケーション

■Microsoft Silverlight for Windows Embedded の修正にまつわる問題と対処
WEC 7 で、付属のメディアプレイヤーアプリケーション(Music Player, Photo Viewer, Video Player)を組み込んだ OS イメージをビルドしていらっしゃる方は、月例アップデータを適用する場合、注意する必要があります。今年リリースされた月例アップデータの中に、適用すると、これらメディアプレイヤーアプリケーションが動作しなくなる症状を引き起こすものがあるからです。

具体的に言うと、Microsoft Silverlight for Windows Embedded に対する修正が多く投入された Monthly Update May 2014 において、その問題を確認しています。これは、不具合というよりは、月例アップデータのパッケージング上の問題だと思います。Monthly Update May 2014 には、以下の8件の修正が投入されているのですが、この中に、問題の要因があるようです:

 Windows Embedded Compact 7 Monthly Update May 2014
 http://www.microsoft.com/en-us/download/details.aspx?id=43368

  FIX: Cannot display all UI elements correctly in a SWE application for Windows Embedded Compact 7
  
FIX: Storyboard doesn’t run if it references a custom DependencyProperty in Windows Embedded Compact 7
  FIX: Poor performance when you use XAMLRuntime OpenGL in Windows Embedded Compact 7
  FIX: Cannot receive the GID_END gesture message in an SWE application on a Windows Embedded Compact 7-based device
  FIX: An update is available about adding the GetTemplateChild method to the SWE IXRControl class in Windows Embedded Compact 7
  FIX: Setting DataContext to null resets two-way binding in the SWE application in Windows Embedded Compact 7
  FIX: ListBox selection issue when you use touch gestures in an SWE application on a Windows Embedded Compact 7-based device
  FIX: A RadioButton in a ListBox control stays in checked state when removed and re-added in Windows Embedded Compact 7

このアップデータを適用する前に、メディアプレイヤーアプリケーションを組み込んだ OS イメージをビルドしたことがある場合、このアップデータを適用してから OS イメージをビルドすると、その OS 上でメディアプレイヤーアプリケーションを起動しようとすると、起動時にアプリケーション内部で例外送出が起き、起動しないのです。この症状は、OS イメージをビルドする際、Platform Builder のソリューションエクスプローラで以下のフォルダ配下をリビルドすることで解決できます:

 C:/WINCE700/
  public/
   mediaapps/
    oak/
     samples/
★     cemp

‘cemp’ ディレクトリ配下に、メディアプレイヤーアプリケーションのソースコードがあります。アップデータを適用後、このディレクトリ配下をリビルドしてから OS イメージをビルドする(※OSDesign をリビルドする)ことにより、メディアアプリケーションが起動しないという問題が解消します。

この問題の原因は不明ですが、アップデータに含まれる Silverlight for Windows Embedded (SWE) の修正において、バイナリ互換性を壊してしまったものがあり、そのため、アプリケーションをリビルドしなければならない、ということのようです。

■問題の発生要因
さて、このような問題は、通常起きませんし、起きてはならないことだと思います。WEC 7 に付属しているコンポーネントが、アップデータの適用によって動作しなくなるということは、通常は考えられない事態です。実際、僕は初めて体験しました。特殊な状況だと思います。

この問題ですが、冒頭の方で、「不具合というよりは、月例アップデータのパッケージング上の問題だと思います。」と述べました。どういうことかといえば、ビルド済みの中間バイナリファイルが要因なのです。メディアプレイヤーアプリケーションと同様、WEC 7 に付属するアプリケーションである標準シェル(explorer.exe)や IE 7 は、メディアプレイヤーと同様、アプリケーション部分はソースファイルが付属するのですが、ビルド済みの中間バイナリファイル(.lib)も付属しており、手作業で明示的にソースファイルをビルドしない限りは、ビルド済みの中間バイナリファイルをリンクしてアプリケーションの .exe が生成されます。仮に、それらのアプリケーションとのバイナリ互換性を壊す修正が OS 本体に加えられた場合は、アプリケーションのビルド済み中間バイナリファイルも、修正と一緒に配布されるでしょう。従って、メディアプレイヤーアプリケーションで起きたような問題は、発生しないのです。

一方、メディアプレイヤーアプリケーションは、ソースファイルしか付属していないため、バイナリ互換性を壊す修正が OS 本体に加えられても、それに対応したビルド済み中間バイナリファイルはアップデータに含まれません。OS イメージをビルドする際、メディアプレイヤーアプリケーションのソースが未だビルドされていない場合は、ビルドされて、ビルド済み中間バイナリファイルが、ソースファイルのディレクトリ内に生成されます。OS イメージをビルドする際に、メディアプレイヤーアプリケーションのソースファイルから生成されたビルド済み中間バイナリファイルは、ソースファイルが更新されるか、または、手作業で明示的にソースファイルをリビルドしなければ更新されません。これが、上述した問題の原因、というわけなのです。

今回紹介した、Silverlight for Windows Embedded アプリケーションが月例アップデータ適用後に動作しなくなる、という問題は、僕は初めて体験しました。特殊なケースだとは思いますが、月例アップデータ、および、メディアプレイヤーアプリケーション(WMP サンプルアプリケーション)の WEC 7 における提供のされ方に要因があり、今後も起こる可能性がある問題だと思います。月例アップデータを適用する際には、適用前に、どのような修正が加えられたのかを確認し、Silverlight for Windows Embedded に関する修正の場合は、注意される方が良いと思います。

Add comment 2014/08/05 koga

WinCE/WEC の Secure Loader

前回(2013/02/10)から、一年ほど間が空いてしまいました。その間に、Windows Embedded Comact の最新版である Windows Embedded Comapct 2013 (WEC 2013) の一般提供も始まりました。この Blog でも、今後 WEC 2013 のことも交えて書く予定です。

ですが、今回は、前回の続編となることを書きます。組込み機器用の OS として WinCE/WEC が備えている、セキュリティを確保するための機能です。

■拡張性と脆弱性
前回は、ActivateDevice[Ex]() を用いてデバイスドライバを動的ロードすることができると説明しました。これは、便利な機能である反面、脆弱性の要因でもあります。

デバイスドライバを動的ロードできるということは、OS イメージに含めていないデバイスドライバを、OS の動作中に追加して、あらかじめ組み込まれてはいない機能を利用できるということです。たとえば、Flash メモリなどに配置した OS イメージを書き換えてアップデートする場合に、Flash メモリ用のデバイスドライバを OS イメージに組み込んでいなくとも、アップデート処理を実行するアプリケーションの .exe と、Flash メモリ用のデバイスドライバの .dll、および新しい OS イメージを USB メモリに入れて WEC デバイスにマウントし、アプリケーションを実行してアップデート処理を行うことが可能です。アップデート処理を実行するアプリケーションは、最初に ActivateDevice[Ex]() を使って、Flash メモリ用のデバイスドライバをカーネルにロードさせ、その後、DeviceIoControl() を使ってデバイスドライバを呼び出すことにより、OS イメージを Flash メモリに書き込む、というわけです。

デバイスドライバ、つまりカーネルモジュールを動的ロードできれば、このように拡張性を得られる一方で、悪意を持ったソフトウェアによる攻撃を容易にするという側面もあります。(悪意を持った)アプリケーションが可能な攻撃は、仮想メモリと実行モードによって制限されていますから、カーネルに対して致命的な障害を与えることは困難です。しかし、(悪意を持った)カーネルモジュールをアプリケーションがロードできてしまえば、カーネルのメモリ空間をアクセスできますし、プロセッサの特権モードで動きますので、カーネルに致命的な障害を引き起こすことは難しくありません。
(WinCE 5.0 までの純粋マイクロカーネルの場合には、デバイスドライバは、ユーザプロセスであるデバイスマネージャにロードされて動きますので、カーネルの保護は、より堅牢だったと言えます。)

■WinCE/WEC の Secure Loader
WinCE/WEC には、悪意を持ったソフトウェアによる攻撃を防ぐ機能として、Secure Loader (Loader Verifier Module) が用意されています。これは、あらかじめ OS イメージに組み込まれているアプリケーションや、認証されたアプリケーション以外は実行できないようにする仕組みです。WEC 7 のリファレンスでは、次のページで説明されています:

 Security Loader (Compact 7)
 http://msdn.microsoft.com/en-us/library/gg155695(v=winembedded.70).aspx

Secure Loader を有効にした OS イメージを作るには、OS Design のカタログ項目において、Loader Verifier Module を選択してビルドします。Loader Verifier Module は、Platform Builder のカタログ項目ビューにおいて、次の場所にあります:

 
  Core OS
   Windows Embedded Comapct
    Security
★    Loader Verifier Module

Secure Loader を有効にすると、OS イメージに組み込まれていないアプリケーションは、実行できなくなります。つまり、上で述べたデバイスドライバの動的ロードの例のように、USB メモリに入れたアプリケーションを実行しようとしても、実行できません。

OS イメージに組み込まれていないアプリケーションの実行を許さない処理は、WinCE/WEC のローダーによって行われます。ローダーが実行ファイル(executable)をロードする際に、ロードして構わないファイルかどうかをチェックして、条件に合わないものが指定された場合はエラーとするのです。

ローダーのソースコードは、
 C:/WINCE700/private/winceos/COREOS/nk/kernel/loader.c
にあります。loader.c で実装されている OpenExecutable() が、実行ファイルをロードする関数ですが、OpenExecutable() は、OS イメージに収録されたファイルに対しては OpenFileFromROM() を、ファイルシステム上のファイルに対しては OpenFileFromFilesys() を呼び出します。OpenFileFromROM() と OpenFileFromFilesys() は、FSOpenModule() という関数を呼び出して実行ファイルの内容をロードしますが、この FSOpenModule() において、ロードして構わないファイルかどうかのチェックが行われるようです。FSOpenModule() のソースは
 C:/WINCE700/private/winceos/COREOS/nk/kernel/fscall.c
にありますが、この関数は、filesys.dll を呼び出します。filesys.dll のソースは開示されていないため、詳細は分かりませんが、OpenFileFromROM() の場合、FSOpenModule() に渡す第二引数のフラグビット列で OPENMODULE_OPEN_ROMMODULE ビットが必ず 1 になるため、このビットを使って、OS イメージに収録されたファイルと、それ以外のファイルを区別して扱っているのだと思われます。

なお、Secure Loader 機能自体は、filesys.dll ではなく、lvmod.dll という DLL で実装されており、filesys.dll が lvmod.dll を呼び出すようです。カタログ項目の Loader Verifier Module を選択すると lvmod.dll が OS イメージに組み込まれることは、
 C:/WINCE700/public/common/oak/files/common.bib
を見ると分かります。Loader Verifier Module に関連付られた SysGen 変数は CE_MODULES_LVMOD ですので、これをキーにして common.bib を検索してみて下さい。

■署名による認証
Secure Loader を有効にすることにより、OS イメージに組み込まれていないアプリケーションを実行できないようになります。これでセキュリティは非常に高まりますが、拡張性は損なわれます。あらかじめ固定された機能しか動作しない、昔ながらの組込み機器であれば、ROM に配置した OS イメージに組み込まれたアプリケーションしか動かせなくても、問題ありません。しかし、サードパーティ製のアプリケーションを動かせるようにしたり、冒頭で述べたアップデート機能など、特定の場合にだけしか使わない機能を OS イメージには組み込まず、必要な時にだけ使いたい、という場合には、 OS イメージに組み込まれたアプリケーションしか実行できないのでは、対応できません。

ご安心下さい。WinCE/WEC の Secure Loader は、そのような場合に対応するための機能も備えています。実行ファイルに対する署名と、署名に対する認証機構により、OS イメージに組み込まれていないアプリケーションでも、認証できるものは実行を許すようになっています。上述した lvmod.dll が、この認証処理を行います。lmvod.dll が行う認証処理は、上述したローダーから呼び出される他、API としても提供されています。Secure Loader の API については、リファレンスの次のページをご覧ください:

 Security Loader Reference (Compact 7)
 http://msdn.microsoft.com/en-us/library/gg155306(v=winembedded.70).aspx

このリファレンスのページを見ると、ファイルを認証する API に加え、ブロックリスト、つまり、署名に対して認証エラーとするファイルの一覧を扱うものがあります。署名されており、署名に対する認証処理が成功するアプリケーション(実行ファイル)であっても、不正な動作をすることが分かった場合に、それをブロック対象として登録し、実行できないようにすることが可能なのです。

このように、不正なソフトウェアが実行されるのを防ぎ、セキュリティを確保するための仕組みを、拡張性と共に提供しているのが WinCE/WEC の Secure Loader というわけです。Secure Loader 用に、実行ファイルに署名を付ける手順は、リファレンスの次のページで説明されています:

 Signing Binaries (Compact 7)
 http://msdn.microsoft.com/en-us/library/gg156011(v=winembedded.70).aspx

 Deploy an Application on an OS with Security Loader (Compact 7)
 http://msdn.microsoft.com/en-us/library/jj200466(v=winembedded.70).aspx

WEC の最新版である WEC 2013 のリファレンスにも、同じ内容の説明があります:

 Signing Binaries (Compact 2013)
 http://msdn.microsoft.com/en-us/library/gg156011.aspx

 Deploy an Application on an OS with Security Loader (Compact 2013)
 http://msdn.microsoft.com/en-us/library/jj200466.aspx

■WinCE/WEC のセキュリティ
組込み機器のセキュリティは、一つの方策だけで確保できるものでは、ありません。機器の特性に応じて、複数の方策を組み合わせる必要があります。WinCE/WEC でのセキュリティの考え方や実現方策については、以下のページが参考になるでしょう。興味のある方は、ご覧になってみて下さい。

 Security for Windows Embedded Compact (Compact 7)
 http://msdn.microsoft.com/en-us/library/ee498894(v=WinEmbedded.70).aspx

 Trusted Environment Creation (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-us/library/ee498576(v=winembedded.60).aspx

 Windows Embedded CE 6.0 Security Model
 http://msdn.microsoft.com/en-us/library/ee497961(v=winembedded.60).aspx

 Security for Windows Embedded Compact Code Samples (Compact 7)
 http://msdn.microsoft.com/en-us/library/hh802407(v=winembedded.70).aspx

Add comment 2014/02/02 koga

IME と、ソフトウェアキーボードに関する tips

■はじめに
ご存じの方も多いと思いますが、WEC/WinCE には、日本語入力の IME (Input Method Editor) が付属しています。WEC 7 ですと、Platform Builder の Catalog Items View で次のカタログ項目を選択して OS Design をビルドすることにより、日本語 IME 3.1 が OS イメージに組み込まれます。

 Core OS
  International
   Language
    Japanese
     Input Method Editor (Choose 1)
★     IME 3.1

日本語入力用の IME として、IME 3.1 に加えて Pocket IME 2.0 も付属しており、Catalog Items View には、IME 3.1 と同じ階層に表示されます。今回は、Pocket IME ではなく、IME についての tips を紹介します。

■IME の初期入力モードの設定
IME の入力モードは、IME ツールバーの入力モードアイコンをクリックして表示されるポップアップメニューで変更できます。これは、WinXP/Vista/Windows 7 と同様です。ただし、WEC/WinCE 付属の IME では、プロパティダイアログで初期入力モードを設定することができません。初期入力モードは、レジストリでのみ設定可能なようです。

IME のレジストリ設定項目は、リファレンスの次のページで説明されています:

 Japanese IME 3.1 Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee491573.aspx

 Japanese IME 3.1 Registry Settings (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee491573(v=winembedded.60).aspx

なお、WinCE 6.0 の方のリファレンスには、”Japanese IME 3.1 Architecture” というページや、”Japanese IME 3.1 Customizable User Interface” というセクションがあり、IME のカスタマイズを行う際に必要となる情報が記載されています。興味のある方は、そちらも御覧になってみて下さい。

さて、初期入力モードを設定するレジストリ項目は、上のページで説明されている、HKEY_LOCAL_MACHINE\Software\Microsoft\IMEJP\3.1\MSIME キーの下の option3 です。この値は、デフォルトでは「ひらがな」入力モードになっています。これを変更して、たとえば「半角英数」入力モードにしたい場合は、0×0000000C を指定します。ただし、0×0000000C そのものを設定すると、「かな入力」になってしまいます。「ローマ字入力」にしたい場合は(※上のページに説明がある通り、デフォルトは「ローマ字入力です)、ローマ字入力を指定する 0×00000001 と組み合わせた値(論理 OR 結合した値)の 0×0000000D を指定して下さい。

つまり、OS Design のレジストリ設定ファイル(OSDesign.reg や project.reg)に次の行を追加して OS イメージをビルドすると、日本語 IME の初期入力モードが「半角英数」になります。

[HKEY_LOCAL_MACHINE\Software\Microsoft\IMEJP\3.1\MSIME]
    "option3"=dword:0000000D

■ソフトウェアキーボードの設定
次に、ソフトウェアキーボード(Software-based Input Panel; SIP)に関する tips です。デフォルトの振る舞いでは、エディットフィールドなど、テキスト入力の GUI 部品にフォーカスが当たると、自動的に SIP が表示されますが、WEC 7 では、この振る舞いを変更できます。

WEC 7 の SIP のレジストリ設定項目のリファレンスは、次のページです:

 Input Panel Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee504097.aspx

このページにある HKEY_CURRENT_USER\ControlPanel\SIP キーの説明を見て下さい。TurnOffAutoDeploy という値を 1 にすると、SIP が自動的に表示されない(are not auto deployed)と書かれています。実際、OSDesign.reg に次の行を追加して OS イメージをビルドすると、SIP が自動表示されません:

[HKEY_CURRENT_USER\ControlPanel\Sip]
    "TurnOffAutoDeploy"=dword:1


注意:リファレンスでは、キーの名前は ‘HKEY_CURRENT_USER\ControlPanel\SIP’ となっていますが、実際は、上の設定例のように、末尾は ‘Sip’ (先頭のみ大文字)が正しいようです。WINCE700\public\COMMON\oak\files/common.reg の記述を見ても、そうなっています。

なお、WinCE 6.0 のリファレンスを見ると、HKEY_CURRENT_USER\ControlPanel\SIP キーに TurnOffAutoDeploy という値がありません:

 Input Panel Registry Settings (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee504097(v=winembedded.60).aspx

WinCE 6.0 の OS Design に上記の TurnOffAutoDeploy の設定を追加して OS イメージをビルドしてみても、SIP が自動表示される動作は変わりません。つまり、WinCE 6.0 までは undocumented だったが実は使えた、という機能ではなく、WEC 7 になって初めて使えるようになった機能のようです。

しかし、Windows Mobile では、TurnOffAutoDeploy の設定が有効だったようで、’TurnOffAutoDeploy’ で Web を検索すると、Windows Mobile の tips として紹介しているページがヒットします。たとえば、次のページです。

 How To Stop Your SIP From Automatically Popping Up
 http://pocketnow.com/tweaks-hacks/how-to-stop-your-sip-from-automatically-popping-up

 Windows Mobile Registry Tricks
 http://www.ehow.com/list_7200029_windows-mobile-registry-tricks.html

Windows Mobile(6.x)のカーネルは WinCE 5.0 だったようですから、念のためにと思い、WinCE 5.0 のリファレンスも見てみましたが、WinCE 6.0 と同様、TurnOffAutoDeploy の記述は、ありません:

 Input Panel Registry Settings (Windows CE 5.0)
 http://msdn.microsoft.com/en-us/library/aa452674.aspx 

真相は分かりませんが、Windows Mobile でのみ提供されていた機能が、ユーザや開発者からの要望により WEC 7 にも追加された、ということなのかも知れません。

Add comment 2012/12/31 koga

telnetd と ftpd のユーザ認証

WEC 7/WinCE 6.0 には、皆さんお馴染みの Telnet サーバ(telnetd)と FTP サーバ(ftpd)が付属しています。どちらも、ユーザ認証なしで動かすことができ、開発中のデバイスを、ネットワーク経由で遠隔操作する際に便利です。しかし、ユーザ認証なしのままの設定では、セキュリティ面で大きなリスクがあります。今回は、WEC 7/WinCE 6.0 付属の telnetd と ftpd について、ユーザ認証を有効にする場合に必要な手順を述べます。

■はじめに
telnetd と ftpd は、OS Design のカタログビューでは、次の場所にあります:

・WEC 7 のカタログ項目
 <OS Design 名>
  Core OS
   Windows Embedded Compact
    Communication Services and Networking
     Servers
★     FTP Server
★     Telnet Server

・WinCE 6.0 のカタログ項目
 <OS Design 名>
  コア OS
   CEBASE
    通信サービスおよびネットワーク
     サーバー
★     FTP サーバー
★     Telnet サーバー

これらのカタログ項目を選択することにより、telnetd と ftpd が OS イメージに組み込まれます。

■ユーザ認証無しで動かす場合の設定
冒頭で述べたように、telnetd と ftpd のどちらも、レジストリ設定により、ユーザ認証無しで動かすことができます。次の行を、OS Design のレジストリ設定ファイル、つまり、OSDesign.reg(WEC 7 の場合)や project.reg(WinCE 6.0 の場合)に記述すれば、ユーザ認証無しで動作します。

[HKEY_LOCAL_MACHINE\Comm\TELNETD]
    "IsEnabled"=dword:1
    "UseAuthentication"=dword:0

[HKEY_LOCAL_MACHINE\Comm\FTPD]
    "IsEnabled"=dword:1
    "AllowAnonymous"=dword:1
    "AllowAnonymousUpload"=dword:1
    "NoSystemInfo"=dword:0


telnetd は、UseAuthentication に0を指定すると、接続時にユーザ認証を行いません。ftpd は、AllowAnonymous に1を指定すると、匿名アクセスを許可します。telnetd と ftpd に対するレジストリ設定項目の詳細については、リファレンスの次のページをご覧下さい。

 
 Telnet Server Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee499490

 FTP Server Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee498908

上のページは、WEC 7 のリファレンスですが、WinCE 6.0 の場合も同じです。なお、FTP サーバのレジストリ設定のページ(上の二番目のページ)にある DefaultDir の説明にあるように、デフォルトでは、FTP アカウントのルートディレクトリは /Temp に設定されます。WEC 7/WinCE のルートディレクトリを FTP アカウントでもルートディレクトリとしたい場合は、DefaultDir の値を “\\” にして下さい。

■ユーザ認証を有効にするための設定
telnetd と ftpd のユーザ認証無しのアクセスを禁止して、必ずユーザ認証を行わせるには、レジストリ設定を次のようにして下さい。

  • telnetd のレジストリ設定で、UseAuthentication を指定しないか(デフォルト値は0)、または、明示的に0を指定する。
  • ftpd のレジストリ設定で、AllowAnonymous と AllowAnonymousUpload を指定しないか(デフォルト値は0)、または、明示的に0を指定する。
  • アクセスを許可するユーザを、UserList で指定する。

たとえば、’Administrator’ というユーザにのみアクセスを許可する場合は、レジストリ設定ファイルに次の記述を入れて下さい。

[HKEY_LOCAL_MACHINE\Comm\TELNETD]
    "IsEnabled"=dword:1
    "UseAuthentication"=dword:1
    "UserList"="Administrator"

[HKEY_LOCAL_MACHINE\Comm\FTPD]
    "IsEnabled"=dword:1
    "NoSystemInfo"=dword:1
    "UserList"="Administrator"


上の記述例では、ftpd のレジストリ設定で NoSystemInfo に1を設定することにより、FTP クライアントがシステム情報を要求しても返さないようにしています。telnetd と ftpd のどちらも、平文でパスワードを受け取りますので、セキュリティが高くありません(※そのため、OS Design のこれらのカタログ項目を選択すると、Platform Builder がセキュリティリスクの警告ダイアログを表示します)。多少ともセキュリティを高める方策として、NoSystemInfo に1を指定するのは、悪くない考えだと思います。

さて、これだけでは、telnetd と ftpd にユーザ Administrator で接続することは、できません。次の二つの手順が、追加で必要です:

  1. OS Design に、ユーザ認証のカタログ項目を追加する。
  2. ユーザ登録を実行する。

以下、これらについて順に述べます。

(1)ユーザ認証のカタログ項目
以前に書いたエントリ(「WEC/WinCE から共有ディレクトリ(ファイルサーバ)をアクセス」)で、SMB/CIFS クライアントを組み込む場合には、認証処理に必要なコンポーネントも組み込む必要があると書きました。これと同様に、telnetd と ftpd のユーザ認証機能を有効にする場合も、認証処理用のコンポーネントを組み込まなければいけません。

telnetd と ftpd のユーザ認証では、認証処理用のコンポーネントとして必要なのは NTML です。WEC 7 の場合であれば、次のカタログ項目を選択して下さい。

 <OS Design 名>
  Core OS
   Windows Embedded Compact
    Security
     Authentication Services (SSPI)
★     NTLM

(2)ユーザ登録
ユーザ登録を行うには、アプリケーションから NTLMSetUserInfo() を呼び出して下さい。この関数で、ユーザのアカウント名とパスワードを設定できます。たとえば、OS の起動完了後に自動実行されるアプリケーションを実装し、そのアプリケーションが、NTLMSetUserInfo() を呼び出して telnetd と ftpd のユーザアカウントを登録する、というのが、お手軽な方策でしょう。NTLMSetUserInfo() については、リファレンスの次のページをご覧下さい:

 NTLMSetUserInfo (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee498121

ところで、telnetd と ftpd のレジストリ項目の UserList では、アクセスを許可するユーザを複数指定できるのですが、リファレンスの説明に間違いがありますので、注意して下さい。リファレンスには、許可対象のユーザが複数ある場合、カンマ区切りで指定すると書かれていますが、これはセミコロン区切りの間違いです。WinCE 6.0 のリファレンスの Telnet サーバに関するページには、この間違いを指摘するコメントが寄せられています:

 Telnet Server Registry Settings (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee499490(v=winembedded.60)

上のページの末尾にある Community Content の欄に、”Telnet Server Registry Settings corrections” というコメントがあり、上記の間違いを指摘しています。

UserList の記法の、より正確な説明は、telnetd と ftpd がユーザ認証時に利用している AuthHelpValidateUser() という API 関数を宣言したヘッダファイルに記載されています。この API 関数は、リファレンスに載っていないのですが、
 %_WINCEROOT%/public/common/sdk/inc/authhlp.h
で宣言されており、この authhlp.h の冒頭のコメント中に、より正確な記法の説明があります。その説明によれば、許可するユーザに加えて、拒否するユーザの指定も可能です。

■telnetd と ftpd のソースコード
今回のエントリの最後に、telnetd と ftpd のソースコードの場所を紹介しておきます。リファレンスページにも記載されているのですが、これらのソースコードは、次の場所にあります:

 telnetd
 %_WINCEROOT%/public/servers/sdk/samples/telnetd/

 ftpd
 %_WINCEROOT%/public/servers/sdk/samples/ftpd/

samples というディレクトリの配下に収録されていることからも分かるように、これらは、どちらかといえばサンプルコードという扱いです。実装上の制限が加えられている個所もありますので(たとえば、telnted は、同時接続数は最大9です)、必要であれば、カスタマイズを加えて利用するのが良いでしょう。telnetd のソースコードを改変し、限られたコマンドしか受け付けないようにすることでセキュリティを高める、というのは、その一例だと思います。

Add comment 2012/08/18 koga

CeLogFlush.exe と Kernel Tracker

WEC 7 や WinCE 6.0 のデバイスドライバや、アプリケーションの開発を行っていて、期待しているパフォーマンスが達成されなかったり、予想していたタイミングでスレッドが実行されない、などの問題が生じた場合、どこに要因があるのかを調べるには、カーネルのログ機能と Kernel Tracker を使うのが便利です。WEC/WinCE カーネルのログ機能は、デバッグメッセージを出力するなどの単純なものではなく、スレッドの切り替わりや、各種同期オブジェクトの獲得や解放、および、割り込み処理の発火など、OS 内部の詳細な動きを記録できるようになっています。

WEC/WinCE カーネルが出力したログの内容は、Kernel Tracker を使って、グラフィカルに表示できます。以下に、WEC 7 をデバイスエミュレータで動かして取得したログの内容を、Kernel Tracker で表示した様子を示します。

Kernel Tracker の画面キャプチャ

Kernel Tracker の画面キャプチャ

上の画面キャプチャを見ると、標準シェル(explorer.exe)のスレッドが 100ms の Quantum を使い果たし、servicesd.exe 内の同じ優先度を持つスレッドに切り替わった様子が分かります。また、ほぼ一定間隔で割り込み応答動作が起きていることも分かります。これは、1ms おきに発生するタイマ割り込みに対するものです。

このように、WEC/WinCE カーネルのログ機能を使うと、1ms より細かい時間精度でスレッドの動きを知ることができ、OS 内部の動作を分析するのに役立ちます。カーネルデバッガを使ってステップ実行する場合とは異なり、通常の動作での OS 内部の振る舞いを知ることができますので、うまく使えば、強力なツールとなります。また、後述するように、出荷後のデバイスに搭載されているものなど、ログ機能を有効にしない OS イメージに対しても、一時的にログ機能を有効にしてログ採取できるのも、非常に便利な点でしょう。

■CeLogFlush.exe によるログ採取(標準設定)
WEC/WinCE カーネルのログ機能については、リファレンスの次のページで説明されています:

 CeLog Event Tracking (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee479601

 CeLog Event Tracking Overview (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-us/library/ee480432(v=winembedded.60)

このログ機能を使って、WEC/WinCE カーネルが出力するログをファイルに保存する手順は、次の通りです。以下の説明は WEC 7 の場合ですが、WinCE 6.0 でも同様です。

  1. OS Design のカタログ項目で、Target Control Support (Shell.exe) を選択する(SYSGEN_SHELL を有効にする)。
  2. OS Design の「構成プロパティ」の Build Options で、Enable KITL を Yes に設定する。
  3. 同じく Build Options で、Flush tracked events to release directory を Yes (IMGAUTOFLUSH=1) に設定する。

ただし、WinCE 6.0 の場合は、次のいずれかの手順が追加で必要です。

  • OS Design の「構成プロパティ」の Build Options で、Enable event tracking during boot を Yes (IMGCELOGENABLE=1) に設定する。
  • project.bib の FILES セクションに、celog.dll を追加する。

つまり、WinCE 6.0 の場合は、IMGAUTOFLUSH に加えて IMGCELOGENABLE も1に設定しなければ(または、明示的に celog.dll を .bib ファイルに記述しなければ)、カーネルのログ出力が起きません。一方、WEC 7 の方は、IMGCELOGENABLE は設定しなくても、IMGAUTOFLUSH を1に設定すればカーネルのログ出力が起きるのです。実際、リファレンスを見ても、そのように説明されています:

 Including CeLogFlush in a Run-Time Image (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-us/library/ee481413(v=WinEmbedded.60).aspx

 Enable CeLog Event Tracking (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee480716

WinCE 6.0 と WEC 7 の、この違いは、%_WINCEROOT%/public/COMMON/oak/files/common.bib の記述内容の違いによるものです。WinCE 6.0 の common.bib には、IMGCELOGENABLE が1の場合に celog.dll を MODULES セクションに追加する行があるだけです。一方、WEC 7 の common.bib では、次のようになっています。

MODULES
;  Name            Path                                           Memory Type
;  --------------  ---------------------------------------------  -----------
…
IF IMGCELOGENABLE
   celog.dll       $(_FLATRELEASEDIR)\celog.dll                NK  SHK
ENDIF IMGCELOGENABLE
…

; ====================================================================
; FILES section
;
; ====================================================================

FILES
…
; Setting IMGAUTOFLUSH or IMGOSCAPTURE without IMGCELOGENABLE will include
; celog.dll in the FILES section instead of MODULES, so that the DLL will
; be loaded late enough to read settings from the device registry.
IF IMGCELOGENABLE !
IF IMGAUTOFLUSH
   celog.dll       $(_FLATRELEASEDIR)\celog.dll                NK  SH
ENDIF IMGAUTOFLUSH
IF IMGOSCAPTURE
   celog.dll       $(_FLATRELEASEDIR)\celog.dll                NK  SH
ENDIF IMGOSCAPTURE
ENDIF IMGCELOGENABLE


WEC 7 の場合は、common.bib の内容が上のようになっているため、IMGCELOGENABLE を設定せずに IMGAUTOFLUSH だけを1に設定した場合は、celog.dll が .bib ファイルの FILES セクションに追加されますので、OS イメージに celog.dll が収録されます。これに対して、WinCE 6.0 では、IMGCELOGENABLE が1に設定されなければ celog.dll が OS イメージに収録されません。そのため、IMGCELOGENABLE も1に設定するか、または、project.bib の FILES セクションに celog.dll の行を追加する必要があるのです。

上記の設定を行った OS Design をビルドして、ターゲットデバイスにダウンロードして動かすと、Flat Release Drectory、つまり環境変数 _FLATRELEASEDIR が指すディレクトリに celog.clg というファイルが作られて、カーネルが出力したログが書き込まれます。ターゲットデバイスと Platform Builder との接続を切れば、celog.clg ファイルを開くことができるようになりますので、Kernel Tracker で開いてみて下さい。

WEC 7 の場合は、.clg ファイルが Kernel Tracker と関連づけられているため、.clg ファイルのアイコンをダブルクリックすると、Kernel Tracker が起動します。WinCE 6.0 の場合は、Kernel Tracker を起動した後、File メニューで .clg ファイルを開く必要があります。詳細は、次のページをご覧下さい:

 Remote Timeline Viewer (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/gg156030

 Starting Kernel Tracker in File Mode (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee480674(v=winembedded.60)

■CeLogFlush.exe によるログ採取(設定のカスタマイズ)
さて、KITL と Target Control Support (Shell.exe) を有効にした OS イメージで、Flat Release Directory に WEC/WinCE カーネルのログを出力できることは分かりました(Target Control Support (Shell.exe) ではなく、Release Directory File System を有効にするのでも構いません)。これらを有効にしない限り、カーネルのログをファイルへ出力することは、できないのでしょうか?

Flat Release Directory 以外のディレクトリへファイルを出力することは、レジストリ設定により可能です。WEC/WinCE カーネルのログは、celog.dll によって RAM 上のリングバッファへ格納され、その内容を、CeLogFlush.exe がファイルへ出力する、という仕組みになっています。CeLogFlush.exe および celog.dll に対するレジストリ設定は、リファレンスの次のページで説明されています。

 CeLog Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee480468

 CeLogFlush Registry Settings (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee481192(v=winembedded.60)

ログを出力するファイルは、上のページの説明にある通り、[HKEY_LOCAL_MACHINE\System\CeLog] キーの FileName で設定できます。たとえば、SD カードにログファイルを出力する場合は、次のような行を .reg ファイルへ追加すればよいでしょう。

[HKEY_LOCAL_MACHINE\System\CeLog]
    "BufferSize"=dword:20000
    "FileName"="\\Storage Card\\celog.clg"
    "FileSize"=dword:0
    "FileFlags"=dword:0
    "FlushTimeout"=dword:2710
    "ThreadPriority"=dword:F8
    "Transport"="LocalFile"
    "UseUI"=dword:0
    "ZoneCE"=dword:c003e2


なお、BufferSize や FlushTimeout の値は、デフォルトよりも小さくしないで下さい。これらを小さくすると、celog.dll が確保するリングバッファがすぐに満杯になったり、あるいは、ログが出力されていなくてもすぐにバッファのフラッシュ時間に達してしまい、必要以上にログ出力が増えます(CeLogFlush.exe によるファイルへのログ書き込みによっても、カーネルのログ出力が発生することに留意して下さい)。その結果、OS の実効速度が実用にならないものになってしまう場合もあるからです。

もう一点注意です。[HKEY_LOCAL_MACHINE\System\CeLog] キーの FileName 値の設定で、ログの出力先を外部ストレージにする場合、そのストレージデバイスがマウントされるよりも前に CeLogFlush.exe が起動されないようにしなければいけません。IMGAUTOFLUSH を1に設定した場合、common.reg ファイルの記述により、[HKEY_LOCAL_MACHINE\init] キーに対する以下の設定が追加されます:

[HKEY_LOCAL_MACHINE\init]
        "Launch05"="CeLogFlush.exe"


この設定では、デバイスマネージャ(device.dll)よりも先に CeLogFlush.exe がロード・起動されてしまうため、CeLogFlush.exe が初期化時に出力ファイルを作成できず、エラーで終了してしまいます。従って、device.dll の起動順序(Launch20)よりも後の起動順序を設定する必要があります。デバイスマネージャが起動してストレージがマウントされるまでに若干の時間がかかることを考慮すると、gwes.dll(Launch30)の後にする方が、より確実だと思われます。

■ログ機能を有効にしていない OS イメージでのログ採取
ここまでの説明で、celog.dll と CeLogFlush.exe を OS イメージに組み込んでいれば、WEC/WinCE カーネルのログをファイルへ出力できることが分かりました。しかし、カーネルのログが常にファイルへ出力されると、若干のオーバーヘッドを生みますし、また、セキュリティの観点からも、好ましいことでは、ありません。このことは、上で紹介した WEC 7 のリファレンスページにも注意書き(Note)として記載されています。

さて、今回のエントリの冒頭で、次のように書きました:

また、後述するように、出荷後のデバイスに搭載されているものなど、ログ機能を有効にしない OS イメージに対しても、一時的にログ機能を有効にしてログ採取できるのも、非常に便利な点でしょう。

実は、celog.dll と CeLogFlush.exe を OS イメージに組み込んでいなくても、OS の起動後に celog.dll をカーネルにロードさせて、ログ機能を有効にできるのです。従って、USB メモリなどの外部ストレージに celog.dll と CeLogFlush.exe を入れておき、OS の起動後に、手動で CeLogFlush.exe を始動すれば、必要な時にだけログを採取できます。このことは、リファレンスの次のページでも説明されています:

 Collecting Data On A Standalone Device With CeLogFlush (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee480886(v=winembedded.60)

CeLogFlush.exe は、起動すると終了要求されるまで、celog.dll が出力したログをリングバッファから読み出してファイルへ出力するループ動作を実行します。”SYSTEM/CeLogFlush Quit” という名前の event に対して SetEvent() を呼び出すことにより、CeLogFlush.exe に終了要求できます。または、CeLogFlush.exe のソースファイルと同じ場所に収録されている、CeLogStopFlush というサンプルプログラムも参考になります。CeLogStopFlush は、CeLogFlushCommon.lib というライブラリを CeLogFlush.exe と共用しており、CeLogFlushCommon.lib の FLUSH_SignalStopFlush() という関数を呼び出します。FLUSH_SignalStopFlush() は、”SYSTEM/CeLogFlush Quit” という名前の event を OpenEvent() でオープンして、SetEvent() を呼び出すだけです(※SetEvent() の後、CloseHandle() を呼び出します)。

■おまけ
いかがでしょうか?ここまでの説明で、WEC/WinCE カーネルのログ機能が、出荷用の OS イメージに対する障害解析ツールとしても利用可能な、強力なものであることを、お分かり頂けたのではないかと思います。以下に、このログ機能について、いくつか補足します。

(1)CeLogFlush.exe と celog.dll のソースコード
 CeLogFlush.exe と celog.dll のソースコードは、それぞれ次の場所にあります:

 CeLogFlush.exe
 %_WINCEROOT%/public/COMMON/sdk/samples/celog/flush/CeLogFlush/

 celog.dll
 %_WINCEROOT%/private/winceos/COREOS/nk/celog/celogdll/

 CeLogFlush.exe と celog.dll は、”SYSTEM/CeLog Data” という名前の共有メモリ領域(CreateFileMapping() によって生成されるメモリマップドオブジェクト)上に配置したリングバッファを介して、WEC/WinCE カーネルが出力したログデータを受け渡しします。リングバッファが満杯に近付くと、celog.dll が event オブジェクトを使って CeLogFlush.exe に通知して、リングバッファの内容をファイルへ出力させる、という連携です。リングバッファのサイズは、celog.dll が共有メモリ領域を生成する際に、レジストリの設定値に従って決定します。celog.dll は、共有メモリ上のリングバッファ構造体のヘッダにバッファサイズを書き込むことにより、CeLogFlush.exe にサイズを伝えます。CeLogFlush.exe は、リングバッファが満杯に近付かなくとも(つまり、celog.dll から event オブジェクトで通知されなくとも)、レジストリで設定されたタイムアウト時間が経過すると、リングバッファの内容をファイルへ出力します。従って、ログ出力の量が少ない場合でも、一定周期でログファイルへの書き出しが行われます。

(2)”Enable event tracking during boot” を設定しない場合の動作
 OS Design の「構成プロパティ」の Build Options で、”Enable event tracking during boot” を Yes (IMGCELOGENABLE=1) に設定しない場合とする場合の違いについて、もう少し詳しく述べておきます。

  IMGCELOGENABLE を1に設定した場合としない場合の違いは、WEC/WinCE カーネルの初期化が完了した後から、カーネルの起動が完了するまでの間のログ出力を採取するかどうかです。つまり、IMGCELOGENABLE を1に設定した場合は、CeLogFlush.exe が起動する前に出力されたログも採取できるのに対し、IMGCELOGENABLE を1に設定しない場合は、CeLogFlush.exe が起動した以降のログのみ採取可能となります。この違いは、celog.dll がロードされるタイミングの違いによって生じます。そのタイミングの違いを引き起こすのは、.bib ファイルの設定です。

  WEC 7 の場合、common.bib の設定で、IMGAUTOFLUSH のみ1に設定した場合(IMGCELOGENABLE は1に設定しない場合)は、celog.dll が .bib ファイルの MODULES セクションではなく、FILES セクションに配置されると述べました。この結果、WEC/WinCE カーネルの初期化が完了した直後のタイミングでは、celog.dll がロードされず、CeLogFlush.exe によって初めてロードされるのです。これについて、もう少しだけ詳しく述べます。

  WEC/WinCE カーネルの初期化が終わり、マルチスレッドモードへ遷移して最初に起動されるスレッドが実行する関数である SystemStartupFunc() の中で、LoggerInit() という、ログ機能の初期化関数を呼び出します。この LoggerInit() は、”CeLog.dll” を引数として LoadKernelLibrary() を呼び出し、celog.dll をカーネルにロードすることを要求します。しかし、この時点では、filesys.dll がロードされておらず、ファイルシステム機能が初期化されていません。そのため、カーネルの loader は、OS イメージの中の modules、つまり、.bib ファイルの MODULES セクションに配置された DLL しかロードできないのです(※ちなみに、SystemStartupFunc() は、LoggerInit() を呼び出す前に、LoaderInit() を呼び出してカーネルの loader を初期化します)。そのため、LoggerInit() による CeLog.dll のロードは成功せず、その時点では、ログ出力が有効になりません。その後、CeLogFlush.exe が起動すると、CeLogFlush.exe の初期化処理において、再び “CeLog.dll” を引数として LoadKernelLibrary() が呼び出されます。この時点では、filesys.dll が動作していますので、FILES セクションに配置された DLL もロードできる、というわけです。

  さて、celog.dll は、ロードされると、InitLibrary() という初期化関数を呼び出します。この関数の中で、IOCTL_CELOG_REGISTER を ioctl コードとする KernelLibIoControl() 呼び出しを行い、ログ出力関数群の関数テーブル(CeLogExportTable 構造体)をカーネル本体に登録します。これらの関数は、カーネル本体の中にあるログ出力部に登録されます。カーネル本体の中にあるログ出力部は、登録された関数テーブルの中の pfnCeLogQueryZones というメンバを使って、ログ出力 DLL から、出力対象とする zone の組み合わせを示すマスクビット列を得て、ログ出力の有無判定に使う、という仕組みになっています。

  上で述べた、カーネル本体の処理のソースコードは、それぞれ次の場所にあります:

  SystemStartupFunc()
  %_WINCEROOT%/private/winceos/COREOS/nk/celog/schedule.c

  カーネル本体の中のログ出力部
  %_WINCEROOT%/private/winceos/COREOS/nk/logger/logger.c

(3)Readlog
  Kernel Tracker を使うと、WEC/WinCE カーネルのログ機能が出力したログデータをグラフィカルに表示できることを、冒頭で紹介しました。このログデータ、つまり .clg ファイルの内容を解析する付属のツールは、他にもあります。それが Readlog です。Readlog について、リファレンスの次のページをご覧下さい:

  Readlog Viewing Tool (Windows Embedded Compact 7)
  http://msdn.microsoft.com/en-us/library/ee481220.aspx

  Readlog Viewing Tool (Windows Embedded CE 6.0)
  http://msdn.microsoft.com/en-US/library/ee481220(v=winembedded.60)

  スレッドの切り替わりの様子などを直観的に見るには、Kernel Tracker が便利ですが、Kernel Tracker には表示されないログ内容をチェックしたり、ログ全体の分析結果などを手早く表示するには、Readlog の方が便利です。ちなみに、WinCE 6.0 の Kernel Tracker では、”Thread Migrate” のログを表示できませんが、WEC 7 のものでは表示できます。この “Thread Migrate” は、システムコールの発生、つまり、プロセス(カーネルである nk.exe 以外のプロセス)中のスレッドの、カーネル呼び出しによる、ユーザモードとカーネルモードの間の遷移に伴うコンテキストスイッチを示します。

(4)ログ機能のカスタマイズ
  ここまでの説明では、WEC/WinCE カーネルのログ出力は、celog.dll によって実行されると述べました。しかし、celog.dll を使わず、独自のログ出力 DLL を実装して使うことが可能です。また、独自のログ出力 DLL を celog.dll と共存させることも可能です(複数のログ出力 DLL を共存させることに意味があるかどうかは、別としてですが)。

  独自のログ出力 DLL を実装する方法について、リファレンスの次のページで説明されています。今のところ、WinCE 6.0 向けのものしかありませんが、WEC 7 でも同様の筈です。興味のある方は、カーネル本体のログ出力部や celog.dll のソースコードと併せ、ご覧になってみて下さい。

  CeLog Tool Customization (Windows Embedded CE 6.0)
  http://msdn.microsoft.com/en-us/library/ee480013(v=winembedded.60)

  Implementing a Custom Event Tracking Library (Windows Embedded CE 6.0)
  http://msdn.microsoft.com/en-US/library/ee480279(v=winembedded.60)

  Implementing an Event Tracking Library (Windows Embedded CE 6.0)
  http://msdn.microsoft.com/en-US/library/ee480272(v=winembedded.60)

Add comment 2012/08/16 koga

WEC 7 の Meiryo フォント

WEC 7 (Windows Embedded Compact 7) で、日本語フォントに Meiryo が追加されたのをご存じの方は、少なくないと思います。WEC 7 に標準で付属するフォントについては、リファレンスの次のページをご覧下さい。

 Fonts Catalog Items and Sysgen Variables (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee489874

上のページに書かれていますが、WEC 7 の Meiryo フォントは、Windows 7 のものと同じバージョンだそうです。Windows 7 と同様に、ClearType を有効にすることで、従来の MS ゴシックに比べて、より綺麗な文字表示が可能となります。ディスプレイドライバに対して ClearType の有効/無効を設定するためのレジストリキーは、次のページにある “ClearType Registry Keys” をご覧下さい。

 Display Driver Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee482851

さて、Meiryo フォントを使う場合に、注意しなければいけないことがあります。それは、”Monotype Imaging AC3 Font Compression” です。以前のエントリ(「圧縮フォント」)で書いたように、このカタログ項目を選択すると、MS ゴシックなどのアジア言語圏用のフォントファイルとして、通常の .ttc ではなく圧縮版の .ac3 が OS イメージに組み込まれます。ところが、OS イメージが小さくなるようにしたいと思って、Meiryo フォントを組み込む場合にも、この “Monotype Imaging AC3 Font Compression” を選択すると、ウィンドウのタイトルバーやメニュー項目、ボタンのラベルなど、標準の GUI 部品の日本語文字列が表示されなくなるのです。

そうなってしまう理由は、%_WINCEROOT%/public/COMMON/oak/files/ ディレクトリにある common.reg と common.bib を見ると分かります。まず、common.reg で “[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]” を検索してみて下さい。すると、このキーに対して、MS UI Gothic を代表的なフォントに関連づけるブロックがあって、その次に、Meiryo UI を、代表的なフォントおよび、MS ゴシック系統のフォントファミリに関連づけるブロックがあります。以下に、当該個所を引用します。


; @CESYSGEN IF FONTS_MSGOTHIC || FONTS_MSGOTHIC30 || FONTS_MSGOTHIC30_1_19 || FONTS_MSGOTHIC_1_50 || FONTS_MSGOTHIC_1_60 || FONTS_MSGOTHIC_1_70 || FONTS_MSGOTHIC_1_80 || FONTS_MSGOTHIC_1_90 || FONTS_MSGOTHIC_1_48
[HKEY_LOCAL_MACHINE\SYSTEM\GDI\GLYPHCACHE]
    "limit"=dword:5000
[HKEY_LOCAL_MACHINE\SYSTEM\GDI]
   "FontLinkMethods"=dword:1
; @CESYSGEN IF !FONTS_AC3_VERSIONS
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]
      "Arial"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Courier New"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Segoe UI"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Symbol"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Tahoma"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Times New Roman"="\\Windows\\msgothic.ttc,MS UI Gothic"
; @CESYSGEN ENDIF !FONTS_AC3_VERSIONS
; @CESYSGEN IF FONTS_AC3_VERSIONS
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]
      "Arial"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Courier New"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Segoe UI"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Symbol"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Tahoma"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Times New Roman"="\\Windows\\msgothic.ac3,MS UI Gothic"
; @CESYSGEN ENDIF FONTS_AC3_VERSIONS
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SkipTable]
      "Tahoma"="005c,00a5,007e,0391-03c9,2026,2116,221a,25a0-25ff"
; @CESYSGEN ENDIF FONTS_MSGOTHIC

; @CESYSGEN IF FONTS_MEIRYO
[HKEY_LOCAL_MACHINE\SYSTEM\GDI\GLYPHCACHE]
    "limit"=dword:5000
[HKEY_LOCAL_MACHINE\SYSTEM\GDI]
        "FontLinkMethods"=dword:1
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]
      "Arial"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Courier New"="\\Windows\\meiryo.ttc,Meiryo UI"
      "MS Gothic"="\\Windows\\meiryo.ttc,Meiryo UI"
      "MS PGothic"="\\Windows\\meiryo.ttc,Meiryo UI"
      "MS UI Gothic"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Segoe UI"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Symbol"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Tahoma"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Times New Roman"="\\Windows\\meiryo.ttc,Meiryo UI"
; @CESYSGEN ENDIF FONTS_MEIRYO

この記述があるために、MS ゴシックと Meiryo のカタログ項目を両方選択した場合、デフォルトのフォントとして Meiryo が設定されます。ここで、FONTS_AC3_VERSIONS が設定されているか否か、つまり、”Monotype Imaging AC3 Font Compression” が選択されているか否かに関わらず、meiryo.ttc が設定されることにも注意して下さい。実は、msgothic とは違い、meiryo には、.ac3 ファイルが存在せず、meiryo.ttc しかありません。興味のある方は、%_WINCEROOT%/public/COMMON/oak/files/ ディレクトリをご覧になってみて下さい。

なお、レジストリの [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink] キーについては、リファレンスの次のページに説明があります:

 Fonts Linking Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee489864

さて、MS ゴシックと Meiryo のカタログ項目を両方選択した場合、common.reg の記述により、Meiryo がデフォルトのフォントとして設定されることが分かりました。次は、common.bib を見てみましょう。common.bib で “; @CESYSGEN IF FONTS_AC3_VERSIONS” を検索してみて下さい。この行の以下、つまり、FONTS_AC3_VERSIONS が設定されている場合の条件ブロック内には、Meiryo に関する行が存在しないのです。FONTS_AC3_VERSIONS が設定されていない場合の条件ブロック(ELSE ブロック)には、meiryo.ttc が記述されています。

これで、お分かりでしょうか。OS Design で、MS ゴシックと Meiryo のカタログ項目を両方選択すると、Meiryo (meiryo.ttc) がデフォルトのフォントとして設定される一方、”Monotype Imaging AC3 Font Compression” が選択されていると、common.bib の記述により、meiryo.ttc が OS イメージに組み込まれないのです!

というわけで、Meiryo フォントを OS イメージに組み込む場合は、カタログ項目の “Monotype Imaging AC3 Font Compression” を選択しては、いけません。

さて、”Monotype Imaging AC3 Font Compression” については、Silverlight for Windows Embedded アプリケーションの場合も注意が必要です。リファレンスの次のページにある、”Monotype Imaging AC3 Font Compression” の説明をご覧になってみて下さい。

 Japanese Catalog Items and Sysgen Variables (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee491212.aspx

上のページには、AC3 フォント圧縮が、Silverlight for Windows Embedded ではサポートされておらず、そのため、AC3 フォント圧縮を有効にした OS Design では、非圧縮版のフォントファイルをアプリケーションに埋め込む必要がある、と書かれています。ちなみに、WinCE 6.0 のリファレンスにある AC3 フォント圧縮のカタログ項目の説明には、このような注意書きが、見当たりません(※もし、僕が見落としているのであれば、教えて下さい):

 Japanese OS Design Development (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee491212(v=winembedded.60)

WEC 7 において、Meiryo フォントおよび Silverlight for Windows Embedded アプリケーションが AC3 フォント圧縮をサポートしていない理由は、分かりません。もしかすると、Meiryo フォントが AC3 フォント圧縮に向かない仕組みなのかも知れません。Silverlight for Windows Embedded アプリケーションでは、表示を綺麗にするために Meiryo フォントを使うようになっており、そのため、上述したように、AC3 フォント圧縮が有効になっていると日本語が表示されない(meiryo.ttc が OS イメージに組み込まれないため)、ということなのかも知れません。

Add comment 2012/07/13 koga

WEC/WinCE から共有ディレクトリ(ファイルサーバ)をアクセス

前回のエントリで、.NET CF アプリケーションから WNetAddConnection3() を呼び出す例を述べました。その例の説明で書いたように、WNetAddConnection3() は、Windows フィルサーバとの接続などを行う API です。

■Windows ファイルサーバに対するクライアント機能
Windows ファイルサーバ(CIFS サーバ)をアクセスする機能、つまり、Windows ファイルサーバに対するクライアント機能は、”Windows Networking API/Redirector” というコンポーネントになっており、SYSGEN 変数の SYSGEN_REDIR を設定することにより、OS イメージに組み込まれます。詳細については、リファレンスの次のページをご覧ください。

 Windows Networking API/Redirector Reference (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee495264.aspx

 Windows Networking API/Redirector (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee494246(v=winembedded.60).aspx

Platform Builder のカタログ項目ビュー(Catalog Items View)の階層で言うと、次の項目を選択すると、SMB/CIFS クライアント機能が OS Design に組み込まれます(※WEC 7 の場合):

 <OS Design 名>
 Core OS
  Windows Embedded Compact
   Communication Services and Networking
    Networking – General
★    Windows Networking API/Redirector (SMB/CIFS)

ここで、”Redirector” という Windows の用語に馴染みのない方は、たとえば、次の解説記事が参考になるのではないかと思います。

 「基礎から学ぶWindowsネットワーク 第20回」
 http://www.atmarkit.co.jp/fwin2k/network/baswinlan020/baswinlan020_03.html

 「基礎から学ぶWindowsネットワーク」
 http://www.atmarkit.co.jp/fwin2k/network/baswinlan002/baswinlan002_03.html

なお、CIFS クライアントだけでなく、CIFS サーバ機能も WEC/WinCE に付属しています。こちらは、カタログ項目ビューの階層の、次の場所にあります:

 <OS Design 名>
 Core OS
  Windows Embedded Compact
   Communication Services and Networking
    Servers
     File Server (SMB/CIFS)

CIFS サーバに関する記述は、なぜか WEC 7 のリファレンスに見当たりません。興味のある方は、WinCE 6.0 のリファレンスをご覧ください。

 File Server (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-us/library/ee500573(v=winembedded.60).aspx

■SMB/CIFS クライアント機能を組み込む場合の注意点
さて、SMB/CIFS クライアント機能(Windows Networking API/Redirector)を組み込む場合、一つ注意しなければいけません。WEC/WinCE のリファレンスには、このコンポーネントが依存するのは、TCP/IP (SYSGEN_TCPIP) と Winsock (SYSGEN_WINSOCK)、および NDIS (SYSGEN_NDIS) とだけ書かれているのですが、それらのコンポーネントだけでは、SMB/CIFS サーバにアクセスすることは、できません。

CIFS サーバに接続する場合は、認証処理が必要ですが、認証処理に必要なコンポーネントは、SMB/CIFS クライアント機能を組み込んでも自動的に組み込まれないため、明示的に組み込む必要があるのです。認証処理に必要なコンポーネントは、WEC 7 ですと、カタログ項目ビューの階層の、次の場所にあります:

 <OS Design 名>
 Core OS
  Windows Embedded Compact
   Security
    Authentication Services (SSPI)
★    Kerberos
★    NTLM

通常は、NTLM だけを選択しても CIFS サーバに接続できるでしょう。お手元の環境で、試してみて下さい。これらのコンポーネントについては、リファレンスの次のページで説明されています(※WEC 7 の場合)。

 NTLM Security Support Provider (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee498104.aspx

 Kerberos Security Support Provider (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee498711.aspx

 Authentication Services (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee498877.aspx

Add comment 2012/05/07 koga

.NET CF アプリケーションとカーネルランドを一緒にデバッグ(1/2)

今回は、マネージドコードのアプリケーション、つまり、.NET CF のアプリケーションとカーネルランドを、Ethernet 経由で一緒にデバッグする方法を説明します。「一緒にデバッグする」というのは、”「同時にデバッグする」ことはできないが、アプリケーションデバッガとカーネルデバッガを各々動かすことにより、アプリケーションとカーネルランドを、それぞれのデバッガでデバッグする”という意味です。

皆さんご存じの通り、ネイティブコードのアプリケーションの場合には、アプリケーションもカーネルランドも、どちらもカーネルデバッガでデバッグできます。たとえば、アプリケーションからデバイスドライバを呼び出した場合、デバイスドライバのソースコードにブレークポイントを設定してブレークした時、アプリケーションからデバイスドライバまでのコールスタック(「呼び出し履歴」)を見ることができます。アプリケーションがデバイスドライバを呼び出す場合、システムコールを経由しますが、カーネルデバッガは、その経路を把握して、あたかも通常の関数呼び出しのように、コールスタックを表示してくれるのです。僕は、このように、一つのデバッガだけでアプリケーションとカーネルランドをデバッグすることを指して「同時にデバッグする」と表現しています。

一方、マネージドコード(.NET CF)のアプリケーションの場合には、一つのデバッガだけでアプリケーションとカーネルの両方をデバッグすることは、できません。アプリケーションのデバッガとカーネルデバッガを各々動かす必要があるのです。このことを指して、ここでは「一緒にデバッグする」と表現します。

■Ethernet 経由でのアプリケーションデバッガ接続
Ethernet 経由で WinCE/WEC のアプリケーションデバッガを接続する場合は、ActiveSync は使用しません。ActiveSync は、2005年にリリースされた 4.0 から TCP/IP 接続をサポートしていませんから、使えないのです。ActiveSync を使わずに、TCP/IP で WinCE/WEC に接続する手順は、Visual Studio のリファレンスのページで説明されています:

 How to: Connect to Windows CE Device Without ActiveSync
 http://msdn.microsoft.com/en-US/library/ms228708(v=vs.90).aspx

上のページは、Visual Studio 2008 のリファレンスです。日本語の説明を読みたい場合は、Visual Studio 2005 ですが、ユニダックス社の「CE6.0 技術情報」に日本語の説明があります:

 11. アプリケーションのリモートデバッグ
 http://www.unidux.co.jp/embedded/techinfo/ce6/000437.php

上のページで説明されているように、Visual Studio に付属している次の5つのファイルを、WinCE/WEC の /Windows ディレクトリへコピーして、Visual Studio のデバイス設定を行うことにより、TCP/IP でアプリケーションデバッガを接続できます。

 Clientshutdown.exe
 ConmanClient2.exe
 CMaccept.exe
 eDbgTL.dll
 TcpConnectionA.dll

WEC 7 で、AMR9 コアの CPU のボードに接続する場合ですと、上記のファイルは、次の場所にあります。

 C:\Program Files\Common Files\microsoft shared\CoreCon\1.0\Target\wce400\armv5\

これらのファイルを、WinCE/WEC が起動した後に、/Windows ディレクトリに USB メモリなどを使ってコピーするか、または、OS Design の project.bib ファイルを編集して OS イメージに組み込めば、使えます。

または、OS Design のカタログ項目で、”Target Control Support(Shell.exe)” か “Release Directory File System” を選択している場合は、Flat Release Directory(環境変数 _FLATRELEASEDIR が指すディレクトリ)に上記5つのファイルを置いても、使えます。Target Control Support を有効にしてカーネルデバッガを使っている場合には、これが一番お手軽でしょう。

■OS Design から作った SDK との関連づけ
マネージドコードのアプリケーションも、ネイティブコードのアプリケーションも、WinCE/WEC のアプリケーションは、Visual Studio の「スマートデバイス」プロジェクトで作成します。それらのアプリケーションをデバッグする場合は、上で紹介したページで説明されている手順で、WinCE/WEC と接続する必要があります。

Visual Studio 2008 日本語版と WEC 7 の場合ですと、以下のような手順になります。

  1. 上記の5つのファイルを、WEC 7 の /Windows ディレクトリへコピーする。
  2. WEC 7 を DHCP 有効で動かしている場合は、コマンドプロンプトで ipconfig を実行して、WEC 7 の IP アドレスを調べる。
  3. Visual Studio 2008 の [ツール] > [オプション...] メニューを選択し、「オプション」ダイアログを開く。
  4. 「オプション」ダイアログの左端にあるツリービューで、[デバイスツール」を展開し、その下にある「デバイス」を選択する。
  5. 「オプション」ダイアログの右端に表示された「デバイス」画面にある、「デバイス(V):」というリストボックスから、アプリケーションのビルドに使った SDK のデバイスを選択する。
  6. 「デバイス(V):」リストボックスの右側にある「プロパティ」ボタンをクリックして、選択したデバイスのプロパティダイアログを開く。
  7. プロパティダイアログの「トランスポート(R):」というドロップダウンリストから、「TCP 接続トランスポート」を選択する。
  8. 「トランスポート(R):」ドロップダウンリストの右側にある「構成(C)...」ボタンをクリックして、「TCP/IP トランスポートの構成」ダイアログを開く。
  9. 「TCP/IP トランスポートの構成」ダイアログにある二つのラジオボタンのうち、「特定の IP アドレスを使用(S):」を選択する。
  10. 「特定の IP アドレスを使用(S):」の下にあるエディットフィールド兼ドロップダウンリストに、WEC 7 の IP アドレスを入力して設定する。
  11. 「TCP/IP トランスポートの構成」ダイアログ、プロパティダイアログ、および「オプション」ダイアログの OK ボタンを順にクリックして、設定内容を確定する。
  12. WEC 7 で、ConmanClient2.exe と CMaccept.exe を順に実行する。
  13. Visual Studio 2008 の [ツール] > [デバイスへの接続...] メニューを選択する。

■ターゲットボードとホスト PC を直結する場合
さて、上の手順では、WinCE/WEC を DHCP 有効で動かしている場合(デフォルトでは、DHCP 有効です)、WinCE/WEC を起動するたびに IP アドレスを調べて Visual Studio の「TCP/IP トランスポート構成」の設定に反映しなければいけません。DHCP 有効ではなく、固定 IP アドレスで動かせば、WinCE/WEC を起動するたびに設定する必要がなくなり、少しだけ手間を減らせます。

あるいは、WinCE/WEC とホスト PC をハブ経由で接続せず、クロスの Ethernet ケーブル(*)で直接接続する場合は、DHCP サーバにアクセスできませんから、WinCE/WEC とホスト PC 共に、固定 IP アドレスを割り当てる必要があります。

※最近のネットワークインタフェースは、ストレートの Ethernet ケーブルで直接接続しても、自動認識してくれるものが多くなっています。従って、WinCE/WEC とホスト PC を Ethernet ケーブルで直接接続する際、クロスケーブルがなければ、ストレートケーブルで接続しても大丈夫な場合があります。手元にクロスケーブルがない場合は、試してみて下さい。
 なお、Ethernet 経由でリモートデバッグする場合、WinCE/WEC とホスト PC をハブ経由で接続するよりも、直接接続する方が、一般的には通信速度が上がりますので、より快適にデバッグできます。

Visual Studio を動かすホスト PC、つまり、Windows 7 や Vista/WindowsXP に固定 IP アドレスを設定する手順は、皆さんご存じだと思いますので、ここでは、WinCE/WEC に固定 IP アドレスを設定する方法を述べます。

WEC 7 と WinCE 6.0 の IP アドレス設定のレジストリは、リファレンスの以下のページで説明されています:

 TCP/IPv4 Configurable Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee494881.aspx

 TCP/IPv4 Configurable Registry Settings (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee494881(v=winembedded.60).aspx

上のページの中ほどにある、”Adapter-specific Values” という表を見て下さい。ここに、”EnableDHCP”, “DefaultGateway”, “IpAddress”, “Subnetmask” が載っています。これらのレジストリ項目を使って、WinCE/WEC に固定 IP アドレスを設定できます。レジストリキーは、これらのページに書かれている通り、
 [HKEY_LOCAL_MACHINE\Comm\<アダプタ名>\Parms\Tcpip]
です。たとえば、弊社が提供している Armadillo-400 シリーズ用の BSP であれば、以下の行を .reg ファイルに書いて OS イメージをビルドすると、クラス C の固定 IP アドレス 192.168.0.50 が設定されます:

[HKEY_LOCAL_MACHINE\Comm\FEC1\Parms\Tcpip]
    "EnableDHCP"=dword:0
    "DefaultGateway"="192.168.0.1"
    "IpAddress"="192.168.0.50"
    "Subnetmask"="255.255.255.0"


ここまでの設定は、Visual Studio のスマートデバイスプロジェクトのアプリケーションを Ethernet 経由でデバッグするための手順です。次に、今回の本題である、マネージドコード(.NET CF)のアプリケーションをカーネルランドと一緒にデバッグする方法を説明します。

■カーネルデバッガも一緒に動かす方法
今回の冒頭で、「.NET CF のアプリケーションとカーネルランドを一緒にデバッグするとは、アプリケーションデバッガとカーネルデバッガを各々動かすことにより、それぞれをデバッグすること」だと述べました。アプリケーションデバッガとカーネルデバッガを各々動かすというのは、どういうことかと言えば、Visual Studio を二つ起動して、一方でアプリケーションデバッガ、もう一方でカーネルデバッガを動かす、ということです。

以下に、もう少し具体的な手順を述べます。以下のようにすれば、アプリケーションデバッガとカーネルデバッガを各々動かして、.NET CF のアプリケーションとカーネルランドを一緒にデバッグできます。

  1. Visual Studio を起動して、OS Design のプロジェクトを開く。
  2. OS Design のプロジェクトをビルドしてできた OS イメージを、ホスト PC と Ethernet 接続したターゲットボードに転送し、カーネルデバッガを有効にして WinCE/WEC を起動する。
  3. Visual Studio をもう一つ起動して、デバッグしたいアプリケーションのプロジェクトを開く。
  4. 上で述べた手順を使って、アプリケーションのプロジェクトを開いた Visual Studio から WinCE/WEC に接続する。
  5. アプリケーションのデバッグを開始する。

このようにすれば、二つ起動した Visual Studio のうち、OS Design のプロジェクトを開いた方でカーネルデバッガが動き、アプリケーションのプロジェクトを開いた方でアプリケーションデバッガが動きます。なお、アプリケーションデバッガで設定したブレークポイントでアプリケーションが停止した場合、OS(WinCE/WEC)は動作し続けていますが、カーネルデバッガで設定したブレークポイントで停止した場合は、OS 全体が停止しますので、アプリケーションの動作も停止します。これは、アプリケーションデバッガとカーネルデバッガで違う点です。

以上で、アプリケーションとカーネルランドを一緒にデバッグする方法の説明は、一応終わりです。ただし、いくつか補足が必要なので、次回に続けます。もし、上の手順を試してみたが、アプリケーションデバッガとカーネルデバッガを一緒に動かせない、という方は、次回の説明もあわせて読んでみて下さい。

Add comment 2012/04/03 koga

Previous Posts


Categories

Links

Posts by Authors

Recent Posts

Calendar

2017年3月
« 9月    
 1234
567891011
12131415161718
19202122232425
262728293031  

Posts by Month

Posts by Category

Meta