[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:
Joseph Doherty
2026-05-06 06:33:02 -04:00
parent 4dfc0cee65
commit 460c61df43
5 changed files with 1157 additions and 7 deletions
@@ -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),&param_1,piVar5);
uVar1 = param_1;
if ((param_1 == *(uint *)(iVar4 + 0x30)) ||
(FUN_1000f5ef((void *)(param_1 + 0x3c),&param_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),&param_1,piVar1);
piVar2 = param_1;
if ((param_1 == *(int **)(iVar5 + 0x30)) ||
(FUN_1000f5ef(param_1 + 0xf,&param_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;
}
```
+22 -7
View File
@@ -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)**