BUG: GetTextExtentPoint Fails in App Based on Windows/Win32s

Last reviewed: March 2, 1996
Article ID: Q147647
The information in this article applies to:
  • Microsoft Windows Software Development Kit (SDK) version 3.1
  • Microsoft Win32 Application Programming Interface included with:

        - Microsoft Windows NT version 3.51
        - Microsoft Windows 95 version 4.0
        - Microsoft Win32s version 1.30c
    

SYMPTOMS

GetTextExtentPoint fails when all of the following conditions are present:

  • You have either a 16-bit application running under Windows 3.1 or a 32-bit application running under Win32s.
  • The application uses GetTextExtentPoint().
  • The string buffer parameter has been allocated with GlobalAlloc() or has been reallocated with GlobalReAlloc().
  • The string size is an exact multiple of 32 bytes.

Under Win32s, GetLastError returns an error 87 (Invalid Parameter). The debug version of Windows 3.1 displays a Fatal Exit code 0x700A with this error message:

   GetTextExtentPoint - Invalid string

CAUSE

As stated earlier, this problem occurs only when the allocated size of the string is an exact multiple of 32 bytes.

This is a bug in Microsoft Windows 3.1 that causes ramifications in a 16-bit application running under Windows 3.1. A 16-bit application running under Windows NT 3.51 will have the same problem, but it will run without any problems under Windows 95.

This bug is not specific to Win32s. However, because Win32s runs under the Windows environment, a 32-bit application running under Windows 3.1 by way of Win32s will also exhibit this problem. However, a 32-bit application running under Windows NT or Windows 95 will not exhibit this problem.

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. We are researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available.

MORE INFORMATION

Note that GetTextExtentPoint() will succeed if you pass a string constant that has a size that is a multiple of 32. For example, the following will work:

   GetTextExtentPoint(hDC, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 32, &size);

Sample Code to Reproduce Problem

Note that error checking is not implemented in the following code.

 HGLOBAL hMem;
 HDC hDC;
 SIZE size;
 int blksize, i;
 char szMsg[256];
 LPSTR lpBuf;

  blksize=32;
  #ifdef WIN32
    SetLastError(0);
  #endif

  hDC = GetDC(hWnd);
  hMem = GlobalAlloc(GHND, blksize);
  lpBuf = (LPSTR) GlobalLock(hMem);
  for (i=0; i<blksize; i++)
    lpBuf[i] = 't';

  if (!GetTextExtentPoint(hDC, lpBuf, blksize, &size))
  {
     #ifdef WIN32
       wsprintf(szMsg, "GetTextExtentPoint Error %d\r\n", GetLastError());
     #else
       wsprintf(szMsg, "GetTextExtentPoint Error\r\n);
     #endif
     MessageBox(NULL, szMsg, "Test", MB_OK);
  }
  GlobalUnlock(hMem);

  #ifdef WIN32
    SetLastError(0);
  #endif

  hMem = GlobalReAlloc(hMem, 2*blksize, GMEM_ZEROINIT);
  lpBuf = (LPSTR) GlobalLock(hMem);
  for (i=0; i<blksize; i++)
    lpBuf[blksize+i] = 'T';

  if (!GetTextExtentPoint(hDC, lpBuf, 2*blksize, &size))
  {
     #ifdef WIN32
       wsprintf(szMsg, "GetTextExtentPoint Error %d\r\n", GetLastError());
     #else
       wsprintf(szMsg, "GetTextExtentPoint Error \r\n");
     #endif
     MessageBox(NULL, szMsg, "Test", MB_OK);
  }

  GlobalUnlock(hMem);
  if (hMem) GlobalFree(hMem);


Additional reference words: win32s gdi 1.30c 4.00 3.10 3.51
KBCategory: kbprg kbbuglist
KBSubcategory: w32s kbgdi


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: March 2, 1996
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.