internal DdeConversation(DdemlConversation conversation) { _DdemlObject = conversation; _DdemlObject.StateChange += this.OnStateChange; _Service = _DdemlObject.Service; _Topic = _DdemlObject.Topic; _Handle = _DdemlObject.Handle; _IsPaused = _DdemlObject.IsPaused; }
protected virtual RequestResult OnRequest(DdemlConversation conversation, string item, int format) { return RequestResult.NotProcessed; }
protected virtual PokeResult OnPoke(DdemlConversation conversation, string item, byte[] data, int format) { return PokeResult.NotProcessed; }
protected virtual ExecuteResult OnExecute(DdemlConversation conversation, string command) { return ExecuteResult.NotProcessed; }
protected virtual void OnDisconnect(DdemlConversation conversation) { }
protected virtual void OnAfterConnect(DdemlConversation conversation) { }
public virtual void Resume(DdemlConversation conversation) { if (IsDisposed) { throw new ObjectDisposedException(this.GetType().ToString()); } if (!IsRegistered) { throw new InvalidOperationException(Resources.NotRegisteredMessage); } if (conversation == null) { throw new ArgumentNullException("conversation"); } if (!conversation.IsPaused) { throw new InvalidOperationException(Resources.NotPausedMessage); } // Enable the DDEML callback for the specified conversation only. bool result = Ddeml.DdeEnableCallback(_InstanceId, conversation.Handle, Ddeml.EC_ENABLEALL); // Check the result to see if the DDEML callback was enabled. if (!result) { int error = Ddeml.DdeGetLastError(_InstanceId); throw new DdemlException(Resources.ServerResumeFailedMessage, error); } // Decrement the conversation's waiting count. The conversation will only resume if the count is zero. conversation.DecrementWaiting(); }
protected override void OnAfterConnect(DdemlConversation conversation) { DdeConversation c = new DdeConversation(conversation); conversation.Tag = c; _Parent.OnAfterConnect(c); }
protected override void OnStopAdvise(DdemlConversation conversation, string item) { _Parent.OnStopAdvise((DdeConversation)conversation.Tag, item); }
protected override RequestResult OnRequest(DdemlConversation conversation, string item, int format) { DdeServer.RequestResult result = _Parent.OnRequest((DdeConversation)conversation.Tag, item, format); if (result == DdeServer.RequestResult.NotProcessed) { return RequestResult.NotProcessed; } if (result == DdeServer.RequestResult.PauseConversation) { return RequestResult.PauseConversation; } if (result == DdeServer.RequestResult.Processed) { return new RequestResult(result.Data); } return RequestResult.NotProcessed; }
protected override bool OnStartAdvise(DdemlConversation conversation, string item, int format) { return _Parent.OnStartAdvise((DdeConversation)conversation.Tag, item, format); }
protected override PokeResult OnPoke(DdemlConversation conversation, string item, byte[] data, int format) { DdeServer.PokeResult result = _Parent.OnPoke((DdeConversation)conversation.Tag, item, data, format); if (result == DdeServer.PokeResult.NotProcessed) { return PokeResult.NotProcessed; } if (result == DdeServer.PokeResult.PauseConversation) { return PokeResult.PauseConversation; } if (result == DdeServer.PokeResult.Processed) { return PokeResult.Processed; } if (result == DdeServer.PokeResult.TooBusy) { return PokeResult.TooBusy; } return PokeResult.NotProcessed; }
protected override ExecuteResult OnExecute(DdemlConversation conversation, string command) { DdeServer.ExecuteResult result = _Parent.OnExecute((DdeConversation)conversation.Tag, command); if (result == DdeServer.ExecuteResult.NotProcessed) { return ExecuteResult.NotProcessed; } if (result == DdeServer.ExecuteResult.PauseConversation) { return ExecuteResult.PauseConversation; } if (result == DdeServer.ExecuteResult.Processed) { return ExecuteResult.Processed; } if (result == DdeServer.ExecuteResult.TooBusy) { return ExecuteResult.TooBusy; } return ExecuteResult.NotProcessed; }
protected override void OnDisconnect(DdemlConversation conversation) { _Parent.OnDisconnect((DdeConversation)conversation.Tag); }
protected virtual bool OnStartAdvise(DdemlConversation conversation, string item, int format) { return true; }
public virtual void Disconnect(DdemlConversation conversation) { if (IsDisposed) { throw new ObjectDisposedException(this.GetType().ToString()); } if (!IsRegistered) { throw new InvalidOperationException(Resources.NotRegisteredMessage); } if (conversation == null) { throw new ArgumentNullException("conversation"); } if (_ConversationTable.ContainsKey(conversation.Handle)) { // Terminate the conversation. Ddeml.DdeDisconnect(conversation.Handle); // Remove the Conversation from the conversation table. _ConversationTable.Remove(conversation.Handle); } }
protected virtual void OnStopAdvise(DdemlConversation conversation, string item) { }
internal bool ProcessCallback(DdemlTransaction transaction) { // This is here to alias the transaction object with a shorter variable name. DdemlTransaction t = transaction; switch (t.uType) { case Ddeml.XTYP_ADVREQ: { StringBuilder psz; int length; // Get the topic name from the hsz1 string handle. psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); length = Ddeml.DdeQueryString(_InstanceId, t.hsz1, psz, psz.Capacity, Ddeml.CP_WINANSI); string topic = psz.ToString(); // Get the item name from the hsz2 string handle. psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); length = Ddeml.DdeQueryString(_InstanceId, t.hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI); string item = psz.ToString(); // Create the advise request cache key. string key = topic + "!" + item + ":" + t.uFmt.ToString(); // Get the data being advised if the cache does not contain it already. if (!_AdviseRequestCache.ContainsKey(key)) { // Get the data from the subclass. byte[] data = OnAdvise(topic, item, t.uFmt); // Add the data to the cache because it will be needed later. _AdviseRequestCache.Add(key, data); } // Get the data from the advise request cache. byte[] cached = _AdviseRequestCache[key]; // Get the number of remaining transactions of this type for the same topic name, item name, and format tuple. int remaining = t.dwData1.ToInt32(); // If this is the last transaction then free the data handle. if (remaining == 0) { // TODO: Does the data handle really need to be freed here? // Remove the data from the cache because it is no longer needed. _AdviseRequestCache.Remove(key); } // Create and return the data handle representing the data being advised. if (cached != null && cached.Length > 0) { t.dwRet = Ddeml.DdeCreateDataHandle(_InstanceId, cached, cached.Length, 0, t.hsz2, t.uFmt, 0); return true; } // This transaction could not be processed here. return false; } case Ddeml.XTYP_ADVSTART: { // Get the item name from the hsz2 string handle. StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); int length = Ddeml.DdeQueryString(_InstanceId, t.hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI); string item = psz.ToString(); // Get the Conversation from the conversation table. DdemlConversation conversation = _ConversationTable[t.hConv]; // Get a value indicating whether an advise loop should be initiated from the subclass. t.dwRet = OnStartAdvise(conversation, item, t.uFmt) ? new IntPtr(1) : IntPtr.Zero; return true; } case Ddeml.XTYP_ADVSTOP: { // Get the item name from the hsz2 string handle. StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); int length = Ddeml.DdeQueryString(_InstanceId, t.hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI); string item = psz.ToString(); // Get the Conversation from the conversation table. DdemlConversation conversation = _ConversationTable[t.hConv]; // Inform the subclass that the advise loop has been terminated. OnStopAdvise(conversation, item); // Return zero to indicate that there are no problems. t.dwRet = IntPtr.Zero; return true; } case Ddeml.XTYP_CONNECT: { // Get the topic name from the hsz1 string handle. StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); int length = Ddeml.DdeQueryString(_InstanceId, t.hsz1, psz, psz.Capacity, Ddeml.CP_WINANSI); string topic = psz.ToString(); // Get a value from the subclass indicating whether the connection should be allowed. t.dwRet = OnBeforeConnect(topic) ? new IntPtr(1) : IntPtr.Zero; return true; } case Ddeml.XTYP_CONNECT_CONFIRM: { // Get the topic name from the hsz1 string handle. StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); int length = Ddeml.DdeQueryString(_InstanceId, t.hsz1, psz, psz.Capacity, Ddeml.CP_WINANSI); string topic = psz.ToString(); // Create a Conversation object and add it to the conversation table. _ConversationTable.Add(t.hConv, new DdemlConversation(t.hConv, _Service, topic)); // Inform the subclass that a conversation has been established. OnAfterConnect(_ConversationTable[t.hConv]); // Return zero to indicate that there are no problems. t.dwRet = IntPtr.Zero; return true; } case Ddeml.XTYP_DISCONNECT: { // Get the Conversation from the conversation table. DdemlConversation conversation = _ConversationTable[t.hConv]; // Remove the Conversation from the conversation table. _ConversationTable.Remove(t.hConv); // Inform the subclass that the conversation has been disconnected. OnDisconnect(conversation); // Return zero to indicate that there are no problems. t.dwRet = IntPtr.Zero; return true; } case Ddeml.XTYP_EXECUTE: { // Get the command from the data handle. int length = Ddeml.DdeGetData(t.hData, null, 0, 0); byte[] data = new byte[length]; length = Ddeml.DdeGetData(t.hData, data, data.Length, 0); string command = _Context.Encoding.GetString(data, 0, data.Length); if (command[command.Length - 1] == '\0') { command = command.Substring(0, command.Length - 1); } // Get the Conversation from the conversation table. DdemlConversation conversation = _ConversationTable[t.hConv]; // Send the command to the subclass and get the result. ExecuteResult result = OnExecute(conversation, command); // Return DDE_FACK if the subclass processed the command successfully. if (result == ExecuteResult.Processed) { t.dwRet = new IntPtr(Ddeml.DDE_FACK); return true; } // Return CBR_BLOCK if the subclass needs time to process the command. if (result == ExecuteResult.PauseConversation) { // Increment the conversation's waiting count. conversation.IncrementWaiting(); t.dwRet = new IntPtr(Ddeml.CBR_BLOCK); return true; } // Return DDE_FBUSY if the subclass is too busy. if (result == ExecuteResult.TooBusy) { t.dwRet = new IntPtr(Ddeml.DDE_FBUSY); return true; } // Return DDE_FNOTPROCESSED if the subclass did not process the command. t.dwRet = new IntPtr(Ddeml.DDE_FNOTPROCESSED); return true; } case Ddeml.XTYP_POKE: { // Get the item name from the hsz2 string handle. StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); int length = Ddeml.DdeQueryString(_InstanceId, t.hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI); string item = psz.ToString(); // Get the data from the data handle. length = Ddeml.DdeGetData(t.hData, null, 0, 0); byte[] data = new byte[length]; length = Ddeml.DdeGetData(t.hData, data, data.Length, 0); // Get the Conversation from the conversation table. DdemlConversation conversation = _ConversationTable[t.hConv]; // Send the data to the subclass and get the result. PokeResult result = OnPoke(conversation, item, data, t.uFmt); // Return DDE_FACK if the subclass processed the data successfully. if (result == PokeResult.Processed) { t.dwRet = new IntPtr(Ddeml.DDE_FACK); return true; } // Return CBR_BLOCK if the subclass needs time to process the data. if (result == PokeResult.PauseConversation) { // Increment the conversation's waiting count. conversation.IncrementWaiting(); t.dwRet = new IntPtr(Ddeml.CBR_BLOCK); return true; } // Return DDE_FBUSY if the subclass is too busy. if (result == PokeResult.TooBusy) { t.dwRet = new IntPtr(Ddeml.DDE_FBUSY); return true; } // Return DDE_FNOTPROCESSED if the subclass did not process the data. t.dwRet = new IntPtr(Ddeml.DDE_FNOTPROCESSED); return true; } case Ddeml.XTYP_REQUEST: { // Get the item name from the hsz2 string handle. StringBuilder psz = new StringBuilder(Ddeml.MAX_STRING_SIZE); int length = Ddeml.DdeQueryString(_InstanceId, t.hsz2, psz, psz.Capacity, Ddeml.CP_WINANSI); string item = psz.ToString(); // Get the Conversation from the conversation table. DdemlConversation conversation = _ConversationTable[t.hConv]; // Send the request to the subclass and get the result. RequestResult result = OnRequest(conversation, item, t.uFmt); // Return a data handle if the subclass processed the request successfully. if (result == RequestResult.Processed) { // Create and return the data handle for the data being requested. if (result.Data != null) { t.dwRet = Ddeml.DdeCreateDataHandle(_InstanceId, result.Data, result.Data.Length, 0, t.hsz2, t.uFmt, 0); } return true; } // Return CBR_BLOCK if the subclass needs time to process the request. if (result == RequestResult.PauseConversation) { conversation.IncrementWaiting(); t.dwRet = new IntPtr(Ddeml.CBR_BLOCK); return true; } // Return DDE_FNOTPROCESSED if the subclass did not process the command. t.dwRet = new IntPtr(Ddeml.DDE_FNOTPROCESSED); return true; } } // This transaction could not be processed here. return false; }