#include <windows.h>
#include <stdio.h>
#include <conio.h>

int main()
{
  // Идентификатор динамического пула
  HANDLE hHeap;

  // Указатель, в который будет записан адрес
  // полученного блока памяти
  char *lpszBuff;

  // =================================================
  // Работа с динамическим пулом
  // Используем структурную обработку исключений
  // =================================================
    
  // Создаем динамический пул
  hHeap = HeapCreate(0, 0x1000, 0x2000);

  // Если произошла ошибка, выводим ее код и
  // завершаем работу приложения
  if(hHeap == NULL)
  {
    fprintf(stdout,"HeapCreate: Error %ld\n", 
      GetLastError());
    getch();
    return 0;
  }

  // Пытаемся получить из пула блок памяти
  __try
  {
    lpszBuff = (char*)HeapAlloc(hHeap, 
      HEAP_GENERATE_EXCEPTIONS, 0x1500);
  }
  
  // Если память недоступна, происходит исключение,
  // которое мы обрабатываем
  __except (EXCEPTION_EXECUTE_HANDLER) 
  {
    fprintf(stdout,"1. HeapAlloc: Exception %lX\n", 
      GetExceptionCode());
  }

  // Пытаемся записать в буфер текстовую строку
  __try
  {
    strcpy(lpszBuff, "Строка для проверки");
  }
  
  // Если содержимое указателя lpszBuff равно NULL,
  // произойдет исключение
  __except (EXCEPTION_EXECUTE_HANDLER) 
  {
    fprintf(stdout,"1. strcpy: Exception %lX \n", 
      GetExceptionCode());
  }

  // Выполняем повторную попытку, указывая теньший
  // размер блока памяти
  __try
  {
    lpszBuff = (char*)HeapAlloc(hHeap, 
      HEAP_GENERATE_EXCEPTIONS, 0x100);
  }
  __except (EXCEPTION_EXECUTE_HANDLER) 
  {
    fprintf(stdout,"2. HeapAlloc: Exception %lX\n", 
      GetExceptionCode());
  }

  __try
  {
    strcpy(lpszBuff, "Test string");
  }
  __except (EXCEPTION_EXECUTE_HANDLER) 
  {
    fprintf(stdout,"2. strcpy: Exception %lX \n", 
      GetExceptionCode());
  }

  // Отображаем записанную строку
  if(lpszBuff != NULL)
    printf("String:>%s<\n", lpszBuff);

  // Изменяем размер блока памяти
  __try
  {
    HeapReAlloc(hHeap, 
      HEAP_GENERATE_EXCEPTIONS | 
      HEAP_REALLOC_IN_PLACE_ONLY,
      lpszBuff, 150);
  }
  __except (EXCEPTION_EXECUTE_HANDLER) 
  {
    fprintf(stdout,"HeapReAlloc: Exception %lX \n", 
      GetExceptionCode());
  }

  // Освобождаем блок памяти
  if(lpszBuff != NULL)
    HeapFree(hHeap, HEAP_NO_SERIALIZE, lpszBuff);
  
  // Удаляем пул памяти
  if(!HeapDestroy(hHeap))
    fprintf(stdout,"Ошибка %ld при удалении пула\n", 
      GetLastError());
  
  // =================================================
  // Работа со стандартным пулом
  // Исключения не обрабатываем
  // =================================================

  // Получаем блок памяти из стандартного пула
  lpszBuff = (char*)HeapAlloc(GetProcessHeap(), 
    HEAP_ZERO_MEMORY, 0x1000);
  
  // Если памяти нет, выводим сообщение об ошибке
  // и завершаем работу программы
  if(lpszBuff == NULL)
  {
    fprintf(stdout,"3. HeapAlloc: Error %ld\n", 
      GetLastError());

    getch();
    return 0;
  }

  // Выполняем копирование строки
  strcpy(lpszBuff, "Test string");
  
  // Отображаем скопированную строку
  printf("String:>%s<\n", lpszBuff);

  // Освобождаем блок памяти
  if(lpszBuff != NULL)
    HeapFree(GetProcessHeap(), 
      HEAP_NO_SERIALIZE, lpszBuff);

  // =================================================
  // Работа со стандартными функциями
  // Исключения не обрабатываем
  // =================================================
  
  lpszBuff = malloc(1000);

  if(lpszBuff != NULL)
  {
    strcpy(lpszBuff, "Test string");
    printf("String:>%s<\n", lpszBuff);
    free(lpszBuff);
  }

  printf("Press any key...");
  getch();
  return 0;
}

