Wine; MSDN Library October 2001 (英語版) のインストール法(how to install MSDN Library in Wine)

[目次] (https://qiita.com/Yutaka_Aoki/items/9d38ea98406f4096435b)

[English Version (Translated from Japanese to English)] (https://qiita.com/Yutaka_Aoki/items/a145f5499f5d1894b8c4)

# Inside Wine; MSDN Library October 2001 (英語版) のインストール方法

最初に結論を言っておく。

1. 以下の方法を取れば、CD 3枚の「Full Install」に成功し、MSDN Library の HTML HELP の基本機能は完全に利用できるようになる。
2. 具体的には、内容の表示、目次の表示、キーワード検索(Index)(インクリメンタル検索も正常)、(全文)検索、目次の同期、独自サブセットの設定が出来る。
3. 今、分かっている不具合
  1. 「戻る」ボタンや、「Back space」キーで、「戻る」機能が全く働かないらしい。
  2. 左のエディット・ボックスの下のリスト領域の表示が更新されないことがある。その場合、ヘッダ部分の別のタブ・ボタンを押してから戻ると正常に更新される。
  3. デフォルトのフォントが小さすぎる上に、表示-フォント の中の最大、大、中、小、最小の項目が全て無効表示になってしまっている。これに関しては、CHM ファイルの圧縮を解き、いったん、HTMLに戻して css や style を修正して、CHM を作り直す、という手方が昔から知られている。

## 取り急ぎ報告まで(2018/03/04)

該当の *.ocx と *.dll を本家 Windows の c:\windows\system32 から、 .wine の system32 にコピーしておいて、下のスクリプトを使って Help を起動すると、ほとんどの不具合が起きなくなりました。今までは、飛べないリンクが有ったのですが、実験する限り、飛べるようになった様です。つまり、スクリプト方式のリンクも正常動作するようになった、ということです。


```bash:
#!/bin/bash

WINEDLLOVERRIDES='hhctrl.ocx=n'
WINEDLLOVERRIDES+=';comctl32=n'
WINEDLLOVERRIDES+=';mshtml=n'
WINEDLLOVERRIDES+=';shlwapi=n'
WINEDLLOVERRIDES+=';wininet=n'
WINEDLLOVERRIDES+=';urlmon=n'
WINEDLLOVERRIDES+=';itss=n'
WINEDLLOVERRIDES+=';shdocvw=n'

export WINEDLLOVERRIDES

wine /media/Xxxx/WINDOWS/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL
```



## 取り急ぎ報告まで(2018/03/03)

以前は、次のような不具合がありました。

「 左のペーンで Index Tab を選択し、キーワードを Edit Box に入れた後、出てきた候補一覧の中から一行を選択した後に、さらに候補が複数ある時に出てくるダイアログボックスで、さらに選択をした場合に発生する。この最後の選択で、どれを選択しても、最も最初の候補が右のペーンに表示されてしまう。

例えば、検索キーワードとして、SetFocus と入れると、COleControl::SetFocs 関連のものしか表示できない。故にキーワード検索からは、::SetFocus などを表示する事は難しい。」

これは、次の様にすると直ることが判明しました。

・本家 Windows の sytem32 から、comctrl32.dll を .wine の system32 へコピーし、native を使う設定に指定してから hh.exe を起動する。


### 原因

最も単純に考えれば、`c:~/wine/dlls/comctl32/listview.c` の LISTVIEW_GetNextItem() 関数が正しい戻り値を返して来ないことではないかと推定されます。


-----------------------------

以下では、「Full Install」の場合を説明する。

## 光学ドライブのマウントの準備

/etc/fstab に、光学ドライブ(BD, DVD, CDなど)のマウント情報を書いておきます。これは、必須では無いのですが、コマンドラインが楽になるため、今回は書いておきます。

ただし、この副作用として、Ubuntu の起動時に、ドライブにマウントできずに待機状態になるため、「s」キーを押さなくてはならなくなります（だから、スクリプトか、bash の alias 機能を使った方がいいかも知れません。）。


ここで、/mnt/dvd というフォルダが既にあることを確認しておきます。なければ、

```
$ sudo mkdir /mnt/dvd
```

として作成しておきます。次に、


```
$ sudo gedit /etc/fstab
```

として、/etc/fstab に以下の最後にある行を追加しておきます。

```
# <file system> <mount point>   <type>  <options>       <dump>  <pass>

# *中略*

/dev/sr0        /mnt/dvd       iso9660   ro,user,auto  0       0
```


## インストール手順

### 1. CD-ROM を光学ドライブへ挿入

MSDN Library の CD-ROM を光学ドライブへ挿入します。

### 2. 光学ドライブへマウント

```
$ sudo mount /mnt/dvd
```

とします。

### 3. 光学ドライブにドライブ文字 F: を割り当てる。

```
$ winecfg
```

として、例えば、Windows の 「F:」ドライブに、/mnt/dvd を割り当てておく。

### 4. カレントディレクトリ変更


```
$ cd /mnt/dvd
```

として、カレントディレクリを光学ドライブにしておきます。

### 5. MSDN Libray のインストーラーを起動

```
$ wine setup.exe
```

とする。インストーラーが起動するので、いくつかの質問に答えて、インストール先を指定する。以下ではインストール先を 「e:/MSDN」 にしていることを前提にする。


「Full Install」のボタンを押すと、CD-1 から、インストール先へのファイルのコピーが始まる。


### 6. フォント関連のエラーのダイアログが出る。

これは、Wine のエミュレーターが出していて、インストーラー自身は関与していないらしい。

「無視する」（みたいな）ボタンを押す。インストールは終わらずにそのまま続行する。


### 7. CD-2 へのメディア交換

メディア交換を促すダイアログが出たら、以下の通りにやる。この通りにやらないと、上手く行かないかもしれない。

まず、新しい端末を起動する。Ubuntu の場合、左の縦のタスクバーの端末のアイコンを右クリックし、「新しい端末」を選ぶ。そこで、

```
$ wine eject f:
```

とする。光学ドライブのトレイが「イジェクト」され、CD-1 のメディアが出てくる。メディアを CD-2 に交換し、トレイを指で押して、メディアをドライブに入れる。

再度、

```
$ sudo mount /mnt/dvd
```

とする。

その後、インストーラーの「CD-2を入れてください(<---英語)」のダイアログの「続行（みたいな）」ボタンを押す。


### 8. CD-3 についても同じ事を繰り返す。

### 9. インストールが終了する。


デスクトップにアイコンも作成される。本当の問題は、起動である。


## 現状、どうなってるかの確認

この状態で、コマンドラインから、

```
$ wine hh e:/MSDN/2001OCT/1033/MSDN130.COL
```

としてみると、

01bd:err:htmlhelp:doWinMain Failed to open HTML Help file 'e:/MSDN/2001OCT/1033/MSDN130.COL'.


と出て起動できない。次節で対処法を述べる。


## コマンドラインからの起動法

以下のようにするとコマンドラインから起動できるようになる。最初に、

```
$ cd ~/.wine/dirve_c/windows/system32
```

とする。本家 Windows の 「?:/windows/system32」 にある

```c:?/windows/system32
hhctrl.ocx
```

をカレントディレクトリ ( ~/.wine/dirve_c/windows/system32 ) にコピーする。これは、Nautilus から行っても、cp コマンドで行っても良い。

コピー後、

リンク : [本物の regsvr32 を使う] (https://qiita.com/Yutaka_Aoki/items/9655d714519797967c2e)

を読んで、本家 Windows の regsvr32 を使えるようにしておく。そして、


```
wine /media/XXXXX/WINDOWS/system32/regsvr32.exe hhctrl.ocx
```

とする。/media/XXXXX の部分には、本家の Windows ドライブの Linux におけるパス名を書く。

これで、hhctrl.ocx を (Wine上の)Windows の COM SERVER に登録する。


次に、

```
$ export WINEDLLOVERRIDES=hhctrl.ocx=n
```

として、環境変数 WINEDLLOVERRIDES を設定し、hhctrl.ocx について、Wine 版(Built-in)ではなくWindows 本家(Native)版を使うように設定する。

その後、

```
$ wine hh e:/MSDN/2001OCT/1033/MSDN130.COL
```

としてみると、MSDN Library Otober 2001 (英語版) が起動することが分かる。

## デスクトップ・アイコンからの起動法

デスクトップのアイコンを右クリックしてプロパティーを見てみると、

コマンド欄が以下のようになっている:

`env WINEPREFIX="/home/taro-yamada/.wine" wine C:\\windows\\hh.exe e:\\MSDN\\2001OCT\\1033\\MSDN130.COL`

「taro-yamada」の部分は、login 名(?)なので、今の自分の login 名(?)が出る。


これを、以下の様に直す:

`env WINEPREFIX="/home/taro-yamada/.wine" WINEDLLOVERRIDES=hhctrl.ocx=n wine C:\\windows\\hh.exe e:\\MSDN\\2001OCT\\1033\\MSDN130.COL`

これで、アイコンをクリックしてみると、起動できる事が分かる。



## 参考： hhctrl.ocx の UUID


リンク: (http://www.nongnu.org/chmspec/latest/Miscellaneous.html#GUIDs_HHCtrl_SystemSort)

に

```
6.1.4. {4662DAB0-D393-11D0-9A56-00C04FB68B66}

From: $OBJINST internal file.
InprocServer32: HHCTRL.OCX
ThreadingModel: Both
VersionIndependentProgID: HHCtrl.SystemSort
ProgID: HHCtrl.SystemSort.666
```

とある。


# キーワード検索で、2番目以降の候補を表示できない不具合について

## MS製 Spy++ を使って調査

まず、MSDN Library の HTML HELP を表示しておいて、

`c:/Program Files/Microsoft Visual Studio/Common Tools`

で、

```
$ wine spyxx
```
として、Spy++ を起動して調査。

HTML HELP の左側のペーンの、

「キーワード(N)」タブの、「キーワードを入力してください(W)」エディット・ボックスに「SetFocus」と入れ、Enter キーを押す。

「該当するトピック」というタイトルのダイアログ・ボックスが出て、中身の一番上に
「トピックをクリックしてから、[表示] をクリックしてください(T)」と表示される。この時、リストボックスのヘッダ部分が 「タイトル」「場所」で、中身が

```
COleDontrol::SetFocus	Microsoft Foundation Class Library and Templates
CWindow::SetFocus		Microsoft Foundation Class Library and Templates
CWnd::SetFocus			Microsoft Foundation Class Library and Templates
SetFocus				Windows User Interface: Platform SDK
SetFocus Method			Visual Stduio Environment
```
であり、一番下の右端に 「表示(D)」「キャンセル」ボタンがある。

Spy++ では、

```
-□000F005C "該当するトピック" #32770 (ダイアログ)
 - □000D01A6 "List1" SysListView32
     □000C01A0 "" SysHeader32
   □00130138 "表示(&D)" Button
   □000F00CC "キャンセル" Button
   □0002022A "トピックをクリックしてから、[表示] をクリックしてください(&T)" Static
```

と表示される。つまり、この「トピック」の一覧表示に使われているのは、クラス名が"SysListView32"、即ち、「WC_LISTVIEW」クラスのコントロールで、MFC で言うと CListCtrl である。

Wine で言うと :

```c:
source:    ~/wine/dlls/comctl32/listview.c
classname: WC_LISTVIEW : "SysListView32"
func:      LISTVIEW_WindowProc
```

である。ここで、選択候補の内、4行目の

```
SetFocus				Windows User Interface: Platform SDK
```

を選択したとする。


この時、プログラム目線では、選択 Item を取得する1つの方法は、MFC では以下の関数である。ただし、他にも例えば、親ウィンドウへの通知メッセージや、CustomDraw のコールバック関数など、様々な方法がある。

```c:
int CListCtrl::GetNextItem(int nItem, int nFlags) const
	{ ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0)); }

POSITION CListCtrl::GetFirstSelectedItemPosition() const
	{ ASSERT(::IsWindow(m_hWnd)); return (POSITION) (1+GetNextItem(-1, LVIS_SELECTED)); }

int CListCtrl::GetNextSelectedItem(POSITION& pos) const
	{ ASSERT(::IsWindow(m_hWnd)); int nOldPos = (int)pos-1; pos = (POSITION) (1+GetNextItem(nOldPos, LVIS_SELECTED)); return nOldPos; }
```

見て分かるように、これらの MFC の関数は、LVM_GETNEXTITEM メッセージを、WPARAM を LVIS_SELECTED にして SendMessage することが本質である。

ここで、

1. もし、選択位置として「0」が返されたとしたなら、この異常は説明できる。
2. 「3」が返されたとしても、その後の処理で、何らかの問題が生じて「0」に変化した(?)としても、この異常を説明できる。



```c:~/wine/dlls/comctl32/listview.c
static INT LISTVIEW_GetNextItem(const LISTVIEW_INFO *infoPtr, INT nItem, UINT uFlags)
{
    UINT uMask = 0;
    LVFINDINFOW lvFindInfo;
    INT nCountPerColumn;
    INT nCountPerRow;
    INT i;

    TRACE("nItem=%d, uFlags=%x, nItemCount=%d\n", nItem, uFlags, infoPtr->nItemCount);
    if (nItem < -1 || nItem >= infoPtr->nItemCount) return -1;

    ZeroMemory(&lvFindInfo, sizeof(lvFindInfo));

    if (uFlags & LVNI_CUT)
      uMask |= LVIS_CUT;

    if (uFlags & LVNI_DROPHILITED)
      uMask |= LVIS_DROPHILITED;

    if (uFlags & LVNI_FOCUSED)
      uMask |= LVIS_FOCUSED;

    if (uFlags & LVNI_SELECTED)
      uMask |= LVIS_SELECTED;

    /* if we're asked for the focused item, that's only one, 
     * so it's worth optimizing */
    if (uFlags & LVNI_FOCUSED)
    {
	if ((LISTVIEW_GetItemState(infoPtr, infoPtr->nFocusedItem, uMask) & uMask) != uMask) return -1;
	return (infoPtr->nFocusedItem == nItem) ? -1 : infoPtr->nFocusedItem;
    }
    
    if (uFlags & LVNI_ABOVE)
    {
      if ((infoPtr->uView == LV_VIEW_LIST) || (infoPtr->uView == LV_VIEW_DETAILS))
      {
        while (nItem >= 0)
        {
          nItem--;
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
      else
      {
        /* Special case for autoarrange - move 'til the top of a list */
        if (is_autoarrange(infoPtr))
        {
          nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr);
          while (nItem - nCountPerRow >= 0)
          {
            nItem -= nCountPerRow;
            if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
              return nItem;
          }
          return -1;
        }
        lvFindInfo.flags = LVFI_NEARESTXY;
        lvFindInfo.vkDirection = VK_UP;
        LISTVIEW_GetItemPosition(infoPtr, nItem, &lvFindInfo.pt);
        while ((nItem = LISTVIEW_FindItemW(infoPtr, nItem, &lvFindInfo)) != -1)
        {
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
    }
    else if (uFlags & LVNI_BELOW)
    {
      if ((infoPtr->uView == LV_VIEW_LIST) || (infoPtr->uView == LV_VIEW_DETAILS))
      {
        while (nItem < infoPtr->nItemCount)
        {
          nItem++;
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
      else
      {
        /* Special case for autoarrange - move 'til the bottom of a list */
        if (is_autoarrange(infoPtr))
        {
          nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr);
          while (nItem + nCountPerRow < infoPtr->nItemCount )
          {
            nItem += nCountPerRow;
            if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
              return nItem;
          }
          return -1;
        }
        lvFindInfo.flags = LVFI_NEARESTXY;
        lvFindInfo.vkDirection = VK_DOWN;
        LISTVIEW_GetItemPosition(infoPtr, nItem, &lvFindInfo.pt);
        while ((nItem = LISTVIEW_FindItemW(infoPtr, nItem, &lvFindInfo)) != -1)
        {
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
    }
    else if (uFlags & LVNI_TOLEFT)
    {
      if (infoPtr->uView == LV_VIEW_LIST)
      {
        nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr);
        while (nItem - nCountPerColumn >= 0)
        {
          nItem -= nCountPerColumn;
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
      else if ((infoPtr->uView == LV_VIEW_SMALLICON) || (infoPtr->uView == LV_VIEW_ICON))
      {
        /* Special case for autoarrange - move 'til the beginning of a row */
        if (is_autoarrange(infoPtr))
        {
          nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr);
          while (nItem % nCountPerRow > 0)
          {
            nItem --;
            if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
              return nItem;
          }
          return -1;
        }
        lvFindInfo.flags = LVFI_NEARESTXY;
        lvFindInfo.vkDirection = VK_LEFT;
        LISTVIEW_GetItemPosition(infoPtr, nItem, &lvFindInfo.pt);
        while ((nItem = LISTVIEW_FindItemW(infoPtr, nItem, &lvFindInfo)) != -1)
        {
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
    }
    else if (uFlags & LVNI_TORIGHT)
    {
      if (infoPtr->uView == LV_VIEW_LIST)
      {
        nCountPerColumn = LISTVIEW_GetCountPerColumn(infoPtr);
        while (nItem + nCountPerColumn < infoPtr->nItemCount)
        {
          nItem += nCountPerColumn;
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
      else if ((infoPtr->uView == LV_VIEW_SMALLICON) || (infoPtr->uView == LV_VIEW_ICON))
      {
        /* Special case for autoarrange - move 'til the end of a row */
        if (is_autoarrange(infoPtr))
        {
          nCountPerRow = LISTVIEW_GetCountPerRow(infoPtr);
          while (nItem % nCountPerRow < nCountPerRow - 1 )
          {
            nItem ++;
            if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
              return nItem;
          }
          return -1;
        }
        lvFindInfo.flags = LVFI_NEARESTXY;
        lvFindInfo.vkDirection = VK_RIGHT;
        LISTVIEW_GetItemPosition(infoPtr, nItem, &lvFindInfo.pt);
        while ((nItem = LISTVIEW_FindItemW(infoPtr, nItem, &lvFindInfo)) != -1)
        {
          if ((LISTVIEW_GetItemState(infoPtr, nItem, uMask) & uMask) == uMask)
            return nItem;
        }
      }
    }
    else
    {
      nItem++;

      /* search by index */
      for (i = nItem; i < infoPtr->nItemCount; i++)
      {
        if ((LISTVIEW_GetItemState(infoPtr, i, uMask) & uMask) == uMask)
          return i;
      }
    }

    return -1;
}

static UINT LISTVIEW_GetItemState(const LISTVIEW_INFO *infoPtr, INT nItem, UINT uMask)
{
    LVITEMW lvItem;

    if (nItem < 0 || nItem >= infoPtr->nItemCount) return 0;

    lvItem.iItem = nItem;
    lvItem.iSubItem = 0;
    lvItem.mask = LVIF_STATE;
    lvItem.stateMask = uMask;
    if (!LISTVIEW_GetItemW(infoPtr, &lvItem)) return 0;

    return lvItem.state & uMask;
}
```



## リンク先へ飛べない不具合の原因について。

MSDN Library 内の Win32 API の SetFocus() の HTML のソースを調べます。


### ソースの調べ方

本家 Window を起動し、Microsoft HTML Help Workshop 4.74.8702.0, 1996-1999 を用いて、

```
winui.chm
```

を 「decompile」する。出力先として aaa フォルダを指定する。すると、


/xxx/aaa/hh/winui/keybinpt_8yb7.htm

が出来ていて、その中に Win32 API の SetFocus() の(Main)項目がある。

### 実際の SetFocus() の項目のソース


```html:/aaa/hh/winui/keybinpt_8yb7.htm
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML DIR="LTR"><HEAD>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=Windows-1252">
<TITLE>SetFocus</TITLE>
<SCRIPT SRC="../linkcss.js"></SCRIPT>
<SCRIPT SRC="../langref.js"></SCRIPT>
<META NAME="MS-HKWD" CONTENT="SetFocus">
</HEAD>
<BODY TOPMARGIN="0">
<DIV STYLE="display:none;">
<OBJECT ID="hhobj_1" TYPE="application/x-oleobject" CLASSID="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
	<PARAM NAME="Command" VALUE="ALink,MENU">
	<PARAM NAME="DefaultTopic" VALUE="../notopic_0pk4.htm">
	<PARAM NAME="Item1" VALUE="">
	<PARAM NAME="Item2" VALUE="_win32_getlasterror">
</OBJECT>
<OBJECT ID="hhobj_2" TYPE="application/x-oleobject" CLASSID="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
	<PARAM NAME="Command" VALUE="ALink,MENU">
	<PARAM NAME="DefaultTopic" VALUE="../notopic_0pk4.htm">
	<PARAM NAME="Item1" VALUE="">
	<PARAM NAME="Item2" VALUE="_psdk_requirements">
</OBJECT>
<OBJECT ID="hhobj_3" TYPE="application/x-oleobject" CLASSID="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
	<PARAM NAME="Command" VALUE="ALink,MENU">
	<PARAM NAME="DefaultTopic" VALUE="../notopic_0pk4.htm">
	<PARAM NAME="Item1" VALUE="">
	<PARAM NAME="Item2" VALUE="_win32_attachthreadinput">
</OBJECT>
</DIV>


<TABLE CLASS="buttonbarshade" CELLSPACING=0><TR><TD>&nbsp;</TD></TR></TABLE>
<TABLE CLASS="buttonbartable" CELLSPACING=0>
<TR ID="hdr"><TD CLASS="runninghead" NOWRAP>Platform&nbsp;SDK:&nbsp;Windows&nbsp;User&nbsp;Interface</TD></TR>
</TABLE>

<H1><A NAME="_win32_setfocus"></A>SetFocus</H1>

<P>The <B>SetFocus</B> function sets the keyboard focus to the specified window. The window must be attached to the calling thread's message queue. </P>

<PRE class=syntax><B>HWND SetFocus(
  HWND</B><I> hWnd</I>   // handle to window
<B>);</B></PRE>

<H4>Parameters</H4>

<DL>
<DT><I>hWnd</I></DT>

<DD>[in] Handle to the window that will receive the keyboard input. If this parameter is NULL, keystrokes are ignored. 
</DD>
</DL>

<H4>Return Values</H4>

<P>If the function succeeds, the return value is the handle to the window that previously had the keyboard focus. If the <I>hWnd</I> parameter is invalid or the window is not attached to the calling thread's message queue, the return value is NULL. To get extended error information, call <A HREF="JavaScript:hhobj_1.Click()"><B>GetLastError</B></A>.</P>

<H4>Remarks</H4>

<P>The <B>SetFocus</B> function sends a <B>WM_KILLFOCUS</B> message to the window that loses the keyboard focus and a <B>WM_SETFOCUS</B> message to the window that receives the keyboard focus. It also activates either the window that receives the focus or the parent of the window that receives the focus. </P>

<P>If a window is active but does not have the focus, any key pressed will produce the <B>WM_SYSCHAR</B>, <B>WM_SYSKEYDOWN</B>, or <B>WM_SYSKEYUP</B> message. If the VK_MENU key is also pressed, the <I>lParam</I> parameter of the message will have bit 30 set. Otherwise, the messages produced do not have this bit set. </P>

<P>By using the <B>AttachThreadInput</B> function, a thread can attach its input processing to another thread. This allows a thread to call <B>SetFocus</B> to set the keyboard focus to a window attached to another thread's message queue. </P>

<P>For an example, see <A HREF="dlgboxes_1s1k.htm">Initializing a Dialog Box</A>. </P>

<H4><A HREF="JavaScript:hhobj_2.Click()">Requirements</A> </H4>

<P><B>&nbsp;&nbsp;Windows NT/2000 or later: </B>Requires Windows NT 3.1 or later.<BR>
<B>&nbsp;&nbsp;Windows 95/98/Me: </B>Requires Windows 95 or later.<BR>
<B>&nbsp;&nbsp;Header: </B>Declared in Winuser.h; include Windows.h.<BR>
<B>&nbsp;&nbsp;Library: </B>Use User32.lib.</P>

<H4>See Also</H4>

<P><A HREF="keybinpt_4l9w.htm">Keyboard Input Overview</A>, <A HREF="keybinpt_43jn.htm">Keyboard Input Functions</A>, <A HREF="JavaScript:hhobj_3.Click()"><B>AttachThreadInput</B></A>, <A HREF="keybinpt_6ppv.htm"><B>GetFocus</B></A>, <A HREF="keybinpt_9sc3.htm"><B>WM_KILLFOCUS</B></A>, <A HREF="keybinpt_2ldf.htm"><B>WM_SETFOCUS</B></A>, <A HREF="keybacel_125u.htm"><B>WM_SYSCHAR</B></A>, <A HREF="keybinpt_1yjy.htm"><B>WM_SYSKEYDOWN</B></A>, <A HREF="keybinpt_9upc.htm"><B>WM_SYSKEYUP</B></A> </P>
<DIV CLASS="footer">Microsoft Platform SDK, February 2001 Edition.<BR>This content last built on Thursday, February 01, 2001.<BR>&nbsp;</DIV>

</BODY>
</HTML>
```

### 飛べないリンクの例

上の方にある「GetLastError」:

```html:
<A HREF="JavaScript:hhobj_1.Click()"><B>GetLastError</B></A>.</P>
```

下の方にある「AttachThreadInput」:

```html:
<A HREF="JavaScript:hhobj_3.Click()"><B>AttachThreadInput</B></A>
```


### 飛べるリンクの例


下の方にある「GetFocus」:

```html:
<A HREF="keybinpt_6ppv.htm"><B>GetFocus</B></A>
```


下の方にある「WM_SETFOCUS」:

```html:
<A HREF="keybinpt_2ldf.htm"><B>WM_SETFOCUS</B></A>
```

### 関連ソース

```html:
<OBJECT ID="hhobj_1" TYPE="application/x-oleobject" CLASSID="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
	<PARAM NAME="Command" VALUE="ALink,MENU">
	<PARAM NAME="DefaultTopic" VALUE="../notopic_0pk4.htm">
	<PARAM NAME="Item1" VALUE="">
	<PARAM NAME="Item2" VALUE="_win32_getlasterror">
</OBJECT>
・・・
<OBJECT ID="hhobj_3" TYPE="application/x-oleobject" CLASSID="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
	<PARAM NAME="Command" VALUE="ALink,MENU">
	<PARAM NAME="DefaultTopic" VALUE="../notopic_0pk4.htm">
	<PARAM NAME="Item1" VALUE="">
	<PARAM NAME="Item2" VALUE="_win32_attachthreadinput">
</OBJECT>
```

### 原因推定

リンクへ飛べる場合と飛べない場合を比較すると、HTML 内の java script 関連の不具合が疑われる。つまり、Wine では、上記の場合に java script の実行が上手く行っていない可能性が高い。







### ieframe.dll

.wine の system32 に色々な native dll をコピーして試していたところ、次のような事を発見。

ieframe.dll は、native のものを .wine の system32 置いておくだけで 右のペーンが真っ白になってしまう。それは、native をロードする指定をしていなくても。


### itircl.dll

itircl.dll は、何もしていしていなくても、なぜか、「native」がロードされているらしい。

0207:trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\itircl.dll" at 0x20410000: builtin
0207:trace:loaddll:free_modref Unloaded module L"C:\\windows\\system32\\itircl.dll" : builtin
0207:trace:loaddll:load_native_dll Loaded L"C:\\windows\\system32\\itircl.dll" at 0x5d500000: native


### 調査した dll 群


```
itss.dll
jscript.dll
shdocvw.dll
msls31.dll
mshtml.dll
jscript.dll
ieframe.dll
advapi32.dll
shlwapi.dll
urlmon.dll
msvcrt.dll
rpcrt4.dll
iphlpapi.dll
netapi32.dll
secur32.dll
version.dll
wininet.dll
itircl.dll
shell32.dll
usp10.dll
ole32.dll
oleaut32.dll
imm32.dll
```

## GetLastError() へのリンクが上手く動作した時のスクリプト

ただし、この状態だと「戻る」ボタンが効かないらしい。


```bash:
#!/bin/bash

export WINEDEBUG=+loaddll


WINEDLLOVERRIDES=hhctrl.ocx=n
WINEDLLOVERRIDES+=';comctl32=n'

# 他の dll を native にしている場合、
# mshtml を、native にしておかないと起動出来ないらしい。
WINEDLLOVERRIDES+=';mshtml=n'

# 他の dll を native にしている場合、
# shlwapi を、native にしておかないと起動出来ないらしい。
WINEDLLOVERRIDES+=';shlwapi=n'

# itss を native にして、かつ、wininet を native してないと、
# GetLastError でとんだ直後に右の本文ペーンが真っ白になってしまう。
WINEDLLOVERRIDES+=';wininet=n'


# urlmon を native にしておかないと上手く行かないらしい。
WINEDLLOVERRIDES+=';urlmon=n'

# itss を native にするだけで、飛べないリンク先であるところの GetLastError
# に飛べるようになる。
WINEDLLOVERRIDES+=';itss=n'

# これを native にすると、左で選択したとき、右に表示される前に
# hh.exe がダウンしてしまう不具合が直った。
WINEDLLOVERRIDES+=';shdocvw=n'


echo WINEDLLOVERRIDES=$WINEDLLOVERRIDES
export WINEDLLOVERRIDES



#wine C:/windows/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL

wine /media/Xxxx/WINDOWS/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL
```



## 始めて GetLastError への Jump が上手く行ったときのスクリプト

```bash:
#!/bin/bash

export WINEDEBUG=+loaddll


WINEDLLOVERRIDES=hhctrl.ocx=n
WINEDLLOVERRIDES+=';comctl32=n'
WINEDLLOVERRIDES+=';mshtml=n'
WINEDLLOVERRIDES+=';advapi32=n'
WINEDLLOVERRIDES+=';shlwapi=n'
WINEDLLOVERRIDES+=';shell32=n'
WINEDLLOVERRIDES+=';oleaut32=n'
WINEDLLOVERRIDES+=';ole32=n'
WINEDLLOVERRIDES+=';version=n'
WINEDLLOVERRIDES+=';netapi32=n'

# ws2_32 と ws2help はセット。
WINEDLLOVERRIDES+=';ws2_32=n'
WINEDLLOVERRIDES+=';ws2help=n'

WINEDLLOVERRIDES+=';wininet=n'
WINEDLLOVERRIDES+=';urlmon=n'

WINEDLLOVERRIDES+=';msls31=n'

WINEDLLOVERRIDES+=';itss=n'

# これを native にすると、左で選択したとき、右に表示される前に
# hh.exe がダウンしてしまう不具合が直った。
WINEDLLOVERRIDES+=';shdocvw=n'


# crypt32 はダメらしい：
# WINEDLLOVERRIDES+=';crypt32=n'



# mpr はダメらしい :
# WINEDLLOVERRIDES+=';mpr=n'




# WINEDLLOVERRIDES+=';jscript=n'




# WINEDLLOVERRIDES+=';jscript=n'
# WINEDLLOVERRIDES+=';ieframe=n'





# msvcrt.dllは、どうもダメらしい :
# WINEDLLOVERRIDES+=';msvcrt=n'

# rpcrt4 はダメらしい :
# WINEDLLOVERRIDES+=';rpcrt4=n'

# WINEDLLOVERRIDES+=';iphlpapi=n'



# WINEDLLOVERRIDES+=';secur32=n'



# WINEDLLOVERRIDES+=';itircl=n'



# WINEDLLOVERRIDES+=';usp10=n'


# WINEDLLOVERRIDES+=';imm32=n'


echo WINEDLLOVERRIDES=$WINEDLLOVERRIDES
export WINEDLLOVERRIDES

#
# ieframe.dll は、native のものを .wine の system32 置いておくだけで 右のペーンが真っ白になってしまう。
#



#wine C:/windows/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL

wine /media/Xxxx/WINDOWS/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL
```


## 調査メモ

```bash:
#!/bin/bash

export WINEDEBUG=+loaddll


WINEDLLOVERRIDES=hhctrl.ocx=n
WINEDLLOVERRIDES+=';comctl32=n'

# 他の dll を native にしている場合、
# mshtml を、native にしておかないと起動出来ないらしい。
WINEDLLOVERRIDES+=';mshtml=n'

# advapi32 は、n,b どちらでも大丈夫らしい。
# WINEDLLOVERRIDES+=';advapi32=n'

# 他の dll を native にしている場合、
# shlwapi を、native にしておかないと起動出来ないらしい。
WINEDLLOVERRIDES+=';shlwapi=n'

# shell32 は、n,b どちらでも大丈夫らしい。
#WINEDLLOVERRIDES+=';shell32=n'


# oleaut32 + ole32 は、n,b どちらでも大丈夫らしい。
# WINEDLLOVERRIDES+=';oleaut32=n'
# WINEDLLOVERRIDES+=';ole32=n'

# version は、n,b どちらでも大丈夫らしい。
# WINEDLLOVERRIDES+=';version=n'

# netapi32 は、n,b どちらでも大丈夫らしい。
# WINEDLLOVERRIDES+=';netapi32=n'


# itss を native にして、かつ、wininet を native してないと、
# GetLastError でとんだ直後に右の本文ペーンが真っ白になってしまう。
WINEDLLOVERRIDES+=';wininet=n'


# urlmon を native にしておかないと上手く行かないらしい。
WINEDLLOVERRIDES+=';urlmon=n'

# msls31 は、n,b どちらでも大丈夫らしい。
# 
# WINEDLLOVERRIDES+=';msls31=n'


# itss を native にするだけで、飛べないリンク先であるところの GetLastError
# に飛べるようになる。
WINEDLLOVERRIDES+=';itss=n'

# これを native にすると、左で選択したとき、右に表示される前に
# hh.exe がダウンしてしまう不具合が直った。
WINEDLLOVERRIDES+=';shdocvw=n'


#
# ws2_32 と ws2help はセット。
# セットにすれば、n でも b でも異常なし。
#WINEDLLOVERRIDES+=';ws2_32=n'
#WINEDLLOVERRIDES+=';ws2help=n'




# crypt32 はダメらしい：
# WINEDLLOVERRIDES+=';crypt32=n'



# mpr はダメらしい :
# WINEDLLOVERRIDES+=';mpr=n'




# WINEDLLOVERRIDES+=';jscript=n'




# WINEDLLOVERRIDES+=';jscript=n'
# WINEDLLOVERRIDES+=';ieframe=n'





# msvcrt.dllは、どうもダメらしい :
# WINEDLLOVERRIDES+=';msvcrt=n'

# rpcrt4 はダメらしい :
# WINEDLLOVERRIDES+=';rpcrt4=n'

# WINEDLLOVERRIDES+=';iphlpapi=n'



# WINEDLLOVERRIDES+=';secur32=n'



# WINEDLLOVERRIDES+=';itircl=n'



# WINEDLLOVERRIDES+=';usp10=n'


# WINEDLLOVERRIDES+=';imm32=n'


echo WINEDLLOVERRIDES=$WINEDLLOVERRIDES
export WINEDLLOVERRIDES

#
# ieframe.dll は、native のものを .wine の system32 置いておくだけで 右のペーンが真っ白になってしまう。
#



#wine C:/windows/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL

wine /media/Xxxx/WINDOWS/hh.exe e:/MSDN/2001OCT/1033/MSDN130.COL
```








## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa

## aaa
aaa