Read/WriteFile и управление памятью

Тема в разделе "WASM.X64", создана пользователем Mikl___, 30 дек 2024.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.914
    Пять вариантов программы, которая выполняет следующее:
    1. открывает файл,
    2. читает его содержимое в память и в поле Edit,
    3. Вы что-либо меняете в Edit'e изменения передаются в память,
    4. содержимое памяти сохраняется в файл.
    Во вложении1 четыре варианта, asm-\rc-файлы и иконка
    Во вложении2 пятый вариант, asm-\rc-файлы и иконка

    GlobalAlloc, GlobalFree

    Получение блока памяти

    Для получения блока памяти используют функцию GlobalAlloc,
    Код (C):
    1. HGLOBAL WINAPI GlobalAlloc (
    2.     UINT fuAlloc, // тип выделяемой памяти
    3.     DWORD cbAlloc // размер блока памяти в байтах
    Параметр fuAlloc определяет тип выделяемой памяти. Размер блока памяти в байтах должен передаваться через параметр cbAlloc. Функция возвращает идентификатор глобального блока памяти или NULL, если Windows не может выделить память указанного объема.
    Параметра fuAlloc должен быть указан как логическая комбинация следующих значений:
    ЗначениеhexОписание
    GMEM_FIXED
    0​
    Заказывается фиксированный блок памяти. Этот флаг несовместим с флагом GMEM_MOVEABLE. Фиксированный сегмент, созданный с использованием флага GMEM_FIXED, является перемещаемым. Для такого сегмента в процессе перемещения логический адрес не изменяется, но линейный (и физический) может изменяться
    GMEM_MOVEABLE
    2​
    Заказывается перемещаемый блок памяти. Логический адрес перемещаемого блока памяти может изменяться. Несовместим с флагом GMEM_FIXED
    GMEM_NOCOMPACT
    10​
    Для удовлетворения запроса памяти не следует выполнять объединение всех свободных участков памяти в один и удалять блоки памяти, отмеченные как удаляемые
    GMEM_NODISCARD
    20​
    Для удовлетворения запроса памяти не следует выполнять объединение всех свободных участков памяти в один
    GMEM_ZEROINIT
    40​
    Во все байты блока необходимо записать нулевые значения
    GPTR
    40​
    Комбинация флагов GMEM_FIXED и GMEM_ZEROINIT
    GHDN
    42​
    Комбинация флагов GMEM_MOVEABLE и GMEM_ZEROINIT
    GMEM_MODIFY
    80​
    Выполняется изменение характеристик существующего блока памяти. этот флаг необходимо указывать вместе с флагами GMEM_DISCARDABLE и GMEM_MOVEABLE
    GMEM_LOCKCOUNT
    FF​
    GMEM_DISCARDABLE
    100​
    Заказывается удаляемый блок памяти. Этот флаг должен использоваться совместно с флагом GMEM_MOVEABLE. Если блок памяти был перемещаемый, то теперь дополнительно он будет и удаляемый. Этот флаг должен использоваться совместно с флагом GMEM_MODIFY
    GMEM_NOT_BANKED
    1000​
    Получить блок памяти вне фрейма дополнительной памяти EMS
    GMEM_LOWER
    1000​
    Синоним GMEM_NOT_BANKED
    GMEM_SHARE
    2000​
    Синоним GMEM_DDESHARE
    GMEM_DDESHARE
    2000​
    Блок памяти будет использоваться совместно несколькими приложениями при помощи механизма динамического обмена данными DDE
    GMEM_NOTIFY
    4000​
    Если заказанный объект будет удален, требуется вызов процедуры извещения. Процедура извещения назначается функцией GlobalNotify и должна располагаться в фиксированном сегменте кода в библиотеке DLL. С ее помощью приложение может разрешить или запретить Windows удалять блок данных
    GMEM_DISCARDED
    4000​
    GMEM_VALID_FLAGS
    7F72​
    GMEM_INVALID_HANDLE
    8000​

    Фиксирование и расфиксирование блока памяти

    Для получения доступа к полученному блоку памяти его необходимо зафиксировать, вызвав функцию GlobalLock.
    GlobalLock возвращает указатель на данный объект памяти глобальных данных. Функция GlobalLock наращивает(увеличивает на единицу) счетчик блокировки перемещаемых объектов и фиксирует память. Фиксированная память не будет перемещаться или сбрасывается до тех пор, пока объект памяти не будет перераспределен функцией GlobalReAlloc. Объект остается блокированным (фиксированным) в памяти до тех пор, пока счетчик блокировки не уменьшится до нуля
    Код (C):
    1. GlobalLock(
    2.     HGLOBAL hglb // дескриптор блокированного объекта памяти
    Возвращаемое значение указывает на первый байт памяти в глобальном объекте, если функция завершается успешно. Возвращаемое значение=0, если память объекта была сброшена, или произошла ошибка
    GlobalUnlock разблокирует данный объект памяти глобальных данных. Функция не имеет никакого действия на фиксированную память
    Код (C):
    1. GlobalUnlock(
    2.    HGLOBAL hglb // дескриптор разблокируемой памяти глобальных данных
    Возвращаемое значение =0, если счетчик блокировки (фиксации) объекта был уменьшен (на единицу) до нуля. В противном случае, возвращаемое значение ≠ 0

    Определение идентификатора блока памяти по его адресу

    С помощью функции GlobalHandle можно, зная селектор блока памяти, определить идентификатор блока памяти
    Код (C):
    1. DWORD WINAPI GlobalHandle(
    2.   UINT uGlobalSel // селекторная компонента логического адреса блока памяти
    Параметр uGlobalSel указывает селекторную компоненту логического адреса блока памяти. Младшее слово возвращаемого значения содержит идентификатор блока памяти, старшее - селектор блока памяти. В случае ошибки возвращается нулевое значение.

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

    Чтобы заказать удаляемый блок памяти, нужно указать флаги GMEM_DISCARDABLE и GMEM_MOVEABLE
    Код (ASM):
    1. invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_DISCARDABLE, 200000
    При необходимости Windows может удалить полученный таким образом блок из памяти, сохранив только его идентификатор, и использовать ранее распределенную этому блоку памяти для других приложений.

    Определение состояния блока памяти

    При попытке зафиксировать удаленный блок с помощью функции GlobalLock приложение получит от этой функции значение NULL. В этом случае следует вызвать функцию GlobalFlags, предназначенную для определения состояния блока памяти, и проверить, находится ли данный блок в удаленном состоянии.
    Код (C):
    1. UINT WINAPI GlobalFlags(
    2.      HGLOBAL hglb // идентификатор блока памяти
    Функция возвращает состояние блока памяти, указанного своим единственным параметром. Младший байт возвращаемого значения содержит содержимое счетчика фиксаций блока памяти. В старшем байте могут быть установлены флаги GMEM_DISCARDABLE и GMEM_DISCARDED. Если установлен флаг GMEM_DISCARDABLE, проверяемый блок памяти может быть удален Windows в процессе дефрагментации свободной области памяти. Если же установлен флаг GMEM_DISCARDED, удаление блока памяти уже произошло.

    Изменение характеристик блока памяти

    Для получения доступа к удаленному блоку памяти его необходимо восстановить, вызвав функцию GlobalReAlloc. Эта функция позволяет изменить характеристики существующего блока памяти
    Если надо изменить размер заказанного ранее блока памяти, сделав его равным 51200 байт, можно для этого использовать следующий фрагмент кода:
    Код (ASM):
    1.  invoke GlobalReAlloc,hmemGlobal, 51200, \
    2. GMEM_MODIFY or GMEM_DISCARDABLE or GMEM_MOVEABLE or GMEM_ZEROINIT
    3.   mov hmemGlobal,rax
    После вызова функции блок памяти будет перемещаемый и удаляемый, причем если раньше его размер был меньше 51200 байт, во все байты дополнительной памяти будут записаны нулевые значения. При увеличении размера блока может возникнуть ситуация нехватки памяти, поэтому проверяйте значение идентификатора, возвращаемой функцией GlobalReAlloc, на неравенство нулю.
    Можно инициировать удаление блока памяти при помощи функции GlobalReAlloc, если указать нулевой размер блока и флаг GMEM_MOVEABLE.

    Определение размера блока памяти

    С помощью функции GlobalSize можно определить размер блока памяти по его идентификатору:
    Код (C):
    1. DWORD WINAPI GlobalSize(
    2.   HGLOBAL hglb // идентификатор глобального блока памяти
    Функция возвращает размер блока памяти, идентификатор которого задан параметром hglb. Если указанный блок памяти не существует или удален, возвращается нулевое значение

    Дефрагментация памяти

    После вызова GlobalCompact, Windows выполнит объединение всех свободных блоков в один. В качестве параметра функции необходимо указать требуемый размер непрерывного блока свободной памяти:
    Код (C):
    1. DWORD WINAPI GlobalCompact(
    2.      DWORD dwMinFree // требуемый размер непрерывного блока свободной памяти
    Функция возвращает размер самого большого доступного непрерывного блока памяти, причем, если параметр не равен 0 или -1, выполняется дефрагментация памяти и удаление блоков, отмеченных как удаляемые. Если параметр функции указан как 0 или -1, функция не выполняет дефрагментацию памяти, но возвращает правильное значение с учетом возможного выполнения дефрагментации.

    Освобождение блока памяти

    Для освобождения глобального блока памяти, полученного от функции GlobalAlloc, вы должны использовать функцию GlobalFree
    Код (C):
    1. HGLOBAL WINAPI GlobalFree(
    2.      HGLOBAL hglb // идентификатор глобального блока памяти
    Идентификатор освобождаемого блока передается функции в качестве ее единственного параметра. Функция возвращает NULL при успешном завершении или значение hglb при ошибке. Перед освобождением зафиксированных блоков памяти их следует предварительно расфиксировать. Можно узнать содержимое счетчика фиксаций блока при помощи функции GlobalFlags

    Фиксирование страниц блока памяти

    при использовании виртуальной памяти вся глобальная область памяти делится на страницы размером 4 Кбайт. Эти страницы могут располагаться в физической оперативной памяти или на диске в специальном файле виртуальной памяти. Если приложение обращается к странице, которая отсутствует в физической оперативной памяти, она загружается туда из файла виртуальной памяти.
    Однако на загрузку страницы памяти из файла требуется значительное время. В некоторых случаях необходимо обеспечить постоянное присутствие блока памяти в физической оперативной памяти.
    Фиксирование блока памяти функцией GlobalFix не предотвращает сброс страниц памяти, распределенных блоку, в файл виртуальной памяти, а всего лишь запрещает перемещение блока памяти в линейном адресном пространстве.
    Для исключения страниц памяти, принадлежащих указанному блоку памяти, из процесса страничного обмена необходимо использовать функцию GlobalPageLock:
    Код (C):
    1. UINT WINAPI GlobalPageLock(
    2.      HGLOBAL hglb // идентификатор блока памяти
    Идентификатор блока, для которого необходимо запретить страничный обмен, указывается через параметр hglb.
    Windows поддерживает счетчик блокирования страничного обмена. Содержимое этого счетчика увеличивается на единицу при каждом вызове функции GlobalPageLock.
    Функция GlobalPageLock возвращает новое значение счетчика или ноль при ошибке.
    Как только надобность в блокировке страничного обмена отпадает, следует вызвать функцию GlobalPageUnlock:
    Код (C):
    1. UINT WINAPI GlobalPageUnlock(
    2.      HGLOBAL hglb // идентификатор блока памяти
    Эта функция разрешает страничный обмен для блока памяти, заданного параметром hglb. Функция возвращает текущее значение счетчика или ноль при ошибке

    Принудительное удаление блока памяти

    GlobalDiscard
    Для получения блоков памяти используют GlobalAlloc. Вам едва ли потребуется перемещаемая память, так как система управления памятью выполняет операцию перемещения с помощью механизма страничной адресации, не изменяя значение логического адреса.
    В случае, если вы решили получить блок перемещаемой памяти, перед использованием его необходимо зафиксировать функцией GlobalLock. Если вы заказываете перемещаемый блок памяти, функция GlobalAlloc возвращает не адрес блока памяти, а его идентификатор.
    Если же вы получаете фиксированный блок памяти, то функции GlobalAlloc вернет вам его адрес, который можно немедленно использовать. Операционная система сможет перемещать этот блок памяти без изменения его логического адреса.


    asm-файл
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ZZZ_OPEN equ  1
    4. ZZZ_SAVE equ  2
    5. ZZZ_EXIT equ  3
    6. MAXSIZE equ 256
    7. MEM_SIZE equ 65535
    8. EditID equ 1
    9. IDR_MAINMENU equ 30
    10. .code
    11. WinMain proc <20>
    12. local msg:MSG
    13.           xor ebx,ebx
    14.           mov edi,offset ClassName
    15.           mov esi,IMAGE_BASE
    16.           invoke LoadCursorFromFileA,"br_Rabbit3.cur"
    17.           push rax ;hIconSm
    18.           push rdi ;lpszClassName
    19.           push IDR_MAINMENU;lpszMenuName
    20.           push COLOR_WINDOW;hbrBackground
    21.           push rax ;hCursor
    22.           push rax        ;hIcon
    23.           push rsi ;hInstance
    24.           push rbx        ;cbClsExtra & cbWndExtra
    25.           pushaddr WndProc;lpfnWndProc
    26.           push sizeof WNDCLASSEX;cbSize & style
    27.           invoke RegisterClassExA,esp ;addr WNDCLASSEX
    28.           push rbx
    29.           push rsi
    30.           shl esi,9 ;rsi=512*400000h=CW_USEDEFAULT
    31.           push rbx
    32.           push rbx
    33.           push rsi
    34.           push rsi
    35.           push rsi
    36.           push rsi
    37.           sub esp,20h
    38.           invoke CreateWindowExA,WS_EX_CLIENTEDGE,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    39.           invoke SetFocus,hwndEdit
    40.           lea edi,msg
    41. @@: invoke GetMessageA,edi,0,0,0
    42.           invoke TranslateMessage,edi
    43.           invoke DispatchMessageA,edi
    44.           jmp @b
    45. WinMain endp
    46. WndProc proc <12> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    47. local szReadWrite:QWORD ;number of bytes actually read or write
    48.          mov hWnd,rcx
    49.          mov wParam,r8
    50.          mov lParam,r9
    51.          cmp edx,WM_DESTROY
    52.          je wmDESTROY
    53.          cmp edx,WM_COMMAND
    54.          je wmCOMMAND
    55.          cmp edx,WM_CREATE
    56.          je wmCREATE
    57.          cmp edx,WM_SIZE
    58.          je wmSIZE
    59.          leave
    60.          jmp NtdllDefWindowProc_
    61. wmDESTROY:invoke GlobalFree,hMem
    62.          invoke CloseHandle,hFile
    63.          invoke RtlExitUserProcess,0
    64. wmSIZE: movzx eax,word ptr lParam+2
    65.          movzx r9,r9w;word ptr lParam
    66.          mov qword ptr[rsp+28h],TRUE
    67.          mov [rsp+20h],rax
    68.          invoke MoveWindow,hwndEdit,0,0
    69.          jmp wmBYE
    70. OPEN: invoke GetOpenFileName,&dlgOpenOfn
    71.          test eax,eax
    72.          je wmBYE
    73.          and qword ptr[rsp+30h],0
    74.          mov qword ptr[rsp+28h],FILE_ATTRIBUTE_NORMAL
    75.          mov qword ptr[rsp+20h],OPEN_EXISTING
    76.          invoke CreateFile,&Buffer,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,0
    77.          mov hFile,rax;handle to file
    78.          invoke GetFileSize,eax,0
    79.          mov FileSize,rax
    80.          and qword ptr[rsp+20h],0
    81.          invoke ReadFile,hFile,hMem,eax,&szReadWrite
    82. ;забрать в окно редактора текст из буфера
    83.          invoke SetWindowTextA,hwndEdit,hMem
    84. ;заголовок окна - имя открытого файла
    85.          movzx edx,dlgOpenOfn.nFileOffset
    86.          add edx,offset Buffer
    87.          invoke SetWindowTextA,hWnd
    88.          jmp wmBYE
    89. SAVE:;узнать длину текст в окне редактора
    90.         invoke GetWindowTextLengthA,hwndEdit
    91.          inc eax
    92.          mov FileSize,rax
    93. ;вывести текст из окна редактора в буфер
    94.          invoke GetWindowTextA,hwndEdit,hMem,FileSize
    95.          invoke SetFilePointer,hFile,0,0,FILE_BEGIN
    96. ;прочитать текст из буфера в файл
    97.          and qword ptr[rsp+20h],0
    98.          invoke WriteFile,hFile,hMem,FileSize,&szReadWrite
    99.          jmp wmBYE
    100. wmCREATE:mov dlgOpenOfn.hwndOwner,rcx
    101.          push 0
    102.          push IMAGE_BASE
    103.          push EditID
    104.          push rcx
    105.          push 0
    106.          push 0
    107.          push 0
    108.          push 0
    109.          sub esp,20h
    110.          invoke CreateWindowExA,0,"edit",0,WS_VISIBLE or WS_CHILD or ES_LEFT \
    111. or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or ES_AUTOVSCROLL
    112.         mov hwndEdit,rax
    113. ;выделить память
    114.         invoke  GlobalAlloc,GPTR,MEM_SIZE
    115.         mov hMem,rax
    116.         jmp wmBYE
    117. wmCOMMAND:movzx r8d,word ptr wParam
    118.         or r9,r9 ;cmp lParam,0
    119.         jnz wmBYE
    120.         cmp r8d,ZZZ_EXIT
    121.         ja wmBYE
    122.         jmp [menu_handlers+r8*8]
    123. EXIT: invoke DestroyWindow,hWnd
    124. wmBYE:  leave
    125.         retn
    126. menu_handlers dq wmBYE,OPEN,SAVE,EXIT
    127. WndProc endp
    128. ;---------------------------------------
    129. .data
    130. ClassName db 'Файловые операции и управление памятью: GlobalAlloc, GlobalFree',0
    131. dlgOpenTitle db 'Открытие файла',0
    132. ;------------------------------------------
    133. align 8
    134. dlgOpenOfn  label  OPENFILENAME
    135. dd sizeof OPENFILENAME,?;lStructSize
    136. dq ?            ;hwndOwner
    137. dq IMAGE_BASE   ;hInstance
    138. dq FilterString ;lpstrFilter
    139. dq ?            ;lpstrCustomFilter
    140. dd ?            ;nMaxCustFilter
    141. dd ?            ;nFilterIndex
    142. dq Buffer       ;lpstrFile
    143. dd MAXSIZE,?    ;nMaxFile
    144. dq ?            ;lpstrFileTitle
    145. dd ?,?          ;nMaxFileTitle
    146. dq ?            ;lpstrInitialDir
    147. dq dlgOpenTitle ;lpstrTitle
    148. dd OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or \
    149. OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY;Flags
    150. dw ?            ;nFileOffset
    151. dw ?            ;nFileExtension
    152. dq ?            ;lpstrDefExt
    153. dd ?,?          ;lCustData
    154. dq ?            ;lpfnHook
    155. dq ?            ;lpTemplateName
    156. ;-------------------------------------------
    157. FilterString db 'All Files (*.*)',0,'*.*',0
    158. db 'Text Files (*.txt)',0,'*.txt',0,0
    159. .data?
    160. hwndEdit dq ? ;handle for edit control
    161. hHeap dq ?
    162. hMem dq ?
    163. FileSize dq ?
    164. hFile dq ?;handle of file
    165. Buffer db MAXSIZE dup(?)
    166. end
    rc-файл
    Код (C):
    1. #define ZZZ_OPEN 1
    2. #define ZZZ_SAVE 2
    3. #define ZZZ_EXIT 3
    4. #define IDR_MAINMENU 30
    5. IDR_MAINMENU MENU
    6. {
    7.    POPUP "&File"
    8.    {       MENUITEM "&Open",ZZZ_OPEN
    9.             MENUITEM "&Save",ZZZ_SAVE
    10.             MENUITEM SEPARATOR
    11.             MENUITEM "&Exit",ZZZ_EXIT
    12.     }
    13.     MENUITEM "&Exit",ZZZ_EXIT
    14. }
     

    Вложения:

    E.D., k3rnl, MaKsIm и ещё 1-му нравится это.
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.914

    GetProcessHeap, RtlAllocateHeap, HeapFree

    Куча (heap) — область зарезервированного адресного пространства размером в одну или более страниц, из которой диспетчер куч (heap menager) может динамически выделять память меньшими порциями. Диспетчер куч представляет собой набор функций для выделения и освобождения памяти (в отличие от функции VirtualAlloc они не обязательно соблюдают гранулярность выделения памяти). Функции дисптчера куч реализованы в Ntdll.dll и Ntoskernel.exe. Функции подсистем вызывают функции из Ntdll.dll, компоненты исполнительной системы и драйвера устройств — из Ntoskernel.exe
    Каждый процесс получает при создании стандартную кучу (default process heap), размер которой по умолчанию равен 1 Мб, если при сборке исполняемого файла не было указано иное. Однако этот объем памяти резервируется только для начала и по мере необходимости автоматически увеличивается (в исполняемом файле можно указать и начальный размер переданной памяти). Стандартную кучу процесса используют не только Win32-приложения, но и некоторые Wm32-функции, которым нужны блоки временной памяти. Процесс может создавать дополнительные закрытые кучи вызовом HeapCreate. Когда куча больше не нужна, занимаемое ею виртуальное адресное пространство можно освободить, вызвав HeapDestroy. В течение своего жизненного цикла процесс имеет право уничтожать лишь те кучи, которые он создал с помощью HeapCreate.
    Для выделения памяти из стандартной кучи поток должен получить ее дескриптор вызовом GetProcessHeap (эта функция возвращает адрес структуры данных, описывающей кучу, но вызывающая программа не должна полагаться на использование этой структуры). Затем поток передает этот описатель функциям НеарАllос и HeapFree, выделяя и освобождая блоки памяти в данной куче. Диспетчер куч также позволяет упорядочивать операции выделения и освобождения памяти в каждой куче, чтобы несколько потоков могли одновременно вызывать функции управления кучами, не повреждая ее структуры данных. Для стандартной кучи процесса такое упорядочение осуществляется по умолчанию (Вы можете отключать его в рамках каждого вызова). Но создавая дополнительную закрытую кучу, Вы должны указать HeapCreate, следует ли упорядочивать в ней операции выделения и освобождения памяти.
    Диспетчер куч поддерживает ряд недокументированных флагов, которые можно определить в рамках всей системы или конкретной программы с помощью утилиты Global Flags (Gflags.t-xe) из Windows 2000 Support Tools, Platform SDK или DDK. Действия, выполняемые диспетчером куч при задании большинства флагов, понятны без дополнительных объяснений. После установки этих флагов неправильное использование кучи или ее повреждение обычно вызывает генерацию ошибок или исключений.
    Основные используемые функции:
    • GetProcessHeap — Извлекает дескриптор в кучу по умолчанию вызывающего процесса. Затем этот дескриптор можно использовать в последующих вызовах функций кучи
    • RtlAllocateHeap — выделяет блок памяти из кучи
    • HeapFree — Освобождает блок памяти, выделенный из кучи функцией RtlAllocateHeap или HeapReAlloc

    Создание блока памяти из кучи

    Если вам нужен блок памяти из кучи, вы можете его создать при помощи функции HeapCreate:
    Код (C):
    1. HANDLE HeapCreate(
    2.   DWORD  flOptions,     // флаг создания блока
    3.   DWORD  dwInitialSize, // первоначальный размер блока в байтах
    4.   DWORD  dwMaximumSize);// максимальный размер блока в байтах
    Параметры dwMaximumSize и dwInitialSize определяют размер зарезервированного блока памяти.
    Параметр flOptions может быть равным 0, HEAP_NO_SERIALIZE и HEAP_GENERATE_EXCEPTIONS.
    Параметр HEAP_NO_SERIALIZE относится к мультизадачности. Если параметр не указан, работающие параллельно задачи одного процесса не могут одновременно получать доступ к такому блоку. Можно использовать флаг HEAP_NO_SERIALIZE для повышения производительности, если создаваемым блоком будет пользоваться только одна задача процесса.
    При выделении памяти из блока могут возникать ошибочные ситуации. Если не указан флаг HEAP_GENERATE_EXCEPTIONS, при ошибках соответствующей функции будут возвращать значение NULL. В противном случае в приложении будут генерироваться исключения. Флаг HEAP_GENERATE_EXCEPTIONS удобен в тех случаях, когда в приложении предусмотрена обработка исключений, позволяющая исправлять возникающие ошибки.
    В случае удачи функция HeapCreate возвращает идентификатор созданного блока памяти из кучи. При ошибке возвращается 0 (либо возникает исключение, если указан флаг HEAP_GENERATE_EXCEPTIONS).

    Удаление блока памяти из кучи

    Для удаления блока памяти из кучи, созданного функцией HeapCreate, используют HeapDestroy:
    Код (C):
    1. BOOL HeapDestroy(
    2.    HANDLE hHeap// идентификатор удаляемого блока памяти
    Через единственный параметр этой функции передается идентификатор удаляемого блока памяти из кучи. Не следует удалять стандартный блок памяти из кучи, передавая этой функции значение, полученное от функции GetProcessHeap.
    Функция HeapDestroy выполняет безусловное удаление блока памяти из кучи, даже если из него были получены блоки памяти и на момент удаления блок памяти из кучи они не были возвращены системе.

    Получение блока памяти из кучи

    Для получения блока памяти из кучи используют функцию HeapAlloc:
    Код (C):
    1. LPVOID HeapAlloc(
    2.   HANDLE hHeap,    // идентификатор блока
    3.   DWORD  dwFlags,  // управляющие флаги
    4.   DWORD  dwBytes); // объем получаемой памяти в байтах
    В качестве параметра hHeap можно использовать либо идентификатор, полученный от GetProcessHeap, либо идентификатор блока памяти, созданный при помощи HeapCreate.
    Параметр dwBytes определяет объем памяти в байтах. Параметр dwFlags комбинация следующих значений:
    ЗначениеhexОписание
    HEAP_NO_SERIALIZE
    1​
    Если указан этот флаг, не выполняется блокировка одновременного обращения к блоку памяти нескольких задач одного процесса
    HEAP_GROWABLE
    2​
    HEAP_GENERATE_EXCEPTIONS
    4​
    Если при выполнении функции произойдет ошибка, возникнет исключение
    HEAP_ZERO_MEMORY
    8​
    Выделенная память заполняется нулями
    HEAP_REALLOC_IN_PLACE_ONLY
    10​
    HEAP_TAIL_CHECKING_ENABLED
    20​
    HEAP_FREE_CHECKING_ENABLED
    40​
    HEAP_DISABLE_COALESCE_ON_FREE
    80​
    HEAP_MAXIMUM_TAG
    FFF​
    HEAP_PSEUDO_TAG_FLAG
    8000​
    HEAP_CREATE_ALIGN_16
    10000​
    HEAP_CREATE_ENABLE_TRACING
    20000​

    Изменение размера блока памяти

    С помощью HeapReAlloc приложение может изменить размер блока памяти, выделенного ранее функцией HeapAlloc, уменьшив или увеличив его.
    Код (C):
    1. LPVOID HeapReAlloc(
    2.   HANDLE hHeap,    // идентификатор кучи
    3.   DWORD  dwFlags,  // флаг изменения размера блока памяти
    4.   LPVOID lpMem,    // адрес блока памяти
    5.   DWORD  dwBytes); // новый размер блока памяти в байтах
    Для кучи hHeap функция изменяет размер блока памяти, расположенного по адресу lpMem. Новый размер составит dwBytes байт.
    В случае удачи HeapReAlloc возвращает адрес нового блока памяти, который не обязательно будет совпадать с адресом, полученным этой функцией через параметр lpMem.
    Через параметр dwFlags можно передавать те же параметры, что и через аналогичный параметр для функции HeapAlloc. Дополнительно можно указать параметр HEAP_REALLOC_IN_PLACE_ONLY, определяющий, что при изменении размера блока памяти его нужно оставить на прежнем месте адресного пространства. Если указан этот параметр, в случае успешного завершения функция HeapReAlloc вернет то же значение, что было передано ей через параметр lpMem.

    Определение размера блока памяти

    Зная адрес блока памяти, полученного из кучи, можно определить его размер при помощи HeapSize:
    Код (C):
    1. DWORD HeapSize(
    2.   HANDLE  hHeap,   // идентификатор кучи
    3.   DWORD   dwFlags, // управляющие флаги
    4.   LPCVOID lpMem);  // адрес проверяемого блока памяти
    В случае ошибки эта функция возвращает -1.
    Если блок памяти использует только одна задача процесса, можно передать через параметр dwFlags значение HEAP_NO_SERIALIZE.

    Освобождение памяти

    Память, выделенную с помощью функции HeapAlloc освобождают, как только в ней отпадет надобность. Это делают при помощи HeapFree:
    Код (C):
    1. BOOL HeapFree(
    2.   HANDLE hHeap,   // идентификатор кучи
    3.   DWORD  dwFlags, // флаги освобождения памяти
    4.   LPVOID lpMem);  // адрес освобождаемого блока памяти
    Если блок памяти использует только одна задача процесса, можно передать через параметр dwFlags значение HEAP_NO_SERIALIZE.
    Если размер блока памяти, выделенного функцией HeapAlloc, был изменен функцией HeapReAlloc, для освобождения такого блока памяти нужно использовать функцию HeapFree

    Другие функции кучи

    GetProcessHeaps — Получение дескрипторов для всех куч, допустимых для вызывающего процесса
    HeapCompact — Объединение смежных свободных блоков памяти в куче
    HeapLock — Получение блокировки, связанной с указанной кучей
    HeapUnlock — Освобождение блокировки, связанной с указанной кучей.
    HeapQueryInformation — Извлечение сведений об указанной куче
    HeapSetInformation — Задает сведения для указанной кучи
    HeapValidate — Проверка указанной кучи
    HeapWalk — Перечисление блоков памяти в указанной куче
    asm-файл
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ZZZ_OPEN equ  1
    4. ZZZ_SAVE equ  2
    5. ZZZ_EXIT equ  3
    6. MAXSIZE equ 256
    7. MEM_SIZE equ 65535
    8. EditID equ 1
    9. IDR_MAINMENU equ 30
    10. .code
    11. WinMain proc <20>
    12. local msg:MSG
    13. xor ebx,ebx
    14. mov edi,offset ClassName
    15. mov esi,IMAGE_BASE
    16. invoke LoadCursorFromFileA,"br_Rabbit3.cur"
    17. push rax ;hIconSm
    18. push rdi ;lpszClassName
    19. push IDR_MAINMENU;lpszMenuName
    20. push COLOR_WINDOW;hbrBackground
    21. push rax ;hCursor
    22. push rax        ;hIcon
    23. push rsi ;hInstance
    24. push rbx        ;cbClsExtra & cbWndExtra
    25. pushaddr WndProc;lpfnWndProc
    26. push sizeof WNDCLASSEX;cbSize & style
    27. invoke RegisterClassExA,esp ;addr WNDCLASSEX
    28. push rbx
    29. push rsi
    30. shl esi,9 ;rsi=512*400000h=CW_USEDEFAULT
    31. push rbx
    32. push rbx
    33. push rsi
    34. push rsi
    35. push rsi
    36. push rsi
    37. sub esp,20h
    38.     invoke CreateWindowExA,WS_EX_CLIENTEDGE,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    39. invoke SetFocus,hwndEdit
    40.     lea edi,msg
    41. @@: invoke GetMessageA,edi,0,0,0
    42. invoke TranslateMessage,edi
    43. invoke DispatchMessageA,edi
    44. jmp @b
    45. WinMain endp
    46. WndProc proc <12> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    47. local szReadWrite:QWORD ;number of bytes actually read or write
    48. mov hWnd,rcx
    49. mov lParam,r9
    50. cmp edx,WM_DESTROY
    51. je wmDESTROY
    52. cmp edx,WM_COMMAND
    53. je wmCOMMAND
    54. cmp edx,WM_CREATE
    55. je wmCREATE
    56. cmp edx,WM_SIZE
    57. je wmSIZE
    58. leave
    59. jmp NtdllDefWindowProc_
    60. wmDESTROY:invoke HeapFree,hHeap,0,hMem
    61. invoke CloseHandle,hFile
    62. invoke RtlExitUserProcess,0
    63. wmSIZE: movzx eax,word ptr lParam+2
    64. movzx r9,r9w;word ptr lParam
    65. mov qword ptr[rsp+28h],TRUE
    66. mov [rsp+20h],rax
    67. invoke MoveWindow,hwndEdit,0,0
    68. jmp wmBYE
    69. OPEN: invoke GetOpenFileName,&dlgOpenOfn
    70. test eax,eax
    71. je wmBYE
    72. and qword ptr[rsp+30h],0
    73. mov qword ptr[rsp+28h],FILE_ATTRIBUTE_NORMAL
    74. mov qword ptr[rsp+20h],OPEN_EXISTING
    75. invoke CreateFile,&Buffer,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,0
    76. mov hFile,rax;handle to file
    77. invoke GetFileSize,eax,0
    78. mov FileSize,rax
    79. and qword ptr[rsp+20h],0
    80. invoke ReadFile,hFile,hMem,eax,&szReadWrite
    81. ;забрать в окно редактора текст из буфера
    82. invoke SetWindowTextA,hwndEdit,hMem
    83. ;заголовок окна - имя открытого файла
    84. movzx edx,dlgOpenOfn.nFileOffset
    85. add edx,offset Buffer
    86. invoke SetWindowTextA,hWnd
    87. jmp wmBYE
    88. SAVE:;узнать длину текст в окне редактора
    89.        invoke GetWindowTextLengthA,hwndEdit
    90.        inc eax
    91.        mov FileSize,rax
    92. ;вывести текст из окна редактора в буфер
    93.        invoke GetWindowTextA,hwndEdit,hMem,FileSize
    94.        invoke SetFilePointer,hFile,0,0,FILE_BEGIN
    95. ;прочитать текст из буфера в файл
    96.        and qword ptr[rsp+20h],0
    97.        invoke WriteFile,hFile,hMem,FileSize,&szReadWrite
    98.        jmp wmBYE
    99. wmCREATE:mov dlgOpenOfn.hwndOwner,rcx
    100.        push 0
    101.        push IMAGE_BASE
    102.        push EditID
    103.        push rcx
    104.        push 0
    105.        push 0
    106.        push 0
    107.        push 0
    108.        sub esp,20h
    109.        invoke CreateWindowExA,0,"edit",0,WS_VISIBLE or WS_CHILD or ES_LEFT \
    110. or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or ES_AUTOVSCROLL
    111.        mov hwndEdit,rax
    112. ;выделить память
    113.        invoke GetProcessHeap
    114.        mov hHeap,rax
    115.        invoke RtlAllocateHeap,eax,HEAP_ZERO_MEMORY,MEM_SIZE
    116.         mov hMem,rax
    117.         jmp wmBYE
    118. wmCOMMAND:and r8d,0FFFFh;word ptr wParam
    119.        or r9,r9 ;cmp lParam,0
    120.        jnz wmBYE
    121.        cmp r8d,ZZZ_EXIT
    122.        ja wmBYE
    123.        jmp [menu_handlers+r8*8]
    124. EXIT: invoke DestroyWindow,hWnd
    125. wmBYE:  leave
    126.        retn
    127. menu_handlers dq wmBYE,OPEN,SAVE,EXIT
    128. WndProc endp
    129. ;---------------------------------------
    130. .data
    131. ClassName db 'Файловые операции и управление памятью: GetProcessHeap, RtlAllocateHeap, HeapFree',0
    132. dlgOpenTitle db 'Открытие файла',0
    133. ;------------------------------------------
    134. align 8
    135. dlgOpenOfn  label  OPENFILENAME
    136. dd sizeof OPENFILENAME,?;lStructSize
    137. dq ?            ;hwndOwner
    138. dq IMAGE_BASE   ;hInstance
    139. dq FilterString ;lpstrFilter
    140. dq ?            ;lpstrCustomFilter
    141. dd ?            ;nMaxCustFilter
    142. dd ?            ;nFilterIndex
    143. dq Buffer       ;lpstrFile  
    144. dd MAXSIZE,?    ;nMaxFile
    145. dq ?            ;lpstrFileTitle
    146. dd ?,?          ;nMaxFileTitle
    147. dq ?            ;lpstrInitialDir
    148. dq dlgOpenTitle ;lpstrTitle
    149. dd OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or \
    150. OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY;Flags
    151. dw ?            ;nFileOffset
    152. dw ?            ;nFileExtension
    153. dq ?            ;lpstrDefExt
    154. dd ?,?          ;lCustData
    155. dq ?            ;lpfnHook
    156. dq ?            ;lpTemplateName
    157. ;-------------------------------------------
    158. FilterString db 'All Files (*.*)',0,'*.*',0
    159. db 'Text Files (*.txt)',0,'*.txt',0,0
    160. .data?
    161. hwndEdit dq ? ;handle for edit control
    162. hHeap dq ?
    163. hMem dq ?
    164. FileSize dq ?
    165. hFile dq ?;handle of file
    166. Buffer db MAXSIZE dup(?)
    167. end
    rc-файл
    Код (C):
    1. #define ZZZ_OPEN 1
    2. #define ZZZ_SAVE 2
    3. #define ZZZ_EXIT 3
    4. #define IDR_MAINMENU 30
    5. IDR_MAINMENU MENU
    6. {
    7. POPUP "&File"
    8. {       MENUITEM "&Open",ZZZ_OPEN
    9.                 MENUITEM "&Save",ZZZ_SAVE
    10. MENUITEM SEPARATOR
    11. MENUITEM "&Exit",ZZZ_EXIT
    12. }
    13. MENUITEM "&Exit",ZZZ_EXIT
    14. }
     
    Последнее редактирование: 3 янв 2025
    E.D. и MaKsIm нравится это.
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.914

    Асинхронные файловые операции

    Получение виртуальной памяти

    У приложения две возможности заказать страницы виртуальной памяти:
    1. Зарезервировать заданный диапазон адресов в адресном пространстве приложения
    2. фактически получить в пользование страницы виртуальной памяти, к которым можно выполнять обращение
    Процесс резервирования не отнимает много времени и не приводит к изменениям в файлах страниц. При резервировании приложение только отмечает область памяти, лежащую в заданном диапазоне адресов как зарезервированную.
    Для чего может потребоваться резервирование диапазона адресов?
    При отображении файла, имеющего большие размеры, в память, приложение может зарезервировать область виртуальной памяти, имеющую размер, равный размеру файла (даже если файл занимает несколько сотен Мбайт). При этом гарантируется, что для адресации этой области памяти можно будет использовать сплошной диапазон адресов. Это удобно, если вы собираетесь работать с файлом, как с массивом, расположенным в оперативной памяти.
    Если же приложение не резервирует, а получает страницы памяти для непосредственного использования, эти страницы физически создаются в виртуальной памяти и заполняются нулями. При этом может происходить запись в файлы страниц. Такой процесс отнимает больше времени, чем резервирование.
    Чтобы зарезервировать или получить в свое распоряжение некоторое количество страниц виртуальной памяти, приложение должно воспользоваться функцией VirtualAlloc, прототип которой представлен ниже:
    Код (C):
    1. LPVOID VirtualAlloc(
    2.   LPVOID lpvAddress,        // адрес области
    3.   DWORD  cbSize,            // размер области
    4.   DWORD  fdwAllocationType, // способ получения памяти
    5.   DWORD  fdwProtect);       // тип доступа
    Параметры lpvAddress и cbSize задают, соответственно, начальный адрес и размер резервируемой либо получаемой в пользование области памяти. При резервировании адрес округляется до ближайшей границы блока размером 64 Кбайт. В остальных случаях адрес округляется до границы ближайшей страницы памяти.
    Параметр lpvAddress можно указать как NULL. При этом операционная система выберет начальный адрес самостоятельно.
    Параметр cbSize округляется до целого числа страниц. Поэтому если вы пытаетесь с помощью функции VirtualAlloc получить область памяти размером в один байт, вам будет выделена страница размером 4096 байт. При попытке получить блок памяти размером 4097=4096+1 байт вы получите две страницы памяти общим размером 2×4096=8192 байта. Программный интерфейс системы управления виртуальной памятью не предназначен для работы с областями малого размера.
    Для параметра fdwAllocationType можно использовать комбинацию из следующих значений:
    ЗначениеhexОписание
    MEM_COMMIT
    1000​
    Выполняется выделение страниц памяти для непосредственной работы с ними. Выделенные страницы заполняются нулями
    MEM_RESERVE
    2000​
    Функция VirtualAlloc выполняет резервирование диапазона адресов в адресном пространстве приложения
    MEM_DECOMMIT
    4000​
    MEM_RELEASE
    8000​
    MEM_FREE
    10000​
    MEM_PRIVATE
    20000​
    MEM_MAPPED
    40000​
    MEM_RESET
    80000​
    MEM_TOP_DOWN
    100000​
    Память выделяется в области верхних адресов адресного пространства приложения
    MEM_IMAGE
    1000000​
    С помощью параметра fdwProtect приложение может установить желаемый тип доступа для заказанных страниц. Можно использовать комбинацию из следующих значений:
    ЗначениеhexbinРазрешенный доступ
    PAGE_NOACCESS
    1​
    1​
    Запрещен любой вид доступа
    PAGE_READONLY
    2​
    10​
    Только чтение
    PAGE_READWRITE
    4​
    100​
    Чтение и запись
    PAGE_WRITECOPY
    8​
    1000​
    К выделенной области памяти предоставляется доступ для копирования при записи. При создании или открывании файла необходимо указать флаги GENERIC_READ и GENERIC_WRITE
    PAGE_EXECUTE
    10​
    10000​
    Только исполнение программного кода
    PAGE_EXECUTE_READ
    20​
    100000​
    Исполнение и чтение
    PAGE_EXECUTE_READWRITE
    40​
    1000000​
    Исполнение, чтение и запись
    PAGE_EXECUTE_WRITECOPY
    80​
    10000000​
    Любая попытка записи на этой странице заставляет систему выдать процессу закрытую копию данной страницы
    PAGE_GUARD100
    100000000​
    Сигнализация доступа к странице. Это значение можно использовать вместе с любыми другими, кроме PAGE_NOACCESS
    PAGE_NOCACHE2001000000000Отмена кэширования для страницы памяти. Используется драйверами устройств. Это значение можно использовать вместе с любыми другими, кроме PAGE_NOACCESS
    Если страница отмечена как PAGE_READONLY, при попытке записи в нее возникает аппаратное прерывание защиты доступа (access violation). Страница также не может содержать исполнимый код. Попытка выполнения такого кода приведет к возникновению прерывания.
    У вас есть возможность получения страниц, предназначенных только для хранения исполнимого кода. Если такие страницы отмечены как PAGE_EXECUTE, для них не разрешаются операции чтения и записи.
    При необходимости зафиксировать обращение к той или иной странице приложение может отметить ее как PAGE_GUARD. Если произойдет попытка обращения к такой странице, возникнет исключение с кодом STATUS_GUARD_PAGE, после чего признак PAGE_GUARD будет автоматически сброшен.
    В случае успешного завершения VirtualAlloc возвратит адрес зарезервированной или полученной области страниц. При ошибке возвращается 0.
    Приложение может вначале зарезервировать страницы, вызвав функцию VirtualAlloc с параметром MEM_RESERVE, а затем получить их в пользование, вызвав эту же функцию еще раз для полученной области памяти, но уже с параметром MEM_COMMIT

    Освобождение виртуальной памяти

    После использования необходимо освободить полученную виртуальную память, вызвав функцию VirtualFree
    Код (C):
    1. BOOL VirtualFree(
    2.   LPVOID lpvAddress,   // адрес области
    3.   DWORD  cbSize,       // размер области
    4.   DWORD  fdwFreeType); // выполняемая операция
    Через параметры lpvAddress и cbSize передаются адрес и размер освобождаемой области.
    Если область виртуальной памяти зарезервировали функцией VirtualAlloc с параметром MEM_RESERVE для последующего получения страниц, а затем вызвали эту функцию с параметром MEM_COMMIT, можно или освободить область памяти, обозначив соответствующие страницы как свободные, или оставить их зарезервированными, но не используемыми.
    В первом случае функцию VirtualFree нужно вызвать с параметром fdwFreeType=MEM_RELEASE, во втором - fdwFreeType=MEM_DECOMMIT
    WriteFile и ReadFile вызываются с параметром ovlp типа OVERLAPPED при организации асинхронных операций
    Код (ASM):
    1. OVERLAPPED struc
    2.    Internal ULONG_PTR ?
    3.    InternalHigh ULONG_PTR ?
    4.    union
    5.       struc
    6.          _Offset DWORD ?
    7.          OffsetHigh DWORD ?
    8.       ends
    9.    Pointer PVOID ?
    10.    ends
    11. hEvent HANDLE ?
    12. OVERLAPPED ends
    Первые два элемента (Internal, InternalHigh) предназначены для использования системой, третий и четвертый элемент (_Offset, OffsetHigh) определяют начальное 64-разрядное смещение в файле. Если требуется прочитать не весь файл, а его вторую половину, тогда ovlp._Offset, будет равно (FileSize/2). Если файл достаточно большой то после ReadFile/WriteFile рекомендуют вызвать WailtForSingleObject(hFile, INFINITE)
    asm-файл
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ZZZ_OPEN equ  1
    4. ZZZ_SAVE equ  2
    5. ZZZ_EXIT equ  3
    6. MAXSIZE equ 256
    7. MEM_SIZE equ 0FFFC0h
    8. EditID equ 1
    9. IDR_MAINMENU equ 30
    10. .code
    11. WinMain proc <20>
    12. local msg:MSG
    13. xor ebx,ebx
    14. mov edi,offset ClassName
    15. mov esi,IMAGE_BASE
    16. invoke LoadCursorFromFileA,"br_Rabbit3.cur"
    17. push rax ;hIconSm
    18. push rdi ;lpszClassName
    19. push IDR_MAINMENU;lpszMenuName
    20. push COLOR_WINDOW;hbrBackground
    21. push rax ;hCursor
    22. push rax        ;hIcon
    23. push rsi ;hInstance
    24. push rbx        ;cbClsExtra & cbWndExtra
    25. pushaddr WndProc;lpfnWndProc
    26. push sizeof WNDCLASSEX;cbSize & style
    27. invoke RegisterClassExA,esp ;addr WNDCLASSEX
    28. push rbx
    29. push rsi
    30. shl esi,9 ;rsi=512*400000h=CW_USEDEFAULT
    31. push rbx
    32. push rbx
    33. push rsi
    34. push rsi
    35. push rsi
    36. push rsi
    37. sub esp,20h
    38.     invoke CreateWindowExA,WS_EX_CLIENTEDGE,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    39. invoke SetFocus,hwndEdit
    40.     lea edi,msg
    41. @@: invoke GetMessageA,edi,0,0,0
    42. invoke TranslateMessage,edi
    43. invoke DispatchMessageA,edi
    44. jmp @b
    45. WinMain endp
    46. WndProc proc <12> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    47. local szReadWrite:QWORD ;number of bytes actually read or write
    48. mov hWnd,rcx
    49. mov wParam,r8
    50. mov lParam,r9
    51. cmp edx,WM_DESTROY
    52. je wmDESTROY
    53. cmp edx,WM_COMMAND
    54. je wmCOMMAND
    55. cmp edx,WM_CREATE
    56. je wmCREATE
    57. cmp edx,WM_SIZE
    58. je wmSIZE
    59. leave
    60. jmp NtdllDefWindowProc_
    61. wmDESTROY:invoke VirtualFree,pBuffer,0,MEM_RELEASE
    62. invoke CloseHandle,hFile
    63. invoke RtlExitUserProcess,0
    64. wmSIZE: movzx eax,word ptr lParam+2
    65. movzx r9,r9w;word ptr lParam
    66. mov qword ptr[rsp+28h],TRUE
    67. mov [rsp+20h],rax
    68. invoke MoveWindow,hwndEdit,0,0
    69. jmp wmBYE
    70. OPEN: invoke GetOpenFileName,&dlgOpenOfn
    71. test eax,eax
    72. je wmBYE
    73. and qword ptr[rsp+30h],0
    74. and qword ptr[rsp+28h],FILE_FLAG_OVERLAPPED or FILE_FLAG_NO_BUFFERING
    75. mov qword ptr[rsp+20h],OPEN_EXISTING
    76. invoke CreateFile,&Buffer,GENERIC_READ or GENERIC_WRITE,0,0
    77. mov hFile,rax;handle to file
    78. invoke GetFileSize,eax,0
    79. mov FileSize,rax
    80. lea eax,ovlp
    81. mov [rsp+20h],rax
    82. invoke ReadFile,hFile,pBuffer,FileSize,&szReadWrite
    83. ;забрать в окно редактора текст из буфера
    84. invoke SetWindowTextA,hwndEdit,pBuffer
    85. ;заголовок окна - имя открытого файла
    86. movzx edx,dlgOpenOfn.nFileOffset
    87. add edx,offset Buffer
    88. invoke SetWindowTextA,hWnd
    89. jmp wmBYE
    90. SAVE:;узнать длину текст в окне редактора
    91.         invoke GetWindowTextLengthA,hwndEdit
    92. inc eax
    93. mov FileSize,rax
    94. ;вывести текст из окна редактора в буфер
    95. invoke GetWindowTextA,hwndEdit,pBuffer,FileSize
    96. ;прочитать текст из буфера в файл
    97. lea eax,ovlp
    98. mov [rsp+20h],rax
    99. invoke WriteFile,hFile,pBuffer,FileSize,&szReadWrite
    100. jmp wmBYE
    101. wmCREATE:mov dlgOpenOfn.hwndOwner,rcx
    102. push 0
    103. push IMAGE_BASE
    104. push EditID
    105. push rcx
    106. push 0
    107. push 0
    108. push 0
    109. push 0
    110. sub esp,20h
    111. invoke CreateWindowExA,0,"edit",0,WS_VISIBLE or WS_CHILD or ES_LEFT \
    112. or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or ES_AUTOVSCROLL
    113. mov hwndEdit,rax
    114. invoke VirtualAlloc,NULL,MEM_SIZE,MEM_COMMIT or MEM_RESERVE,PAGE_READWRITE
    115. mov pBuffer,rax
    116.         jmp wmBYE
    117. wmCOMMAND:movzx r8d,word ptr wParam
    118. or r9,r9 ;cmp lParam,0
    119. jnz wmBYE
    120. cmp r8d,ZZZ_EXIT
    121. ja wmBYE
    122. jmp [menu_handlers+r8*8]
    123. EXIT: invoke DestroyWindow,hWnd
    124. wmBYE:  leave
    125.         retn
    126. menu_handlers dq wmBYE,OPEN,SAVE,EXIT
    127. WndProc endp
    128. ;---------------------------------------
    129. .data
    130. ClassName db 'Асинхронные файловые операции',0
    131. dlgOpenTitle db 'Открытие файла',0
    132. ovlp  label  OVERLAPPED
    133. dq 0;Internal ULONG_PTR ?
    134. dq 0;InternalHigh ULONG_PTR ?
    135. dd 0;_Offset DWORD ?
    136. dd 0;OffsetHigh DWORD ?
    137. dq 0;Pointer PVOID ?
    138. dq 0; hEvent HANDLE ?
    139. ;------------------------------------------
    140. align 8
    141. dlgOpenOfn  label  OPENFILENAME
    142. dd sizeof OPENFILENAME,?;lStructSize
    143. dq ?            ;hwndOwner
    144. dq IMAGE_BASE   ;hInstance
    145. dq FilterString ;lpstrFilter
    146. dq ?            ;lpstrCustomFilter
    147. dd ?            ;nMaxCustFilter
    148. dd ?            ;nFilterIndex
    149. dq Buffer       ;lpstrFile
    150. dd MAXSIZE,?    ;nMaxFile
    151. dq ?            ;lpstrFileTitle
    152. dd ?,?          ;nMaxFileTitle
    153. dq ?            ;lpstrInitialDir
    154. dq dlgOpenTitle ;lpstrTitle
    155. dd OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or \
    156. OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY;Flags
    157. dw ?            ;nFileOffset
    158. dw ?            ;nFileExtension
    159. dq ?            ;lpstrDefExt
    160. dd ?,?          ;lCustData
    161. dq ?            ;lpfnHook
    162. dq ?            ;lpTemplateName
    163. ;-------------------------------------------
    164. FilterString db 'All Files (*.*)',0,'*.*',0
    165. db 'Text Files (*.txt)',0,'*.txt',0,0
    166. .data?
    167. hwndEdit dq ? ;handle for edit control
    168. pBuffer dq ?
    169. FileSize dq ?
    170. hFile dq ?;handle of file
    171. Buffer db MAXSIZE dup(?)
    172. end
    rc-файл
    Код (C):
    1. #define ZZZ_OPEN 1
    2. #define ZZZ_SAVE 2
    3. #define ZZZ_EXIT 3
    4. #define IDR_MAINMENU 30
    5. IDR_MAINMENU MENU
    6. {
    7.       POPUP "&File"
    8.       {       MENUITEM "&Open",ZZZ_OPEN
    9.                 MENUITEM "&Save",ZZZ_SAVE
    10.                MENUITEM SEPARATOR
    11.                MENUITEM "&Exit",ZZZ_EXIT
    12.        }
    13.       MENUITEM "&Exit",ZZZ_EXIT
    14. }
     
    E.D. и MaKsIm нравится это.
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.914

    Файлы проецируемые в память

    Файл нужно только открыть с помощью CreateFile, а ReadFile и WriteFile уже не требуются ;)

    Создание отображения файла

    Приложение открывает файл при помощи CreateFile. Для создания отображения файла взывают CreateFileMapping
    Код (C):
    1. HANDLE CreateFileMapping(
    2.   HANDLE hFile,           // идентификатор отображаемого файла
    3.   LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // дескриптор защиты
    4.   DWORD flProtect,         // защита для отображаемого файла
    5.   DWORD dwMaximumSizeHigh, // старшие 32 разряда размера файла
    6.   DWORD dwMaximumSizeLow,  // младшие 32 разряда размера файла
    7.   LPCTSTR lpName);         // имя отображенного файла
    Параметр hFile ― идентификатор файла, для которого выполняется отображение в память, или значение -1. В первом случае функция CreateFileMapping отобразит заданный файл в память, во втором - создаст отображение с использованием файла виртуальной памяти.
    Параметр lpFileMappingAttributes ― адрес дескриптора защиты. В большинстве случаев этот параметр = 0.
    Параметром flProtect, задает защиту для создаваемого отображения файла. Для этого параметра можно задать следующий набор значений, комбинируя их с дополнительными атрибутами, которые будут перечислены ниже:
    ЗначениеhexbinОписание
    PAGE_NOACCESS
    1​
    1​
    Любая попытка чтения, записи или выполнения кода на этой странице вызывает нарушение доступа
    PAGE_READONLY
    2​
    10​
    К выделенной области памяти предоставляется доступ только для чтения. При создании или открывании файла необходимо указать флаг GENERIC_READ
    PAGE_READWRITE
    4​
    100​
    К выделенной области памяти предоставляется доступ для чтения и записи. При создании или открывании файла необходимо указать флаги GENERIC_READ и GENERIC_WRITE
    PAGE_WRITECOPY
    8​
    1000​
    К выделенной области памяти предоставляется доступ для копирования при записи. При создании или открывании файла необходимо указать флаги GENERIC_READ и GENERIC_WRITE.
    PAGE_EXECUTE
    10​
    10000​
    Любая попытка чтения или записи на этой странице вызывает нарушение доступа, но выполнение кода разрешено
    PAGE_EXECUTE_READ
    20​
    100000​
    Любая попытка записи на этой странице вызывает нарушение доступа, но чтение или выполнение кода разрешено
    PAGE_EXECUTE_READWRITE
    40​
    1000000​
    Страница доступна для чтения, записи и выполнение ― никакие действия не вызывают нарушение доступа
    PAGE_EXECUTE_WRITECOPY
    80​
    10000000​
    Любая попытка записи на этой странице заставляет систему выдать процессу закрытую копию данной страницы
    PAGE_GUARD
    100​
    100000000​
    Любая попытка чтения или записи сторожевой страницы вызывает исключение EXEPTION_GUARD_PAGE, и она перестает быть сторожевой; этот атрибут можно комбинировать с любым другим атрибутом, кроме PAGE_NOACCES
    PAGE_NOCACHE
    200​
    1000000000​
    Отмена кэширования для страницы памяти. Используется драйверами устройств. Это значение можно использовать вместе с любыми другими, кроме PAGE_NOACCESS
    Эти значения можно комбинировать при помощи логической операции ИЛИ со следующими атрибутами:
    АтрибутhexОписание
    SEC_FILE
    800000​
    SEC_IMAGE
    1000000​
    Используется при отображении программного файла, содержащего исполнимый код. Этот атрибут несовместим с остальными перечисленными в этом списке атрибутами
    SEC_VLM
    2000000​
    SEC_PROTECTED_IMAGE
    2000000​
    SEC_RESERVE
    4000000​
    Если указан этот атрибут, вместо выделения выполняется резервирование страниц виртуальной памяти. Зарезервированные таким образом страницы можно будет получить в пользование при помощи функции VirtualAlloc. Атрибут SEC_RESERVE можно указывать только в том случае, если в качестве параметра hFile функции CreateFileMapping передается значение -1
    SEC_COMMIT
    8000000​
    Если указан этот атрибут, выполняется выделение физических страниц в памяти или в файле виртуальной памяти. Этот атрибут используется по умолчанию
    SEC_NOCACHE
    10000000​
    Отмена кэширования для всех страниц отображаемой области памяти. Должен использоваться вместе с атрибутами SEC_RESERVE или SEC_COMMIT
    SEC_WRITECOMBINE
    40000000​
    SEC_LARGE_PAGES
    80000000​
    С помощью dwMaximumSizeHigh и dwMaximumSizeLow указывают 64-разрядный размер файла. Параметр dwMaximumSizeHigh содержит старшее 32-разряда, dwMaximumSizeLow ― младшие 32-разряда. Для файлов, длина которых укладывается в 32 разряда, dwMaximumSizeHigh=0.
    Если dwMaximumSizeHigh=dwMaximumSizeLow=0. В этом случае предполагается, что размер файла не будет изменяться.
    Через lpName указывают имя отображения, которое будет доступно всем работающим одновременно приложениям. lpName представляет собой текстовую строку, закрытую 0 и не содержащую символов "\".
    Если отображение используется только одним процессом, lpName=0.
    В случае успешного завершения функция CreateFileMapping возвращает идентификатор созданного отображения. При ошибке возвращается значение NULL.
    Так как имя отображения глобально, возможно возникновение ситуации, когда процесс пытается создать отображение с уже существующим именем. В этом случае функция CreateFileMapping возвращает идентификатор существующего отображения. Такую ситуацию определяют с помощью GetLastError, вызвав ее сразу после функции CreateFileMapping. Функция GetLastError вернет значение ERROR_ALREADY_EXISTS.

    Выполнение отображения файла в память

    Мы выполнили первые два шага, необходимые для работы с файлом, отображаемым на память, ― открыть файл функцией CreateFile и создать отображения функцией CreateFileMapping. Получив от CreateFileMapping идентификатор объекта-отображения, выполняем отображение, вызвав MapViewOfFile или MapViewOfFileEx. В результате заданный фрагмент отображенного файла будет доступен в адресном пространстве процесса.
    Код (C):
    1. LPVOID MapViewOfFile(
    2.   HANDLE hFileMappingObject,  // идентификатор отображения
    3.   DWORD dwDesiredAccess,   // режим доступа
    4.   DWORD dwFileOffsetHigh,  // смещение в файле (старшее слово)
    5.   DWORD dwFileOffsetLow,   // смещение в файле (младшее слово)
    6.   DWORD dwNumberOfBytesToMap);// количество отображаемых байт
    Функция MapViewOfFile создает окно размером dwNumberOfBytesToMap байт, которое смещено относительно начала файла на количество байт, заданное dwFileOffsetHigh и dwFileOffsetLow. Если dwNumberOfBytesToMap=0, будет выполнено отображение всего файла.
    Смещение нужно задавать таким образом, чтобы оно попадало на границу минимального пространства памяти, которое можно зарезервировать. Значение 64 Кбайта подходит в большинстве случаев.
    Более точно гранулярность памяти определяют при помощи GetSystemInfo. Этой функции в качестве единственного параметра передают указатель на структуру типа SYSTEM_INFO, определенную следующим образом:
    Код (ASM):
    1. SYSTEM_INFO struct
    2.    wProcessorArchitecture dw ?; архитектура системы
    3.    wReserved dw ?; зарезервировано
    4.    dwPageSize dd ?; размер страницы
    5.    lpMinimumApplicationAddress dq ?; минимальный адрес, доступный приложениям и библиотекам DLL
    6.    lpMaximumApplicationAddress dq ?; максимальный адрес, доступный приложениям и библиотекам DLL
    7.    dwActiveProcessorMask dd ?; маски процессоров
    8.    dwNumberOfProcessors dd ?; количество процессоров
    9.    dwProcessorType dd ?; тип процессора
    10.    dwAllocationGranularity dd ?; гранулярность памяти
    11.    wProcessorLevel dw ?; уровень процессора
    12.    wProcessorRevision dw ?; модификация процессора
    13. SYSTEM_INFO ends
    Функция заполнит поля этой структуры различной информацией о системе. В поле dwAllocationGranularity будет записан минимальный размер резервируемой области памяти.
    Параметр dwDesiredAccess определяет требуемый режим доступа к отображению, то есть режимы доступа для страниц виртуальной памяти, используемых для отображения. Для этого параметра вы можете указать комбинацию из следующих значений:
    ЗначениеhexОписание
    FILE_MAP_COPY
    1​
    Доступ для копирования при записи. При создании отображения необходимо указать атрибут PAGE_WRITECOPY
    FILE_MAP_WRITE
    2​
    Доступ на запись и чтение. При создании отображения функции CreateFileMapping необходимо указать тип защиты
    FILE_MAP_READ
    4​
    Доступ только на чтение. При создании отображения необходимо указать тип защиты PAGE_READWRITE или PAGE_READ
    FILE_MAP_EXECUTE
    20​
    Доступ на исполнение. При создании отображения необходимо указать тип защиты PAGE_EXECUTE или PAGE_EXECUTE_READ или PAGE_EXECUTE_READWRITE
    FILE_MAP_ALL_ACCESS
    F001F​
    Аналогично FILE_MAP_WRITE
    В случае успешного выполнения отображения функция MapViewOfFile возвращает адрес отображенной области памяти. При ошибке возвращается значение NULL.
    При необходимости приложение может запросить отображение в заранее выделенную область адресного пространства. Для этого следует воспользоваться функцией MapViewOfFileEx:
    Код (C):
    1. LPVOID MapViewOfFileEx(
    2.   HANDLE hFileMappingObject,  // идентификатор отображения
    3.   DWORD dwDesiredAccess,      // режим доступа
    4.   DWORD dwFileOffsetHigh,  // смещение в файле (старшее слово)
    5.   DWORD dwFileOffsetLow,   // смещение в файле (младшее слово)
    6.   DWORD dwNumberOfBytesToMap, // количество отображаемых байт
    7.   LPVOID lpBaseAddress);// предполагаемый адрес для отображения файла
    Функция аналогична только что рассмотренной функции MapViewOfFile за исключением того, что она имеет еще один параметр lpBaseAddress ― предполагаемый адрес для выполнения отображения.
    Выполнение отображения с использованием функции MapViewOfFileEx используется в тех случаях, когда с помощью файла, отображаемого на память, организуется общая область памяти, доступная нескольким работающим параллельно процессам. При этом можно сделать так, что начальный адрес этой области был одним и тем же для любого процесса, работающего с данным отображением.
    Функция MapViewOfFileEx выполняет резервирование адресов, поэтому не нужно передавать ей адрес области памяти, полученный от функции VirtualAlloc. Адрес, указанный через параметр lpBaseAddress, должен находиться на границе гранулярности памяти.
    Приложение может создавать несколько отображений для разных или одинаковых фрагментов одного и того же файла.

    Открытие отображения

    Если несколько процессов используют совместно одно и то же отображение, первый процесс создает это отображение с помощью функции CreateFileMapping, указав имя отображения, остальные процессы должны открыть отображение, вызвав функцию OpenFileMapping:
    Код (C):
    1. HANDLE OpenFileMapping(
    2.   DWORD   dwDesiredAccess, // режим доступа
    3.   BOOL    bInheritHandle,  // флаг наследования
    4.   LPCTSTR lpName);         // адрес имени отображения файла
    Через параметр lpName этой функции следует передать имя открываемого отображения. Имя должно быть задано точно также, как при создании отображения функцией CreateFileMapping.
    Параметр dwDesiredAccess определяет требуемый режим доступа к отображению и указывается точно также, как и для описанной выше функции MapViewOfFile.
    Параметр bInheritHandle определяет возможность наследования идентификатора отображения. Если bInheritHandle=TRUE, порожденные процессы могут наследовать идентификатор, если bInheritHandle=FALSE ― нет.

    Отмена отображения файла

    Если созданное отображение больше не нужно, его следует отменить с помощью функции UnmapViewOfFile:
    Код (C):
    1. BOOL UnmapViewOfFile(
    2.      LPVOID lpBaseAddress// адрес области отображения
    Единственный параметр этой функции ― адрес области отображения, полученный от функций MapViewOfFile или MapViewOfFileEx.
    В случае успеха функция возвращает TRUE. Гарантируется, что все измененные страницы оперативной памяти, расположенные в отменяемой области отображения, будут записаны на диск в отображаемый файл. При ошибке функция возвращает FALSE.
    Если приложение создало несколько отображений для файла, перед завершением работы с файлом все они должны быть отменены с помощью функции UnmapViewOfFile. Далее с помощью функции CloseHandle следует закрыть идентификаторы отображения, полученный от функции CreateFileMapping и CreateFile.

    Принудительная запись измененных данных

    После отмены отображения все измененные страницы памяти записываются в отображаемый файл. Если это потребуется, приложение может в любое время выполнить принудительную запись измененных страниц в файл при помощи функции FlushViewOfFile:
    Код (C):
    1. BOOL FlushViewOfFile(
    2.   LPCVOID lpBaseAddr, // начальный адрес сохраняемой области
    3.   DWORD dwNumberOfBytesToFlush); // размер области в байтах
    С помощью параметров lpBaseAddr и dwNumberOfBytesToFlush можно выбрать любой фрагмент внутри области отображения, для которого будет выполняться сохранение измененный страниц на диске. Если задать значение параметра dwNumberOfBytesToFlush равным нулю, будут сохранены все измененные страницы, принадлежащие области отображения

    asm-файл
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ZZZ_OPEN equ  1
    4. ZZZ_SAVE equ  2
    5. ZZZ_EXIT equ  3
    6. MAXSIZE equ 256
    7. MEM_SIZE equ 65535
    8. EditID equ 1
    9. IDR_MAINMENU equ 30
    10. .code
    11. WinMain proc <20>
    12. local msg:MSG
    13.      xor ebx,ebx
    14.      mov edi,offset ClassName
    15.      mov esi,IMAGE_BASE
    16.      invoke LoadCursorFromFileA,"br_Rabbit3.cur"
    17.      push rax ;hIconSm
    18.      push rdi ;lpszClassName
    19.      push IDR_MAINMENU;lpszMenuName
    20.      push COLOR_WINDOW;hbrBackground
    21.      push rax ;hCursor
    22.      push rax        ;hIcon
    23.      push rsi ;hInstance
    24.      push rbx        ;cbClsExtra & cbWndExtra
    25.      pushaddr WndProc;lpfnWndProc
    26.      push sizeof WNDCLASSEX;cbSize & style
    27.      invoke RegisterClassExA,esp ;addr WNDCLASSEX
    28.      push rbx
    29.      push rsi
    30.      shl esi,9 ;rsi=512*400000h=CW_USEDEFAULT
    31.      push rbx
    32.      push rbx
    33.      push rsi
    34.      push rsi
    35.      push rsi
    36.      push rsi
    37.      sub esp,20h
    38.     invoke CreateWindowExA,WS_EX_CLIENTEDGE,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE
    39.     invoke SetFocus,hwndEdit
    40.     lea edi,msg
    41. @@: invoke GetMessageA,edi,0,0,0
    42.      invoke TranslateMessage,edi
    43.      invoke DispatchMessageA,edi
    44.      jmp @b
    45. WinMain endp
    46. WndProc proc <12> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    47. local hFile:QWORD ;handle of file
    48. local szReadWrite:QWORD ;number of bytes actually read or write
    49.      mov wParam,r8
    50.      mov lParam,r9
    51.      mov hWnd,rcx
    52.      cmp  edx,WM_DESTROY
    53.      je   wmDESTROY
    54.      cmp  edx,WM_COMMAND
    55.      je   wmCOMMAND
    56.      cmp  edx,WM_CREATE
    57.      je   wmCREATE
    58.      cmp  edx,WM_SIZE
    59.      je   wmSIZE
    60.      leave
    61.      jmp NtdllDefWindowProc_
    62. wmDESTROY:test OpenFlag,1
    63.      jnz @f
    64.      invoke UnmapViewOfFile,pMapping
    65.      invoke CloseHandle,hMapping
    66.      invoke CloseHandle,hFile
    67. @@: invoke RtlExitUserProcess,NULL
    68. wmSIZE: movzx eax,word ptr lParam+2
    69.      movzx r9d,word ptr lParam
    70.      invoke MoveWindow,hwndEdit,0,0,,eax,TRUE
    71.      jmp wmBYE
    72. OPEN: test OpenFlag,1
    73.      jnz @f
    74.      invoke UnmapViewOfFile,pMapping
    75.      invoke CloseHandle,hMapping
    76.      invoke CloseHandle,hFile
    77.      and OpenFlag,0
    78. @@: mov dlgOpenOfn.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or\
    79. OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
    80.       invoke GetOpenFileName,&dlgOpenOfn
    81.       test eax,eax
    82.       je wmBYE
    83.       and qword ptr[rsp+30h],0
    84.       mov qword ptr[rsp+28h],FILE_ATTRIBUTE_ARCHIVE
    85.       mov qword ptr[rsp+20h],OPEN_EXISTING
    86.       invoke CreateFile,&dOpenBuffer,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE,0
    87.       mov hFile,rax;handle to file
    88. ;создание в памяти объекта "проекция файла"
    89.       and qword ptr[rsp+28h],0
    90.       mov qword ptr[rsp+20h],MEM_SIZE
    91.       invoke CreateFileMapping,eax,0,PAGE_READWRITE,0
    92.       mov hMapping,rax
    93. ;отображение проекции файла на адресное пространство процесса
    94.       and qword ptr[rsp+20h],0
    95.       invoke MapViewOfFile,eax,FILE_MAP_WRITE,0,0
    96.       mov pMapping,rax
    97.       invoke SendMessageA,hwndEdit,WM_SETTEXT,0,eax
    98.       movzx edx,dlgOpenOfn.nFileOffset
    99.       add edx,offset dOpenBuffer
    100.       invoke SetWindowTextA,hWnd
    101.       or OpenFlag,1
    102.       jmp wmBYE
    103. SAVE: invoke SendMessageA,hwndEdit,WM_GETTEXT,MEM_SIZE,pMapping
    104.       jmp wmBYE
    105. wmCREATE:mov dlgOpenOfn.hwndOwner,rcx
    106.       push 0
    107.       push IMAGE_BASE
    108.       push EditID
    109.       push rcx
    110.       push 0
    111.       push 0
    112. push 0
    113. push 0
    114. sub esp,20h
    115. invoke CreateWindowExA,0,"edit",0,WS_VISIBLE or WS_CHILD or ES_LEFT \
    116. or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ES_AUTOHSCROLL or ES_AUTOVSCROLL
    117. mov hwndEdit,rax
    118.         jmp wmBYE
    119. wmCOMMAND:movzx r8d,word ptr wParam
    120. or r9,r9 ;cmp lParam,0
    121. jnz wmBYE
    122. cmp r8d,ZZZ_EXIT
    123. ja wmBYE
    124. jmp [menu_handlers+r8*8]
    125. EXIT: invoke DestroyWindow,hWnd
    126. wmBYE:  leave
    127.         retn
    128. menu_handlers dq wmBYE,OPEN,SAVE,EXIT
    129. WndProc endp
    130. ;---------------------------------------
    131. .data
    132. ClassName db 'Файлы проецируемые в память',0
    133. dlgOpenTitle db 'Открытие файла',0
    134. ;------------------------------------------
    135. align 8
    136. dlgOpenOfn label  OPENFILENAME
    137. dd sizeof OPENFILENAME,?;lStructSize
    138. dq ?            ;hwndOwner
    139. dq IMAGE_BASE   ;hInstance
    140. dq FilterString ;lpstrFilter
    141. dq ?            ;lpstrCustomFilter
    142. dd ?            ;nMaxCustFilter
    143. dd ?            ;nFilterIndex
    144. dq Buffer       ;lpstrFile
    145. dd MAXSIZE,?    ;nMaxFile
    146. dq ?            ;lpstrFileTitle
    147. dd ?,?          ;nMaxFileTitle
    148. dq ?            ;lpstrInitialDir
    149. dq dlgOpenTitle ;lpstrTitle
    150. dd OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or \
    151. OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY;Flags
    152. dw ?            ;nFileOffset
    153. dw ?            ;nFileExtension
    154. dq ?            ;lpstrDefExt
    155. dd ?,?          ;lCustData
    156. dq ?            ;lpfnHook
    157. dq ?            ;lpTemplateName
    158. ;-------------------------------------------
    159. FilterString db 'All Files (*.*)',0,'*.*',0
    160. db 'Text Files (*.txt)',0,'*.txt',0,0
    161. .data?
    162. dOpenBuffer db MAXSIZE dup(?)
    163. hwndEdit dq ? ;handle for edit control
    164. hMapping dq ? ;file mapped handle
    165. pMapping dq ?
    166. OpenFlag db 0
    167. end
    rc-файл
    Код (C):
    1. #define ZZZ_OPEN 1
    2. #define ZZZ_SAVE 2
    3. #define ZZZ_EXIT 3
    4. #define IDR_MAINMENU 30
    5. IDR_MAINMENU MENU
    6. {
    7.     POPUP "&File"
    8.     {       MENUITEM "&Open",ZZZ_OPEN
    9.              MENUITEM "&Save",ZZZ_SAVE
    10.              MENUITEM SEPARATOR
    11.              MENUITEM "&Exit",ZZZ_EXIT
    12.       }
    13.      MENUITEM "&Exit",ZZZ_EXIT
    14. }
     
    E.D., MaKsIm, Research и ещё 1-му нравится это.
  5. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    170
    https://learn.microsoft.com/ru-ru/windows/win32/memory/comparing-memory-allocation-methods
     
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.914

    Выделение памяти в COM

    COM определяет несколько функций для выделения и освобождения памяти в куче.
    Почему COM определяет собственные функции выделения памяти? Одна из причин ― предоставление уровня абстракции над распределителем кучи. COM не привязан к конкретному языку программирования.

    CoTaskMemAlloc

    Выделяет блок памяти
    Код (C):
    1.  CoTaskMemAlloc(
    2.    cb // Размер выделенного блока памяти в байтах
    Если функция выполняется успешно, она возвращает выделенный блок памяти. В противном случае возвращается значение NULL

    CoTaskMemRealloc

    Изменяет размер ранее выделенного блока памяти задач
    Код (C):
    1. LPVOID CoTaskMemRealloc(
    2.   LPVOID pv, // Указатель на перераспределенный блок памяти
    3.   cb //Размер перераспределенного блока памяти в байтах.

    CoTaskMemFree

    Освобождает блок памяти задачи, ранее выделенный с помощью вызова функции CoTaskMemAlloc или CoTaskMemRealloc
    Код (C):
    1. void CoTaskMemFree(
    2.     LPVOID pv // Указатель на блок памяти, который требуется освободить
     

    Вложения:

    Последнее редактирование: 3 янв 2025
  7. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    170
    Спасибо за статью! А я это так, к общей информации. По факту с выпуском х64 и появлении виртуальной памяти shared memory механизм перестал работать / стал бесполезным? Я так это понимаю, ничего кроме хип алок не использую.
     
  8. HESH

    HESH Active Member

    Публикаций:
    2
    Регистрация:
    20 мар 2008
    Сообщения:
    146
    По просьбе Mikl___ выкладываю пример работы с буферами неопределённого размера (автоматически расширяемыми при необходимости)
    на основе COM-интерфейса IStream.
     

    Вложения:

    • Example.rar
      Размер файла:
      6,5 КБ
      Просмотров:
      51
    Mikl___ нравится это.
  9. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    137
    Используя нити.
     

    Вложения:

    • fiber.zip
      Размер файла:
      10,8 КБ
      Просмотров:
      48
    • log.png
      log.png
      Размер файла:
      12,5 КБ
      Просмотров:
      49
    Mikl___ нравится это.
  10. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    137
    Mikl___

    Проще и более эффективно(нет ядерных вызовов при расширении буфера) не сделать в принципе.
     
    Mikl___ нравится это.