Skip to content

Session with Marek #174

Description

@FiveTechSoft

Issue: Lessons learned connecting FiveTechSoft Harbour + HMG rddads to OpenADS server

Summary

Successfully connected a FiveTechSoft Harbour 3.2 + HMG 3.4.4 (32-bit, MinGW) client to OpenADS 1.8.83 remote server. Documenting issues encountered and fixes applied to help other users.

Environment

  • Server: OpenADS 1.8.83-1-gd89f323 (openads_serverd.exe x64)
  • Client: FiveTechSoft Harbour 3.2.0dev (r2410251209) + HMG 3.4.4.ssl3 (built from source)
  • ACE DLL: ace32.dll built from OpenADS source via CMake (msvc-x86-static preset with /MT)
  • Import library: Generated with dlltool --no-leading-underscore from openace32.dll

Issues encountered and fixes

1. Import library: ordinal vs name-based exports

Problem: The OpenADS openace32.dll exports both ordinal ([41] AdsConnect) and decorated name (_AdsConnect@8) exports. The initial import library was generated using ordinal matching, which worked for x64 but caused crashes on i686 (32-bit).

Fix: Generate the import library using name-based exports with --no-leading-underscore:

dlltool -d ace32.def -l libace32.a --no-leading-underscore

This ensures PE import names (_AdsConnect@8) match exactly what the DLL exports, avoiding ordinal mismatches.

2. Missing VC++ runtime (static CRT fix)

Problem: The MSVC-built ace32.dll required VCRUNTIME140.dll. On machines without the VC++ redistributable installed, the client crashed silently.

Fix: Rebuilt ace32.dll with static CRT using the msvc-x86-static CMake preset (/MT flags). The resulting DLL only depends on KERNEL32.dll and WS2_32.dll.

3. URI must include the data directory path

Problem: Using tcp://127.0.0.1:16262/ (empty path) in AdsConnect60() caused "Connect: path outside data directory" error.

Root cause: In session.cpp, resolve_under_root() returns std::nullopt for empty client paths (path.cpp:105). The server requires a non-empty path to resolve against its --data roots.

Fix: Include the data directory in the URI:

tcp://127.0.0.1:16262/D:/path/to/data

This matches the pattern used in unit tests (tests/unit/) and the E2E test (tests/e2e/README.md).

4. CDX index file must exist before remote USE

Problem: USE CCOLONIA.DBF ALIAS CCOL NEW EXCLUSIVE VIA "ADSCDX" hung indefinitely (never returned) when the .cdx file did not exist.

Root cause: Server error 5103 (OpenIndex: CCOLONIA.cdx) — the ADSCDX RDD automatically tries to open a matching CDX file. If it doesn't exist, the server returns an error but the client-side RDD doesn't handle it properly and hangs.

Fix: Create the CDX index file locally before connecting remotely:

USE CCOLONIA ALIAS CCOL NEW EXCLUSIVE VIA "DBFCDX"
INDEX ON CCOL->COLONIA TAG COLONIA
INDEX ON CCOL->NOMBRE TAG NOMBRE
CCOL->(DbCloseArea())

5. ? console output in GUI mode

Problem: Using ? (console output) inside functions called from a -gui build caused HMG ErrorSys to catch an error and show a "Program Error" dialog, even though the ? calls were harmless.

Fix: Replace all ? console output with file-based tracing (MemoWrit) for GUI applications. Use append-on-write pattern:

FUNCTION _tlog( cFile, cMsg )
   LOCAL cOld := ""
   IF File( cFile )
      cOld := MemoRead( cFile )
   ENDIF
   MemoWrit( cFile, cOld + Time() + " " + cMsg + Chr(13)+Chr(10) )
RETURN

6. DBF file must be valid before remote open

Problem: The initial CCOLONIA.DBF was created with incorrect parameters (empty field descriptors, RecSize=0). The server would accept the USE but the client would hang.

Fix: Ensure the DBF has proper structure with valid field definitions before connecting remotely.

Key patterns from unit tests

The OpenADS unit tests (tests/unit/) reveal the correct API usage patterns:

Aspect Pattern
Local connect AdsConnect60(dir_path, ADS_LOCAL_SERVER, nullptr, nullptr, 0, &hConn)
Remote connect AdsConnect60("tcp://127.0.0.1:<port>/<data-path>", ADS_REMOTE_SERVER, ...)
Open table AdsOpenTable(hConn, "filename.dbf", ...) — bare filename only
Data path Goes in the connection URI, not in the table name

Suggested improvements

  1. Better error reporting for ADS 5103: When a CDX file is missing, the client-side RDD should return an error instead of hanging.
  2. Empty URI path handling: Consider defaulting to the server's --data root when the client sends an empty path in the URI (with a deprecation warning).
  3. ACE DLL version string: The built-in AdsVersion() returns "1.8a" which is the DLL header version, not the server version. Consider including the OpenADS git version.

Files modified

  • colonias.prg — Main program with file-based tracing
  • colonias_common.prg — Remote connection flow with verbose trace logging
  • Import library: libace32.a generated with dlltool --no-leading-underscore

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions