#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <dos.h>

#pragma argsused

int PASCAL
WinMain(HINSTANCE hInstance,
   HINSTANCE hPrevInstance,
   LPSTR     lpszCmdLine, int nCmdShow)
{
  BYTE szBuf[100];
  HGLOBAL hmemGlobal;
  HGLOBAL hmemGlDiscard;
  LPVOID  lpvoidGlobal;
  LPVOID  lpvoidGlDiscard;
  DWORD   dwMaxFreeMem;

  // Определяем размер доступной памяти
  dwMaxFreeMem = GlobalCompact(-1l);

  wsprintf(szBuf, "Доступно памяти:\t%lu\n",
        dwMaxFreeMem);
  MessageBox(NULL, (LPSTR)szBuf, "Global Block", MB_OK);

  // --------------------------------------------------------
  // Работаем с перемещаемым блоком памяти
  // --------------------------------------------------------

  // Дефрагментируем память для получения блока
  // размером 100000 байт
  dwMaxFreeMem = GlobalCompact(100000l);

  // Заказываем буфер размером 100000 байт
  hmemGlobal = GlobalAlloc(GHND, 100000l);

  if(hmemGlobal != NULL)
  {
    // Если буфер получен, фиксируем его в памяти
    lpvoidGlobal = GlobalLock(hmemGlobal);
    if(lpvoidGlobal != (LPVOID) NULL)
    {
      // Если блок успешно зафиксирован,
      // выводим значения идентификатора блока
      // и логический адрес блока
      wsprintf(szBuf, "hmemGlobal=\t%04.4X\n"
        "lpvoidGlobal=\t%04.4X:%04.4X",
        hmemGlobal,
        FP_SEG(lpvoidGlobal), FP_OFF(lpvoidGlobal));

      MessageBox(NULL, (LPSTR)szBuf, "Global Block", MB_OK);

      // -----------------------------------------
      // Можно работать с полученным блоком памяти
      // Записываем в первый байт блока символ S
      *(LPSTR)lpvoidGlobal = 'S';
      // -----------------------------------------

      // Разрешаем перемещение блока
      GlobalUnlock(hmemGlobal);
    }
    else
    {
      MessageBox(NULL, "Ошибка при фиксировании блока",
        "Global Block", MB_OK);
    }
    // Отдаем блок памяти операционной системе
    GlobalFree(hmemGlobal);
  }
  else
  {
    MessageBox(NULL, "Мало памяти для перемещаемого блока",
      "Global Block", MB_OK);
  }

  // --------------------------------------------------------
  // Работаем с удаляемым блоком памяти
  // --------------------------------------------------------

  // Заказываем удаляемый блок памяти размером 200000 байт
  hmemGlDiscard =
      GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 200000l);

  if(hmemGlDiscard != NULL)
  {
    // Если мы его получили, удаляем блок
    GlobalDiscard(hmemGlDiscard);

    // Пытаемся зафиксировать блок памяти
    lpvoidGlDiscard = GlobalLock(hmemGlDiscard);

    if(lpvoidGlDiscard != (LPVOID) NULL)
    {
      // Если удалось (чего не должно быть, так как
      // мы только что удалили блок), выводим
      // идентификатор блока и логический адрес
      wsprintf(szBuf, "hmemGlDiscard=\t%04.4X\n"
        "lpvoidGlDiscard=\t%04.4X:%04.4X",
        hmemGlDiscard,
        FP_SEG(lpvoidGlDiscard), FP_OFF(lpvoidGlDiscard));
      MessageBox(NULL, (LPSTR)szBuf, "Global Block", MB_OK);

      // Разрешаем перемещение блока
      GlobalUnlock(hmemGlDiscard);
    }
    else
    {
      // Если блок памяти не удалось зафиксировать,
      // проверяем, не был ли он удален
      if(GlobalFlags(hmemGlDiscard) & GMEM_DISCARDED)
      {
         MessageBox(NULL, "Блок удален и мы его восстанавливаем",
           "Global Block", MB_OK);

         // Восстанавливаем удаленный блок памяти
         hmemGlDiscard = GlobalReAlloc(hmemGlDiscard, 200000l,
           GMEM_MOVEABLE | GMEM_DISCARDABLE);

         // Фиксируем блок памяти
         lpvoidGlDiscard = GlobalLock(hmemGlDiscard);

         if(lpvoidGlDiscard != (LPVOID) NULL)
         {
           // Выводим идентификатор и логический адрес
           // зафиксированного блока памяти
           wsprintf(szBuf, "hmemGlDiscard=\t%04.4X\n"
             "lpvoidGlDiscard=\t%04.4X:%04.4X",
             hmemGlDiscard,
             FP_SEG(lpvoidGlDiscard), FP_OFF(lpvoidGlDiscard));
           MessageBox(NULL, (LPSTR)szBuf, "Global Block", MB_OK);

           // Освобождаем блок памяти
           GlobalUnlock(hmemGlDiscard);
         }
         else
         {
           MessageBox(NULL, "Ошибка при фиксировании блока",
           "Global Block", MB_OK);
         }
      }
    }

    // Отдаем удаляемый блок памяти операционной системе
    GlobalFree(hmemGlDiscard);
  }
  else
  {
    MessageBox(NULL, "Мало памяти для удаляемого блока",
      "Global Block", MB_OK);
  }

  return 0;
}