#include <dos.h>
#include <stdio.h>
#include <malloc.h>

char buf[2048], far *fptr = buf;
char msg[] = "String for storing(для записи) in Windows clipboard\n\n\n";

void main(void) {

	union REGS inregs, outregs;
	struct SREGS segregs;
	unsigned long clipbrd_size, i;

	printf("\n\nРабота с WINDOWS CLIPBOARD и критической секцией\n"
			"(C) Frolov A. 1992\n\n");

// Проверяем, работает ли программа под управлением
// WINDOWS в расширенном режиме.

	 inregs.x.ax = 0x1600;
	 int86( 0x2f, &inregs, &outregs);

	 if (outregs.h.al == 0) {
		printf("\nТребуется расширенный режим Windows!\n");
		exit(-1);
	 }

// Выводим на экран версию WINDOWS

	 printf("Версия Windows - %d.%d\n",
		outregs.h.al, outregs.h.ah);

// Определяем и выводим на экран идентификатор
// виртуальной машины, на которой работает
// данная программа.

	 inregs.x.ax = 0x1683;
	 int86( 0x2f, &inregs, &outregs);
	 printf("Виртуальная машина - VM%d\n",
		outregs.x.bx);

// Входим в критическую секцию. До выхода из нее
// переключение задач в WINDOWS блокировано.

	 inregs.x.ax = 0x1681;
	 int86( 0x2f, &inregs, &outregs);

	 printf("\n\nВошли в критическую секцию.\n"
			 "Попробуйте переключить задачу клавишами <ALT-TAB>,\n"
			 "затем нажмите любую другую клавишу для выхода\n"
			 "из критической секции\n");

// После нажатия на любую клавишу выходим
// из критической секции

	 getch();

	 inregs.x.ax = 0x1682;
	 int86( 0x2f, &inregs, &outregs);

	 printf("Вышли из критической секции\n");

// Проверяем доступность CLIPBOARD. Если доступен,
// выводим версию драйвера WINDOWS, использующегося
// для поддержки DOS-программ - WINOLDAP.

	 inregs.x.ax = 0x1700;
	 int86( 0x2f, &inregs, &outregs);
	 if(outregs.x.ax == 0x1700) {
		printf("\nClipboard недоступна");
		exit(-1);
	 }
	 else printf("\nВерсия WINOLDAP - %d.%d",
		outregs.h.al, outregs.h.ah);

// Открываем CLIPBOARD

	 inregs.x.ax = 0x1701;
	 int86( 0x2f, &inregs, &outregs);
	 if(outregs.x.ax == 0x0000) {
		printf("\nОшибка при открытии Clipboard");
		exit(-1);
	 }

// Получаем объем данных, находящихся в CLIPBOARD.
// Регистр DX равен 1, следовательно, мы будем работать с
// текстовыми данными.

	 inregs.x.ax = 0x1704;
	 inregs.x.dx = 0x01;
	 int86( 0x2f, &inregs, &outregs);

// Вычисляем объем данных

	 clipbrd_size = outregs.x.dx << 16l;
	 clipbrd_size += outregs.x.ax;
	 if(clipbrd_size == 0L)
		printf("\nClipboard пуст");

	 else printf("\nОбъем данных в Clipboard: %lu\n", clipbrd_size);

// Получаем данные из CLIPBOARD. В регистре DX
// задаем значение 7, что соответствует тексту
// в кодировке OEM. При этом в процессе передачи
// данных выполняется перекодировка из представления
// ANSI (используется в WINDOWS) в представление
// OEM (используется в DOS)

	 inregs.x.ax = 0x1705;
	 inregs.x.dx = 0x07;
	 segregs.es  = FP_SEG(fptr);
	 inregs.x.bx = FP_OFF(fptr);

	 int86x( 0x2f, &inregs, &outregs, &segregs);

// Выводим содержимое CLIPBOARD, если
// там что-нибудь есть.

	 if(outregs.x.ax == 0) printf("\nВ Clipboard ничего нет!");
	 else {
		printf("Содержимое Clipborad:\n");

		for(i=0l; i < clipbrd_size; i++) {
			putch(buf[i]);
		}
	 }

// Очищаем CLIPBOARD

	 inregs.x.ax = 0x1702;
	 int86( 0x2f, &inregs, &outregs);

// Записываем в CLIPBOARD текстовые данные
// в кодировке OEM

	 inregs.x.ax = 0x1703;
	 inregs.x.dx = 0x07;
	 inregs.x.si = 0x00;
	 inregs.x.cx = strlen(msg);

	 fptr = msg;
	 segregs.es  = FP_SEG(fptr);
	 inregs.x.bx = FP_OFF(fptr);

	 int86x( 0x2f, &inregs, &outregs, &segregs);
	 if(outregs.x.ax == 0) {
		printf("\nОшибка при записи в Clipboard");
		exit(-1);
	 }

// Устанавливаем размер CLIPBOARD, равный
// длине записанной в него строки

	 inregs.x.ax = 0x1709;
	 inregs.x.si = 0x00;
	 inregs.x.cx = strlen(msg);
	 int86( 0x2f, &inregs, &outregs);

// Закрываем CLIPBOARD

	 inregs.x.ax = 0x1708;
	 int86( 0x2f, &inregs, &outregs);

	 exit(0);
}

