Device2Cloudオープンセミナ2012CeLogFlush.exe と Kernel Tracker

IP アドレス設定をアプリケーションから変更するには

2012/07/22 koga

WEC 7 (Windows Embedded Compact 7) や WinCE 6.0 (Windows Embedded CE 6.0) で、IP アドレス設定を変更するには、コントロールパネルの “Network and Dial-up Connections” を使います。これは、WinXP と同様です。WEC 7/WinCE の通常の使い方、つまり、ユーザが画面操作で IP アドレスを設定できる場合は、それで全く問題ありません。

しかし、ヘッドレスのデバイスの場合、つまり、画面操作ができない場合は、どうでしょうか?WEC 7/WinCE 6.0 には、IP アドレスをコマンドラインで設定できるユーティリティは付属していませんので、自前で作る必要があります。その方法、つまり、IP アドレス設定をアプリケーションから変更する方法について、以下に説明します。

■コントロールパネルのソースコードを見てみる
IP アドレス設定をアプリケーションから変更するには、どうすればよいでしょう?それを調べる最も確実な方法は、同じことをやっているモジュールのソースコードを読んでみることです。つまり、コントロールパネルの “Network and Dial-up Connections” アプレットが、どうやって IP アドレスの設定変更を処理しているかを見ればよい、というわけです。コントロールパネルの、このアプレットを起動する部分のソースコードは、
 %_WINCEROOT%/public/wceshellfe/oak/ctlpnl/connpnl/
にあります。

“Network and Dial-up Connections” アプレットを起動する処理は、connpnl.cpl という、コントロールパネル用の DLL で実装されています。上のディレクトリを見ると、ソースファイルは connpnl.cpp 一つだけです。connpnl.cpp の内容を見ると、DllEntry() と CPlApplet() が実装されています。IP アドレスの設定がどのように処理されるのかを追跡するには、CPlApplet() の中にブレークポイントをセットして、カーネルデバッガを使うのが簡単です。CPlApplet() の本体は、message 引数に対する switch 文だけですが、アプレットを起動する処理は、コントロールパネルのアイコンがダブルクリックされた場合、つまり、CPL_DBLCLK に対する case 節にあります。そこを見ると、”\\Windows\\connmc.exe” を第一引数として CreateProcess() を呼び出しており、connmc.exe がアプレットの実体であることが分かります。

この connmc.exe のソースコードは、WEC 7 のソースツリーを探してみると、
 %_WINCEROOT%/public/COMMON/oak/drivers/netsamp/connmc/
にあることが分かります。connmc.exe が、”Network and Dial-up Connections” アプレットの実体です。

“Network and Dial-up Connections” アプレットで、ネットワークアダプタのアイコンをダブルクリックして IP アドレスを設定するダイアログ(プロパティシート)を表示する処理は、実は、上のディレクトリにあるソースファイルでは実装されていません。その実装は、
 %_WINCEROOT%/public/COMMON/oak/drivers/netui/
にある network.c で実装されています。network.c に入っている AdapterIPProperties() が、IP アドレスのプロパティシートを表示して、IP アドレス設定を行う関数なのです。

connmc.exe から、netui/ ディレクトリにある network.c の関数が呼び出される、というのは、ソースコードを見ただけでは、分かりません。こういう場合は、カーネルデバッガを使って追いかけるのが簡単です。connmc.exe のメインウィンドウのウィンドウプロシージャは、connmc.cpp で実装されている ConnMCWndProc() ですから、この関数にブレークポイントをセットしてカーネルデバッガでステップ実行すれば、AdapterIPProperties() まで辿りつくことができるでしょう。参考までに、ConnMCWndProc() から AdapterIPProperties() までの呼び出し連鎖を記します。

 connmc.exe
  ConnMCWndProc()		: connmc.cpp
  ConnMCHandleCommand()		: connmc.cpp
  LanConnInfo::showProperties()	: lanconninfo.cpp
  CallAdapterIPProperties()	: %_WINCEROOT%/public/common/oak/inc/netui.h
  CallUAdapterIPProperties()	: %_WINCEROOT%/public/common/oak/inc/netui_user.h
 netui.dll
  AdapterIPProperties()		: network.c


ちなみに、CallUAdapterIPProperties() による AdapterIPProperties() の呼び出しでは、netui.dll を LoadLibraryW() でロードして GetProcAddressW() により関数ポインタを取得する、という方法で行っています。そのため、connmc.exe のリンクライブラリを見ても、netui.lib が入っておらず、connmc.exe が netui.dll で実装されている関数を呼び出すということは、分からないでしょう。やはり、カーネルデバッガを使って追いかけるのが簡単です。

■IP アドレス設定を変更する処理手順
さて、本題に戻ります。”Network and Dial-up Connections” アプレット、つまり connmc.exe が、ネットワークアダプタの IP アドレスを設定する処理は、ソースを追ってみると、次の手順であることが分かります:

  1. レジストリの [HKEY_LOCAL_MACHINE\Comm\<アダプタ名>\Parms\Tcpip] キー配下の各キー値を設定する。
  2. ネットワークスタック(NDIS)に対して、アダプタの設定変更動作を DeviceIoControl() で要求する。

レジストリの [HKEY_LOCAL_MACHINE\Comm\<アダプタ名>\Parms\Tcpip] キー配下の各キー値を設定するのは、上で述べた、netui.dll の AdapterIPProperties() です。そして、DeviceIoControl() を使ってアダプタの設定変更動作を NDIS に要求するのが、connmc.exe の LanConnInfo::showProperties() です。ここで、NDIS のデバイス名は “NDS0″、アダプタの設定変更動作を要求する ioctl コードは IOCTL_NDIS_REBIND_ADAPTER です。詳細は、lanconninfo.cpp と、NDIS 関連の定数を定義しているヘッダファイル(%_WINCEROOT%/public/common/sdk/inc/ntddndis.h)をご覧になってみて下さい。

というわけで、アプリケーションから IP アドレス設定を変更するには、レジストリを書き換えた後に NDIS を DeviceIoControl() で呼び出して設定変更を反映させればよいことが分かりました。IP アドレス設定を変更するコマンドラインユーティリティを作る場合は、この方法で試してみて下さい。

Entry Filed under: OS の内部動作, アプリケーション開発

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Categories

Links

Posts by Authors

Recent Posts

Calendar

2012年7月
« 6月   8月 »
1234567
891011121314
15161718192021
22232425262728
293031  

Posts by Month

Posts by Category

Meta