Операционная система Microsoft Windows 3.1 для программиста -том 3

Файл gmem/gmem.cpp


#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; }

Перед началом работы приложение определяет объем свободной памяти, вызывая функцию GlobalCompact со значением параметра, равным -1.


Определенное значение выводится на экран при помощи функции MessageBox.

Далее приложение вызывает функцию GlobalCompact еще раз для освобождения непрерывного блока свободной памяти размером 100000 байт.

После этого приложение заказывает буфер размером 100000 байт, вызывая функцию GlobalAlloc. В качестве первого параметра этой функции указана константа GHND, соответствующее перемещаемой памяти, инициализированной нулевым значением.

В случае успешного получения блока памяти он фиксируется и на экран выводится значение идентификатора блока и его логический адрес. После этого в первый байт полученного блока записывается код символа 'S' и блок расфиксируется. При ошибке выдается сообщение.

Далее полученный блок освобождается и возвращается операционной системе, для чего вызывается функция GlobalFree.

После этого приложение заказывает удаляемый блок памяти размером 200000 байт и сразу же удаляет его, вызывая макрокоманду GlobalDiscard. Затем приложение предпринимает попытку зафиксировать только что удаленный блок памяти, вызывая функцию GlobalLock. Если блок памяти удалился успешно, функция GlobalLock должна вернуть значение NULL. В этом случае нам надо убедиться в том, что блок был удален, и если это так и есть, восстановить удаленный блок.

Для проверки приложение использует функцию GlobalFlags. Если блок, идентификатор которого был передан этой функции в качестве параметра, удален, в возвращаемом значении установлен флаг GMEM_DISCARDED.

Для восстановления удаленного блока приложение вызывает функцию GlobalReAlloc, указывая размер и характеристики блока. Затем восстановленный блок фиксируется в памяти и на экран выводится его идентификатор и логический адрес.

Перед завершением работы приложения блок расфиксируется и освобождается.

Файл определения модуля приложения GMEM приведен в листинге 2.4.


Содержание раздела