# OxygenBasic review and patch summary

Date: 2026-04-13

## Scope

The uploaded archive is a full OxygenBasic distribution, not a single application. I prioritized the files that have the highest leverage over the rest of the tree:

- core Win32/path/process helpers
- compiler front-ends
- user-facing search/editor tools
- a few demos that duplicated the same process-launch defects

Patch size: 14 files changed, 115 insertions, 71 deletions.

## High-value bugs fixed

### 1) `INVALID_HANDLE_VALUE` was defined incorrectly
- Files:
  - `inc/WinData.inc:1062`
  - `inc/WindataW.inc:1050`
- Problem:
  - `INVALID_HANDLE_VALUE` was set to `0` instead of `-1`.
  - Any code that relies on Win32 invalid-handle semantics can silently mis-handle failure paths.
- Fix:
  - Changed both definitions to `-1`.

### 2) `FindFirstFile` failure detection was wrong
- Files:
  - `inc/SysUtil.inc:70`
  - `inc/SearchUtil.inc:320`
- Problem:
  - Both helpers treated the returned handle as a generic truthy value.
  - `FindFirstFile` failure is signaled by `INVALID_HANDLE_VALUE`, not `0`.
- Fix:
  - Replaced the truthy check with an explicit comparison against `INVALID_HANDLE_VALUE`.

### 3) `Exec` misused `CreateProcess`
- File:
  - `inc/SysUtil.inc:189`
- Problems:
  - `STARTUPINFO` and `PROCESS_INFORMATION` were not zero-initialized.
  - `STARTUPINFO.cb` was never set.
  - Wait logic used `hThread` instead of `hProcess`.
  - `CreateProcess` failure was ignored.
  - The function always returned `0`, even after querying the child exit code.
- Fix:
  - Zero-initialize both structures.
  - Set `infs.cb=sizeof(STARTUPINFO)`.
  - Check the return value of `CreateProcess`.
  - Wait on `hProcess` when `wait<>0`.
  - Close handles only when valid.
  - Return a negative Win32 error on launch failure, and the child exit code when waiting.

### 4) `QuExec` command construction was brittle
- File:
  - `inc/SysUtil.inc:212`
- Problem:
  - The old version always concatenated quoted and unquoted segments in a fixed pattern, which made spacing and empty-argument handling fragile.
- Fix:
  - Rebuilt the command line incrementally and only appended optional sections when present.

### 5) Path helpers used undersized fixed buffers and unsafe scanning
- Files:
  - `inc/SysUtil.inc:153`
  - `inc/WinUtil.inc:290`
  - `inc/SysUtil.inc:175`
- Problems:
  - `AppExePath` used a 512-byte buffer and scanned backward without enough guard logic.
  - `CurDir` used a 256-byte buffer.
- Fix:
  - Expanded buffers to 4096.
  - Added guards for zero/long-path returns.
  - Kept behavior compatible with the original trailing-slash option.

### 6) Compiler front-ends destroyed argument case
- Files:
  - `tools/co2.o2bas:46`
  - `tools/co2m64.o2bas:42`
  - `inc/self/co2m64.o2bas:40`
  - `inc/self/co2m641.o2bas:39`
- Problem:
  - Each file lowercased the entire command line up front.
  - That is safe for switches, but not for filenames or JIT/runtime arguments that may be case-sensitive.
- Fix:
  - Preserved the raw argument string.
  - Added a separate lowercased working copy for switch parsing only.
  - Made extension checks case-insensitive explicitly.

### 7) Tool execution paths were fragile for uppercase extensions and spaced `.bat` names
- Files:
  - `tools/FindEd.o2bas:280`
  - `tools/Peroxide.o2bas:544`
  - `demos/GL/Grafide/GrafideGUI.inc:492`
- Problems:
  - Extension checks were case-sensitive.
  - `.bat` execution used unquoted filenames in some places.
- Fix:
  - Switched to `lcase(right(...))` extension checks.
  - Wrapped batch names in quotes before passing them to `DOS()`.

### 8) Two demo-local `CreateProcess` wrappers repeated the same core bug
- Files:
  - `demos/System/CustomConsole.o2bas:26`
  - `demos/GL/ConsoleG/ConsoleCommand.o2bas:11`
- Problem:
  - The demos had the same missing initialization / wrong wait-handle pattern found in `SysUtil.inc`.
- Fix:
  - Applied the same `STARTUPINFO` initialization and `WaitForSingleObject(hProcess, ...)` correction.

## Shortcomings still present

### Architectural duplication
There is still substantial duplication between `inc/OXFB` and `inc/self`, especially in compiler/parser-related sources. That increases maintenance drag and drift risk.

### Buffer-size debt
A number of UI/editor helpers still use small fixed buffers (many 256-byte or 512-byte patterns remain outside the files patched here). These are not all path-related, but they are still a long-term reliability risk.

### Process-launch policy is not centralized
Even after the patches, process spawning logic still appears in multiple demos and tools. The healthiest next step is to route all launch/quoting/wait behavior through a single hardened helper.

### Release hygiene is mixed
The tree blends source, demos, binaries, logs, manuals, config files, and packaging scripts in one distribution. That is workable for a personal toolkit, but it makes testing, reproducibility, and packaging harder.

### No obvious automated regression runner
The `inf/testlog*.o2bas` files are useful as regression material, but they are not wired into an automated pass/fail harness in this archive.

## Recommended next steps

1. Make `SysUtil.inc` the only supported process-launch layer.
2. Eliminate duplicated front-end parsing logic where possible.
3. Replace remaining path/text fixed buffers with shared helpers.
4. Create a minimal self-host regression runner for a curated set of `inf/testlog*.o2bas` cases.
5. Separate `src`, `tools`, `demos`, `tests`, and `dist` in future packaging.

## Patched files

- `inc/WinData.inc`
- `inc/WindataW.inc`
- `inc/SysUtil.inc`
- `inc/SearchUtil.inc`
- `inc/WinUtil.inc`
- `tools/co2.o2bas`
- `tools/co2m64.o2bas`
- `inc/self/co2m64.o2bas`
- `inc/self/co2m641.o2bas`
- `tools/FindEd.o2bas`
- `tools/Peroxide.o2bas`
- `demos/GL/Grafide/GrafideGUI.inc`
- `demos/System/CustomConsole.o2bas`
- `demos/GL/ConsoleG/ConsoleCommand.o2bas`

## Validation note

This patch set was produced by static review in the current sandbox. I did not run the Windows compiler/toolchain here.
