Win32 assembly: 13. Memory map file

zhaozj2021-02-17  54

Thirteenth lesson memory map file

In this lesson, we will tell the memory mapped files and demonstrate how to use it. You will find that the memory mapping file is very simple.

theory:

If you carefully study an example of the previous lesson, it will find that it has a serious flaw: What if you want to read the content that is greater than the system allocation? What if you want to search for strings that just exceed the boundary of the memory block? For the first question, you may say that as long as you continue to read, don't you solve it? As for the second question, you will say some special processing at the boundary of the memory block, such as putting some flags. The principle is indeed a good line, but this is very difficult to deal with with the degree of complexity. The second question is a famous boundary judgment problem, and many errors in the program are caused. Think about it, if we can assign a big memory block that can accommodate the entire file, don't you all solve these two questions? Yes, Win32's memory maps do allow us to assign a memory that can exist enough files in reality.

Using memory map files you can think of the operating system has put all the files all in memory, then you only need to move the file pointer to read and write. This way you don't even need to call those API functions that assign, release memory blocks, and file input / output, and you can use this as a way to share data between different processes. The use of memory maps actually does not involve actual file operations, which is more like a visible memory space for each process. As for the way the memory map file is used as a process sharing data, it is docked, because you have to handle data synchronization issues, otherwise your application may probably get outdated or wrong data or even crash. In this lesson, we will mainly describe the memory map file, will not involve synchronization between processes. The memory maps in Win32 are very wide, such as: even if the core module of the system --- PE format file loader also uses a memory mapping file, because the file in the PE format is not loaded into memory at one time, for example He is only loaded in the first load, while the other parts are loaded again, which is only available to the longevity of the memory map file. Most of the actual files are similar to the PE loader, so you should also take advantage of memory mapping files when processing this class.

The memory map file itself has some limitations. For example, once you generate a memory mapping file, then you cannot change its size during that session. So the memory map file is very useful for read-only files and file operations that do not affect their size. Of course, this does not mean that the file operation that will cause changes to its size will not be able to use the memory file. You can estimate the possible size of the file after the operation, and then generate such a memory map file, then the file The length can grow to such a size. Our explanation is enough, let's take a look at the details of the realization:

Call CREATEFILE Opens the file you want to map. Call CREATEFILEMAPPING, which requires the handle that is previously CreateFile returned, which generates a memory mapping object based on the file object created in the createFile function. Call the MapViewOffile function to map a region of the entire file or the entire file to memory. This function returns a pointer to the first byte mapped to memory. Use this pointer to read and write files. Call unmapViewoffile to release file mapping. Call the CloseHandle to turn off the memory mapping file. Note that the handle of the memory map file must be passed. Call the CloseHandle to close the file. Note The handle of the file created by CreateFile must be passed.

Example: The following example allows the user to open a file via the "Open File" dialog box, then use the memory map file to open the file, if successful, the title of the window will display the name of the file opened, you can choose File / Save "menu item to save the name. The program will save the contents of the open file to the new file. Note that this whole process You do not only use the allocated memory of GlobalAlloc. .386 .model flat, stdcall WinMain proto: DWORD,: DWORD,: DWORD,: DWORD include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc include / masm32 / IncludE/COMDLG32.INC includeLIB /MASM32/LIB/USER32.LIB INCLUDELIB /MASM32/LIB/kernel32.lib incrudelib /masm32/lib/comdlg32.lib

.const IDM_Open EQU 1 IDM_SAVE EQU 2 IDM_EXIT EQU 3 MaxSize EQU 260

.DATA CLASSNAME DB "WIN32AMFILEMAPINGCLASS", 0 AppName DB "Win32 ASM file mapping example", 0 menuname DB "firstmenu", 0 OFN OpenFileName <> Filterstring DB "All Files", 0, "*. *", 0 dB "Text Files ", 0," *. Txt ", 0,0 Buffer DB MaxSize DUP (0) HMapfile Handle 0; Hadle to The Mapped File, Must Be; Initialized with 0 Because We Also Use It As; a Flag in WM_DESTROY Section TOO

? .Data hInstance HINSTANCE CommandLine LPSTR hFileRead HANDLE;??? Handle to the source file hFileWrite HANDLE;?? Handle to the output file hMenu HANDLE pMemory DWORD;? Pointer to the data in the source file SizeWritten DWORD;? Number of bytes actually Written by Writefile

.code start: invoke GetModuleHandle, NULL mov hInstance, eax invoke GetCommandLine mov CommandLine, eax invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT invoke ExitProcess, eaxWinMain proc hInst: HINSTANCE, hPrevInst: HINSTANCE, CmdLine: LPSTR, CmdShow: DWORD LOCAL wc : WNDCLASSEX LOCAL msg: mSG LOCAL hwnd: HWND mov wc.cbSize, SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra, NULL mov wc.cbWndExtra, NULL push hInst pop wc.hInstance mov wc.hbrBackground, COLOR_WINDOW 1 mov wc.lpszMenuName, OFFSET MenuName mov wc.lpszClassName, OFFSET ClassName invoke LoadIcon, NULL, IDI_APPLICATION mov wc.hIcon, eax mov wc.hIconSm, eax invoke LoadCursor, NULL, IDC_ARROW mov wc.hCursor , EAX INVOKE RegisterClassex, Addr WC Invoke CreateWindowex, WS_EX_CLIENTEDGE, ADDR ClassName, / Addr Appname, W S_OVERLAPPEDWINDOW, CW_USEDEFAULT, / CW_USEDEFAULT, 300,200, NULL, NULL, / hInst, NULL mov hwnd, eax invoke ShowWindow, hwnd, SW_SHOWNORMAL invoke UpdateWindow, hwnd .WHILE TRUE invoke GetMessage, ADDR msg, NULL, 0,0 .BREAK .IF ( ! EAX) Invoke TranslateMessage, Addr Msg .Endw Mov Eax, Msg.wParam Ret Winmain Endp

WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM .IF uMsg == WM_CREATE invoke GetMenu, hWnd; Obtain the menu handle mov hMenu, eax mov ofn.lStructSize, SIZEOF ofn push hWnd pop ofn.hWndOwner push hInstance pop ofn.hInstance mov ofn.lpstrFilter, OFFSET FilterString mov ofn.lpstrFile, OFFSET buffer mov ofn.nMaxFile, MAXSIZE .ELSEIF uMsg == WM_DESTROY .if hMapFile! = 0 call CloseMapFile .endif invoke PostQuitMessage, NULL .ELSEIF uMsg == WM_COMMAND mov eax, wParam .if lParam == 0 .if ax == IDM_OPEN mov ofn.Flags, OFN_FILEMUSTEXIST or / OFN_PATHMUSTEXIST or OFN_LONGNAMES or / OFN_EXPLORER or OFN_HIDEREADONLY invoke GetOpenFileName, ADDR ofn .if eax ==

TRUE invoke CreateFile, ADDR buffer, / GENERIC_READ, / 0, / NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, / NULL mov hFileRead, eax invoke CreateFileMapping, hFileRead, NULL, PAGE_READONLY, 0,0, NULL mov hMapFile, eax mov eax, OFFSET buffer movzx edx, ofn.nFileOffset add eax, edx invoke SetWindowText, hWnd, eax invoke EnableMenuItem, hMenu, IDM_OPEN, MF_GRAYED invoke EnableMenuItem, hMenu, IDM_SAVE, MF_ENABLED .endif .elseif ax == IDM_SAVE mov ofn.Flags, OFN_LONGNAMES or / OFN_EXPLORER or OFN_HIDEREADONLY Invoke Getsavefilena Me, addr offn .if EAX ==

TRUE invoke CreateFile, ADDR buffer, / GENERIC_READ or GENERIC_WRITE, / FILE_SHARE_READ or FILE_SHARE_WRITE, / NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE, / NULL mov hFileWrite, eax invoke MapViewOfFile, hMapFile, FILE_MAP_READ, 0,0,0 mov pMemory, eax invoke GetFileSize, hFileRead , NULL invoke WriteFile, hFileWrite, pMemory, eax, ADDR SizeWritten, NULL invoke UnmapViewOfFile, pMemory call CloseMapFile invoke CloseHandle, hFileWrite invoke SetWindowText, hWnd, ADDR AppName invoke EnableMenuItem, hMenu, IDM_OPEN, MF_ENABLED invoke EnableMenuItem, hMenu, IDM_SAVE, MF_GRAYED .e ndif .else invoke DestroyWindow, hWnd .endif .endif .ELSE invoke DefWindowProc, hWnd, uMsg, wParam, lParam ret .ENDIF xor eax, eax ret WndProc endpCloseMapFile PROC invoke CloseHandle, hMapFile mov hMapFile, 0 invoke CloseHandle, hFileRead ret CloseMapFile endp

End Start

analysis:

Invoke Createfile, AddR Buffer, /

Generic_read, /

0, /

NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, /

NULL

When the user chooses to open the file, we call CREATEFILE to open. Note We specify generic_read (general reading) to indicate that the file we open can only be read, set DWSHAREMODE to 0, indicating that we don't want other processes to access the file when we operate.

Invoke CreateFilemapping, HfileRead, Null, Page_Readonly, 0, 0, Null

We call CREATEFILEMAPPING to generate a memory mapping file on the open file. CreateFilemapping The syntax is as follows: CreateFileMapping Proto Hfile: DWORD, / LPFILEMAPPINGATTRIBUTES: DWORD, / FLPROTECT: DWORD, / DWMAXIMUMSIGH: DWORD, / DWMAXIMUMSELOW: DWORD, / LPNAME: DWORD

You should know that this function is not necessary to map the entire file to the memory, you can use this function to map part of the file. You can specify the size of the memory map file in the parameter dwmaximumsizehigh and dwmaximumsizelow. If the value you specify is greater than the actual file, the actual file will grow to the specified size, if you want the mapping, the memory size is just right and the actual size of the file, etc. Then, the two parameters are set to 0. You can set lpfilemappingAttributes to null, allowing Windows to give the memory mapping file on the default security properties. Flprotect defines the protection properties of the memory map file, we specify it to specify that the memory mapping file can only be read. Note that this property is impossible to contradict the properties specified in CreateFile, otherwise you cannot generate a memory mapping file. LPNAME Specifies the name of the memory mapping file, if you want the memory mapper to use it for other processes, you must give it a name. However, in our example, only our process uses the memory map file, we ignore this parameter.

Mov Eax, Offset Buffer Movzx EDX, OFN.NFILEOFFSET Add Eax, Edx Invoke SetWindowText, HWnd, Eax

If the function createfilemapping call is successful, we replace the window's title bar to the name of the file being opened. The file name saved in the buffer is a full file name with the path, so in order to display only the file name we need to use the value of the member NfileOffset in the OpenFileName structure to find the start address of the file name.

Invoke EnableMenuItem, HMENU, IDM_Open, MF_GRAYED Invoke EnableMenuItem, HMENU, IDM_SAVE, MF_ENABLED

In order to avoid the user one-time open multiple files, we let the "Open File" menu item gray display so that the menu item that opens the file is invalid. Functions EnableMenuItem can be used to change the properties of the menu item. The user may then save a file or close the application directly. If the user selects closes the application, you must turn off the memory map file and the file in advance, the code is as follows:

.ELSEIF UMSG == WM_DESTROY .IF HMAPFILE! = 0 Call ClosemapFile .endif Invoke PostquitMessage, Null

In the above code segment, after the WMM_DESTROY message is received, it detects whether the HMAPFile value is 0 after the message processing process is received. If not 0 indicates that the relevant file is not closed, it is necessary to call ClosemapFile to turn off them. Closemapfile Proc Invoke CloseHandle, Hmapfile Mov Hmapfile, 0 Invoke CloseHandle, HfileRead Ret ClosemapFile Endp

The above process call is used to turn off the memory map file and the originally opened file, which can make the program exit without resource leakage. If the user selects the saved file, pop up a "Save File" dialog box, when the user enters the name of the new file, we call the createFile function to create a new file --- Output file.

Invoke MapViewoffile, Hmapfile, File_Map_read, 0,0,0 MOV PMEMORY, EAX

After the output file is created, we call MapViewOffile to map the part that wants to map to the memory. The syntax of this function is as follows:

MapViewOffile Proto HfilemappingObject: DWORD, / DWDESIREDACCESS: DWORD, / DWFILEOFFSETHIGH: DWORD, / DWFILEOFFSETLOW: DWORD, / DWNUMBEROFBYTOSTOMAP: DWORD

DwdesiredAccess is used to specify what we want to do with the file. In our example, we just want to read, so specify the flag file_map_read. DWFILEOFFSETHIGH and DWFILEOFFSETLOW are used to specify the start offset position to open the file. Our example wants to map the entire file, so specify their value of 0. Dwnumberofbytestomap is used to specify the number of bytes that want to map. If you want to map the entire file, set this value of 0. After calling MapViewOffile, we hope that the part has been mapped to memory. You will get a pointer to the start memory block.

Invoke GetFileSize, HfileRead, NULL

Calling this function can get the size of the file, which is transmitted via EAX. If the length of the file exceeds 4G, the high value portion of the file length DWORD (that is, more than 4G parts) is saved in FileSizeHighword. Because we estimate that the general file will not be so big, it ignores this value.

Invoke Writefile, HfileWrite, Pmemory, Eax, Addr Sizewritten, Null

Write the data in the memory map file to the output file.

Invoke unmapViewoffile, Pmemory

After writing, we release the mapping.

Call Closemapfile Invoke CloseHandle, HfileWrite

Turn off the handle of the memory map and output file.

Invoke SetWindowText, HWnd, Addr Appname

The title strip of the recovery window to the name of the application.

Invoke EnableMenuItem, HMENU, IDM_Open, MF_ENABED INVOKE ENABLEMENUITEM, HMENU, IDM_SAVE, MF_GRAYED

转载请注明原文地址:https://www.9cbs.com/read-30125.html

New Post(0)