I've been fighting with the same issue for several weeks now and it has
me completely stuck. I was hoping someone might have some experience
and guidance developing an ActiveSync service provider and could offer
some advice. I have some specific questions about ObjectNotify (in
particular the ONF_CHANGED and ONF_DELETED flags in a one to many
object mapping), but first let me describe the end symptom I've been
unable to overcome.

The problem I experience is that records transferred from the desktop
to the device take several connections to settle out correctly. More
specifically, if I add one new record to the desktop store, I see the
following happen:

Connection 1 - The record is correctly copied from the desktop to the
device. The ActiveSync manager shows that 1 of 1 record was processed
and everything is synchronized. Records appear on both stores as
expected.

Connection 2 - Even though nothing has changed, the second connection
will claim to process 2 records. From looking at my logs, the desktop
requests the record from the device (calling the device's GetPacket
function - although the SetPacket call on the desktop side does not
appear to have the RSF_CONFLICT_OBJECT flag set surprisingly.). The
record is sent up to the desktop and the ActiveSync Manager then
deletes the desktop object using the desktop's DeleteObject. It then
re-adds the desktop record as part of the SetPacket call. Finally it
tells the device to clear its dirty bits (ObjectNotify called with
ONF_CLEAR_CHANGE) associated with the record in question.

Connection 3 - The manager shows 1 record being processed. The record
is deleted from the desktop (DeleteObject).

Connection 4 - The manager shows 1 record being processed. The record
is copied from the device back to the desktop (SetPacket on the
desktop).

Connection 5 and later - No actions are necessary. Everything is
synchronized.

Aside from the inconvenience of requiring multiple connections, after
the third connection is problematic because the record disappears from
the desktop store until synchronized again upon connection 4.

To offer a little background, I have the device store all of the
records in a memory mapped file. When the file is passed into the
ObjectNotify function (without the ONF_CHANGED or ONF_DELETED flags), I
return a list of all items with changed records towards the front of
the list and unchanged at the end. The number of changed records gets
specified by cOidChg and the number of unchanged records using cOidDel.
I have the one file map to multiple objects.

I later implemented the FindObjects function hoping that would help,
but it didn't matter. It is now called and enumerates the lists in the
opposite order as the documentation requests (unchanged first and
changed second).

I admittedly do not entirely understand how to handle the cases where
ONF_CHANGED or ONF_DELETED are set in ObjectNotify since I have the one
file to many object mapping on the device side. I have tried many
things, but nothing has made much of a difference. All the
documentation I have found only describes it for a one to one mapping
and not a one to many mapping. I've logged the pNotify->oidObject
value whenever these flags are set, but I've never seen the value match
my object ID so I'm not sure what to make of it. If anyone has any
suggestions for this, it may be helpful.

I also checked wcesmgr.log and nothing seems to be out of the ordinary.
It reports that it is synchronizing 1 or 2 objects as described above
and also mentions the call to DeleteObject as a "DeleteObjectOnDesktop"
line item. From looking at my own debug logs, the desktop seems to
enumerate its objects fine and the IsItemChanged function returns that
the object has not changed (FALSE). Calls to the desktop function
CompareItem seem to work fine too. The device side is mainly
characterized by calls to GetObjTypeInfo, FindObjects, ObjectNotify,
GetPacket, and SetPacket.

My best guess is that there's something on the device side provider
causing this. I've played with ObjectNotify for a couple of weeks now
with no luck. Has anyone seen anything like this or have any
suggestions? Answers would be great, but even resources or suggestions
would be helpful. I feel like I'm running in circles at the present
and have been disappointed by the resources out there on active service
provider development. Any help would be much appreciated.

Thanks in advance.

Re: AS Provider Desktop to Device Transfer Problems by bpfrack

bpfrack
Sat May 06 14:00:33 CDT 2006

I was finally able to solve this problem. Since there is so little out
there to aid in active sync provider development, I wanted to share my
resolution with anyone searching the usenet groups with a similar
problem.

There are 3 things to watch out for which could lead to a problem
similar to what I have described. The third item is the one that had
me in trouble.

1. If you are mapping one file object to multiple objects, you need to
make sure that you return the number of changed and unchanged objects
in ObjectNotify. You use cOidDel for the number of unchanged objects,
so don't let the name fool you. Microsoft's documentation describes
how to do this, but their examples are always 1 to 1. Some people say
that you need to implement FindObjects to get the mapping to work, but
I don't believe that is the case (I haven't tried removing my
FindObjects function though, so I cannot say for sure. I do know that
implementing FindObjects in itself did not fix my problem). I believe
that because FindObject is documented in a more direct and
straightfoward manner, people tend to do it correctly and it solves
their problem.

2. Whereas the above point described the call to ObjectNotify where
neither ONF_CHANGED or ONF_DELETED are set, this pertains to when
ONF_CLEAR_CHANGE is set. If your ObjectNotify function returns TRUE
when this is set, then it tells the activesync manager that the object
changed during synchronization and needs to be updated again. You
normally want to return FALSE to tell it that the object has not
changed between the time it was transferred (GetPacket call) and the
call to ObjectNotify to clear the dirty bits with ONF_CLEAR_CHANGE set.

3. Ultimately, the part that I was missing was that in my device
provider's SetPacket function, I did not set oidNew to the object ID
but instead left the value uninitialized. The REPLSETUP structure has
an oid (an input to your provider) and an oidNew (an output) member.
When data is transferred from the desktop to the device, the activesync
manager makes up its own object ID for the record. It passes that to
your device's SetPacket function. It is up to the device SetPacket
function to specify the actual objID that it is going to use for the
object in oidNew. If you do not set this value, whatever value it has
will be returned to the activesync manager and it will assume that this
random value is the object ID. When you synchronize again, it looks
for these random values which won't match the data values returned in
your lists by the ObjectNotify or FindObjects call. As a result, it
thinks those objects need transferred over because it doesn't have a
record of them. You simply need to set oidNew to the object ID you
save it under in your device store when your device provider's
SetPacket function is called. I only believe that you need to do this
on the device side. I finally figured this out when reading through
Microsoft's documentation yet again to try to focus on any object ID
notes and catching a brief mention of oidNew in the FAQ. The comments
are very brief, but gave me enough insight to figure this out.

I remain sadly disappointed in the amount of documentation and
resources available for ActiveSync developers. I have previously done
development for Palm devices and Palm Synchronization Conduits. At the
time, I thought synchronization development there was tedious.
ActiveSync has been much worse in my experience though. If anyone
knows of any helpful resources, I'd definately be interested. In the
meantime, I encourage anyone posting problems to also post their
solutions so we can help each other out!