[R3/R4] Path-A trace: synthesizer is in Lmx.dll's NMX-frame decoder
Five-stage Ghidra headless decompile traces the byte-to-MXSTATUS_PROXY synthesis path end-to-end across LmxProxy.dll and Lmx.dll. New evidence files committed alongside R3/R4 verdict update: - analysis/ghidra/exports/LmxProxy.dll.fire-event-xrefs.md - analysis/ghidra/exports/LmxProxy.dll.status-synthesis-decompile.md - analysis/ghidra/exports/LmxProxy.dll.mxstatus-safearray-decompile.md - analysis/ghidra/exports/Lmx.dll.set-attribute-result-decompile.md Layer-by-layer findings (bytes flow inward; synthesis flows outward): 1. `Lmx.aaDCT` at 0x10178fc0 is `SysAllocString(L"Lmx.aaDCT")` — a tracing category BSTR, not a table. 2. `MXSTATUS_PROXY` is a 16-byte marshalled struct (4 × i16 padded to i32 boundaries with Pack=4) — the OUTPUT of synthesis, not a lookup entry. 3. `LmxProxy.dll` Fire_* event handlers receive already-populated `MXSTATUS_PROXY[]` and forward through ATL dispatch — no synthesis. 4. `LmxProxy.dll` Fire_* CALLERS (FUN_1001657f / FUN_10016b50 / FUN_10016d4b) call FUN_10003f60(out_safearray, in_status_ptr, count=1) which is a VERBATIM memcpy of an existing 14-byte buffer into the SAFEARRAY — no transformation. 5. `Lmx.dll`'s `PreboundReference::OnSetAttributeResult` (FUN_10114a90) receives an already-populated `short *param_7` status buffer. Log line confirms the layout: `<success %d category %d detectedBy %d detail %d>`. Dispatches on typed values — synthesis is upstream of this function too. The synthesizer is the NMX-frame decoder in Lmx.dll that calls OnSetAttributeResult / OnGetAttributeResult / equivalent OperationComplete handler. The decoder takes raw NMX bytes plus operation context (item handle, engine state, retry state, correlation id) and computes the populated MXSTATUS_PROXY. There is NO static lookup table — synthesis is per-message contextual. Two viable paths to typed promotion (both substantial; neither a small codec patch): - Path A: port the synthesizer. ~1-2 weeks. Requires extending the Rust session to track per-operation context (handles, retries, correlation ids). Out of V1 scope. - Path B: empirical capture pairs. ~30 min × 6-10 scenarios. Output is a (byte, context → status) mapping that approximates without re-implementing. Risk: mapping is only valid for captured contexts. R3/R4 stay settled at verbatim-preserve. The .NET reference does the same for the same reason: the synthesizer is too context- dependent to mirror without porting the entire operation-tracking state machine. Reopen criteria sharpened: either (a) a consumer files a concrete use case for typed promotion of a specific byte+context combination (Path B's empirical capture for that one combination is the cheapest answer); or (b) a major-version bump justifies the state-machine port (Path A). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,501 @@
|
||||
# Lmx.dll selected decompile
|
||||
|
||||
## FUN_10114a90 at 10114a90
|
||||
|
||||
Signature: `undefined FUN_10114a90(void)`
|
||||
|
||||
```c
|
||||
|
||||
void __thiscall
|
||||
FUN_10114a90(undefined4 *param_1,int param_2,int *param_3,ushort param_4,undefined4 param_5,
|
||||
void *param_6,short *param_7)
|
||||
|
||||
{
|
||||
char cVar1;
|
||||
uint uVar2;
|
||||
undefined4 uVar3;
|
||||
basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *pbVar4;
|
||||
int iVar5;
|
||||
undefined4 *puVar6;
|
||||
wchar_t *pwVar7;
|
||||
wchar_t *pwVar8;
|
||||
size_t _MaxCount;
|
||||
DWORD DVar9;
|
||||
int iVar10;
|
||||
int *piVar11;
|
||||
undefined2 uVar12;
|
||||
wchar_t _Ch;
|
||||
_func_basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>_ptr_basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>_ptr
|
||||
*p_Var13;
|
||||
undefined4 uVar14;
|
||||
undefined1 local_ba4 [20];
|
||||
undefined1 local_b90 [20];
|
||||
undefined4 local_b7c;
|
||||
undefined4 local_b74;
|
||||
void *local_b70;
|
||||
short *local_b6c;
|
||||
undefined4 *local_b68;
|
||||
int *local_b64;
|
||||
char local_b5e;
|
||||
char local_b5d;
|
||||
undefined4 *local_b5c [391];
|
||||
wchar_t local_540 [520];
|
||||
undefined1 local_130 [20];
|
||||
undefined1 local_11c [20];
|
||||
undefined1 local_108 [60];
|
||||
undefined1 local_cc [20];
|
||||
undefined4 local_b8 [36];
|
||||
undefined4 local_28;
|
||||
undefined4 local_24;
|
||||
undefined4 local_20;
|
||||
uint local_14;
|
||||
void *local_10;
|
||||
undefined1 *puStack_c;
|
||||
undefined4 local_8;
|
||||
|
||||
local_8 = 0xffffffff;
|
||||
puStack_c = &LAB_101729a5;
|
||||
local_10 = ExceptionList;
|
||||
uVar2 = DAT_101d60b8 ^ (uint)&stack0xfffffffc;
|
||||
ExceptionList = &local_10;
|
||||
local_b5c[0] = (undefined4 *)(uint)param_4;
|
||||
local_b74 = param_5;
|
||||
local_b70 = param_6;
|
||||
local_b6c = param_7;
|
||||
local_14 = uVar2;
|
||||
cVar1 = FUN_100408d0(uVar2);
|
||||
if (cVar1 != '\0') {
|
||||
local_20 = *(undefined4 *)(local_b6c + 2);
|
||||
swprintf_s(local_540,0x104,L"<success %d category %d detectedBy %d detail %d>",
|
||||
(int)(short)*(undefined4 *)local_b6c,local_20,*(undefined4 *)(local_b6c + 4),
|
||||
(int)local_b6c[6]);
|
||||
local_b64 = (int *)FUN_10004010(local_b74,local_b70);
|
||||
local_b5c[0] = (undefined4 *)FUN_100040a0(local_b5c[0]);
|
||||
uVar3 = FUN_100300d0(param_3);
|
||||
iVar5 = param_2;
|
||||
p_Var13 = endl_exref;
|
||||
pbVar4 = (basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *)
|
||||
FUN_1001a0e0(*(undefined4 *)(DAT_101d6474 + 0x20),
|
||||
L"PreboundReference::OnSetAttributeResult - ENTER correlationId ",param_2,
|
||||
L" pValue ",uVar3,L" quality ",local_b5c[0],L" timestamp ",local_b64,
|
||||
L" mxStatus ",local_540);
|
||||
pbVar4 = std::basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>::operator<<
|
||||
(pbVar4,iVar5);
|
||||
uVar3 = FUN_1001a0e0(pbVar4);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
pbVar4 = (basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *)
|
||||
FUN_1001a0e0(uVar3);
|
||||
std::basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>::operator<<
|
||||
(pbVar4,p_Var13);
|
||||
}
|
||||
if (param_2 == 0) {
|
||||
if (*local_b6c == -1) {
|
||||
iVar5 = (**(code **)(*param_3 + 0x60))(param_3,&local_b68);
|
||||
iVar5 = FUN_10048e60(iVar5 == 0,iVar5,300,"preboundreference.cpp");
|
||||
if (iVar5 == 0) goto LAB_1011543c;
|
||||
if (local_b68 != (undefined4 *)0x0) {
|
||||
local_b64 = (int *)0x0;
|
||||
local_8 = 1;
|
||||
uVar12 = 0x1011;
|
||||
iVar5 = (**(code **)(*param_3 + 0x80))(param_3,&local_b64);
|
||||
if (iVar5 == 0) {
|
||||
FUN_1008e710(local_b64);
|
||||
local_8._0_1_ = 2;
|
||||
FUN_10112f20(local_b90);
|
||||
local_8._0_1_ = 1;
|
||||
FUN_10021cc0();
|
||||
FUN_1005f730(&local_28);
|
||||
uVar3 = CONCAT22(uVar12,(undefined2)local_20);
|
||||
cVar1 = FUN_100057b0(local_28,local_24,uVar3,0x138,"preboundreference.cpp");
|
||||
uVar12 = (undefined2)((uint)uVar3 >> 0x10);
|
||||
if (cVar1 != '\0') {
|
||||
FUN_1004c220();
|
||||
local_8._0_1_ = 3;
|
||||
FUN_1004c320(param_1[0x14]);
|
||||
local_b5c[0] = local_b8;
|
||||
uVar12 = 0x1011;
|
||||
FUN_10073b80(local_b5c,0);
|
||||
iVar5 = FUN_1005f730(local_130);
|
||||
FUN_10040470(*(undefined2 *)(iVar5 + 2));
|
||||
local_8._0_1_ = 1;
|
||||
FUN_1002e080();
|
||||
}
|
||||
cVar1 = FUN_100057b0(local_28,local_24,CONCAT22(uVar12,(undefined2)local_20),0x144,
|
||||
"preboundreference.cpp");
|
||||
if (cVar1 == '\0') {
|
||||
param_1[0x2a] = 4;
|
||||
}
|
||||
else {
|
||||
iVar5 = FUN_1005f730(local_11c);
|
||||
if (*(short *)(iVar5 + 10) == 0) {
|
||||
FUN_101131d0();
|
||||
}
|
||||
else {
|
||||
param_1[0x2a] = 3;
|
||||
param_1[0x29] = 0;
|
||||
FUN_10114620();
|
||||
}
|
||||
}
|
||||
}
|
||||
local_8 = 0xffffffff;
|
||||
if (local_b64 != (int *)0x0) {
|
||||
(**(code **)(*local_b64 + 8))(local_b64);
|
||||
}
|
||||
goto LAB_1011543c;
|
||||
}
|
||||
}
|
||||
else if (((DAT_101d8c40 == 2) && (param_1[0x29] == 0)) &&
|
||||
(*(ushort *)(param_1[0x19] + 0x2ac) - 0x7c17 < 0x3e9)) {
|
||||
cVar1 = FUN_100408d0(uVar2);
|
||||
if (cVar1 != '\0') {
|
||||
uVar3 = FUN_10003fc0(*(undefined4 *)local_b6c,*(undefined4 *)(local_b6c + 2),
|
||||
*(undefined4 *)(local_b6c + 4),*(undefined4 *)(local_b6c + 6));
|
||||
p_Var13 = endl_exref;
|
||||
uVar3 = FUN_1001a0e0(*(undefined4 *)(DAT_101d6474 + 0x1c),
|
||||
L"PreboundReference - attempting local platform <",param_1 + 6,
|
||||
L"> - status ",uVar3);
|
||||
uVar3 = FUN_1001dec0(uVar3);
|
||||
uVar3 = FUN_1001a0e0(uVar3);
|
||||
pbVar4 = (basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *)
|
||||
FUN_1001a0e0(uVar3);
|
||||
std::basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>::operator<<
|
||||
(pbVar4,p_Var13);
|
||||
}
|
||||
param_1[5] = param_1[5] + 1;
|
||||
param_1[0x2a] = 1;
|
||||
param_1[0x29] = 1;
|
||||
FUN_10112cd0();
|
||||
goto LAB_1011543c;
|
||||
}
|
||||
LAB_10115432:
|
||||
param_1[0x2a] = 4;
|
||||
goto LAB_1011543c;
|
||||
}
|
||||
if (param_2 != 1) goto LAB_1011543c;
|
||||
param_1[0x2a] = 6;
|
||||
if (*local_b6c != -1) {
|
||||
if (*(char *)(param_1 + 0x1b) != '\0') {
|
||||
if ((uint)param_1[0x21] < 8) {
|
||||
puVar6 = param_1 + 0x1c;
|
||||
}
|
||||
else {
|
||||
puVar6 = (undefined4 *)param_1[0x1c];
|
||||
}
|
||||
iVar5 = (**(code **)(*(int *)param_1[0x14] + 0x44))((int *)param_1[0x14],puVar6);
|
||||
if (iVar5 < 0) {
|
||||
/* WARNING: Subroutine does not return */
|
||||
FUN_1005bf30(iVar5,0,"E:\\BldSrc\\6\\s\\ExtInterfaces\\Lmx\\IMxReferencePtr.h",0x75);
|
||||
}
|
||||
*(undefined1 *)(param_1 + 0x1b) = 0;
|
||||
}
|
||||
if (*(int *)(local_b6c + 2) == 3) {
|
||||
LAB_1011502e:
|
||||
param_1[0x2a] = 6;
|
||||
goto LAB_1011543c;
|
||||
}
|
||||
if ((*(int *)(local_b6c + 2) == 4) && (local_b6c[6] == 0x1f42)) {
|
||||
local_b70 = operator_new(8);
|
||||
local_8 = 0xb;
|
||||
if (local_b70 == (void *)0x0) {
|
||||
local_b5c[0] = (undefined4 *)0x0;
|
||||
}
|
||||
else {
|
||||
local_b5c[0] = (undefined4 *)FUN_10112b50(param_1);
|
||||
}
|
||||
local_8 = 0xffffffff;
|
||||
cVar1 = FUN_10048d60(local_b5c[0] != (undefined4 *)0x0,0x23b,"preboundreference.cpp");
|
||||
if (cVar1 != '\0') {
|
||||
uVar3 = FUN_10016fd0();
|
||||
FUN_1005f7e0(uVar3);
|
||||
FUN_1004c220();
|
||||
local_8 = 0xc;
|
||||
FUN_1004c320(param_1[0x14]);
|
||||
local_b68 = local_b8;
|
||||
FUN_10073b80(&local_b68,0);
|
||||
param_1[5] = param_1[5] + 1;
|
||||
param_1[0x2a] = 1;
|
||||
DVar9 = GetTickCount();
|
||||
FUN_1008f150(local_b5c[0],0,0,0,0,*(undefined4 *)local_b6c,*(undefined4 *)(local_b6c + 2),
|
||||
*(undefined4 *)(local_b6c + 4),*(undefined4 *)(local_b6c + 6),0,DVar9);
|
||||
local_8 = 0xffffffff;
|
||||
FUN_1002e080();
|
||||
}
|
||||
goto LAB_1011543c;
|
||||
}
|
||||
goto LAB_10115432;
|
||||
}
|
||||
iVar5 = (**(code **)(*param_3 + 0x60))(param_3,&local_b68);
|
||||
iVar5 = FUN_10048e60(iVar5 == 0,iVar5,0x19d,"preboundreference.cpp");
|
||||
if (iVar5 == 0) goto LAB_1011543c;
|
||||
if (local_b68 == (undefined4 *)0x0) goto LAB_1011502e;
|
||||
local_b64 = (int *)0x0;
|
||||
local_8 = 6;
|
||||
uVar12 = 0x1011;
|
||||
iVar5 = (**(code **)(*param_3 + 0x80))(param_3,&local_b64);
|
||||
if (iVar5 == 0) {
|
||||
FUN_1008e710(local_b64);
|
||||
local_8._0_1_ = 7;
|
||||
FUN_10112f20(local_ba4);
|
||||
local_8 = CONCAT31(local_8._1_3_,6);
|
||||
FUN_10021cc0();
|
||||
if (*(char *)(param_1 + 0x1b) != '\0') {
|
||||
piVar11 = param_1 + 0x1c;
|
||||
if (7 < (uint)param_1[0x21]) {
|
||||
piVar11 = (int *)*piVar11;
|
||||
}
|
||||
FUN_1005f700(piVar11);
|
||||
*(undefined1 *)(param_1 + 0x1b) = 0;
|
||||
}
|
||||
iVar5 = FUN_1005f730(local_108);
|
||||
if (*(short *)(iVar5 + 10) == 0) {
|
||||
local_b5d = '\0';
|
||||
local_b5e = '\0';
|
||||
puVar6 = (undefined4 *)FUN_1005f730(local_cc);
|
||||
cVar1 = FUN_100057b0(*puVar6,puVar6[1],CONCAT22(uVar12,*(undefined2 *)(puVar6 + 2)),0x1c1,
|
||||
"preboundreference.cpp");
|
||||
if (cVar1 == '\0') {
|
||||
if (*(char *)(param_1 + 4) != '\0') {
|
||||
FUN_1004c220();
|
||||
local_8._0_1_ = 8;
|
||||
FUN_1004c320(param_1[0x14]);
|
||||
local_b5c[0] = local_b8;
|
||||
FUN_10073b80(local_b5c,0);
|
||||
local_8 = CONCAT31(local_8._1_3_,6);
|
||||
FUN_1002e080();
|
||||
}
|
||||
local_b5e = '\x01';
|
||||
}
|
||||
else {
|
||||
pwVar7 = (wchar_t *)FUN_1005f590();
|
||||
cVar1 = FUN_10134a10(pwVar7);
|
||||
if (cVar1 == '\0') {
|
||||
pwVar8 = wcschr(pwVar7,L'.');
|
||||
if ((pwVar8 != (wchar_t *)0x0) &&
|
||||
(_MaxCount = (int)pwVar8 - (int)pwVar7 >> 1, _MaxCount != 0)) {
|
||||
pwVar8 = (wchar_t *)FUN_1005f610();
|
||||
iVar5 = _wcsnicmp(pwVar7,pwVar8,_MaxCount);
|
||||
if (iVar5 == 0) {
|
||||
_Ch = L'.';
|
||||
pwVar7 = (wchar_t *)FUN_1005f660();
|
||||
pwVar7 = wcschr(pwVar7,_Ch);
|
||||
if (pwVar7 == (wchar_t *)0x0) goto LAB_10114e2f;
|
||||
}
|
||||
local_b5d = '\x01';
|
||||
}
|
||||
}
|
||||
}
|
||||
LAB_10114e2f:
|
||||
if ((*(char *)(param_1 + 4) == '\0') || ((local_b5d == '\0' && (local_b5e == '\0')))) {
|
||||
param_1[0x2a] = 4;
|
||||
}
|
||||
else {
|
||||
local_b70 = operator_new(8);
|
||||
local_8._0_1_ = 9;
|
||||
if (local_b70 == (void *)0x0) {
|
||||
local_b5c[0] = (undefined4 *)0x0;
|
||||
}
|
||||
else {
|
||||
local_b5c[0] = (undefined4 *)FUN_10112b50(param_1);
|
||||
}
|
||||
local_8 = CONCAT31(local_8._1_3_,6);
|
||||
cVar1 = FUN_10048d60(local_b5c[0] != (undefined4 *)0x0,0x1ee,"preboundreference.cpp");
|
||||
if (cVar1 == '\0') {
|
||||
param_1[0x2a] = 4;
|
||||
iVar5 = FUN_10022ff0();
|
||||
if (*(int *)(iVar5 + 0xac) == 0) {
|
||||
iVar10 = FUN_1002f080();
|
||||
if (iVar10 != 0) goto LAB_10114f66;
|
||||
uVar3 = 0;
|
||||
}
|
||||
else {
|
||||
LAB_10114f66:
|
||||
uVar3 = *(undefined4 *)(iVar5 + 0xac);
|
||||
}
|
||||
uVar14 = 0;
|
||||
FUN_10022ff0(uVar3,0);
|
||||
cVar1 = FUN_10022ba0(uVar3,uVar14);
|
||||
if (cVar1 != '\0') {
|
||||
uVar3 = FUN_1005f590();
|
||||
uVar3 = FUN_10022ff0(L"PreboundReference::OnSetAttributeResult unable to crreate CPreboundReferenceAdapter for ref %s"
|
||||
,uVar3);
|
||||
FUN_10022cb0(uVar3);
|
||||
}
|
||||
}
|
||||
else {
|
||||
*(undefined1 *)(param_1 + 4) = 0;
|
||||
uVar3 = FUN_10016fd0();
|
||||
FUN_1005f7e0(uVar3);
|
||||
FUN_1008fc40(&DAT_1017a514);
|
||||
FUN_1008fc70(&DAT_1017a514);
|
||||
param_1[5] = param_1[5] + 1;
|
||||
param_1[0x2a] = 1;
|
||||
DVar9 = GetTickCount();
|
||||
local_b70 = (void *)CONCAT22(local_b70._2_2_,0x1f42);
|
||||
local_b7c = (uint)local_b7c._2_2_ << 0x10;
|
||||
FUN_1008f150(local_b5c[0],0,0,0,0,local_b7c,4,0,local_b70,0,DVar9);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
param_1[0x2a] = 3;
|
||||
param_1[0x29] = 0;
|
||||
FUN_10114620();
|
||||
}
|
||||
}
|
||||
local_8 = 0xffffffff;
|
||||
if (local_b64 != (int *)0x0) {
|
||||
(**(code **)(*local_b64 + 8))(local_b64);
|
||||
}
|
||||
LAB_1011543c:
|
||||
if (*(char *)(param_1 + 0x1b) != '\0') {
|
||||
if ((uint)param_1[0x21] < 8) {
|
||||
puVar6 = param_1 + 0x1c;
|
||||
}
|
||||
else {
|
||||
puVar6 = (undefined4 *)param_1[0x1c];
|
||||
}
|
||||
iVar5 = (**(code **)(*(int *)param_1[0x14] + 0x44))((int *)param_1[0x14],puVar6);
|
||||
if (iVar5 < 0) {
|
||||
/* WARNING: Subroutine does not return */
|
||||
FUN_1005bf30(iVar5,0,"E:\\BldSrc\\6\\s\\ExtInterfaces\\Lmx\\IMxReferencePtr.h",0x75);
|
||||
}
|
||||
*(undefined1 *)(param_1 + 0x1b) = 0;
|
||||
}
|
||||
if ((param_1[0x2a] != 1) && (param_1[0x2a] != 2)) {
|
||||
FUN_10050df0(local_b6c,param_1);
|
||||
}
|
||||
piVar11 = param_1 + 5;
|
||||
*piVar11 = *piVar11 + -1;
|
||||
if (*piVar11 == 0) {
|
||||
(**(code **)*param_1)(1);
|
||||
}
|
||||
local_b5c[0] = (undefined4 *)param_1[0x2a];
|
||||
if (param_1[5] == 1) {
|
||||
local_b68 = param_1;
|
||||
piVar11 = (int *)FUN_100484c0(&local_b70,&local_b68);
|
||||
iVar5 = *piVar11;
|
||||
cVar1 = FUN_10048d60(iVar5 != *(int *)(param_1[0x19] + 0x180),0x273,"preboundreference.cpp");
|
||||
if (cVar1 != '\0') {
|
||||
FUN_100382e0(&local_b70,iVar5);
|
||||
piVar11 = param_1 + 5;
|
||||
*piVar11 = *piVar11 + -1;
|
||||
if (*piVar11 == 0) {
|
||||
(**(code **)*param_1)(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
cVar1 = FUN_100408d0();
|
||||
if (cVar1 != '\0') {
|
||||
uVar3 = FUN_10001e20(local_b5c);
|
||||
p_Var13 = endl_exref;
|
||||
uVar3 = FUN_1001a0e0(*(undefined4 *)(DAT_101d6474 + 0x20),
|
||||
L"PreboundReference::OnSetAttributeResult - EXIT status ",uVar3);
|
||||
pbVar4 = (basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *)
|
||||
FUN_1001a0e0(uVar3);
|
||||
std::basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>::operator<<
|
||||
(pbVar4,p_Var13);
|
||||
}
|
||||
ExceptionList = local_10;
|
||||
__security_check_cookie(local_14 ^ (uint)&stack0xfffffffc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## FUN_100dc750 at 100dc750
|
||||
|
||||
Signature: `undefined FUN_100dc750(void)`
|
||||
|
||||
```c
|
||||
|
||||
void __thiscall FUN_100dc750(int *param_1,uint param_2,int param_3,int param_4,BSTR param_5)
|
||||
|
||||
{
|
||||
char cVar1;
|
||||
uint uVar2;
|
||||
undefined4 uVar3;
|
||||
basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *pbVar4;
|
||||
undefined4 *puVar5;
|
||||
_func_basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>_ptr_basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>_ptr
|
||||
*p_Var6;
|
||||
uint local_23c;
|
||||
int *local_234;
|
||||
BSTR local_230;
|
||||
uint local_22c;
|
||||
int local_228;
|
||||
int local_224;
|
||||
BSTR local_220;
|
||||
wchar_t local_21c [260];
|
||||
uint local_14;
|
||||
void *local_10;
|
||||
undefined1 *puStack_c;
|
||||
undefined4 local_8;
|
||||
|
||||
local_8 = 0xffffffff;
|
||||
puStack_c = &LAB_1016d12b;
|
||||
local_10 = ExceptionList;
|
||||
uVar2 = DAT_101d60b8 ^ (uint)&stack0xfffffffc;
|
||||
ExceptionList = &local_10;
|
||||
local_14 = uVar2;
|
||||
cVar1 = FUN_100408d0(uVar2);
|
||||
if (cVar1 != '\0') {
|
||||
local_23c._0_2_ = (short)param_2;
|
||||
swprintf_s(local_21c,0x104,L"<success %d category %d detectedBy %d detail %d>",
|
||||
(int)(short)local_23c,param_3,param_4,(int)(short)param_5);
|
||||
p_Var6 = endl_exref;
|
||||
uVar3 = FUN_1001a0e0(*(undefined4 *)(DAT_101d6474 + 0x14),
|
||||
L"DemandReadCallback::CancelWithStatus - status ",local_21c);
|
||||
pbVar4 = (basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *)
|
||||
FUN_1001a0e0(uVar3);
|
||||
std::basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>::operator<<
|
||||
(pbVar4,p_Var6);
|
||||
}
|
||||
if (((param_3 == 5) && (param_4 == 0)) && ((short)param_5 == 1)) {
|
||||
local_23c = param_2 & 0xffff0000;
|
||||
local_230 = (BSTR)CONCAT22(local_230._2_2_,5);
|
||||
local_228 = 3;
|
||||
local_22c = local_23c;
|
||||
local_224 = 2;
|
||||
local_220 = local_230;
|
||||
}
|
||||
else {
|
||||
local_22c = param_2;
|
||||
local_228 = param_3;
|
||||
local_224 = param_4;
|
||||
local_220 = param_5;
|
||||
}
|
||||
cVar1 = FUN_100408d0(uVar2);
|
||||
if (cVar1 != '\0') {
|
||||
swprintf_s(local_21c,0x104,L"<success %d category %d detectedBy %d detail %d>",
|
||||
(int)(short)local_22c,local_228,local_224,(int)(short)local_220);
|
||||
p_Var6 = endl_exref;
|
||||
uVar3 = FUN_1001a0e0(*(undefined4 *)(DAT_101d6474 + 0x14),
|
||||
L"DemandReadCallback::CancelWithStatus - Calling OnGetAttributeResult with status "
|
||||
,local_21c);
|
||||
pbVar4 = (basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_> *)
|
||||
FUN_1001a0e0(uVar3);
|
||||
std::basic_ostream<unsigned_short,struct_std::char_traits<unsigned_short>_>::operator<<
|
||||
(pbVar4,p_Var6);
|
||||
}
|
||||
puVar5 = (undefined4 *)FUN_10005170();
|
||||
local_8 = 0;
|
||||
(**(code **)(*param_1 + 4))(*puVar5,0,DAT_101d6504,DAT_101d6508,&local_22c);
|
||||
local_8 = 0xffffffff;
|
||||
if (local_234 != (int *)0x0) {
|
||||
(**(code **)(*local_234 + 8))(local_234);
|
||||
}
|
||||
SysFreeString(local_230);
|
||||
ExceptionList = local_10;
|
||||
__security_check_cookie(local_14 ^ (uint)&stack0xfffffffc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# LmxProxy.dll xrefs
|
||||
|
||||
## 0x15f72 at 10015f72
|
||||
|
||||
Target function: `FUN_10015f72`
|
||||
|
||||
| From | Ref type | Caller function |
|
||||
| --- | --- | --- |
|
||||
| `1001695a` | `UNCONDITIONAL_CALL` | `FUN_1001657f` |
|
||||
|
||||
## 0x1611f at 1001611f
|
||||
|
||||
Target function: `FUN_1001611f`
|
||||
|
||||
| From | Ref type | Caller function |
|
||||
| --- | --- | --- |
|
||||
| `10016cc8` | `UNCONDITIONAL_CALL` | `FUN_10016b50` |
|
||||
|
||||
## 0x16271 at 10016271
|
||||
|
||||
Target function: `FUN_10016271`
|
||||
|
||||
| From | Ref type | Caller function |
|
||||
| --- | --- | --- |
|
||||
| `10016eb3` | `UNCONDITIONAL_CALL` | `FUN_10016d4b` |
|
||||
|
||||
## 0x163c0 at 100163c0
|
||||
|
||||
Target function: `FUN_100163c0`
|
||||
|
||||
| From | Ref type | Caller function |
|
||||
| --- | --- | --- |
|
||||
| `10016ad8` | `UNCONDITIONAL_CALL` | `FUN_1001657f` |
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
# LmxProxy.dll selected decompile
|
||||
|
||||
## FUN_10003f60 at 10003f60
|
||||
|
||||
Signature: `HRESULT __cdecl FUN_10003f60(undefined4 * param_1, undefined2 * param_2, ULONG param_3)`
|
||||
|
||||
```c
|
||||
|
||||
HRESULT __cdecl FUN_10003f60(undefined4 *param_1,undefined2 *param_2,ULONG param_3)
|
||||
|
||||
{
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> bVar1;
|
||||
HRESULT HVar2;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *pbVar3;
|
||||
SAFEARRAY *pSVar4;
|
||||
HRESULT HVar5;
|
||||
_func_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr
|
||||
*p_Var6;
|
||||
SAFEARRAYBOUND local_18;
|
||||
LONG local_10;
|
||||
IRecordInfo *local_c;
|
||||
undefined2 *local_8;
|
||||
|
||||
local_c = (IRecordInfo *)0x0;
|
||||
HVar2 = GetRecordInfoFromGuids((GUID *)&DAT_1001c2d0,1,0,0,(GUID *)&DAT_1001b530,&local_c);
|
||||
if (HVar2 < 0) {
|
||||
if ((HVar2 != -0x7ffd7fe3) &&
|
||||
(bVar1 = FUN_10003f01(*(basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> **)
|
||||
(DAT_100294e0 + 4)),
|
||||
bVar1 != (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>)0x0)) {
|
||||
HVar5 = HVar2;
|
||||
p_Var6 = endl_exref;
|
||||
pbVar3 = (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *)
|
||||
FUN_10002dbf(*(int **)(DAT_100294e0 + 4),L"GetRecordInfoFromGuids failed - hr = ");
|
||||
pbVar3 = std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar3,HVar5);
|
||||
std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<(pbVar3,p_Var6);
|
||||
}
|
||||
}
|
||||
else {
|
||||
local_18.lLbound = 0;
|
||||
local_18.cElements = param_3;
|
||||
pSVar4 = SafeArrayCreateEx(0x24,1,&local_18,local_c);
|
||||
*param_1 = pSVar4;
|
||||
(*local_c->lpVtbl->Release)(local_c);
|
||||
if ((SAFEARRAY *)*param_1 == (SAFEARRAY *)0x0) {
|
||||
HVar2 = -0x7fffbffb;
|
||||
}
|
||||
else {
|
||||
HVar2 = SafeArrayGetLBound((SAFEARRAY *)*param_1,1,&local_10);
|
||||
if ((-1 < HVar2) && (HVar2 = SafeArrayAccessData((SAFEARRAY *)*param_1,&local_8), -1 < HVar2))
|
||||
{
|
||||
*local_8 = *param_2;
|
||||
*(undefined4 *)(local_8 + 2) = *(undefined4 *)(param_2 + 2);
|
||||
*(undefined4 *)(local_8 + 4) = *(undefined4 *)(param_2 + 4);
|
||||
local_8[6] = param_2[6];
|
||||
SafeArrayUnaccessData((SAFEARRAY *)*param_1);
|
||||
HVar2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HVar2;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## FUN_10015db2 at 10015db2
|
||||
|
||||
Signature: `void * __thiscall FUN_10015db2(void * this, int * param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6)`
|
||||
|
||||
```c
|
||||
|
||||
/* WARNING: Function: __EH_prolog3 replaced with injection: EH_prolog3 */
|
||||
/* WARNING: Function: __EH_epilog3 replaced with injection: EH_epilog3 */
|
||||
|
||||
void * __thiscall
|
||||
FUN_10015db2(void *this,int *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,
|
||||
undefined4 param_5,undefined4 param_6)
|
||||
|
||||
{
|
||||
*(undefined4 *)this = 1;
|
||||
FUN_10015d38((void *)((int)this + 4),param_1);
|
||||
*(undefined4 *)((int)this + 8) = 0;
|
||||
*(undefined4 *)((int)this + 0x10) = param_2;
|
||||
*(undefined4 *)((int)this + 0x14) = param_3;
|
||||
*(undefined4 *)((int)this + 0x18) = param_4;
|
||||
*(undefined4 *)((int)this + 0xc) = param_6;
|
||||
*(undefined4 *)((int)this + 0x1c) = param_5;
|
||||
*(undefined4 *)((int)this + 0x20) = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## FUN_10015e4e at 10015e4e
|
||||
|
||||
Signature: `void * __thiscall FUN_10015e4e(void * this, int * param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6)`
|
||||
|
||||
```c
|
||||
|
||||
/* WARNING: Function: __EH_prolog3 replaced with injection: EH_prolog3 */
|
||||
/* WARNING: Function: __EH_epilog3 replaced with injection: EH_epilog3 */
|
||||
|
||||
void * __thiscall
|
||||
FUN_10015e4e(void *this,int *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,
|
||||
undefined4 param_5,undefined4 param_6)
|
||||
|
||||
{
|
||||
*(undefined4 *)this = 2;
|
||||
*(undefined4 *)((int)this + 4) = 0;
|
||||
FUN_10015d38((void *)((int)this + 8),param_1);
|
||||
*(undefined4 *)((int)this + 0x20) = 0;
|
||||
*(undefined4 *)((int)this + 0x10) = param_2;
|
||||
*(undefined4 *)((int)this + 0x14) = param_3;
|
||||
*(undefined4 *)((int)this + 0x18) = param_4;
|
||||
*(undefined4 *)((int)this + 0xc) = param_6;
|
||||
*(undefined4 *)((int)this + 0x1c) = param_5;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
# LmxProxy.dll selected decompile
|
||||
|
||||
## FUN_1001657f at 1001657f
|
||||
|
||||
Signature: `undefined __stdcall FUN_1001657f(uint param_1, undefined4 param_2)`
|
||||
|
||||
```c
|
||||
|
||||
/* WARNING: Function: __EH_prolog3_catch_GS replaced with injection: EH_prolog3 */
|
||||
|
||||
void FUN_1001657f(uint param_1,undefined4 param_2)
|
||||
|
||||
{
|
||||
DWORD DVar1;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> bVar2;
|
||||
undefined *puVar3;
|
||||
int iVar4;
|
||||
int *piVar5;
|
||||
DWORD DVar6;
|
||||
undefined4 *puVar7;
|
||||
HRESULT HVar8;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *pbVar9;
|
||||
uint uVar10;
|
||||
undefined4 uVar11;
|
||||
wchar_t *pwVar12;
|
||||
_func_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr
|
||||
*p_Var13;
|
||||
void **in_stack_ffffff1c;
|
||||
undefined1 local_d4 [36];
|
||||
VARIANTARG local_b0;
|
||||
_union_2683 local_a0;
|
||||
VARIANTARG local_90;
|
||||
VARIANTARG local_80;
|
||||
int *local_70 [2];
|
||||
DWORD local_68;
|
||||
undefined *local_64;
|
||||
IUnknown *local_60 [2];
|
||||
BSTR local_58;
|
||||
uint local_54;
|
||||
int *local_50 [2];
|
||||
SAFEARRAY *local_48;
|
||||
undefined1 local_44 [4];
|
||||
FILETIME local_40;
|
||||
undefined2 local_38 [8];
|
||||
undefined1 local_28 [32];
|
||||
uint local_8;
|
||||
undefined4 uStack_4;
|
||||
|
||||
uStack_4 = 0xc4;
|
||||
local_54 = param_1;
|
||||
local_68 = 0;
|
||||
local_64 = (undefined *)0x0;
|
||||
local_58 = (BSTR)0x0;
|
||||
local_8 = 0;
|
||||
FUN_1000107a((int *)local_50);
|
||||
local_8 = CONCAT31(local_8._1_3_,1);
|
||||
uVar11 = 0;
|
||||
uVar10 = 3;
|
||||
puVar3 = FUN_10003248();
|
||||
iVar4 = FUN_10003897(puVar3,uVar10);
|
||||
puVar3 = FUN_10003248();
|
||||
uVar10 = FUN_1000305b(puVar3,iVar4,uVar11);
|
||||
if ((char)uVar10 != '\0') {
|
||||
pwVar12 = L"OnDataChange callback received";
|
||||
piVar5 = (int *)FUN_10003248();
|
||||
FUN_100031b7(piVar5,pwVar12);
|
||||
}
|
||||
if (DAT_10029594 == 0) {
|
||||
local_8 = local_8 & 0xffffff00;
|
||||
FUN_1000111b((int *)local_50);
|
||||
local_8 = 0xffffffff;
|
||||
SysFreeString(local_58);
|
||||
}
|
||||
else {
|
||||
DVar6 = GetCurrentThreadId();
|
||||
if (DVar6 == DAT_10029594) {
|
||||
iVar4 = *(int *)(param_1 + 8);
|
||||
FUN_1000f663((void *)(iVar4 + 0x2c),&local_40.dwHighDateTime,(int *)(param_1 + 0xc));
|
||||
DVar6 = local_40.dwHighDateTime;
|
||||
if ((((undefined *)local_40.dwHighDateTime != *(undefined **)(iVar4 + 0x30)) &&
|
||||
(FUN_1000f5ef((undefined *)(local_40.dwHighDateTime + 0x3c),&local_40.dwHighDateTime,
|
||||
(int *)(param_1 + 0x10)), DVar1 = local_40.dwHighDateTime,
|
||||
(undefined *)local_40.dwHighDateTime != *(undefined **)(DVar6 + 0x40))) &&
|
||||
(*(char *)(local_40.dwHighDateTime + 0x1c) != '\0')) {
|
||||
if (*(char *)(local_40.dwHighDateTime + 0x1f) == '\0') {
|
||||
if (*(char *)(local_40.dwHighDateTime + 0x1e) == '\0') {
|
||||
local_40.dwHighDateTime = 0;
|
||||
local_28._0_4_ = (uint)(ushort)local_28._2_2_ << 0x10;
|
||||
local_28._4_4_ = 0;
|
||||
local_28._8_4_ = 0;
|
||||
local_28._12_4_ = (undefined *)0x0;
|
||||
(**(code **)(**(int **)(DVar6 + 0x24) + 0x60))
|
||||
(*(int **)(DVar6 + 0x24),*(undefined4 *)(DVar1 + 0x18),
|
||||
&local_40.dwHighDateTime,local_28);
|
||||
if ((local_28._0_2_ == 0xffff) && (local_28._4_4_ == 0)) {
|
||||
*(undefined1 *)(DVar1 + 0x1e) = 1;
|
||||
*(byte *)(DVar1 + 0x1d) = (byte)(local_40.dwHighDateTime >> 1) & 1;
|
||||
}
|
||||
}
|
||||
piVar5 = *(int **)(DVar6 + 0x24);
|
||||
if (local_50[0] != (int *)0x0) {
|
||||
(**(code **)(*local_50[0] + 8))(local_50[0]);
|
||||
local_50[0] = (int *)0x0;
|
||||
}
|
||||
iVar4 = (**(code **)(*piVar5 + 0x50))
|
||||
(piVar5,*(undefined4 *)(DVar1 + 0x18),local_44,&local_68,local_38,
|
||||
&local_58,local_50);
|
||||
}
|
||||
else {
|
||||
if (*(char *)(local_40.dwHighDateTime + 0x1e) == '\0') {
|
||||
local_40.dwHighDateTime = 0;
|
||||
local_28._0_4_ = (uint)(ushort)local_28._2_2_ << 0x10;
|
||||
local_28._4_4_ = 0;
|
||||
local_28._8_4_ = 0;
|
||||
local_28._12_4_ = (undefined *)0x0;
|
||||
(**(code **)(**(int **)(DVar6 + 0x30) + 0x28))
|
||||
(*(int **)(DVar6 + 0x30),*(undefined4 *)(DVar1 + 0x18),
|
||||
&local_40.dwHighDateTime,local_28);
|
||||
if ((local_28._0_2_ == 0xffff) && (local_28._4_4_ == 0)) {
|
||||
*(undefined1 *)(DVar1 + 0x1e) = 1;
|
||||
*(byte *)(DVar1 + 0x1d) = (byte)(local_40.dwHighDateTime >> 1) & 1;
|
||||
}
|
||||
}
|
||||
piVar5 = *(int **)(DVar6 + 0x30);
|
||||
if (local_50[0] != (int *)0x0) {
|
||||
(**(code **)(*local_50[0] + 8))(local_50[0]);
|
||||
local_50[0] = (int *)0x0;
|
||||
}
|
||||
iVar4 = (**(code **)(*piVar5 + 0x20))
|
||||
(piVar5,*(undefined4 *)(DVar1 + 0x18),local_44,&local_68,local_38,
|
||||
local_50);
|
||||
}
|
||||
iVar4 = FUN_1000f8d9((undefined4 *)(uint)(iVar4 == 0),iVar4,0x6d,"MxCallback.cpp");
|
||||
if (iVar4 != 0) {
|
||||
if (*(char *)(DVar1 + 0x28) == '\0') {
|
||||
FUN_1000107a((int *)local_60);
|
||||
local_8 = CONCAT31(local_8._1_3_,4);
|
||||
if (*(char *)(DVar1 + 0x1d) == '\0') {
|
||||
local_40.dwLowDateTime = 0;
|
||||
local_40.dwHighDateTime = 0;
|
||||
CoFileTimeNow(&local_40);
|
||||
local_28._8_4_ = local_40.dwLowDateTime;
|
||||
local_28._12_4_ = local_40.dwHighDateTime;
|
||||
}
|
||||
else {
|
||||
local_28._8_4_ = local_68;
|
||||
local_28._12_4_ = local_64;
|
||||
}
|
||||
HVar8 = (*local_60[0]->lpVtbl[5].QueryInterface)
|
||||
(local_60[0],(IID *)(local_28 + 8),in_stack_ffffff1c);
|
||||
if (HVar8 < 0) {
|
||||
_com_issue_errorex(HVar8,local_60[0],(_GUID *)&DAT_1001b590);
|
||||
}
|
||||
puVar3 = FUN_100012e6(local_60);
|
||||
FUN_10001269(local_70,puVar3);
|
||||
local_8._0_1_ = 5;
|
||||
FUN_100060a2((CComVariant *)&local_b0,local_70[0],0x40);
|
||||
local_8._0_1_ = 6;
|
||||
FUN_100060a2((CComVariant *)&local_a0.n2,local_50[0],0);
|
||||
local_8._0_1_ = 7;
|
||||
HVar8 = FUN_10003f60(&local_48,local_38,1);
|
||||
if (HVar8 < 0) {
|
||||
bVar2 = FUN_10003f01(*(basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> **)
|
||||
(DAT_100294e0 + 8));
|
||||
if (bVar2 != (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>)0x0) {
|
||||
p_Var13 = endl_exref;
|
||||
pbVar9 = (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *)
|
||||
FUN_10002dbf(*(int **)(DAT_100294e0 + 8),
|
||||
L"CUserConnectionCallback::OnDataChange - Create MxStatus SafeArray failed. hr = "
|
||||
);
|
||||
pbVar9 = std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar9,HVar8);
|
||||
std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar9,p_Var13);
|
||||
}
|
||||
}
|
||||
else {
|
||||
local_8 = CONCAT31(local_8._1_3_,8);
|
||||
FUN_10015f72((void *)(*(int *)(local_54 + 8) + 0xc),*(long *)(local_54 + 0xc),
|
||||
*(long *)(local_54 + 0x10),local_a0._0_4_);
|
||||
local_8._0_1_ = 7;
|
||||
local_8._1_3_ = 0;
|
||||
HVar8 = SafeArrayDestroy(local_48);
|
||||
if (HVar8 != 0) {
|
||||
pwVar12 =
|
||||
L"CUserConnectionCallback::OnDataChange - SafeArrayDestroy failed - hr %08X";
|
||||
piVar5 = (int *)FUN_10003248();
|
||||
FUN_1000308b(piVar5,pwVar12);
|
||||
}
|
||||
}
|
||||
local_8._0_1_ = 6;
|
||||
VariantClear((VARIANTARG *)&local_a0.n2);
|
||||
local_8._0_1_ = 5;
|
||||
VariantClear(&local_b0);
|
||||
local_8._0_1_ = 4;
|
||||
FUN_1000111b((int *)local_70);
|
||||
local_8 = CONCAT31(local_8._1_3_,1);
|
||||
FUN_1000111b((int *)local_60);
|
||||
}
|
||||
else {
|
||||
VariantInit(&local_80);
|
||||
local_8._0_1_ = 10;
|
||||
VariantInit(&local_90);
|
||||
local_8._0_1_ = 0xb;
|
||||
VariantInit((VARIANTARG *)local_28);
|
||||
local_8._0_1_ = 0xc;
|
||||
local_40.dwHighDateTime = 0;
|
||||
FUN_100069ad(local_50[0],(ushort *)&local_80,(undefined2 *)&local_90,
|
||||
(undefined2 *)local_28,(BSTR)&local_40.dwHighDateTime);
|
||||
HVar8 = FUN_10003f60(&local_48,local_38,1);
|
||||
if (HVar8 < 0) {
|
||||
bVar2 = FUN_10003f01(*(basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> **)
|
||||
(DAT_100294e0 + 8));
|
||||
if (bVar2 != (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>)0x0) {
|
||||
p_Var13 = endl_exref;
|
||||
pbVar9 = (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *)
|
||||
FUN_10002dbf(*(int **)(DAT_100294e0 + 8),
|
||||
L"CUserConnectionCallback::OnDataChange - Create MxStatus SafeArray failed on Buffered Data callback. hr = "
|
||||
);
|
||||
pbVar9 = std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar9,HVar8);
|
||||
std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar9,p_Var13);
|
||||
}
|
||||
}
|
||||
else {
|
||||
local_8 = CONCAT31(local_8._1_3_,0xd);
|
||||
FUN_100163c0((void *)(*(int *)(local_54 + 8) + 0x18),*(long *)(local_54 + 0xc),
|
||||
*(long *)(local_54 + 0x10),local_40.dwHighDateTime);
|
||||
local_8._0_1_ = 0xc;
|
||||
local_8._1_3_ = 0;
|
||||
HVar8 = SafeArrayDestroy(local_48);
|
||||
if (HVar8 != 0) {
|
||||
pwVar12 =
|
||||
L"CUserConnectionCallback::OnDataChange - SafeArrayDestroy failed - hr %08X";
|
||||
piVar5 = (int *)FUN_10003248();
|
||||
FUN_1000308b(piVar5,pwVar12);
|
||||
}
|
||||
}
|
||||
local_8._0_1_ = 0xb;
|
||||
VariantClear((VARIANTARG *)local_28);
|
||||
local_8._0_1_ = 10;
|
||||
VariantClear(&local_90);
|
||||
local_8 = CONCAT31(local_8._1_3_,1);
|
||||
VariantClear(&local_80);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
local_40.dwHighDateTime = (DWORD)&DAT_100295bc;
|
||||
EnterCriticalSection((LPCRITICAL_SECTION)&DAT_100295bc);
|
||||
local_8._0_1_ = 2;
|
||||
puVar7 = FUN_10015e06(local_d4,(int *)(-(uint)(param_1 != 4) & param_1),param_2);
|
||||
local_8._0_1_ = 3;
|
||||
FUN_1001654d(&DAT_100295b0,DAT_100295b0,puVar7);
|
||||
local_8._0_1_ = 2;
|
||||
FUN_1000d639((int)local_d4);
|
||||
local_8 = CONCAT31(local_8._1_3_,1);
|
||||
LeaveCriticalSection((LPCRITICAL_SECTION)&DAT_100295bc);
|
||||
}
|
||||
local_8 = local_8 & 0xffffff00;
|
||||
FUN_1000111b((int *)local_50);
|
||||
local_8 = 0xffffffff;
|
||||
SysFreeString(local_58);
|
||||
}
|
||||
FUN_10017482();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## FUN_10016b50 at 10016b50
|
||||
|
||||
Signature: `HRESULT __stdcall FUN_10016b50(uint param_1, undefined4 param_2, undefined4 * param_3)`
|
||||
|
||||
```c
|
||||
|
||||
/* WARNING: Function: __EH_prolog3_catch replaced with injection: EH_prolog3 */
|
||||
/* WARNING: Function: __EH_epilog3 replaced with injection: EH_epilog3 */
|
||||
|
||||
HRESULT FUN_10016b50(uint param_1,undefined4 param_2,undefined4 *param_3)
|
||||
|
||||
{
|
||||
uint uVar1;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> bVar2;
|
||||
undefined *puVar3;
|
||||
int iVar4;
|
||||
int *piVar5;
|
||||
DWORD DVar6;
|
||||
undefined4 *puVar7;
|
||||
HRESULT HVar8;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *pbVar9;
|
||||
uint uVar10;
|
||||
HRESULT HVar11;
|
||||
undefined4 uVar12;
|
||||
wchar_t *pwVar13;
|
||||
_func_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr
|
||||
*p_Var14;
|
||||
undefined1 local_40 [36];
|
||||
undefined *local_1c;
|
||||
undefined4 local_18 [4];
|
||||
int local_8;
|
||||
undefined4 uStack_4;
|
||||
|
||||
uStack_4 = 0x30;
|
||||
local_8 = 0x10016b5c;
|
||||
local_18[0] = 0;
|
||||
uVar12 = 0;
|
||||
uVar10 = 3;
|
||||
puVar3 = FUN_10003248();
|
||||
iVar4 = FUN_10003897(puVar3,uVar10);
|
||||
puVar3 = FUN_10003248();
|
||||
uVar10 = FUN_1000305b(puVar3,iVar4,uVar12);
|
||||
if ((char)uVar10 != '\0') {
|
||||
pwVar13 = L"OnSetAttributeResult callback received";
|
||||
piVar5 = (int *)FUN_10003248();
|
||||
FUN_100031b7(piVar5,pwVar13);
|
||||
}
|
||||
if (DAT_10029594 != 0) {
|
||||
DVar6 = GetCurrentThreadId();
|
||||
uVar10 = param_1;
|
||||
if (DVar6 == DAT_10029594) {
|
||||
piVar5 = (int *)(param_1 + 0xc);
|
||||
iVar4 = *(int *)(param_1 + 8);
|
||||
FUN_1000f663((void *)(iVar4 + 0x2c),¶m_1,piVar5);
|
||||
uVar1 = param_1;
|
||||
if ((param_1 == *(uint *)(iVar4 + 0x30)) ||
|
||||
(FUN_1000f5ef((void *)(param_1 + 0x3c),¶m_1,(int *)(uVar10 + 0x10)),
|
||||
param_1 == *(uint *)(uVar1 + 0x40))) {
|
||||
return -0x7fffbffb;
|
||||
}
|
||||
HVar8 = FUN_10003f60(local_18,(undefined2 *)param_3,1);
|
||||
if (-1 < HVar8) {
|
||||
local_8 = 2;
|
||||
FUN_1001611f((void *)(*(int *)(uVar10 + 8) + 0xc),*piVar5,*(long *)(uVar10 + 0x10),local_18)
|
||||
;
|
||||
local_8 = 0xffffffff;
|
||||
HVar8 = FUN_10016d1a();
|
||||
return HVar8;
|
||||
}
|
||||
bVar2 = FUN_10003f01(*(basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> **)
|
||||
(DAT_100294e0 + 8));
|
||||
if (bVar2 == (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>)0x0) {
|
||||
return HVar8;
|
||||
}
|
||||
HVar11 = HVar8;
|
||||
p_Var14 = endl_exref;
|
||||
pbVar9 = (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *)
|
||||
FUN_10002dbf(*(int **)(DAT_100294e0 + 8),
|
||||
L"CUserConnectionCallback::OnSetAttributeResult - Create MxStatus SafeArray failed. hr = "
|
||||
);
|
||||
pbVar9 = std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar9,HVar11);
|
||||
std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<(pbVar9,p_Var14);
|
||||
return HVar8;
|
||||
}
|
||||
local_1c = &DAT_100295bc;
|
||||
EnterCriticalSection((LPCRITICAL_SECTION)&DAT_100295bc);
|
||||
local_8 = 0;
|
||||
puVar7 = FUN_10015db2(local_40,(int *)(-(uint)(param_1 != 4) & param_1),*param_3,param_3[1],
|
||||
param_3[2],param_3[3],param_2);
|
||||
local_8._0_1_ = 1;
|
||||
FUN_1001654d(&DAT_100295b0,DAT_100295b0,puVar7);
|
||||
local_8 = (uint)local_8._1_3_ << 8;
|
||||
FUN_1000d639((int)local_40);
|
||||
local_8 = 0xffffffff;
|
||||
LeaveCriticalSection((LPCRITICAL_SECTION)&DAT_100295bc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## FUN_10016d4b at 10016d4b
|
||||
|
||||
Signature: `HRESULT __stdcall FUN_10016d4b(int * param_1, undefined4 param_2, undefined4 * param_3)`
|
||||
|
||||
```c
|
||||
|
||||
/* WARNING: Function: __EH_prolog3_catch replaced with injection: EH_prolog3 */
|
||||
/* WARNING: Function: __EH_epilog3 replaced with injection: EH_epilog3 */
|
||||
|
||||
HRESULT FUN_10016d4b(int *param_1,undefined4 param_2,undefined4 *param_3)
|
||||
|
||||
{
|
||||
int *piVar1;
|
||||
int *piVar2;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> bVar3;
|
||||
undefined *puVar4;
|
||||
int iVar5;
|
||||
int *piVar6;
|
||||
DWORD DVar7;
|
||||
undefined4 *puVar8;
|
||||
HRESULT HVar9;
|
||||
basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *pbVar10;
|
||||
uint uVar11;
|
||||
undefined4 uVar12;
|
||||
wchar_t *pwVar13;
|
||||
_func_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr_basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>_ptr
|
||||
*p_Var14;
|
||||
undefined1 local_40 [36];
|
||||
undefined *local_1c;
|
||||
undefined4 local_18 [4];
|
||||
int local_8;
|
||||
undefined4 uStack_4;
|
||||
|
||||
uStack_4 = 0x30;
|
||||
local_8 = 0x10016d57;
|
||||
uVar12 = 0;
|
||||
uVar11 = 3;
|
||||
puVar4 = FUN_10003248();
|
||||
iVar5 = FUN_10003897(puVar4,uVar11);
|
||||
puVar4 = FUN_10003248();
|
||||
uVar11 = FUN_1000305b(puVar4,iVar5,uVar12);
|
||||
if ((char)uVar11 != '\0') {
|
||||
pwVar13 = L"OperationComplete callback received";
|
||||
piVar6 = (int *)FUN_10003248();
|
||||
FUN_100031b7(piVar6,pwVar13);
|
||||
}
|
||||
if (DAT_10029594 != 0) {
|
||||
DVar7 = GetCurrentThreadId();
|
||||
piVar6 = param_1;
|
||||
if (DVar7 == DAT_10029594) {
|
||||
piVar1 = param_1 + 4;
|
||||
iVar5 = param_1[3];
|
||||
FUN_1000f663((void *)(iVar5 + 0x2c),¶m_1,piVar1);
|
||||
piVar2 = param_1;
|
||||
if ((param_1 == *(int **)(iVar5 + 0x30)) ||
|
||||
(FUN_1000f5ef(param_1 + 0xf,¶m_1,piVar6 + 5), param_1 == (int *)piVar2[0x10])) {
|
||||
return -0x7fffbffb;
|
||||
}
|
||||
HVar9 = FUN_10003f60(local_18,(undefined2 *)param_3,1);
|
||||
if (-1 < HVar9) {
|
||||
local_8 = 2;
|
||||
FUN_10016271((void *)(piVar6[3] + 0xc),*piVar1,piVar6[5],local_18);
|
||||
local_8 = 0xffffffff;
|
||||
HVar9 = FUN_10016f05();
|
||||
return HVar9;
|
||||
}
|
||||
bVar3 = FUN_10003f01(*(basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> **)
|
||||
(DAT_100294e0 + 8));
|
||||
if (bVar3 == (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>)0x0) {
|
||||
return HVar9;
|
||||
}
|
||||
p_Var14 = endl_exref;
|
||||
pbVar10 = (basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_> *)
|
||||
FUN_10002dbf(*(int **)(DAT_100294e0 + 8),
|
||||
L"CUserConnectionCallback::CUserConnectionCallback::OperationComplete - Create MxStatus SafeArray failed. hr = "
|
||||
);
|
||||
pbVar10 = std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<
|
||||
(pbVar10,HVar9);
|
||||
std::basic_ostream<wchar_t,struct_std::char_traits<wchar_t>_>::operator<<(pbVar10,p_Var14);
|
||||
HVar9 = FUN_10016f05();
|
||||
return HVar9;
|
||||
}
|
||||
local_1c = &DAT_100295bc;
|
||||
EnterCriticalSection((LPCRITICAL_SECTION)&DAT_100295bc);
|
||||
local_8 = 0;
|
||||
puVar8 = FUN_10015e4e(local_40,param_1,*param_3,param_3[1],param_3[2],param_3[3],param_2);
|
||||
local_8._0_1_ = 1;
|
||||
FUN_1001654d(&DAT_100295b0,DAT_100295b0,puVar8);
|
||||
local_8 = (uint)local_8._1_3_ << 8;
|
||||
FUN_1000d639((int)local_40);
|
||||
local_8 = 0xffffffff;
|
||||
LeaveCriticalSection((LPCRITICAL_SECTION)&DAT_100295bc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -44,17 +44,32 @@ The `OnBufferedDataChange` **public event shape** the wwtools api-notes describe
|
||||
|
||||
**Severity: P1** (was a blocker; now settled per option: verbatim preserve is the canonical native behaviour)
|
||||
|
||||
**Status (2026-05-06): SETTLED.** Ghidra headless decompile + string-ref walk across `Lmx.dll`, `LmxProxy.dll`, `NmxAdptr.dll`, `NmxSvc.exe`, and `NmxSvcps.dll` (logs at `analysis/ghidra/exports/Lmx.dll.aadct-decompile.md` + `analysis/ghidra/exports/LmxProxy.dll.completion-status-decompile.md`) confirms there is **no static byte→status lookup table** to extract. Specifically:
|
||||
**Status (2026-05-06): SETTLED.** Five-stage Ghidra headless decompile traced the byte-to-`MXSTATUS_PROXY` synthesis path end-to-end across `Lmx.dll` and `LmxProxy.dll`. Logs:
|
||||
- `analysis/ghidra/exports/Lmx.dll.aadct-decompile.md` — `aaDCT` symbol
|
||||
- `analysis/ghidra/exports/LmxProxy.dll.completion-status-decompile.md` — Fire_* event handlers
|
||||
- `analysis/ghidra/exports/LmxProxy.dll.fire-event-xrefs.md` — xrefs to Fire_*
|
||||
- `analysis/ghidra/exports/LmxProxy.dll.status-synthesis-decompile.md` — Fire_* callers (`FUN_1001657f` / `FUN_10016b50` / `FUN_10016d4b`)
|
||||
- `analysis/ghidra/exports/LmxProxy.dll.mxstatus-safearray-decompile.md` — `FUN_10003f60` (the SafeArray creator)
|
||||
- `analysis/ghidra/exports/Lmx.dll.set-attribute-result-decompile.md` — `PreboundReference::OnSetAttributeResult` (`FUN_10114a90`)
|
||||
|
||||
- The `Lmx.aaDCT` symbol referenced at `0x10178fc0` is a `SysAllocString(L"Lmx.aaDCT")` call into a global BSTR — a logging category name, not a status-mapping table. Decompiled function body is a textbook static initializer, no array / lookup logic.
|
||||
- `MXSTATUS_PROXY` (`analysis/decompiled-interop/Interop.Lmx/Interop/Lmx/MXSTATUS_PROXY.cs`) is a 4-field struct (`success: i16`, `category: MxStatusCategory`, `detectedBy: MxStatusSource`, `detail: i16`), used as the marshalled COM event payload — not a static array of pre-mapped statuses.
|
||||
- The `Fire_OnDataChange` / `Fire_OnWriteComplete` / `Fire_OperationComplete` / `Fire_OnBufferedDataChange` event-firing functions in `LmxProxy.dll` (RVAs `0x15f72`, `0x1611f`, `0x16271`, `0x163c0`) receive **already-populated** `MXSTATUS_PROXY[]` arrays — the byte-to-struct synthesis happens upstream in the proxy's NMX-callback ingestion code, not via a table lookup. The synthesis is per-call computation from operation state (engine ids, item handles, retry counters), not a static byte→status promotion.
|
||||
Findings, layer by layer (the wire bytes flow inward; the synthesis flows outward):
|
||||
|
||||
This means the .NET reference's verbatim-preservation strategy IS the canonical native behaviour: there is no table to mirror because the native code computes the `MXSTATUS_PROXY` from operation context per-event, not from a lookup. The 1-byte completion frames `0x00`, `0x41`, `0xEF` etc. are intermediate NMX-internal signaling that the proxy synthesizes contextual status from; the only frame with a proven typed promotion is the 5-byte status-word `00 00 50 80 00` → `MxStatus.WriteCompleteOk`.
|
||||
1. **`Lmx.aaDCT`** at `0x10178fc0` is a `SysAllocString(L"Lmx.aaDCT")` into a global BSTR — a tracing category name, not a status-mapping table. No array / lookup logic.
|
||||
2. **`MXSTATUS_PROXY`** (16 bytes, Pack=4) is a 4-field marshalled struct: `success: i16` at offset 0, `category: i16` at offset 4, `detectedBy: i16` at offset 8, `detail: i16` at offset 12. It is the *output* of synthesis, not a lookup-table entry.
|
||||
3. **`LmxProxy.dll` Fire_* event handlers** (`FUN_10015f72`, `FUN_1001611f`, `FUN_10016271`, `FUN_100163c0`) take an *already-populated* `MXSTATUS_PROXY[]` and forward it through ATL connection-point dispatch. No synthesis here.
|
||||
4. **`LmxProxy.dll` Fire_* callers** (`FUN_1001657f` for OnDataChange / OnBufferedDataChange, `FUN_10016b50` for OnWriteComplete, `FUN_10016d4b` for OperationComplete) call **`FUN_10003f60(out_safearray, in_status_ptr, count=1)`** which creates the SafeArray. `FUN_10003f60` is **a verbatim memcpy** of an existing 14-byte buffer into the SAFEARRAY data — no transformation. Source confirms: bytes flow `*local_8 = *param_2; *(local_8+2) = *(param_2+2); *(local_8+4) = *(param_2+4); local_8[6] = param_2[6]`.
|
||||
5. **`Lmx.dll` `PreboundReference::OnSetAttributeResult`** (`FUN_10114a90`) — the CALLER of step 4's path — receives an already-populated `short *param_7` status buffer. Its log line confirms the layout: `swprintf_s(L"<success %d category %d detectedBy %d detail %d>", (i16)*p, *(p+2), *(p+4), p[6])`. Its dispatch logic checks typed values (`*local_b6c == -1`, `*(int *)(local_b6c + 2) == 3`) — synthesis is upstream of THIS function too.
|
||||
|
||||
**Current best answer:** unchanged — `Session::operation_status_events()` exposes `Stream<Item = RawOperationStatus>` carrying frame bytes. Promote to a typed `WriteCompleted` only on the proven `00 00 50 80 00` 5-byte pattern. Other bytes stay raw as `MxStatus { Success: 0, Category: Unknown, DetectedBy: Unknown, Detail: byte }`. The Rust codec mirrors `src/MxNativeCodec/NmxOperationStatusMessage.cs:TryParseInner`.
|
||||
**The synthesizer is the NMX-frame decoder in `Lmx.dll`** that calls `OnSetAttributeResult` / `OnGetAttributeResult` / equivalent OperationComplete handler. That decoder takes raw NMX bytes (e.g. 1-byte `0x00`/`0x41`/`0xEF` completion frames or 5-byte `00 00 50 80 00`-style status words) plus operation context (which item, which engine, retry state, last-write-correlation-id) and computes the populated `MXSTATUS_PROXY`. **There is no static lookup table** — the synthesis is per-message contextual.
|
||||
|
||||
**Reopen when:** a live capture surfaces a 1-byte completion frame whose surrounding context (e.g. observed `MXSTATUS_PROXY` struct fired through the .NET probe alongside the byte) lets us back-derive a context-aware promotion. Since the native code synthesises the struct from operation state rather than a table, the promotion logic would itself need to be context-aware — i.e. the codec would need access to the originating operation's context, which is upstream of the bytes themselves. Until then, verbatim preservation is correct by construction.
|
||||
**Why this means R3/R4 stay at "verbatim preserve" canonically.** Two viable paths exist if a future consumer demands typed promotion (neither is a small Rust patch):
|
||||
|
||||
- **Path A — port the synthesizer.** Find every NMX-decoder callsite of `OnSetAttributeResult`/`OnGetAttributeResult`/`OperationComplete` in `Lmx.dll` (next xref ring beyond `FUN_10114a90`); decompile each; reverse-engineer the per-decoder synthesis logic; port to Rust. The synthesis depends on operation-tracking state (item handles, retry counters, correlation ids) the Rust codec does not currently track — so the port is more than a codec change; it's a session-state-machine extension. Estimate: ~1-2 weeks of focused work.
|
||||
- **Path B — empirical capture pairs.** Run the .NET probe in scenarios that produce each completion byte; capture the (input NMX bytes, observed `MXSTATUS_PROXY`) pair via Frida hooks on `LmxProxy.dll!FUN_10003f60`; build an empirical (byte + context → status) mapping. ~30 min × 6-10 scenarios. Output: a mapping table that approximates the synthesizer without re-implementing it. Risk: the mapping is only valid for the captured operation contexts; new contexts may produce statuses outside the table.
|
||||
|
||||
**Current best answer:** unchanged — `Session::operation_status_events()` exposes `Stream<Item = RawOperationStatus>` carrying frame bytes. Promote to a typed `WriteCompleted` only on the proven `00 00 50 80 00` 5-byte pattern. Other bytes stay raw as `MxStatus { Success: 0, Category: Unknown, DetectedBy: Unknown, Detail: byte }`. The Rust codec mirrors `src/MxNativeCodec/NmxOperationStatusMessage.cs:TryParseInner`. The .NET reference does the same, for the same reason: the synthesizer is too context-dependent to mirror without porting the entire operation-tracking state machine, and that exceeds V1 scope.
|
||||
|
||||
**Reopen when:** either (a) a consumer files a concrete use case for typed promotion of a specific byte+context combination — at which point Path B's empirical capture for that one combination is the cheapest answer; or (b) a major-version bump justifies the operation-tracking state-machine port (Path A). Until then, verbatim preservation is correct by construction.
|
||||
|
||||
### R4 — Completion-only byte mapping **(settled 2026-05-06 — collapses into R3's resolution)**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user