|
|
#include "shellprv.h"
#pragma hdrstop
#include "uemapp.h"
#define MAXRCSTRING 514
// Major hack follows to get this to work with the DEBUG alloc/free -- on NT
// Local and Global heap functions evaluate to the same heap. The problem
// here is that LocalFree gets mapped to DebugLocalFree, but when we
// call FormatMessage, the buffer is not allocated through DebugLocalAlloc,
// so it dies.
//
#ifdef DEBUG
#undef LocalFree
#define LocalFree GlobalFree
#endif
// this will check to see if lpcstr is a resource id or not. if it
// is, it will return a LPSTR containing the loaded resource.
// the caller must LocalFree this lpstr. if pszText IS a string, it
// will return pszText
//
// returns:
// pszText if it is already a string
// or
// LocalAlloced() memory to be freed with LocalFree
// if pszRet != pszText free pszRet
LPTSTR WINAPI ResourceCStrToStr(HINSTANCE hInst, LPCTSTR pszText) { TCHAR szTemp[MAXRCSTRING]; LPTSTR pszRet = NULL;
if (!IS_INTRESOURCE(pszText)) return (LPTSTR)pszText;
if (LOWORD((DWORD_PTR)pszText) && LoadString(hInst, LOWORD((DWORD_PTR)pszText), szTemp, ARRAYSIZE(szTemp))) { size_t cch = lstrlen(szTemp) + 1; pszRet = LocalAlloc(LPTR, cch * SIZEOF(TCHAR)); if (pszRet) StringCchCopy(pszRet, cch, szTemp); } return pszRet; }
LPSTR ResourceCStrToStrA(HINSTANCE hInst, LPCSTR pszText) { CHAR szTemp[MAXRCSTRING]; LPSTR pszRet = NULL;
if (!IS_INTRESOURCE(pszText)) return (LPSTR)pszText;
if (LOWORD((DWORD_PTR)pszText) && LoadStringA(hInst, LOWORD((DWORD_PTR)pszText), szTemp, ARRAYSIZE(szTemp))) { size_t cch = (lstrlenA(szTemp) + 1); pszRet = LocalAlloc(LPTR, cch * SIZEOF(CHAR)); if (pszRet) StringCchCopyA(pszRet, cch, szTemp); } return pszRet; }
LPTSTR _ConstructMessageString(HINSTANCE hInst, LPCTSTR pszMsg, va_list *ArgList) { LPTSTR pszRet; LPTSTR pszRes = ResourceCStrToStr(hInst, pszMsg); if (!pszRes) { DebugMsg(DM_ERROR, TEXT("_ConstructMessageString: Failed to load string template")); return NULL; }
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszRes, 0, 0, (LPTSTR)&pszRet, 0, ArgList)) { DebugMsg(DM_ERROR, TEXT("_ConstructMessageString: FormatMessage failed %d"),GetLastError()); DebugMsg(DM_ERROR, TEXT(" pszRes = %s"), pszRes ); DebugMsg(DM_ERROR, !IS_INTRESOURCE(pszMsg) ? TEXT(" pszMsg = %s") : TEXT(" pszMsg = 0x%x"), pszMsg ); pszRet = NULL; }
if (pszRes != pszMsg) LocalFree(pszRes);
return pszRet; // free with LocalFree()
}
LPSTR _ConstructMessageStringA(HINSTANCE hInst, LPCSTR pszMsg, va_list *ArgList) { LPSTR pszRet; LPSTR pszRes = ResourceCStrToStrA(hInst, pszMsg); if (!pszRes) { DebugMsg(DM_ERROR, TEXT("_ConstructMessageString: Failed to load string template")); return NULL; }
if (!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszRes, 0, 0, (LPSTR)&pszRet, 0, ArgList)) { DebugMsg(DM_ERROR, TEXT("_ConstructMessageString: FormatMessage failed %d"),GetLastError()); DebugMsg(DM_ERROR, TEXT(" pszRes = %S"), pszRes );
DebugMsg(DM_ERROR, !IS_INTRESOURCE(pszMsg) ? TEXT(" pszMsg = %s") : TEXT(" pszMsg = 0x%x"), pszMsg ); pszRet = NULL; }
if (pszRes != pszMsg) LocalFree(pszRes);
return pszRet; // free with LocalFree()
}
// NOTE: ShellMessageBoxW has been re-implemented in shlwapi, so shell32 redirects that api there
// Shlwapi doesn't need an A version (because it's in shell32), so we're leaving this code here...
//
int WINCAPI ShellMessageBoxA(HINSTANCE hInst, HWND hWnd, LPCSTR pszMsg, LPCSTR pszTitle, UINT fuStyle, ...) { LPSTR pszText; int result; CHAR szBuffer[80]; va_list ArgList;
// BUG 95214
#ifdef DEBUG
IUnknown* punk = NULL; if (SUCCEEDED(SHGetThreadRef(&punk)) && punk) { ASSERTMSG(hWnd != NULL, "shell32\\msgbox.c : ShellMessageBoxA - Caller should either be not under a browser or should have a parent hwnd"); punk->lpVtbl->Release(punk); } #endif
if (!IS_INTRESOURCE(pszTitle)) { // do nothing
} else if (LoadStringA(hInst, LOWORD((DWORD_PTR)pszTitle), szBuffer, ARRAYSIZE(szBuffer))) { // Allow this to be a resource ID or NULL to specifiy the parent's title
pszTitle = szBuffer; } else if (hWnd) { // Grab the title of the parent
GetWindowTextA(hWnd, szBuffer, ARRAYSIZE(szBuffer));
//
// we would rather not use the "Desktop" as our title,
// but sometimes that is the window that is used, and we dont
// have a better title. callers should review to make sure that
// they want "Desktop" as the title to the dialog in
// the case that the hwnd passed in is the desktop window.
//
if (!lstrcmpA(szBuffer, "Program Manager")) { LoadStringA(HINST_THISDLL, IDS_DESKTOP, szBuffer, ARRAYSIZE(szBuffer)); pszTitle = szBuffer; DebugMsg(TF_WARNING, TEXT("No caption for SHMsgBox() on desktop")); } else pszTitle = szBuffer; } else { pszTitle = ""; }
va_start(ArgList, fuStyle); pszText = _ConstructMessageStringA(hInst, pszMsg, &ArgList); va_end(ArgList);
if (pszText) { result = MessageBoxA(hWnd, pszText, pszTitle, fuStyle | MB_SETFOREGROUND); LocalFree(pszText); } else { DebugMsg(DM_ERROR, TEXT("smb: Not enough memory to put up dialog.")); result = -1; // memory failure
}
return result; }
//
// returns:
// pointer to formatted string, free this with SHFree() (not Free())
//
LPTSTR WINCAPI ShellConstructMessageString(HINSTANCE hInst, LPCTSTR pszMsg, ...) { LPTSTR pszRet; va_list ArgList;
va_start(ArgList, pszMsg);
pszRet = _ConstructMessageString(hInst, pszMsg, &ArgList);
va_end(ArgList);
return pszRet; // free with SHFree()
}
|