public virtual void Pause(DdemlConversation conversation) { if (IsDisposed) { throw new ObjectDisposedException(this.GetType().ToString()); } if (!IsRegistered) { throw new InvalidOperationException(DDE.NotRegisteredMessage); } if (conversation == null) { throw new ArgumentNullException("conversation"); } if (conversation.IsPaused) { throw new InvalidOperationException(DDE.AlreadyPausedMessage); } // Disable the DDEML callback for the specified conversation only. bool result = Ddeml.DdeEnableCallback(_InstanceId, conversation.Handle, Ddeml.EC_DISABLE); // Check the result to see if the DDEML callback was disabled. if (!result) { int error = Ddeml.DdeGetLastError(_InstanceId); throw new DdemlException(DDE.ServerPauseFailedMessage, error); } // Increment the conversation's waiting count. conversation.IncrementWaiting(); }
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) { // 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; }