解讀 FindServicingStackDirectoryVersion
功能:
找到當前版本的 Servicing Stack的目錄的版本號,
用輸入的目錄與保存在註冊表中的值進行對照。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ComponentBased Servicing\Version
比如,可能是這樣的值:
10.0.14393.693:%SystemRoot%\winsxs\amd64_microsoft-windows-servicingstack_31bf3856ad364e35_10.0.14393.693_none_42ff55c9655f38bf
在這個目錄下,保存了這樣一些文件:
amd64_installed
CbsCore.dll
CbsMsg.dll
cmiadapter.dll
cmiaisupport.dll
dpx.dll
drupdate.dll
drvstore.dll
GlobalInstallOrder.xml
msdelta.dll
mspatcha.dll
poqexec.exe
smiengine.dll
smipi.dll
TiFileFetcher.exe
TiWorker.exe
WcmTypes.xsd
wcp.dll
wdscore.dll
wrpint.dll
這不是導出函數,所以,還是要用直接地址法調用該函數。
a1:輸入參數,Servicing Stack的目錄,比如c:\\windows\\winsxs\\x86_microsoft-windows-servicingstack_31bf3856ad364e35_6.3.9600.18384_none_9dfef83fe2e442e4\\
a2:輸出參數,版本號的前兩位,比如:0x00060003,即,6.3;
a3:輸出參數,版本號的前兩位,比如:0x258047d0,即:9600.18384。
這個函數本身並不很重要,但是,其中有幾點是值得注意的:
1、計算Servicing Stack版本號的過程十分複雜,不是簡單地把目錄中的數值讀出來就行了;
2、匹配Servicing Stack版本,需要同時滿足這樣幾個條件:首先,能正確讀出 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ComponentBased Servicing\Version 註冊表項,其次,
3、讀註冊表的函數RegOpenKeyExW
v4 =RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ComponentBased Servicing\\Version",
0,
0x20019u,
&phkResult);
不僅能讀到 HKEY_LOCAL_MACHINE\SOFTWARE,還能讀到
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node,且完全是由
RegOpenKeyExW 自身所控制,不需要人爲參與。
4、讀出來的路徑是內部表示形式,與實際的路徑不同,用 FileExpandPath 函數進行擴展:
v15 =FileExpandPath(v3, (WCHAR**)&lpString2);
直接讀出來的值:
%SystemRoot%\winsxs\amd64_microsoft-windows-servicingstack_31bf3856ad364e35_10.0.14393.693_none_42ff55c9655f38bf
經過函數 FileExpandPath的擴展以後,變成:
c:\\windows\\winsxs\\x86_microsoft-windows-servicingstack_31bf3856ad364e35_6.3.9600.18384_none_9dfef83fe2e442e4
5、路徑的比較使用CompareStringW函數
CompareStringW(0x7Fu,1u, lpString1, -1, v16, -1) == 2
在比較前,還要保證是字符串的後面加上 \。
更好的函數,即直接讀 Servicing Stack 目錄的函數在 ssshim.dll 中,GetServicingStackFilePath,在 dism 中調用,SsShimInterface::GetServicingStackFilePath。
很好的消息是,GetServicingStackFilePath是導出函數。
調用方法:
v16 =SsShimInterface::InternalBindServicingStack(
(SsShimInterface *)&hLibModule,*v6, v24, v72, v69, v64, v65);
v16 =
SsShimInterface::GetServicingStackFilePath(
(SsShimInterface*)&hLibModule,
L"cbscore.dll",
(unsigned__int16
**)&lpMem);
//----- (10095990)--------------------------------------------------------
int __fastcall FindServicingStackDirectoryVersion(
const WCHAR*a1,
unsigned int *a2,
unsigned int *a3)
{
v41 =a2;
v43 =0;
v44 =0;
v45 =0;
lpString1 =a1;
phkResult =0;
v48 =0;
lpString2 =0;
v3 =0;
v4 =RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ComponentBased Servicing\\Version",
0,
0x20019u,
&phkResult);
v5 =v4 <
0;
if (v4 >
0)
v5 =(((unsigned __int16)v4
|
0x80070000) &
0x80000000)
!= 0;
if (v5
)
{
LABEL_98:
v15 =-2147023728;
CBSWdsLog(0x4000000,
-2147023728,
1, "Failed to find a matching version for servicing stack:%S", lpString1);
goto LABEL_64;
}
for (i =
0;; i = dwIndex
+
1 )
{
dwIndex =i;
memset(&Dst,
0,0x206u);
v7 =phkResult;
v51 =260;
ValueName =0;
Type =0;
cbData =0;
cchValueName =
260;
v8 =RegEnumValueW(phkResult, i,
&ValueName, &cchValueName,0,
&Type,0,
&cbData);
if (v8 >
0)
v9 =(unsigned __int16)v8
|
0x80070000;
else
v9 =v8;
if (v8 !=
259)
{
if (v9 <
0)
{
CBSWdsLog(0x4000000, v9,
1, "Failed to RegEnumValue.");
goto LABEL_14;
}
if (Type !=
2&& Type
!=
1 )
{
v9 =-2147024883;
CBSWdsLog(0x4000000,
-2147024883,
1, "Registry value for %S is not a dword type.",&ValueName);
v15 =-2147024883;
LABEL_74:
CBSWdsLog(0x4000000, v9,
1, "Failed to enumerate all servicing stackversions.");
goto LABEL_64;
}
v10 =(cbData
>>1)
+
1;
if (v10 >
0x3FFFFFFF)
{
v37 =-2147317563;
CBSWdsLog(0x4000000,
-2147317563,
1, "string sizetoo big");
LABEL_77:
v9 =v37;
CBSWdsLog(0x4000000, v37,
1, "Failed to allocate string to enum registry value:%S",
&ValueName);
v3 =v48;
goto LABEL_14;
}
v11 =(wchar_t
*)operator new(2
* v10 +
4);
EndPtr =v11;
if (!v11
)
{
v37 =-2147024882;
CBSWdsLog(0x4000000,
-2147024882,
1, "Failed to allocate string");
goto LABEL_77;
}
*(_DWORD
*)v11
=v10;
v12 =(BYTE
*)(v11
+
2);
*(_WORD
*)v12
=
0;
v9 =0;
v13 =RegEnumValueW(v7, dwIndex,
&ValueName, &v51,0,
&Type,v12, &cbData);
if (v13
)
{
if ( v13 >
0 )
v9 =(unsigned __int16)v13
|
0x80070000;
else
v9 =v13;
CBSWdsLog(0x4000000, v9,
1, "Failed to enum value after it already existedonce.");
operator delete(EndPtr);
v3 =v48;
}
else
{
v14 =EndPtr;
EndPtr[v10+
1] =
0;
v3 =v14
+ 2;
v48 =v14
+ 2;
}
}
LABEL_14:
v15 =v9;
if (v9 ==
-2147024637
)
break;
if (v9 <
0)
goto LABEL_74;
v15 =FileExpandPath(v3,
(WCHAR**)&lpString2);
if (v15 <
0)
{
CBSWdsLog(0x4000000, v15,
1, "Failed to expand path from onine store: %S",lpString2);
goto LABEL_64;
}
v15 =0;
v16 =lpString2;
if (lpString2[wcslen(lpString2)
-
1] !=
92 )
{
v17 =0;
EndPtr =0;
v18 =0;
if (lpString2
)
{
v17 =*((_DWORD*)lpString2-
1);
v18 =wcslen(lpString2);
}
if (v17 < v18
+
2 )
{
v38 =operator new(2
*
(v18 +
2) +
4);
if ( v38
)
{
v39 =(WCHAR
*)lpString2;
*v38= v18
+2;
v40 =v38
+ 1;
if ( v39
)
memcpy(v40, v39,
2 * v18
+2);
else
*(_WORD
*)v40
=
0;
v16 =(const WCHAR
*)v40;
EndPtr = v39;
v17 =v18
+ 2;
lpString2 = v16;
goto LABEL_21;
}
v27 =-2147024882;
CBSWdsLog(0x4000000,
-2147024882,
1, "Failed to allocate string");
v15 =-2147024882;
}
else
{
LABEL_21:
v15 =0;
if ( !v17
|| v17 >0x7FFFFFFF
)
v15 =-2147024809;
if ( v15 >=
0 )
{
v15 =0;
v19 =v17;
v20 =v16;
if ( v17
)
{
while ( *v20
)
{
++v20;
if ( !--v19
)
goto LABEL_90;
}
if ( v19
)
{
v21 = v17
-v19;
goto LABEL_30;
}
}
LABEL_90:
v15 =-2147024809;
}
v21 =0;
LABEL_30:
if ( v15 >=
0 )
{
v15 =0;
v22 =&lpString2[v21];
v23 =v17
- v21;
if ( v17 ==v21
)
goto LABEL_92;
v24 =v23
- v17 +v21
+
2147483646;
v25 =(char
*)((char
*)L"\\"
-
(char*)v22);
while ( v24
)
{
v26 =
*(_WORD *)&v25[(_DWORD)v22];
if ( !v26
)
break;
*v22= v26;
--v24;
++v22;
if ( !--v23
)
goto LABEL_92;
}
if ( !v23
)
{
LABEL_92:
--v22;
v15 =
-2147024774;
}
*v22=
0;
}
v27 =v15;
if ( v15 <
0 )
CBSWdsLog(0x4000000, v15,
1, "Failed to concatstring.");
if ( EndPtr
)
operator delete(EndPtr
-2);
if ( v15 >=
0 )
{
LABEL_45:
v3 =v48;
v16 =lpString2;
goto LABEL_46;
}
}
CBSWdsLog(0x4000000, v27,
1, "Failed to concat backslash onto string.");
goto LABEL_45;
}
LABEL_46:
if (v15 <
0)
{
CBSWdsLog(0x4000000, v15,
1, "Failed to ensure path to online store is backslashterminated: %S", v16);
goto LABEL_64;
}
if (CompareStringW(0x7Fu, 1u, lpString1,
-1, v16,
-1)
==
2 )
{
EndPtr =&ValueName;
v28 =_wcstoul(&ValueName,&EndPtr,
10);
if (EndPtr
)
{
if (
46 ==*EndPtr
)
{
v29 =v28
<< 16;
++EndPtr;
v30 =_wcstoul(EndPtr,
&EndPtr,10);
if ( EndPtr
)
{
if (
46 ==
*EndPtr)
{
v31 = v30
|v29;
++EndPtr;
v32 = _wcstoul(EndPtr,&EndPtr,
10);
if ( EndPtr
)
{
if (
46 ==
*EndPtr)
{
v33 = v32
<<16;
++EndPtr;
v34 = _wcstoul(EndPtr,&EndPtr,
10);
if ( EndPtr
)
{
if ( !*EndPtr)
{
v35 = v34
|v33;
if ( v31
>v44 || v31
== v44 &&v35
> v45
)
{
v43 =
1;
v44 = v31;
v45 = v35;
}
}
}
}
}
v3 = v48;
}
}
}
}
}
if (v3
)
{
operator delete((void
*)(v3 -
2));
v3 =0;
v48 =0;
}
}
v15 =0;
if (!v43
)
goto LABEL_98;
*v41= v44; // a2,輸出
*a3= v45; // 輸出
LABEL_64: // 清理
if (lpString2
)
operator delete((void
*)(lpString2
-2));
if (v3
)
operator delete((void
*)(v3
-
2));
if (phkResult
)
RegCloseKey(phkResult);
return v15;
}