Posts Tagged ‘C++’

AccEx C++ Library R3

Sunday, February 8th, 2009

AccEx Library for Open AIM DevelopersA new release of the AccEx library is now available. This is a library of functions and classes for C++ based Open AIM clients and plugins using the AIM SDK.

This release adds three new classes.

AccEx::CAccExPluginPreferences

This class wraps an AccEx::CAccExPreferences object to help you manage the reserved name space for preferences in a plugin. Open AIM Plugins can keep any number of preferences under the “aimcc.plugin.__GUID__.prefs.__PREF__” key specifier where __GUID__ is your plugin key and __PREF__ is any alphanumeric name for your preference.

The class is initialized with a pointer to the session and the plugin’s CLSID. It builds the base preference specifier for the plugin and gives you easy access to the preferences under it. The class also has methods to let you test if a given specifier is in the plugin’s name space and is of a particular preference. The GetPref() and SetPref() methods are identical to that of AccEx::CAccExPreferences with the only exception that you use the __PREF__ suffix rather than the full specifier.

AccEx::CAccExDAccEventSink

This class helps you implement your own DAccEvents handler. It differs from a the CAccEventSink supplied by the Open AIM SDK in a number of ways.

  1. Supports ATL
  2. Adds an OnPreEventMapFilter() function that you can use to filter out events
  3. Adds an OnUnknownDispId() function that you can use to catch unhandled events
  4. Wraps all calls to your handler functions in an exception handler
  5. Adds an OnException() function that is called when an exception occurs
  6. Event handlers are not virtual functions
  7. Does not implement the IAccSession manager (See: AccEx::CAccExIAccSessionArray)

AccEx::CAccExIAccSessionArray

This class helps you keep track of up to 10 IAccSession objects. The purpose of this class is to encapsulate the management of these interfaces in an array along with their connection point cookie. You can add, remove, and find sessions. There are handy methods to get the first session, also known as the primary session, check if the array is empty, and check if a session is already registered.

You can download the latest release and get more information at the AccEx page.

AccEx C++ Library R2

Saturday, January 31st, 2009

AccEx Library for Open AIM DevelopersA new release of the AccEx library is now available. This is a library of functions and classes for C++ based Open AIM clients and plugins using the AIM SDK.

This release adds some handy helper functions ported over from some of my previous posts. One makes it easier to register plugin commands and the other makes it easy to register an active modeless window in your plugin so that dialog navigation keys are functional. These versions are public domain.

As a follow-on to my post on pushing data to the user’s Buddy Updates feed, I added a new function that can be called to push a plugin installed or updated item to the feed.

I am now including a Visual Studio 2005 build project.

AccEx Solution Explorer

See the AccEx page for more details.

How to Debug a C++ AIM Plugin

Friday, January 30th, 2009

Here are some tips on how you can debug your own C++ plugins for AIM.

First, I suggest you get about three or four screen names. Developing C++ plugins requires a lot of client re-starts which can get you log-in rate-limited very fast. Also don’t forget to take advantage of the edit and continue feature in Visual Studio while debugging since this will save you a login cycle.

Debugging a plugin is a little bit different than an entire application. I typically compile my plugin in Visual Studio. Then launch AIM using my IM control panel program. Incidentally, this app also lets me kill AIM completely which I need to do when I crash or want to force a restart. When I see the login window, I attach the debugger via the attach to process dialog (CTRL+ALT+P). Look for the aim6.exe process and attach to it. I then set my breakpoints and log in.

NB: There are two things you should note with the debugger. First is to make sure you are debugging native code and not script; very easy to miss. Second, is that your breakpoints will appear as inactive at this time since the plugin is not loaded yet. As long as you make sure you are debugging native code you should not have to worry too much about the breakpoints being disabled. They should light up once you are online.

AIM has its own crash handler that collects stack trace and other information to send along. Since I am developing my own plugin, it makes no sense to report these crashes to AOL. You can temporarily disable it by renaming the C:\Program Files\Common Files\AOL\AOLDiag\tbdiag.dll file to something else. Without it, all crashes get handled by Windows which lets you attach the debugger at the crash point.

With just these few tips you should be able to get started on debugging your own plugins easily.

How to Push an Item to the Buddy Updates Feed

Wednesday, January 28th, 2009

In my previous post, I provided a tool to help you get a Buddy Updates feed. In this post, I will cover how you can programmatically push an item to this feed.

The first thing you should know before using this API is that you should observe some basic rules of netiquette:

  • Don’t push anything without checking with the user first.
  • Don’t persist any permission granted by the user unless you inform them of such persistence.
  • Provide a place where the user can view and edit their permission to push items to their feed.

Please keep the above rules in mind as you write clients and plugins that push data to a user’s Buddy Updates feed.

Version 1.6.8 of the AIM SDK provides an interface that you can use to push just about anything to the user’s Buddy Updates Feed. This is the same API used by the AIM client to push all plugin installs.

To push an item to this feed you will need to do get the buddy feed manger (IAccBuddyFeedManager) from the session (IAccSession), create a buddy feed item (IAccBuddyFeed), set its properties, and finally push the item via the buddy feed manager. Here is a simple function that adds a test item to the feed:

HRESULT PushTestFeed(IAccSession *pSession)
{
    CComPtr<IAccBuddyFeedManager> spFeedManager;
    if ( SUCCEEDED( get_BuddyFeedManager(pSession, &spFeedManager) ) )
    {
        CComPtr<IAccBuddyFeed> spFeed;
        if ( SUCCEEDED( spFeedManager->CreateBuddyFeed( &spFeed ) ) )
        {
            put_FeedTitle(spFeed, CComBSTR(OLESTR("Feed Title")) );
            put_FeedLink(spFeed, CComBSTR(OLESTR("Feed Link")));
            put_FeedDescription(spFeed, CComBSTR(OLESTR("Feed Description")));
            put_FeedPublisher(spFeed, CComBSTR(OLESTR("Feed Publisher")));
            put_ItemTitle(spFeed, CComBSTR(OLESTR("Item Title")));
            put_ItemLink(spFeed, CComBSTR(OLESTR("Item Link"))); 
            put_ItemDescription(spFeed, CComBSTR(OLESTR("Item Descrtiption"))); 
            put_ItemGuid(spFeed, CComBSTR(OLESTR("Item GUID")));
            put_ItemCategory(spFeed, CComBSTR(OLESTR("Item Category")));
            AccTransId transId;
            return spFeedManager->Push(spFeed, &transId);
        }
    }
    return E_FAIL;
}

The result of pushing the above content to my feed is shown here:

...
<item>
    <title>Feed Title : Item Title</title>
    <link>Item Link</link>
    <description>Item Description</description>
    <author>gusblog</author>
    <aimId>gusblog</aimId>
    <pubDate>Wed, 28 Jan 2009 10:00:00 GMT</pubDate>
    <category>Item Category</category>
    <origFeedTitle>Feed Title</origFeedTitle>
    <origFeedLink>Feed Link</origFeedLink>
    <guid>Item Guid</guid>
</item>
...

AIM uses the feed’s link as the source for the favicon.ico when rendering it in the client and on the web. You must be in the online state before you can push an item. Pushing an item with an existing item GUID in the feed will replace the current content.

Reading an AIM SDK Preference via C++

Wednesday, January 14th, 2009

The AIM SDK (AIMcc) has an interface called IAccPreferences that is used for reading and writing preferences. Preferences are associated with a session so they can only be accessed once you have an IAccSession object.

It is up to clients to implement the actual data store behind these preferences by registering an object that implements either IAccPreferencesHook or IAccPreferencesHook2. You can find more information about these interfaces in technote 3 of the AIM SDK.

In this two-part series I will provide some sample code for reading preferences. This first post provides an ATL/C++ example and my next post will provide a JavaScript example.

In the process of making easy to use sample code, I will need to create some helper classes. These classes will be part of an evolving distribution called AccEx which I am hereby placing in the public domain. I will start by distributing these as source files only until I have more classes. AccEx distributions will be available here.

For this post, I created a helper class in AccEx called CAccExPreferences in order to make it easy to read and write preferences in C++. This class has overloaded methods to help you read a preference in various native formats like bool, int, float, etc. and one method to write a preference from a CComVariant.

So let’s use this thing. Like I said above, the IAccPreferences interface is implemented by AIMcc and associated with the IAccSession since they are (mostly) per-user preferences. Therefore, the only thing you need to initialize a CAccExPreferences object is an IAccSession pointer. The class will take care of acquiring the IAccPreferences interface for you. Here is a simple use-case that reads a real AIMcc preference.

// This sample source is public domain
#include <stdafx.h>
#include "AccExPreferences.h"
 
static WCHAR kDisclosePluginsToBuddyFeed[] = 
    OLESTR("aimcc.privacy.disclosePluginsToBuddyFeed");
 
HRESULT CanDisclosePluginsToBuddyFeed(IAccSession *pIAccSession)
{
    bool enabled;
    AccEx::CAccExPreferences prefs(pIAccSession);
 
    if ( SUCCEEDED( 
            prefs.GetPref(kDisclosePluginsToBuddyFeed, enabled) 
         ) && enabled )
    {
        // preference is enabled.
        return S_OK;
    }
    return S_FALSE;
}

Stay tuned for my next post where I will do the same using JavaScript.