Межпроцессное взаимодействие

Тема в разделе "WASM.ARTICLES", создана пользователем Mikl___, 24 апр 2022.

  1. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    Inter Process Communication
    Inter Process Communication или IPC используется для обмена данными между двумя приложениями или процессами. Процессы могут быть запущенными либо на одном и том же компьютере, либо на разных компьютерах объединенных в сеть. Операционная система Windows поддерживает различные методы IPC:
    • Буфер обмена: когда пользователь использует команду копирования или вырезания в любом приложении/окне, скопированные данные сохраняются в буфере обмена окнами (временное хранилище). Другое приложение может получить доступ к данным из буфера обмена.
    • COM: модель компонентных объектов предлагает платформу для взаимодействия между процессами в шаблонах сервера и клиента. COM-сервер может быть локальным сервером или внутрипроцессным сервером. Также может быть несколько COM-клиентов, которые взаимодействуют с COM-сервером и обмениваются данными.
    • WM_COPYDATA: Windows предоставляет сообщение, то есть WM_COPYDATA, которое позволяет процессу обмениваться данными с другим процессом. Можно использовать с SendMessage или SendMessageTimeout, у которого в качестве одного из параметров используется адрес структуры COPYDATASTRUCT. Сообщение WM_COPYDATA используется для обмена данными внутри локального компьютера.
    • DDE: динамический обмен данными — это протокол, который содержит набор рекомендаций и правил для отправки данных между процессами. Процесс использует функцию SendMessage с сообщением WM_DDE_INITIATE или WM_DDE_ACK, отправленным в ответ на сообщение WM_DDE_INITIATE. Для обмена данными используется общая память.
    • Memory Mapped File и Paging File: быстрые механизмы связи между процессами, обеспечивают эффективный способ использования содержимого файла в виртуальной памяти или путем доступа к общей области в памяти. В этих IPC данные файла рассматриваются как часть адресного пространства процесса, так что процесс может легко получить доступ к адресу содержимого. Любой другой процесс, имеющий доступ к общей памяти, должен реализовать синхронизацию, чтобы снизить риск повреждения данных. Сопоставление файлов выполняется в той же системе/машине и недоступно для сетевых процессов.
    • Pipe-каналы: можно использовать как в качестве однонаправленного, так и двунаправленного механизма обмена данными. Windows поддерживает два типа каналов: именованный и анонимный канал.
      • Анонимные каналы могут использоваться в одной сети или только между связанными процессами,
      • Именованные каналы могут использоваться в сети внутри разных процессов.
      Pipe -канал рассматривают как очередь FIFO, где один конец канала действует как сервер, а другой конец канала — как клиент.
    • Mailslot-канал: обеспечивает только одностороннюю связь. Один процесс может создать mailslot-канал в качестве сервера, а другой процесс — клиентский mailslot-канал. Клиент mailslot отправляет сообщение на сервер mailslot, записывая сообщение, и сообщения добавляются к серверу mailslot до тех пор, пока сервер не прочитает их. Процесс может иметь mailslot как на сервере, так и на клиенте, и это помогает в многонаправленной связи. Mailslot предоставляет возможность транслировать сообщение по сети.
    • Sockets: эффективный способ отправки и получения данных по сети и на локальном компьютере. Использует несколько протоколов, таких как TCP/IP и UDP. Используется с комбинацией IP-адреса машины и адреса порта, по которому могут передаваться данные.
    • RPC: Remote Procedure Call (удаленный вызов процедур) обеспечивает способ связи по сети, так что процесс может вызывать функцию в другом процессе. RPC поддерживает тесную связь между клиентом и сервером с высокой производительностью.
    • LPC: Local Procedure Call (локальный вызов процедур). LPC используется операционной системой для передачи сообщений между подсистемами через порты. Основные достоинства LPC:
      • Высокая производительность;
      • Простота и функциональность;
      • Доступность для программ режима пользователя и для драйверов режима ядра.
      LPC использует клиент-серверную архитектуру и предоставляет API схожий с интерфейсом сокетов. Во взаимодействии участвуют поток-сервер и один или несколько потоков-клиентов: каждый клиент предварительно соединяется с сервером, посылает одно или несколько сообщений, на некоторые из этих сообщений получает ответ и разрывает соединение.
    Во вложении приложения для иллюстрации IPC (Mailslot, WM_COPYDATA, DDE, Clipboard, Paging File, Memory Mapped File, Named Pipe). От одного приложения к другому передаются:
    • текстовое сообщение
    • картинки
    • звук из wav-файла
    Картинки и wav-файл находятся во вложении в папке Images.
     

    Вложения:

    • IPC.zip
      Размер файла:
      3,1 МБ
      Просмотров:
      275
    • Images.zip
      Размер файла:
      1,4 МБ
      Просмотров:
      138
    Marylin, ALLIGATOR и youneuoy нравится это.
  2. Mikl___

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

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

    01. WM_COPYDATA

    Перед отправкой сообщения WM_COPYDATA структура COPYDATASTRUCT инициализируется информацией о типе пересылаемых данных, объеме данных и указателем на блок данных. Затем с помощью функции SendMessage сообщение WM_COPYDATA пересылается в принимающую программу; параметр wParam содержит дескриптор окна программы, а lParam ― адрес структуры COPYDATASTRUCT. Для передачи данных должна использоваться только функция синхронной отправки сообщения SendMessage, а не PostMessage, которая передает сообщение асинхронным образом. Память под передаваемые данные резервируется и удерживается до тех пор, пока приложение-приемник не обработает сообщение и не оповестит об этом систему. До этого момента приложение-отправитель переходит в режим ожидания. Если нужно ограничивать время ожидания, пока целевое приложение по какой-то причине может не ответить на сообщение, тогда используют функцию SendMessageTimeout.
    Когда сообщение поступает обработчику WM_COPYDATA принимающей программы, указатель на данные копируется из структуры COPYDATASTRUCT и используется, как любой другой указатель.
    В принимающем процессе размер блока данных, адрес которого содержит lpData, извлекается из элемента cbData. Значение, считываемое из элемента lpData принимающей программой, будет отличаться от значения, помещенного туда отправляющей программой. Перед передачей сообщения WM_COPYDATA операционная система выделяет в адресном пространстве принимающего процесса блок памяти, копирует данные из отправляющего процесса и обновляет значение lpData. В адресных пространствах этих процессов адреса размещении блока не совпадут.
    В структуре COPYDATASTRUCT имеется поле, dwData, в котором можно передать 32-разрядное значение, определяемое в программе. Можно поместить туда любое значение, но я помещаю туда константы определенные для работы с буфером обмена (CF_TEXT, CF_DIB, CF_WAVE) (добавлены некоторые форматы из сообщения SadKo)
    КонстантаhexОписание формата данных
    CF_TEXT
    1​
    Текстовые данные в виде массив символов. Каждая строка завершается комбинацией символов 0Dh и 0Ah, весь массив закрыт нулем
    CF_BITMAP
    2​
    Битовое изображение в формате, который зависит от устройства отображения (Device Dependent Bitmap)
    CF_METAFILEPICT
    3​
    Метафайл
    CF_SYLK
    4​
    Формат Microsoft Symbolic Link. Этот формат предназначен для передачи текстовых данных, причем каждая строка заканчивается комбинацией символов 0Dh и 0Ah. Используется в некоторых программных продуктах Microsoft
    CF_DIF
    5​
    Формат Data Interchange Format. Аналогично формату CF_SYLK, формат CF_DIF предназначен для передачи текстовых данных
    CF_TIFF
    6​
    Графическое изображение в формате Tag Image File Format, который был разработан Microsoft, Aldus Corporation и Hewlett-Packard
    CF_OEMTEXT
    7​
    Аналогично предыдущему, однако буфер содержит символы в кодировке OEM
    CF_DIB
    8​
    Битовое изображение в формате, который не зависит от устройства отображения (Device Independent Bitmap)
    CF_PALETTE
    9​
    Палитра цветов. Используется при записи в Clipboard битовых изображений DIB
    CF_PENDATA
    A​
    Формат данных используется в расширении операционной системы Windows, предназначенном для работы с перьевым вводом
    CF_RIFF
    B​
    Формат Resource Interchange File Format
    CF_WAVE
    C​
    Звуковые данные. Подмножество формата Resource Interchange File Format
    CF_UNICODETEXT
    D​
    Текст в формате UTF-16, аналогично CF_TEXT и CF_OEMTEXT
    CF_ENHMETAFILE
    E​
    Дескриптор (HANDLE) к EMF (Enhanced Metafile) ― HENHMETAFILE
    CF_HDROP
    F​
    Дескриптор к структуре HDROP, которая содержит список путей к файлам, используемая при Drag&Drop. Приложение может запросить информацию о файлах, вызвав функцию DragQueryFile
    CF_LOCALE10Объект HGLOBAL, содержащий информацию о локали текста в буфере обмена
    CF_DIBV511Объект в памяти, содержащий структуру BITMAPV5HEADER, за которой следует информация о цветовом пространстве и данные картинки
    CF_OWNERDISPLAY80Формат данных определяется приложением, записавшим такие данные в Clipboard. Это же приложение отвечает за отображение данных
    CF_DSPTEXT81Текстовое представление данных, формат которых определен приложением
    CF_DSPBITMAP82Представление данных, формат которых определен приложением, в виде битового изображения
    CF_DSPMETAFILEPICT83Представление данных, формат которых определен приложением, в виде метафайла
    CF_DSPENHMETAFILE8EФормат EMF (Enhanced Metafile)
    При использовании метода WM_COPYDATA помните, что сообщения должны пересылаться, а не просто регистрироваться. Чтобы освободить память, выделенную в адресном пространстве принимающего процесса, операционную систему нужно проинформировать о моменте завершении пересылки. Получатель сообщения WM_COPYDATA обращается с блоком данных как будто он предназначен только для чтения. Для внесения изменении в полученные данные, в принимающей программе необходимо подготовить их локальную копию.
    Объект памяти, который должен быть помещен в буфер обмена, должен быть размещен, при помощи использования функции GlobalAlloc с флажками GMEM_DDESHARE и GMEM_MOVEABLE.
    Как только объект памяти помещен в буфер обмена, монопольное использование этого дескриптора памяти переходит к системе. Когда буфер обмена очищается, а объект памяти имеет один из следующих форматов буфера обмена, система освобождает объект памяти, обращаясь к обозначенной функции:
    Наименование функции,
    которая освобождает объект
    Формат буфера обмена
    DeleteMetaFileCF_DSPENHMETAFILE
    CF_DSPMETAFILEPICT
    CF_ENHMETAFILE
    CF_METAFILEPICT
    DeleteObjectCF_BITMAP
    CF_DSPBITMAP
    CF_PALETTE
    GlobalFreeCF_DIB
    CF_DSPTEXT
    CF_OEMTEXT
    CF_TEXT
    CF_UNICODETEXT
    В том случае, если буфер обмена освобожден от объекта памяти, чей формат не показывается в предшествующем списке, прикладная программа сама должна освободить объект памяти.
    02.jpg
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. ID_SEND_ICO equ 102
    6. ID_SEND_WAV equ 103
    7. IDC_DIALOG equ 200
    8. IDC_ICON1 equ 500
    9. IDC_IMG1 equ 104
    10. COPYDATASTRUCT struct
    11.   dwData dq ?
    12.   cbData dd ?,?
    13.   lpData dq ?
    14. COPYDATASTRUCT ends
    15. .code
    16. WinMain proc
    17. enter 30h,0
    18. mov r9d,256
    19. mov [rbp-10h],r9
    20. mov qword ptr [rbp-8],LR_DEFAULTCOLOR
    21. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON
    22. mov r9d,offset DialogProc
    23. mov qword ptr[rbp-10h],rax
    24. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    25. invoke RtlExitUserProcess,NULL
    26. WinMain endp
    27. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    28. local buffer:qword
    29. local cdata:COPYDATASTRUCT
    30. local FSize:dword
    31. local hFile:dword
    32. local p:qword
    33. local szReadWrite:qword ;number of bytes actually read or write
    34. local hResource:qword
    35. local pResource:qword
    36. mov hWnddlg,rcx
    37. mov lParam,r9
    38. cmp edx,WM_CLOSE
    39. je wmCLOSE
    40. cmp edx,WM_COMMAND
    41. je wmCOMMAND
    42. cmp edx,WM_INITDIALOG
    43. je wmINITDIALOG
    44. xor eax,eax
    45. jmp exit0
    46. wmINITDIALOG:
    47.         invoke GetDlgItem,,IDC_IMG1
    48. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    49. jmp wmBYE
    50. wmSEND_TXT:invoke GlobalAlloc,GPTR,256
    51. mov buffer,rax
    52.         mov cdata.lpData,rax
    53. invoke  GetDlgItemText,hWnddlg,ID_TXT,eax,256
    54.         or      eax,eax
    55.         jz      wmBYE
    56.         ; Заполнить структуру COPYDATASTRUCT
    57.         mov     cdata.dwData,CF_TEXT
    58.         ; Учитываем закрывающий строку 0
    59.         inc     eax
    60.         mov     cdata.cbData,eax
    61. jmp @f
    62. wmSEND_ICO:; Отправить изображение второму приложению
    63. mov     cdata.dwData,CF_BITMAP
    64. mov edx,p1
    65. invoke FindResource,0,,RT_ICON; find the resource
    66. mov hResource,rax
    67. invoke  SizeofResource,0,eax ; get its size
    68. mov     cdata.cbData,eax
    69. mov FSize,eax
    70. invoke LoadResource,0,hResource ; load the resource
    71. invoke LockResource,eax;pResource
    72. mov cdata.lpData,rax
    73. mov p,rax
    74. ;-------------------------------------------------
    75.         mov ecx,256
    76. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    77. mov [rsp+20h],rcx
    78. mov [rsp+28h],rcx
    79. mov edx,FSize
    80. invoke  CreateIconFromResourceEx,p,,TRUE,30000h;270376,TRUE,30000h
    81. mov [rsp+20h],rax
    82. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    83. xor p1,11b
    84. ;--------------------------------------------------
    85. jmp @f
    86. wmSEND_WAV:mov ecx,offset wav_file
    87. invoke CreateFile,,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,\
    88.         FILE_ATTRIBUTE_ARCHIVE,0
    89.         mov hFile,eax
    90.         invoke GetFileSize,eax,0
    91. mov FSize,eax
    92.         mov     cdata.dwData,CF_WAVE
    93.         mov     cdata.cbData,eax
    94. invoke GlobalAlloc,GPTR,eax
    95.         mov cdata.lpData,rax
    96. lea r9d,szReadWrite
    97. and qword ptr[rsp+20h],0
    98.         invoke ReadFile,hFile,eax,FSize
    99.         invoke CloseHandle,hFile
    100. @@:; Найти окно получателя
    101. mov edx,offset szWin
    102.         invoke  FindWindow,NULL
    103.         or      eax,eax
    104.         jz      wmBYE
    105. ; Отправить данные получателю
    106. lea r9d,cdata
    107. mov qword ptr[rsp+20h],SMTO_ABORTIFHUNG
    108. mov qword ptr[rsp+28h],500
    109. and qword ptr[rsp+30h],0
    110. invoke  SendMessageTimeout,eax,WM_COPYDATA,hWnddlg
    111. jmp wmBYE
    112. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    113.         je      wmSEND_TXT
    114.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    115.         je      wmSEND_ICO
    116. cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    117.         je      wmSEND_WAV
    118. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    119.         jne     wmBYE
    120. wmCLOSE:invoke EndDialog,,0
    121. wmBYE:  mov eax,TRUE
    122. exit0: leave
    123. retn
    124. DialogProc endp
    125. ;---------------------------------------
    126. .data
    127. szWin db 'WM_COPYDATA Reciever',0
    128. wav_file db '..\Images\03.wav',0
    129. p1 dd 1
    130. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_DIALOG 200
    7. #define IDC_ICON1 500
    8. #define IDC_IMG1 104
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "WM_COPYDATA Sender"
    15. BEGIN
    16.     CONTROL      "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON  "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. IDC_DIALOG equ 200
    4. IMAGE_BASE equ 400000h
    5. ID_TXT equ 100
    6. ID_ICON equ 102
    7. IDC_ICON1 equ 500
    8. COPYDATASTRUCT struct
    9.   dwData dq ? ;дескриптор типа передаваемых данных
    10.   cbData dd ?,? ;размер данных
    11.   lpData dq ? ;указатель на данные
    12. COPYDATASTRUCT ends
    13. .code
    14. WinMain proc dummy:qword
    15. mov r9d,offset DialogProc
    16. and qword ptr[rsp+20h],0
    17.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    18.         invoke  RtlExitUserProcess,NULL
    19. WinMain endp
    20. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    21. local p:qword
    22. local FSize:dword
    23. local lpwiocb:WAVEHDR
    24. local hWaveOut:qword
    25. mov hWnddlg,rcx
    26. mov lParam,r9
    27. cmp edx,WM_CLOSE
    28. je wmCLOSE
    29. cmp edx,WM_COPYDATA ; Пришло сообщение WM_COPYDATA?
    30. je wmCOPYDATA
    31. cmp edx,WM_COMMAND
    32. je wmCOMMAND
    33. xor eax,eax
    34. jmp exit0
    35. wmCOPYDATA:; Получить строку от первого приложения
    36. ; В lParam приходит указатель на структуру COPYDATASTRUCT
    37.         cmp     [r9+COPYDATASTRUCT.cbData],0; Размер данных нулевой?
    38.         je      wmBYE; Да, пропускаем
    39.         cmp     [r9+COPYDATASTRUCT.dwData],CF_TEXT; Это нужный тип данных?
    40.         je COPYDATA_TEXT; Нет, пропускаем
    41. cmp     [r9+COPYDATASTRUCT.dwData],CF_BITMAP; Это нужный тип данных?
    42.         je COPYDATA_ICON; Нет, пропускаем
    43. cmp     [r9+COPYDATASTRUCT.dwData],CF_WAVE; Это нужный тип данных?
    44.         jne wmBYE
    45. COPYDATA_MUSIC:mov eax,[r9+COPYDATASTRUCT.cbData]
    46. mov FSize,eax
    47. mov r8,[r9+COPYDATASTRUCT.lpData]
    48. mov p,r8
    49.         add r8d,14h
    50.         lea ecx,hWaveOut
    51.         xor r9,r9
    52. mov [rsp+20h],r9
    53. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    54.         or edx,WAVE_MAPPER
    55.         invoke waveOutOpen
    56. ; Подготавливаем заголовок для вывода
    57. xor eax,eax
    58. mov ecx,(sizeof WAVEHDR)/8
    59. lea edx,lpwiocb
    60. mov edi,edx
    61. rep stosq
    62. mov rax,p
    63. add rax,2Ch
    64. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    65. mov eax,FSize
    66. sub eax,2Ch
    67. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    68. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    69. ; Запускаем проигрывание блока
    70. lea edx,lpwiocb
    71. invoke waveOutWrite,hWaveOut,,sizeof WAVEHDR
    72. @@: test lpwiocb.dwFlags,WHDR_DONE
    73. jz @b
    74. lea edx,lpwiocb
    75. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    76. invoke waveOutClose,hWaveOut
    77. jmp wmBYE
    78. COPYDATA_TEXT:
    79.         invoke  SetDlgItemText,,ID_TXT,[r9+COPYDATASTRUCT.lpData]
    80. jmp wmBYE
    81. COPYDATA_ICON:; Создать HICON напрямую из памяти
    82. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    83. mov qword ptr[rsp+20h],256
    84. mov qword ptr[rsp+28h],256
    85. invoke  CreateIconFromResourceEx,[r9+COPYDATASTRUCT.lpData],\
    86. [r9+COPYDATASTRUCT.cbData],TRUE,30000h
    87. mov [rsp+20h],rax
    88. invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON;,eax
    89. jmp wmBYE
    90. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    91. jne wmBYE
    92. wmCLOSE:invoke EndDialog,,0
    93. wmBYE:  mov eax,TRUE
    94. exit0: leave
    95. ret
    96. DialogProc endp
    97. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "WM_COPYDATA Reciever"
    9. BEGIN
    10. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13. CONTROL 1,ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
     
    Последнее редактирование: 24 янв 2024
    Marylin нравится это.
  3. Mikl___

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

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

    02. Clipboard

    Функции для работы с Clipboard

    В Windows предусмотрено несколько функций для работы с Clipboard.
    Перед тем как выполнить запись или чтение данных, приложение должно получить доступ к Clipboard, открыв ее при помощи функции OpenClipboard:
    Код (C):
    1. BOOL WINAPI OpenClipboard(HWND hwnd);
    В качестве параметра этой функции передается дескриптор окна, которое будет "владеть" Clipboard. При необходимости функция этого окна будет получать сообщения, извещающие о необходимости выполнения определенных операций с Clipboard. Если доступ к Clipboard получен, OpenClipboard = TRUE. Если же Clipboard уже открыт другим приложением, OpenClipboard вернет FALSE.
    После использования приложение должно закрыть Clipboard, вызвав функцию CloseClipboard:
    Код (C):
    1. BOOL WINAPI CloseClipboard(void);
    Функция в случае успеха возвращает TRUE, в случае ошибки ― FALSE.
    Содержимое открытого Clipboard можно сбросить функцией EmptyClipboard:
    Код (C):
    1. BOOL WINAPI EmptyClipboard(void);
    EmptyClipboard возвращает TRUE при нормальном завершении или FALSE при ошибке.
    Для выполнения записи данных в Clipboard используют функцию SetClipboardData:
    Код (C):
    1. HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE  hData);
    У SetClipboardData два параметра. Первый параметр определяет формат запоминаемых в Clipboard данных, второй параметр передается дескриптор незафиксированного глобального блока памяти, содержащего запоминаемые данные.
    Для параметра uFormat используют константу, соответствующую одному из предопределенных форматов, или константу полученную от функции RegisterClipboardFormat.
    Функция RegisterClipboardFormat позволяет регистрировать собственные форматы данных для Clipboard.
    Список предопределенных форматов данных для Clipboard в разделе об WM_COPYDATA.
    Для чтения данных из Clipboard используют функцию GetClipboardData:
    Код (C):
    1. HANDLE  WINAPI GetClipboardData(UINT uFormat);
    Единственный параметр задает требуемый формат данных. Если Clipboard содержит данные в указанном формате, функция GetClipboardData возвращает дескриптор незафиксированного глобального блока памяти, содержащего требуемые данные.
    Запись данных в Clipboard
    Для записи данных в Clipboard, выполняют следующую последовательность действий:
    1. Открыть Clipboard функцией OpenClipboard
    2. Сбросить содержимое Clipboard функцией EmptyClipboard
    3. Заказать с помощью GlobalAlloc глобальный блок памяти с размером, достаточным для размещения записываемых в Clipboard данных
    4. Зафиксировать полученный блок памяти функцией GlobalLock
    5. Записать в зафиксированный блок памяти данные
    6. Расфиксировать блок памяти функцией GlobalUnlock
    7. Вызвать функцию SetClipboardData, передав ей через первый параметр формат данных, а через второй ― дескриптор расфиксированного блока памяти, содержащего данные
    8. Закрыть Clipboard функцией CloseClipboard
    Блок памяти, полученный для данных, не уничтожается функцией GlobalFree, после того как его дескриптор был использован в вызове функции SetClipboardData.
    При записи в Clipboard перемещения данных не происходит. Функция SetClipboardData изменяет атрибуты передаваемого ей блока памяти, блок памяти меняет своего "хозяина", переходит в собственность операционной системы Windows и приобретает атрибут GMEM_DDESHARE.
    Если приложение заказало глобальный блок памяти без атрибута GMEM_DDESHARE, этот блок памяти принадлежит приложению. Оно отвечает за уничтожение такого блока памяти. Если же приложение "забыло" уничтожить заказанный ей глобальный блок памяти, блок памяти уничтожает Windows при завершении приложения.
    Блок памяти, предназначенный для хранения данных Clipboard, не уничтожается при завершении работы приложения, создавшего его.
    Если приложение снабдит блок памяти атрибутом GMEM_DDESHARE, Windows не будет автоматически уничтожать его при завершении работы приложения. Приложение обязано уничтожить его самостоятельно, как только этот блок памяти перестанет быть нужным.
    Блоки памяти с атрибутом GMEM_DDESHARE используются в Windows для организации общего поля памяти, доступного всем приложениям. В Windows для адресации памяти все приложения обращаются к одной локальной таблице дескрипторов LDT, все приложения могут адресоваться к одному блоку памяти, если будут знать его селектор.
    Память Clipboard в Windows устроена в виде набора блоков памяти "общего пользования" (по одному на каждый формат данных). Функция SetClipboardData получает у приложения "личный" глобальный блок памяти с данными, и отдает его в "коллективное пользование", добавляя атрибут GMEM_DDESHARE.
    Если данные записаны в Clipboard с передачей дескриптора глобального блока памяти функции SetClipboardData, больше нельзя использовать этот дескриптор для адресации данных.
    В любой момент времени пользователь может уничтожить такой блок памяти записью в Clipboard новых данных. В процессе записи новых данных приложение вызовет функцию EmptyClipboard, которая уничтожит все блоки памяти, распределенные Clipboard раньше.
    Если операция записи данных в Clipboard выполняется при обработке одного сообщения, никакое другое приложение не будет работать с Clipboard во время записи данных. Если этот обработчик попутно создает диалоговые панели, пользователь может записать в Clipboard содержимое, например, однострочного текстового редактора, реализованного в виде органа управления диалоговой панели.
    Для исключения конфликтных ситуаций, связанных с попыткой одновременного доступа к Clipboard со стороны нескольких приложений, используют следующее правило:
    Все операции с Clipboard от его открытия и до закрытия должны выполняться в одном обработчике сообщения. Нельзя открывать Clipboard в обработчике одного сообщения, а закрывать в обработчике другого сообщения. Между открытием и закрытием Clipboard нельзя создавать диалоговые панели или выполнять другие действия, которые могут повлечь за собой создание диалоговых панелей (например, вызов функций SendMessage или PeekMessage)
    Операционная система Windows создает для каждого приложения отдельную локальную таблицу дескрипторов LDT и отдельное адресное пространство. Никакое приложение ни при каких обстоятельствах не может иметь доступа к адресному пространству другого приложения.
    Если для передачи данных между приложениями использовать функции Clipboard, гарантирована совместимость на уровне исходных текстов с операционной системой Windows.
    Чтение данных из Clipboard
    Процедура чтения данных из Clipboard. Приложение должно сделать следующее.
    1. Открыть Clipboard функцией OpenClipboard
    2. Вызвать GetClipboardData, передав ей через единственный параметр требуемый формат данных. Если Clipboard содержит данные в указанном формате, функция GetClipboardData возвратит дескриптор незафиксированного блока памяти, содержащего нужные данные. Если в Clipboard нет данных в указанном формате, будет возвращено значение NULL
    3. Зафиксировать блок памяти, дескриптор которого получен от функции GetClipboardData, функцией GlobalLock
    4. Переписать данные из зафиксированного буфера данных Clipboard в буфер, заказанный специально для этого приложением
    5. Расфиксировать блок памяти, дескриптор которого получен от функции GetClipboardData, функцией GlobalUnlock
    6. Закрыть Clipboard функцией CloseClipboard
    Чтение содержимого Clipboard, как и запись в Clipboard, нужно выполнять в обработчике одного сообщения.
    Приложение должно переписать данные из блока памяти Clipboard в свой, созданный специально, а не пользоваться блоком памяти, дескриптор которого был получен от функции GetClipboardData. В любой момент времени пользователь может уничтожить этот блок памяти, перезаписав содержимое Clipboard новыми данными.
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. IDC_DIALOG equ 200
    4. ID_TXT equ 100
    5. ID_ICON equ 102
    6. IDC_ICON1 equ 500
    7. WM_CLIPBOARDUPDATE  equ 31Dh
    8. .code
    9. WinMain proc  dummy:qword
    10. mov r9d,offset DialogProc
    11. and qword ptr[rsp+20h],0
    12.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    13.         invoke  RtlExitUserProcess,NULL
    14. WinMain endp
    15. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    16. local buffer[96]:BYTE
    17. local hGin:qword
    18. local p:qword
    19. local FSize:dword
    20. local lpwiocb:WAVEHDR
    21. local hWaveOut:qword
    22. mov hWnddlg,rcx
    23. mov lParam,r9
    24. cmp edx,WM_CLOSE
    25. je wmCLOSE
    26. cmp edx,WM_CLIPBOARDUPDATE
    27. je wmCLIPBOARDUPDATE
    28. cmp edx,WM_COMMAND
    29. je wmCOMMAND
    30. xor eax,eax
    31. jmp exit0
    32. wmCLIPBOARDUPDATE:; Получить строку от первого приложения
    33. ; В lParam приходит указатель на тип данных?
    34. invoke OpenClipboard,hWnddlg ;открываем буфер обмена
    35. invoke __imp_GetClipboardData,lParam;извлекаем текст из буфера обмена
    36. mov hGin,rax
    37. invoke GlobalLock,eax  ;блокируем память
    38. cmp     lParam,CF_WAVE; Это нужный тип данных?
    39.         jz WAVE
    40. cmp     lParam,CF_DIB; Это нужный тип данных?
    41.         jz DIB
    42. cmp lParam,CF_TEXT
    43. jnz wmBYE
    44. ;---------------------------------------------------
    45. TXT: mov ecx,96
    46. mov esi,eax
    47. lea edi,buffer
    48. mov r8d,edi
    49. rep movsb
    50.         invoke  SetDlgItemText,hWnddlg,ID_TXT
    51. jmp @0
    52. DIB: and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    53. mov qword ptr[rsp+20h],256
    54. mov qword ptr[rsp+28h],256
    55. invoke  CreateIconFromResourceEx,eax,lParam,TRUE,30000h
    56. mov [rsp+20h],rax
    57. invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON;,eax
    58. jmp @0
    59. WAVE: mov p,rax
    60. mov r8,rax;p
    61. mov eax,[r8+4]
    62. mov FSize,eax
    63.         add r8d,14h
    64.         lea ecx,hWaveOut
    65.         xor r9,r9
    66. mov [rsp+20h],r9
    67. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    68.         or edx,WAVE_MAPPER
    69.         invoke waveOutOpen
    70. ; Подготавливаем заголовок для вывода
    71. lea edx,lpwiocb
    72. mov edi,edx
    73. xor eax,eax
    74. mov ecx,(sizeof WAVEHDR)/8
    75. rep stosq
    76. mov rax,p
    77. add rax,2Ch
    78. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    79. mov eax,FSize
    80. sub eax,2Ch
    81. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    82. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    83. ; Запускаем проигрывание блока
    84. lea edx,lpwiocb
    85. invoke waveOutWrite,hWaveOut,,sizeof WAVEHDR
    86. @@: test lpwiocb.dwFlags,WHDR_DONE
    87. jz @b
    88. lea edx,lpwiocb
    89. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    90. invoke waveOutClose,hWaveOut
    91. @0: invoke GlobalLock,hGin
    92. invoke CloseClipboard
    93. jmp wmBYE
    94. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    95. jne wmBYE
    96. wmCLOSE:invoke EndDialog,,0
    97. wmBYE:  mov eax,TRUE
    98. exit0: leave
    99. ret
    100. DialogProc endp
    101. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "Clipboard Reciever"
    9. BEGIN
    10. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13. CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. ID_SEND_ICO equ 102
    6. ID_SEND_WAV equ 103
    7. IDC_DIALOG equ 200
    8. IDC_ICON1 equ 500
    9. IDC_IMG1 equ 104
    10. WM_CLIPBOARDUPDATE  equ 31Dh
    11. extern __imp_SetClipboardData:qword
    12. .code
    13. WinMain proc
    14. enter 30h,0
    15. mov r9d,256;cx
    16. mov [rbp-10h],r9
    17. mov qword ptr [rbp-8],LR_DEFAULTCOLOR
    18. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    19. mov r9d,offset DialogProc
    20. mov qword ptr[rbp-10h],rax;30h-10h=+20h
    21. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    22. invoke RtlExitUserProcess,NULL
    23. WinMain endp
    24. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    25. size_of_buffer equ 96
    26. local buffer[size_of_buffer]:BYTE
    27. local hGout:qword
    28. local p:qword
    29. local FSize:dword
    30. local hFile:dword
    31. local szReadWrite:qword ;number of bytes actually read or write
    32. local hResource:qword
    33. local pResource:qword
    34. local type0:qword
    35. mov hWnddlg,rcx
    36. mov lParam,r9
    37. cmp edx,WM_CLOSE
    38. je wmCLOSE
    39. cmp edx,WM_COMMAND
    40. je wmCOMMAND
    41. cmp edx,WM_INITDIALOG
    42. je wmINITDIALOG
    43. xor eax,eax
    44. jmp exit0
    45. wmINITDIALOG:;
    46.         invoke GetDlgItem,,IDC_IMG1
    47. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    48. jmp wmBYE
    49. wmSEND_TXT:lea r8d,buffer
    50. invoke  GetDlgItemText,,ID_TXT,,size_of_buffer;255
    51.         or      eax,eax
    52.         jz      wmBYE
    53. mov FSize,eax
    54. invoke GlobalAlloc,GPTR,size_of_buffer;GHND or GMEM_DDESHARE
    55. mov hGout,rax
    56. invoke GlobalLock,eax
    57. mov p,rax
    58. mov edi,eax
    59. lea esi,buffer
    60. mov ecx,FSize
    61. rep movsb
    62. and byte ptr[rdi],0
    63. mov type0,CF_TEXT
    64. ;----------------------------------------------------
    65. jmp @f
    66. wmSEND_ICO:; Отправить изображение второму приложению
    67. mov edx,p1
    68. invoke FindResource,0,,RT_ICON; find the resource
    69. mov hResource,rax
    70. invoke  SizeofResource,0,eax ; get its size
    71. mov FSize,eax
    72. invoke GlobalAlloc,GPTR,eax; or GMEM_DDESHARE,eax
    73. mov hGout,rax
    74. invoke GlobalLock,eax
    75. mov p,rax
    76. mov edi,eax
    77. invoke LoadResource,0,hResource ; load the resource
    78. invoke LockResource,eax;pResource
    79. mov esi,eax
    80. mov ecx,FSize
    81. rep movsb
    82. ;------------------------------------------------
    83.         mov ecx,256
    84. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    85. mov [rsp+20h],rcx
    86. mov [rsp+28h],rcx
    87. mov edx,FSize
    88. invoke  CreateIconFromResourceEx,p,,TRUE,30000h
    89. mov [rsp+20h],rax
    90. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    91. mov type0,CF_DIB
    92. xor p1,11b
    93. ;--------------------------------------------------
    94. jmp @f
    95. wmSEND_WAV:mov ecx,offset wav_file
    96. invoke CreateFile,,GENERIC_READ,0,0,OPEN_EXISTING,\
    97.         FILE_ATTRIBUTE_ARCHIVE,0
    98.         mov hFile,eax
    99.         invoke GetFileSize,eax,0
    100. mov FSize,eax
    101. invoke GlobalAlloc,GPTR,eax
    102. mov hGout,rax
    103. invoke GlobalLock,eax
    104. mov p,rax
    105. lea r9d,szReadWrite
    106.         invoke ReadFile,hFile,eax,FSize,,0
    107.         invoke CloseHandle,hFile
    108. mov type0,CF_WAVE
    109. ;--------------------------------------------------------
    110. @@: invoke GlobalUnlock,hGout
    111. invoke OpenClipboard,hWnddlg
    112. or eax,eax
    113. jz wmBYE
    114. invoke EmptyClipboard
    115. invoke __imp_SetClipboardData,type0,hGout
    116. invoke CloseClipboard
    117. ; Найти окно получателя
    118. mov edx,offset szWin
    119.         invoke  FindWindow,NULL
    120.         or      eax,eax
    121.         jz      wmBYE
    122. ; Отправить данные получателю
    123. invoke  PostMessage,eax,WM_CLIPBOARDUPDATE,hWnddlg,type0
    124. jmp wmBYE
    125. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    126.         je      wmSEND_TXT
    127.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    128.         je      wmSEND_ICO
    129. cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    130.         je      wmSEND_WAV
    131. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    132.         jne     wmBYE
    133. wmCLOSE:invoke EndDialog,,0
    134. wmBYE:  mov eax,TRUE
    135. exit0: leave
    136. retn
    137. DialogProc endp
    138. ;---------------------------------------
    139. .data
    140. szWin db 'Clipboard Reciever',0
    141. wav_file db '..\Images\03.wav',0
    142. p1 dd 1
    143. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_DIALOG 200
    7. #define IDC_ICON1 500
    8. #define IDC_IMG1 104
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "Clipboard Sender"
    15. BEGIN
    16.     CONTROL      "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON  "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
     
    Marylin нравится это.
  4. Mikl___

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

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

    04. Paging File (страничный файл)

    Страничный файл входит в общую физическую память вычислительной системы увеличивая ее объем. В физической памяти создается проекция страничного файла, которая отображается на виртуальное адресное пространство нескольких процессов. Первый процесс создает в памяти проекцию страничного файла и отображает ее на свое адресное пространство, записывает в эту память некоторые данные. Второй процесс отображает ту же проекцию страничного файла на свое адресное пространство, читает эти данные. При создании проекции файла в разделе Memory Mapped File в качестве первого параметра функции CreateFileMapping указывают дескриптор открытого файла на диске. Чтобы создать проекцию страничного файла, первый параметр функции CreateFileMapping должен быть равным -1 (INVALID_HANDLE_VALUE). Предпоследний параметр функции задает размер проекции, а последний ― произвольное имя объекта, которое должно быть известно во втором процессе. С помощью функции MapViewOfFile в виртуальной памяти процесса выделяется область в памяти того же размера и проекция страничного файла отображается на эту же область памяти.
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. ID_SEND_ICO equ 102
    6. ID_SEND_WAV equ 103
    7. IDC_DIALOG equ 200
    8. IDC_ICON1 equ 500
    9. IDC_IMG1 equ 104
    10. .code
    11. WinMain proc dummy:qword
    12.        mov r9d,256
    13.        mov [rsp+20h],r9
    14.        mov qword ptr [rsp+28],LR_DEFAULTCOLOR
    15.        invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON
    16.        mov r9d,offset DialogProc
    17.        mov qword ptr[rsp+20h],rax
    18.        invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    19.        invoke RtlExitUserProcess,NULL
    20. WinMain endp
    21. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    22. size_of_buffer equ 96
    23. local buffer[size_of_buffer]:BYTE
    24. local hFile:dword
    25. local FSize:dword
    26. local hMapping:qword
    27. local pMapping:qword
    28. local hResource:qword
    29. local pResource:qword
    30. local szReadWrite:qword
    31. local type0:qword
    32.        mov hWnddlg,rcx
    33.        mov lParam,r9
    34.        cmp edx,WM_CLOSE
    35.        je wmCLOSE
    36.        cmp edx,WM_COMMAND
    37.        je wmCOMMAND
    38.        cmp edx,WM_INITDIALOG
    39.        je wmINITDIALOG
    40.        xor eax,eax
    41.        jmp exit0
    42. wmINITDIALOG:;
    43.         invoke GetDlgItem,,IDC_IMG1
    44.        invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    45.        jmp wmBYE
    46. wmSEND_TXT:       lea r8d,buffer
    47.        invoke  GetDlgItemText,,ID_TXT,,size_of_buffer
    48.         or      eax,eax
    49.         jz      wmBYE
    50.         inc     eax
    51.        mov FSize,eax
    52. ;создание в памяти объекта "проекция файла"
    53.        sub esp,30h
    54.        movr qword ptr[rsp+28h],szMapName
    55.        mov eax,FSize
    56.        mov [rsp+20h],rax
    57.        or rcx,INVALID_HANDLE_VALUE
    58.         invoke CreateFileMapping,,0,PAGE_READWRITE,0
    59.        mov hMapping,rax
    60. ;отображение проекции файла на адресное пространство процесса
    61. mov ecx,eax
    62. mov eax,FSize
    63. mov [rsp+20h],rax
    64. invoke MapViewOfFile,,FILE_MAP_ALL_ACCESS,0,0
    65. mov pMapping,rax
    66. mov ecx,FSize
    67. mov edi,eax
    68. lea esi,buffer
    69. rep movsb
    70. mov type0,WM_USER+1
    71. ;--------------------------------------------------
    72. jmp @f
    73. wmSEND_ICO:sub esp,30h
    74. mov edx,p1
    75. invoke FindResource,0,,RT_ICON; find the resource
    76. mov hResource,rax
    77. invoke  SizeofResource,0,eax ; get its size
    78. mov     FSize,eax
    79. invoke LoadResource,0,hResource ; load the resource
    80. invoke LockResource,eax
    81. mov esi,eax
    82. ;созддание в памяти объекта "проекция файла"
    83. movr qword ptr[rsp+28h],szMapName
    84. mov eax,FSize
    85. mov [rsp+20h],rax
    86. or rcx,INVALID_HANDLE_VALUE
    87.         invoke CreateFileMapping,,0,PAGE_READWRITE,0
    88. mov hMapping,rax
    89. ;отображение проекции файла на адресное пространство процесса
    90. mov ecx,eax
    91. mov eax,FSize
    92. mov [rsp+20h],rax
    93. invoke MapViewOfFile,,FILE_MAP_ALL_ACCESS,0,0
    94. mov pMapping,rax
    95. mov ecx,FSize
    96. mov edi,eax;rdi,pMapping
    97. rep movsb
    98. ;--------------------------------------------------
    99.         mov ecx,256
    100. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    101. mov [rsp+20h],rcx
    102. mov [rsp+28h],rcx
    103. mov edx,FSize
    104. invoke  CreateIconFromResourceEx,pMapping,,TRUE,30000h;270376,TRUE,30000h
    105. mov [rsp+20h],rax
    106. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    107. xor p1,11b
    108. mov type0,WM_USER+2
    109. ;-------------------------------------------------------
    110. jmp @f
    111. wmSEND_WAV:sub esp,40h
    112. mov ecx,offset wav_file
    113. xor r9d,r9d
    114. mov qword ptr[rsp+30h],r9
    115. mov qword ptr[rsp+28h],FILE_ATTRIBUTE_ARCHIVE
    116. mov qword ptr[rsp+20h],OPEN_EXISTING
    117. invoke CreateFile,,GENERIC_READ or GENERIC_WRITE,\
    118. FILE_SHARE_READ or FILE_SHARE_WRITE
    119.         mov hFile,eax
    120.         invoke GetFileSize,eax,0
    121. mov FSize,eax
    122. ;созддание в памяти объекта "проекция файла"
    123. movr qword ptr[rsp+28h],szMapName
    124. mov eax,FSize
    125. mov [rsp+20h],rax
    126. or rcx,INVALID_HANDLE_VALUE
    127.         invoke CreateFileMapping,,0,PAGE_READWRITE,0
    128. mov hMapping,rax
    129. ;отображение проекции файла на адресное пространство процесса
    130. xor r8d,r8d
    131. mov [rsp+20h],r8
    132. invoke MapViewOfFile,eax,FILE_MAP_ALL_ACCESS,,0,FSize
    133. mov pMapping,rax
    134. ;-------------------------------------------------
    135. and qword ptr[rsp+20h],0
    136. lea r9,szReadWrite
    137. invoke ReadFile,hFile,pMapping,FSize
    138. mov type0,WM_USER+3
    139. @@:; Найти окно получателя
    140. mov edx,offset szWin
    141.         invoke  FindWindow,NULL
    142.         or      eax,eax
    143.         jz      wmBYE
    144. ; Отправить данные получателю
    145. mov qword ptr[rsp+20h],SMTO_ABORTIFHUNG
    146. mov qword ptr[rsp+28h],5000
    147. and qword ptr[rsp+30h],0
    148.         invoke  SendMessageTimeout,eax,type0,hWnddlg,FSize
    149. invoke UnmapViewOfFile,pMapping
    150. invoke CloseHandle,hMapping
    151. jmp wmBYE
    152. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    153.         je      wmSEND_TXT
    154.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    155.         je      wmSEND_ICO
    156. cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    157.         je      wmSEND_WAV
    158. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    159.         jne     wmBYE
    160. wmCLOSE:invoke EndDialog,,0
    161. wmBYE:  mov eax,TRUE
    162. exit0: leave
    163. retn
    164. DialogProc endp
    165. ;---------------------------------------
    166. .data
    167. szWin db 'Paging File Reciever',0
    168. wav_file db '..\Images\03.wav',0
    169. szMapName db "13-15=Mapping",0
    170. p1 dd 1
    171. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_DIALOG 200
    7. #define IDC_ICON1 500
    8. #define IDC_IMG1 104
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "Paging File Sender"
    15. BEGIN
    16.     CONTROL      "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON  "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. IDC_DIALOG equ 200
    4. IMAGE_BASE equ 400000h
    5. ID_TXT equ 100
    6. ID_ICON equ 102
    7. IDC_ICON1 equ 500
    8. .code
    9. WinMain proc dummy:qword
    10. mov r9d,offset DialogProc
    11. and qword ptr[rsp+20h],0
    12.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    13.         invoke  RtlExitUserProcess,NULL
    14. WinMain endp
    15. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    16. local pMapping:qword
    17. local hMapping:qword
    18. local FSize:dword
    19. local lpwiocb:WAVEHDR
    20. local hWaveOut:qword
    21. local type0:dword
    22. mov hWnddlg,rcx
    23. mov lParam,r9
    24. cmp edx,WM_CLOSE
    25. je wmCLOSE
    26. cmp edx,WM_USER+3
    27. je wmUSER_3
    28. cmp edx,WM_USER+1
    29. je wmUSER_1
    30. cmp edx,WM_USER+2
    31. je wmUSER_2
    32. cmp edx,WM_COMMAND
    33. je wmCOMMAND
    34. xor eax,eax
    35. jmp exit0
    36. wmUSER_3:; Получить музыку от первого приложения
    37. mov type0,CF_WAVE
    38. jmp @f
    39. wmUSER_1:; Получить строку от первого приложения
    40. mov type0,CF_TEXT
    41. jmp @f
    42. wmUSER_2:; Получить картинку от первого приложения
    43. mov type0,CF_DIB
    44. @@: mov r8d,offset lpszName
    45. invoke OpenFileMapping,FILE_MAP_ALL_ACCESS,FALSE
    46. mov hMapping,rax
    47. mov ecx,eax
    48. mov rax,lParam
    49. mov [rsp+20h],rax
    50. invoke MapViewOfFile,,FILE_MAP_ALL_ACCESS,0,0
    51. mov pMapping,rax
    52. cmp type0,CF_TEXT
    53. je TXT
    54. cmp type0,CF_DIB
    55. je DIB
    56. WAVE: mov r8,pMapping
    57.         add r8d,14h
    58.         lea ecx,hWaveOut
    59.         xor r9,r9
    60. mov [rsp+20h],r9
    61. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    62.         or edx,WAVE_MAPPER
    63.         invoke waveOutOpen
    64. ; Подготавливаем заголовок для вывода
    65. lea edx,lpwiocb
    66. mov edi,edx
    67. xor eax,eax
    68. mov ecx,(sizeof WAVEHDR)/8
    69. rep stosq
    70. mov rax,pMapping
    71. mov ecx,eax
    72. add rax,2Ch
    73. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    74. mov eax,[rcx+4]
    75. sub eax,2Ch
    76. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    77. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    78. ; Запускаем проигрывание блока
    79. lea edx,lpwiocb
    80. mov rcx,hWaveOut
    81. mov r8d,sizeof WAVEHDR
    82. invoke waveOutWrite
    83. @@: cmp lpwiocb.dwFlags,WHDR_DONE or WHDR_PREPARED
    84. jnz @b
    85. lea edx,lpwiocb
    86. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    87. invoke waveOutClose,hWaveOut
    88. jmp @f
    89. TXT: invoke  SetDlgItemText,hWnddlg,ID_TXT,pMapping
    90. jmp @f
    91. DIB: and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    92. mov qword ptr[rsp+20h],256
    93. mov qword ptr[rsp+28h],256
    94. invoke  CreateIconFromResourceEx,pMapping,lParam,TRUE,30000h
    95. mov [rsp+20h],rax
    96. invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    97. @@: invoke UnmapViewOfFile,pMapping
    98.         invoke CloseHandle,hMapping
    99. jmp wmBYE
    100. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    101. jne wmBYE
    102. wmCLOSE:invoke EndDialog,,0
    103. wmBYE:  mov eax,TRUE
    104. exit0: leave
    105. ret
    106. DialogProc endp
    107. lpszName db "13-15=Mapping",0
    108. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "Paging File Reciever"
    9. BEGIN
    10. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13. CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
     
  5. Mikl___

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

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

    06a. Named Pipe

    Средство передачи данных между параллельно работающими процессами. Позволяет организовать передачу данных между локальными процессами, а также между процессами, запущенными на различных рабочих станциях в сети.
    Pipe-каналы похожи на файлы. Pipe просты в использовании.
    Через Pipe-канал можно передавать данные только между двумя процессами. Один из процессов создает канал, другой открывает его. После этого оба процесса могут передавать данные через канал в одну или обе стороны, используя для этого функции, предназначенные для работы с файлами ReadFile и WriteFile. Приложения могут выполнять над Pipe-каналами синхронные или асинхронные операции. При использовании асинхронных операций необходимо обеспечить синхронизацию.

    Именованные и анонимные каналы

    Существуют две разновидности pipe-каналов ― именованные (Named Pipes) и анонимные (Anonymous Pipes). Именованным каналам при создании присваивается имя, которое доступно для других процессов. Зная имя какой-либо рабочей станции в сети, процесс может получить доступ к каналу, созданному на этой рабочей станции.
    Анонимные каналы используются для организации передачи данных между родительскими и дочерними процессами, запущенными на одном компьютере.

    Имена каналов

    Имена каналов имеют следующий вид:
    Код (C):
    1. \\Имя_Сервера\pipe\Имя_Канала
    Если процесс открывает канал, созданный на другой рабочей станции нужно указать имя сервера. Если процесс создает канал или открывает канал на своей рабочей станции, вместо имени указывается символ точки:
    Код (C):
    1. \\.\pipe\Имя_Канала
    Процесс может создать канал только на той рабочей станции, где он запущен, поэтому при создании канала имя сервера никогда не указывается.

    Реализации каналов

    Один серверный процесс создает один канал (одну реализацию канала) для работы с одним клиентским процессом.
    Если требуется организовать взаимодействие одного серверного процесса с несколькими клиентскими. Например, сервер базы данных должен принимать от клиентов запросы и рассылать ответы на них. Тогда серверный процесс создает несколько реализаций канала, по одной реализации для каждого клиентского процесса.

    Функции для работы с каналами

    Наиболее важные функции предназначенные для работы с Pipe-каналами. Более подробная информация в документации MSDN.

    Создание канала

    Для создания именованных и анонимных pipe-каналов используются функции CreatePipe и CreateNamedPipe.

    Функция CreatePipe

    Анонимный канал создается функцией CreatePipe
    Код (C):
    1. BOOL CreatePipe(
    2.   PHANDLE hReadPipe,// адрес переменной, в которую будет записан дескриптор канала для чтения данных
    3.   PHANDLE hWritePipe,// адрес переменной, в которую будет записан дескриптор канала для записи данных
    4.   LPSECURITY_ATTRIBUTES lpPipeAttributes, // адрес переменной для атрибутов защиты
    5.   DWORD nSize);// количество байт памяти, зарезервированной для канала
    Канал может использоваться как для записи в него данных, так и для чтения. Поэтому при создании канала функция CreatePipe возвращает два дескриптора, записывая их по адресу, заданному в параметрах hReadPipe и hWritePipe.
    дескриптор, записанный по адресу hReadPipe, передается как параметр функции ReadFile или ReadFileEx для выполнения операции чтения. дескриптор, записанный по адресу hWritePipe, передается функции WriteFile или WriteFileEx для выполнения операции записи.
    Через параметр lpPipeAttributes передается адрес переменной, содержащей атрибуты защиты для создаваемого канала. Чаще этот параметр указывают как NULL. В результате канал будет иметь атрибуты защиты, принятые по умолчанию.
    Параметр nSize определяет размер буфера для создаваемого канала. Если этот размер указан как нуль, создается буфер с размером, принятым по умолчанию. При необходимости система может изменить указанный размер буфера.
    В случае успеха функция CreatePipe возвращает значение TRUE, при ошибке ― FALSE. Для уточнения причины возникновения ошибки используют функцию GetLastError.

    Функция CreateNamedPipe

    Для создания именованного канала Pipe используют функцию CreateNamedPipe. Прототип этой функции:
    Код (C):
    1. HANDLE CreateNamedPipe(
    2.   LPCTSTR lpName,          // адрес строки имени канала
    3.   DWORD   dwOpenMode,      // режим открытия канала
    4.   DWORD   dwPipeMode,      // режим работы канала
    5.   DWORD   nMaxInstances,   // максимальное количество реализаций канала
    6.   DWORD   nOutBufferSize,  // размер выходного буфера в байтах
    7.   DWORD   nInBufferSize,   // размер входного буфера в байтах
    8.   DWORD   nDefaultTimeOut, // время ожидания в миллисекундах
    9.   LPSECURITY_ATTRIBUTES lpSecurityAttributes); // адрес переменной для атрибутов защиты
    Через параметр lpName передается адрес строки имени канала в форме \\.\pipe\Имя_Канала (при создании канала имя сервера не указывается, так как канал можно создать только на той рабочей станции, где запущен процесс, создающий канал).
    Параметр dwOpenMode задает режим, в котором открывается канал.
    Pipe-канал может быть ориентирован либо на передачу потока байт, либо на передачу сообщений. В первом случае данные через канал передаются по байтам, во втором ― отдельными блоками заданной длины.
    Режим работы канала (ориентированный на передачу байт или сообщений) задается константами PIPE_TYPE_BYTE или PIPE_TYPE_MESSAGE, которые указываются в параметре dwOpenMode. По умолчанию используют режим PIPE_TYPE_BYTE.
    Помимо способа передачи данных через канал, с помощью параметра dwOpenMode можно указать, будет ли данный канал использован только для чтения данных, только для записи или одновременно для чтения и записи. Способ использования канала задается указанием одной из следующих констант:
    КонстантаhexbinИспользование канала
    PIPE_ACCESS_INBOUND
    1​
    00000001Только для чтения
    PIPE_ACCESS_OUTBOUND
    2​
    00000010Только для записи
    PIPE_ACCESS_DUPLEX
    3​
    00000011Для чтения и записи
    Перечисленные параметры должны быть одинаковы для всех реализаций канала. Параметры, которые могут отличаться для разных реализаций канала:
    Константаhex Использование канала
    PIPE_READMODE_BYTE
    0​
    Канал открывается на чтение в режиме последовательной передачи отдельных байт
    PIPE_READMODE_MESSAGE
    2​
    Канал открывается на чтение в режиме передачи отдельных сообщений указанной длины
    PIPE_WAIT
    0​
    Канал будет работать в блокирующем режиме, когда процесс переводится в состояние ожидания до завершения операций в канале
    PIPE_NOWAIT
    1​
    Неблокирующий режим работы канала. Если операция не может быть выполнена немедленно, в неблокирующем режиме функция завершается с ошибкой
    FILE_FLAG_OVERLAPPED
    40000000​
    Использование асинхронных операций (ввод и вывод с перекрытием). Данный режим позволяет процессу выполнять полезную работу параллельно с проведением операций в канале
    FILE_FLAG_WRITE_THROUGH
    80000000​
    В этом режиме функции, работающие с каналом, не возвращают управление до тех пор, пока не будет полностью завершена операция на удаленном компьютере. Используется только с каналом, ориентированном на передачу отдельных байт и только в том случае, когда канал создан между процессами, запущенными на различных станциях сети
    Дополнительно через параметр dwOpenMode можно передавать флаги защиты:
    ФлагhexОписание
    WRITE_DAC
    40000​
    Вызывающий процесс должен иметь права доступа на запись к произвольному управляющему списку доступа именованного канала access control list (ACL)
    WRITE_OWNER
    80000​
    Вызывающий процесс должен иметь права доступа на запись к процессу, владеющему именованным каналом Pipe
    ACCESS_SYSTEM_SECURITY1000000 Вызывающий процесс должен иметь права доступа на запись к управляющему списку доступа именованного канала access control list (ACL)
    Параметр dwPipeMode определяет режим работы канала. В этом параметре можно указать константы PIPE_TYPE_BYTE, PIPE_TYPE_MESSAGE, PIPE_READMODE_BYTE, PIPE_READMODE_MESSAGE, PIPE_WAIT и PIPE_NOWAIT. Для всех реализаций канала необходимо указывать один и тот же набор констант.
    Параметр nMaxInstances определяет максимальное количество реализаций, которые могут быть созданы для канала. Можно указывать значения от 1 до PIPE_UNLIMITED_INSTANCES. В случае максимальное количество реализаций ограничивается только наличием свободных системных ресурсов.
    Если один серверный процесс использует несколько реализаций канала для связи с несколькими клиентскими процессами, общее количество реализаций может быть меньше, чем потенциальное максимальное количество клиентов. Это связано с тем, что клиенты могут использовать реализации по очереди, если только они не пожелают связаться с серверным процессом все одновременно.
    Параметры nOutBufferSize и nInBufferSize определяют размер буферов, используемых для записи в канал и чтения из канала. При необходимости система может использовать буферы других, по сравнению с указанными, размеров.
    Параметр nDefaultTimeOut определяет время ожидания для реализации канала. Для всех реализаций необходимо указывать одинаковое значение этого параметра.
    Через параметр lpPipeAttributes передается адрес переменной, содержащей атрибуты защиты для создаваемого канала. Обычно этот параметр равен NULL. В результате канал будет иметь атрибуты защиты, принятые по умолчанию.
    В случае успеха функция CreateNamedPipe возвращает дескриптор созданной реализации канала, который можно использовать в операциях чтения и записи, выполняемых с помощью функций ReadFile и WriteFile.
    При ошибке CreateNamedPipe возвращает значение INVALID_HANDLE_VALUE. Код ошибки можете уточнить, вызвав функцию GetLastError.

    Использование функции CreateFile

    Функция CreateFile, предназначена для работы с файлами, может использоваться для создания новых каналов и открытия существующих. Вместо имени файла указывают имя pipe-канала.
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. WM_CLIPBOARDUPDATE equ 31Dh
    4. ID_TXT equ 100
    5. ID_SEND_TXT equ 101
    6. ID_SEND_ICO equ 102
    7. ID_SEND_WAV equ 103
    8. IDC_DIALOG equ 200
    9. IDC_ICON1 equ 500
    10. IDC_IMG1 equ 104
    11. .code
    12. WinMain proc dummy:qword
    13. mov r9d,256
    14. mov [rsp+20h],r9
    15. mov qword ptr [rsp+28],LR_DEFAULTCOLOR
    16. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    17. mov r9d,offset DialogProc
    18. mov qword ptr[rsp+20h],rax
    19. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    20. invoke RtlExitUserProcess,NULL
    21. WinMain endp
    22. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    23. size_of_buffer equ 256
    24. local cbWritten:dword;Количество байт, переданных через канал
    25. local FSize:dword;
    26. local hNamePipe:qword; дескриптор канала Mailslot
    27. local hFile:dword
    28. local p:qword
    29. local hResource:qword
    30. local type0:qword
    31. mov hWnddlg,rcx
    32. mov lParam,r9
    33. cmp edx,WM_CLOSE
    34. je wmCLOSE
    35. cmp edx,WM_COMMAND
    36. je wmCOMMAND
    37. cmp edx,WM_INITDIALOG
    38. je wmINITDIALOG
    39. xor eax,eax
    40. jmp exit0
    41. wmINITDIALOG:;
    42.         invoke GetDlgItem,,IDC_IMG1
    43. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    44. jmp wmBYE
    45. wmSEND_TXT:invoke GlobalAlloc,GPTR,size_of_buffer
    46.         mov p,rax;Буфер для передачи данных через канал
    47. invoke  GetDlgItemText,hWnddlg,ID_TXT,eax,size_of_buffer;255
    48.         or      eax,eax
    49.         jz      wmBYE
    50.         inc     eax
    51. mov FSize,eax
    52. mov type0,WM_USER+1
    53. jmp @f
    54. wmSEND_ICO:mov edx,p1
    55. invoke FindResource,0,,RT_ICON; find the resource
    56. mov hResource,rax
    57. invoke  SizeofResource,0,eax ; get its size
    58. mov FSize,eax
    59. invoke LoadResource,0,hResource ; load the resource
    60. invoke LockResource,eax;pResource
    61.   mov p,rax
    62. ;-------------------------------------------------
    63.         mov ecx,256
    64. and qword ptr[rsp+30h],LR_DEFAULTCOLOR
    65. mov [rsp+20h],rcx
    66. mov [rsp+28h],rcx
    67. mov edx,FSize
    68. invoke  CreateIconFromResourceEx,p,,TRUE,30000h
    69. mov [rsp+20h],rax
    70. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    71. xor p1,11b
    72. mov type0,WM_USER+2
    73. jmp @f
    74. wmSEND_WAV:mov ecx,offset wav_file
    75. xor r9d,r9d
    76. mov qword ptr[rsp+30h],r9
    77. mov qword ptr[rsp+28h],FILE_ATTRIBUTE_ARCHIVE
    78. mov qword ptr[rsp+20h],OPEN_EXISTING
    79. invoke CreateFile,,GENERIC_READ or GENERIC_WRITE,\
    80. FILE_SHARE_READ or FILE_SHARE_WRITE
    81.         mov hFile,eax
    82.         invoke GetFileSize,eax,0
    83. mov FSize,eax
    84. invoke GlobalAlloc,GPTR,eax
    85.         mov p,rax
    86. lea r9d,cbWritten
    87. and qword ptr[rsp+20h],0
    88.         invoke ReadFile,hFile,eax,FSize
    89.         invoke CloseHandle,hFile
    90. mov type0,WM_USER+3
    91. @@:; Найти окно получателя
    92. mov edx,offset szWin
    93.         invoke  FindWindow,NULL
    94.         or      eax,eax
    95.         jz      wmBYE
    96.         ; Отправить данные получателю
    97. mov qword ptr[rsp+20h],SMTO_ABORTIFHUNG
    98. mov qword ptr[rsp+28h],250
    99. and qword ptr[rsp+30h],0
    100.         invoke  SendMessageTimeout,eax,type0,hWnddlg,FSize
    101. ; Создаем пайп
    102. mov ecx,offset szPipeName
    103. xor r9d,r9d
    104. mov qword ptr[rsp+20h],OPEN_EXISTING
    105. mov [rsp+28h],r9
    106. mov [rsp+30h],r9
    107. invoke CreateFile,,GENERIC_WRITE,FILE_SHARE_READ
    108. mov hNamePipe,rax
    109. mov rdx,p
    110. lea r9d,cbWritten
    111. and qword ptr[rsp+20h],0
    112.         invoke WriteFile,eax,,FSize
    113. ;Закрываем дескриптор канала
    114. invoke CloseHandle,hNamePipe
    115. jmp wmBYE
    116. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    117.         je      wmSEND_TXT
    118.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    119.         je      wmSEND_ICO
    120.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    121.         je      wmSEND_WAV
    122. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    123.         jne     wmBYE
    124. wmCLOSE:invoke EndDialog,,0
    125. wmBYE:  mov eax,TRUE
    126. exit0: leave
    127. retn
    128. DialogProc endp
    129. ;---------------------------------------
    130. szWin db 'Pipe Reciever',0
    131. szPipeName db "\\.\pipe\MyPipe",0; Имя создаваемого пайпа
    132. p1 dd 1
    133. wav_file db '..\Images\03.wav',0
    134. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_DIALOG 200
    7. #define IDC_ICON1 500
    8. #define IDC_IMG1 104
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "Pipe Sender"
    15. BEGIN
    16.     CONTROL      "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON  "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. WM_CLIPBOARDUPDATE equ 31Dh
    4. IDC_DIALOG equ 200
    5. ID_TXT equ 100
    6. ID_ICON equ 102
    7. IDC_ICON1 equ 500
    8. .code
    9. WinMain proc dummy:qword
    10. mov r9d,offset DialogProc
    11. and qword ptr[rsp+20h],0
    12.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    13.         invoke  RtlExitUserProcess,NULL
    14. WinMain endp
    15. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    16. local cbRead:DWORD;Количество байт данных, принятых через канал
    17. local buffer:qword;Буфер для передачи данных через канал
    18. local lpwiocb:WAVEHDR
    19. local hWaveOut:qword
    20. mov hWnddlg,rcx
    21. mov lParam,r9
    22. cmp edx,WM_CLOSE
    23. je wmCLOSE
    24. cmp edx,WM_USER+1
    25. je wmUSER_1
    26. cmp edx,WM_USER+2
    27. je wmUSER_2
    28. cmp edx,WM_USER+3
    29. je wmUSER_3
    30. cmp edx,WM_COMMAND
    31. je wmCOMMAND
    32. xor eax,eax
    33. jmp exit0
    34. wmUSER_1:; Получить строку от первого приложения
    35. mov type0,CF_TEXT
    36. jmp @f
    37. wmUSER_2:mov type0,CF_DIB
    38. jmp @f
    39. wmUSER_3:mov type0,CF_WAVE
    40. @@: invoke GlobalAlloc,GMEM_FIXED,lParam
    41. mov buffer,rax
    42. mov ecx,offset lpszPipeName
    43. invoke CreateNamedPipe,,PIPE_ACCESS_INBOUND,PIPE_TYPE_BYTE,1,0,lParam,0,0
    44. mov hNamedPipe,rax
    45. invoke ConnectNamedPipe,eax,NULL
    46. lea r9d,cbRead
    47. and qword ptr[rsp+20h],0
    48. invoke ReadFile,hNamedPipe,buffer,lParam
    49. ;----------------------------------------------------
    50. cmp type0,CF_TEXT
    51. je TEXT
    52. cmp type0,CF_DIB
    53. je DIB
    54. WAVE: mov r8,buffer
    55.         add r8d,14h
    56.         lea ecx,hWaveOut
    57.         xor r9,r9
    58. mov [rsp+20h],r9
    59. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    60.         or edx,WAVE_MAPPER
    61.         invoke waveOutOpen
    62. ; Подготавливаем заголовок для вывода
    63. lea edx,lpwiocb
    64. mov edi,edx
    65. xor eax,eax
    66. mov ecx,(sizeof WAVEHDR)/8
    67. rep stosq
    68. mov rax,buffer
    69. mov ecx,eax
    70. add rax,2Ch
    71. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    72. mov eax,[rcx+4]
    73. sub eax,2Ch
    74. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    75. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    76. ; Запускаем проигрывание блока
    77. lea edx,lpwiocb
    78. mov rcx,hWaveOut
    79. mov r8d,sizeof WAVEHDR
    80. invoke waveOutWrite
    81. @@: test lpwiocb.dwFlags,WHDR_DONE
    82. jz @b
    83. lea edx,lpwiocb
    84. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    85. invoke waveOutClose,hWaveOut
    86. jmp @0
    87. ;------------------------------------------------------------
    88. TEXT: invoke  SetDlgItemText,hWnddlg,ID_TXT,buffer
    89. jmp @0
    90. ;----------------------------------------------------
    91. DIB: and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    92. mov qword ptr[rsp+20h],256
    93. mov qword ptr[rsp+28h],256
    94. invoke  CreateIconFromResourceEx,buffer,lParam,TRUE,30000h
    95. mov [rsp+20h],rax
    96. invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    97. ;-----------------------------------------------------------
    98. @0:     invoke GlobalFree,buffer
    99. invoke DisconnectNamedPipe,hNamedPipe
    100. invoke CloseHandle,hNamedPipe
    101. jmp wmBYE
    102. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    103. jne wmBYE
    104. wmCLOSE:;Перед завершением приложения закрываем дескриптор канала Mailslot
    105. invoke EndDialog,hWnddlg,0
    106. wmBYE:  mov eax,TRUE
    107. exit0: leave
    108. ret
    109. DialogProc endp
    110. type0 db ?
    111. lpszPipeName db "\\.\pipe\MyPipe",0;Имя создаваемого пайпа
    112. hNamedPipe dq ?;дескриптор пайпа
    113. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "Pipe Reciever"
    9. BEGIN
    10. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13. CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
     
  6. Mikl___

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

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

    03. Memory Mapped File

    Обмен данными между процессами через файлы, отображенных на память. Обладает высоким быстродействием, так как данные передаются между процессами непосредственно через виртуальную память.
    Отображение создается функцией CreateFileMapping.
    Фрагмент кода в котором создается отображение файла, а затем выполняется отображение этого файла в память:
    Код (C):
    1. hFileMapping = CreateFileMapping(hSrcFile, NULL,PAGE_READWRITE,0,dwFileSize,NULL);
    2. if(hFileMapping == NULL)
    3.   return;
    4. lpFileMap = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
    5. if(lpFileMap == 0)
    6.   return;
    В качестве первого параметра для функции CreateFileMapping передают дескриптор файла, открытого функцией CreateFile. Последний параметр указан как NULL, поэтому отображение не имеет имени.
    Если отображение используется для передачи данных между процессами, указывают имя. Пользуясь этим именем, другие процессы смогут открыть отображение функцией OpenFileMapping.
    дескриптора файла, передаваемого функции CreateFileMapping через первый параметр. Если создается отображение только для того чтобы обеспечить передачу данных между процессами, не нужно создавать файл на диске компьютера. В качестве дескриптора файла указывается значение 0FFFFFFFFh (-1), создается отображение непосредственно в виртуальной памяти без использования дополнительного файла.
    Код (C):
    1. CHAR lpFileShareName[] = "$MyVerySpecialFileShareName$";
    2. hFileMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0, 100,lpFileShareName);
    После того как создан объект-отображение, выполняется отображение файла в память при помощи функции MapViewOfFile. В случае успеха эта функция вернет указатель на отображенную область памяти.
    Первый процесс создал отображение. Второй процесс, который выполняет обмен данными с первым процессом, открывает это отображение по имени при помощи функции OpenFileMapping:
    Код (C):
    1. hFileMapping = OpenFileMapping (FILE_MAP_READ | FILE_MAP_WRITE, FALSE, lpFileShareName);
    Далее второе приложение выполняет отображение, вызывая функцию MapViewOfFile:
    Код (C):
    1. lpFileMap = MapViewOfFile(hFileMapping,FILE_MAP_READ| FILE_MAP_WRITE,0,0,0);
    Используя значением, полученное от функции MapViewOfFile, второе приложение получает указатель на отображенную область памяти. Эта область находится в тех же страницах виртуальной памяти, что и область, созданная первым процессом. Два процесса получили указатели на общие страницы памяти.
    Перед завершением работы процессы должны отменить отображение файла и освободить дескриптор созданного объекта-отображения:
    Код (C):
    1. UnmapViewOfFile(lpFileMap);
    2. CloseHandle(hFileMapping);
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. ID_SEND_ICO equ 102
    6. ID_SEND_WAV equ 103
    7. IDC_DIALOG equ 200
    8. IDC_ICON1 equ 500
    9. IDC_IMG1 equ 104
    10. .code
    11. WinMain proc dummy:qword
    12. mov r9d,256
    13. mov [rsp+20h],r9
    14. mov qword ptr [rsp+28],LR_DEFAULTCOLOR
    15. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    16. mov r9d,offset DialogProc
    17. mov qword ptr[rsp+20h],rax
    18. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    19. invoke RtlExitUserProcess,NULL
    20. WinMain endp
    21. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    22. size_of_buffer equ 96
    23. local buffer[size_of_buffer]:BYTE
    24. local FSize:dword
    25. local hResource:qword
    26. local pResource:qword
    27. local szReadWrite:qword
    28. local type0:qword
    29. mov hWnddlg,rcx
    30. mov lParam,r9
    31. cmp edx,WM_CLOSE
    32. je wmCLOSE
    33. cmp edx,WM_COMMAND
    34. je wmCOMMAND
    35. cmp edx,WM_INITDIALOG
    36. je wmINITDIALOG
    37. xor eax,eax
    38. jmp exit0
    39. wmINITDIALOG:;
    40.         invoke GetDlgItem,,IDC_IMG1
    41. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    42. jmp wmBYE
    43. wmSEND_TXT:mov type0,WM_USER+1
    44. lea r8d,buffer
    45. invoke  GetDlgItemText,,ID_TXT,,size_of_buffer;255
    46.         or      eax,eax
    47.         jz      wmBYE
    48.         inc     eax
    49. mov FSize,eax
    50. ;созддание файла
    51. sub esp,40h
    52. xor r8,r8
    53. mov qword ptr[rsp+20h],OPEN_ALWAYS
    54. mov [rsp+28h],r8
    55. mov [rsp+30h],r8
    56. mov ecx,offset szMapName0
    57. invoke CreateFile,,GENERIC_READ or GENERIC_WRITE,,0
    58. mov hFile,rax
    59. lea edx,buffer
    60. lea r9d,szReadWrite
    61. and qword ptr[rsp+20h],0
    62. invoke WriteFile,eax,,FSize
    63. invoke Func,hFile,0
    64. jmp @0
    65. wmSEND_ICO:sub esp,30h
    66. mov type0,WM_USER+2
    67. mov edx,p1
    68. invoke FindResource,0,,RT_ICON; find the resource
    69. mov hResource,rax
    70. invoke  SizeofResource,0,eax ; get its size
    71. mov     FSize,eax
    72. invoke LoadResource,0,hResource ; load the resource
    73. invoke LockResource,eax
    74. mov esi,eax
    75. ;созддание в памяти объекта "проекция файла" и
    76. ;отображение проекции файла на адресное пространство процесса
    77. invoke Func,INVALID_HANDLE_VALUE,FSize
    78. ;-----------------------------------------------------------------
    79. mov ecx,FSize
    80. mov edi,eax;rdi,pMapping
    81. rep movsb
    82. ;--------------------------------------------------
    83. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    84. mov qword ptr[rsp+20h],256
    85. mov qword ptr[rsp+28h],256
    86. mov edx,FSize
    87. invoke  CreateIconFromResourceEx,pMapping,,TRUE,30000h;270376,TRUE,30000h
    88. mov [rsp+20h],rax
    89. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    90. xor p1,11b
    91. jmp @0
    92. ;-------------------------------------------------------
    93. wmSEND_WAV:sub esp,40h
    94. mov type0,WM_USER+3
    95. mov ecx,offset wav_file
    96. xor r9d,r9d
    97. mov qword ptr[rsp+30h],r9
    98. mov qword ptr[rsp+28h],FILE_ATTRIBUTE_ARCHIVE
    99. mov qword ptr[rsp+20h],OPEN_EXISTING
    100. invoke CreateFile,,GENERIC_READ or GENERIC_WRITE,\
    101. FILE_SHARE_READ or FILE_SHARE_WRITE
    102.         mov hFile,rax
    103. invoke Func,rax,0
    104. @0:; Найти окно получателя
    105. mov edx,offset szWin
    106.         invoke  FindWindow,NULL
    107.         or      eax,eax
    108.         jz      wmBYE
    109. ; Отправить данные получателю
    110. mov qword ptr[rsp+20h],SMTO_ABORTIFHUNG
    111. mov qword ptr[rsp+28h],5000
    112. and qword ptr[rsp+30h],0
    113.         invoke  SendMessageTimeout,eax,type0,hWnddlg,0
    114. invoke UnmapViewOfFile,pMapping
    115. invoke CloseHandle,hMapping
    116. invoke CloseHandle,hFile
    117. cmp type0,WM_USER+1
    118. jnz     wmBYE
    119. mov ecx,offset szMapName0
    120. invoke DeleteFile
    121. jmp wmBYE
    122. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    123.         je      wmSEND_TXT
    124.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    125.         je      wmSEND_ICO
    126. cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    127.         je      wmSEND_WAV
    128. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    129.         jne     wmBYE
    130. wmCLOSE:invoke EndDialog,,0
    131. wmBYE:  mov eax,TRUE
    132. exit0: leave
    133. retn
    134. DialogProc endp
    135. ;----------------------------------------
    136. Func proc hFile:qword,FSize:qword
    137. mov FSize,rdx
    138. ;созддание в памяти объекта "проекция файла"
    139. movr qword ptr[rsp+28h],szMapName
    140. mov [rsp+20h],rdx
    141.         invoke CreateFileMapping,,0,PAGE_READWRITE,0
    142. mov hMapping,rax
    143. ;отображение проекции файла на адресное пространство процесса
    144. mov rax,FSize
    145. mov [rsp+20h],rax
    146. invoke MapViewOfFile,hMapping,FILE_MAP_ALL_ACCESS,0,0
    147. mov pMapping,rax
    148. leave
    149. ret
    150. Func endp
    151. ;---------------------------------------
    152. szWin db 'Memory-Mapped File Reciever',0
    153. wav_file db '..\Images\03.wav',0
    154. szMapName db "13-15=Mapping",0
    155. szMapName0 db "15.txt",0
    156. p1 dd 1
    157. hMapping dq ?
    158. pMapping dq ?
    159. hFile dq ?
    160. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_DIALOG 200
    7. #define IDC_ICON1 500
    8. #define IDC_IMG1 104
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "Memory-Mapped File Sender"
    15. BEGIN
    16.     CONTROL      "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON  "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. WM_CLIPBOARDUPDATE equ 31Dh
    4. IDC_DIALOG equ 200
    5. IMAGE_BASE equ 400000h
    6. ID_TXT equ 100
    7. ID_ICON equ 102
    8. IDC_ICON1 equ 500
    9. .code
    10. WinMain proc dummy:qword
    11. mov r9d,offset DialogProc
    12. and qword ptr[rsp+20h],0
    13.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    14.         invoke  RtlExitUserProcess,NULL
    15. WinMain endp
    16. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    17. local pMapping:qword
    18. local hMapping:qword
    19. local FSize:dword
    20. local lpwiocb:WAVEHDR
    21. local hWaveOut:qword
    22. mov hWnddlg,rcx
    23. mov lParam,r9
    24. cmp edx,WM_CLOSE
    25. je wmCLOSE
    26. cmp edx,WM_USER+3
    27. je wmUSER_3
    28. cmp edx,WM_USER+1
    29. je wmUSER_1
    30. cmp edx,WM_USER+2
    31. je wmUSER_2
    32. cmp edx,WM_COMMAND
    33. je wmCOMMAND
    34. xor eax,eax
    35. jmp exit0
    36. wmUSER_2:; Получить иконку от первого приложения
    37. mov type0,CF_DIB
    38. jmp @f
    39. wmUSER_1:; Получить строку от первого приложения
    40. mov type0,CF_TEXT
    41. jmp @f
    42. wmUSER_3:; Получить музыку от первого приложения
    43. mov type0,CF_WAVE
    44. jmp @f
    45. @@: mov r8d,offset lpszName
    46. invoke OpenFileMapping,FILE_MAP_READ,FALSE
    47. mov hMapping,rax
    48. xor r8,r8
    49. mov [rsp+20h],r8
    50. invoke MapViewOfFile,eax,FILE_MAP_READ,,0
    51. mov pMapping,rax
    52. ;-------------------------------------------
    53. cmp type0,CF_DIB
    54. je DIB
    55. cmp type0,CF_TEXT
    56. je TEXT
    57. WAVE: mov r8,pMapping
    58.         add r8d,14h
    59.         lea ecx,hWaveOut
    60.         xor r9,r9
    61. mov [rsp+20h],r9
    62. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    63.         or edx,WAVE_MAPPER
    64.         invoke waveOutOpen
    65. ; Подготавливаем заголовок для вывода
    66. lea edx,lpwiocb
    67. mov edi,edx
    68. xor eax,eax
    69.         mov ecx,(sizeof WAVEHDR)/8
    70. rep stosq
    71. mov rax,pMapping
    72. mov ecx,eax
    73. add rax,2Ch
    74. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    75. mov eax,[rcx+4]
    76. sub eax,2Ch
    77. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    78. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    79. ; Запускаем проигрывание блока
    80. lea edx,lpwiocb
    81. mov rcx,hWaveOut
    82. mov r8d,sizeof WAVEHDR
    83. invoke waveOutWrite
    84. @@: cmp lpwiocb.dwFlags,WHDR_DONE or WHDR_PREPARED
    85. jnz @b
    86. lea edx,lpwiocb
    87. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    88. invoke waveOutClose,hWaveOut
    89.         jmp @f;wmBYE
    90. ;--------------------------------------------------
    91. TEXT: invoke  SetDlgItemText,hWnddlg,ID_TXT,pMapping
    92.         jmp @f;wmBYE
    93. ;------------------------------------------------------
    94. DIB: and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    95. mov qword ptr[rsp+20h],256
    96. mov qword ptr[rsp+28h],256
    97. invoke  CreateIconFromResourceEx,pMapping,lParam,TRUE,30000h
    98. mov [rsp+20h],rax
    99. invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    100. @@: invoke UnmapViewOfFile,pMapping
    101.         invoke CloseHandle,hMapping
    102. jmp wmBYE
    103. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    104. jne wmBYE
    105. wmCLOSE:invoke EndDialog,,0
    106. wmBYE:  mov eax,TRUE
    107. exit0: leave
    108. ret
    109. DialogProc endp
    110. align 10h
    111. lpszName db "13-15=Mapping",0
    112. type0 db ?
    113. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "Memory-Mapped File Reciever"
    9. BEGIN
    10. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13. CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
     
  7. Mikl___

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

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

    07. Dynamic Data Exchange

    Механизм динамического обмена данными DDE (Dynamic Data Exchange), позволяет создать постоянно действующие каналы между несколькими одновременно работающими приложениями Windows. Каналы могут создаваться автоматически при запуске приложения или при необходимости и по явному запросу пользователя. После создания каналов, они будут работать без вмешательства пользователя.
    В Windows механизм DDE реализован через передачу сообщений с помощью функции SendMessage с использованием глобальных блоков памяти, доступных всем приложениям. При создании DDE-приложений программист вынужден вникать во все детали процесса создания канала связи, придерживаясь определенного в SDK протокола.
    Начиная с Windows 3.1 появилось расширение ― управляющая библиотека динамического обмена данными DDEML, выполненная как DLL.
    Библиотека DDEML упрощает DDE-приложения и избавляет программиста от учета деталей протокола обмена сообщениями.
    В Windows динамический обмен данных организуется с помощью библиотеки DDEML. Сетевые возможности Windows базируются на сетевом динамическом обмене данными Network DDE.
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. ID_SEND_ICO equ 102
    6. ID_SEND_WAV equ 103
    7. IDC_DIALOG equ 200
    8. IDC_ICON1 equ 500
    9. IDC_IMG1 equ 104
    10. WM_USER_INITIATE equ WM_USER + 1
    11. extern __imp_DdeGetData:qword
    12. .code
    13. WinMain proc dummy:qword
    14. mov r9d,256
    15. mov [rsp+20h],r9
    16. mov qword ptr [rsp+28],LR_DEFAULTCOLOR
    17. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    18. mov r9d,offset DialogProc
    19. mov qword ptr[rsp+20h],rax
    20. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    21. invoke RtlExitUserProcess,NULL
    22. WinMain endp
    23. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    24. local hFile:dword
    25. local cbWritten:dword
    26. local hResource:qword
    27. local pResource:qword
    28. mov hWnddlg,rcx
    29. mov lParam,r9
    30. cmp edx,WM_CLOSE
    31. je wmCLOSE
    32. cmp edx,WM_COMMAND
    33. je wmCOMMAND
    34. cmp edx,WM_INITDIALOG
    35. je wmINITDIALOG
    36. cmp edx,WM_USER_INITIATE
    37. je wmUSER_INITIATE
    38. xor eax,eax
    39. jmp exit0
    40. wmUSER_INITIATE:
    41. mov edx,offset szService
    42. invoke DdeCreateStringHandle,idInst,,CP_WINANSI
    43. mov hszService,rax
    44. mov edx,offset szTopic
    45. invoke DdeCreateStringHandle,idInst,,CP_WINANSI
    46. mov hszTopic,rax
    47. mov edx,offset szItem
    48. invoke DdeCreateStringHandle,idInst,,CP_WINANSI
    49. mov hszItem,rax
    50. ; Регистрируем сервис
    51. invoke DdeNameService,idInst,hszService,NULL,DNS_REGISTER
    52. jmp wmBYE
    53. wmINITDIALOG:
    54. ; mov hwnd,rcx
    55.         invoke GetDlgItem,,IDC_IMG1
    56. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    57. ; Выполняем инициализацию
    58. mov ecx,offset idInst
    59. mov edx,offset DDEServerCallback
    60. invoke DdeInitialize,,,APPCLASS_STANDARD,0
    61. or eax,eax
    62. jz @f
    63. mov edx,offset Error0
    64. mov edx,offset szAppName
    65. invoke MessageBox,hWnddlg,,,MB_ICONEXCLAMATION or MB_OK
    66. jmp wmCLOSE
    67. ; После успешной инициализации получаем дескрипторы строк для сервиса, раздела и элемента данных
    68. @@:     invoke SendMessage,hWnddlg,WM_USER_INITIATE,0,0
    69. mov eax,TRUE
    70. jmp wmBYE
    71. wmSEND_ICO:mov edx,p1
    72. mov type0,(WM_USER+3)
    73. invoke FindResource,0,,RT_ICON; find the resource
    74. mov hResource,rax
    75. invoke  SizeofResource,0,eax ; get its size
    76. mov FSize,rax
    77. invoke LoadResource,0,hResource ; load the resource
    78. invoke LockResource,eax;pResource
    79. mov p,rax
    80.         mov ecx,eax
    81. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    82. mov qword ptr[rsp+20h],256
    83. mov qword ptr[rsp+28h],256
    84. invoke  CreateIconFromResourceEx,,FSize,TRUE,30000h;270376,TRUE,30000h
    85. mov [rsp+20h],rax
    86. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    87. xor p1,11b
    88. jmp @f
    89. wmSEND_WAV:mov ecx,offset wav_file
    90. xor r9d,r9d
    91. mov type0,(WM_USER+4)
    92. mov qword ptr[rsp+30h],r9
    93. mov qword ptr[rsp+28h],FILE_ATTRIBUTE_ARCHIVE
    94. mov qword ptr[rsp+20h],OPEN_EXISTING
    95. invoke CreateFile,,GENERIC_READ or GENERIC_WRITE,\
    96. FILE_SHARE_READ or FILE_SHARE_WRITE
    97.         mov hFile,eax
    98.         invoke GetFileSize,eax,0
    99. mov FSize,rax
    100. invoke GlobalAlloc,GPTR,eax
    101.         mov p,rax
    102. lea r9d,cbWritten
    103. and qword ptr[rsp+20h],0
    104.         invoke ReadFile,hFile,eax,FSize
    105.         invoke CloseHandle,hFile
    106. jmp @f
    107. wmSEND_TXT:invoke GlobalAlloc,GPTR,256
    108.         mov p,rax
    109. mov type0,(WM_USER+2)
    110. invoke GetDlgItemText,hWnddlg,ID_TXT,eax,256
    111. inc eax
    112. mov FSize,rax
    113. ; Найти окно получателя
    114. @@: mov edx,offset szWin
    115.         invoke  FindWindow,NULL
    116.         or      eax,eax
    117.         jz      wmBYE
    118.         ; Отправить данные получателю
    119.         invoke  PostMessage,eax,type0,hWnddlg,FSize
    120. jmp wmBYE
    121. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    122.         je      wmSEND_WAV
    123.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    124.         je      wmSEND_TXT
    125.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    126.         je      wmSEND_ICO
    127. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    128.         jne     wmBYE
    129. wmCLOSE:;Завершение работы канала связи
    130. cmp hConvApp,NULL
    131. jnz @f
    132. invoke DdeDisconnect,hConvApp
    133. @@:; Сервис больше не доступен
    134. invoke DdeNameService,idInst,hszService,NULL,DNS_UNREGISTER
    135. ; Освобождение дескрипторов строк
    136. invoke DdeFreeStringHandle,idInst, hszService
    137. invoke DdeFreeStringHandle,idInst, hszTopic
    138. invoke DdeFreeStringHandle,idInst, hszItem
    139. invoke EndDialog,hWnddlg,0
    140. wmBYE:  mov eax,TRUE
    141. exit0: leave
    142. retn
    143. DialogProc endp
    144. DDEServerCallback proc wType:qword,wFmt:qword,hConv:qword,hsz1:qword,hsz2:qword,hData:qword,dwData1:qword,dwData2:qword
    145. mov hConv,r8
    146. mov hsz1,r9
    147. cmp ecx,XTYP_CONNECT
    148. je      xtypCONNECT
    149. cmp ecx,XTYP_REQUEST
    150. je xtypREQUEST
    151. cmp ecx,XTYP_EXECUTE
    152. je xtypEXECUTE
    153. cmp ecx,XTYP_ERROR
    154. je xtypERROR
    155. cmp ecx,XTYP_DISCONNECT
    156. je xtypDISCONNECT
    157. cmp ecx,XTYP_CONNECT_CONFIRM
    158. je xtypCONNECT_CONFIRM
    159. xor eax,eax
    160. jmp wmBYE
    161. xtypCONNECT:;Создание канала передачи данных
    162. ; Если сервис поддерживается, возвращаем признак успешного создания канала
    163. mov rax,hsz2
    164. cmp rax,hszService
    165. jne xtypEXECUTE
    166. mov eax,TRUE
    167. jmp wmBYE
    168. xtypDISCONNECT:; Завершение работы канала
    169. and hConvApp,NULL
    170. xtypERROR:; Ошибка
    171. ; Запрос на выполнение команды, отрабатывается вхолостую
    172. xtypEXECUTE: xor eax,eax
    173. jmp wmBYE
    174. xtypREQUEST:; Создаем дескриптор данных
    175.         cmp edx,CF_TEXT
    176. jz @f
    177. cmp edx,CF_BITMAP
    178. jz @f
    179. cmp edx,CF_WAVE
    180. jnz wmBYE
    181. @@: xor r9d,r9d
    182. mov rax,hszItem
    183. mov [rsp+20h],rax
    184. mov [rsp+28h],rdx
    185. mov [rsp+30h],r9
    186. invoke DdeCreateDataHandle,idInst,p,FSize
    187. ; В случае успеха возвращаем созданный дескриптор или ноль
    188. mov hData,rax
    189. jmp wmBYE
    190. ;  Подтверждение создания канала
    191. xtypCONNECT_CONFIRM:
    192. mov hConvApp,r8
    193. @@: xor eax,eax
    194. wmBYE: leave
    195. retn
    196. DDEServerCallback endp
    197. ;---------------------------------------
    198. szWin db 'DDE Reciever',0
    199. wav_file db '..\Images\03.wav',0
    200. Error0 db "Could not initialize server!",0
    201. ; дескриптор приложения, полученный после регистрации в библиотеке DDEML
    202. idInst dq 0
    203. hszService dq 0
    204. hszTopic dq 0
    205. hszItem dq 0
    206. ; дескриптор канала
    207. hConvApp dq 0
    208. ; Буфер для приема данных
    209. p dq ?
    210. szService db "07s",0
    211. szTopic db "Brer Rabbit",0
    212. szItem db "DDEData",0
    213. szAppName db "DDEML Server",0
    214. ;hwnd dq ?
    215. FSize dq ?
    216. type0 dq ?
    217. p1 dd 1
    218. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_IMG1 104
    7. #define IDC_DIALOG 200
    8. #define IDC_ICON1 500
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "DDE Sender"
    15. BEGIN
    16.     CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. IDC_DIALOG equ 200
    4. ID_TXT equ 100
    5. ID_ICON equ 102
    6. IDC_ICON1 equ 500
    7. TXT equ 10
    8. ICO equ 11
    9. WAV equ 12
    10. WM_USER_INITIATE equ WM_USER + 1
    11. extern __imp_DdeGetData:qword
    12. .code
    13. WinMain proc dummy:qword
    14. mov r9d,offset DialogProc
    15. and qword ptr[rsp+20h],0
    16.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    17.         invoke  RtlExitUserProcess,NULL
    18. WinMain endp
    19. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    20. local buffer:qword
    21. local lpwiocb:WAVEHDR
    22. local hWaveOut:qword
    23. local dwResult:dword
    24. mov hWnddlg,rcx
    25. mov lParam,r9
    26. cmp edx,WM_CLOSE
    27. je wmCLOSE
    28. cmp edx,WM_USER+4
    29. je MUSIC_FROM_SERVER
    30.         cmp edx,WM_USER+2
    31. je MSG_FROM_SERVER
    32.         cmp edx,WM_USER+3
    33. je ICON_FROM_SERVER
    34. cmp edx,WM_COMMAND
    35. je wmCOMMAND
    36. cmp edx,WM_USER_INITIATE
    37. je wmUSER_INITIATE
    38. cmp edx,WM_INITDIALOG
    39. je wmINITDIALOG
    40. xor eax,eax
    41. jmp exit0
    42. wmINITDIALOG:; Выполняем инициализацию
    43. xor esi,esi
    44. mov ecx,offset idInst
    45. mov edx,offset DDEServerCallback
    46. invoke DdeInitialize,,,APPCMD_CLIENTONLY or APPCLASS_STANDARD,0
    47. or eax,eax
    48. jnz Error
    49. ; После успешной инициализации получаем дескрипторы строк для сервиса, раздела и элемента данных
    50. @@:     invoke SendMessage,hWnddlg,WM_USER_INITIATE,0,0
    51. mov eax,TRUE
    52. jmp wmBYE
    53. ICON_FROM_SERVER:mov wFmt,CF_BITMAP
    54. jmp @f
    55. MSG_FROM_SERVER:mov wFmt,CF_TEXT
    56. jmp @f
    57. MUSIC_FROM_SERVER:mov wFmt,CF_WAVE
    58. @@: invoke GlobalAlloc,GMEM_FIXED,lParam
    59. mov buffer,rax
    60. ; Запускаем транзакцию чтения данных
    61. mov rax,hConv
    62. mov esi,4
    63. or eax,eax
    64. jz Error
    65. mov r8,rax
    66. mov rax,wFmt
    67. mov [rsp+20h],rax
    68. mov qword ptr[rsp+28h],XTYP_REQUEST
    69. mov qword ptr[rsp+30h],TIMEOUT_ASYNC;5000
    70. lea eax,dwResult
    71. mov [rsp+38h],rax
    72. invoke DdeClientTransaction,0,0,,hszItem
    73. ; Получаем строку от сервера
    74. mov esi,5
    75. or eax,eax;if(hData != NULL)
    76. jz Error
    77. invoke __imp_DdeGetData,eax,buffer,lParam,0
    78. mov esi,6
    79. or eax,eax
    80. jz Error
    81. cmp wFmt,CF_BITMAP
    82. jnz @f
    83. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    84. mov qword ptr[rsp+20h],256
    85. mov qword ptr[rsp+28h],256
    86. invoke  CreateIconFromResourceEx,buffer,eax,TRUE,30000h
    87. mov [rsp+20h],rax
    88. invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    89. jmp @0
    90. @@:     cmp wFmt,CF_TEXT
    91. jnz @f
    92. invoke  SetDlgItemText,hWnddlg,ID_TXT,buffer
    93. jmp @0
    94. ;-----------------------------------------------------------
    95. @@: mov r8,buffer
    96.         add r8d,14h
    97.         lea ecx,hWaveOut
    98.         xor r9,r9
    99. mov [rsp+20h],r9
    100. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    101.         or edx,WAVE_MAPPER
    102.         invoke waveOutOpen
    103. ; Подготавливаем заголовок для вывода
    104. lea edx,lpwiocb
    105. mov edi,edx
    106. xor eax,eax
    107. mov ecx,(sizeof WAVEHDR)/8
    108. rep stosq
    109. mov rax,buffer
    110. mov ecx,eax
    111. add rax,2Ch
    112. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    113. mov eax,[rcx+4]
    114. sub eax,2Ch
    115. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    116. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    117. ; Запускаем проигрывание блока
    118. lea edx,lpwiocb
    119. mov rcx,hWaveOut
    120. mov r8d,sizeof WAVEHDR
    121. invoke waveOutWrite
    122. @@: test lpwiocb.dwFlags,WHDR_DONE
    123. jz @b
    124. lea edx,lpwiocb
    125. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    126. invoke waveOutClose,hWaveOut
    127. ;------------------------------------------------------------
    128. @0: invoke GlobalFree,buffer
    129. jmp wmBYE
    130. wmUSER_INITIATE:; Инициализация DDEML и создание канала связи
    131. invoke DDEClientOpen
    132. or eax,eax
    133. jnz wmBYE
    134. mov edx,offset Error1
    135. mov r8d,offset szAppName
    136. invoke MessageBox,hWnddlg,,,MB_ICONEXCLAMATION or MB_YESNO
    137. cmp eax,IDNO
    138. jz      wmBYE
    139. mov ecx,offset szService
    140. invoke WinExec,,SW_SHOW
    141. cmp eax,32
    142. mov esi,2
    143. jb Error
    144. ; После удачного запуска повторяем попытку инициализации DDEML и создания канала связи
    145. invoke DDEClientOpen
    146. jmp wmBYE
    147. Error: mov r8d,offset szAppName
    148. invoke MessageBox,hWnddlg,ErrorMsg[rsi*8],,MB_ICONEXCLAMATION
    149. jmp aExit
    150. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    151. jne wmBYE
    152. wmCLOSE:; Завершаем работу с DDEML. Закрываем канал связи
    153. cmp hConv,0
    154. jz @f
    155. invoke DdeDisconnect,hConv
    156. @@:; Освобождаем дескрипторы строк
    157. invoke DdeFreeStringHandle,idInst,hszService
    158. invoke DdeFreeStringHandle,idInst,hszTopic
    159. invoke DdeFreeStringHandle,idInst,hszItem
    160. aExit: invoke EndDialog,hWnddlg,0
    161. wmBYE:  mov eax,TRUE
    162. exit0: leave
    163. ret
    164. DialogProc endp
    165. DDEServerCallback proc wType:qword,wFmt:qword,hConv:qword,hsz1:qword,hsz2:qword,hData:qword,dwData1:qword,dwData2:qword
    166. xor eax,eax
    167. wmBYE: leave
    168. retn
    169. DDEServerCallback endp
    170. DDEClientOpen proc
    171. local dummy:qword
    172. ; При успешной инициализации создаем дескрипторы строк для сервиса,
    173. ; раздела и элемента данных
    174. mov edx,offset szService
    175. invoke DdeCreateStringHandle,idInst,,CP_WINANSI
    176. mov hszService,rax
    177. mov edx,offset szTopic
    178. invoke DdeCreateStringHandle,idInst,,CP_WINANSI
    179. mov hszTopic,rax
    180. mov edx,offset szItem
    181. invoke DdeCreateStringHandle,idInst,,CP_WINANSI
    182. mov hszItem,rax
    183. ; Устанавливаем канал связи
    184. invoke DdeConnect,idInst, hszService, hszTopic,0
    185. mov hConv,rax
    186. ; Возвращаем дескриптор созданного канала связи
    187. leave
    188. ret
    189. DDEClientOpen endp
    190. ;-----------------------------------
    191. szAppName db "DDEML Client",0
    192. szService db "07s",0
    193. szTopic db "Brer Rabbit",0
    194. szItem db "DDEData",0
    195. ErrorMsg dq Error0,Error1,Error2,Error3,Error4,Error5,Error6
    196. Error0 db "Could not initialize client!",0
    197. Error1 db "Сервер не запущен",10,"Запустить?",0
    198. Error2 db "Невозможно запустить сервер",0
    199. Error3 db "Сервер не отвечает",0
    200. Error4 db "hConv = 0",0
    201. Error5 db "hData = 0",0
    202. Error6 db "lParam = 0",0
    203. ; дескриптор приложения для DDEML
    204. hConv dq 0
    205. idInst dq 0
    206. hszService dq ?
    207. hszTopic dq ?
    208. hszItem dq ?
    209. wFmt dq ?
    210. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "DDE Reciever"
    9. BEGIN
    10.         CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13. CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
     
  8. Mikl___

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

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

    05. Mailslot

    Mailslot-каналы позволяют выполнять одностороннюю передачу данных от одного или нескольких клиентов к одному или нескольким серверам. Особенность mailslot-каналов в том, что они позволяют передавать данные в широковещательном режиме.
    На компьютере или в сети могут работать несколько серверных процессов, способных получать сообщения через mailslot-каналы. При этом один клиентский процесс может посылать сообщения сразу всем этим серверным процессам.
    Создание mailslot-канала
    Mailslot-канал создается серверным процессом с помощью функции CreateMailslot. После создания серверный процесс получает дескриптор mailslot-канала. Используя этот дескриптор, сервер может читать сообщения, посылаемые в канал клиентскими процессами. Сервер не может выполнять над mailslot-каналом операцию записи, так как этот канал предназначен только для односторонней передачи данных ― от клиента к серверу.
    Прототип функции CreateMailslot:
    Код (C):
    1. HANDLE CreateMailslot(
    2.   LPCTSTR lpName,          // адрес имени канала Mailslot
    3.   DWORD   nMaxMsgSize,     // максимальный размер сообщения
    4.   DWORD   lReadTimeout,    // время ожидания для чтения
    5.   LPSECURITY_ATTRIBUTES lpSecurityAttributes); // адрес структуры защиты
    Через параметр lpName передают функции CreateMailslot адрес строки символов с именем mailslot-канала. Имя имеет следующий вид:
    Код (C):
    1. \\.\mailslot\[Путь]Имя_Канала
    В этом имени путь необязательная компонента. Но можно указать его аналогично тому, как это делается для файлов. Имя mailslot-канала задается аналогично имени pipe-канала.
    Параметр nMaxMsgSize ― максимальный размер сообщений, передаваемых через mailslot-канал. Можно указать нулевое значение, при этом размер сообщений не будет ограничен. Есть одно исключение ― размер широковещательных сообщений, передаваемых всем рабочим станциям и серверам домена не должен превышать 400 байт.
    С помощью параметра lReadTimeout серверное приложение задает время ожидания для операции чтения в миллисекундах, по истечении которого функция чтения вернет код ошибки. Если в этом параметре указать значение MAILSLOT_WAIT_FOREVER, ожидание будет бесконечным.
    Параметр lpSecurityAttributes задает адрес структуры защиты, который можно указать как NULL.
    При ошибке функцией CreateMailslot возвращается значение INVALID_HANDLE_VALUE. Код ошибки можно определить при помощи функции GetLastError.
    Пример использования функции CreateMailslot в серверном приложении:
    Код (C):
    1. LPSTR lpszMailslotName = "\\\\.\\mailslot\\$MailslotName$";
    2. hMailslot = CreateMailslot(lpszMailslotName, 0, MAILSLOT_WAIT_FOREVER, NULL);
    В примере задан максимальный размер сообщения, поэтому на эту величину нет ограничений (кроме ограничения в 400 байт для сообщений, передаваемых всем компьютерам домена в широковещательном режиме).
    Время ожидания указано как MAILSLOT_WAIT_FOREVER, поэтому функции, работающие с данным mailslot-каналом , будут работать в блокирующем режиме.
    Открытие mailslot-канала
    Сперва клиентский процесс должен открыть mailslot-канал. Для этого используют функцию CreateFile
    Код (C):
    1. LPSTR lpszMailslotName = "\\\\.\\mailslot\\$MailslotName$";
    2. hMailslot = CreateFile( lpszMailslotName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    Здесь в качестве первого параметра функции CreateFile передается имя mailslot-канала. Вы можете открыть mailslot-канал, созданный на другой рабочей станции в сети. Для этого строка имени канала, передаваемая функции CreateFile, должна иметь следующий вид:
    Код (C):
    1.  \\Имя_Рабочей_Станции\mailslot\[Путь]Имя_Канала
    Можно открыть канал для передачи сообщений всем рабочим станциям заданного домена. Для этого необходимо задать имя по следующему образцу:
    Код (C):
    1. \\Имя_Домена\mailslot\[Путь]Имя_Канала
    Для передачи сообщений одновременно всем рабочим станциям сети первичного домена имя задается следующим образом
    Код (C):
    1. \\*\mailslot\[Путь]Имя_Канала
    В качестве второго параметра функции CreateFile используют константу GENERIC_WRITE. Эта константа определяет, что над открываемым каналом будет выполняться операция записи. Клиентский процесс может только посылать сообщения в mailslot-канал, но не читать их оттуда. Чтение сообщений из mailslot-канала ― задача для серверного процесса.
    Третий параметр FILE_SHARE_READ, так как сервер может читать сообщения, посылаемые одновременно несколькими клиентскими процессами.
    Константа OPEN_EXISTING используется потому, что функция CreateFile открывает существующий канал, а не создает новый.
    Запись сообщений в канал Mailslot
    Запись сообщений в mailslot-канал выполняет клиентский процесс, вызывая для этого функцию WriteFile.
    Код (C):
    1. HANDLE hMailslot;
    2. char   szBuf[512];
    3. DWORD  cbWritten;
    4. WriteFile(hMailslot, szBuf, strlen(szBuf) + 1,  &cbWritten, NULL);
    В качестве первого параметра этой функции необходимо передать дескриптор mailslot-канала, полученный от функции CreateFile.
    Второй параметр определяет адрес буфера с сообщением, третий ― размер сообщения. Если сообщение передается в виде текстовой строки, тогда закрыть строку нужно нулем, для определения длины сообщения можно воспользоваться функцией strlen.
    Чтение сообщений из канала Mailslot
    Серверный процесс может читать сообщения из созданного им mailslot-канала при помощи функции ReadFile
    Код (C):
    1. HANDLE hMailslot;
    2. char   szBuf[512];
    3. DWORD  cbRead;
    4. ReadFile(hMailslot, szBuf, 512, &cbRead, NULL);
    Через первый параметр функции ReadFile передается дескриптор созданного mailslot-канала, полученный от функции CreateMailslot. Второй и третий параметры задают, адрес буфера сообщения и его размер.
    Перед выполнением операции чтения следует проверить состояние mailslot-канала. Если в mailslot-канале нет сообщений, то функцию ReadFile вызывать не следует. Для проверки состояния канала воспользуйтесь функцией GetMailslotInfo.
    Определение состояния канала Mailslot
    Серверный процесс может определить текущее состояние mailslot-канала по его дескриптору с помощью функции GetMailslotInfo
    Код (C):
    1. BOOL GetMailslotInfo(
    2.   HANDLE  hMailslot,        // дескриптор канала Mailslot
    3.   LPDWORD lpMaxMessageSize, // адрес максимального размера сообщения
    4.   LPDWORD lpNextSize,    // адрес размера следующего сообщения
    5.   LPDWORD lpMessageCount,   // адрес количества сообщений
    6.   LPDWORD lpReadTimeout);   // адрес времени ожидания
    Через параметр hMailslot передается дескриптор mailslot-канала , состояние которого необходимо определить.
    Остальные параметры ― указатели на переменные типа DWORD, в которые будут записаны параметры состояния mailslot-канала.
    В переменную, адрес которой передается через параметр lpMaxMessageSize, после возвращения из функции GetMailslotInfo будет записан максимальный размер сообщения. Это значение можно использовать для динамического получения буфера памяти, в который это сообщение будет прочитано функцией ReadFile.
    В переменную, адрес которой указан через параметр lpNextSize, записывается размер следующего сообщения, если оно есть в канале. Если в канале больше нет сообщений, в эту переменную будет записана константа MAILSLOT_NO_MESSAGE.
    С помощью параметра lpMessageCount можно определить количество сообщений, записанных в канал клиентскими процессами. Если это количество равно нулю ― не следует вызывать функцию ReadFile для чтения несуществующего сообщения.
    В переменную, адрес которой задается в параметре lpReadTimeout, записывается текущее время ожидания, установленное для канала (в миллисекундах).
    Если вся информация, которую можно получить с помощью функции GetMailslotInfo не нужна, некоторые из ее параметров (первого) можно указать как NULL.
    В случае успешного завершения функция GetMailslotInfo возвращает значение TRUE, а при ошибке ― FALSE. Код ошибки можно получить, вызвав функцию GetLastError.
    Пример использования функции GetMailslotInfo:
    Код (C):
    1. BOOL fReturnCode;
    2. DWORD  cbMessages;
    3. DWORD  cbMsgNumber;
    4. fReturnCode = GetMailslotInfo(hMailslot, NULL, &cbMessages, &cbMsgNumber, NULL);
    Изменение состояния канала Mailslot
    С помощью функции SetMailslotInfo серверный процесс может изменить время ожидания для mailslot-канала уже после его создания.
    Прототип функции SetMailslotInfo
    Код (C):
    1. BOOL SetMailslotInfo(
    2.   HANDLE hMailslot,      // дескриптор канала Mailslot
    3.   DWORD  dwReadTimeout); // время ожидания
    Через параметр hMailslot функции SetMailslotInfo передается дескриптор mailslot-канала, для которого нужно изменить время ожидания.
    Новое значение времени ожидания в миллисекундах задается через параметр dwReadTimeout. Можно указать здесь значение 0 или MAILSLOT_WAIT_FOREVER. Если dwReadTimeout=0 функции, работающие с каналом, вернут управление немедленно, dwReadTimeout=MAILSLOT_WAIT_FOREVER ― будут находиться в состоянии ожидания до тех пор, пока не завершится выполняемая операция.
    Текст приложения-сервера
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. WM_CLIPBOARDUPDATE equ 31Dh
    4. ID_TXT equ 100
    5. ID_SEND_TXT equ 101
    6. ID_SEND_ICO equ 102
    7. ID_SEND_WAV equ 103
    8. IDC_DIALOG equ 200
    9. IDC_ICON1 equ 500
    10. IDC_IMG1 equ 104
    11. .code
    12. WinMain proc dummy:qword
    13. mov r9d,256
    14. mov [rsp+20h],r9
    15. mov qword ptr [rsp+28],LR_DEFAULTCOLOR
    16. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    17. mov r9d,offset DialogProc
    18. mov qword ptr[rsp+20h],rax
    19. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    20. invoke RtlExitUserProcess,NULL
    21. WinMain endp
    22. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    23. local cbWritten:dword;Количество байт, переданных через канал
    24. local FSize:dword;
    25. local p:qword
    26. local hMailslot:qword; дескриптор канала Mailslot
    27. local hResource:qword
    28. local hFile:dword
    29. local szReadWrite:qword ;number of bytes actually read or write
    30. local lpwiocb:WAVEHDR
    31. local hWaveOut:qword
    32. local type0:qword
    33. mov hWnddlg,rcx
    34. mov lParam,r9
    35. cmp edx,WM_CLOSE
    36. je wmCLOSE
    37. cmp edx,WM_COMMAND
    38. je wmCOMMAND
    39. cmp edx,WM_INITDIALOG
    40. je wmINITDIALOG
    41. xor eax,eax
    42. jmp exit0
    43. wmINITDIALOG:;
    44.         invoke GetDlgItem,,IDC_IMG1
    45. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    46. jmp wmBYE
    47. wmSEND_TXT:invoke GlobalAlloc,GPTR,256
    48.         mov p,rax;Буфер для передачи данных через канал
    49. invoke  GetDlgItemText,hWnddlg,ID_TXT,eax,256
    50.         or      eax,eax
    51.         jz      wmBYE
    52.         inc     eax
    53. mov FSize,eax
    54. mov type0,WM_USER+1
    55. jmp @f
    56. wmSEND_ICO:mov edx,p1
    57. invoke FindResource,0,,RT_ICON; find the resource
    58. mov hResource,rax
    59. invoke  SizeofResource,0,eax ; get its size
    60. mov FSize,eax
    61. invoke LoadResource,0,hResource ; load the resource
    62. invoke LockResource,eax;pResource
    63.   mov p,rax
    64. ;-------------------------------------------------
    65. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    66. mov qword ptr[rsp+20h],256
    67. mov qword ptr[rsp+28h],256
    68. mov edx,FSize
    69. invoke  CreateIconFromResourceEx,p,,TRUE,30000h;270376,TRUE,30000h
    70. mov [rsp+20h],rax
    71. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    72. xor p1,11b
    73. mov type0,WM_USER+2
    74. jmp @f
    75. wmSEND_WAV:sub esp,40h
    76. mov ecx,offset wav_file
    77. xor r9d,r9d
    78. mov qword ptr[rsp+30h],r9
    79. mov qword ptr[rsp+28h],FILE_ATTRIBUTE_ARCHIVE
    80. mov qword ptr[rsp+20h],OPEN_EXISTING
    81. invoke CreateFile,,GENERIC_READ or GENERIC_WRITE,\
    82. FILE_SHARE_READ or FILE_SHARE_WRITE
    83.         mov hFile,eax
    84.         invoke GetFileSize,eax,0
    85. mov FSize,eax
    86. invoke GlobalAlloc,GPTR,eax
    87.         mov p,rax
    88. mov type0,WM_USER+3
    89. lea r9d,cbWritten
    90. and qword ptr[rsp+20h],0
    91.         invoke ReadFile,hFile,eax,FSize
    92.         invoke CloseHandle,hFile
    93. @@:; Создаем канал с процессом MSLOTS
    94. mov ecx,offset szMailslotName
    95. xor r9d,r9d
    96. mov qword ptr[rsp+20h],OPEN_EXISTING
    97. mov [rsp+28h],r9
    98. mov [rsp+30h],r9
    99. invoke CreateFile,,GENERIC_WRITE,FILE_SHARE_READ
    100. mov hMailslot,rax
    101. lea r9d,cbWritten
    102. and qword ptr[rsp+20h],0
    103.         invoke WriteFile,hMailslot,p,FSize
    104. ; Найти окно получателя
    105. mov edx,offset szWin
    106.         invoke  FindWindow,NULL
    107.         or      eax,eax
    108.         jz      wmBYE
    109. ; Отправить данные получателю
    110. invoke PostMessage,eax,type0,hWnddlg,FSize
    111. ;Закрываем дескриптор канала
    112. invoke CloseHandle,hMailslot
    113. jmp wmBYE
    114. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    115.         je      wmSEND_TXT
    116.         cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    117.         je      wmSEND_ICO
    118. cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    119.         je      wmSEND_WAV
    120. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    121.         jne     wmBYE
    122. wmCLOSE:invoke EndDialog,,0
    123. wmBYE:  mov eax,TRUE
    124. exit0: leave
    125. retn
    126. DialogProc endp
    127. ;---------------------------------------
    128. szWin db 'Mailslot Reciever',0
    129. szMailslotName db "\\.\mailslot\brer_Rabbit",0; Имя создаваемого канала
    130. wav_file db '..\Images\03.wav',0
    131. p1 dd 1
    132. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_DIALOG 200
    7. #define IDC_ICON1 500
    8. #define IDC_IMG1 104
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "Mailslot Sender"
    15. BEGIN
    16.     CONTROL      "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Напишите что-нибудь и нажмите 'Отправить текст'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Отправить текст",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Отправить ICO",ID_SEND_ICO,  149,45,60,15
    21.     PUSHBUTTON  "Отправить WAV",ID_SEND_WAV,  149,65,60,15
    22.     PUSHBUTTON "Выход", IDCANCEL,            149,85,60,15
    23. END
    Текст приложения-клиента
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. WM_CLIPBOARDUPDATE equ 31Dh
    4. IDC_DIALOG equ 200
    5. ID_TXT equ 100
    6. ID_ICON equ 102
    7. IDC_ICON1 equ 500
    8. TXT equ 10
    9. ICO equ 11
    10. WAV equ 12
    11. .code
    12. WinMain proc dummy:qword
    13. mov r9d,offset DialogProc
    14. and qword ptr[rsp+20h],0
    15.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    16.         invoke  RtlExitUserProcess,NULL
    17. WinMain endp
    18. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    19. local cbRead:DWORD;Количество байт данных, принятых через канал
    20. local cbMessages:DWORD;Размер сообщения в байтах
    21. local cbMsgNumber:DWORD;Количество сообщений в канале Mailslot
    22. local buffer:QWORD
    23. local lpwiocb:WAVEHDR
    24. local hWaveOut:qword
    25. mov hWnddlg,rcx
    26. mov lParam,r9
    27. cmp edx,WM_CLOSE
    28. je wmCLOSE
    29. cmp edx,WM_INITDIALOG
    30. je wmINITDIALOG
    31. cmp edx,WM_USER+1
    32. je wmUSER_1
    33. cmp edx,WM_USER+2
    34. je wmUSER_2
    35. cmp edx,WM_USER+3
    36. je wmUSER_3
    37. cmp edx,WM_COMMAND
    38.      je wmCOMMAND
    39.      xor eax,eax
    40.      jmp exit0
    41. wmUSER_1:mov type0,CF_TEXT
    42.      jmp @f
    43.      wmUSER_2:mov type0,CF_DIB
    44.      jmp @f
    45. wmUSER_3:mov type0,CF_WAVE
    46. ; Определяем состояние канала Mailslot
    47. @@: lea r8d,cbMessages
    48.      lea r9d,cbMsgNumber
    49.      xor edx,edx
    50.      mov [rsp+20h],rdx
    51.      invoke GetMailslotInfo,hMailslot
    52. ; Выполняем задержку на  500 миллисекунд
    53.      invoke Sleep,500
    54. ; Если в канале есть Mailslot сообщения, читаем первое из них и выводим на экран
    55.      cmp cbMsgNumber,0
    56.      jz wmBYE
    57.      invoke GlobalAlloc,GMEM_FIXED,lParam
    58.      mov buffer,rax
    59.      mov edx,eax
    60.      lea r9d,cbRead
    61.      and qword ptr[rsp+20h],0
    62.      invoke ReadFile,hMailslot,,lParam
    63.      cmp type0,CF_TEXT
    64.      je TEXT
    65.         cmp type0,CF_DIB
    66.      je DIB
    67. WAVE: mov r8,buffer
    68.         add r8d,14h
    69.         lea ecx,hWaveOut
    70.         xor r9,r9
    71.      mov [rsp+20h],r9
    72.      mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    73.         or edx,WAVE_MAPPER
    74.         invoke waveOutOpen
    75. ; Подготавливаем заголовок для вывода
    76.      lea edx,lpwiocb
    77.      mov edi,edx
    78.      xor eax,eax
    79.      mov ecx,(sizeof WAVEHDR)/8
    80.      rep stosq
    81.      mov rax,buffer
    82.      mov ecx,eax
    83.      add rax,2Ch
    84.      mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    85.      mov eax,[rcx+4]
    86.      sub eax,2Ch
    87.      mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    88.      invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    89. ; Запускаем проигрывание блока
    90.      lea edx,lpwiocb
    91.      mov rcx,hWaveOut
    92.      mov r8d,sizeof WAVEHDR
    93.      invoke waveOutWrite
    94. @@: test lpwiocb.dwFlags,WHDR_DONE
    95.      jz @b
    96.      lea edx,lpwiocb
    97.      invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    98.      invoke waveOutClose,hWaveOut
    99.      invoke GlobalFree,buffer
    100.      jmp wmBYE
    101. TEXT: invoke  SetDlgItemText,hWnddlg,ID_TXT,buffer
    102.      invoke GlobalFree,buffer
    103.      jmp wmBYE
    104. DIB:    and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    105.      mov qword ptr[rsp+20h],256
    106.      mov qword ptr[rsp+28h],256
    107.      invoke  CreateIconFromResourceEx,buffer,lParam,TRUE,30000h
    108.      mov [rsp+20h],rax
    109.      invoke  SendDlgItemMessage,hWnddlg,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    110.      invoke GlobalFree,buffer
    111.      jmp wmBYE
    112. wmINITDIALOG:; Создаем канал Mailslot, имеющий имя lpszMailslotName
    113.      mov ecx,offset lpszMailslotName
    114.      invoke CreateMailslot,,0,MAILSLOT_WAIT_FOREVER, NULL
    115.      mov hMailslot,rax
    116.      jmp wmBYE
    117. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    118.      jne wmBYE
    119. wmCLOSE:;Перед завершением приложения закрываем дескриптор канала Mailslot
    120.      invoke CloseHandle,hMailslot
    121.      invoke EndDialog,hWnddlg,0
    122. wmBYE:  mov eax,TRUE
    123. exit0: leave
    124. ret
    125. DialogProc endp
    126. lpszMailslotName db "\\.\mailslot\brer_Rabbit",0;Имя создаваемого канала Mailslot
    127. hMailslot dq ?;дескриптор канала Mailslot
    128. type0 db ?
    129. end
    ресурсы
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,140
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "Mailslot Reciever"
    9. BEGIN
    10.      CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11.      CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP |     ES_AUTOHSCROLL,5,7,199,13
    12.      DEFPUSHBUTTON  "Выход",IDCANCEL,149,27,60,15
    13.       CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,23,128,128
    14. END
     
    asmlamo нравится это.
  9. Mikl___

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

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

    OLE/ActiveX

    Универсальная технология, одно из ее применений ― межпроцессный обмен данными. OLE создавалась на смену DDE. Для обмена данными существует интерфейс IDataObject. Для обмена данными по сети используется DCOM, ее можно рассматривать как объединение ActiveX и RPC.

    Windows Sockets

    Отвечает за обмен данными в глобальной сети. Сокеты используются в локальных сетях. Взаимодействие происходит через так называемые разъемы-"сокеты", которые представляют собой абстракцию конечных точек коммуникационной линии, соединяющей два приложения. С этими объектами программа работает, ждет соединения, посылает данные и так далее.

    Microsoft Message Queue (MSMQ)

    Этот протокол обеспечивает посылку сообщений между приложениями с помощью очереди сообщений. Отличие от стандартной очереди сообщений Windows ― он может работать с удаленными процессами и с процессами, которые на данный момент недоступны (например, не запущены). Доставка сообщения по адресу гарантируется. Оно ставится в специальную очередь сообщений и находится там до тех пор, пока не появляется возможность его доставить.

    Удаленный вызов процедур (Remote Procedure Call, RPC)

    С помощью этой технологии общение через сеть прозрачно как для сервера, так и для клиента. И серверу, и клиенту кажется, что "собеседник" расположен локально по отношению к ним.

    Distributed Component Object Model (DCOM)

    Программная архитектура, разработанная компанией Microsoft для распределения приложений между несколькими компьютерами в сети. Программный компонент на одной из машин может использовать DCOM для передачи сообщения (его называют удаленным вызовом процедуры) к компоненту на другой машине. DCOM автоматически устанавливает соединение, передает сообщение и возвращает ответ удаленного компонента.

    Remote Method Invocation (RMI)

    Механизм, который позволяет вызывать метод удаленного объекта. Все операции по подготовке и передаче данных инкапсулируются в вызываемом методе клиентского объекта-заглушки (stub). Вызов метода не отличается от вызова метода обычного локального объекта, за небольшим исключением:
    • локальные объекты передаются по значению (копии)
    • при передаче удаленного (Remote) объекта, если он экспортирован, передается stub этого объекта
    • передаваемые объекты должны быть Serializable
    • при вызове удаленного метода может возбуждаться исключение RemoteException (ошибки маршализации/демаршализации, передачи данных и другие возможные ошибки протокола)
    При вызове метода работают с удаленным интерфейсом, а не с удаленным классом.

    Common Object Request Broker Architecture (CORBA)

    Общая архитектура брокера объектных запросов; типовая архитектура опосредованных запросов к объектам) — технологический стандарт написания распределенных приложений, продвигаемый консорциумом (рабочей группой) OMG и соответствующая ему информационная технология. CORBA обеспечивает взаимодействие между системами, работающих под разными операционными системами, написанными на разных языках программирования и запущенных на разном вычислительном оборудовании. CORBA использует объектно-ориентированную модель, системы, использующие CORBA, не обязательно должны быть объектно-ориентированными. CORBA — пример парадигмы распределенной объектной системы.

    DLL

    Важной особенностью использования динамических библиотек является возможность одновременного использования одной библиотеки несколькими модулями. Динамическая библиотека становится продолжением запустившего ее приложения, загружаясь в адресное пространство процесса. Данные процесса доступны из динамической библиотеки и данные динамической библиотеки доступны для процесса. При компоновке динамической библиотеки сегмент данных объявлен как секция с общим доступом. При запуске приложения, которое будет загружать динамическую библиотеку, эта область памяти будет общей для всех приложений.
     
  10. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Код (C):
    1. static void SendString (LPCSTR string)
    2. {
    3.     HANDLE handles[257];
    4.     char name[32];
    5.     int i, length;
    6.  
    7.     for (i=0; i<257; i++)
    8.     {
    9.         sprintf (name, "Mutex#u", i);
    10.         handles[i] = CreateMutex (NULL, TRUE, name);
    11.     }
    12.  
    13.     length = lstrlen (string);
    14.     for (i=0; i<length; i++)
    15.     {
    16.         ReleaseMutex (handles[string[i]]);
    17.         WaitForSingleObject (handles[string[i]], INFINITE);
    18.     }
    19.  
    20.     ReleaseMutex (handles[256]);
    21.  
    22.     for (i=0; i<257; i++)
    23.         CloseHandle (handles[i]);
    24. }
    25. static LPSTR ReceiveString ()
    26. {
    27.     LPSTR string;
    28.     HANDLE handles[257];
    29.     char name[32];
    30.     int i, length, result;
    31.     string = malloc (1024);
    32.     length = 0;
    33.  
    34.     for (i=0; i<257; i++)
    35.     {
    36.         sprintf (name, "Mutex#u", i);
    37.         handles[i] = CreateMutex (NULL, FALSE, name);
    38.     }
    39.  
    40.     while (TRUE)
    41.     {
    42.         result = WaitForMultipleObjects (257, handles, FALSE, INFINITE);
    43.         if (result < 0 || result > 255)
    44.             break;
    45.      
    46.         string[length++] = (char)result;
    47.         ReleaseMutex (handles[result]);
    48.     }
    49.     string[length] = 0;
    50.  
    51.     for (i=0; i<257; i++)
    52.         CloseHandle (handles[i]);
    53.  
    54.     return string;
    55. }
    56.  
     
    Mikl___ и youneuoy нравится это.
  11. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    rmn,
    спасибо огромное! А разве у WaitForMultipleObjects может быть больше объектов, чем 64?
     
  12. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Не может. Это надо на потоках разруливать. Основной поток записывает в массив хендлов MAX-1 дескрипторов, а последним ― хендл вспомогательного потока, который ждет на следующих MAX-1 дескрипторах и опционально дополнительном вспомогательном потоке.
     
  13. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    Объекты синхронизации

    08. Evet Pipes

    Windows позволяет создавать объекты синхронизации, которые называются событиями (event object). Объекты-события могут находиться в signaled состоянии или nonsignaled состоянии. Сигнальное состояние объекта (signaled) соответствует моменту времени, когда объект не принадлежит ни одному потоку и его можно "захватить". Состояние "сброшен" (nonsignaled) соответствует моменту, когда какой-либо поток уже владеет этим объектом. Доступ к объекту разрешается, когда поток, владеющий объектом, освободит его.
    Установка состояния выполняется вызовом соответствующей функции.
    Одна из задач создает объект-событие, вызывая для этого функцию CreateEvent. У события есть имя, которое доступно всем задачам активных процессов. В процессе создания или позже эта задача устанавливает событие в исходное состояние (signaled или nonsignaled).
    Вызывая функции WaitForSingleObject или WaitForMultipleObjects, задача ожидает момент, когда событие перейдет в signaled состояние.
    Другая задача, принадлежащая тому же самому или другому процессу, получает дескриптор события по его имени с помощью функции OpenEvent. Дальше используя функции SetEvent, ResetEvent или PulseEvent, приложение изменяет состояние события.
    После создания nonsignaled/неотмеченного события первая задача переходит в состояние ожидания, пока вторая задача не подготовит для нее данные. Как только это произойдет, вторая задача отмечает и затем сбрасывает событие, что приводит к завершению ожидания первой задачей.
    Отобразив подготовленные данные, первая задача опять входит в состояние ожидания, пока вторая задача не подготовит данные и не отметит событие. С помощью объекта-события две задачи синхронизируют свою работу.

    Создание события

    Для создания события приложение вызывает функцию CreateEvent
    Код (C):
    1. HANDLE CreateEvent(
    2.   LPSECURITY_ATTRIBUTES lpEventAttributes, // атрибуты защиты
    3.   BOOL    bManualReset,  // флаг ручного сброса события
    4.   BOOL    bInitialState, // флаг начального состояния события
    5.   LPCTSTR lpName       // адрес имени объекта-события
    6. );
    Параметр lpEventAttributes задает атрибуты защиты и в большинстве случаев может быть указан как NULL.
    Параметр bManualReset выбирает один из двух режимов работы объекта-события: ручной или автоматический. Если bManualReset=TRUE, событие нужно сбрасывать вручную при помощи функции ResetEvent. Если bManualReset=FALSE, событие будет сброшено (переведено в nonsignaled состояние) автоматически сразу после того как задача завершит ожидание этого события.
    Параметр bInitialState определяет начальное состояние события. Если bInitialState =TRUE, объект-событие создается в signaled/отмеченном состоянии, если bInitialState=FALSE ― в nonsignaled.
    Чтобы событием могли использовать задачи, созданные разными процессами, необходимо с помощью параметра lpName задать имя объекта-события. В качестве имени можно выбрать любое имя размером не более MAX_PATH=260 символов, не содержащее символ “\”.
    Если событие используется задачами, работающими в рамках одного процесса, имя события можно не задавать (lpName=NULL). Будет создано безымянное событие.
    В случае успешного завершения функция CreateEvent возвращает дескриптор события, который используется при выполнении операций над объектом-событием. При ошибке возвращается NULL (код ошибки получают при помощи GetLastError).
    Если при создании события указано имя уже существующего в системе события, созданного другой задачей ― тогда функция GetLastError возвратит значение ERROR_ALREADY_EXISTS=0B7h.

    Открытие события

    Если событие используется задачами, созданными в рамках одного процесса, его не нужно открывать. В качестве параметра функциям, изменяющим состояние объекта-события, можно передавать дескриптор события, полученный при создании от функции CreateEvent.
    Если событие используется для синхронизации задач, принадлежащих разным процессам, нужно при создании события задать его имя. Задача, изменяющая состояние события и принадлежащая другому процессу, должна открыть объект-событие с помощью функции OpenEvent, передав ей имя этого объекта.
    Прототип функции OpenEvent:
    Код (C):
    1. HANDLE OpenEvent(
    2.   DWORD   fdwAccess,      // флаги доступа
    3.   BOOL    fInherit,       // флаг наследования
    4.   LPCTSTR lpszEventName // адрес имени объекта-события
    5. );
    Флаги доступа, передаваемые через параметр fdwAccess, определяют требуемый уровень доступа к объекту-событию. Этот параметр может быть комбинацией следующих значений:
    Значениеhexbin Описание
    EVENT_QUERY_STATE
    SEMAPHORE_QUERY_STATE
    1​
    0.0000.0000.0000.0000.0001Право на запрос состояния объекта события
    EVENT_MODIFY_STATE
    SEMAPHORE_MODIFY_STATE
    2​
    0.0000.0000.0000.0000.0010 Полученный дескриптор можно использовать функциями SetEvent и ResetEvent
    4​
    0.0000.0000.0000.0000.0100
    8​
    0.0000.0000.0000.0000.1000
    DELETE
    10000​
    0.0001.0000.0000.0000.0000Право на удаление объекта
    READ_CONTROL
    20000​
    0.0010.0000.0000.0000.0000Право на чтение информации в дескрипторе безопасности для объекта, не включая информацию в SACL. Для чтения или записи SACL необходимо запросить право доступа ACCESS_SYSTEM_SECURITY
    WRITE_DAC
    40000​
    0.0100.0000.0000.0000.0000Право на изменение DACL в дескрипторе безопасности для объекта. Право доступа на запись к произвольному управляющему списку доступа объекта access control list (ACL)
    WRITE_OWNER
    80000​
    0.1000.0000.0000.0000.0000Право на изменение владельца в дескрипторе безопасности объекта.
    SYNCHRONIZE1000001.0000.0000.0000.0000.0000 Полученный дескриптор можно использовать в любых функциях ожидания события
    MUTEX_ALL_ACCESS1F00011.1111.0000.0000.0000.0001Указаны все возможные для Mutex флаги доступа
    EVENT_ALL_ACCESS
    SEMAPHORE_ALL_ACCESS
    1F00031.1111.0000.0000.0000.0011Указаны все возможные для Event и Semaphore флаги доступа
    Параметр fInherit определяет возможность наследования полученного дескриптора. Если fInherit=TRUE, дескриптор может наследоваться дочерними процессами. Если fInherit=FALSE, наследование не допускается.
    Через параметр lpszEventName передают имени объекта-события.
    С помощью OpenEvent несколько задач могут открыть один и тот же объект-событие и выполнять одновременное ожидание этого объекта.

    Установка события

    Для установки объекта-события в отмеченное состояние используется функция SetEvent:
    Код (C):
    1. BOOL SetEvent(HANDLE hEvent);
    В качестве параметра функции необходимо передать дескриптор объекта-события, полученного от CreateEvent или OpenEvent. При успешном завершении возвращается TRUE, при ошибке ― FALSE. Код ошибки получают через GetLastError.

    Cброс события

    Сброс события (установка в неотмеченное состояние) выполняется функцией ResetEvent:
    Код (C):
    1. BOOL ResetEvent(HANDLE hEvent);
    Если задача создала событие, работающее в автоматическом режиме, оно будет сбрасываться без помощи ResetEvent, если какая-либо задача выполняла ожидание этого события и событие произошло.

    Функция PulseEvent

    Функция PulseEvent выполняет установку объекта-события в signaled состояние с последующим сбросом события в nonsignaled состояние:
    Код (C):
    1. BOOL PulseEvent(HANDLE hEvent);
    Если эта функция вызвана для события, работающего в ручном режиме, то все задачи, ожидающие это событие, завершат ожидание и продолжат свою работу. Событие при этом будет установлено в nonsignaled состояние.
    Для автоматических объектов-событий выполняются аналогичные действия, но функция возвращает управление сразу как только одна из ожидающих задач перейдет в активное состояние.


    Текст приложения-сервера (08s.asm)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT        equ 100
    4. ID_SEND_TXT    equ 101
    5. ID_SEND_ICO    equ 102
    6. ID_SEND_WAV    equ 103
    7. IDC_DIALOG    equ 200
    8. IDC_ICON1    equ 500
    9. IDC_IMG1     equ 104
    10. EVENT_DATA_COUNT = 16
    11. size_of_buffer     = 96
    12. time_interval    = 10
    13. EventPipeObjectStruct struct
    14.     hEventDataHigh    dq EVENT_DATA_COUNT dup(?)
    15.     hEventDataLow    dq EVENT_DATA_COUNT dup(?)
    16.     hEventAck    dq ?
    17. EventPipeObjectStruct ends
    18. .code
    19. WinMain proc
    20.     enter    30h,0
    21.     mov    r9d,256;cx
    22.     mov    [rbp-10h],r9
    23.     mov    qword ptr [rbp-8],LR_DEFAULTCOLOR
    24.     invoke    LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    25.     mov    r9d,offset DialogProc
    26.     mov    qword ptr[rbp-10h],rax;30h-10h=+20h
    27.     invoke    DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    28.     invoke    RtlExitUserProcess,NULL
    29. WinMain endp
    30.  
    31. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    32. local    hFile:qword
    33. local    szEventName[32]:byte
    34. local    szReadWrite:qword    ;number of bytes actually read or write
    35. local    hResource:qword
    36. local    pResource:qword
    37.  
    38.     mov    hWnddlg,rcx
    39.     mov    lParam,r9
    40.  
    41.     cmp    edx,WM_INITDIALOG
    42.     je    wmINITDIALOG
    43.     cmp    edx,WM_CLOSE
    44.     je    wmCLOSE
    45.     cmp    edx,WM_COMMAND
    46.     je    wmCOMMAND
    47.  
    48.     xor    eax,eax
    49.     jmp    exit0
    50. wmINITDIALOG:invoke GetDlgItem,,IDC_IMG1
    51.     invoke    SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    52.     xor    edi,edi;for(DWORD i = 0; i < 16; i++)
    53. @@:; set current event name
    54.     invoke    sprintf,&szEventName,&Format1,edi
    55. ; create new object
    56.     invoke    CreateEvent,0,0,0,&szEventName
    57.     mov    EventPipeObject.hEventDataHigh[rdi*8],rax
    58. ; check for errors
    59.     or    eax,eax;if(EventPipeObject.hEventDataHigh[i] == NULL)
    60.     jz    wmBYE;exit0;
    61. ; create "low" data event handles
    62. ; set current event name
    63.     invoke    sprintf,&szEventName,&Format2,edi
    64. ; create new object
    65.     invoke    CreateEvent,0,0,0,&szEventName
    66.     mov    EventPipeObject.hEventDataLow[rdi*8],rax
    67. ; check for errors
    68.     or    eax,eax;if(EventPipeObject.hEventDataLow[i] == NULL)
    69.     jz    wmBYE;exit0
    70.     inc    edi
    71.     cmp    edi,EVENT_DATA_COUNT
    72.     jb    @b
    73. ; create acknowledgement event
    74. ; create new object
    75.     invoke    CreateEvent,0,0,0,&Format3
    76.     mov    EventPipeObject.hEventAck,rax
    77.     jmp    wmBYE
    78. wmSEND_TXT:invoke GlobalAlloc,GPTR,size_of_buffer
    79.     mov    p,rax
    80.     invoke  GetDlgItemText,hWnddlg,ID_TXT,eax,size_of_buffer
    81.         or      eax,eax
    82.         jz      wmBYE
    83.     mov    dwLength,eax
    84.     mov    edx,offset szWin
    85.         invoke  FindWindow,NULL
    86.         or      eax,eax
    87.         jz      wmBYE
    88.     mov    edx,WM_USER+1
    89.     jmp    @0
    90. ;-----------------------------------------------------------
    91. wmSEND_ICO:; Отправить изображение второму приложению
    92.         mov    edx,p1
    93.     invoke    FindResource,0,,RT_ICON; find the resource
    94.     mov    hResource,rax
    95.     invoke  SizeofResource,0,eax        ; get its size
    96.     mov    dwLength,eax
    97.     invoke    LoadResource,0,hResource    ; load the resource
    98.     invoke    LockResource,eax;pResource
    99.     mov    p,rax
    100. ;-------------------------------------------------
    101.     and    qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    102.     mov    qword ptr[rsp+20h],256
    103.     mov    qword ptr[rsp+28h],256
    104.     mov    edx,dwLength
    105.     invoke  CreateIconFromResourceEx,eax,,TRUE,30000h;270376,TRUE,30000h
    106.     mov    [rsp+20h],rax
    107.     invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    108.     xor    p1,11b
    109. ; Отправить данные получателю
    110.     mov    edx,offset szWin
    111.         invoke  FindWindow,NULL
    112.         or      eax,eax
    113.         jz      wmBYE
    114. ; Отправить данные получателю
    115.     mov    edx,WM_USER+2
    116.     jmp    @0
    117. ;-----------------------------------------------------------------------
    118. wmSEND_WAV:mov    ecx,offset wav_file
    119.     invoke    CreateFile,,GENERIC_READ,0,0,OPEN_EXISTING,\
    120.         FILE_ATTRIBUTE_ARCHIVE,0
    121.         mov    hFile,rax
    122.         invoke    GetFileSize,eax,0
    123.     mov    dwLength,eax
    124.     invoke    GlobalAlloc,GPTR,eax
    125.     invoke    GlobalLock,eax
    126.     mov    p,rax
    127.     lea    r9d,szReadWrite
    128.     mov    r8d,dwLength
    129.         invoke    ReadFile,hFile,eax,,,0
    130.         invoke    CloseHandle,hFile
    131. ;-------------------------------------------------------
    132. ; Найти окно получателя
    133.     mov    edx,offset szWin
    134.         invoke  FindWindow,NULL
    135.         or      eax,eax
    136.         jz      wmBYE
    137. ; Отправить данные получателю
    138.     mov    edx,WM_USER+3
    139. ;------------------------------------------------
    140. @0:; Отправить данные получателю
    141.     mov    r9d,dwLength
    142.     invoke    PostMessage,eax,,hWnddlg
    143.     or    eax,eax
    144.     jz    wmBYE;if(EventPipeObject.hEventAck == NULL)
    145. ; ---------------------------------------------------------------------------
    146. ; send block data
    147.     mov    rsi,p
    148.     xor    edi,edi
    149. @@:    movzx    eax,byte ptr[rdi+rsi]
    150. ;set "high" data event
    151.     shr    al, 4
    152.     invoke    SetEvent,EventPipeObject.hEventDataHigh[rax*8]
    153.     test    eax, eax
    154.     jz    wmBYE
    155. ; set "low" data event
    156.     movzx    eax,byte ptr[rdi+rsi]
    157.     and    al,0Fh
    158.     invoke    SetEvent,EventPipeObject.hEventDataLow[rax*8]
    159.     test    eax, eax
    160.     jz    wmBYE
    161. ; wait for acknowledgement
    162.     invoke    WaitForSingleObject,EventPipeObject.hEventAck,INFINITE
    163.     test    eax, eax
    164.     jnz    wmBYE
    165.     inc    edi
    166.     cmp    edi,dwLength
    167.     jb    @b
    168.     jmp    wmBYE
    169. wmCOMMAND:cmp    r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    170.         je      wmSEND_ICO
    171.     cmp    r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    172.         je      wmSEND_TXT
    173.     cmp    r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    174.         je      wmSEND_WAV
    175.     cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    176.         jne     wmBYE
    177. wmCLOSE:invoke    EndDialog,,0
    178. ; Закрываем дескрипторы объектов-событий
    179.     xor    edi,edi
    180. @@:    invoke    CloseHandle,EventPipeObject.hEventDataHigh[rdi*8]
    181.     inc    edi
    182.     cmp    edi,2*EVENT_DATA_COUNT+1
    183.     jb    @b
    184. wmBYE:    mov    eax,TRUE
    185. exit0:    leave
    186.     retn
    187. DialogProc endp
    188. ;------------------------------------------------------------
    189. Format1        db "Song_of_the_South_H%u",0
    190. Format2        db "Song_of_the_South_L%u",0
    191. Format3        db "Song_of_the_South_A",0
    192. p1        dd 1
    193. wav_file    db '..\Images\03.wav',0
    194. align 16
    195. EventPipeObject EventPipeObjectStruct <>
    196. szWin        db 'EventPipe Reciever',0
    197. p        dq ?
    198. dwLength    dd ?
    199. end
    rc-файл (08s.rc)
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT        100
    3. #define ID_SEND_TXT    101
    4. #define ID_SEND_ICO    102
    5. #define ID_SEND_WAV    103
    6. #define IDC_IMG1     104
    7.  
    8. #define IDC_DIALOG    200
    9. #define IDC_ICON1    500
    10.  
    11. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    12. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    13.  
    14. IDC_DIALOG DIALOG 0, 0, 212, 140
    15. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    16. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    17. CAPTION "EventPipe Sender"
    18. BEGIN
    19.     CONTROL     "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    20.     CONTROL     "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    21.     CONTROL    "Write something and click 'Send Text'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    22.     DEFPUSHBUTTON "Send Text",ID_SEND_TXT,149,27,60,15
    23.     PUSHBUTTON  "Send ICO",ID_SEND_ICO,149,45,60,15
    24.     PUSHBUTTON    "Send WAV",ID_SEND_WAV,149,65,60,15
    25.     PUSHBUTTON    "Exit", IDCANCEL,149,85,60,15
    26. END
    Текст приложения-клиента (08r.asm)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. EVENT_DATA_COUNT = 16
    4. ;time_interval = 10
    5. EventPipeObjectStruct struct
    6.     hEventDataHigh    dq EVENT_DATA_COUNT dup(?)
    7.     hEventDataLow    dq EVENT_DATA_COUNT dup(?)
    8.     hEventAck    dq ?
    9. EventPipeObjectStruct ends
    10.  
    11. IDC_DIALOG    equ 200
    12. ID_TXT        equ 100
    13. ID_ICON        equ 102
    14. ID_PROGRESS    equ 106
    15. IDC_ICON1    equ 500
    16. .code
    17. WinMain proc
    18.     enter    30h,0
    19.     mov    r9d,offset DialogProc
    20.     and    qword ptr[rbp-10h],0
    21.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    22.         invoke  RtlExitUserProcess,NULL
    23. WinMain endp
    24. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    25.  
    26.     mov    hWnddlg,rcx
    27.     mov    lParam,r9
    28.  
    29.         cmp     edx,WM_INITDIALOG
    30.     jne     wmBYE
    31. wmINITDIALOG:mov hWnd,rcx
    32.         mov     edx,GWL_STYLE
    33.     invoke    GetWindowLongPtr
    34.         or    eax,WS_THICKFRAME OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX
    35.     mov    edx,GWL_STYLE
    36.     invoke    SetWindowLongPtr,hWnddlg,,rax
    37.     mov    r8d,offset WndProc
    38.     mov    edx,GWL_WNDPROC
    39.     invoke    SetWindowLongPtr,hWnddlg
    40. ; Найти окно получателя
    41.     mov    edx,offset szWin
    42.         invoke  FindWindow,NULL
    43.         or      eax,eax
    44.         jnz    @f;wmBYE
    45.     mov    edx,offset Error1
    46.     mov    r8d,offset szAppName
    47.     invoke    MessageBox,hWnddlg,,,MB_ICONEXCLAMATION or MB_YESNO
    48.     cmp    eax,IDNO
    49.     jz      @f;wmBYE
    50.     mov    ecx,offset szService
    51.     invoke    WinExec,,SW_SHOW
    52. ; create "high" data event handles
    53.     xor    edi,edi;for(DWORD i = 0; i < ; i++)
    54. ; set current event name
    55. @@:    invoke    sprintf,&szEventName,&Format1,edi
    56. ; open existing object
    57.     invoke    OpenEvent,EVENT_ALL_ACCESS,0,&szEventName
    58.     mov    EventPipeObject.hEventDataHigh[rdi*8],rax
    59.     or    eax,eax
    60.     jz    wmBYE
    61.     invoke    sprintf,&szEventName,&Format2,edi
    62. ; open existing object
    63.     invoke    OpenEvent,EVENT_ALL_ACCESS,0,&szEventName
    64.     mov    EventPipeObject.hEventDataLow[rdi*8],rax
    65. ; check for errors
    66.     or    eax,eax;if(EventPipeObject.hEventDataLow[i] == NULL)
    67.     jz    wmBYE
    68.     inc    edi
    69.     cmp    edi,EVENT_DATA_COUNT
    70.     jb    @b
    71. ; create acknowledgement event
    72.     invoke    OpenEvent,EVENT_ALL_ACCESS,0,&Format3
    73.     mov    EventPipeObject.hEventAck,rax
    74. ;--------------------------------------------------
    75. ; Шрифт текста
    76.     pushaddr szFont
    77.     push    FIXED_PITCH+FF_DONTCARE
    78.     push    PROOF_QUALITY
    79.     push    CLIP_DEFAULT_PRECIS
    80.     push    OUT_RASTER_PRECIS
    81.     push    ANSI_CHARSET
    82.     push    FALSE
    83.     push    FALSE
    84.     push    FALSE
    85.     push    FW_BOLD
    86.     sub    esp,20h
    87.         invoke  CreateFont,32,12,0,0
    88.         mov     hFont,rax
    89.  
    90.         invoke  GetDlgItem,hWnddlg,ID_PROGRESS
    91.         mov     hProgress,rax
    92. ; Установить наш собственный обработчик
    93.     mov    r8d,offset ProgressWindowProc
    94.         invoke  SetWindowLongPtr,hProgress,GWL_WNDPROC
    95.         ; Сохранить хэндл предыдущего обработчика
    96.         mov     OldProc,rax
    97. wmBYE:    xor    eax,eax
    98.     leave
    99.     retn
    100. DialogProc endp
    101. WndProc proc    hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    102. local    text:dword
    103. local    ps:PAINTSTRUCT
    104. local    hDC:dword
    105. local    rcClient:RECT
    106.  
    107.     mov    hWnd,rcx
    108.     mov    lParam,r9
    109.  
    110.     cmp    edx,WM_CLOSE
    111.     je    wmCLOSE
    112.     cmp    edx,WM_COMMAND
    113.     je    wmCOMMAND
    114.     cmp    edx,WM_USER+1
    115.     je    wmUSER_1
    116.     cmp    edx,WM_USER+2
    117.     je    wmUSER_2
    118.     cmp    edx,WM_USER+3
    119.     je    wmUSER_3
    120.     leave
    121.     jmp    NtdllDialogWndProc_
    122. ;-----------------------------------------------------
    123. wmUSER_1:mov    rax,lParam
    124.     mov    DataLength,rax
    125.     inc    eax
    126.     invoke    GlobalAlloc,GPTR,eax
    127.     mov    p_Text,rax
    128.     invoke    EventPipeRecieve,eax
    129.     and    byte ptr[rdi],0
    130.         invoke  SetDlgItemText,hWnd,ID_TXT,p_Text
    131.     invoke    GlobalFree,p_Text
    132.     jmp    wmBYE
    133. wmUSER_2:and    percent,0
    134.         xor    ecx,ecx
    135.     mov    [rsp+20h],rcx
    136.     movr    qword ptr[rsp+28h],hThread2
    137.     mov    r8d,offset TimerFuncProgress
    138.     invoke    CreateThread,,0,,13
    139.     invoke    CloseHandle,hThread2
    140. ;------------------------------------------------------
    141.     mov    rax,lParam
    142.     mov    DataLength,rax
    143.     invoke    GlobalAlloc,GPTR,eax
    144.     xor    ecx,ecx
    145.     mov    [rsp+20h],rcx
    146.     movr    qword ptr[rsp+28h],hThread3
    147.     mov    r8d,offset TimerFuncICO
    148.     invoke    CreateThread,,0,,eax
    149.     invoke    CloseHandle,hThread3
    150.     jmp    wmBYE
    151. wmUSER_3:and    percent,0
    152.         xor    ecx,ecx
    153.     mov    [rsp+20h],rcx
    154.     movr    qword ptr[rsp+28h],hThread4
    155.     mov    r8d,offset TimerFuncProgress
    156.     invoke    CreateThread,,0,,128
    157.     invoke    CloseHandle,hThread4
    158. ;-----------------------------------------------
    159.     mov    rax,lParam
    160.     mov    DataLength,rax
    161.     invoke    GlobalAlloc,GPTR,eax
    162.     xor    ecx,ecx
    163.     mov    [rsp+20h],rcx
    164.     movr    qword ptr[rsp+28h],hThread5
    165.     mov    r8d,offset TimerFuncWAV
    166.     invoke    CreateThread,,0,,eax
    167.     invoke    CloseHandle,hThread5
    168.     jmp    wmBYE
    169. wmCOMMAND:cmp    r8d,BN_CLICKED shl 16 + IDCANCEL
    170.     jne    wmBYE
    171. wmCLOSE:invoke    EndDialog,,0
    172. ; Закрываем дескрипторы объектов-событий
    173.     xor    edi,edi
    174. @@:    invoke    CloseHandle,EventPipeObject.hEventDataHigh[rdi*8]
    175.     inc    edi
    176.     cmp    edi,2*EVENT_DATA_COUNT+1
    177.     jb    @b
    178. wmBYE:  mov    eax,TRUE
    179. exit0:    leave
    180.     ret
    181. WndProc endp
    182.  
    183. TimerFuncICO proc p:qword
    184.     mov    p,rcx
    185.  
    186.     invoke    EventPipeRecieve
    187. ; Создать HICON напрямую из памяти
    188.     and    qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    189.     mov    qword ptr[rsp+20h],256
    190.     mov    qword ptr[rsp+28h],256
    191.     invoke  CreateIconFromResourceEx,p,DataLength,TRUE,30000h
    192.     mov    [rsp+20h],rax
    193.     invoke  SendDlgItemMessage,hWnd,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    194.     invoke    GlobalFree,p
    195. exit2:    leave
    196.     ret
    197. TimerFuncICO endp
    198.  
    199. TimerFuncWAV proc p:qword
    200. local    lpwiocb:WAVEHDR
    201. local    hWaveOut:qword
    202.     mov    p,rcx
    203.  
    204.     invoke    EventPipeRecieve
    205. WAVE:    mov    r8,p
    206. ;"RIFF"+(File size)+(File Type Header)+(Format chunk marker)+(Length of format data) = 14h
    207.         add    r8d,14h
    208.         lea    ecx,hWaveOut
    209.         xor    r9,r9
    210.     mov    [rsp+20h],r9
    211.     mov    qword ptr[rsp+28h],WAVE_ALLOWSYNC
    212.         or    edx,WAVE_MAPPER
    213.         invoke    waveOutOpen
    214. ; Подготавливаем заголовок для вывода
    215.     lea    edx,lpwiocb
    216.     mov    edi,edx
    217.     xor    eax,eax
    218.     mov    ecx,(sizeof WAVEHDR)/8
    219.     rep    stosq
    220.  
    221.     mov    rax,p
    222.     mov    ecx,eax
    223. ;"RIFF"+(File size)+(File Type Header)+(Format chunk marker)+(Length of format data)+\
    224. ;(Type of format)+(Number of Channels)+(Sample Rate)+(Sample Rate*BitsPerSample*Channels/8)+\
    225. ;(BitsPerSample*Channels/8)+(Bits per sample)+(“data” chunk header)+(Size of the data section)=2Ch
    226.     add    eax,2Ch
    227.  
    228.     mov    [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    229.     mov    eax,[rcx+4];размер блока данных
    230.     sub    eax,2Ch
    231.     mov    [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    232.  
    233.     invoke    waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    234. ; Запускаем проигрывание блока
    235.     lea    edx,lpwiocb
    236.     mov    rcx,hWaveOut
    237.     mov    r8d,sizeof WAVEHDR
    238.     invoke    waveOutWrite
    239. @@:    test    lpwiocb.dwFlags,WHDR_DONE
    240.     jz    @b
    241.     lea    edx,lpwiocb
    242.     invoke    waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    243.     invoke    waveOutClose,hWaveOut
    244. @1:    invoke    GlobalFree,p
    245. exit2:    leave
    246.     ret
    247. TimerFuncWAV endp
    248. TimerFuncProgress proc lParam:qword
    249.     mov    lParam,rcx
    250. ; Сформировать строку для отрисовки
    251. @@:    mov    r8d,percent
    252.     mov    edx,offset szText
    253.     mov    ecx,offset buff
    254.         invoke  wsprintf
    255. ; Назначить строку свойством ProgressBar
    256.     mov    r8d,offset buff
    257.     mov    edx,offset szProp
    258.         invoke  SetProp,hProgress
    259. ; Назначить значение процента свойством ProgressBar
    260.     mov    r8d,percent
    261.     mov    edx,offset szPerc
    262.         invoke  SetProp,hProgress
    263. ; Перерисовать содержимое окна
    264.         invoke  InvalidateRect,hProgress,0,FALSE
    265.         inc     percent
    266.         cmp     percent,101
    267.         je    exit0
    268.     invoke    Sleep,lParam
    269.     jmp    @b
    270. exit0:    leave
    271.     ret
    272. TimerFuncProgress endp
    273. EventPipeRecieve proc p:qword
    274. local    dwEventDataLowValue:byte
    275.  
    276.     mov    edi,ecx
    277.     add    rcx,DataLength
    278.     mov    EndDataLength,ecx
    279. @@:    lea    edx,EventPipeObject.hEventDataLow
    280.     invoke    WaitForMultipleObjects,EVENT_DATA_COUNT,,0,2
    281.     mov    dwEventDataLowValue,al;eax
    282.     cmp    eax,EVENT_DATA_COUNT;if(dwEventDataLowValue >= EVENT_DATA_COUNT)
    283.     jnb    exit1
    284. ; wait for "high" data value
    285.     lea    edx,EventPipeObject.hEventDataHigh
    286.     invoke    WaitForMultipleObjects,EVENT_DATA_COUNT,,0,0
    287. ; calculate byte value from high/low value
    288.     shl    al,4;dwEventDataHighValue * 16
    289.     add    al,dwEventDataLowValue
    290. ; store byte value
    291.     stosb
    292. ; set acknowledgement event
    293.     invoke    SetEvent,EventPipeObject.hEventAck
    294. ;------------------------------------------------------------------
    295. ; increase ptr
    296. exit1:    cmp    edi,EndDataLength
    297.     jb    @b;for(DWORD i = 0; i < EndDataLength; i++)
    298.     leave
    299.     ret
    300. EventPipeRecieve endp
    301. ProgressWindowProc proc hEdit:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    302. local    text:dword
    303. local    ps:PAINTSTRUCT
    304. local    hDC:dword
    305. local    rcClient:RECT
    306.  
    307.     mov    hEdit,rcx
    308.     mov    uMsg,rdx
    309.     mov    wParam,r8
    310.     mov    lParam,r9
    311.  
    312.     cmp    edx,WM_PAINT
    313.     je    wmPAINT
    314.     mov    [rsp+20h],r9;lParam
    315.     mov    r9,wParam
    316.     mov    r8,uMsg
    317.     mov    rdx,hEdit
    318.         invoke  CallWindowProc,OldProc
    319.     jmp    wmBYE
    320. wmPAINT:; Размеры окна
    321.         lea     edx,rcClient
    322.         invoke  GetClientRect,hEdit;,edi
    323.         ; Получить текст из свойств
    324.     mov    edx,offset szProp
    325.         invoke  GetProp,hEdit;hProgress
    326.         mov     text,eax
    327. ; Начать рисование
    328.         lea     edx,ps
    329.         invoke  BeginPaint,hEdit;hProgress
    330.         mov     hDC,eax
    331. ; Шрифт
    332.         invoke  SelectObject,hDC,hFont
    333.         invoke  SetBkMode,hDC,TRANSPARENT
    334. ; Отрисовать общий фон
    335.         invoke  GetSysColorBrush,COLOR_WINDOW
    336.         lea     edx,rcClient
    337.         invoke  FillRect,hDC,,eax
    338. ; Текст для отрисовки есть?
    339.         cmp     text,0
    340.         je      @f
    341.         invoke  GetSysColor,COLOR_WINDOWTEXT
    342.         invoke  SetTextColor,hDC,eax
    343.     mov    edx,offset buff
    344.     mov    qword ptr[rsp+20h],DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER or DT_CENTER
    345.         lea     r9d,rcClient
    346.         invoke  DrawText,hDC,,-1
    347. @@:; Вычислить размеры области для заливки
    348.     mov    edx,offset szPerc
    349.         invoke  GetProp,hEdit;hProgress
    350.         mov     ecx,eax
    351.         lea     r9d,rcClient
    352.         mov     eax,[r9].RECT.right
    353.         sub     eax,[r9].RECT.left
    354.         mul     ecx
    355.         xor     edx,edx
    356.         mov     ecx,100
    357.         div     ecx
    358. ; Позиция выполненного прогресса
    359.         add     eax,[r9].RECT.left
    360. ; Наложить выполненный прогресс
    361.     mov    ecx,[r9].RECT.left
    362.     mov    edx,[r9].RECT.top
    363.     mov    r9d,[r9].RECT.bottom
    364.         invoke  CreateRectRgn,,,eax
    365.         invoke  SelectClipRgn,hDC,eax
    366.         invoke  GetSysColorBrush,COLOR_HIGHLIGHT
    367.     lea     edx,rcClient
    368.         invoke  FillRect,hDC,,eax
    369. ; Текст для отрисовки есть?
    370.         cmp     text,0
    371.         je      @f
    372.         invoke  GetSysColor,COLOR_HIGHLIGHTTEXT
    373.         invoke  SetTextColor,hDC,eax
    374.     mov    qword ptr[rsp+20h],DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER or DT_CENTER
    375.     mov    edx,offset buff
    376.         lea     r9d,rcClient
    377.         invoke  DrawText,hDC,,-1
    378. @@:    lea     edx,ps
    379.         invoke  EndPaint,hDC
    380.     xor    eax,eax
    381. wmBYE:    leave
    382.     retn
    383. ProgressWindowProc endp
    384. ;-----------------------------------------------------------------------
    385. .data
    386. hWnd        dq ?
    387. Format1        db "Song_of_the_South_H%u",0
    388. Format2        db "Song_of_the_South_L%u",0
    389. Format3        db "Song_of_the_South_A",0
    390. p_Text        dq ?
    391. p_ICO        dq ?
    392. p_WAV        dq ?
    393. szWin        db "EventPipe Sender",0
    394. Error1        db "The server is not running.",10,"Run?",0
    395. szAppName    db "EventPipe Reciever",0
    396. szService    db "08s",0
    397. hThread2    dq ?
    398. hThread3    dq ?
    399. hThread4    dq ?
    400. hThread5    dq ?
    401. szEventName    db 32 dup(?)
    402. buff        db 100 dup(?)
    403. szText      db '%u%% completed',0
    404. percent        dd 0
    405. hProgress    dq ?
    406. hFont        dq ?
    407. szProp        db 'text',0
    408. szPerc        db 'percent',0
    409. szFont        db "Verdana",0
    410. OldProc        dq ?
    411. align 16
    412. EventPipeObject EventPipeObjectStruct <>
    413. DataLength    dq ?
    414. EndDataLength    dd ?
    415. end
    rc-файл (08r.rc)
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG    200
    3. #define ID_TXT        100
    4. #define ID_ICON        102
    5. #define ID_PROGRESS    106
    6.  
    7. IDC_DIALOG DIALOG 0,0,212,154
    8. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    9. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    10. CAPTION "EventPipe Reciever"
    11. BEGIN
    12.     CONTROL    "",-1,"BUTTON",BS_GROUPBOX, 2, -3, 207, 24
    13.     CONTROL    "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,5,199,13
    14.         CONTROL    "",ID_PROGRESS,"STATIC",WS_VISIBLE | 3 | WS_DISABLED | WS_BORDER,2,22,146,19
    15.     DEFPUSHBUTTON  "Exit",IDCANCEL,149,25,60,15
    16.         CONTROL    "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,3,40,128,128
    17. END
    08.jpg
     

    Вложения:

    • EventPipes.zip
      Размер файла:
      1,6 МБ
      Просмотров:
      94
    Последнее редактирование: 25 авг 2022
  14. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    в аттаче ICO/WAV/ASM/RC/EXE-файлы. Текстовые строки между приложениями передаются мгновенно, рисунки и медиа-файлы передаются продолжительное время, поэтому (чтобы пользователь не закрыл клиентское приложение раньше времени) к клиентскому приложению пришлось добавить progress-bar. Механизм progress bar'а с надписью заимствован на сайте manhunter'a https://www.manhunter.ru/ assembler/ 1753 kak sdelat progressbar s nadpisyu.html за что ему огромное спасибо :)
    Краткое пояснение: стандартный элемент msctls_progress32 не используется, вместо него взят элемент STATIC. Полоса индикатора и надпись рисуется на канве элемента диалогового окна, которое выделено под индикатор. При рисовании текста поверх индикатора прогресса, учтена разница в цвете фона и полосы выполненной части. Взаимодействие основного потока приложения и индикатора реализуется через сабклассирование.

    10. Semaphores

    Семафоры позволяют обеспечить доступ к ресурсу для заранее определенного, ограниченного приложением количества задач. Все остальные задачи, пытающиеся получить доступ сверх установленного лимита, будут переведены при этом в состояние ожидания до тех пор, пока какая либо задача, получившая доступ к ресурсу раньше, не освободит ресурс, связанный с данным семафором.
    Задачи, пытающиеся получить доступ к ресурсу, должны быть переведены в состояние ожидания и пребывать в нем до тех пор, пока не завершит свою работу одна из задач, уже получившая доступ к ресурсу.
    Семафор может находиться в signaled (отмеченном) или unsignaled (неотмеченном) состоянии. Приложение выполняет ожидание семафора при помощи WaitForSingleObject или WaitForMultipleObject. Если семафор находится в неотмеченном состоянии, задача, вызвавшая для него функцию WaitForSingleObject, находится в состоянии ожидания. Если состояние семафора становится отмеченным, работа задачи возобновляется. С каждым семафором связывается счетчик, начальное и максимальные значения которого задаются при создании семафора. Значение этого счетчика уменьшается, когда задача вызывает для семафора функцию WaitForSingleObject или WaitForMultipleObject, и увеличивается при вызове другой, специально предназначенной для этого функции.
    Если значение счетчика семафора равно нулю, он находится в неотмеченном состоянии. Если же это значение больше нуля, семафор переходит в отмеченное состояние.
    Допустим приложение создало семафор, указав для него максимальное значение счетчика, равное трем. Пусть начальное значение этого счетчика также будет равно трем.
    Если в этой ситуации несколько запускаемых по очереди задач будут выполнять с помощью функции WaitForSingleObject ожидание семафора, то первые три запущенные задачи будут работать, а все остальные перейдут в состояние ожидания. Первые три вызова функции WaitForSingleObject приведут к последовательному уменьшению значения счетчика семафора до нуля, в результате чего семафор переключится в неотмеченное состояние.
    Задача, запущенная четвертой, вызовет функцию WaitForSingleObject для неотмеченного семафора, в результате чего она будет ждать. Точно также, задачи, запущенные после запуска четвертой задачи, будут выполнять ожидание для того же семафора.
    Как долго продлится ожидание?
    До тех пор, пока одна из первых трех задач не освободит семафор, увеличив его счетчик на единицу вызовом специальной функции. Сразу после этого будет запущена одна из задач, ожидающих наш семафор.
    Функции для работы с семафорами
    Создание семафора
    Для создания семафора приложение должно вызвать функцию CreateSemaphore
    Код (C):
    1. HANDLE CreateSemaphore(
    2.   LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // атрибуты защиты
    3.   LONG lInitialCount,  // начальное значение счетчика семафора
    4.   LONG lMaximumCount,  // максимальное значение счетчика семафора
    5.   LPCTSTR  lpName     // адрес строки с именем семафора
    6. );
    В качестве атрибутов защиты вы можете передать значение NULL.
    Через параметры lInitialCount и lMaximumCount передается, начальное и максимальное значение счетчика, связанного с создаваемым семафором. Начальное значение счетчика lInitialCount должно быть больше или равно нулю и не должно превосходить максимальное значение счетчика, передаваемое через параметр lMaximumCount.
    Имя семафора указывается с помощью параметра lpName.
    В случае удачного создания CreateSemaphore возвращает дескриптор семафора. В случае ошибки ― NULL, код ошибки можно узнать с помощью GetLastError.
    Имена семафоров доступны всем приложениям в системе, возможна ситуация, когда приложение пытается создать семафор с уже использованным именем. Тогда новый семафор не создается, а приложение получает дескриптор существующего семафора. При такой ситуации GetLastError возвращает значение ERROR_ALREADY_EXISTS=0B7h.
    Уничтожение семафора
    Для уничтожения семафора его дескриптор передается CloseHandle. При завершении процесса все созданные им семафоры уничтожаются автоматически.
    Открытие семафора
    Если семафор используется для синхронизации задач, созданных в одном приложении, можно создать безымянный семафор, указав lpName=0. Если необходимо синхронизировать задачи разных процессов, определяют имя семафора. Один процесс создает семафор с помощью функции CreateSemaphore, другой открывает семафор, получая дескриптор для уже существующего семафора. Существующий семафор открывают функцией OpenSemaphore
    Код (C):
    1. HANDLE OpenSemaphore(
    2.   DWORD   fdwAccess,           // требуемый доступ
    3.   BOOL    fInherit,            // флаг наследования
    4.   LPCTSTR lpszSemaphoreName // адрес имени семафора
    5. );
    Флаги доступа, передаваемые через параметр fdwAccess, определяют требуемый уровень доступа к семафору. Этот параметр может быть комбинацией следующих значений:
    ЗначениеhexОписание
    SEMAPHORE_ALL_ACCESS1F0003Указаны все возможные флаги доступа
    SEMAPHORE_QUERY_STATE
    1​
    SEMAPHORE_MODIFY_STATE
    2​
    Возможно изменение значение счетчика семафора функцией ReleaseSemaphore
    SYNCHRONIZE100000 Полученный дескриптор можно будет использовать в любых функциях ожидания события
    Параметр fInherit определяет возможность наследования полученного дескриптора. Если fInherit=TRUE, дескриптор может наследоваться дочерними процессами. Если fInherit=FALSE, наследование не допускается.
    Через lpszSemaphoreName функции передают адрес имени семафора.
    Если семафор открыт, функция OpenSemaphore возвращает его дескриптор. При ошибке возвращается значение NULL. Код ошибки определяют при помощи GetLastError.

    Увеличение значения счетчика семафора

    Для увеличения значения счетчика семафора приложение должно использовать функцию ReleaseSemaphore
    Код (C):
    1. BOOL ReleaseSemaphore(
    2.   HANDLE hSemaphore,        // дескриптор семафора
    3.   LONG   cReleaseCount,     // значение инкремента
    4.   LPLONG lplPreviousCount // адрес переменной для записи предыдущего значения счетчика семафора
    5. );
    ReleaseSemaphore увеличивает значение счетчика семафора, дескриптор которого передается ей через параметр hSemaphore, на значение, указанное в параметре cReleaseCount.
    Через параметр cReleaseCount передают значение большее нуля. Если в результате увеличения новое значение счетчика должно будет превысить максимальное значение, заданное при создании семафора, ReleaseSemaphore возвращает признак ошибки и не изменяет значение счетчика.
    Предыдущее значение счетчика, которое было до использования функции ReleaseSemaphore, записывается в переменную. Адрес этой переменной передается через параметр lplPreviousCount.
    Если ReleaseSemaphore завершилась успешно, возвращается TRUE. При ошибке возвращается FALSE. Код ошибки можно определить при помощи GetLastError.
    ReleaseSemaphore используется для решения двух задач:
    1. с помощью ReleaseSemaphore задачи освобождают ресурс, доступ к которому регулируется семафором. Они могут делать это после использования ресурса или перед своим завершением.
    2. ReleaseSemaphore может быть использована на этапе инициализации мультизадачного приложения. Создавая семафор с начальным значением счетчика, равным нулю, главная задача блокирует работу задач, выполняющих ожидание этого семафора. После завершения инициализации главная задача с помощью функции ReleaseSemaphore может увеличить значение счетчика семафора до максимального, в результате чего известное количество ожидающих задач будет активизировано.

    Уменьшение значения счетчика семафора

    В Windows нет функции, специально предназначенной для уменьшения значения счетчика семафора. Этот счетчик уменьшается, когда задача вызывает функции ожидания, такие как WaitForSingleObject или WaitForMultipleObject. Если задача вызывает несколько раз функцию ожидания для одного и того же семафора, содержимое его счетчика каждый раз будет уменьшаться.

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

    Единственная возможность определения текущего значения счетчика семафора заключается в увеличении этого значения функцией ReleaseSemaphore. Значение счетчика, которое было до увеличения, будет записано в переменную, адрес которой передается функции ReleaseSemaphore через параметр lplPreviousCount.
    В Windows не предусмотрено средств, с помощью которых можно было бы определить текущее значение семафора, не изменяя его. Нельзя задать функции ReleaseSemaphore нулевое значение инкремента, так как в этом случае указанная функция просто вернет соответствующий код ошибки.
    Текст приложения-сервера (10s.asm)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. ID_SEND_ICO equ 102
    6. ID_SEND_WAV equ 103
    7. IDC_DIALOG equ 200
    8. IDC_ICON1 equ 500
    9. IDC_IMG1 equ 104
    10. SEMAPHORE_DATA_COUNT = 16
    11. size_of_buffer = 96
    12. time_interval    = 10
    13. SemaphoreObjectStruct struct
    14. hSemaphoreDataHigh dq SEMAPHORE_DATA_COUNT dup(?)
    15. hSemaphoreDataLow dq SEMAPHORE_DATA_COUNT dup(?)
    16. hSemaphoreAck dq ?
    17. SemaphoreObjectStruct ends
    18. .code
    19. WinMain proc
    20. enter 30h,0
    21. mov r9d,256;cx
    22. mov [rbp-10h],r9
    23. mov qword ptr [rbp-8],LR_DEFAULTCOLOR
    24. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    25. mov r9d,offset DialogProc
    26. mov qword ptr[rbp-10h],rax;30h-10h=+20h
    27. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    28. invoke RtlExitUserProcess,NULL
    29. WinMain endp
    30. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    31. local hFile:qword
    32. local szSemaphoreName[32]:byte
    33. local szReadWrite:qword ;number of bytes actually read or write
    34. local hResource:qword
    35. local pResource:qword
    36. mov hWnddlg,rcx
    37. mov lParam,r9
    38. cmp edx,WM_INITDIALOG
    39. je wmINITDIALOG
    40. cmp edx,WM_CLOSE
    41. je wmCLOSE
    42. cmp edx,WM_COMMAND
    43. je wmCOMMAND
    44. xor eax,eax
    45. jmp exit0
    46. wmINITDIALOG:invoke GetDlgItem,,IDC_IMG1
    47. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    48. xor edi,edi;for(DWORD i = 0; i < 16; i++)
    49. @@:; set current Semaphore name
    50. invoke sprintf,&szSemaphoreName,&Format1,edi
    51. ; create new object
    52. invoke CreateSemaphore,0,0,1,&szSemaphoreName
    53. mov SemaphoreObject.hSemaphoreDataHigh[rdi*8],rax
    54. ; check for errors
    55. or eax,eax;if(SemaphoreObject.hSemaphoreDataHigh[i] == NULL)
    56. jz wmBYE;exit0;
    57. ; create "low" data Semaphore handles
    58. ; set current Semaphore name
    59. invoke sprintf,&szSemaphoreName,&Format2,edi
    60. ; create new object
    61. invoke CreateSemaphore,0,0,1,&szSemaphoreName
    62. mov SemaphoreObject.hSemaphoreDataLow[rdi*8],rax
    63. ; check for errors
    64. or eax,eax;if(SemaphoreObject.hSemaphoreDataLow[i] == NULL)
    65. jz wmBYE;exit0
    66. inc edi
    67. cmp edi,SEMAPHORE_DATA_COUNT
    68. jb @b
    69. ; create acknowledgement Semaphore
    70. ; create new object
    71. invoke CreateSemaphore,0,0,1,&Format3
    72. mov SemaphoreObject.hSemaphoreAck,rax
    73. jmp wmBYE
    74. wmSEND_TXT:invoke GlobalAlloc,GPTR,size_of_buffer
    75. mov p,rax
    76. invoke  GetDlgItemText,hWnddlg,ID_TXT,eax,size_of_buffer
    77.         or      eax,eax
    78.         jz      wmBYE
    79. mov dwLength,eax
    80. mov edx,offset szWin
    81.         invoke  FindWindow,NULL
    82.         or      eax,eax
    83.         jz      wmBYE
    84. mov edx,WM_USER+1
    85. jmp @0
    86. ;-----------------------------------------------------------
    87. wmSEND_ICO:; Отправить изображение второму приложению
    88.         mov edx,p1
    89. invoke FindResource,0,,RT_ICON; find the resource
    90. mov hResource,rax
    91. invoke  SizeofResource,0,eax ; get its size
    92. mov dwLength,eax
    93. invoke LoadResource,0,hResource ; load the resource
    94. invoke LockResource,eax;pResource
    95. mov p,rax
    96. ;-------------------------------------------------
    97. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    98. mov qword ptr[rsp+20h],256
    99. mov qword ptr[rsp+28h],256
    100. mov edx,dwLength
    101. invoke  CreateIconFromResourceEx,eax,,TRUE,30000h;270376,TRUE,30000h
    102. mov [rsp+20h],rax
    103. invoke  SendDlgItemMessage,hWnddlg,IDC_IMG1,STM_SETIMAGE,IMAGE_ICON
    104. xor p1,11b
    105. ; Отправить данные получателю
    106. mov edx,offset szWin
    107.         invoke  FindWindow,NULL
    108.         or      eax,eax
    109.         jz      wmBYE
    110. ; Отправить данные получателю
    111. mov edx,WM_USER+2
    112. jmp @0
    113. ;-----------------------------------------------------------------------
    114. wmSEND_WAV:mov ecx,offset wav_file
    115. invoke CreateFile,,GENERIC_READ,0,0,OPEN_EXISTING,\
    116.         FILE_ATTRIBUTE_ARCHIVE,0
    117.         mov hFile,rax
    118.         invoke GetFileSize,eax,0
    119. mov dwLength,eax
    120. invoke GlobalAlloc,GPTR,eax
    121. invoke GlobalLock,eax
    122. mov p,rax
    123. lea r9d,szReadWrite
    124. mov r8d,dwLength
    125.         invoke ReadFile,hFile,eax,,,0
    126.         invoke CloseHandle,hFile
    127. ;-------------------------------------------------------
    128. ; Найти окно получателя
    129. mov edx,offset szWin
    130.         invoke  FindWindow,NULL
    131.         or      eax,eax
    132.         jz      wmBYE
    133. ; Отправить данные получателю
    134. mov edx,WM_USER+3
    135. ;------------------------------------------------
    136. @0:; Отправить данные получателю
    137. mov r9d,dwLength
    138. invoke PostMessage,eax,,hWnddlg
    139. or eax,eax
    140. jz wmBYE;if(SemaphoreObject.hSemaphoreAck == NULL)
    141. ; ---------------------------------------------------------------------------
    142. ; send block data
    143. mov rsi,p
    144. xor edi,edi
    145. @@: movzx eax,byte ptr[rdi+rsi]
    146. ;set "high" data Semaphore
    147. shr al, 4
    148. invoke ReleaseSemaphore,SemaphoreObject.hSemaphoreDataHigh[rax*8],1,0
    149. test eax, eax
    150. jz wmBYE
    151. ; set "low" data Semaphore
    152. movzx eax,byte ptr[rdi+rsi]
    153. and al,0Fh
    154. invoke ReleaseSemaphore,SemaphoreObject.hSemaphoreDataLow[rax*8],1,0
    155. test eax, eax
    156. jz wmBYE
    157. ; wait for acknowledgement
    158. invoke WaitForSingleObject,SemaphoreObject.hSemaphoreAck,INFINITE
    159. test eax, eax
    160. jnz wmBYE
    161. inc edi
    162. cmp edi,dwLength
    163. jb @b
    164. jmp wmBYE
    165. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_ICO
    166.         je      wmSEND_ICO
    167. cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    168.         je      wmSEND_TXT
    169. cmp r8d,BN_CLICKED shl 16 + ID_SEND_WAV
    170.         je      wmSEND_WAV
    171. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    172.         jne     wmBYE
    173. wmCLOSE:invoke EndDialog,,0
    174. ; Закрываем дескрипторы объектов-событий
    175. xor edi,edi
    176. @@: invoke CloseHandle,SemaphoreObject.hSemaphoreDataHigh[rdi*8]
    177. inc edi
    178. cmp edi,2*SEMAPHORE_DATA_COUNT+1
    179. jb @b
    180. wmBYE: mov eax,TRUE
    181. exit0: leave
    182. retn
    183. DialogProc endp
    184. ;------------------------------------------------------------
    185. Format1 db "Song_of_the_South_H%u",0
    186. Format2 db "Song_of_the_South_L%u",0
    187. Format3 db "Song_of_the_South_A",0
    188. p1 dd 1
    189. wav_file db '..\Images\03.wav',0
    190. align 16
    191. SemaphoreObject SemaphoreObjectStruct <>
    192. szWin db 'Semaphore Reciever',0
    193. p dq ?
    194. dwLength dd ?
    195. end
    ресурсы сервера (10s.rc)
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define ID_SEND_ICO 102
    5. #define ID_SEND_WAV 103
    6. #define IDC_IMG1 104
    7. #define IDC_DIALOG 200
    8. #define IDC_ICON1 500
    9. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    10. IDC_ICON2 ICON "..\\Images\\icon2.ico"
    11. IDC_DIALOG DIALOG 0, 0, 212, 140
    12. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    13. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    14. CAPTION "Semaphore Sender"
    15. BEGIN
    16.     CONTROL     "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    17.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    18.     CONTROL "Write something and click 'Send Text'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    19.     DEFPUSHBUTTON "Send Text",ID_SEND_TXT,149,27,60,15
    20.     PUSHBUTTON  "Send ICO",ID_SEND_ICO,149,45,60,15
    21.     PUSHBUTTON "Send WAV",ID_SEND_WAV,149,65,60,15
    22.     PUSHBUTTON "Exit", IDCANCEL,149,85,60,15
    23. END
    Текст приложения-клиента (10s.asm)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. SEMAPHORE_DATA_COUNT = 16
    4. SemaphoreObjectStruct struct
    5. hSemaphoreDataHigh dq SEMAPHORE_DATA_COUNT dup(?)
    6. hSemaphoreDataLow dq SEMAPHORE_DATA_COUNT dup(?)
    7. hSemaphoreAck dq ?
    8. SemaphoreObjectStruct ends
    9. IDC_DIALOG equ 200
    10. ID_TXT equ 100
    11. ID_ICON equ 102
    12. ID_PROGRESS equ 106
    13. IDC_ICON1 equ 500
    14. .code
    15. WinMain proc
    16. enter 30h,0
    17. mov r9d,offset DialogProc
    18. and qword ptr[rbp-10h],0
    19.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    20.         invoke  RtlExitUserProcess,NULL
    21. WinMain endp
    22. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    23. mov hWnddlg,rcx
    24. mov lParam,r9
    25.         cmp edx,WM_INITDIALOG
    26. jne wmBYE
    27. wmINITDIALOG:mov hWnd,rcx
    28.         mov edx,GWL_STYLE
    29. invoke GetWindowLongPtr
    30.     or eax,WS_THICKFRAME OR WS_MINIMIZEBOX OR WS_MAXIMIZEBOX
    31. mov edx,GWL_STYLE
    32. invoke SetWindowLongPtr,hWnddlg,,rax
    33. mov r8d,offset WndProc
    34. mov edx,GWL_WNDPROC
    35. invoke SetWindowLongPtr,hWnddlg
    36. ; Найти окно получателя
    37. mov edx,offset szWin
    38.         invoke  FindWindow,NULL
    39.         or      eax,eax
    40.         jnz @f;wmBYE
    41. mov edx,offset Error1
    42. mov r8d,offset szAppName
    43. invoke MessageBox,hWnddlg,,,MB_ICONEXCLAMATION or MB_YESNO
    44. cmp eax,IDNO
    45. jz      @f;wmBYE
    46. mov ecx,offset szService
    47. invoke WinExec,,SW_SHOW
    48. ; create "high" data event handles
    49. xor edi,edi;for(DWORD i = 0; i < ; i++)
    50. ; set current event name
    51. @@: invoke sprintf,&szSemaphoreName,&Format1,edi
    52. ; open existing object
    53. invoke OpenSemaphore,SEMAPHORE_ALL_ACCESS,0,&szSemaphoreName
    54. mov SemaphoreObject.hSemaphoreDataHigh[rdi*8],rax
    55. or eax,eax
    56. jz wmBYE
    57. invoke sprintf,&szSemaphoreName,&Format2,edi
    58. ; open existing object
    59. invoke OpenSemaphore,SEMAPHORE_ALL_ACCESS,0,&szSemaphoreName
    60. mov SemaphoreObject.hSemaphoreDataLow[rdi*8],rax
    61. ; check for errors
    62. or eax,eax;if(SemaphoreObject.hSemaphoreDataLow[i] == NULL)
    63. jz wmBYE
    64. inc edi
    65. cmp edi,SEMAPHORE_DATA_COUNT
    66. jb @b
    67. ; create acknowledgement event
    68. invoke OpenSemaphore,SEMAPHORE_ALL_ACCESS,0,&Format3
    69. mov SemaphoreObject.hSemaphoreAck,rax
    70. ;--------------------------------------------------
    71. ; Шрифт текста
    72. pushaddr szFont
    73. push FIXED_PITCH+FF_DONTCARE
    74. push PROOF_QUALITY
    75. push CLIP_DEFAULT_PRECIS
    76. push OUT_RASTER_PRECIS
    77. push ANSI_CHARSET
    78. push FALSE
    79. push FALSE
    80. push FALSE
    81. push FW_BOLD
    82. sub esp,20h
    83.         invoke  CreateFont,32,12,0,0
    84.         mov     hFont,rax
    85.         invoke  GetDlgItem,hWnddlg,ID_PROGRESS
    86.         mov     hProgress,rax
    87. ; Установить наш собственный обработчик
    88. mov r8d,offset ProgressWindowProc
    89.         invoke  SetWindowLongPtr,hProgress,GWL_WNDPROC
    90.         ; Сохранить дескриптор предыдущего обработчика
    91.         mov     OldProc,rax
    92. wmBYE: xor eax,eax
    93. leave
    94. retn
    95. DialogProc endp
    96. WndProc proc hWnd:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    97. local text:dword
    98. local ps:PAINTSTRUCT
    99. local hDC:dword
    100. local rcClient:RECT
    101. mov hWnd,rcx
    102. mov lParam,r9
    103. cmp edx,WM_CLOSE
    104. je wmCLOSE
    105. cmp edx,WM_COMMAND
    106. je wmCOMMAND
    107. cmp edx,WM_USER+1
    108. je wmUSER_1
    109. cmp edx,WM_USER+2
    110. je wmUSER_2
    111. cmp edx,WM_USER+3
    112. je wmUSER_3
    113. leave
    114. jmp NtdllDialogWndProc_
    115. ;-----------------------------------------------------
    116. wmUSER_1:mov rax,lParam
    117. mov DataLength,rax
    118. inc eax
    119. invoke GlobalAlloc,GPTR,eax
    120. mov p_Text,rax
    121. invoke SemaphoreRecieve,eax
    122. and byte ptr[rdi],0
    123.         invoke  SetDlgItemText,hWnd,ID_TXT,p_Text
    124. invoke GlobalFree,p_Text
    125. jmp wmBYE
    126. wmUSER_2:and percent,0
    127.         xor ecx,ecx
    128. mov [rsp+20h],rcx
    129. movr qword ptr[rsp+28h],hThread2
    130. mov r8d,offset TimerFuncProgress
    131. invoke CreateThread,,0,,13
    132. invoke CloseHandle,hThread2
    133. ;------------------------------------------------------
    134. mov rax,lParam
    135. mov DataLength,rax
    136. invoke GlobalAlloc,GPTR,eax
    137. xor ecx,ecx
    138. mov [rsp+20h],rcx
    139. movr qword ptr[rsp+28h],hThread3
    140. mov r8d,offset TimerFuncICO
    141. invoke CreateThread,,0,,eax
    142. invoke CloseHandle,hThread3
    143. jmp wmBYE
    144. wmUSER_3:and percent,0
    145.         xor ecx,ecx
    146. mov [rsp+20h],rcx
    147. movr qword ptr[rsp+28h],hThread4
    148. mov r8d,offset TimerFuncProgress
    149. invoke CreateThread,,0,,128
    150. invoke CloseHandle,hThread4
    151. ;-----------------------------------------------
    152. mov rax,lParam
    153. mov DataLength,rax
    154. invoke GlobalAlloc,GPTR,eax
    155. xor ecx,ecx
    156. mov [rsp+20h],rcx
    157. movr qword ptr[rsp+28h],hThread5
    158. mov r8d,offset TimerFuncWAV
    159. invoke CreateThread,,0,,eax
    160. invoke CloseHandle,hThread5
    161. jmp wmBYE
    162. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    163. jne wmBYE
    164. wmCLOSE:invoke EndDialog,,0
    165. ; Закрываем дескрипторы объектов-событий
    166. xor edi,edi
    167. @@: invoke CloseHandle,SemaphoreObject.hSemaphoreDataHigh[rdi*8]
    168. inc edi
    169. cmp edi,2*SEMAPHORE_DATA_COUNT+1
    170. jb @b
    171. wmBYE:  mov eax,TRUE
    172. exit0: leave
    173. ret
    174. WndProc endp
    175. TimerFuncICO proc p:qword
    176. mov p,rcx
    177. invoke SemaphoreRecieve
    178. ; Создать HICON напрямую из памяти
    179. and qword ptr[rsp+30h],LR_DEFAULTCOLOR;LR_DEFAULTCOLOR=0
    180. mov qword ptr[rsp+20h],256
    181. mov qword ptr[rsp+28h],256
    182. invoke  CreateIconFromResourceEx,p,DataLength,TRUE,30000h
    183. mov [rsp+20h],rax
    184. invoke  SendDlgItemMessage,hWnd,ID_ICON,STM_SETIMAGE,IMAGE_ICON
    185. invoke GlobalFree,p
    186. exit2: leave
    187. ret
    188. TimerFuncICO endp
    189. TimerFuncWAV proc p:qword
    190. local lpwiocb:WAVEHDR
    191. local hWaveOut:qword
    192. mov p,rcx
    193. invoke SemaphoreRecieve
    194. WAVE: mov r8,p
    195. ;"RIFF"+(File size)+(File Type Header)+(Format chunk marker)+(Length of format data) = 14h
    196.         add r8d,14h
    197.         lea ecx,hWaveOut
    198.         xor r9,r9
    199. mov [rsp+20h],r9
    200. mov qword ptr[rsp+28h],WAVE_ALLOWSYNC
    201.         or edx,WAVE_MAPPER
    202.         invoke waveOutOpen
    203. ; Подготавливаем заголовок для вывода
    204. lea edx,lpwiocb
    205. mov edi,edx
    206. xor eax,eax
    207. mov ecx,(sizeof WAVEHDR)/8
    208. rep stosq
    209. mov rax,p
    210. mov ecx,eax
    211. ;"RIFF"+(File size)+(File Type Header)+(Format chunk marker)+(Length of format data)+\
    212. ;(Type of format)+(Number of Channels)+(Sample Rate)+(Sample Rate*BitsPerSample*Channels/8)+\
    213. ;(BitsPerSample*Channels/8)+(Bits per sample)+(“data” chunk header)+(Size of the data section)=2Ch
    214. add eax,2Ch
    215. mov [rdx].WAVEHDR.lpData,rax ;адрес блока данных
    216. mov eax,[rcx+4];размер блока данных
    217. sub eax,2Ch
    218. mov [rdx].WAVEHDR.dwBufferLength,eax ;размер блока данных
    219. invoke waveOutPrepareHeader,hWaveOut,,sizeof WAVEHDR
    220. ; Запускаем проигрывание блока
    221. lea edx,lpwiocb
    222. mov rcx,hWaveOut
    223. mov r8d,sizeof WAVEHDR
    224. invoke waveOutWrite
    225. @@: test lpwiocb.dwFlags,WHDR_DONE
    226. jz @b
    227. lea edx,lpwiocb
    228. invoke waveOutUnprepareHeader,hWaveOut,,sizeof WAVEHDR
    229. invoke waveOutClose,hWaveOut
    230. @1: invoke GlobalFree,p
    231. exit2: leave
    232. ret
    233. TimerFuncWAV endp
    234. TimerFuncProgress proc lParam:qword
    235. mov lParam,rcx
    236. ; Сформировать строку для рисования
    237. @@: mov r8d,percent
    238. mov edx,offset szText
    239. mov ecx,offset buff
    240.         invoke  wsprintf
    241. ; Назначить строку свойством ProgressBar
    242. mov r8d,offset buff
    243. mov edx,offset szProp
    244.         invoke  SetProp,hProgress
    245. ; Назначить значение процента свойством ProgressBar
    246. mov r8d,percent
    247. mov edx,offset szPerc
    248.         invoke  SetProp,hProgress
    249. ; Перерисовать содержимое окна
    250.         invoke  InvalidateRect,hProgress,0,FALSE
    251.         inc     percent
    252.         cmp     percent,101
    253.         je exit0
    254. invoke Sleep,lParam
    255. jmp @b
    256. exit0: leave
    257. ret
    258. TimerFuncProgress endp
    259. SemaphoreRecieve proc p:qword
    260. local dwSemaphoreDataLowValue:byte
    261. mov edi,ecx
    262. add rcx,DataLength
    263. mov EndDataLength,ecx
    264. @@: lea edx,SemaphoreObject.hSemaphoreDataLow
    265. invoke WaitForMultipleObjects,SEMAPHORE_DATA_COUNT,,0,2
    266. cmp eax,SEMAPHORE_DATA_COUNT;if(dwSemaphoreDataLowValue >= SEMAPHORE_DATA_COUNT)
    267. jnb exit1
    268. ; wait for "high" data value
    269. mov dwSemaphoreDataLowValue,al
    270. lea edx,SemaphoreObject.hSemaphoreDataHigh
    271. invoke WaitForMultipleObjects,SEMAPHORE_DATA_COUNT,,0,0
    272. ; calculate byte value from high/low value
    273. shl al,4;dwSemaphoreDataHighValue * 16
    274. add al,dwSemaphoreDataLowValue
    275. ; store byte value
    276. stosb
    277. ; set acknowledgement event
    278. invoke ReleaseSemaphore,SemaphoreObject.hSemaphoreAck,1,0
    279. ;------------------------------------------------------------------
    280. ; increase ptr
    281. exit1: cmp edi,EndDataLength
    282. jb @b;for(DWORD i = 0; i < EndDataLength; i++)
    283. leave
    284. ret
    285. SemaphoreRecieve endp
    286. ProgressWindowProc proc hEdit:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    287. local text:dword
    288. local ps:PAINTSTRUCT
    289. local hDC:dword
    290. local rcClient:RECT
    291. mov hEdit,rcx
    292. mov uMsg,rdx
    293. mov wParam,r8
    294. mov lParam,r9
    295. cmp edx,WM_PAINT
    296. je wmPAINT
    297. mov [rsp+20h],r9;lParam
    298. mov r9,wParam
    299. mov r8,uMsg
    300. mov rdx,hEdit
    301.         invoke  CallWindowProc,OldProc
    302. jmp wmBYE
    303. wmPAINT:; Размеры окна
    304.         lea     edx,rcClient
    305.         invoke  GetClientRect,hEdit;,edi
    306.         ; Получить текст из свойств
    307. mov edx,offset szProp
    308.         invoke  GetProp,hEdit;hProgress
    309.         mov     text,eax
    310. ; Начать рисование
    311.         lea     edx,ps
    312.         invoke  BeginPaint,hEdit;hProgress
    313.         mov     hDC,eax
    314. ; Шрифт
    315.         invoke  SelectObject,hDC,hFont
    316.         invoke  SetBkMode,hDC,TRANSPARENT
    317. ; Нарисовать общий фон
    318.         invoke  GetSysColorBrush,COLOR_WINDOW
    319.         lea     edx,rcClient
    320.         invoke  FillRect,hDC,,eax
    321. ; Текст для рисования есть?
    322.         cmp     text,0
    323.         je      @f
    324.         invoke  GetSysColor,COLOR_WINDOWTEXT
    325.         invoke  SetTextColor,hDC,eax
    326. mov edx,offset buff
    327. mov qword ptr[rsp+20h],DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER or DT_CENTER
    328.         lea     r9d,rcClient
    329.         invoke  DrawText,hDC,,-1
    330. @@:; Вычислить размеры области для заливки
    331. mov edx,offset szPerc
    332.         invoke  GetProp,hEdit;hProgress
    333.         mov     ecx,eax
    334.         lea     r9d,rcClient
    335.         mov     eax,[r9].RECT.right
    336.         sub     eax,[r9].RECT.left
    337.         mul     ecx
    338.         xor     edx,edx
    339.         mov     ecx,100
    340.         div     ecx
    341. ; Позиция выполненного прогресса
    342.         add     eax,[r9].RECT.left
    343. ; Наложить выполненный прогресс
    344. mov ecx,[r9].RECT.left
    345. mov edx,[r9].RECT.top
    346. mov r9d,[r9].RECT.bottom
    347.         invoke  CreateRectRgn,,,eax
    348.         invoke  SelectClipRgn,hDC,eax
    349.         invoke  GetSysColorBrush,COLOR_HIGHLIGHT
    350. lea     edx,rcClient
    351.         invoke  FillRect,hDC,,eax
    352. ; Текст для рисования есть?
    353.         cmp     text,0
    354.         je      @f
    355.         invoke  GetSysColor,COLOR_HIGHLIGHTTEXT
    356.         invoke  SetTextColor,hDC,eax
    357. mov qword ptr[rsp+20h],DT_NOPREFIX or DT_SINGLELINE or DT_VCENTER or DT_CENTER
    358. mov edx,offset buff
    359.         lea     r9d,rcClient
    360.         invoke  DrawText,hDC,,-1
    361. @@: lea     edx,ps
    362.         invoke  EndPaint,hDC
    363. xor eax,eax
    364. wmBYE: leave
    365. retn
    366. ProgressWindowProc endp
    367. ;-----------------------------------------------------------------------
    368. .data
    369. hWnd dq ?
    370. Format1 db "Song_of_the_South_H%u",0
    371. Format2 db "Song_of_the_South_L%u",0
    372. Format3 db "Song_of_the_South_A",0
    373. p_Text dq ?
    374. p_ICO dq ?
    375. p_WAV dq ?
    376. szWin db "Semaphore Sender",0
    377. Error1 db "The server is not running.",10,"Run?",0
    378. szAppName db "Semaphore Reciever",0
    379. szService db "10s",0
    380. hThread2 dq ?
    381. hThread3 dq ?
    382. hThread4 dq ?
    383. hThread5 dq ?
    384. szSemaphoreName db 32 dup(?)
    385. buff db 100 dup(?)
    386. szText  db '%u%% completed',0
    387. percent dd 0
    388. hProgress dq ?
    389. hFont dq ?
    390. szProp db 'text',0
    391. szPerc db 'percent',0
    392. szFont db "Verdana",0
    393. OldProc dq ?
    394. align 16
    395. SemaphoreObject SemaphoreObjectStruct <>
    396. DataLength dq ?
    397. EndDataLength dd ?
    398. end
    ресурсы клиента (10r.rc)
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. #define ID_PROGRESS 106
    6. IDC_DIALOG DIALOG 0,0,212,154
    7. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    8. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    9. CAPTION "Semaphore Reciever"
    10. BEGIN
    11. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -3, 207, 24
    12. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,5,199,13
    13.         CONTROL "",ID_PROGRESS,"STATIC",WS_VISIBLE | 3 | WS_DISABLED | WS_BORDER,2,22,146,19
    14. DEFPUSHBUTTON  "Exit",IDCANCEL,149,25,60,15
    15.         CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,3,40,128,128
    16. END
    10.jpg
    в аттаче ICO/WAV/ASM/RC/EXE-файлы
     

    Вложения:

    • Semaphores.zip
      Размер файла:
      1,6 МБ
      Просмотров:
      84
  15. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Receiver.c
    Код (C):
    1.  
    2. #include <win/Common.h>
    3. #include <win/Manifest.h>
    4. #include <win/Window.h>
    5. #include <win/Dialog.h>
    6. #include <win/RichEdit.h>
    7. #include <rtl/memory.h>
    8. #include <rtl/string.h>
    9. #include <rtl/StaticLib.h>
    10. #include <win/StaticLib.h>
    11. #include "resource.h"
    12. /* -------------------------------------------------------------------------- */
    13. static LPCWSTR MUTEX_DATA = L"MtxData";
    14. static LPCWSTR EVENT_BEGIN_TRANSMISSION = L"EvBeginTransmission";
    15. static LPCWSTR EVENT_END_TRANSMISSION = L"EvEndTransmission";
    16. static LPCWSTR EVENT_RECEIVER_READY = L"EvReceiverReady";
    17. /* -------------------------------------------------------------------------- */
    18. typedef struct MainDialog
    19. {
    20.     HWND hwnd;
    21.     HWND hwndOutput;
    22.     HANDLE eventBegin;
    23.     HANDLE eventEnd;
    24.     HANDLE eventReceiverReady;
    25.     HANDLE eventStop;
    26.     HANDLE threadHandle;
    27.     DWORD threadId;
    28. }MainDialog;
    29. /* -------------------------------------------------------------------------- */
    30. static void AppendLine (HWND hwndOutput, LPCWSTR format, ...)
    31. {
    32.     va_list args;
    33.     wstring_t text;
    34.     CHARRANGE cr;
    35.     if (format && format[0])
    36.     {
    37.         va_start (args, format);
    38.         wstring_init (&text, NULL);
    39.         wstring_vformat (&text, format, args);
    40.         cr.cpMin = -1;
    41.         cr.cpMax = -1;
    42.         RichEdit_ExGetSel (hwndOutput, &cr);
    43.         Edit_ReplaceSel (hwndOutput, text.cstr);
    44.         wstring_clear (&text);
    45.     }
    46. }
    47. /* -------------------------------------------------------------------------- */
    48. static DWORD WINAPI ReceiveMessageThread (LPVOID param)
    49. {
    50.     MainDialog* dlg;
    51.     HANDLE handles[18];
    52.     wchar_t name[256];
    53.     uint32_t i, index;
    54.     string_t buffer;
    55.     wstring_t text;
    56.     uint8_t value;
    57.     dlg = (MainDialog*)param;
    58.     for (i=0; i<16; i++)
    59.     {
    60.         rtl_wsprintf (name, 256, L"%s:%u", MUTEX_DATA, i);
    61.         handles[i] = OpenMutexW (MUTEX_ALL_ACCESS, FALSE, name);
    62.         if (!handles[i])
    63.         {
    64.             while (i--)
    65.                 CloseHandle (handles[i]);
    66.             return 0;
    67.         }
    68.     }
    69.     handles[16] = dlg->eventEnd;
    70.     handles[17] = dlg->eventStop;
    71.     string_init (&buffer, NULL);
    72.     value = 0;
    73.     i = 0;
    74.     SetEvent (dlg->eventReceiverReady);
    75.     while (TRUE)
    76.     {
    77.         index = WaitForMultipleObjects (18, handles, FALSE, INFINITE);
    78.        
    79.         if (index >= WAIT_OBJECT_0 && index < WAIT_OBJECT_0 + 18)
    80.             index -= WAIT_OBJECT_0;
    81.         else if (index >= WAIT_ABANDONED_0 && index < WAIT_ABANDONED_0 + 18)
    82.             index -= WAIT_ABANDONED_0;
    83.         else
    84.             break;
    85.         if (index > 15)
    86.             break;
    87.         ReleaseMutex (handles[index]);
    88.         value = (value << 4) | (uint8_t)index;
    89.         if (i++)
    90.         {
    91.             string_append_data (&buffer, (const char*)&value, 1);
    92.             value = 0;
    93.             i = 0;
    94.         }
    95.     }
    96.     ResetEvent (dlg->eventReceiverReady);
    97.     if (!string_empty (&buffer))
    98.     {
    99.         wstring_init_data (&text, (const wchar_t*)buffer.cstr, buffer.length / sizeof(wchar_t));
    100.         AppendLine (dlg->hwndOutput, L"%s\n", text.cstr);
    101.         wstring_clear (&text);
    102.     }
    103.     string_clear (&buffer);
    104.     for (i=0; i<16; i++)
    105.         CloseHandle (handles[i]);
    106.     return 0;
    107. }
    108. /* -------------------------------------------------------------------------- */
    109. static DWORD WINAPI ReceiverThread (LPVOID param)
    110. {
    111.     MainDialog* dlg;
    112.     HANDLE threadHandle;
    113.     DWORD threadId;
    114.     HANDLE handles[2];
    115.     uint32_t index;
    116.     dlg = (MainDialog*)param;
    117.     handles[0] = dlg->eventBegin;
    118.     handles[1] = dlg->eventStop;
    119.     while (TRUE)
    120.     {
    121.         index = WaitForMultipleObjects (2, handles, FALSE, INFINITE);
    122.         if (index != 0)
    123.             break;
    124.         threadHandle = CreateThread (NULL, 0, ReceiveMessageThread, dlg, 0, &threadId);
    125.         if (threadHandle)
    126.         {
    127.             WaitForSingleObject (threadHandle, INFINITE);
    128.             CloseHandle (threadHandle);
    129.         }
    130.     }
    131.     return 0;
    132. }
    133. /* -------------------------------------------------------------------------- */
    134. static BOOL OnInitDialog (MainDialog* dlg, HWND hwndFocus, LPARAM lParam)
    135. {
    136.     Dialog_EnableTabTexture (dlg->hwnd);
    137.     dlg->hwndOutput = GetDlgItem (dlg->hwnd, IDC_OUTPUT);
    138.     dlg->eventStop = CreateEvent (NULL, TRUE, FALSE, NULL);
    139.     dlg->eventBegin = CreateEventW (NULL, TRUE, FALSE, EVENT_BEGIN_TRANSMISSION);
    140.     dlg->eventEnd = CreateEventW (NULL, TRUE, TRUE, EVENT_END_TRANSMISSION);
    141.     dlg->eventReceiverReady = CreateEventW (NULL, TRUE, FALSE, EVENT_RECEIVER_READY);
    142.     dlg->threadHandle = CreateThread (NULL, 0, ReceiverThread, dlg, 0, &dlg->threadId);
    143.     return TRUE;
    144. }
    145. /* -------------------------------------------------------------------------- */
    146. static void OnCommand (MainDialog* dlg, int id, HWND hwndCtl, UINT codeNotify)
    147. {
    148.     switch (id)
    149.     {
    150.     case IDCANCEL:
    151.         if (codeNotify == BN_CLICKED)
    152.             EndDialog (dlg->hwnd, 0);
    153.         break;
    154.     }
    155. }
    156. /* -------------------------------------------------------------------------- */
    157. static void OnDestroy (MainDialog* dlg)
    158. {
    159.     SetEvent (dlg->eventStop);
    160.     if (dlg->threadHandle)
    161.     {
    162.         WaitForSingleObject (dlg->threadHandle, INFINITE);
    163.         CloseHandle (dlg->threadHandle);
    164.     }
    165.     CloseHandle (dlg->eventStop);
    166.     CloseHandle (dlg->eventBegin);
    167.     CloseHandle (dlg->eventEnd);
    168.     CloseHandle (dlg->eventReceiverReady);
    169.     Window_RemoveStruct (dlg->hwnd);
    170. }
    171. /* -------------------------------------------------------------------------- */
    172. static INT_PTR WINAPI DlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    173. {
    174.     MainDialog* dlg;
    175.     dlg = Window_EnterWndProc (MainDialog, hwnd, msg, wParam, lParam);
    176.     if (dlg)
    177.     {
    178.         switch (msg)
    179.         {
    180.             HANDLE_MSG (dlg, WM_INITDIALOG, OnInitDialog);
    181.             HANDLE_MSG (dlg, WM_COMMAND, OnCommand);
    182.             HANDLE_MSG (dlg, WM_DESTROY, OnDestroy);
    183.         }
    184.     }
    185.     return FALSE;
    186. }
    187. /* -------------------------------------------------------------------------- */
    188. int WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
    189. {
    190.     INITCOMMONCONTROLSEX icc;
    191.     icc.dwSize = sizeof(icc);
    192.     icc.dwICC = ICC_STANDARD_CLASSES;
    193.     InitCommonControlsEx (&icc);
    194.     RichEdit_Initialize();
    195.     DialogBoxParam (GetModuleHandle (NULL), MAKEINTRESOURCE (IDD_MAIN), NULL, DlgProc, 0l);
    196.     return 0;
    197. }
    198. /* -------------------------------------------------------------------------- */
    199.  
    Transmitter.c
    Код (C):
    1.  
    2. #include <win/Common.h>
    3. #include <win/Manifest.h>
    4. #include <win/Window.h>
    5. #include <win/Dialog.h>
    6. #include <win/Edit.h>
    7. #include <rtl/memory.h>
    8. #include <rtl/string.h>
    9. #include <rtl/StaticLib.h>
    10. #include <win/StaticLib.h>
    11. #include "resource.h"
    12. /* -------------------------------------------------------------------------- */
    13. static LPCWSTR MUTEX_DATA = L"MtxData";
    14. static LPCWSTR EVENT_BEGIN_TRANSMISSION = L"EvBeginTransmission";
    15. static LPCWSTR EVENT_END_TRANSMISSION = L"EvEndTransmission";
    16. static LPCWSTR EVENT_RECEIVER_READY = L"EvReceiverReady";
    17. /* -------------------------------------------------------------------------- */
    18. typedef struct MainDialog
    19. {
    20.     HWND hwnd;
    21.     HWND hwndMessage;
    22.     HANDLE mutexes[16];
    23.     HANDLE eventBegin;
    24.     HANDLE eventEnd;
    25.     HANDLE eventReceiverReady;
    26. }MainDialog;
    27. /* -------------------------------------------------------------------------- */
    28. static void CreateSyncObjects (MainDialog* dlg)
    29. {
    30.     wchar_t name[256];
    31.     uint32_t i;
    32.     for (i=0; i<16; i++)
    33.     {
    34.         rtl_wsprintf (name, 256, L"%s:%u", MUTEX_DATA, i);
    35.         dlg->mutexes[i] = CreateMutexW (NULL, TRUE, name);
    36.     }
    37.     dlg->eventBegin = CreateEventW (NULL, TRUE, FALSE, EVENT_BEGIN_TRANSMISSION);
    38.     dlg->eventEnd = CreateEventW (NULL, TRUE, TRUE, EVENT_END_TRANSMISSION);
    39.     dlg->eventReceiverReady = CreateEventW (NULL, TRUE, FALSE, EVENT_RECEIVER_READY);
    40. }
    41. /* -------------------------------------------------------------------------- */
    42. static void CloseSyncObjects (MainDialog* dlg)
    43. {
    44.     uint32_t i;
    45.     SetEvent (dlg->eventEnd);
    46.     CloseHandle (dlg->eventBegin);
    47.     CloseHandle (dlg->eventEnd);
    48.     CloseHandle (dlg->eventReceiverReady);
    49.     for (i=0; i<16; i++)
    50.         CloseHandle (dlg->mutexes[i]);
    51. }
    52. /* -------------------------------------------------------------------------- */
    53. static void SendData (MainDialog* dlg, LPCVOID data, uint32_t size)
    54. {
    55.     uint8_t* ptr;
    56.     if (data && size)
    57.     {
    58.         ResetEvent (dlg->eventEnd);
    59.         SetEvent (dlg->eventBegin);
    60.         if (WaitForSingleObject (dlg->eventReceiverReady, 5000) == WAIT_OBJECT_0)
    61.         {
    62.             for (ptr = (uint8_t*)data; size; ptr++, size--)
    63.             {
    64.                 ReleaseMutex (dlg->mutexes[(*ptr) >> 4]);
    65.                 WaitForSingleObject (dlg->mutexes[(*ptr) >> 4], INFINITE);
    66.                 ReleaseMutex (dlg->mutexes[(*ptr) & 0x0F]);
    67.                 WaitForSingleObject (dlg->mutexes[(*ptr) & 0x0F], INFINITE);
    68.             }
    69.         }
    70.         ResetEvent (dlg->eventBegin);
    71.         SetEvent (dlg->eventEnd);
    72.     }
    73. }
    74. /* -------------------------------------------------------------------------- */
    75. static void OnSendMessage (MainDialog* dlg)
    76. {
    77.     wstring_t text;
    78.     wstring_init (&text, NULL);
    79.     Edit_GetTextW (dlg->hwndMessage, &text);
    80.     SendData (dlg, text.cstr, text.length * sizeof(wchar_t));
    81.     wstring_clear (&text);
    82.     SetWindowTextW (dlg->hwndMessage, L"");
    83.     SetFocus (dlg->hwndMessage);
    84. }
    85. /* -------------------------------------------------------------------------- */
    86. static BOOL OnInitDialog (MainDialog* dlg, HWND hwndFocus, LPARAM lParam)
    87. {
    88.     Dialog_EnableTabTexture (dlg->hwnd);
    89.     dlg->hwndMessage = GetDlgItem (dlg->hwnd, IDC_MESSAGE);
    90.     CreateSyncObjects (dlg);
    91.     return TRUE;
    92. }
    93. /* -------------------------------------------------------------------------- */
    94. static void OnCommand (MainDialog* dlg, int id, HWND hwndCtl, UINT codeNotify)
    95. {
    96.     switch (id)
    97.     {
    98.     case IDCANCEL:
    99.         if (codeNotify == BN_CLICKED)
    100.             EndDialog (dlg->hwnd, 0);
    101.         break;
    102.     case IDC_SEND:
    103.         OnSendMessage (dlg);
    104.         break;
    105.     }
    106. }
    107. /* -------------------------------------------------------------------------- */
    108. static void OnDestroy (MainDialog* dlg)
    109. {
    110.     CloseSyncObjects (dlg);
    111.     Window_RemoveStruct (dlg->hwnd);
    112. }
    113. /* -------------------------------------------------------------------------- */
    114. static INT_PTR WINAPI DlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    115. {
    116.     MainDialog* dlg;
    117.     dlg = Window_EnterWndProc (MainDialog, hwnd, msg, wParam, lParam);
    118.     if (dlg)
    119.     {
    120.         switch (msg)
    121.         {
    122.             HANDLE_MSG (dlg, WM_INITDIALOG, OnInitDialog);
    123.             HANDLE_MSG (dlg, WM_COMMAND, OnCommand);
    124.             HANDLE_MSG (dlg, WM_DESTROY, OnDestroy);
    125.         }
    126.     }
    127.     return FALSE;
    128. }
    129. /* -------------------------------------------------------------------------- */
    130. int WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
    131. {
    132.     INITCOMMONCONTROLSEX icc;
    133.     icc.dwSize = sizeof(icc);
    134.     icc.dwICC = ICC_STANDARD_CLASSES;
    135.    
    136.     InitCommonControlsEx (&icc);
    137.     DialogBoxParam (GetModuleHandle (NULL), MAKEINTRESOURCE (IDD_MAIN), NULL, DlgProc, 0l);
    138.     return 0;
    139. }
    140. /* -------------------------------------------------------------------------- */
    141.  
     

    Вложения:

    • MutexIPC.rar
      Размер файла:
      56,6 КБ
      Просмотров:
      85
  16. Mikl___

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

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

    09. Mutexs

    При необходимости обеспечения последовательного использования ресурсов задачами, созданными в рамках разных процессов, вместо критических секций используют объекты синхронизации Mutex (mutually exclusive ― взаимно исключающий).
    Объект Mutex может находится в сигнальном или несигнальном состоянии. Когда задача, принадлежащая любому процессу, становится владельцем объекта Mutex, он переключается в несигнальное состояние. Если задача «отказывается» от владения Mutex, его состояние ― сигнальное.
    Организация последовательного доступа к ресурсам с использованием Mutex возможна потому, что в каждый момент только одна задача может владеть этим объектом. Все остальные задачи для того чтобы завладеть объектом, который уже захвачен, должны ждать, с помощью функции WaitForSingleObject.
    Чтобы Mutex был доступен задачам, принадлежащим различным процессам, при создании ему присваивается имя (аналогично тому, как это делают для объекта-события или семафора).
    Объект Mutex находится в сигнальном или несигнальном состоянии до тех пор, пока последняя программа, использующая Mutex, не закроет его дескриптор, поэтому Mutex может оставаться в памяти и после того, как исходное приложение, создавшее его, завершило работу. Поскольку Mutex широко используется, Mutex'у должны быть предоставлены явные разрешения, позволяющие любому процессу использовать его.
    Создание Mutex
    Для создания Mutex используют CreateMutex,
    Код (C):
    1. HANDLE CreateMutex(
    2.   LPSECURITY_ATTRIBUTES lpMutexAttributes, // атрибуты защиты
    3.   BOOL bInitialOwner, // начальное состояние
    4.   LPCTSTR lpName);    // имя объекта Mutex
    • В качестве lpMutexAttributes можно указать NULL либо права Mutex нужно указывать явным образом. В случае lpMutexAttributes=0 права, которые получит Mutex будут зависеть от прав того, кто этот Mutex создает
      ВладелецПраваhex
      СистемаMUTEX_ALL_ACCESS1F0001
      администраторыMUTEX_ALL_ACCESS1F0001
      все остальныеSYNCHRONIZE | READ_CONTROL | MUTEX_QUERY_STATE120001
      Приложению, желающему отправлять отладочные сообщения, требуется только возможность дождаться и захватить Mutex, и это представлено правом SYNCHRONIZE.
    • bInitialOwner ― начальное состояние Mutex.
      • Если bInitialOwner=TRUE, задача, создающая Mutex, будет им владеть сразу после создания.
      • Если bInitialOwner=FALSE, после создания Mutex не будет принадлежать ни одной задаче, пока не будет захвачен ими явным образом.
    • lpName ― указатель на имя Mutex, действуют те же правила, что и для имени объекта-события. Имя не должно содержать символ «\», его длина не должна превышать значение MAX_PATH.
    Если Mutex будет использован задачами только одного процесса, вместо lpName можно указать NULL ― создается «безымянный» Mutex.
    CreateMutex возвращает дескриптор созданного Mutex или NULL при ошибке.
    Когда приложение пытается создать Mutex с именем, которое уже используется в системе другим Mutex, тогда CreateMutex вернет дескриптор существующего объекта Mutex, а GetLastError, вызванная сразу после вызова функции CreateMutex, вернет значение ERROR_ALREADY_EXISTS.
    Если при вызове CreateMutex именованный Mutex уже существует и захвачен другим потоком, функция возвращает управление сразу, не дожидаясь его освобождения, даже если параметр bInitialOwner =TRUE. Если, по логике кода, создающий Mutex поток должен стать его владельцем, необходимо явно вызвать WaitForSingleObject, если GetLastError вернула ERROR_ALREADY_EXISTS
    Функция создания объектов-событий CreateEvent ведет себя в данной ситуации аналогично.

    Освобождение дескриптора Mutex

    Если Mutex больше не нужен, нужно освободить его дескриптор при помощи CloseHandle. При завершении процесса освобождаются дескрипторы всех Mutex, созданных для него.
    Если ни одно приложение не владеет объектом Mutex, функция WaitForSingleObject возвращает значение WAIT_OBJECT_0. В том случае когда какое-либо приложение владеет объектом Mutex, данное приложение перейдет в состояние ожидания.
    После окончания потребности в Mutex приложение переводит объект Mutex в несигнальное состояние с помощью функции ReleaseMutex

    Открытие Mutex

    Зная имя Mutex (lpszMutexName), можно его открыть с помощью OpenMutex,
    Код (C):
    1. HANDLE OpenMutex(
    2.   DWORD   fdwAccess, // требуемый доступ
    3.   BOOL    fInherit,  // флаг наследования
    4.   LPCTSTR lpszMutexName ); // адрес имени Mutex
    Флаги доступа, передаваемые через параметр fdwAccess, определяют требуемый уровень доступа к Mutex. Параметр может быть комбинацией значений:
    ЗначениеhexОписание
    MUTEX_ALL_ACCESS1F0001Указаны все возможные флаги доступа. полный доступ (разрешены все возможные виды доступа) Доступ к объекту Mutex. Для использования Mutex требуется только право доступа SYNCHRONIZE; чтобы изменить безопасность Mutex, укажите MUTEX_ALL_ACCESS. Функция завершается ошибкой, если дескриптор безопасности указанного объекта не разрешает запрошенный доступ для вызывающего процесса.
    MUTEX_MODIFY_STATE
    1​
    определяет возможность изменения значение счетчика Mutex функцией Release
    CREATE_MUTEX_INITIAL_OWNER
    1​
    Полученный дескриптор можно будет использовать в любых функциях ожидания события
    DELETE
    10000​
    Разрешено удаление объекта
    READ_CONTROL
    20000​
    Разрешено чтение информации в дескрипторе безопасности для объекта, не включая информацию в SACL (System Access Control List ― список управления доступом к объектам). Для чтения или записи SACL необходимо запросить право доступа ACCESS_SYSTEM_SECURITY.
    WRITE_DAC
    40000​
    Разрешено изменение DACL (Discretionary Access Control List — список избирательного управления доступом, контролируемый владельцем объекта и регламентирующий права пользователей и групп на действия с объектом: чтение, запись, удаление и т.д.) в дескрипторе безопасности для объекта
    WRITE_OWNER
    80000​
    Разрешено изменение владельца в дескрипторе безопасности объекта
    SYNCHRONIZE100000позволяет использовать дескриптор объекта Mutex в любой из функций ожидания
    Параметр fInherit определяет возможность наследования полученного дескриптора.
    • Если fInherit=TRUE, дескриптор наследуется дочерними процессами
    • Если fInherit=FALSE, наследование не допускается
    Через параметр lpszEventName передают OpenMutex адрес символьной строки, содержащей имя объекта Mutex
    С помощью функции OpenMutex несколько задач могут открыть один и тот же объект Mutex и затем выполнять одновременное ожидание для этого объекта.
    Функция OpenMutex завершается ошибкой, если объект Mutex с указанным именем не существует.

    Как завладеть Mutex?

    Зная дескриптор Mutex, полученный от CreateMutex или OpenMutex, задача может завладеть объектом при помощи функций ожидания событий
    • для одного объекта:
      • SignalObjectAndWait
      • WaitForSingleObject
      • WaitForSingleObjectEx
    • для нескольких объектов:
      • WaitForMultipleObjects
      • WaitForMultipleObjectsEx
      • MsgWaitForMultipleObjects
      • MsgWaitForMultipleObjectsEx
    Любой поток с дескриптором для объекта Mutex может использовать одну из функций ожидания для запроса владения объектом Mutex. Если объект Mutex принадлежит другому потоку, функция ожидания блокирует запрашивающий поток, пока собственный поток не выпустит объект Mutex с помощью функции ReleaseMutex.
    Функция WaitForSingleObject возвращает управление, как только дескриптор объекта, передаваемый ей в качестве параметра, перейдет в сигнальное состояние. Если Mutex не принадлежит ни одной задаче, его состояние будет сигнальным.
    При вызове функцию WaitForSingleObject для Mutex, который никому не принадлежит, WaitForSingleObject сразу возвращает управление. Задача, вызвавшая функцию WaitForSingleObject, становится владельцем Mutex. Если другая задача вызовет функцию WaitForSingleObject для этого Mutex, то она будет переведена в состояние ожидания до тех пор, пока первая задача не «откажется от своих прав» на данный Mutex. Освобождение Mutex выполняется функцией ReleaseMutex.
    Захват Mutex аналогичен входу в критическую секцию.

    Освобождение Mutex

    Для отказа от владения Mutex (для его освобождения) используется функция ReleaseMutex:
    Код (C):
    1. BOOL ReleaseMutex(HANDLE  hMutex);
    Единственный параметр этой функции ― дескриптор Mutex. Функция возвращает TRUE при успешном завершении и FALSE при ошибке.
    Освобождение Mutex соответствует выходу из критической секции.

    Рекурсивное использование Mutex

    Объекты Mutex допускают рекурсивное использование. Задача может выполнять рекурсивные попытки завладеть одним и тем же Mutex и при этом она не будет переводиться в состояние ожидания.
    В случае рекурсивного использования каждому вызову функции ожидания должен соответствовать вызов функции освобождения Mutex ReleaseMutex.
    Функция ReleaseMutex уменьшает счетчик рекурсии в объекте Mutex на 1. Если данный объект передавался во владение потоку неоднократно, поток обязан вызвать ReleaseMutex столько раз, сколько необходимо для обнуления счетчика рекурсии. Как только счетчик станет равен 0, переменная, хранящая идентификатор потока, тоже обнулится, и объект Mutex освободится. После этого система проверит, ожидают ли освобождения Mutex какие-нибудь другие потоки. Если да, система «по-честному» выберет один из ждущих потоков и передаст ему во владение объект Mutex.

    Уничтожение Mutex

    Для уничтожения Mutex его дескриптор передается CloseHandle. При завершении процесса все созданные им Mutex'ы не уничтожаются автоматически, а «висят» в памяти.

    Благодарности

    Огромное спасибо rmn за подсказки и замечания :yes3:

    Блин #1 (неудачная реализация)

    Сделал, но передача через Mutex (в отличие от событий и семафоров) работает крайне неустойчиво, даже при передаче текстовой строки возможно появление неверных символов, чего уж мечтать о передаче картинок или звукового файла. Кнопку «Send Text» нужно нажать несколько раз, прежде чем появится заданный текст.
    Текст приложения-сервера (09s.asm)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. ID_TXT equ 100
    4. ID_SEND_TXT equ 101
    5. IDC_DIALOG equ 200
    6. IDC_ICON1 equ 500
    7. IDC_IMG1 equ 104
    8. MUTEX_DATA_COUNT = 16
    9. size_of_buffer = 96
    10. MUTEX_ALL_ACCESS equ 1F0001h
    11. .code
    12. WinMain proc
    13. enter 30h,0
    14. mov r9d,256;cx
    15. mov [rbp-10h],r9
    16. mov qword ptr [rbp-8],LR_DEFAULTCOLOR
    17. invoke LoadImage,IMAGE_BASE,IDC_ICON1,IMAGE_ICON;,256,256,LR_DEFAULTCOLOR
    18. mov r9d,offset DialogProc
    19. mov qword ptr[rbp-10h],rax;30h-10h=+20h
    20. invoke DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    21. invoke RtlExitUserProcess,NULL
    22. WinMain endp
    23. DialogProc proc hWnddlg:QWORD,uMsg:QWORD,wParam:QWORD,lParam:QWORD
    24. local MutexName[256]:word
    25. local SizeString:dword
    26. mov hWnddlg,rcx
    27. mov lParam,r9
    28. cmp edx,WM_INITDIALOG
    29. je wmINITDIALOG
    30. cmp edx,WM_CLOSE
    31. je wmCLOSE
    32. cmp edx,WM_COMMAND
    33. je wmCOMMAND
    34. cmp edx,WM_DESTROY
    35. je wmDESTROY
    36. xor eax,eax
    37. jmp exit0
    38. wmINITDIALOG:mov hWnd,rcx
    39. invoke GetDlgItem,,IDC_IMG1
    40. invoke SendMessage,eax,STM_SETIMAGE,IMAGE_ICON,lParam
    41. ;Create Sync Objects
    42. xor edi,edi
    43. @@: lea ecx,MutexName
    44. mov edx,offset fmt
    45. invoke wsprintfW,,,edi
    46. lea r8d,MutexName
    47. invoke CreateMutexW,0,TRUE
    48. mov mutexes[rdi*8],rax
    49. inc edi
    50. cmp edi,MUTEX_DATA_COUNT
    51. jb @b
    52. mov r9d,offset EVENT_BEGIN_TRANSMISSION
    53. invoke CreateEventW,NULL,TRUE,FALSE
    54. mov eventBegin,rax
    55. mov r9d,offset EVENT_END_TRANSMISSION
    56. invoke CreateEventW,NULL,TRUE,TRUE
    57. mov eventEnd,rax
    58. mov r9d,offset EVENT_RECEIVER_READY
    59. invoke CreateEventW,NULL,TRUE,FALSE
    60. mov eventReceiverReady,rax
    61. jmp wmBYE
    62. wmSEND_TXT:lea r8d,MutexName
    63. invoke GetDlgItemText,hWnd,ID_TXT,,256
    64. mov SizeString,eax
    65. ;Send Data--------------------------------------
    66. invoke ResetEvent,eventEnd
    67. invoke SetEvent,eventBegin
    68. invoke WaitForSingleObject,eventReceiverReady,5000
    69.         cmp eax,WAIT_OBJECT_0
    70. jnz @0
    71.  
    72.         lea esi,MutexName
    73. @@: movzx edi,byte ptr[rsi]
    74. shr edi,4
    75. invoke ReleaseMutex,mutexes[rdi*8]
    76. invoke WaitForSingleObject,mutexes[rdi*8],INFINITE
    77. movzx edi,byte ptr[rsi]
    78. and edi,0Fh
    79. invoke ReleaseMutex,mutexes[rdi*8]
    80. invoke WaitForSingleObject,mutexes[rdi*8],INFINITE
    81.         inc esi
    82. dec SizeString
    83. jnz @b
    84. @0: invoke ResetEvent,eventBegin
    85.        invoke SetEvent,eventEnd
    86.         jmp wmBYE
    87. wmDESTROY:;Close Sync Objects
    88.        invoke SetEvent,eventEnd
    89.        invoke CloseHandle,eventBegin
    90.        invoke CloseHandle,eventEnd
    91.        invoke CloseHandle,eventReceiverReady
    92.        xor edi,edi
    93. @@: invoke CloseHandle,mutexes[rdi*8]
    94.        inc edi
    95.        cmp edi,MUTEX_DATA_COUNT
    96.        jb @b
    97.        jmp wmBYE
    98. ; ---------------------------------------------------------------------------
    99. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + ID_SEND_TXT
    100.         je      wmSEND_TXT
    101. cmp     r8d,BN_CLICKED shl 16 + IDCANCEL
    102.         jne     wmBYE
    103. wmCLOSE:invoke EndDialog,,0
    104. wmBYE: mov eax,TRUE
    105. exit0: leave
    106. retn
    107. DialogProc endp
    108. ;---------------------------------------
    109. .data
    110. szWin db "Mutex Reciever",0
    111. hWnd dq ?
    112. align 10h
    113. EVENT_BEGIN_TRANSMISSION dw "E","v","B","e","g","i","n","T","r","a","n","s","m","i","s","s","i","o","n",0
    114. EVENT_END_TRANSMISSION dw "E","v","E","n","d","T","r","a","n","s","m","i","s","s","i","o","n",0
    115. EVENT_RECEIVER_READY dw "E","v","R","e","c","e","i","v","e","r","R","e","a","d","y",0
    116. fmt dw "M","t","x","D","a","t","a",":","%","u",0
    117. mutexes dq 16 dup(?)
    118. eventBegin dq ?
    119. eventEnd dq ?
    120. eventReceiverReady dq ?
    121. end
    ресурсы сервера (09s.rc)
    Код (C):
    1. #include "resource.h"
    2. #define ID_TXT 100
    3. #define ID_SEND_TXT 101
    4. #define IDC_IMG1 104
    5. #define IDC_DIALOG 200
    6. #define IDC_ICON1 500
    7. IDC_ICON1 ICON "..\\Images\\icon1.ico"
    8. IDC_DIALOG DIALOG 0, 0, 212, 140
    9. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    10. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    11. CAPTION "Mutex Sender"
    12. BEGIN
    13.     CONTROL     "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    14.     CONTROL "",IDC_IMG1,"Static",WS_CHILDWINDOW|WS_VISIBLE|SS_ICON,5,23,128,128
    15.     CONTROL "Write something and click 'Send Text'",ID_TXT,"EDIT",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    16.     DEFPUSHBUTTON "Send Text",ID_SEND_TXT,149,27,60,15
    17.     PUSHBUTTON "Exit", IDCANCEL,149,85,60,15
    18. END
    Текст приложения-клиента (09r.asm)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. MUTEX_DATA_COUNT = 16
    4. MUTEX_ALL_ACCESS = 1F0001h
    5. size_of_buffer = 96
    6. IDC_DIALOG equ 200
    7. ID_TXT equ 100
    8. ID_ICON equ 102
    9. ID_PROGRESS equ 106
    10. IDC_ICON1 equ 500
    11. .code
    12. WinMain proc
    13. enter 30h,0
    14. mov r9d,offset DialogProc
    15. and qword ptr[rbp-10h],0
    16.         invoke  DialogBoxParam,IMAGE_BASE,IDC_DIALOG,HWND_DESKTOP
    17.         invoke  RtlExitUserProcess,NULL
    18. WinMain endp
    19. DialogProc proc hWnddlg:qword,msg:qword,wParam:qword,lParam:qword
    20. mov hWnddlg,rcx
    21. mov lParam,r9
    22.         cmp edx,WM_INITDIALOG
    23. je wmINITDIALOG
    24. cmp edx,WM_CLOSE
    25. je wmCLOSE
    26. cmp edx,WM_COMMAND
    27. je wmCOMMAND
    28. cmp edx,WM_DESTROY
    29. je wmDESTROY
    30. xor eax,eax
    31. jmp exit0
    32. wmINITDIALOG:mov hWnd,rcx
    33. ; Найти окно получателя
    34. mov edx,offset szWin
    35.         invoke  FindWindow,NULL
    36.         or      eax,eax
    37.         jnz @f;wmBYE
    38. mov edx,offset Error1
    39. mov r8d,offset szAppName
    40. invoke MessageBox,hWnddlg,,,MB_ICONEXCLAMATION or MB_YESNO
    41. cmp eax,IDNO
    42. jz      @f
    43. mov ecx,offset szService
    44. invoke WinExec,,SW_SHOW
    45. @@: invoke CreateEvent,NULL, TRUE, FALSE, NULL
    46. mov eventStop,rax
    47. mov r9d,offset EVENT_BEGIN_TRANSMISSION
    48. invoke CreateEventW,NULL, TRUE, FALSE
    49. mov eventBegin,rax
    50. mov r9d,offset EVENT_END_TRANSMISSION
    51. invoke CreateEventW,NULL, TRUE, TRUE
    52. mov eventEnd,rax
    53. mov r9d,offset EVENT_RECEIVER_READY
    54. invoke CreateEventW,NULL, TRUE, FALSE
    55. mov eventReceiverReady,rax
    56. movr qword ptr[rsp+28h],threadId
    57. xor ecx,ecx
    58. mov [rsp+20h],rcx
    59. mov r8d,offset ReceiverThread
    60. invoke CreateThread,,0,,0
    61. mov threadHandle,rax
    62. jmp wmBYE
    63. wmDESTROY:invoke SetEvent,eventStop
    64. cmp threadHandle,0
    65. jz @f ; dlg->eventStop
    66. invoke WaitForSingleObject,threadHandle,INFINITE
    67. invoke CloseHandle,threadHandle
    68. @@: invoke CloseHandle,eventStop
    69. invoke CloseHandle,eventBegin
    70. invoke CloseHandle,eventEnd
    71. invoke CloseHandle,eventReceiverReady
    72. jmp wmBYE
    73. wmCOMMAND:cmp r8d,BN_CLICKED shl 16 + IDCANCEL
    74. jne wmBYE
    75. wmCLOSE:invoke EndDialog,,0
    76. wmBYE: mov eax,TRUE
    77. exit0: leave
    78. retn
    79. DialogProc endp
    80. ReceiverThread proc
    81. local threadHandle:qword
    82. local threadId:qword
    83. local handles[2]:qword
    84. local index:dword
    85. mov rax,eventBegin
    86. mov handles[0*8],rax
    87. mov rax,eventStop
    88. mov handles[1*8],rax
    89. @@: lea edx,handles
    90. invoke WaitForMultipleObjects,2,,FALSE,INFINITE
    91. mov index,eax
    92. or eax,eax
    93. jnz exit0
    94.         lea eax,threadId
    95. mov [rsp+28h],rax
    96. xor ecx,ecx
    97. mov [rsp+20h],rcx
    98. mov r8d,offset ReceiveMessageThread
    99. invoke CreateThread,,0,,0
    100. mov threadHandle,rax
    101. or eax,eax
    102. jz @0;if (threadHandle)
    103. invoke WaitForSingleObject,eax, INFINITE
    104. invoke CloseHandle,threadHandle
    105. @0: lea edx,handles
    106. invoke WaitForMultipleObjects,2,,FALSE,INFINITE
    107. or eax,eax
    108. jz @b
    109. exit0: leave
    110. xor eax,eax
    111. ret
    112. ReceiverThread endp
    113. ReceiveMessageThread proc
    114. local handles[18]:qword
    115. local MutexName[256]:word
    116. local index:byte
    117. local value:byte
    118. local buffer[256]:byte
    119. local count:dword
    120. lea edi,buffer
    121. xor eax,eax
    122. mov ecx,256/8
    123. rep stosq
    124. xor edi,edi
    125. @@: lea ecx,MutexName
    126. mov edx,offset fmt
    127. invoke wsprintfW,,,edi
    128. lea r8d,MutexName
    129. invoke OpenMutexW,MUTEX_ALL_ACCESS,FALSE
    130. mov handles[rdi*8],rax
    131. or eax,eax
    132. jz @3
    133. inc edi
    134. cmp edi,MUTEX_DATA_COUNT
    135. jb @b
    136.  
    137. mov rax,eventEnd
    138. mov handles[16*8],rax
    139. mov rax,eventStop
    140. mov handles[17*8],rax
    141. and count,0
    142. and value,0
    143. xor esi,esi
    144. invoke SetEvent,eventReceiverReady
    145. @2: lea edx,handles
    146. invoke WaitForMultipleObjects,18,,FALSE,INFINITE
    147. mov index,al
    148.         cmp al,WAIT_OBJECT_0 + 18
    149. jb @f
    150. sub index,WAIT_ABANDONED_0
    151.         cmp index, 17
    152. ja break
    153. @@:     cmp index, 15
    154. ja break
    155. movzx eax,index
    156. invoke ReleaseMutex,handles[rax*8]
    157. mov al,value
    158. shl al,4
    159. or al,index
    160. mov value,al;value = (value << 4) | index
    161. mov ecx,esi
    162. inc esi
    163. test ecx,ecx
    164. jz @2
    165. mov ecx,count
    166. ;----------------------------------------------
    167. mov edx,-17
    168. sub edx,eax
    169. cmp edx,1
    170. jb @f
    171. mov eax,count
    172. mov dl,value
    173. mov buffer[rax],dl
    174. inc count
    175. @@: and value,0
    176. xor esi,esi
    177. jmp @2
    178. ;--------------------------------------------------
    179. @3: or esi,esi
    180. jz exit0;if (!handles[i])
    181. @@: dec esi;while (i--)
    182. invoke CloseHandle,handles[rsi*8]
    183. or esi,esi
    184. jnz @b
    185. jmp exit0
    186. break: invoke ResetEvent,eventReceiverReady
    187. xor edi,edi
    188. @@: invoke CloseHandle,handles[rdi*8]
    189. inc edi
    190. cmp edi,MUTEX_DATA_COUNT
    191. jb @b
    192. lea esi,buffer
    193. cmp byte ptr[rsi],0
    194. jz exit0
    195. lea r8d,buffer
    196.         invoke  SetDlgItemText,hWnd,ID_TXT
    197. exit0: xor eax,eax
    198. leave
    199. ret
    200. ReceiveMessageThread endp
    201. ;-----------------------------------------------------------------------
    202. .data
    203. szWin db "Transmitter",0
    204. Error1 db "The server is not running.",10,"Run?",0
    205. szAppName db "Mutex Reciever",0
    206. szService db "09s",0
    207. eventBegin dq ?
    208. eventEnd dq ?
    209. eventReceiverReady dq ?
    210. eventStop dq ?
    211. threadHandle dq ?
    212. threadId dd ?
    213. hWnd dq ?
    214. align 10h
    215. EVENT_BEGIN_TRANSMISSION dw "E","v","B","e","g","i","n","T","r","a","n","s","m","i","s","s","i","o","n",0
    216. EVENT_END_TRANSMISSION   dw "E","v","E","n","d","T","r","a","n","s","m","i","s","s","i","o","n",0
    217. EVENT_RECEIVER_READY     dw "E","v","R","e","c","e","i","v","e","r","R","e","a","d","y",0
    218. fmt dw "M","t","x","D","a","t","a",":","%","u",0
    219. end
    ресурсы клиента (09r.rc)
    Код (C):
    1. #include "resource.h"
    2. #define IDC_DIALOG 200
    3. #define ID_TXT 100
    4. #define ID_ICON 102
    5. IDC_DIALOG DIALOG 0,0,212,160
    6. STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
    7. WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
    8. CAPTION "Mutex Reciever"
    9. BEGIN
    10. CONTROL "",-1,"BUTTON",BS_GROUPBOX, 2, -1, 207, 24
    11. CONTROL "",ID_TXT,"STATIC",WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL,5,7,199,13
    12. DEFPUSHBUTTON  "Exit",IDCANCEL,149,27,60,15
    13.         CONTROL "",ID_ICON,"STATIC",WS_CHILDWINDOW | SS_ICON,5,48,128,128
    14. END
    В аттаче asm/rc/exe-файлы
    09.jpg
    P.P.S. Буду очень рад если мне подскажут ЧТО я сделал не так

    Продолжение здесь
     

    Вложения:

    • 09_Mutex.zip
      Размер файла:
      112,8 КБ
      Просмотров:
      79
  17. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Зачем выдумывать какие-то отмеченные/неотмеченные состояния? У всех объектов синхронизации есть одно состояние - сигнальное; функции ожидания возвращают управление, когда объект переходит в сигнальное состояние.
    Мьютекс находится в сигнальном состоянии, когда он не захвачен ни одним потоком.

    Важные не указанные моменты:
    - если при вызове CreateMutex именованный мьютекс уже существует и захвачен другим потоком, функция возвращает управление сразу, не дожидаясь его освобождения, даже если параметр bInitialOwner равен TRUE. Так что если по логике кода создающий мьютекс поток должен стать его владельцем, необходимо явно вызвать WaitForSingleObject, если GetLastError вернула ERROR_ALREADY_EXISTS.
    - если владеющий мьютексом поток завершится до освобождения мьютекса, мьютекс освобождается принудительно, при этом функции ожидания вернут WAIT_ABANDONED + N вместо WAIT_OBJECT + N
     
  18. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Справедливости ради, следует ещё упомянуть, что в Windows есть механизм отложенного получения данных Clipboard (Delayed Rendering), связанный с обработкой сообщений WM_RENDERFORMAT, WM_RENDERALLFORMATS, WM_DESTROYCLIPBOARD.
     
    Mikl___ нравится это.
  19. Mikl___

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

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

    Сокеты, датаграммы и каналы связи

    В локальных и глобальных сетях существует два принципиально разных способа передачи данных.
    1. посылка пакетов данных от одного узла другому (или сразу нескольким узлам) без получения подтверждения о доставке и без гарантии того, что передаваемые пакеты будут получены в правильной последовательности. Примером такого протокола ― протокол UDP (User Datagram Protocol),
      используемый в сетях TCP/IP, или протокол IPX, который является базовым в сетях Novell NetWare.
      Основные преимущества датаграмных протоколов высокое быстродействии и возможность широковещательной передачи данных, когда одновременно один узел отправляет сообщения, а другие их получают.
    2. Создание канала передачи данных между двумя различными узлами сети. Канал создается средствами датаграммных протоколов, доставка пакетов в канале гарантированна. Пакеты доходят в целостности и сохранности, в правильном порядке, хотя быстродействие в среднем ниже за счет посылки подтверждений.
      Пример протоколов, использующих каналы связи ― протоколы TCP и SPX
    3. протокол NETBIOS допускает передачу данных с использованием как датаграмм, так и каналов связи.
    Для передачи данных с использованием любого из перечисленных выше способов каждое приложение должно создать объект, который называется сокетом.
    По своему назначению сокет больше всего похож на дескриптор файла (file handle), который нужен для выполнения над файлом операций чтения или записи. Прежде чем приложение, запущенное на узле сети сможет выполнять передачу или прием данных, оно должно создать сокет и проинициализировать его, указав параметры.
    Для сокета необходимо указать три параметра:
    1. IP-адрес, связанный с сокетом,
    2. номер порта, для которого будут выполняться операции передачи данных,
    3. тип сокета.
    Существуют сокеты следующих типов
    1. Предназначен для передачи данных в виде датаграмм,
    2. с использованием каналов связи
    3. Сокеты смешанного типа

    Инициализация приложения и завершение его работы

    В процессе инициализации приложение должно зарегистрировать себя в библиотеке WSOCK32.DLL, которая предоставляет приложениям интерфейс Windows Sockets в среде операционных систем Windows.
    Для инициализации необходимо вызвать функцию WSAStartup, определенную как
    Код (C):
    1. int WSAStartup (WORD wVersionRequested, LPWSADATA  lpWSAData);
    В параметре wVersionRequested указывают версию интерфейса Windows Sockets.
    • Старший байт ― младший номер версии (minor version),
    • младший байт ― старший номер версии (major version).
    Перед вызовом функции WSAStartup параметр lpWSAData содержит указатель на структуру типа WSADATA, в которую записаны сведения о конкретной реализации интерфейса Windows Sockets.
    В случае успеха функция WSAStartup возвращает нулевое значение. При ошибке возвращается одно из следующих значений:
    Код ошибкиhexОписание
    WSASYSNOTREADY276BСетевое программное обеспечение не готово для работы
    WSAVERNOTSUPPORTED276CФункция не поддерживается данной реализацией интерфейса Windows Sockets
    WSAEINVAL2726Библиотека DLL, обеспечивающая интерфейсe Windows Sockets, не соответствует версии, указанной приложением указанной в параметре wVersionRequested
    фрагмент исходного текста приложения, выполняющий инициализацию интерфейса Windows Sockets:
    Код (C):
    1. rc = WSAStartup (MAKEWORD(1, 1), &WSAData);
    2. if(rc != 0)
    3. {
    4.   MessageBox(NULL, "WSAStartup  Error", "Error", MB_OK);
    5.   return FALSE;
    6. }
    7. // Отображаем описание и версию системы Windows Sockets
    8. // в окне органа управления Statusbar
    9. wsprintf(szTemp, "Server use %s %s",
    10.   WSAData.szDescription,WSAData.szSystemStatus);
    11. hwndSb = CreateStatusWindow(WS_CHILD | WS_VISIBLE  | WS_BORDER | SBARS_SIZEGRIP, szTemp, hWnd, IDS_STATUSBAR);
    Содержимое двух полей структуры типа WSADATA отображается в Statusbar'е
    Определение структуры WSADATA и указателя на нее:
    Код (C):
    1. typedef struct WSAData
    2. {
    3.   WORD           wVersion;
    4.   WORD           wHighVersion;
    5.   char           szDescription[WSADESCRIPTION_LEN+1];
    6.   char           szSystemStatus[WSASYS_STATUS_LEN+1];
    7.   unsigned short iMaxSockets;
    8.   unsigned short iMaxUdpDg;
    9.   char FAR *     lpVendorInfo;
    10. } WSADATA ;
    11. typedef WSADATA  FAR *LPWSADATA;
    • Поля szDescription и szSystemStatus после вызова WSAStartup содержат описание конкретной реализации интерфейса Windows Socket и текущее состояние этого интерфейса в виде текстовых строк.
    • В полях wVersion и wHighVersion записаны, версия спецификации Windows Socket, которую будет использовать приложение, и версия спецификации, которой соответствует конкретная реализация интерфейса Windows Socket.
    • Приложение может одновременно создавать несколько сокетов, для использования в разных подзадачах одного процесса. В поле iMaxSockets хранится максимальное количество сокетов, которое можно получить для одного процесса.
    • В поле iMaxUdpDg записан максимальный размер пакета данных, который можно переслать с использованием датаграммного протокола UDP.
    • В поле lpVendorInfo указатель на дополнительную информацию, формат которой зависит от фирмы-изготовителя конкретной реализации системы Windows Sockets.
    Перед завершением работы, приложение должно освободить ресурсы, полученные у операционной системы для работы с Windows Sockets. Для этого приложение должно вызвать функцию WSACleanup. Она возвращает нулевое значение при успехе или значение SOCKET_ERROR = -1. Для получения кода ошибки используют функцию WSAGetLastError. Эта функция позволяет определить код ошибки при неудачном завершении функций интерфейса Windows Sockets. Ее нужно вызывать сразу вслед за неудачно завершившейся функцией.
    Если ошибка возникла при выполнении функции WSACleanup, функция WSAGetLastError может вернуть следующее значение:
    Код ошибкиhexОписание
    WSANOTINITIALISED276DИнтерфейс Windows Sockets не был проинициализирован функцией WSAStartup
    WSAENETDOWN2742Сбой сетевого программного обеспечения
    WSAEINPROGRESS2734Во время вызова функции WSACleanup выполнялась одна из блокирующих функций интерфейса Windows Sockets
    Некоторые функции интерфейса Windows Sockets способны блокировать работу приложения, так как они не возвращают управление до своего завершения. Windows использует вытесняющую многозадачность, это не приводит к блокировке всей системы. Можно избежать использования блокирующих функций, так как для них в интерфейсе Windows Sockets существует замена.

    Создание и инициализация сокета


    После инициализации интерфейса Windows Sockets приложение должно создать один или несколько сокетов, которые будут использованы для передачи данных.

    Создание сокета

    Сокет создается с помощью функции socket:
    Код (C):
    1. SOCKET socket (int af, int type, int protocol);
    • Параметр af определяет формат адреса. Для этого параметра нужно указывать значение AF_INET = 2 или PF_INET с тем же значением, что соответствует формату адреса, принятому в Internet.
      КонстантаhexКонстантаhex
      AF_UNSPEC, PF_UNSPEC0AF_DATAKIT, PF_DATAKIT9
      AF_UNIX, PF_UNIX1AF_CCITT, PF_CCITTA
      AF_INET, PF_INET2AF_SNA, PF_SNAB
      AF_IMPLINK, PF_IMPLINK3AF_DECnet, PF_DECnetC
      AF_PUP, PF_PUP4AF_DLI, PF_DLID
      AF_CHAOS, PF_CHAOS5AF_LAT, PF_LATE
      AF_NS, PF_NS6AF_HYLINK, PF_HYLINKF
      AF_IPX, PF_IPX6AF_APPLETALK, PF_APPLETALK10
      AF_ISO, PF_ISO7AF_NETBIOS11
      AF_OSI, PF_OSI7AF_MAX, PF_MAX12
      AF_ECMA, PF_ECMA8
    • Параметр type определяет тип сокета, который будет использован для данного сокета
      typehexОписание
      SOCK_STREAM1Сокет будет использован для передачи данных через канал связи с использованием протокола TCP
      SOCK_DGRAM2Передача данных будет выполняться без создания каналов связи через датаграммный протокол UDP
      SOCK_RAW3
      SOCK_RDM4
      SOCK_SEQPACKET5
    • Параметр protocol определяет протокол, который будет использован для данного сокета. Обычно указывают нулевое значение. Наиболее часто используются константы:
      protocolhexprotocolhexprotocolhex
      IPPROTO_IP
      0​
      IPPROTO_GGP
      3​
      IPPROTO_ST
      7​
      IPPROTO_ICMP
      1​
      IPPROTO_IPV4
      4​
      IPPROTO_UDP
      11​
      IPPOROTO_IGMP
      2​
      IPPROTO_TCP
      6​
      IPPROTO_RAW
      FF​
      При ошибке возвращается одно из следующих значений:
      Код ошибкиhexОписание
      WSANOTINITIALISED276DИнтерфейс Windows Sockets не был проинициализирован функцией WSAStartup
      WSAENETDOWN2742Сбой сетевого программного обеспечения
      WSAEAFNOSUPPORT273FУказан неправильный тип адреса
      WSAEINPROGRESS2734Выполняется блокирующая функция интерфейса Windows Sockets
      WSAEMFILE2728Израсходован весь запас свободных дескрипторов
      WSAENOBUFS2747Нет памяти для создания буфера
      WSAEPROTONOSUPPORT273BУказан неправильный протокол
      WSAEPROTOTYPE2739Указанный протокол несовместим с данным типом сокета
      WSAESOCKTNOSUPPORT273CУказанный тип сокета несовместим с данным типом адреса
    В случае успеха функция socket возвращает дескриптор, который нужно использовать для выполнения всех операций над данным сокетом. Если произошла ошибка ― функция возвращает значение INVALID_SOCKET = -1. Для анализа причины ошибки вызывают функцию WSAGetLastError, которая вернет код ошибки:
    фрагмент кода, в котором создается сокет для передачи данных с использованием протокола TCP:
    Код (C):
    1. srv_socket  = socket(AF_INET, SOCK_STREAM, 0);
    2. if(srv_socket  == INVALID_SOCKET)
    3. {
    4.   MessageBox(NULL, "socket  Error", "Error", MB_OK);
    5.   return;
    6. }

    Удаление сокета

    Для освобождения ресурсов приложение должно закрывать сокеты, которые ему больше не нужны, вызывая функцию closesocket:
    Код (C):
    1. int closesocket  (SOCKET sock);
    коды ошибок для этой функции:
    Код ошибкиhexОписание
    WSANOTINITIALISED276DПеред использованием функции closesocket необходимо вызвать функцию WSAStartup
    WSAENETDOWN2742Сбой в сети
    WSAENOTSOCK2736Указанный в параметре дескриптор не является сокетом
    WSAEINPROGRESS2734Выполняется блокирующая функция интерфейса Windows Sockets
    WSAEINTR2714Работа функции была отменена при помощи функции WSACancelBlockingCall

    Параметры сокета

    Перед использованием нужно задать параметры сокета. Для этого готовят структуру типа sockaddr:
    Код (C):
    1. struct sockaddr
    2. {
    3.   u_short sa_family;
    4.   char    sa_data[14];
    5. };
    6. typedef struct sockaddr SOCKADDR ;
    7. typedef struct sockaddr *PSOCKADDR  ;
    8. typedef struct sockaddr FAR *LPSOCKADDR   ;
    Для работы с адресами в формате Internet используется другой вариант этой структуры, в котором детализируется
    формат поля sa_data:
    Код (C):
    1. struct sockaddr_in
    2. {
    3.   short   sin_family;
    4.   u_short sin_port;
    5.   struct  in_addr  sin_addr;
    6.   char    sin_zero[8];
    7. };
    8. typedef struct sockaddr_in  SOCKADDR _IN;
    9. typedef struct sockaddr_in  *PSOCKADDR  _IN;
    10. typedef struct sockaddr_in  FAR *LPSOCKADDR   _IN;
    Поле sin_family определяет тип адреса. Нужно записать в это поле значение AF_INET, которое соответствует типу адреса, принятому в Internet:
    Код (C):
    1. srv_address.sin_family = AF_INET ;
    Поле sin_port определяет номер порта, который будет использоваться для передачи данных.
    Порт ― это дескриптор программы, выполняющей обмен на сети. На одном узле может одновременно работать несколько программ, использующих разные порты.
    Особенностью поля sin_port является использование так называемого сетевого формата данных. Формат отличается от того, что принят в процессорах с архитектурой Intel ― младшие байты данных хранятся по старшим адресам памяти. Архитектура процессоров Intel подразумевает хранение старших байтов данных по младшим адресам.
    Универсальный сетевой формат данных используют при организации глобальных сетей, так как в узлах такой сети могут использоваться компьютеры с различной архитектурой.
    Для выполнения преобразований из обычного формат в сетевой и обратно в интерфейсе Windows Sockets предусмотрен специальный набор функций. В частности, для заполнения поля sin_port нужно использовать функцию htons, выполняющую преобразование 16-разрядных данных из формата Intel в сетевой формат.
    Инициализация поля sin_port:
    Код (C):
    1. #define SERV_PORT 5000
    2. srv_address.sin_port = htons(SERV_PORT);
    Поле sin_addr структуры sockaddr_in представляет собой структуру in_addr:
    Код (C):
    1. struct in_addr
    2. {
    3.   union
    4.   {
    5.     struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
    6.     struct { u_short s_w1,s_w2; } S_un_w;
    7.     u_long S_addr;
    8.   } S_un;
    9. };
    10. #define s_addr  S_un.S_addr
    11. #define s_host  S_un.S_un_b.s_b2
    12. #define s_net   S_un.S_un_b.s_b1
    13. #define s_imp   S_un.S_un_w.s_w2
    14. #define s_impno S_un.S_un_b.s_b4
    15. #define s_lh    S_un.S_un_b.s_b3
    При инициализации сокета в этой структуре нужно указать IP-адрес, с которым будет работать данный сокет.
    Если сокет будет работать с любым адресом (например, создается сервер, который будет доступен из узлов с любым адресом), адрес для сокета можно указать следующим образом:
    Код (C):
    1. srv_address.sin_addr.s_addr = INADDR_ANY ;
    Если сокет будет работать с определенным IP-адресом (например, создается приложение-клиент, которое будет обращаться к серверу с конкретным IP-адресом), в указанную структуру необходимо записать реальный адрес.
    Датаграммный протокол UDP позволяет посылать пакеты данных одновременно всем рабочим станциям в широковещательном режиме. Для этого нужно указать адрес как INADDR_BROADCAST.
    Если известен адрес в виде четырех десятичных чисел, разделенных точкой (как его вводит пользователь), тогда поле адреса заполняется при помощи функции inet_addr:
    Код (C):
    1. dest_sin.sin_addr.s_addr = inet_addr ("200.200.200.201");
    В случае ошибки функция вернет значение INADDR_NONE.
    Обратное преобразование IP-адреса в текстовую строку выполняется с помощью функции inet_ntoa,
    Код (C):
    1. char FAR * inet_ntoa (struct in_addr  in);
    При ошибке функция вернет значение NULL.
    Пользователь работает с доменными именами, используя сервер DNS или файл HOSTS. Вначале используется функция gethostbyname, возвращающая IP-адрес, затем полученный адрес записывается в структуру sin_addr
    Код (C):
    1. PHOSTENT  phe;
    2. phe = gethostbyname ("ftp.microsoft.com");
    3. if(phe == NULL)
    4. {
    5.   closesocket  (srv_socket);
    6.   MessageBox(NULL, "gethostbyname  Error", "Error", MB_OK);
    7.   return;
    8. }
    9. memcpy((char FAR *)&(dest_sin.sin_addr ), phe->h_addr, phe->h_length);
    При ошибке gethostbyname возвращает NULL.
    Причину ошибки выясняют, при проверке кода возврата функции WSAGetLastError.
    Если указанный узел найден в базе DNS или в файле HOSTS, функция gethostbyname возвращает указатель на структуру hostent
    Код (C):
    1. struct  hostent
    2. {
    3.   char  FAR * h_name;            // имя узла
    4.   char  FAR * FAR * h_aliases;   // список альтернативных имен
    5.   short h_addr type;              // тип адреса узла
    6.   short h_length;                // длина адреса
    7.   char  FAR * FAR * h_addr _list; // список адресов
    8. #define h_addr   h_addr_list[0]   // адрес
    9. };
    10. typedef struct hostent  *PHOSTENT ;
    11. typedef struct hostent  FAR *LPHOSTENT  ;
    Искомый адрес находится в первом элемента списка h_addr _list[0], на который можно ссылаться при помощи h_addr. Длина поля адреса находится в поле h_length.

    Привязка адреса к сокету


    После подготовки структуры SOCKADDR, в нее записывают параметры сокета (в частности, адрес), выполняется привязка адреса к сокету при помощи функции bind:
    Код (C):
    1. int bind (SOCKET sock, const struct sockaddr FAR * addr, int namelen);
    Параметр sock содержит дескриптор сокета, созданного функцией socket.
    В поле addr записывается указатель на подготовленную структуру SOCKADDR, а в поле namelen ― размер этой структуры.
    В случае ошибки функция bind возвращает значение SOCKET_ERROR. Дальнейший анализ причин ошибки следует выполнять при помощи функции WSAGetLastError. Возможные коды ошибок перечислены ниже:
    Код ошибкиhexОписание
    WSANOTINITIALISED276DПеред использованием функции необходимо вызвать функцию WSAStartup
    WSAENETDOWN2742Сбой в сети
    WSAEADDRINUSE2740Указанный адрес уже используется
    WSAEFAULT271EЗначение параметра namelen меньше размера структуры sockaddr
    WSAEINPROGRESS2734Выполняется блокирующая функция интерфейса Windows Sockets
    WSAEAFNOSUPPORT273FЭтот протокол не может работать с указанным семейством адресов
    WSAEINVAL2726Сокет уже привязан к адресу
    WSAENOBUFS2747Установлено слишком много соединений
    WSAENOTSOCK2736Указанный в параметре дескриптор не является сокетом
    Пример вызова функции bind
    Код (C):
    1. if(bind (srv_socket, (LPSOCKADDR   )&srv_address,
    2.   sizeof(srv_address)) == SOCKET_ERROR )
    3. {
    4.   closesocket  (srv_socket);
    5.   MessageBox(NULL, "bind  Error", "Error", MB_OK);
    6.   return;
    7. }

    Создание канала связи

    Если требуется передача датаграммных сообщений при помощи протокола негарантированной доставки UDP, канал связи не нужен. Сразу после создания сокетов и их инициализации можно приступать к передаче данных. Для передачи данных с использованием протокола TCP необходимо создать канал связи.

    Сторона сервера

    Рассмотрим процедуру создания канала связи со стороны сервера.
    Нужно переключить сокет в режим приема для выполнения ожидания соединения с клиентом при помощи функции listen:
    Код (C):
    1. int listen(SOCKET sock, int backlog);
    Через параметр sock функции необходимо передать дескриптор сокета, который будет использован для создания канала. Параметр backlog задает максимальный размер очереди для ожидания соединения (указывается значение от 1 до 5). Очередь содержит запросы на установку соединений для каждой пары значений (IP-адрес, порт).
    Список возможных кодов ошибок для функции listen.
    Код ошибкиhexОписание
    WSANOTINITIALISED276DПеред использованием функции необходимо вызвать функцию WSAStartup
    WSAENETDOWN2742Сбой в сети
    WSAEADDRINUSE2740Указанный адрес уже используется
    WSAEINPROGRESS2734Выполняется блокирующая функция интерфейса Windows Sockets
    WSAEINVAL2726Сокет еще не был привязан к адресу или уже находится в подключенном состоянии
    WSAEISCONN2748Сокет уже находится в подключенном состоянии
    WSAEMFILE2728Недостаточно дескрипторов файлов
    WSAENOBUFS2747Нет места для размещения буфера
    WSAENOTSOCK2736Указанный в параметре дескриптор не является сокетом
    WSAEOPNOTSUPP273DФункция listen не работает с сокетом указанного типа
    Пример вызов функции listen:
    Код (C):
    1. if(listen(srv_socket, 1) == SOCKET_ERROR )
    2. {
    3.   closesocket  (srv_socket);
    4.   MessageBox(NULL, "listen Error", "Error", MB_OK);
    5.   return;
    6. }
    Необходимо выполнить ожидание соединения. Это выполняется двумя различными способами.
    1. Циклически вызывается функция accept до тех пор, пока не будет установлено соединение. Затем приступают к обмену данными.
      Функция accept имеет следующий прототип:
      Код (C):
      1. SOCKET accept (SOCKET sock, struct sockaddr FAR * addr,
      2.   int FAR * addrlen);
      Через параметр sock необходимо указать дескриптор сокета, который находится в режиме приема для выполнения ожидания.
      Параметр addr должен содержать адрес буфера, в который будет записан адрес узла, подключившегося к серверу. Размер этого буфера необходимо указать в переменной типа int, адрес которой передается через параметр addrlen.
    2. Если ожидание соединения в цикле не вызывает особого энтузиазма, используют способ, основанный на использовании расширения программного интерфейса Windows Socket, предназначенного для выполнения асинхронных операций.
    Список возможных кодов ошибок для функции accept.
    Код ошибкиhexОписание
    WSANOTINITIALISED276DПеред использованием функции необходимо вызвать функцию WSAStartup
    WSAENETDOWN2742Сбой в сети
    WSAEFAULT271EЗначение параметра addrlen меньше размера структуры адреса
    WSAEINTR2714Работа функции была отменена при помощи функции WSACancelBlockingCall
    WSAEINPROGRESS2734Выполняется блокирующая функция интерфейса Windows Sockets
    WSAEINVAL2726Перед вызовом функции accept не была вызвана функция listen
    WSAEMFILE2728Нет доступных дескрипторов
    WSAENOBUFS2747Установлено слишком много соединений
    WSAENOTSOCK2736Указанный в параметре дескриптор не является сокетом
    WSAEOPNOTSUPP273DДанный тип сокета нельзя использовать при вызове функций, ориентированных на работу с каналом связи
    WSAEWOULDBLOCK2733Сокет отмечен как неблокирующий и в настоящее время нет каналов связи, которые нужно устанавливать
    Вместо того чтобы ожидать соединение, вызывая в цикле функцию accept, ваше приложение может вызвать один раз функцию WSAAsyncSelect, указав ей, что при получении запроса на установку соединения функция окна вашего приложения должна получить сообщение:
    Код (C):
    1. #define WSA_ACCEPT   (WM_USER + 1)
    2. // При попытке установки соединения главное окно приложения
    3. // получит сообщение WSA_ACCEPT
    4. rc = WSAAsyncSelect (srv_socket, hWnd, WSA_ACCEPT, FD_ACCEPT );
    5. if(rc > 0)
    6. {
    7.   closesocket  (srv_socket);
    8.   MessageBox(NULL, "WSAAsyncSelect  Error", "Error", MB_OK);
    9.   return;
    10. }
    В данном случае ожидание соединения выполняется для сокета srv_socket. Последний параметр функции равен FD_ACCEPT. Это означает, что при попытке создания канала связи функция окна с дескриптором hWnd получит сообщение WSA_ACCEPT, определенное в вашем приложении.
    Обработчик этого сообщения может выглядит следующим образом:
    Код (C):
    1. void WndProc_OnWSAAccept(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    2. {
    3.   int rc;
    4.   // При ошибке отменяем поступление извещений в главное окно приложения
    5.   if(WSAGETSELECTERROR(lParam) != 0)
    6.   {
    7.     MessageBox(NULL, "accept  Error", "Error", MB_OK);
    8.     WSAAsyncSelect (srv_socket, hWnd, 0, 0);
    9.     return;
    10.   }
    11.   // Определяем размер адреса сокета
    12.   acc_sin_len = sizeof(acc_sin);
    13.   // Разрешаем установку соединения
    14.   srv_socket  = accept (srv_socket, (LPSOCKADDR   )&acc_sin, (int FAR *)&acc_sin_len);
    15.   if(srv_socket  == INVALID_SOCKET)
    16.   {
    17.     MessageBox(NULL, "accept  Error, invalid socket ",
    18.       "Error", MB_OK);
    19.     return;
    20.   }
    21.   // Если на данном сокете начнется передача данных от клиента, в главное окно
    22. // приложения поступит сообщение WSA_NETEVENT. Это же сообщение поступит при
    23. // разрыве соединения
    24.   rc = WSAAsyncSelect (srv_socket, hWnd, WSA_NETEVENT, FD_READ  | FD_CLOSE );
    25.   if(rc > 0)
    26.   {
    27.     closesocket  (srv_socket);
    28.     MessageBox(NULL, "WSAAsyncSelect  Error", "Error", MB_OK);
    29.     return;
    30.   }
    31. }
    Обработчик сообщения вначале вызывает функцию accept, выполняющую создание канала передачи данных. После этого функция WSAAsyncSelect вызывается еще один раз для того чтобы установить асинхронную обработку приема данных от удаленного клиента, а также обработку ситуации разрыва канала связи.

    Сторона клиента

    Для установки соединения в приложении используется функция SetConnection:
    Код (C):
    1. SOCKADDR _IN dest_sin;
    2. void SetConnection(HWND hWnd)
    3. {
    4.   PHOSTENT  phe;
    5.   // Создаем сокет
    6.   srv_socket  = socket(AF_INET, SOCK_STREAM, 0);
    7.   if(srv_socket  == INVALID_SOCKET)
    8.   {
    9.     MessageBox(NULL, "socket  Error", "Error", MB_OK);
    10.     return;
    11.   }
    12.   // Устанавливаем адрес IP и номер порта
    13.   dest_sin.sin_family = AF_INET ;
    14.   // Определяем адрес узла
    15.   phe = gethostbyname ("localhost ");
    16.   if(phe == NULL)
    17.   {
    18.     closesocket  (srv_socket);
    19.     MessageBox(NULL, "gethostbyname  Error", "Error", MB_OK);
    20.     return;
    21.   }
    22.   // Копируем адрес узла
    23.   memcpy((char FAR *)&(dest_sin.sin_addr ), phe->h_addr,  phe->h_length);
    24.   // Копируем номер порта
    25.   dest_sin.sin_port = htons(SERV_PORT);
    26.   // Устанавливаем соединение
    27.   if(connect(srv_socket, (PSOCKADDR  )&dest_sin, sizeof(dest_sin)) < 0)
    28.   {
    29.     closesocket  (srv_socket);
    30.     MessageBox(NULL, "connect Error", "Error", MB_OK);
    31.     return;
    32.   }
    33. }
    Вначале с помощью функции socket создается сокет. Затем выполняется заполнение адресной информацией структуры dest_sin.
    Для получения IP-адреса используют функцию gethostbyname, указав имя узла localhost.
    Это имя отображается в файле HOSTS на адрес 127.0.0.1:
    Код (C):
    1. localhost
    Адрес 127.0.0.1 является локальным. Его можно использовать для тестирования приложений, выполняющих обмен данными при помощи протокола TCP/IP, запуская сервер и клиент на одном и том же компьютере.
    После заполнения структуры с адресной информацией функция connect создает канал связи с сервером.

    Передача и прием данных

    После того как канал создан, начинают передачу данных. Для передачи данных при помощи протокола гарантированной доставки TCP используют функции send и recv.
    У функции передачи данных send четыре параметра
    1. дескриптор сокета sock, на котором выполняется передача,
    2. адрес буфера buf, содержащего передаваемое сообщение,
    3. размер этого буфера bufsize
    4. и флаги flags
    Код (C):
    1. int send (SOCKET sock, const char FAR* buf, int bufsize, int flags);
    Пример передачи данных серверу:
    Код (C):
    1. char szBuf[80];
    2. lstrcpy(szBuf, "Test string");
    3. send (srv_socket, szBuf, lstrlen(szBuf), 0);
    Параметры функции recv, предназначенной для приема данных, аналогичны параметрам функции send:
    Код (C):
    1. int recv (SOCKET sock, char FAR * buf, int bufsize, int flags);
    Функции recv и send возвращают количество, принятых и переданных байт данных. Приложение, которое принимает данные, вызывает функцию recv в цикле до тех пор, пока не будут приняты все переданные данные. На один вызов send может приходиться несколько вызовов функции recv.
    В случае ошибки функции send и recv возвращают значение SOCKET_ERROR. Для анализа причин возникновения ошибки используют функцию WSAGetLastError.
    (Продолжение здесь)​
     
    Marylin нравится это.
  20. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Не хватает некоторых форматов клипборды.
    Привожу обновлённый и дополненный список.
    КонстантаhexbinОписание
    CF_TEXT
    1​
    00000001Текстовые данные в кодировке ANSI, представляющие собой массив символов. Каждая строка завершается комбинацией символов "\r\n", весь массив закрыт двоичным нулем
    CF_BITMAP
    2​
    00000010Хендл битового изображения (HBITMAP) в формате, который зависит от устройства отображения (Device Dependent Bitmap)
    CF_META-FILEPICT
    3​
    00000011Хендл метафайла, описываемый структурой METAFILEPICT
    CF_SYLK
    4​
    00000100Формат Microsoft Symbolic Link. Этот формат предназначен для передачи текстовых данных, причем каждая строка заканчивается комбинацией символов "\r\n". Используется в некоторых программных продуктах Microsoft
    CF_DIF
    5​
    00000101Формат Data Interchange Format. Аналогично формату CF_SYLK, формат CF_DIF предназначен для передачи текстовых данных
    CF_TIFF
    6​
    00000110Графическое изображение в формате Tag Image File Format, который был разработан Microsoft, Aldus Corporation и Hewlett-Packard
    CF_OEMTEXT
    7​
    00000111Аналогично предыдущему, однако буфер содержит символы в кодировке OEM
    CF_DIB
    8​
    00001000Битовое изображение в формате BITMAPINFO, который не зависит от устройства отображения (Device Independent Bitmap)
    CF_PALETTE
    9​
    00001001Палитра цветов. Используется при записи в Clipboard битовых изображений DIB
    CF_PENDATA
    A​
    00001010Этот формат данных используется в расширении операционной системы Windows, предназначенном для работы с перьевым вводом
    CF_RIFF
    B​
    00001011Формат Resource Interchange File Format, более сложный, чем CF_WAVE
    CF_WAVE
    C​
    00001100Звуковые данные. Подмножество формата Resource Interchange File Format
    CF_UNICODE-TEXT
    D​
    00001101Текст в формате UTF-16, аналогично CF_TEXT и CF_OEMTEXT
    CF_ENH-METAFILE
    E​
    00001110Хендл (HANDLE) к EMF (Enhanced Metafile) ― HENHMETAFILE
    CF_HDROP
    F​
    00001111Хендл к структуре HDROP, которая содержит список путей к файлам, используемая при Drag&Drop. Приложение может запросить информацию о файлах, вызвав функцию DragQueryFile
    CF_LOCALE
    10​
    00010000Объект HGLOBAL, содержащий информацию о локали текста в буфере обмена
    CF_DIBV5
    11​
    00010001Объект в памяти, содержащий структуру BITMAPV5HEADER, за которой следует информация о цветном пространстве и данные картинки
    CF_OWNER-DISPLAY
    80​
    10001110Формат данных определяется приложением, записавшим такие данные в Clipboard. Это же приложение отвечает за отображение данных
    CF_DSPTEXT
    81​
    10000001Текстовое представление данных, формат которых определен приложением
    CF_DSPBITMAP
    82​
    10000010Представление данных, формат которых определен приложением, в виде битового изображения
    CF_DSPMETA-FILEPICT
    83​
    10000011Представление данных, формат которых определен приложением, в виде метафайла
    CF_DSPENH-METAFILE
    8E​
    10001110Формат EMF (Enhanced Metafile)
     
    Последнее редактирование модератором: 10 мар 2024