<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>プログラミング：Win32</title><link>http://blogs.wankuma.com/shannon/category/1215.aspx</link><description>プログラミング：Win32</description><managingEditor>シャノン</managingEditor><dc:language>ja-JP</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>シャノン</dc:creator><title>NTネイティブパス名をMS-DOSパス名に変換するには？</title><link>http://blogs.wankuma.com/shannon/archive/2008/08/05/151797.aspx</link><pubDate>Tue, 05 Aug 2008 13:15:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/08/05/151797.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/151797.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/08/05/151797.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/151797.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/151797.aspx</trackback:ping><description>&lt;p&gt;本投稿は備忘録であり、ご回答は &lt;a href="http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200808/08080009.txt"&gt;NTネイティブパス名をMS-DOSパス名に変換するには？&lt;/a&gt; で募っています。&lt;br&gt;マルチポストとなるのを避けるため、こちらには技術的な内容をご回答されませんよう、お願いいたします。&lt;/p&gt; &lt;p&gt;以下本文。&lt;/p&gt; &lt;p&gt;NT パス名、例えば \Device\HarddiskVolume1\... を C:\... に変換するにはどうすればよいのだろう？&lt;/p&gt; &lt;p&gt;ローカルドライブ下にあるパスについては、GetLogicalDriveStrings でドライブ名の一覧を取得し、QueryDosDevice でドライブ名を NT デバイス形式に変換し、前方一致で確認すればできそう。&lt;br&gt;が、ネットワークドライブや、ドライブレターが割り当てられていない UNC パスについてはどうすれば？&lt;/p&gt; &lt;p&gt;ローカルドライブの場合、例えば C: について QueryDosDevice で問い合わせれば \Device\HarddiskVolume1 という文字列のみが返ってくるため、前方一致で判別できる。&lt;br&gt;しかし、例えば、N: が \\Server\Path にマップされている場合、ネットワークドライブ内にあるファイルの NT パスは \Device\LanmanRedirector\Server\Path だが、N: に対して QueryDosDevice を実行すると \Device\LanmanRedirector\;N:謎の数字 \Server\Path のような文字列が返ってきてしまい、前方一致できない。&lt;br&gt;また、QueryDosDevice に UNC を渡しても、対応する NT パスは取得できない。&lt;br&gt;NT パスが \Device\LanmanRedirector\Server\Path となっていれば、それは \\Server\Path を指すのだと解釈してしまうのも、ドライバか何かの実装が異なれば、 LanmanRedirector 以外の名前がありそうで怖い。&lt;/p&gt; &lt;p&gt;RtlNtPathNameToDosPathName という関数もあるが、Undocumented なので、できれば使いたくない。&lt;/p&gt; &lt;p&gt;マウントポイント等の場合にどうなるかは要調査。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/151797.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>追試、情報求む</title><link>http://blogs.wankuma.com/shannon/archive/2008/07/25/150320.aspx</link><pubDate>Fri, 25 Jul 2008 13:44:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/07/25/150320.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/150320.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/07/25/150320.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/150320.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/150320.aspx</trackback:ping><description>&lt;P&gt;Windows API の &lt;A href="http://msdn.microsoft.com/en-us/library/aa364937.aspx"&gt;GetDiskFreeSpaceEx&lt;/A&gt;&amp;nbsp;について MSDN で調べると、&lt;Q&gt; If per-user quotas are being used, this value may be less than the total number of free bytes on a disk. &lt;/Q&gt;とあることから、この関数はディスク クォータに対応していると考えられます。&lt;BR&gt;しかし、Windows 2003 R2 から導入された &lt;A href="http://www.atmarkit.co.jp/fwin2k/special/2003r2_02/2003r2_02_02.html"&gt;File Server Resource Manager&lt;/A&gt;&amp;nbsp;を利用して設定したクォータによって制限された容量は、この関数では取得できない（GetDiskFreeSpaceEx は FSRM に対応していない）という情報を耳にしました。&lt;/P&gt;
&lt;P&gt;当方、2003 R2 または 2008 の環境がないため、試すことができません。&lt;BR&gt;どなたか、この情報は本当なのか、もし本当であれば、それは仕様として Microsoft からドキュメント化されているか、また、回避策はあるのか等、ご存知でしたら教えてください。&lt;/P&gt;
&lt;P&gt;MSDN には &lt;A href="http://msdn.microsoft.com/en-us/library/bb972746.aspx"&gt;FSRM の API&lt;/A&gt; がドキュメント化されていますが、&lt;Q&gt;The FSRM API is available starting with Windows Server 2008.&lt;/Q&gt; と書かれています。これは本当なのでしょうか？ 2003 R2 の FSRM の情報を取得する API は無いということでしょうか？&lt;/P&gt;
&lt;P&gt;また、このような透過的でないクォータ サービスが存在しうるということは、第２、第３の FSRM（Microsoft 製でないものも含む）があり得るということですので、由々しき事態だと思います。&lt;BR&gt;もし本当ならば、これは Microsoft に改善してもらわねばならないと思うのですが、そういったフィードバックはどこに提出すればよいのでしょうか？&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/150320.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>翻訳版でないかなー</title><link>http://blogs.wankuma.com/shannon/archive/2008/07/18/149551.aspx</link><pubDate>Fri, 18 Jul 2008 13:24:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/07/18/149551.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/149551.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/07/18/149551.aspx#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/149551.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/149551.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://www.amazon.co.jp/dp/0735625301/"&gt;Windows Internals 5th Edition&lt;/A&gt;&lt;BR&gt;「インサイド Windows」の第5版。&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.amazon.co.jp/dp/0735624240/"&gt;Windows Via C/C++&lt;/A&gt;&lt;BR&gt;たぶん「Advanced Windows」の第5版。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/149551.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>Visual BasicユーザーのためのWindowsプログラミング入門</title><link>http://blogs.wankuma.com/shannon/archive/2008/06/06/141882.aspx</link><pubDate>Fri, 06 Jun 2008 09:34:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/06/06/141882.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/141882.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/06/06/141882.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/141882.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/141882.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://www.bookcyber.net/basket/detail.cgi?key=4822216810"&gt;Visual BasicユーザーのためのWindowsプログラミング入門&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.bookcyber.net/"&gt;電脳書房&lt;/A&gt;で見つけた古雑誌。思わずぽちっと購入。&lt;/P&gt;
&lt;P&gt;これはですね、タイトルに補足を入れるならば、「Visual Basic（6.0）ユーザーのためのWindows（API）プログラミング入門」です。&lt;BR&gt;冒頭から、「言語としては VB6 を使いつつ、VB6 のオブジェクトや関数は一切使わない Windows プログラム」が出てきます。もちろん、RegisterClassEx に始まり、CreateWindowEx やら GetMessage やらが出てくるあれです。&lt;BR&gt;ただひとつ、Command 関数だけは使われていたので、自分で GetCommandLine 関数に直したりしましたけど。&lt;/P&gt;
&lt;P&gt;俺が始めて「Windowsプログラミング」をやった記念すべき一冊です。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/141882.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>リンクいろいろ</title><link>http://blogs.wankuma.com/shannon/archive/2008/05/27/139629.aspx</link><pubDate>Tue, 27 May 2008 16:09:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/05/27/139629.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/139629.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/05/27/139629.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/139629.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/139629.aspx</trackback:ping><description>&lt;UL&gt;
&lt;LI&gt;ハードリンク 
&lt;LI&gt;リパースポイント 
&lt;LI&gt;シンボリックリンク 
&lt;LI&gt;ジャンクション
&lt;LI&gt;マウントポイント
&lt;LI&gt;subst&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;どう違うのー？&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/139629.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>VC++での、リンカオプションの自動設定</title><link>http://blogs.wankuma.com/shannon/archive/2008/03/24/129373.aspx</link><pubDate>Mon, 24 Mar 2008 16:56:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/03/24/129373.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/129373.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/03/24/129373.aspx#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/129373.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/129373.aspx</trackback:ping><description>&lt;P&gt;例えば&lt;FONT color=#0000ff&gt;、#define&lt;/FONT&gt; _WIN32_WINNT 0x0600 とします。&lt;BR&gt;これは、Windows Vista 以降で実装された機能を使うことの宣言であって、できたプログラムは Vista 以降でしか動かなくなります。&lt;BR&gt;この宣言をしたにもかかわらず、Vista 以降固有の機能を使っていない場合、動くこともありますが、動かないものと思っておくべきです。&lt;/P&gt;
&lt;P&gt;で、WinMain あたりで &lt;A href="http://msdn2.microsoft.com/en-us/library/ms725492.aspx"&gt;VerifyVersionInfo&lt;/A&gt; で Vista 以降かどうか判定して蹴るという方法もあるのですが、もっと楽な手もあります。&lt;BR&gt;それは、リンカオプションの &lt;A href="http://msdn2.microsoft.com/en-us/library/fcc1zstk.aspx"&gt;/SUBSYSTEM&lt;/A&gt; を利用するというものです。&lt;BR&gt;例えばこれを /SUBSYSTEM:WINDOWS,6.0 とすると、Windows 5.x では、実行しようとしたときに「有効な Win32 イメージではありません」と怒られます。&lt;/P&gt;
&lt;P&gt;んで、ちょっと前に挑戦して、うまく行かなかったこと。&lt;BR&gt;WINVER や _WIN32_WINNT シンボルの値に応じて、リンカオプションを自動的に指定できないものかと思うわけです。&lt;BR&gt;コードからリンカオプションを指定するには、&lt;FONT color=#0000ff&gt;#pragma comment&lt;/FONT&gt;( linker, "/SUBSYSTEM:WINDOWS,6.0" ) とやればいいはずです。&lt;BR&gt;この "6.0" の部分を、プリプロセッサシンボルから自動生成できないかなーというわけなのですが。&lt;/P&gt;
&lt;P&gt;どなたかご存知ありません？&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/129373.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>Win32 ファイバ</title><link>http://blogs.wankuma.com/shannon/archive/2008/03/11/127267.aspx</link><pubDate>Tue, 11 Mar 2008 17:32:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/03/11/127267.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/127267.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/03/11/127267.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/127267.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/127267.aspx</trackback:ping><description>&lt;p&gt;空気なんて読みませんよ。&lt;/p&gt; &lt;p&gt;Windows APIで、トップレベルウィンドウを列挙するサンプルコード。&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:5fdbf814-c70d-44cb-ad03-1d98bae1caad" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c"&gt;#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;tchar.h&amp;gt;
#include &amp;lt;locale.h&amp;gt;

static BOOL CALLBACK EnumWindowProc( HWND hWnd, LPARAM lParam )
{
	if( IsWindowVisible( hWnd ) )
	{
		TCHAR szTitle[ 256 ];
		GetWindowText( hWnd, szTitle, 256 );
		_tprintf( _T( "0x%08.8X, %s\n" ), hWnd, szTitle );
	}

	return TRUE;
}

static void EnumWindows1()
{
	EnumWindows( &amp;amp;EnumWindowProc, 0 );
}

int main()
{
	_tsetlocale( LC_ALL, _T( "japanese" ) );

	EnumWindows1();
	_putts( _T( "" ) );

	_putts( _T( "何かキーを押すと終了します。" ) );
	getchar();

	return 0;
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;非表示でないトップレベルウィンドウを列挙して、ウィンドウハンドル値とタイトルを表示します。&lt;br&gt;これといって特筆すべきことはありません。&lt;/p&gt;
&lt;p&gt;これを、「列挙関数を一度呼ぶごとにウィンドウハンドルを１つ返す」という形にしたいと思います。&lt;/p&gt;
&lt;p&gt;まず、ヘッダファイル。ファイル名はEnumWnd.hとします。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b0993e13-c600-4751-9b98-998687383c90" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c"&gt;#pragma once

typedef struct ENUMWND * HENUMWND;

HENUMWND BeginEnumWindows();
HWND EnumWindow( HENUMWND hEnumWnd );
void EndEnumWindows( HENUMWND hEnumWnd );&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;ハンドル型と、列挙の開始関数、ウィンドウを１つ列挙する関数、後始末関数を宣言します。&lt;/p&gt;
&lt;p&gt;続いて、ソース本体。ファイル名はEnumWnd.cppとしましょう。&lt;br&gt;制御が移っていく順番を書いてみました。「数字→」から「→数字」へジャンプします。&lt;br&gt;実行される様子を追いたい場合は、SwitchToFiberの前後にブレークポイントを置いてステップ実行するとよいでしょう。&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:65ebe579-49ad-4457-8d08-a773fadf2f2b" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c"&gt;#include &amp;lt;windows.h&amp;gt;
#include "EnumWnd.h"

struct ENUMWND
{
	LPVOID pMainFiber;
	LPVOID pEnumeratorFiber;
	HWND hwndCurrent;
};

static BOOL CALLBACK EnumWindowProc( HWND hWnd, LPARAM lParam )
{
	// →２
	HENUMWND hEnumWnd = ( HENUMWND )lParam;
	hEnumWnd-&amp;gt;hwndCurrent = hWnd;
	SwitchToFiber( hEnumWnd-&amp;gt;pMainFiber ); // →３

	// →４
	return TRUE; // 列挙中は２→、最後のウィンドウだったら５→
}

static void CALLBACK FiberProc( LPVOID pvParam )
{
	// →１
	HENUMWND hEnumWnd = ( HENUMWND )pvParam;
	EnumWindows( &amp;amp;EnumWindowProc, ( LPARAM )hEnumWnd ); // ２→

	// →５
	for( ; ; )
	{
		hEnumWnd-&amp;gt;hwndCurrent = NULL;
		SwitchToFiber( hEnumWnd-&amp;gt;pMainFiber ); // ３→
	}
}

HENUMWND BeginEnumWindows()
{
	HENUMWND hEnumWnd = new ENUMWND;
	hEnumWnd-&amp;gt;pMainFiber = ConvertThreadToFiber( NULL );
	hEnumWnd-&amp;gt;pEnumeratorFiber = CreateFiber( 0, &amp;amp;FiberProc, hEnumWnd );
	hEnumWnd-&amp;gt;hwndCurrent = NULL;

	return hEnumWnd;
}

HWND EnumWindow( HENUMWND hEnumWnd )
{
	SwitchToFiber( hEnumWnd-&amp;gt;pEnumeratorFiber ); // 初回は１→、２回目以降は４→

	// →３
	return hEnumWnd-&amp;gt;hwndCurrent;
}

void EndEnumWindows( HENUMWND hEnumWnd )
{
	DeleteFiber( hEnumWnd-&amp;gt;pEnumeratorFiber );
	ConvertFiberToThread();
	delete hEnumWnd;
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;ついでに、呼び出し側のコード。&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c15d6bf2-bd61-4d46-8fc7-f5edfce16fbb" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c"&gt;#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;tchar.h&amp;gt;
#include &amp;lt;locale.h&amp;gt;
#include "EnumWnd.h"

static void EnumWindows2()
{
	HENUMWND hEnumWnd = BeginEnumWindows();

	HWND hWnd = EnumWindow( hEnumWnd );
	while( hWnd != NULL )
	{
		if( IsWindowVisible( hWnd ) )
		{
			TCHAR szTitle[ 256 ];
			GetWindowText( hWnd, szTitle, 256 );
			_tprintf( _T( "0x%08.8X, %s\n" ), hWnd, szTitle );
		}

		hWnd = EnumWindow( hEnumWnd );
	}

	EndEnumWindows( hEnumWnd );
}

int main()
{
	_tsetlocale( LC_ALL, _T( "japanese" ) );

	EnumWindows2();
	_putts( _T( "" ) );

	_putts( _T( "何かキーを押すと終了します。" ) );
	getchar();

	return 0;
}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;BeginEnumWindowsは、データを収める構造体を確保して、中身を初期化します。&lt;br&gt;まず、呼び出し側スレッドをファイバ化します（ConvertThreadToFiber）。&lt;br&gt;次に、新しいファイバを作ります（CreateFiber）。&lt;br&gt;ファイバはスレッドと違い、作っただけでは実行を開始しません。FiberProcはまだ眠りについたまま、制御は呼び出し側（EnumWindows2）へ戻ります。&lt;/p&gt;
&lt;p&gt;EnumWindows2からEnumWindowが呼ばれます。&lt;br&gt;この中ではSwitchToFiberが呼ばれています。引数はBeginEnumWindowsで作った、FiberProcを指し示すファイバポインタなので、ここで初めて、FiberProc（１）が実行され始めます。&lt;br&gt;と同時に、EnumWindowの実行は一旦中断されます。&lt;/p&gt;
&lt;p&gt;FiberProcの中ではEnumWindows（EnumWindowではありません）が呼ばれ、制御はEnumWindowsProc（２）に移ります。&lt;br&gt;ここは何の変哲もありません。&lt;/p&gt;
&lt;p&gt;EnumWindowsProcの中で、１つウィンドウハンドルが取得できたので、呼び出し側に制御を返します。&lt;br&gt;BeginEnumWindows内でConvertThreadToFiberで作成したファイバを指定してSwitchToFiberを呼ぶことで、EnumWindowの中断していた箇所（３）に制御が戻り、同時に、EnumWindowProcの実行が一時中断されます。&lt;br&gt;EnumWindowから、呼び出し元であるEnumWindows2に戻り、非表示でなければ、ウィンドウの情報が表示されます。&lt;/p&gt;
&lt;p&gt;再度EnumWindowが呼ばれ、SwitchToFiberが呼ばれると、EnumWindowProcの中断していた箇所（４）に制御が移ります。&lt;br&gt;ウィンドウの列挙が全て完了するまで、以上の繰り返しになります。&lt;/p&gt;
&lt;p&gt;全てのウィンドウを列挙し終えると、FiberProc（５）に戻ってきます。&lt;br&gt;その後は、無限にループしているように見えますが、そうではありません。&lt;br&gt;ループ中のSwitchToFiberでEnumWindow（３）に戻り、呼び出し元のEnumWindows2では結果がNULLなのでループを中断します。&lt;br&gt;EndEnumWindowsで後始末をして、プログラムが終了します。&lt;/p&gt;
&lt;p&gt;FiberProcの中で無限ループのようなコードを書いていた理由は、29行目をコメントアウトし（forブロック全体をコメントアウトしないように）、呼び出し元のEnumWindows2で、EnumWindowがNULLを返した後、EndEnumWindowsを呼ぶ前に、もう一度だけEnumWindowを呼んでみればわかります。&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:193b9c1e-4ac4-4744-9bca-5e6f95dbc0ab" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c:firstline[22]"&gt;static void CALLBACK FiberProc( LPVOID pvParam )
{
	// →１
	HENUMWND hEnumWnd = ( HENUMWND )pvParam;
	EnumWindows( &amp;amp;EnumWindowProc, ( LPARAM )hEnumWnd ); // ２→

	// →５
	// for( ; ; )
	{
		hEnumWnd-&amp;gt;hwndCurrent = NULL;
		SwitchToFiber( hEnumWnd-&amp;gt;pMainFiber ); // ３→
	}
}&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;
&lt;div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b20077c6-cdd1-4d65-904b-96f041f0a7f6" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;&lt;pre name="code" class="c"&gt;void EnumWindows2()
{
	HENUMWND hEnumWnd = BeginEnumWindows();

	HWND hWnd = EnumWindow( hEnumWnd );
	while( hWnd != NULL )
	{
		if( IsWindowVisible( hWnd ) )
		{
			TCHAR szTitle[ 256 ];
			GetWindowText( hWnd, szTitle, 256 );
			_tprintf( _T( "0x%08.8X, %s\n" ), hWnd, szTitle );
		}

		hWnd = EnumWindow( hEnumWnd );
	}

	// もう一度呼んでみる
	hWnd = EnumWindow( hEnumWnd );

	EndEnumWindows( hEnumWnd );
}&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;mainで、何かキーを押すまで終了を待機しているはずなのに、19行目のEnumWindowの呼び出しから戻ることなく、プログラムが終了してしまいます。&lt;/p&gt;
&lt;p&gt;このプログラムには、ファイバは２つありますが、スレッドは１つしかありません。&lt;br&gt;スレッドが終了するには、ExitThreadを呼ぶか、スレッドプロシージャからreturnしますね。&lt;br&gt;さて、このプログラムのスレッドプロシージャはドコでしょうか？&lt;/p&gt;
&lt;p&gt;FiberProcには、呼び出し元がありません。&lt;br&gt;EnumWindow内のSwitchToFiberから呼び出されているようにも見えますが、それは１回目だけです。&lt;br&gt;２回目以降は、いきなりFiberProc（から呼ばれているEnumWindowProc）の途中から始まります。&lt;/p&gt;
&lt;p&gt;呼び出し元がないのですから、帰る先もありません。&lt;br&gt;おわかりでしょうか。&lt;br&gt;このプログラムには、mainの最後とFiberProcの最後、スレッドプロシージャの終了地点が２つあるのです。&lt;br&gt;どちらかからreturnすれば、スレッドは終了してしまいます。&lt;br&gt;だから、FiberProcからは決してreturnしないように、無限ループのようなfor文を書いているのです。&lt;br&gt;FiberProc自体には戻り値がないのも、returnすることがないからでしょう。&lt;/p&gt;
&lt;p&gt;最後に余談。&lt;br&gt;このプログラムにはスレッドが１つしかありませんが、マルチスレッドとファイバの組み合わせも面白いものがあります。&lt;br&gt;CreateFiberで作ったファイバは、CreateFiberの呼び出し元のスレッドに関連付けられません。&lt;br&gt;CreateFiberを呼んだスレッドと、そのファイバに制御を移すためのSwitchToFiberを呼ぶスレッドは異なっていてもかまいません。&lt;br&gt;ファイバは、SwitchToFiberの呼び出し側のスレッドで実行されます。&lt;br&gt;そのため、１つのファイバを実行するスレッドを複数用意して切り替えることができます。&lt;br&gt;ただし、複数のスレッドから同時に１つのファイバにアクセスすることはできません。&lt;/p&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/127267.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>循環参照するDLLのビルド</title><link>http://blogs.wankuma.com/shannon/archive/2008/01/30/119987.aspx</link><pubDate>Wed, 30 Jan 2008 15:54:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/01/30/119987.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/119987.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/01/30/119987.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/119987.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/119987.aspx</trackback:ping><description>&lt;P align=center&gt;&lt;FONT color=#ff0000 size=6&gt;循環参照なんてするな！　終わり。&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;#8230;では怒られるので。&lt;/P&gt;
&lt;P&gt;２つのDLL、Hoge.dllとPiyo.dllがあるとします。&lt;BR&gt;Hoge.dllはPiyo.dllの関数を呼び、Piyo.dllはHoge.dllの関数を呼ぶ。&lt;BR&gt;しかもどちらも暗黙リンクで、GetProcAddressはしたくないという困ったちゃんだとします。&lt;/P&gt;
&lt;P&gt;想定に無理があるのは承知です。&lt;BR&gt;そもそも循環参照した時点で無茶なので、その辺は目をつぶってください。&lt;/P&gt;
&lt;P&gt;で、こういうビルド、実はできます。&lt;BR&gt;Hoge.dllをビルドするときにPiyo.dllは必要ではなく、必要なのはPiyo.libであるというのがミソです。&lt;BR&gt;要は、Piyo.dllとは別にPiyo.libだけ先にビルドできれば良いわけです。&lt;/P&gt;
&lt;P&gt;というわけで、やってみましょう。&lt;/P&gt;
&lt;P&gt;１：Piyo.libのビルド&lt;BR&gt;Piyo.libのビルドに必要なのは、実はPiyo.defだけです。ソースコードすら要りません。&lt;BR&gt;ビルドには、VC++に添付のlib.exeを使います。こんな感じ。&lt;/P&gt;
&lt;P class=cmdprompt&gt;&lt;KBD&gt;lib /DEF:Piyo.def /MACHINE:X86 /OUT:Piyo.lib&lt;/KBD&gt;&lt;/P&gt;
&lt;P&gt;これで、カレントディレクトリにPiyo.libとPiyo.expができます。&lt;/P&gt;
&lt;P&gt;２：Hoge.dllとHoge.libのビルド&lt;BR&gt;こっちは普通にやればいいです。IDEからもできますが、コマンドラインでやってみましょう。&lt;/P&gt;
&lt;P class=cmdprompt&gt;&lt;KBD&gt;cl /c /FoHoge.obj Hoge.cpp&lt;/KBD&gt;&lt;BR&gt;&lt;KBD&gt;link /DEF:Hoge.def /DLL /IMPLIB:Hoge.lib /MACHINE:X86 /OUT:Hoge.dll Hoge.obj Piyo.lib&lt;/KBD&gt;&lt;/P&gt;
&lt;P&gt;最後に Piyo.lib を付け加えています。&lt;BR&gt;これで、Hoge.dll、Hoge.lib、Hoge.expができます。&lt;/P&gt;
&lt;P&gt;３：Piyo.dllのビルド&lt;BR&gt;Piyo.defの代わりにPiyo.expを使うのがポイントです。&lt;/P&gt;
&lt;P class=cmdprompt&gt;&lt;KBD&gt;cl /c /FoPiyo.obj Piyo.cpp&lt;/KBD&gt;&lt;BR&gt;&lt;KBD&gt;link /DLL /MACHINE:X86 /OUT:Piyo.dll Piyo.obj Hoge.lib Piyo.exp&lt;/KBD&gt;&lt;/P&gt;
&lt;P&gt;晴れて循環参照がクリアできました。&lt;BR&gt;ちなみに、エクスポートする関数には明示的に extern "C" をつける必要があるので注意してください。&lt;/P&gt;
&lt;P&gt;なお、改めて言わなくてもわかってると思いますが、これは興味本位で調べたことであって、そもそもやるべきことではありません。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/119987.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>PEファイルの謎</title><link>http://blogs.wankuma.com/shannon/archive/2008/01/27/119466.aspx</link><pubDate>Sun, 27 Jan 2008 17:59:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/01/27/119466.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/119466.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/01/27/119466.aspx#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/119466.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/119466.aspx</trackback:ping><description>&lt;P&gt;PEファイルについて調べてます。&lt;BR&gt;んで、わからないことが数点。&lt;/P&gt;
&lt;P&gt;その１：隠しリンカオプション&lt;BR&gt;VC++ 2008のリンカオプションはMSDNに&lt;A href="http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx"&gt;一覧&lt;/A&gt;があるが、ここに書かれていないオプションが少なくとも一つある。&lt;BR&gt;/INTEGRITYCHECKというのがそれで、これを指定してリンクすると、PEヘッダのIMAGE_OPTIONAL_HEADER.DllCharacteristicsにIMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITYビットが含まれる。&lt;BR&gt;が、このファイルがどういうわけか実行できない。&lt;BR&gt;このフラグは何のためにあるのだろう？&lt;/P&gt;
&lt;P&gt;その２：セクション属性&lt;BR&gt;PEファイル中のセクションの属性は、&lt;A href="http://msdn2.microsoft.com/en-us/library/ms680341.aspx"&gt;IMAGE_SECTION_HEADER構造体&lt;/A&gt;に含まれる。&lt;BR&gt;こいつのCharacteristicsメンバに含まれるフラグのなかに、意味がよくわからないものがある。&lt;BR&gt;列挙すると、IMAGE_SCN_NO_DEFER_SPEC_EXC、IMAGE_SCN_LNK_NRELOC_OVFL、IMAGE_SCN_MEM_DISCARDABLE、IMAGE_SCN_MEM_NOT_CACHED、IMAGE_SCN_MEM_NOT_PAGEDの５つ。&lt;BR&gt;どれも、ビットが立っているとどういう挙動をするのかがよくわからない。&lt;BR&gt;最初の２つは、どうすればこのビットが立つのかもわからない。&lt;/P&gt;
&lt;P&gt;ご存知の方がいらっしゃいましたら、教えてくださると幸いです。&lt;BR&gt;なお、現在、x86とx64アーキテクチャ上での、いわゆるDLLとEXEのみを対象として調べており、他のアーキテクチャ用だとか、「カーネルモードドライバでしか縁のないフラグ」とかには興味がありません。&lt;BR&gt;ので、上に挙げたようなものが、もしそうしたものであったら、詳細なしでも構いません。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/119466.aspx" width = "1" height = "1" /&gt;</description></item><item><dc:creator>シャノン</dc:creator><title>Detours</title><link>http://blogs.wankuma.com/shannon/archive/2008/01/12/117158.aspx</link><pubDate>Sat, 12 Jan 2008 16:21:00 GMT</pubDate><guid>http://blogs.wankuma.com/shannon/archive/2008/01/12/117158.aspx</guid><wfw:comment>http://blogs.wankuma.com/shannon/comments/117158.aspx</wfw:comment><comments>http://blogs.wankuma.com/shannon/archive/2008/01/12/117158.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.wankuma.com/shannon/comments/commentRss/117158.aspx</wfw:commentRss><trackback:ping>http://blogs.wankuma.com/shannon/services/trackbacks/117158.aspx</trackback:ping><description>&lt;P&gt;&lt;A href="http://research.microsoft.com/sn/detours/"&gt;http://research.microsoft.com/sn/detours/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;MS製のDLLインジェクションライブラリですか？&lt;/P&gt;
&lt;P&gt;なんか面白そう。&lt;/P&gt;&lt;img src ="http://blogs.wankuma.com/shannon/aggbug/117158.aspx" width = "1" height = "1" /&gt;</description></item></channel></rss>