Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ БОМ. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 89

Автор Π”ΠΎΠ½Π°Π»ΡŒΠ΄ Бокс

МодСль программирования БОМ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΠ»Π° Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΡƒΡŽ модСль ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ программирования, заставив Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² Π²Π½ΠΈΠΊΠ°Ρ‚ΡŒ Π²ΠΎ Π²Π·Π°ΠΈΠΌΠΎΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρƒ интСрфСйсом ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ. МодСль программирования с MTS Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ модСль БОМ, побуТдая Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² Π²Π½ΠΈΠΊΠ°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ ΠΈ Π²ΠΎ Π²Π·Π°ΠΈΠΌΠΎΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρƒ состояниСм ΠΈ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ. Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ MTS Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ логичСски смодСлирован ΠΊΠ°ΠΊ состояниС ΠΈ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅, Π½ΠΎ Π΅Π³ΠΎ физичСская рСализация Π΄ΠΎΠ»ΠΆΠ½Π° явно Ρ€Π°Π·Π»ΠΈΡ‡Π°Ρ‚ΡŒ эти понятия. Π―Π²Π½ΠΎ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΠ² MTS ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ состояниСм ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ прилоТСния ΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΡΠΈΠ»ΠΈΡ‚ΡŒ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΡƒ инфраструктурой управлСния ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠΎΠΌ ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΎΠΉ, Π»ΠΎΠΊΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ ошибок, Π½Π΅ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΡ€Π΅Ρ‡ΠΈΠ²ΠΎΡΡ‚ΡŒΡŽ Π΄Π°Π½Π½Ρ‹Ρ…, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅ΠΌ доступа Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ ΠΌΠ΅Π»ΠΊΠΈΡ… структурных Π΅Π΄ΠΈΠ½ΠΈΡ† (fine-grain). Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ состояния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Π² Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½Ρ‹ΠΉ Π±Π»ΠΎΠΊ с ΠΈΡ… указатСлями vptr (ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΌΠΈ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°). ВмСсто этого Π² MTS прСдусмотрСны срСдства для записи состояния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π»ΠΈΠ±ΠΎ Π² Π΄Π»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅, Π»ΠΈΠ±ΠΎ Π²ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅. Π­Ρ‚ΠΎ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ находится ΠΏΠΎΠ΄ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅ΠΌ срСды MTS Π½Π° этапС выполнСния, ΠΈ ΠΊ Π½Π΅ΠΌΡƒ обСспСчСн бСзопасный доступ для ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ Π·Π°Π±ΠΎΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎΠ± ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΎΠΉ ΠΈ совмСстимости Π΄Π°Π½Π½Ρ‹Ρ…. БостояниС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΎΡΡ‚Π°Π²Π°Ρ‚ΡŒΡΡ постоянным Π² случаС сбоя ΠΌΠ°ΡˆΠΈΠ½Ρ‹ ΠΈΠ»ΠΈ Π½Π΅ΡˆΡ‚Π°Ρ‚Π½ΠΎΠ³ΠΎ прСкращСния Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, записываСтся Π² Π΄ΠΎΠ»Π³ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅, ΠΈ MTS Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ лишь Π½ΠΈΡ‡Ρ‚ΠΎΠΆΠ½Ρ‹Π΅ измСнСния Π²ΠΎ всСй сСти. ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π½ΠΎΠ΅ состояниС ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ записано Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ, ΡƒΠΏΡ€Π°Π²Π»ΡΠ΅ΠΌΡƒΡŽ MTS, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ MTS Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ обращСния ΠΊ памяти Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ – Π²ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Π½ΠΈΠ΅ ΠΏΠΎΡ€Ρ‡ΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ.

Как Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°Ρ… Π½Π° Π±Π°Π·Π΅ классов ΠΈ Π½Π° Π±Π°Π·Π΅ интСрфСйсов, модСль программирования MTS, ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΈΡ€ΡƒΡŽΡ‰Π°Ρ состояниС, Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ внимания ΠΈ дисциплины со стороны Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, ΠΊΠ°ΠΊ ΠΈ с Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π½Π° Π±Π°Π·Π΅ классов ΠΈ Π½Π° Π±Π°Π·Π΅ интСрфСйсов, модСль MTS, ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΈΡ€ΡƒΡŽΡ‰Π°Ρ состояниС, ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ принята постСпСнно. ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, пошаговоС принятиС ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ прСимущСства MTS Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ постСпСнно. Π­Ρ‚ΠΎ позволяСт Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ MTS со ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒΡŽ, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ мСстной ΠΊΡƒΠ»ΡŒΡ‚ΡƒΡ€Π΅ программирования.

ПослС объСдинСния ΠΊΠΎΠΌΠ°Π½Π΄ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² MTS ΠΈ БОМ Π² Ρ€Π°ΠΌΠΊΠ°Ρ… Ρ„ΠΈΡ€ΠΌΡ‹ Microsoft стало ясно, Ρ‡Ρ‚ΠΎ MTS являСт собой ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ шаг Π² ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΈ БОМ. Π― горячо ΠΏΡ€ΠΈΠ·Ρ‹Π²Π°ΡŽ всСх Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΎΠ² БОМ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒΡΡ Π² эту Ρ‚Ρ€Π΅Ρ‚ΡŒΡŽ Π²ΠΎΠ»Π½Ρƒ развития ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ программирования.


ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π‘. Π˜Π·Π±Ρ€Π°Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ΄

Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄, ΡΠΎΠΏΡ€ΠΎΠ²ΠΎΠΆΠ΄Π°ΡŽΡ‰ΠΈΠΉ Π΄Π°Π½Π½ΡƒΡŽ ΠΊΠ½ΠΈΠ³Ρƒ, содСрТит Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Π½ΠΎΠ΅ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ БОМ (БОМ Chat) Π² совокупности с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΎΠΉ ΠΊΠΎΠ΄ΠΎΠ² ΡƒΡ‚ΠΈΠ»ΠΈΡ‚, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Π½Ρ‹Ρ… Π°Π²Ρ‚ΠΎΡ€ΠΎΠΌ. Π­Ρ‚ΠΎΡ‚ исходный ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ Π² элСктронной Ρ„ΠΎΡ€ΠΌΠ΅ ΠΏΠΎ адрСсу http://www.develop.com/essentialcom. Для удобства ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ БОМ Chat прСдставлСно здСсь Π² ΠΎΡ‚ΠΏΠ΅Ρ‡Π°Ρ‚Π°Π½Π½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ΅.


БОМ Chat – ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ взаимодСйствия Π½Π° Π±Π°Π·Π΅ БОМ

БОМ Chat (Ρ‡Π°Ρ‚) являСтся Π·Π°ΠΊΠΎΠ½Ρ‡Π΅Π½Π½ΠΎΠΉ БОМ-ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ, которая Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ рассрСдоточСнноС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ взаимодСйствия, состоящСС ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… Ρ€Π°Π·Π΄Π΅Π»ΠΎΠ². Π­Ρ‚ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ состоит ΠΈΠ· Ρ‚Ρ€Π΅Ρ… Π΄Π²ΠΎΠΈΡ‡Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²:

comchat.exe – ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹ΠΉ сСрвСр,

comchatps.dll – интСрфСйсный ΠΌΠ°Ρ€ΡˆΠ°Π»Π΅Ρ€ для всСх интСрфСйсов БОМ Chat,

client.exe – клиСнтскоС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, основанноС Π½Π° консоли.

ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ базируСтся Π½Π° СдинствСнном классС БОМ (CLSID_ChatSession). Как ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½Π° рис. B.1, ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ класса Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ интСрфСйс IChatSessionManager, Π° ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ сСанс связи (chat session) Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ интСрфСйс IChatSession . ΠšΠ»ΠΈΠ΅Π½Ρ‚Ρ‹, ΠΆΠ΅Π»Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ извСщСния Ρ‡Π°Ρ‚Π°, Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ интСрфСйс IChatSessionEvents ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ сСанса связи.




COMChat.idl

/////////////////////////////////////////////////////

//

// COMChat.idl

//

// Copyright 1997, Don Box/Addison Wesley

//

// This code accompanies the book "The Component

// Object Model" from Addison Wesley. Blah blah blah

//

//

interface IChatSessionEvents;

[

uuid(5223A050-2441-11d1-AF4F-0060976AA886),

object

]

interface IChatSession : IUnknown

{

import Β«objidl.idlΒ»;

[propget] HRESULT SessionName([out, string] OLECHAR **ppwsz);

HRESULT Say([in, string] const OLECHAR *pwszStatement);

HRESULT GetStatements([out] IEnumString **ppes);

HRESULT Advise([in] IChatSessionEvents *pEventSink,

[out] DWORD *pdwReg);

HRESULT Unadvise([in] DWORD dwReg);

}

[

uuid(5223A051-2441-11d1-AF4F-0060976AA886),

object

]

interface IChatSessionEvents : IUnknown

{

import Β«objidl.idlΒ»;

HRESULT OnNewUser([in, string] const OLECHAR *pwszUser);

HRESULT OnUserLeft([in, string] const OLECHAR *pwszUser);

HRESULT OnNewStatement([in, string] const OLECHAR *pwszUser,

[in, string] const OLECHAR *pwszStmnt);

}

[

uuid(5223A052-2441-11d1-AF4F-0060976AA886),

object

]

interface IChatSessionManager : IUnknown

{

import Β«objidl.idlΒ»;

HRESULT GetSessionNames([out] IEnumString **ppes);

HRESULT FindSession([in, string] const OLECHAR *pwszName,

[in] BOOL bDontCreate,

[in] BOOL bAllowAnonymousAccess,

[out] IChatSession **ppcs);

HRESULT DeleteSession([in, string] const OLECHAR *pwszName);

}

cpp_quote(Β«DEFINE_GUID(CLSID_ChatSession,0x5223a053,0x2441,Β»)

cpp_quote(Β«0x11d1,0xaf,0x4f,0x0,0x60,0x97,0x6a,0xa8,0x86);Β»)


client.cpp

/////////////////////////////////////////////////////

//

// client.cpp

//

// Copyright 1997, Don Box/Addison Wesley

//

// This code accompanies the book "The Component

// Object Model" from Addison Wesley. Blah blah blah

//

//

#define _WIN32_WINNT 0x403

#include <windows.h>

#include <stdio.h>

#include <initguid.h>

#include <wchar.h>

#include Β«../include/COMChat.hΒ»

#include Β«../include/COMChat_i.cΒ»

void Error(HRESULT hr, const char *psz)

{

printf(Β«%s failed and returned 0x%x\nΒ», psz, hr);

}

// utility function to print command line syntax

int Usage(void)

{

const char *psz =

Β«usage: client.exe <action> <user> <host>\nΒ»

Β« where:\nΒ»

Β« action = /sessions|/chat:session|/delete:session\nΒ»

Β« user = /user:domain\\user /password:pw |Β»

Β«/anonymous | <nothing>\nΒ»

Β« host = /host:hostname | <nothing>\nΒ»;

printf(psz);

return -1;

}

// utility function for printing a list of strings

void PrintAllStrings(IEnumString *pes)

{

enum { CHUNKSIZE = 64 };

OLECHAR *rgpwsz[CHUNKSIZE];

ULONG cFetched;

HRESULT hr;

do

{

hr = pes->Next(CHUNKSIZE, rgpwsz, &cFetched);

if (SUCCEEDED(hr))

{

for (ULONG i = 0; i < cFetched; i++)

if (rgpwsz[i])

{

wprintf(L"%s\n", rgpwsz[i]);

CoTaskMemFree(rgpwsz[i]);

}

}

} while (hr == S_OK);

}

// utility function to print initial state of

// a chat session

void PrintToDate(IChatSession *pcs)

{

IEnumString *pes = 0;

HRESULT hr = pcs->GetStatements(&pes);

if (SUCCEEDED(hr))

{

PrintAllStrings(pes);

pes->Release();

}

}

// this class implements the callback interface

// that receives chat notifications. It simply

// prints the event to the console

class EventSink : public IChatSessionEvents

{

public:

STDMETHODIMP QueryInterface(REFIID riid, void**ppv)

{

if (riid == IID_IUnknown)

*ppv = static_cast<IChatSessionEvents*>(this);

else if (riid == IID_IChatSessionEvents)

*ppv = static_cast<IChatSessionEvents*>(this);

else

return (*ppv = 0), E_NOINTERFACE;

reinterpret_cast<IUnknown*>(*ppv)->AddRef();

return S_OK;

}

STDMETHODIMP_(ULONG) AddRef(void)

{

return 2;

}

STDMETHODIMP_(ULONG) Release(void)

{

return 1;

}

STDMETHODIMP OnNewStatement(const OLECHAR *pwszUser,

const OLECHAR *pwszStmt)

{

wprintf(L"%-14s: %s\n", pwszUser, pwszStmt);

return S_OK;

}

STDMETHODIMP OnNewUser(const OLECHAR *pwszUser)

{

wprintf(L"\n\n>>> Say Hello to %s\n\n", pwszUser);

return S_OK;

}

STDMETHODIMP OnUserLeft(const OLECHAR *pwszUser)

{

wprintf(L"\n\n>>> Say Bye to %s\n\n", pwszUser);

return S_OK;

}


};

// type of operations this client can perform

enum ACTION

{

ACTION_NONE,

ACTION_CHAT,

ACTION_DELETE_SESSION,

ACTION_LIST_SESSION_NAMES,

};

// run chat command

void Chat(const OLECHAR *pwszSession,

IChatSessionManager *pcsm, // manager

COAUTHIDENTITY *pcai, // user

bool bAnonymous) // anonymous

{

// create or get the named session

IChatSession *pcs = 0;

HRESULT hr = pcsm->FindSession(pwszSession, FALSE,

TRUE, &pcs);

if (SUCCEEDED(hr))

{

// adjust security blanket for session interface

if (!bAnonymous)

hr = CoSetProxyBlanket(pcs, RPC_C_AUTHN_WINNT,

RPC_C_AUTHZ_NONE, 0,

RPC_C_AUTHN_LEVEL_PKT,

RPC_C_IMP_LEVEL_IDENTIFY,

pcai, EOAC_NONE);

// catch up on past messages

PrintToDate(pcs);

// hook up event sink to receive new messages

EventSink es;

DWORD dwReg;

hr = pcs->Advise(&es, &dwReg);

if (SUCCEEDED(hr))

{

// run UI loop to get statements from console and send them

OLECHAR wszStmt[4096];

while (_getws(wszStmt))

{

hr = pcs->Say(wszStmt);

if (FAILED(hr))

Error(hr, Β«SayΒ»);

}

// tear down connection for event sink

pcs->Unadvise(dwReg);

}

else

Error(hr, Β«AdviseΒ»);

// release chat session

pcs->Release();

}

else

Error(hr, Β«FindSessionΒ»);

}

// run delete command

void Delete(const OLECHAR *pwszSession,

IChatSessionManager *pcsm)

{

HRESULT hr = pcsm->DeleteSession(pwszSession);

if (FAILED(hr))

Error(hr, Β«DeleteSessionΒ»);

}

// run list command

void List(IChatSessionManager *pcsm)

{

IEnumString *pes = 0;

HRESULT hr = pcsm->GetSessionNames(&pes);

if (SUCCEEDED(hr))

{

printf(Β«Active Sessions:\nΒ»);

PrintAllStrings(pes);

pes->Release();

}

}

int main(int argc, char **argv)

{

// declare client control state

bool bAnonymous = false;

static OLECHAR wszSessionName[1024];

static OLECHAR wszDomainName[1024];

static OLECHAR wszUserName[1024];

static OLECHAR wszPassword[1024];

static OLECHAR wszHostName[1024];

COSERVERINFO csi = { 0, wszHostName, 0, 0 };

COSERVERINFO *pcsi = 0;

COAUTHIDENTITY cai = {

wszUserName,

0,

wszDomainName,

0,

wszPassword,

0,

SEC_WINNT_AUTH_IDENTITY_UNICODE

};

static COAUTHIDENTITY *pcai = 0;

static ACTION action = ACTION_NONE;

// parse command line

for (int i = 1; i < argc; i++)

{

if (strcmp(argv[i], Β«/anonymousΒ») == 0)

bAnonymous = true;

else if (strstr(argv[i], Β«/delete:Β») == argv[i])

{

if (action != ACTION_NONE)

return Usage();

action = ACTION_DELETE_SESSION;

mbstowcs(wszSessionName, argv[i] + 8, 1024);

}

else if (strstr(argv[i], Β«/chat:Β») == argv[i])

{

if (action != ACTION_NONE)

return Usage();

action = ACTION_CHAT;

mbstowcs(wszSessionName, argv[i] + 6, 1024);

}

else if (strcmp(argv[i], Β«/sessionsΒ») == 0)

{

if (action != ACTION_NONE)

return Usage();

action = ACTION_LIST_SESSION_NAMES;