Files
mxaccess/analysis/ghidra/exports/LmxProxy.dll.buffered-value-conversion-decompile.md
T
Joseph Doherty fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Initial project state: .NET reference, design, Rust port (M0+M1), evidence
Layout:
- src/                    .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
                          MxAsbClient, probes, tests, harnesses. Executable spec.
- design/                 Architectural plan for the Rust port (M0–M6), error
                          model, protocol invariants, risks (R1–R16), adversarial
                          review log (review.md).
- rust/                   Rust workspace. M0 skeleton + M1 codec parity.
                          mxaccess-codec: 215 unit tests + 2 cross-implementation
                          parity tests (byte-identical against .NET reference).
                          Other crates are M0 stubs awaiting M2+.
- captures/               Frida + netsh + pcap evidence per CLAUDE.md
                          ("captures are evidence, not throwaway logs").
- analysis/               Decompiled C# (frida/proxy/decompiled-*),
                          Ghidra exports for native DLLs (`exports/` only —
                          working state at `projects/` and AVEVA's input
                          binaries at `input/` are gitignored).
- docs/                   Reverse-engineering reference docs.
- tools/                  Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
                          Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/      Rust CI: fmt + build + test + clippy on Windows.
- LICENSE                 MIT (Joseph Doherty, 2026).

Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly

Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:21:00 -04:00

9.8 KiB

LmxProxy.dll selected decompile

FUN_100069ad at 100069ad

Signature: undefined __cdecl FUN_100069ad(int * param_1, ushort * param_2, undefined2 * param_3, undefined2 * param_4, BSTR param_5)


/* WARNING: Function: __EH_prolog3_GS replaced with injection: EH_prolog3 */

void __cdecl
FUN_100069ad(int *param_1,ushort *param_2,undefined2 *param_3,undefined2 *param_4,BSTR param_5)

{
  ULONG UVar1;
  uint uVar2;
  int *piVar3;
  undefined1 *pv;
  wchar_t *pwVar4;
  undefined1 local_bc [8];
  undefined1 local_b4 [8];
  undefined1 local_ac [8];
  SAFEARRAYBOUND local_a4;
  SAFEARRAYBOUND local_9c;
  SAFEARRAYBOUND local_94;
  undefined1 local_8c [4];
  undefined1 local_88 [4];
  uint local_84;
  ushort *local_80;
  undefined2 *local_7c;
  undefined2 *local_78;
  uint local_74;
  int local_70;
  uint local_6c;
  int local_68;
  int local_64;
  BSTR local_60;
  undefined4 local_5c;
  undefined4 local_58;
  char local_51;
  SAFEARRAY *local_50;
  SAFEARRAY *local_4c;
  SAFEARRAY *local_48;
  uint local_44;
  undefined4 local_40;
  LONG local_3c;
  LPVOID local_38 [12];
  int local_8;
  undefined4 uStack_4;
  
  uStack_4 = 0xac;
  local_8 = 0x100069bc;
  local_80 = param_2;
  local_7c = param_3;
  local_78 = param_4;
  local_60 = param_5;
  local_68 = 0;
  local_64 = 0;
  local_6c = 0;
  local_70 = 0;
  uVar2 = (**(code **)(*param_1 + 0x60))(param_1,&local_68);
  if ((int)uVar2 < 0) {
    FUN_10005da7(uVar2,(OLECHAR *)0x0,"Conversions.cpp",0x4ae);
  }
  if (((local_68 != 0xe) ||
      ((**(code **)(*param_1 + 0x94))(param_1,&local_64,&local_6c,&local_70), local_64 != 0x1a93996)
      ) || (UVar1 = *(ULONG *)(local_70 + 4), UVar1 == 0)) goto LAB_10006eb3;
  uVar2 = (uint)*(byte *)(local_70 + 1);
  *(uint *)local_60 = uVar2;
  local_84 = uVar2;
  FUN_100068e0(local_38,0x1a93996,local_6c,local_70);
  local_8 = 0;
  local_94.lLbound = 0;
  local_9c.lLbound = 0;
  local_a4.lLbound = 0;
  local_a4.cElements = UVar1;
  local_9c.cElements = UVar1;
  local_94.cElements = UVar1;
  if (uVar2 == 1) {
    local_44 = 0xb;
LAB_10006b07:
    local_48 = SafeArrayCreate((VARTYPE)local_44,1,&local_94);
    if (local_48 == (SAFEARRAY *)0x0) {
      pwVar4 = L"Unable to create Value SafeArray of type %d - numVtqs %d!";
      piVar3 = (int *)FUN_10003248();
      FUN_1000308b(piVar3,pwVar4);
    }
    else {
      local_4c = SafeArrayCreate(2,1,&local_9c);
      if (local_4c == (SAFEARRAY *)0x0) {
        pwVar4 = L"Unable to create Quality SafeArray - numVtqs %d!";
        piVar3 = (int *)FUN_10003248();
        FUN_1000308b(piVar3,pwVar4);
      }
      else {
        local_50 = SafeArrayCreate(0x15,1,&local_a4);
        if (local_50 != (SAFEARRAY *)0x0) {
          if ((short)local_44 == 8) {
            local_48->fFeatures = local_48->fFeatures | 0x100;
          }
          else {
            local_48->fFeatures = 0;
          }
          uVar2 = local_44 & 0xffff;
          local_5c = 0;
          local_58 = 0;
          local_40 = 0;
          local_3c = 0;
          if (uVar2 == 3) {
            local_3c = 0;
            if (0 < (int)UVar1) {
              do {
                FUN_10006801(local_38,local_8c,&local_5c,&local_40,2);
                SafeArrayPutElement(local_48,&local_3c,local_8c);
                SafeArrayPutElement(local_50,&local_3c,&local_5c);
                SafeArrayPutElement(local_4c,&local_3c,&local_40);
                local_3c = local_3c + 1;
              } while (local_3c < (int)UVar1);
            }
          }
          else if (uVar2 == 4) {
            local_3c = 0;
            if (0 < (int)UVar1) {
              do {
                FUN_10006801(local_38,local_88,&local_5c,&local_40,3);
                SafeArrayPutElement(local_48,&local_3c,local_88);
                SafeArrayPutElement(local_50,&local_3c,&local_5c);
                SafeArrayPutElement(local_4c,&local_3c,&local_40);
                local_3c = local_3c + 1;
              } while (local_3c < (int)UVar1);
            }
          }
          else if (uVar2 == 5) {
            local_3c = 0;
            if (0 < (int)UVar1) {
              do {
                FUN_1000684f(local_38,local_b4,&local_5c,&local_40,4);
                SafeArrayPutElement(local_48,&local_3c,local_b4);
                SafeArrayPutElement(local_50,&local_3c,&local_5c);
                SafeArrayPutElement(local_4c,&local_3c,&local_40);
                local_3c = local_3c + 1;
              } while (local_3c < (int)UVar1);
            }
          }
          else if (uVar2 == 8) {
            local_3c = 0;
            if (0 < (int)UVar1) {
              do {
                local_60 = (BSTR)0x0;
                local_8._0_1_ = 9;
                FUN_10006962(local_38,&local_60,&local_5c,&local_40);
                SafeArrayPutElement(local_48,&local_3c,local_60);
                SafeArrayPutElement(local_50,&local_3c,&local_5c);
                SafeArrayPutElement(local_4c,&local_3c,&local_40);
                local_8 = (uint)local_8._1_3_ << 8;
                SysFreeString(local_60);
                local_3c = local_3c + 1;
              } while (local_3c < (int)UVar1);
            }
          }
          else if (uVar2 == 0xb) {
            local_3c = 0;
            if (0 < (int)UVar1) {
              do {
                FUN_100067b3(local_38,&local_51,&local_5c,&local_40,1);
                local_74 = (local_51 == '\0') - 1 & 0xffff;
                SafeArrayPutElement(local_48,&local_3c,&local_74);
                SafeArrayPutElement(local_50,&local_3c,&local_5c);
                SafeArrayPutElement(local_4c,&local_3c,&local_40);
                local_3c = local_3c + 1;
              } while (local_3c < (int)UVar1);
            }
          }
          else if ((uVar2 == 0x15) && (local_3c = 0, 0 < (int)UVar1)) {
            do {
              if (local_84 == 7) {
                FUN_1000684f(local_38,local_bc,&local_5c,&local_40,7);
                pv = local_bc;
              }
              else {
                FUN_1000684f(local_38,local_ac,&local_5c,&local_40,6);
                pv = local_ac;
              }
              SafeArrayPutElement(local_48,&local_3c,pv);
              SafeArrayPutElement(local_50,&local_3c,&local_5c);
              SafeArrayPutElement(local_4c,&local_3c,&local_40);
              local_3c = local_3c + 1;
            } while (local_3c < (int)UVar1);
          }
          *local_80 = (ushort)local_44 | 0x2000;
          *(SAFEARRAY **)(local_80 + 4) = local_48;
          *local_78 = 0x2015;
          *(SAFEARRAY **)(local_78 + 4) = local_50;
          *local_7c = 0x2002;
          *(SAFEARRAY **)(local_7c + 4) = local_4c;
          local_8 = 0xffffffff;
          if (local_38[0] != (LPVOID)0x0) {
            CoTaskMemFree(local_38[0]);
            local_38[0] = (LPVOID)0x0;
          }
          goto LAB_10006eb3;
        }
        pwVar4 = L"Unable to create Time SafeArray - numVtqs %d!";
        piVar3 = (int *)FUN_10003248();
        FUN_1000308b(piVar3,pwVar4);
      }
    }
  }
  else {
    if (uVar2 == 2) {
      local_44 = 3;
      goto LAB_10006b07;
    }
    if (uVar2 == 3) {
      local_44 = 4;
      goto LAB_10006b07;
    }
    if (uVar2 == 4) {
      local_44 = 5;
      goto LAB_10006b07;
    }
    if (uVar2 == 5) {
      local_44 = 8;
      goto LAB_10006b07;
    }
    if ((5 < uVar2) && (uVar2 < 8)) {
      local_44 = 0x15;
      goto LAB_10006b07;
    }
    pwVar4 = L"BufferedMxVal2VarArray invalid data type %d";
    piVar3 = (int *)FUN_10003248();
    FUN_1000308b(piVar3,pwVar4);
  }
  local_8 = 0xffffffff;
  if (local_38[0] != (LPVOID)0x0) {
    CoTaskMemFree(local_38[0]);
    local_38[0] = (LPVOID)0x0;
  }
LAB_10006eb3:
  FUN_10017473();
  return;
}


FUN_10003f60 at 10003f60

Signature: HRESULT __cdecl FUN_10003f60(undefined4 * param_1, undefined2 * param_2, ULONG param_3)


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;
}