from copy import deepcopy


def _run_all(self, fstype, tests):
    testdir = self.mkworkdir('d')

    share = self.share_command(fstype)
    name = 'sharopen'

    tstring = ''
    for t in tests:
        tstring += ("c:\\%s primary %s %s %s %s %s\n" % (name, *t))

    self.mkfile("testit.bat", f"""\
echo off
set LFN=n
d:
{share}
{tstring}
echo on
rem tests complete
rem end
""", newline="\r\n")

    # assemble handler
    handler_S = self.workdir / 'handler.S'
    handler_S.write_text("""
.code32

.text
.global _int24_handler
_int24_handler:
    movw $1, _int24_received

/* Values for critical error handler action code:
      00h ignore error and continue processing request;
      01h retry operation
      02h terminate program as though INT 21/AH=4Ch called (INT 20h for DOS 1.x)
      03h fail system call in progress (DOS 3+) */
    movb $3, %al
    iret

.data
.global _int24_received
_int24_received:
    .word 0
""")

    # compile sources
    self.mkexe_with_djgpp(name, r"""
#include <dos.h>
#include <dir.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>
#include <share.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <dpmi.h>
#include <go32.h>

#define FNAME "FOO.DAT"

extern void *int24_handler;
extern volatile uint16_t int24_received;

static __dpmi_paddr old_vec;

int install_int24(void)
{
  __dpmi_paddr new_vec;

  __dpmi_get_protected_mode_interrupt_vector(0x24, &old_vec);

  new_vec.selector = _go32_my_cs();
  new_vec.offset32 = (uintptr_t)&int24_handler;
  if (__dpmi_set_protected_mode_interrupt_vector(0x24, &new_vec) == -1)
    return -1;

  return 0;
}

void restore_int24(void)
{
  __dpmi_set_protected_mode_interrupt_vector(0x24, &old_vec);
}

unsigned short sharemode(const char *s) {
  if (strcmp(s, "SH_COMPAT") == 0)
    return SH_COMPAT;

  if (strcmp(s, "SH_DENYRW") == 0)
    return SH_DENYRW;

  if (strcmp(s, "SH_DENYWR") == 0)
    return SH_DENYWR;

  if (strcmp(s, "SH_DENYRD") == 0)
    return SH_DENYRD;

  if (strcmp(s, "SH_DENYNO") == 0)
    return SH_DENYNO;

  return 0xff;
}

unsigned short openmode(const char *s) {
  if (strcmp(s, "RW") == 0)
    return O_RDWR;
  if (s[0] == 'R')
    return O_RDONLY;
  if (s[0] == 'W')
    return O_WRONLY;
  return 0xff;
}

int main(int argc, char *argv[]) {
  int handle;
  int ret;
  int primary = -1;
  unsigned short prismode, priomode, secsmode, secomode;

  if (argc < 7) {
    printf("FAIL: Missing arguments (primary|secondary) prismode priomode secsmode secomode expected\n");
    return -2;
  }
  if (strcmp(argv[1], "primary") == 0)
    primary = 1;
  if (strcmp(argv[1], "secondary") == 0)
    primary = 0;
  if (primary < 0) {
    printf("FAIL: Invalid argument (primary|secondary)\n");
    return -2;
  }

  prismode = sharemode(argv[2]);
  if (prismode == 0xff) {
    printf("FAIL: Invalid argument prismode '%s'\n", argv[2]);
    return -2;
  }
  priomode = openmode(argv[3]);
  if (priomode == 0xff) {
    printf("FAIL: Invalid argument priomode '%s'\n", argv[3]);
    return -2;
  }
  secsmode = sharemode(argv[4]);
  if (secsmode == 0xff) {
    printf("FAIL: Invalid argument secsmode '%s'\n", argv[4]);
    return -2;
  }
  secomode = openmode(argv[5]);
  if (secomode == 0xff) {
    printf("FAIL: Invalid argument secomode '%s'\n", argv[5]);
    return -2;
  }

  // expected result is argv[6]

  // Print results in consistent format
  // FAIL:("SH_DENYNO", "RW", "SH_DENYNO", "RW", "ALLOW")[primary denied]

  if (primary) {
    unsigned short mode = prismode | priomode;
    ret = _dos_open(FNAME, mode, &handle);
    if (ret != 0) {
      printf("FAIL:('%s', '%s', '%s', '%s', '%s')[primary denied]\n",
          argv[2], argv[3], argv[4], argv[5], argv[6]);
      return -1;
    }
//    printf("INFO: primary: File was opened with mode 0x%04x\n", mode);

    // Now start second copy
    spawnlp(P_WAIT, argv[0], argv[0], "secondary", argv[2], argv[3], argv[4], argv[5], argv[6], NULL);

  } else { // secondary
    unsigned short mode = secsmode | secomode;
    int rc;

    if ((rc = install_int24()) != 0) {
        printf("FAIL: Failed to install int24 handler (%d)\n", rc);
        return 1;
    }

    ret = _dos_open(FNAME, mode, &handle);
    if (ret != 0) {
      if (strcmp(argv[6], "DENY") == 0) {
        printf("PASS:('%s', '%s', '%s', '%s', '%s')[secondary denied]\n",
            argv[2], argv[3], argv[4], argv[5], argv[6]);
      } else if (strcmp(argv[6], "INT24") == 0) {
//      printf("INFO: int24_received = 0x%04x\n", int24_received);
        if (int24_received) {
          printf("PASS:('%s', '%s', '%s', '%s', '%s')[secondary denied]\n",
              argv[2], argv[3], argv[4], argv[5], argv[6]);
        } else {
          printf("FAIL:('%s', '%s', '%s', '%s', '%s')[secondary denied]\n",
              argv[2], argv[3], argv[4], argv[5], argv[6]);
        }
      } else {
        printf("FAIL:('%s', '%s', '%s', '%s', '%s')[secondary denied]\n",
            argv[2], argv[3], argv[4], argv[5], argv[6]);
      }
      restore_int24();
      return -1;
    }
    if (strcmp(argv[6], "ALLOW") == 0) {
      printf("PASS:('%s', '%s', '%s', '%s', '%s')[secondary allowed]\n",
          argv[2], argv[3], argv[4], argv[5], argv[6]);
    } else {
      printf("FAIL:('%s', '%s', '%s', '%s', '%s')[secondary allowed]\n",
          argv[2], argv[3], argv[4], argv[5], argv[6]);
    }
    restore_int24();
  }

  _dos_close(handle);
  return 0;
}
""", extraargs=[f'{handler_S}',])

    self.mkfile("FOO.DAT", "some data", dname=testdir)

    config = """$_floppy_a = ""\n"""

    if fstype == "MFS":
        config += """$_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1"\n"""
    else:       # FAT
        name = self.mkimage("12", cwd=testdir)
        config += """$_hdimage = "dXXXXs/c:hdtype1 %s +1"\n""" % name

    return self.runDosemu("testit.bat", config=config, timeout=400)

#
# (Table 01403)
# Values of DOS 2-6.22 file sharing behavior:
#          |     Second and subsequent Opens
# First    |Compat  Deny   Deny   Deny   Deny
# Open     |        All    Write  Read   None
#          |R W RW R W RW R W RW R W RW R W RW
# - - - - -| - - - - - - - - - - - - - - - - -
# Compat R |Y Y Y  N N N  1 N N  N N N  1 N N.
#        W |Y Y Y  N N N  N N N  N N N  N N N.
#        RW|Y Y Y  N N N  N N N  N N N  N N N
# - - - - -|
# Deny   R |C C C  N N N  N N N  N N N  N N N
# All    W |C C C  N N N  N N N  N N N  N N N.
#        RW|C C C  N N N  N N N  N N N  N N N
# - - - - -|
# Deny   R |2 C C  N N N  Y N N  N N N  Y N N
# Write  W |C C C  N N N  N N N  Y N N  Y N N.
#        RW|C C C  N N N  N N N  N N N  Y N N
# - - - - -|
# Deny   R |C C C  N N N  N Y N  N N N  N Y N
# Read   W |C C C  N N N  N N N  N Y N  N Y N.
#        RW|C C C  N N N  N N N  N N N  N Y N
# - - - - -|
# Deny   R |2 C C  N N N  Y Y Y  N N N  Y Y Y
# None   W |C C C  N N N  N N N  Y Y Y  Y Y Y.
#        RW|C C C  N N N  N N N  N N N  Y Y Y

# Legend:
# Y = open succeeds, N = open fails with error code 05h.
# C = open fails, INT 24 generated.
# 1 = open succeeds if file read-only, else fails with error code.
# 2 = open succeeds if file read-only, else fails with INT 24

OPEN_622 = [
# Compat R |Y Y Y  N N N  1 N N  N N N  1 N N.
    ("SH_COMPAT", "R" , "SH_COMPAT", "R" , "ALLOW"),
    ("SH_COMPAT", "R" , "SH_COMPAT", "W" , "ALLOW"),
    ("SH_COMPAT", "R" , "SH_COMPAT", "RW", "ALLOW"),
    ("SH_COMPAT", "R" , "SH_DENYRW", "R" , "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYRW", "W" , "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYRW", "RW", "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYWR", "R" , "DENY"), # File RO success, W fails
    ("SH_COMPAT", "R" , "SH_DENYWR", "W" , "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYWR", "RW", "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYRD", "R" , "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYRD", "W" , "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYRD", "RW", "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYNO", "R" , "DENY"), # File RO success, W fails
    ("SH_COMPAT", "R" , "SH_DENYNO", "W" , "DENY"),
    ("SH_COMPAT", "R" , "SH_DENYNO", "RW", "DENY"),

#        W |Y Y Y  N N N  N N N  N N N  N N N.
    ("SH_COMPAT", "W" , "SH_COMPAT", "R" , "ALLOW"),
    ("SH_COMPAT", "W" , "SH_COMPAT", "W" , "ALLOW"),
    ("SH_COMPAT", "W" , "SH_COMPAT", "RW", "ALLOW"),
    ("SH_COMPAT", "W" , "SH_DENYRW", "R" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYRW", "W" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYRW", "RW", "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYWR", "R" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYWR", "W" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYWR", "RW", "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYRD", "R" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYRD", "W" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYRD", "RW", "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYNO", "R" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYNO", "W" , "DENY"),
    ("SH_COMPAT", "W" , "SH_DENYNO", "RW", "DENY"),

#        RW|Y Y Y  N N N  N N N  N N N  N N N
    ("SH_COMPAT", "RW", "SH_COMPAT", "R" , "ALLOW"),
    ("SH_COMPAT", "RW", "SH_COMPAT", "W" , "ALLOW"),
    ("SH_COMPAT", "RW", "SH_COMPAT", "RW", "ALLOW"),
    ("SH_COMPAT", "RW", "SH_DENYRW", "R" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYRW", "W" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYRW", "RW", "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYWR", "R" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYWR", "W" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYWR", "RW", "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYRD", "R" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYRD", "W" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYRD", "RW", "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYNO", "R" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYNO", "W" , "DENY"),
    ("SH_COMPAT", "RW", "SH_DENYNO", "RW", "DENY"),

# Deny   R |C C C  N N N  N N N  N N N  N N N
    ("SH_DENYRW", "R" , "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYRW", "R" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYRW", "R" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYRW", "R" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYNO", "R" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYNO", "W" , "DENY"),
    ("SH_DENYRW", "R" , "SH_DENYNO", "RW", "DENY"),

# All    W |C C C  N N N  N N N  N N N  N N N.
    ("SH_DENYRW", "W" , "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYRW", "W" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYRW", "W" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYRW", "W" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYNO", "R" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYNO", "W" , "DENY"),
    ("SH_DENYRW", "W" , "SH_DENYNO", "RW", "DENY"),

#        RW|C C C  N N N  N N N  N N N  N N N
    ("SH_DENYRW", "RW", "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYRW", "RW", "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYRW", "RW", "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYRW", "RW", "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYNO", "R" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYNO", "W" , "DENY"),
    ("SH_DENYRW", "RW", "SH_DENYNO", "RW", "DENY"),

# Deny   R |2 C C  N N N  Y N N  N N N  Y N N
    ("SH_DENYWR", "R" , "SH_COMPAT", "R" , "INT24"), # File RO success, W fails INT24
    ("SH_DENYWR", "R" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYWR", "R" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYWR", "R" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYWR", "R" , "ALLOW"),
    ("SH_DENYWR", "R" , "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYNO", "R" , "ALLOW"),
    ("SH_DENYWR", "R" , "SH_DENYNO", "W" , "DENY"),
    ("SH_DENYWR", "R" , "SH_DENYNO", "RW", "DENY"),

# Write  W |C C C  N N N  N N N  Y N N  Y N N.
    ("SH_DENYWR", "W" , "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYWR", "W" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYWR", "W" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYWR", "W" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYRD", "R" , "ALLOW"),
    ("SH_DENYWR", "W" , "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYNO", "R" , "ALLOW"),
    ("SH_DENYWR", "W" , "SH_DENYNO", "W" , "DENY"),
    ("SH_DENYWR", "W" , "SH_DENYNO", "RW", "DENY"),

#        RW|C C C  N N N  N N N  N N N  Y N N
    ("SH_DENYWR", "RW", "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYWR", "RW", "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYWR", "RW", "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYWR", "RW", "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYNO", "R" , "ALLOW"),
    ("SH_DENYWR", "RW", "SH_DENYNO", "W" , "DENY"),
    ("SH_DENYWR", "RW", "SH_DENYNO", "RW", "DENY"),

# Deny   R |C C C  N N N  N Y N  N N N  N Y N
    ("SH_DENYRD", "R" , "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYRD", "R" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYRD", "R" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYRD", "R" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYWR", "W" , "ALLOW"),
    ("SH_DENYRD", "R" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYNO", "R" , "DENY"),
    ("SH_DENYRD", "R" , "SH_DENYNO", "W" , "ALLOW"),
    ("SH_DENYRD", "R" , "SH_DENYNO", "RW", "DENY"),

# Read   W |C C C  N N N  N N N  N Y N  N Y N.
    ("SH_DENYRD", "W" , "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYRD", "W" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYRD", "W" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYRD", "W" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYRD", "W" , "ALLOW"),
    ("SH_DENYRD", "W" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYNO", "R" , "DENY"),
    ("SH_DENYRD", "W" , "SH_DENYNO", "W" , "ALLOW"),
    ("SH_DENYRD", "W" , "SH_DENYNO", "RW", "DENY"),

#        RW|C C C  N N N  N N N  N N N  N Y N
    ("SH_DENYRD", "RW", "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYRD", "RW", "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYRD", "RW", "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYRD", "RW", "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYNO", "R" , "DENY"),
    ("SH_DENYRD", "RW", "SH_DENYNO", "W" , "ALLOW"),
    ("SH_DENYRD", "RW", "SH_DENYNO", "RW", "DENY"),

# Deny   R |2 C C  N N N  Y Y Y  N N N  Y Y Y
    ("SH_DENYNO", "R" , "SH_COMPAT", "R" , "INT24"), # 2
    ("SH_DENYNO", "R" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYNO", "R" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYNO", "R" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYNO", "R" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYNO", "R" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYNO", "R" , "SH_DENYWR", "R" , "ALLOW"),
    ("SH_DENYNO", "R" , "SH_DENYWR", "W" , "ALLOW"),
    ("SH_DENYNO", "R" , "SH_DENYWR", "RW", "ALLOW"),
    ("SH_DENYNO", "R" , "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYNO", "R" , "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYNO", "R" , "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYNO", "R" , "SH_DENYNO", "R" , "ALLOW"),
    ("SH_DENYNO", "R" , "SH_DENYNO", "W" , "ALLOW"),
    ("SH_DENYNO", "R" , "SH_DENYNO", "RW", "ALLOW"),

# None   W |C C C  N N N  N N N  Y Y Y  Y Y Y.
    ("SH_DENYNO", "W" , "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYNO", "W" , "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYNO", "W" , "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYNO", "W" , "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYNO", "W" , "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYNO", "W" , "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYNO", "W" , "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYNO", "W" , "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYNO", "W" , "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYNO", "W" , "SH_DENYRD", "R" , "ALLOW"),
    ("SH_DENYNO", "W" , "SH_DENYRD", "W" , "ALLOW"),
    ("SH_DENYNO", "W" , "SH_DENYRD", "RW", "ALLOW"),
    ("SH_DENYNO", "W" , "SH_DENYNO", "R" , "ALLOW"),
    ("SH_DENYNO", "W" , "SH_DENYNO", "W" , "ALLOW"),
    ("SH_DENYNO", "W" , "SH_DENYNO", "RW", "ALLOW"),

#        RW|C C C  N N N  N N N  N N N  Y Y Y
    ("SH_DENYNO", "RW", "SH_COMPAT", "R" , "INT24"),
    ("SH_DENYNO", "RW", "SH_COMPAT", "W" , "INT24"),
    ("SH_DENYNO", "RW", "SH_COMPAT", "RW", "INT24"),
    ("SH_DENYNO", "RW", "SH_DENYRW", "R" , "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYRW", "W" , "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYRW", "RW", "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYWR", "R" , "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYWR", "W" , "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYWR", "RW", "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYRD", "R" , "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYRD", "W" , "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYRD", "RW", "DENY"),
    ("SH_DENYNO", "RW", "SH_DENYNO", "R" , "ALLOW"),
    ("SH_DENYNO", "RW", "SH_DENYNO", "W" , "ALLOW"),
    ("SH_DENYNO", "RW", "SH_DENYNO", "RW", "ALLOW"),
]


def fixup_matrix(orig, fixups):
    newl = deepcopy(orig)
    for fx in fixups:
        for i, r in enumerate(newl):
            if fx[0:4] == r[0:4]:
                newl[i] = fx
    return newl


OPEN_HYBRID = fixup_matrix(OPEN_622, [
    ("SH_COMPAT", "R" , "SH_DENYWR", "R" , "ALLOW"), # File RO success, W fails. For MS-DOS-7: always success.
    ("SH_COMPAT", "R" , "SH_DENYNO", "R" , "ALLOW"), # File RO success, W fails. For MS-DOS-7: always success.
    ("SH_DENYWR", "R" , "SH_COMPAT", "R" , "ALLOW"), # File RO success, W fails INT24. For MS-DOS-7: always success.
    ("SH_DENYNO", "R" , "SH_COMPAT", "R" , "ALLOW"), # File RO success, W fails INT24. For MS-DOS-7: always success.
])

# Choosing to not support Int24 on MFS. It should have no effect on
# most DJGPP compiled programs as the default Int24 handler always
# returns failure anyway, see discussion here:
# https://github.com/dosemu2/dosemu2/pull/2759#issuecomment-3794907783
OPEN_HYBRID_NO_INT24 = fixup_matrix(OPEN_HYBRID, [
    ("SH_DENYRW", "R" , "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYRW", "R" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYRW", "R" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYRW", "W" , "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYRW", "W" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYRW", "W" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYRW", "RW", "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYRW", "RW", "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYRW", "RW", "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYWR", "R" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYWR", "R" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYWR", "W" , "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYWR", "W" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYWR", "W" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYWR", "RW", "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYWR", "RW", "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYWR", "RW", "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYRD", "R" , "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYRD", "R" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYRD", "R" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYRD", "W" , "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYRD", "W" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYRD", "W" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYRD", "RW", "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYRD", "RW", "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYRD", "RW", "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYNO", "R" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYNO", "R" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYNO", "W" , "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYNO", "W" , "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYNO", "W" , "SH_COMPAT", "RW", "DENY"),
    ("SH_DENYNO", "RW", "SH_COMPAT", "R" , "DENY"),
    ("SH_DENYNO", "RW", "SH_COMPAT", "W" , "DENY"),
    ("SH_DENYNO", "RW", "SH_COMPAT", "RW", "DENY"),
])


def ds3_share_open_twice(self, fstype):
    if fstype == 'MFS':
        tests = OPEN_HYBRID_NO_INT24
    else:
        if 'FDPP' in self.version:
            tests = OPEN_HYBRID
        else:
            tests = OPEN_622

    results = _run_all(self, fstype, tests)
    self.assertIn("rem tests complete", results)
    self.assertNotIn("FAIL:", results)
