How To Handle FNERR_BUFFERTOOSMALL in Windows (131462)



The information in this article applies to:

  • Microsoft Win32 Application Programming Interface (API), when used with:
    • Microsoft Windows 95
    • Microsoft Windows 98
    • the operating system: Microsoft Windows NT
    • the operating system: Microsoft Windows 2000

This article was previously published under Q131462

SUMMARY

When an application uses the Open File common dialog with the OFN_ALLOWMULTISELECT flag, there is a danger that the buffer passed to the common dialog in the OPENFILENAME.lpstrFile field will be too small. In this situation, GetOpenFileName() will return an error value and CommDlgExtendedError() will return FNERR_BUFFERTOOSMALL.

MORE INFORMATION

When you install a hook on the Open File common dialog using the OPENFILENAME.lpfnHook member, the dialog you are hooking is a child of the main Open File dialog. In CDN_SELCHANGE, you should check to see if the buffer originally allocated is large enough to handle all the files selected. You should reallocate the buffer if neccessary and free the previous allocated buffer to prevent memory leaks.

Here is an example of the subclass procedure:
extern "C"
{
WNDPROC* g_lpfnDialogProc =NULL;


unsigned int CALLBACK DialogHook(HWND hwnd, UINT uMsg, WPARAM wParam,
                          LPARAM lParam)
{
	static HWND hwndParentDialog;
	LPOFNOTIFY lpofn;
	int cbLength;
	static LPTSTR lpsz;
	static int LastLen;
	
	switch (uMsg)
	{
	case WM_INITDIALOG:
          // You need to use a copy of the OPENFILENAME struct used to
          // create this dialog. You can store a pointer to the
          // OPENFILENAME struct in the ofn.lCustData so you can
          // retrieve it here in the lParam. Once you have it, you
          // need to hang on to it. Using window properties provides a
          // good thread safe solution to using a global variable.

          if(!SetProp(GetParent(hwnd), "OFN", (void *) lParam))
	  MessageBox(NULL, "SET PRop Failed", "ERROR", MB_OK);
          return (0);

	  case WM_COMMAND:
		  {
			OutputDebugString("command\n");
		  }
		  break;
      case WM_NOTIFY:
          // The OFNOTIFY struct is passed in the lParam of this
          // message.

          lpofn = (LPOFNOTIFY) lParam;

          switch (lpofn->hdr.code)
          {
 	  	case CDN_SELCHANGE:
			  
		LPOPENFILENAME lpofn;
		cbLength = CommDlg_OpenSave_GetSpec(GetParent(hwnd), NULL, 0);
		  
		cbLength += _MAX_PATH;
		
   	     // The OFN struct is stored in a property of dialog window
			  		  
		lpofn = (LPOPENFILENAME) GetProp(GetParent(hwnd),
						  "OFN");
			
		if (lpofn->nMaxFile < cbLength)  

		{
			  // Free the previously allocated buffer.
			  if(lpsz)
				  HeapFree(GetProcessHeap(),
							0,
 				 	                lpsz);
  			 // Allocate a new buffer
			  lpsz = (LPTSTR) HeapAlloc(GetProcessHeap(),
						HEAP_ZERO_MEMORY,
						cbLength);
			  if (lpsz)
			  {
					  
				  lpofn->lpstrFile = lpsz;
				  lpofn->nMaxFile  = cbLength;
			  }
		  }
		  break;
			  
         }
          return (0);

      case WM_DESTROY:

          // Also need to free the property with the OPENFILENAME
          // struct.
          RemoveProp(GetParent(hwnd), "OFN");
          return (0);
  }
  return (0);
} 
				
Finally, this technique only works for 32-bit applications that are using the Explorer-type common dialogs.

Windows 95/98: For 32-bit applications that do not use the OFN_EXPLORER flag, it thunks to the 16-bit common dialog and the hook function only gets a copy of the OPENFILENAME structure.

Windows NT/2000: Applications should use Unicode version of the Open file Common dialog. For example, use OPENFILENAMEW structure and call GetOpenFileNameW API. This workaround will not work for Ansi version of open file Common dialog.

Modification Type:MinorLast Reviewed:12/16/2004
Keywords:kbCmnDlgFileO kbhowto KB131462