Microsoft KB Archive/827638

= BUG: Multithreaded Tablet PC Applications May Quit Because of Memory Corruption =

Article ID: 827638

Article Last Modified on 1/18/2007

-

APPLIES TO


 * Microsoft Windows XP Tablet PC Edition Software Development Kit 1.0
 * Microsoft Windows XP Tablet PC Edition Software Development Kit 1.0

-



SYMPTOMS
Under certain conditions, a class that derives from or that uses either the Microsoft.Ink.Ink class (Managed library) or the InkDisp component object model (COM) object in the Tablet PC functions may experience a memory corruption. The result of this corruption may be that the application quits.



CAUSE
This problem occurs because an internal component of the Ink object may not be correctly reference counted when the internal component is used in a multithreaded application.



WORKAROUND
To work around this problem, you (the developer) can create a dummy Ink object at application load-time and then destroy the dummy Ink object when the application shuts down.

Important The dummy Ink object must be maintained throughout the lifetime of the application; otherwise the heap corruption may still occur.



RESOLUTION
The following Microsoft Visual C++ code shows how to create and to destroy a dummy Ink object.



// WorkAround.cpp //   CComPtr CreateDummyInk {   // The ISF data for the dummy Ink object must be as follows: static const BYTE isf [] = {       0x00, 0xCC, 0x01, 0x00, 0x00, 0x00, 0xC0, 0xB8, 0x02, 0xB0, 0xEA, 0x01, 0x03, 0xBD, 0x01, 0x48,

0x01, 0x49, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00,

0x3B, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3F, 0x00, 0x00,

0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x43,

0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x32, 0x00,

0x00, 0x00, 0x00, 0x52, 0x01, 0x08, 0x00, 0x44, 0x32, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x32, 0x3D, 0x00, 0x00, 0x00,

0x00, 0x40, 0x00, 0x00, 0x47, 0x01, 0x35, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x36, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x46,

0x32, 0x57, 0x09, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x01, 0x08, 0x00, 0x56,

0x00, 0x00, 0x00, 0x00, 0x51, 0x32, 0x50, 0x32, 0x4A, 0x01, 0x08, 0x00, 0x0A, 0x01, 0x00,

};

// The following GUIDs are provided as an example of how to add // custom extended property GUIDs into the Ink objects. static const GUID guidExtProps [] = {       // {B2B38458-097B-41a1-B5B3-C46345DCB28B} { 0xb2b38458, 0x097b, 0x41a1, { 0xb5, 0xb3, 0xc4, 0x63, 0x45, 0xdc, 0xb2, 0x8b } },

// {D5BABAB9-8FBE-4581-B4F5-379EF8C82E91} { 0xd5babab9, 0x8fbe, 0x4581, { 0xb4, 0xf5, 0x37, 0x9e, 0xf8, 0xc8, 0x2e, 0x91 } }, };

CComVariant data; BYTE *pBuff = NULL;

// The variant is a one dimensional array of BYTEs. data.vt = VT_ARRAY | VT_UI1; SAFEARRAYBOUND sab; sab.lLbound = 0; sab.cElements = sizeof(isf);

// Allocate memory for the SafeArray. data.parray = SafeArrayCreate(VT_UI1, 1, &sab);

// Copy ISF into the SafeArray. SafeArrayAccessData(data.parray, (VOID **)(&pBuff)); memcpy(pBuff, isf, sizeof(isf)); SafeArrayUnaccessData(data.parray);

CComPtr spInk;

// Create an Ink object. HRESULT hr = spInk.CoCreateInstance(CLSID_InkDisp);

// Load the Ink data. if(SUCCEEDED(hr)) hr = spInk->Load(data);

CComPtr spDrawAttrs; CComPtr spStroke; if(SUCCEEDED(hr)) {           // Get DrawingAttributes object of the first stroke. // You do not have to check for stroke count, because // the ISF above contains one stroke. CComPtr spStrokes; hr = spInk->get_Strokes(&spStrokes); if(SUCCEEDED(hr)) {                   hr = spStrokes->Item(0, &spStroke); if(SUCCEEDED(hr)) {                          // Get the DrawingAttributes object from the stroke. hr = spStroke->get_DrawingAttributes(&spDrawAttrs); }               }        }

// Add custom properties to DrawingAttributes object. if(SUCCEEDED(hr)) {           // Get the extended properties from DrawingAttributes object. CComPtr spExtProperties; hr = spDrawAttrs->get_ExtendedProperties(&spExtProperties);

// Enumerate all the properties in the static array. ULONG cExtPropCount = sizeof(guidExtProps)/sizeof(GUID);

// Add enumerated properties to the extended property list. for(ULONG i = 0; SUCCEEDED(hr) && (i < cExtPropCount); ++i) {                   CComVariant vtData; vtData.vt = VT_UI1 | VT_ARRAY;

// The data size for extended properties can differ from // the actual size that would be used in the application. vtData.parray = SafeArrayCreateVector(VT_UI1, 0, sizeof(DWORD)); BYTE * pData = NULL; if(NULL != vtData.parray) {                           hr = SafeArrayAccessData(vtData.parray, (void **)&pData); }                   else hr = E_OUTOFMEMORY; if(SUCCEEDED(hr)) {                           memset(pData, 0, sizeof(DWORD)); hr = SafeArrayUnaccessData(vtData.parray); }                   if(SUCCEEDED(hr)) {                           CComPtr spExtProp; hr = spExtProperties->Add(CComBSTR(guidExtProps[i]), vtData, &spExtProp); }           }

// Add DrawingAttributes back to the stroke object // so that the extended properties stick to the // DrawingAttributes object. if(SUCCEEDED(hr)) hr = spStroke->putref_DrawingAttributes(spDrawAttrs); }

// If anything went wrong, unref the Ink object. if(FAILED(hr)) spInk = NULL;

return spInk; }



MORE INFORMATION
In the sample code in the &quot;Resolution&quot; section, the data size for a custom extended property may differ from the actual size that is used in the application. The sizes may be different because the operating system does not force the data size of a custom extended property to be the same size as the property that the application uses. Therefore, it is acceptable to create the same custom extended property with a different data size.



STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

