Windows 2000 に OnLinkPrefixLength を実装してみる

副題 UTAU Plugin autoCVVC Win2000 で エラーになる件について その4 なのです
UTAU Plugin autoCVVC Win2000 で エラーになる件について その1
Windows 2000 と PIP_ADAPTER_UNICAST_ADDRESS

UTAU Plugin autoCVVC Win2000 で エラーになる件について その2
Windows 2000 と PIP_ADAPTER_ADDRESSES
UTAU Plugin autoCVVC Win2000 で エラーになる件について その3

  jz L773043CA
  mov ecx,[ebp-08h]
  and ecx,ebx
  cmp ecx,edi
  jz L7730442D
  push 00000003h
  pop ecx
  mov [esi+14h],ecx //  PrefixOrigin
  mov [esi+18h],ecx //  SuffixOrigin
L773043CA:
  cmp dword ptr [esi+18h],00000005h // SuffixOrigin
  push 00000004h
  pop ecx
  mov [esi+1Ch],ecx
  jz L773043EB
  cmp dword ptr [ebp-08h],7F000001h // localhost 127.0.0.1
  jz L773043EB
  mov edx,[ebp-08h]
  and edx,ebx
  cmp edx,edi
  jz L773043EB
  mov [esi+04h],eax
L773043EB:
  mov eax,[ebp+0Ch] // MIB_IPADDRROW_W2K
  test byte ptr [eax+16h],80h // wType
  jnz L7730443D
L773043F4:
  test byte ptr [eax+16h],01h // wType
  jz L773043FD
  or [esi+04h],ecx

さて、もう少し解析してみて、分かったことがあります。
実は、 *(int*) (ebp + 0xc) には、 IPv4 の MIB_IPADDRTABLE 構造体のアドレスが入っています
これのオフセットの 0x08 を見ると、サブネットマスクが入ってるのです。

例えば、255.255.255.0 なら、 0x00FFFFFF となり、
255.0.0.0 なら、 0x000000FF となります。
欲しい数値は、0x18 と 0x8 です。

  mov eax,DWORD PTR[ebp+0xc]
  mov eax,DWORD PTR[eax+8]
  mov bl,al
  shl ebx,8
  shr eax,8
  mov bl,al
  shl ebx,8
  shr eax,8
  mov bl,al
  shl ebx,8
  shr eax,8
  mov bl,al
  xor eax,eax
L1:
  shl ebx,1
  jnc L2
  inc eax
  jmp L1
L2:
  mov [esi+0x2c],eax // OnLinkPrefixLength

これで、実装できそうです ・ω・ (ebx がこの関数内で使えるため)

ちなみに、ConvertLengthToIpv4Mask は逆の演算をすればOKです
Windows Vista を見るとあらかじめテーブルを 32 QWORD 用意して 返すようにしてますね・ω・

ConvertLengthToIpv4Mask:
  push ebp
  mov ebp,esp
  mov eax,[ebp+08h]
  cmp eax,00000021h
  jnc ERR
  xor ecx,ecx
  and eax,eax
  jz CALEND
LP:
  stc
  rcr ecx,1
  dec eax
  jnz LP
  
  mov al,cl
  shr ecx,8
  shl eax,8
  mov al,cl
  shr ecx,8
  shl eax,8
  mov al,cl
  shr ecx,8
  shl eax,8
  mov al,cl
CALEND: 
  mov ecx,[ebp+0Ch]
  mov [ecx],eax
  xor eax,eax
  jmp END
ERR:
  mov eax,[ebp+0Ch]
  or dword ptr [eax],FFFFFFFFh
  push 00000057h
  pop eax
END:
  pop ebp
  retn 0008h

実装前

sizeof(pUnicast)=48
pUnicast->OnLinkPrefixLength=0
ConvertLengthToIpv4Mask=false
(ローカル エリア接続 2:2:192.168.79.152:255.255.255.0::)
sizeof(pUnicast)=0
pUnicast->OnLinkPrefixLength=0
ConvertLengthToIpv4Mask=false
(ローカル エリア接続:2:192.168.79.202:255.255.255.0::)
sizeof(pUnicast)=48
pUnicast->OnLinkPrefixLength=0
ConvertLengthToIpv4Mask=false
(MS TCP Loopback interface:2:127.0.0.1:255.0.0.0::)

実装後

sizeof(pUnicast)=48
pUnicast->OnLinkPrefixLength=24
ConvertLengthToIpv4Mask=00ffffff
(ローカル エリア接続 2:2:192.168.79.152:255.255.255.0::)
sizeof(pUnicast)=48
pUnicast->OnLinkPrefixLength=24
ConvertLengthToIpv4Mask=00ffffff
(ローカル エリア接続:2:192.168.79.202:255.255.255.0::)
sizeof(pUnicast)=48
pUnicast->OnLinkPrefixLength=8
ConvertLengthToIpv4Mask=000000ff
(MS TCP Loopback interface:2:127.0.0.1:255.0.0.0::)

うまくいきました・ω・

ここで、autoCVVC を動かしてみます。
vc
ですよねー ・ω・

psutil/_psutil_windows.c at master ・ giampaolo/psutil

#if (_WIN32_WINNT >= 0x0600) // Windows Vista and above
SecureZeroMemory((PVOID)pIfRow, sizeof(MIB_IF_ROW2));
pIfRow->InterfaceIndex = pCurrAddresses->IfIndex;
dwRetVal = GetIfEntry2(pIfRow);
#else // Windows XP
pIfRow->dwIndex = pCurrAddresses->IfIndex;
dwRetVal = GetIfEntry(pIfRow);
#endif

あかん、これは、ソースが無い限り無理なやつや…。

おすすめ

2件のフィードバック

  1. 黒翼猫 より:

    >>1
    ありがとうございます。
    私が作ったのとほぼ同じみたいですね。
    考えることは同じと言うわけのようです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です