Here is a quick, dirty and superficial description of how things work in the MS an Widcomm stacks.
With Widcomm you have to define classes derived from various Widcomm base classes. These have virtual members that are called when certain things happen.
So for example, to find bluetooth devices, you derive a class from CBtIf, and call the StartInquiry member. Each time a bluetooth device is encountered your overloaded OnDeviceResponded member is called, and you must store the device address away somewhere. When all devices have been iterated (meaning some timeout threshold has been reached) your OnInquiryComplete member is called.
Then you call StartDiscovery for each device that was found, passing the device address and the service GUID you're looking for. When the stack is done talking to the device (or times out) your OnDiscoveryComplete member is called. You then call ReadDiscoveryRecords, the return code of which will let you know if it discovered the service. If it did, you call FindRFCommScn which provides the 64 bit ID of the service (port) that you will connect to.
Now, once you've found something to connect to, the process is similar for actual data transfer, but worse. It is worse because with discovery you can pretty much just block (using events) until you've found something or given up. With data transfer you derive from CRfCommPort, and your overloaded OnDataReceived will be hammered, from some other thread, as data packets flow. So you'll need to setup some thread safe method of storing away that received data, and add in flow control to stop the data flow whenever your cache grows too big. I use a linked list with a node per packet, while keeping track of how much I've allocated and calling SetFlowEnabled if I've exceeded my cache size. My app's thread is grabbing data out as it needs it, again, in a thread-safe fashion (Critical Sections), and enables flow when enough of the cache has been consumed.
That's all Widcomm specific. With MS stack some parts are saner, like iterating devices and the actual IO. However finding the specific service on a device and connecting to it is far more complex.
To find devices it is all iterative, using WSALookupServiceBegin and WSALookupServiceNext. A few lines of code is all that is required to simply see what devices are out there. Finding a service is a royal pain in the butt, and requires some really low level crap with BT. It involves COM (as in Component Object Model) interfaces, that have to be invoked to parse a bunch of junk, to first find your desired service GUID, and second, extract the port that service is bound to. Once you have that, you simply connect to it as you would any old socket, and the rest is typical socks stuff.
A portion of the original code I hacked up to find a specific service on a device is here:
http://www.developer.com/ws/other/print ... _3640576_3
Anyway, the whole BT experience was an ordeal with both stacks. At least the Widcomm stack was bread and butter stuff for me - thread safety being the most complex part, and having to wrap it in a separate DLL because you can't dynamically link to their DLL (unless you don't care that your app can't execute on non-widcomm devices). So basically it was just a bit of tedium doing extra work because they like C++ classes and multithreading so much. With MS I felt like I was delving too far into the deep, dark chasms of the bloated, consortium-defined Bluetooth specifications for my liking. It was too much out of my control, and dependent on traversing complex data structures that are proprietary to bluetooth.
Dan East