Downloadez l'exemple ici.
.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
includelib
\masm32\lib\comdlg32.lib
.const
IDM_OPEN
equ 1
IDM_SAVE
equ 2
IDM_EXIT
equ 3
MAXSIZE
equ 260
.data
ClassName
db "Win32ASMFileMappingClass",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
; Handle de la 'memory mapped file', doit être
; initialisé avec un 0 parce qu'on doit aussi l'utiliser comme
; un flag dans la section WM_DESTROY
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
hFileRead
HANDLE ?
; Handle du fichier source (fichier réel)
hFileWrite
HANDLE ?
; Handle de la 'sortie' du fichier.
hMenu
HANDLE ?
pMemory
DWORD ?
; Pointer sur les données dans le fichier source.
SizeWritten
DWORD ?
; Nombre d'octes actuellement écrit par WriteFile. (écrit dans la Box
; où on peut mettre du texte)
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain
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, WS_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
invoke DispatchMessage, 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
; Obtient l'handle du menu
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 GetSaveFileName, ADDR ofn
.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
.endif
.else
invoke DestroyWindow, hWnd
.endif
.endif
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc
endp
CloseMapFile
PROC
invoke CloseHandle,hMapFile
mov hMapFile,0
invoke CloseHandle,hFileRead
ret
CloseMapFile
endp
end
start
Quand l'utilisateur choisit un fichier dans la DialogBox qui sert à ouvrir des fichiers, nous appelons CreateFile pour l'ouvrir. Notez que nous spécifions GENERIC_READ pour ouvrir ce fichier avec comme propriété 'Read-Only'. 'dwShareMode' est mis à zéro parce que nous ne voulons pas que d'autres processus n'aient accès au fichier pendant notre opération.
invoke CreateFileMapping,hFileRead,NULL,PAGE_READONLY,0,0,NULL
Alors nous appelons CreateFileMapping pour créer une 'Memory Mapped File' du fichier ouvert. La syntaxe de CreateFileMapping est la suivante :
CreateFileMapping
proto hFile:DWORD,\
lpFileMappingAttributes:DWORD,\
flProtect:DWORD,\
dwMaximumSizeHigh:DWORD,\
dwMaximumSizeLow:DWORD,\
lpName:DWORD
Sachez déjà, que CreateFileMapping ne doit pas Mapper la totalité de la mémoire du fichier. Vous pouvez utiliser cette fonction pour Mapper seulement une partie de la mémoire du fichier réel. Vous spécifiez la taille de la mémoire du fichier à Mapper dans les paramètres dwMaximumSizeHigh et dwMaximumSizeLow. Si vous indiquez une taille plus grande que le fichier réel, le fichier réel sera agrandit à la nouvelle taille. Si vous voulez que la taille de la mémoire du 'File Mapping' soit la même que celle du fichier réel, mettez ces deux derniers paramètres à zéro.
Vous pouvez employer un NUL dans le paramètre lpFileMappingAttributes pour que ce soit Windows qui crée une 'memory mapped file' avec des attributs de sécurité par défaut.
FlProtect définit la protection désirée pour la 'memory mapped file'. Dans notre exemple, nous employons PAGE_READONLY pour permettre uniquement l'opération de lecture sur la 'memory mapped file'. Notez que cet attribut ne doit pas contredire l'attribut employé dans CreateFile sinon CreateFileMapping échouera.
LpName pointe sur le nom de la 'memory mapped file'. Si vous voulez partager ce fichier avec d'autre processus, vous devez lui donner un nom. Mais dans notre exemple, notre processus est le seul qui emploie ce fichier donc nous ignorons ce paramètre.
mov eax,OFFSET buffer
movzx edx,ofn.nFileOffset
add eax,edx
invoke SetWindowText,hWnd,eax
Si CreateFileMapping s'effectue avec succès, le nom du fichier ouvert prend la place du titre de la fenêtre. Le nom du fichier ainsi que son chemin complète sont stocké dans le buffer, nous voulons afficher uniquement le nom de fichier dans le titre donc nous devons ajouter la valeur du membre nFileOffset de la structure OPENFILENAME à l'adresse de ce buffer. (vous avez compris pourquoi ! ! !)
invoke EnableMenuItem,hMenu,IDM_OPEN,MF_GRAYED
invoke EnableMenuItem,hMenu,IDM_SAVE,MF_ENABLED
Comme précaution, nous ne voulons pas que l'utilisateur puisse ouvrir plusieurs fichiers les uns après les autres, donc nous devons griser le sous-menu 'Open' et dégriser le sous-menu 'Save'. EnableMenuItem est justement employé pour changer les attributs du menu..
Après ceci, nous attendons que l'utilisateur clique sur le sous-menu File/Save pour fermer notre programme. Au moment où l'utilisateur ferme le programme, nous devons en fait fermer la 'memory mapped file' ainsi que le fichier réel. Voici comment faire :
.ELSEIF uMsg==WM_DESTROY
.if hMapFile!=0
call CloseMapFile
.endif
invoke PostQuitMessage,NULL
Dans le susdit petit bout de code, quand la procédure de fenêtre reçoit le message WM_DESTROY, il vérifie d'abord la valeur d'hMapFile pour voir si c'est un zéro ou non. Si ce n'est pas le zéro, il appelle la fonction CloseMapFile qui contient le code suivant :
CloseMapFile
PROC
invoke CloseHandle,hMapFile
mov hMapFile,0
invoke CloseHandle,hFileRead
ret
CloseMapFile
endp
CloseMapFile ferme la 'memory mapped file' et le fichier réel, pour empêcher qu'il n'y ait une fuite de ressources lorsqu'on sort de notre programme Win32.
Si l'utilisateur veut le sauvegarder les données dans un autre fichier, le programme l'affiche dans une DialogBox spéciale 'Sauvegarde'. Après qu'il ait tapé le nom du nouveau fichier, le fichier est créé par la fonction CreateFile.
invoke MapViewOfFile,hMapFile,FILE_MAP_READ,0,0,0
mov pMemory,eax
Immédiatement après que le fichier ait été créé, nous appelons MapViewOfFile pour Mapper la partie désirée de la 'memory mapped file' dans la mémoire. Cette fonction a la syntaxe suivante :
MapViewOfFile
proto hFileMappingObject:DWORD,\
dwDesiredAccess:DWORD,\
dwFileOffsetHigh:DWORD,\
dwFileOffsetLow:DWORD,\
dwNumberOfBytesToMap:DWORD
dwDesiredAccess indique quelle opération nous souhaitons faire sur le fichier. Dans notre exemple, nous voulons seulement lire les données, donc nous employons FILE_MAP_READ.
dwFileOffsetHigh et dwFileOffsetLow indiquent l'offset de départ où commence le fichier que vous voulez Mapper en mémoire. Ici, nous voulons lire dans la totalité du fichier donc nous commençons le Mapping à l'offset 0.
dwNumberOfBytesToMap indique le nombre d'octets à Mapper dans la mémoire. Si vous voulez Mapper le fichier en entier (Spécifié par CreateFileMapping), donnez la valeur 0 à MapViewOfFile.
Après l'appel à MapViewOfFile, la partie désirée est chargée dans la mémoire. On vous renverra le pointer du bloc de mémoire qui contient les données du fichier.
invoke GetFileSize,hFileRead,NULL
Regarde de quelle taille est le fichier. La taille du fichier est renvoyée dans eax. Si le fichier est plus grand que 4 GB, le mot de poids fort de la taille du fichier est stocké dans FileSizeHighWord. Puisque nous ne nous attendons pas à manipuler un si grand fichier, nous pouvons l'ignorer.
invoke WriteFile,hFileWrite,pMemory,eax,ADDR SizeWritten,NULL
Écrit les données qui sont configurées(Mappées) dans la mémoire du fichier.
invoke UnmapViewOfFile,pMemory
Quand tout est près avec le fichier d'entrée, on l''Unmap' en mémoire.
call CloseMapFile
invoke CloseHandle,hFileWrite
et on referme tous les fichiers.
invoke SetWindowText,hWnd,ADDR AppName
Restore le titre original de la fenêtre principale.
invoke EnableMenuItem,hMenu,IDM_OPEN,MF_ENABLED
invoke EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED
Réactive le sous-menu 'Open' et désactive le sous-menu 'Save' en le grisant.