/* slotserver.rex -- An example of using Reginald
 * REXX to FUNCDEF and use Windows Mail Slots.
 *
 * This is the script that runs on the server
 * computer. It creates a mailslot and waits for
 * records sent from the respective script that
 * runs on the client (ie, clientslot.rex).
 */

/* So that we don't need the CALL keyword */
OPTIONS "C_CALL WINFUNC NOSOURCE"

/* Some OS functions deal with 32-bit addresses so we need
 * 10 digits to prevent dealing with exponential form
 */
NUMERIC DIGITS 10

/* ============== FUNCDEF some needed OS functions ============ */
DO
	/* Register the Windows OS function CreateMailslot(). We tell it to check
	 * for a return of -1, and if so, raise USER 1 condition.
	 */
	FUNCDEF("CreateMailslot", "void, str, 32u, 32, void", "kernel32",,"U1 -1")

	/* Register the Windows OS function GetMailslotInfo(). We tell it to check
	 * for a return of 0, and if so, raise USER 1 condition.
	 */
	FUNCDEF("GetMailslotInfo", "32, void, 32u *, 32 * stor, 32u * stor, 32u * dual", "kernel32",,"U1 0")

	/* Register the Windows OS function ReadFile(). We tell it to check
	 * for a return of 0, and if so, raise USER 1 condition.
	 */
	FUNCDEF("ReadFile", "32, void, void, 32u, 32u * stor, void", "kernel32",,"U1 0")

	/* Register the Windows OS function CloseHandle() */
	FUNCDEF("CloseHandle", "32, void", "kernel32")

	CATCH FAILURE
		CONDITION("M")
		RETURN
END

/* ================ Read incoming records ================ */
DO
	/* Create a mail slot named testslot in the current directory,
	 * allowing any size records to be received (up to 64K).
	 * Specify that we want ReadFile() to wait forever when reading
	 * a record.
	 */
	handle = CreateMailslot("\\.\mailslot\testslot", , -1)
again:
	/* Wait for the next record to be received at the mailslot. Wait up
	 * up to 10000 milliseconds before returning.
	 */
	err = 10000
	GetMailslotInfo(handle, , msgSize, , err)

	/* Here you may want to check for user aborting if using some sort
	 * of graphical user interface, and RAISE HALT. You may also want
	 * to clear out messages at the window. For example, with REXX GUI,
	 * you'd do a GuiGetMsg 'CLEAR' operation.
	 */

	/* Check if there was a record. If so, the size is not -1 */
	DO WHILE msgSize \= -1

		/* Allocate memory to read in the record. If an error,
		 * REXX will raise SYNTAX
		 */
		buffer = CONVERTDATA(0, msgSize, , "A")

		/* Read the record */
		ReadFile(handle, buffer, msgSize, numRead)

		/* Make sure all the chars were read */
		IF msgSize \= numRead THEN SAY "ERROR: The correct number of characters weren't received!"

		ELSE DO
			/* Assign the record chars to the REXX variable named "buffer" */
			CONVERTDATA(buffer, "buffer", , "=")

			/* Display the received record. Here you'd normally do something useful with it */
			SAY buffer
		END

		/* Read the next message's size */
		GetMailslotInfo(handle, , msgSize)

	END /* msgSize \= -1 */

	/* Delay for 5 seconds so we don't eat up too much CPU time */
	SLEEP(5)

	/* Wait for next record */
	SIGNAL again

	/* Let's CATCH USER 1 so we don't have to error check
	 * any of these calls to the above FUNCDEF'ed functions. Yay!
	 */
	CATCH USER 1
		SAY CONDITION('D') "failed:" UNIXERROR(RXFUNCERRMSG())
		SIGNAL again

	CATCH SYNTAX
		SAY CONDITION('D')
		SIGNAL again

	FINALLY
		IF EXISTS(handle) THEN CloseHandle(handle)
END

/* clientslot.rex -- An example of using Reginald
 * REXX to FUNCDEF and use Windows Mail Slots.
 *
 * This is the script that runs on the client
 * computer. It sends a record to the respective
 * script that runs on the server (ie, serverslot.rex).
 */

/* NOTE!!! You should change the asterisk to the name of the server
 * computer that is running serverslot.rex unless you want to send
 * records to every mailslot named "testslot" on the root domain
 */
mailslotname = "\\*\mailslot\testslot"

/* So that we don't need the CALL keyword */
OPTIONS "C_CALL NOSOURCE"

DO
	/* Open the mailslot that the server has already created on the network.
	 * Note: The serverslot.rex example must already be running. We must
	 * use STREAM's 'OPEN WRITE SHARED' mode.
	 */
	STREAM(mailslotname, 'C', 'OPEN WRITE SHARED')

	/* Here are the contents of what I intend to send. It can be anything
	 * you want, text or binary or whatever.
	 */
	myMessage = "This is a test."

	/* Send the record. It is broadcast to every computer in the primary
	 * domain of the system (because of our use of the asterisk on the
	 * mailslot name). To select a particular computer, you'd have
	 * to be more specific in the mailslot name passed to STREAM().
	 *
	 * A single call to CHAROUT or LINEOUT writes one record.
	 */
	CHAROUT(mailslotname, myMessage)

	/* CATCH NOTREADY so that we don't have to check for errors on STREAM and CHAROUT */
	CATCH NOTREADY
		CONDITION('M')

	FINALLY
		/* Close the mailslot. NOTE: REXX does this automatically for you when
		 * your script ends if you forget
		 */
		STREAM(mailslotname, 'C', 'CLOSE')
RETURN