|
|
/*
* Microsoft Confidential * Copyright (C) Microsoft Corporation 1991 * All Rights Reserved. * * * PIFSUB.C * Misc. subroutines for PIFMGR.DLL * * History: * Created 31-Jul-1992 3:30pm by Jeff Parsons */
#include "shellprv.h"
#pragma hdrstop
#ifdef _X86_
// shell priv can alter the definition of IsDBCSLeadByte!
#if defined(FE_SB)
#ifdef IsDBCSLeadByte
#undef IsDBCSLeadByte
#define IsDBCSLeadByte(x) IsDBCSLeadByteEx(CP_ACP,x)
#endif
#endif
/*
* Most of the routines in this file will need to stay ANSI. If a UNICODE * version is needed, it is supplied. * * This is because for the most part, the information in the PIF files * is ANSI and needs to stay that way. * * (RickTu) * */
/** lstrcpypadA - copy to fixed-length string, appending trailing blanks
* * INPUT * lpszDst -> fixed-length destination string * lpszSrc -> source string * cchMax = size of fixed-length destination string (count of characters) * * OUTPUT * Nothing */
void lstrcpypadA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax) { FunctionName(lstrcpypadA); while (cchMax && *lpszSrc) { cchMax--; *lpszDst++ = *lpszSrc++; } while (cchMax--) { *lpszDst++ = ' '; } }
/** lstrcpyncharA - copy variable-length string, until char
* * INPUT * lpszDst -> fixed-length destination string * lpszSrc -> source string * cchMax = size of fixed-length destination string (count of characters) * ch = character to stop copying at * * OUTPUT * # of characters copied, excluding terminating NULL */
int lstrcpyncharA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax, CHAR ch) { int cch = 0; FunctionName(lstrcpyncharA);
while (--cchMax && *lpszSrc && *lpszSrc != ch) { if (IsDBCSLeadByte(*lpszSrc)) { cch++; *lpszDst++ = *lpszSrc++; if (!*lpszSrc) break; /* Eek! String ends in DBCS lead byte! */ } cch++; *lpszDst++ = *lpszSrc++; } *lpszDst = '\0'; return cch; }
/** lstrskipcharA - skip char in variable-length string
* * INPUT * lpszSrc -> source string * ch = character to skip * * OUTPUT * # of characters skipped, 0 if none */
int lstrskipcharA(LPCSTR lpszSrc, CHAR ch) { int cch = 0; FunctionName(lstrskipcharA);
while (*lpszSrc && *lpszSrc == ch) { cch++; lpszSrc++; } return cch; }
/** lstrskiptocharA - skip *to* char in variable-length string
* * INPUT * lpszSrc -> source string * ch = character to skip *to* * * OUTPUT * # of characters skipped, 0 if none; if char didn't exist, then all * characters are skipped. */
int lstrskiptocharA(LPCSTR lpszSrc, CHAR ch) { int cch = 0; FunctionName(lstrskiptocharA);
while (*lpszSrc && *lpszSrc != ch) { cch++; lpszSrc++; } return cch; }
/** lstrcpyfnameA - copy filename appropriately
* * INPUT * pszDest -> output buffer * cchDest -> size of destination buffer in characters * pszSrc -> source filename * cbMax = size of output buffer * * OUTPUT * # of characters copied, including quotes if any, excluding terminating NULL */
int lstrcpyfnameA(PSTR pszDest, size_t cchDest, PCSTR pszSrc) { CHAR szDest[MAX_PATH]; // PathQuoteSpacesA requires a MAX_PATH buffer; ensure we're using one
HRESULT hr = StringCchCopyA(szDest, ARRAYSIZE(szDest), pszSrc); if (FAILED(hr)) { *pszDest = '\0'; return 0; }
PathQuoteSpacesA(szDest); // quote if necessary
hr = StringCchCopyA(pszDest, cchDest, szDest); if (FAILED(hr)) { *pszDest = '\0'; return 0; } return lstrlenA(pszDest); }
/** lstrunquotefnameA - unquote filename if it contains quotes
* * INPUT * lpszDst -> output buffer * lpszSrc -> source filename (quoted or unquoted) * cchMax = size of output buffer (count of characters) * fShort = TRUE if filename should be converted to 8.3 (eg, for real-mode); * -1 if the filename is known to not be quoted and should just be converted * OUTPUT * # of characters copied, excluding terminating NULL */
int lstrunquotefnameA(LPSTR lpszDst, LPCSTR lpszSrc, int cchMax, BOOL fShort) { int cch; FunctionName(lstrunquotefnameA);
if (fShort != -1) {
if (lpszSrc[0] == '\"') { cch = lstrcpyncharA(lpszDst, lpszSrc+1, cchMax, '\"'); } else { cch = lstrcpyncharA(lpszDst, lpszSrc, cchMax, ' '); } lpszSrc = lpszDst; } if (fShort) { HRESULT hr;
if (lpszSrc != lpszDst) { // copy so we can work on lpszDst buffer of known size
hr = StringCchCopyA(lpszDst, cchMax, lpszSrc); if (FAILED(hr)) { *lpszDst = '\0'; return 0; } }
CharToOemBuffA(lpszSrc, lpszDst, cchMax); cch = GetShortPathNameA( lpszSrc, lpszDst, cchMax ); if (cch >= cchMax) { *lpszDst = '\0'; return 0; }
if (cch) { // if no error...
if (fShort == TRUE) { // if conversion for real-mode...
if ((int)GetFileAttributesA(lpszDst) == -1) { // if filename doesn't exist,
// then just copy the 8.3 portion
// and hope the user's real-mode PATH
// ultimately finds it!
if (NULL != (lpszSrc = StrRChrA(lpszDst, NULL, '\\'))) { hr = StringCchCopyA(lpszDst, cchMax, lpszSrc+1); if (FAILED(hr)) { *lpszDst = '\0'; return 0; } } } } cch = lstrlenA(lpszDst); // recompute the length of the string
} } return cch; }
/** lstrskipfnameA - skip filename in string
* * INPUT * lpszSrc -> string beginning with filename (quoted or unquoted) * * OUTPUT * # of characters skipped, 0 if none */
int lstrskipfnameA(LPCSTR lpszSrc) { int cch = 0; FunctionName(lstrskipfname);
if (lpszSrc[0] == '\"') { cch = lstrskiptocharA(lpszSrc+1, '\"') + 1; if (lpszSrc[cch] == '\"') cch++; } else cch = lstrskiptocharA(lpszSrc, ' '); return cch; }
/*
* NOTE! The careful definitions of achBuf and achFmt, so that * we can support total output of 2 * MAX_STRING_SIZE bytes. */ int cdecl Warning(HWND hwnd, WORD id, WORD type, ...) { LPCTSTR lpchFmt; PPROPLINK ppl = NULL; TCHAR achBuf[2*MAX_STRING_SIZE]; #define achFmt (&achBuf[MAX_STRING_SIZE])
va_list ArgList; FunctionName(Warning);
lpchFmt = achFmt;
// We never use MB_FOCUS to mean whatever it's really supposed
// to mean; we just use it as a kludge to support warning dialogs
// when all we have is a ppl, not an hwnd.
if (type & MB_NOFOCUS) { ppl = (PPROPLINK)hwnd; hwnd = NULL; type &= ~MB_NOFOCUS; } else if (hwnd) ppl = ((PPROPLINK)GetWindowLongPtr(hwnd, DWLP_USER))->ppl;
if (id == IDS_ERROR + ERROR_NOT_ENOUGH_MEMORY) lpchFmt = TEXT(""); else { if (!LoadString(g_hinst, id, achFmt, MAX_STRING_SIZE)) { ASSERTFAIL(); lpchFmt = TEXT(""); } }
va_start(ArgList,type); wvnsprintf(achBuf, MAX_STRING_SIZE, lpchFmt, ArgList); va_end(ArgList);
lpchFmt = NULL; if (ppl) { ASSERTTRUE(ppl->iSig == PROP_SIG); if (!(lpchFmt = ppl->lpszTitle)) lpchFmt = ppl->szPathName+ppl->iFileName; } return MessageBox(hwnd, achBuf, lpchFmt, type); } #undef achFmt
int MemoryWarning(HWND hwnd) { FunctionName(MemoryWarning); return Warning(hwnd, IDS_ERROR + ERROR_NOT_ENOUGH_MEMORY, MB_ICONEXCLAMATION | MB_OK); }
LPTSTR LoadStringSafe(HWND hwnd, UINT id, LPTSTR lpsz, int cchsz) { FunctionName(LoadStringSafe); if (!LoadString(g_hinst, id, lpsz, cchsz)) { ASSERTFAIL(); if (hwnd) { MemoryWarning(hwnd); return NULL; } lpsz = TEXT(""); } return lpsz; }
/** SetDlgBits - Check various dialog checkboxes according to given flags
* * INPUT * hDlg = HWND of dialog box * pbinf -> array of bitinfo descriptors * cbinf = size of array * wFlags = flags * * OUTPUT * Returns NOTHING */
void SetDlgBits(HWND hDlg, PBINF pbinf, UINT cbinf, WORD wFlags) { FunctionName(SetDlgBits);
ASSERTTRUE(cbinf > 0); do { ASSERTTRUE((pbinf->bBit & 0x3F) < 16); CheckDlgButton(hDlg, pbinf->id, !!(wFlags & (1 << (pbinf->bBit & 0x3F))) == !(pbinf->bBit & 0x80)); } while (++pbinf, --cbinf); }
/** GetDlgBits - Set various flags according to dialog checkboxes
* * INPUT * hDlg = HWND of dialog box * pbinf -> array of bitinfo descriptors * cbinf = size of array * lpwFlags -> flags word * * OUTPUT * Returns NOTHING */
void GetDlgBits(HWND hDlg, PBINF pbinf, UINT cbinf, LPWORD lpwFlags) { WORD wFlags; FunctionName(GetDlgBits);
ASSERTTRUE(cbinf > 0); wFlags = *lpwFlags; do { ASSERTTRUE((pbinf->bBit & 0x3F) < 16);
if (pbinf->bBit & 0x40) // 0x40 is a special bit mask
continue; // that means "set but don't get
// this control's value"
wFlags &= ~(1 << (pbinf->bBit & 0x3F)); if (!!IsDlgButtonChecked(hDlg, pbinf->id) == !(pbinf->bBit & 0x80)) wFlags |= (1 << (pbinf->bBit & 0x3F));
} while (++pbinf, --cbinf); *lpwFlags = wFlags; }
/** SetDlgInts - Set various edit controls according to integer fields
* * INPUT * hDlg = HWND of dialog box * pvinf -> array of validation info descriptors * cvinf = size of array * lp -> structure of integers * * OUTPUT * Returns NOTHING */
void SetDlgInts(HWND hDlg, PVINF pvinf, UINT cvinf, LPVOID lp) { WORD wMin, wMax; FunctionName(SetDlgInts);
ASSERTTRUE(cvinf > 0); do { wMin = wMax = *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off);
if (pvinf->fbOpt & VINF_AUTO) {
SendDlgItemMessage(hDlg, pvinf->id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)g_szAuto);
AddDlgIntValues(hDlg, pvinf->id, pvinf->iMax);
if (wMin == 0) { SetDlgItemText(hDlg, pvinf->id, g_szAuto); continue; } } if (pvinf->fbOpt & VINF_AUTOMINMAX) {
SendDlgItemMessage(hDlg, pvinf->id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)g_szAuto); SendDlgItemMessage(hDlg, pvinf->id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)g_szNone);
AddDlgIntValues(hDlg, pvinf->id, pvinf->iMax);
// When AUTOMINMAX is set, we assume that the field
// we're validating is followed in its structure by a
// corresponding max WORD.
wMax = *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off + sizeof(WORD));
if (wMin == 0 && wMax == 0) { SetDlgItemText(hDlg, pvinf->id, g_szNone); continue; }
// Let's try to simplify things by mapping 0xFFFF (aka -1)
// to settings that mean "Auto"
if (wMin == 0xFFFF || wMax == 0xFFFF) { wMin = 0; wMax = (WORD)pvinf->iMax; }
if (wMax == (WORD)pvinf->iMax) { SetDlgItemText(hDlg, pvinf->id, g_szAuto); continue; }
if (wMin != wMax) { //
// We're in a bit of a quandary here. The settings show
// explicit min and max values which are not equal, probably
// due to settings inherited from a 3.1 PIF file. We'll
// just go with the wMax value. Fortunately for us, we
// don't actually have to *do* anything to make this happen.
//
} } SetDlgItemInt(hDlg, pvinf->id, wMin, pvinf->iMin < 0);
} while (++pvinf, --cvinf); }
/** AddDlgIntValues - Fill integer combo-box with appropriate values
* * INPUT * hDlg = HWND of dialog box * id = dialog control ID * iMax = maximum value * * OUTPUT * Returns NOTHING */
void AddDlgIntValues(HWND hDlg, int id, int iMax) { int iStart, iInc; TCHAR achValue[16];
// HACK to make this do something sensible with the environment max;
// they can still enter larger values (up to ENVSIZE_MAX) but I don't
// see any sense in encouraging it. -JTP
if ((WORD)iMax == ENVSIZE_MAX) iMax = 4096;
if ((iMax < 0) || (iMax == 0xFFFF)) // HACK to make this do something sensible
iMax = 16384; // with fields that allow huge maximums -JTP
iStart = iInc = iMax/16; // arbitrarily chop the range up 16 times
while (iStart <= iMax) { StringCchPrintf(achValue, ARRAYSIZE(achValue), TEXT("%d"), iStart); // ok to truncate
SendDlgItemMessage(hDlg, id, CB_ADDSTRING, 0, (LPARAM)(LPTSTR)achValue); iStart += iInc; } }
/** GetDlgInts - Set various integer fields according to dialog edit controls
* * INPUT * hDlg = HWND of dialog box * pvinf -> array of validation info descriptors * cvinf = size of array * lp -> structure of integers * * OUTPUT * Returns NOTHING */
void GetDlgInts(HWND hDlg, PVINF pvinf, int cvinf, LPVOID lp) { WORD wMin, wMax; UINT uTemp; BOOL fSuccess; TCHAR achText[32]; FunctionName(GetDlgInts);
ASSERTTRUE(cvinf > 0); do { uTemp = GetDlgItemInt(hDlg, pvinf->id, &fSuccess, pvinf->iMin < 0); ASSERT(HIWORD(uTemp)==0);
wMin = LOWORD(uTemp);
// In case of error, make sure wMin doesn't actually change
if (!fSuccess) wMin = *(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off);
if (pvinf->fbOpt & VINF_AUTO) {
GetDlgItemText(hDlg, pvinf->id, achText, ARRAYSIZE(achText));
if (lstrcmpi(achText, g_szAuto) == 0) { wMin = 0; } }
if (pvinf->fbOpt & VINF_AUTOMINMAX) {
// When AUTOMINMAX is set, we assume that the field
// we're validating is followed in its structure by a
// corresponding max WORD, which we will ZERO if the
// user selects NONE, or set to its MAXIMUM if the user
// selects AUTO, or otherwise set to match the specified
// MINIMUM.
wMax = wMin;
GetDlgItemText(hDlg, pvinf->id, achText, ARRAYSIZE(achText));
if (lstrcmpi(achText, g_szAuto) == 0) { wMin = 0; wMax = (WORD)pvinf->iMax; } else if (lstrcmpi(achText, g_szNone) == 0) { wMin = 0; wMax = 0; }
*(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off + sizeof(WORD)) = wMax; }
*(WORD UNALIGNED *)((LPBYTE)lp + pvinf->off) = wMin;
} while (++pvinf, --cvinf); }
/** ValidateDlgInts - Validate that integer fields are value
* * INPUT * hDlg = HWND of dialog box * pvinf -> array of validation descriptors * cvinf = size of array * * OUTPUT * Returns TRUE if something is wrong; FALSE if all is okay. */
BOOL ValidateDlgInts(HWND hDlg, PVINF pvinf, int cvinf) { DWORD dw; BOOL fSuccess; TCHAR achText[32]; FunctionName(ValidateDlgInts);
ASSERTTRUE(cvinf > 0); do { dw = GetDlgItemInt(hDlg, pvinf->id, &fSuccess, pvinf->iMin < 0);
// NOTE: AUTO is for "Auto" only, whereas AUTOMINMAX is for
// "Auto" and "None". However, in the interest of simplicity, I
// don't complain if either string is used in either case.
if (pvinf->fbOpt & (VINF_AUTO | VINF_AUTOMINMAX)) { if (!fSuccess) { GetDlgItemText(hDlg, pvinf->id, achText, ARRAYSIZE(achText)); if (lstrcmpi(achText, g_szNone) == 0 || lstrcmpi(achText, g_szAuto) == 0) { continue; // things be lookin' good, check next int...
} } } if (!fSuccess || dw < (DWORD)pvinf->iMin || dw > (DWORD)pvinf->iMax) { Warning(hDlg, pvinf->idMsg, MB_ICONEXCLAMATION | MB_OK, pvinf->iMin, pvinf->iMax); SendDlgItemMessage(hDlg, pvinf->id, EM_SETSEL, 0, MAKELPARAM(0,-1)); SetFocus(GetDlgItem(hDlg, pvinf->id)); return TRUE; // things be lookin' bad, bail out...
} } while (++pvinf, --cvinf); return FALSE; }
/*
* NOTE -- The compiler emits really bad code for some of these guys. * In those cases, we are merely wrapping a call; there is no need to save BP. */
/** LimitDlgItemText - Sets the limit for a dialog edit control
* * INPUT * hDlg = HWND of dialog box * iCtl = ID of control * uiLimit = text limit * * OUTPUT * None. */ void LimitDlgItemText(HWND hDlg, int iCtl, UINT uiLimit) { FunctionName(LimitDlgItemText);
SendDlgItemMessage(hDlg, iCtl, EM_LIMITTEXT, uiLimit, 0); }
/** SetDlgItemPosRange - Sets the pos and range for a dialog slider control
* * INPUT * hDlg = HWND of dialog box * iCtl = ID of control * uiPos = Current position * dwRange = Range (min in low word, max in high word) * * OUTPUT * None. */ void SetDlgItemPosRange(HWND hDlg, int iCtl, UINT uiPos, DWORD dwRange) { FunctionName(SetDlgItemPosRange);
SendDlgItemMessage(hDlg, iCtl, TBM_SETRANGE, 0, dwRange); SendDlgItemMessage(hDlg, iCtl, TBM_SETPOS, TRUE, uiPos); }
/** GetDlgItemPos - Gets the pos of a dialog slider control
* * INPUT * hDlg = HWND of dialog box * iCtl = ID of control * * OUTPUT * Trackbar position. */ UINT GetDlgItemPos(HWND hDlg, int iCtl) { FunctionName(GetDlgItemPos);
return (UINT)SendDlgItemMessage(hDlg, iCtl, TBM_GETPOS, 0, 0); }
/** SetDlgItemPct - Sets the pos for a dialog slider control that measures %
* * INPUT * hDlg = HWND of dialog box * iCtl = ID of control * uiPct = Current position (range 0 .. 100) * * OUTPUT * None. */ void SetDlgItemPct(HWND hDlg, int iCtl, UINT uiPct) { FunctionName(SetDlgItemPct);
SetDlgItemPosRange(hDlg, iCtl, uiPct / (100/NUM_TICKS), MAKELONG(0, NUM_TICKS)); }
/** GetDlgItemPct - Gets the pos of a dialog slider control that measures %
* * INPUT * hDlg = HWND of dialog box * iCtl = ID of control * * OUTPUT * Slider position in the range 0 .. 100. */ UINT GetDlgItemPct(HWND hDlg, int iCtl) { FunctionName(GetDlgItemPct);
return GetDlgItemPos(hDlg, iCtl) * (100/NUM_TICKS); }
/** AdjustRealModeControls - Disables selected items if single-app mode
* * If the proplink says that "single-application mode" is enabled, * then hide all controls whose IDs are less than 4000 and show all * controls whose IDs are greater than or equal to 5000. Controls whose * IDs are in the 4000's are immune to all this hiding/showing. Controls * in the 3000's are actually disabled rather than hidden. Controls in * the 6000's are actually disabled rather than hidden as well. * * RST: Ok, this is nice in theory, but now that we've pulled over this * stuff into shell32.dll, we'll have to go off the actual IDC_ * defines instead of the magic #'s of 3000, 4000 and 5000. * * IDC_ICONBMP == 3001 * IDC_PIF_STATIC == 4000 * IDC_REALMODEISABLE == 5001 * * So, when adding things to shell232.rc or ids.h, plan * accordingly. * * INPUT * ppl = proplink * hDlg = HWND of dialog box * * OUTPUT * Dialog items have been disabled/enabled shown/hidden. * Returns nonzero if we are in normal (not single-app) mode. */
BOOL CALLBACK EnableEnumProc(HWND hwnd, LPARAM lp) { int f; LONG l;
f = SW_SHOW; l = GetWindowLong(hwnd, GWL_ID);
if (!LOWORD(lp) && l < IDC_PIF_STATIC || LOWORD(lp) && l >= IDC_REALMODEDISABLE) f = SW_HIDE;
if (l < IDC_ICONBMP || l >= IDC_PIF_STATIC && l < IDC_CONFIGLBL) ShowWindow(hwnd, f); else EnableWindow(hwnd, f == SW_SHOW);
return TRUE; }
BOOL AdjustRealModeControls(PPROPLINK ppl, HWND hDlg) { BOOL fNormal; FunctionName(AdjustRealModeControls);
fNormal = !(ppl->flProp & PROP_REALMODE); EnumChildWindows(hDlg, EnableEnumProc, fNormal); return fNormal; }
/** OnWmHelp - Handle a WM_HELP message
* * This is called whenever the user presses F1 or clicks the help * button in the title bar. We forward the call on to the help engine. * * INPUT * lparam = LPARAM from WM_HELP message (LPHELPINFO) * pdwHelp = array of DWORDs of help info * * OUTPUT * * None. */
void OnWmHelp(LPARAM lparam, const DWORD *pdwHelp) { FunctionName(OnWmHelp);
WinHelp((HWND) ((LPHELPINFO) lparam)->hItemHandle, NULL, HELP_WM_HELP, (DWORD_PTR) (LPTSTR) pdwHelp); }
/** OnWmContextMenu - Handle a WM_CONTEXTMENU message
* * This is called whenever the user right-clicks on a control. * We forward the call on to the help engine. * * INPUT * wparam = WPARAM from WM_HELP message (HWND) * pdwHelp = array of DWORDs of help info * * OUTPUT * * None. */
void OnWmContextMenu(WPARAM wparam, const DWORD *pdwHelp) { FunctionName(OnWmContextMenu);
WinHelp((HWND) wparam, NULL, HELP_CONTEXTMENU, (DWORD_PTR) (LPTSTR) pdwHelp); }
#ifdef UNICODE
/** PifMgr_WCtoMBPath - Converts UNICODE path to it's ANSI representation
* * This is called whenever we need to convert a UNICODE path to it's * best approximation in ANSI. Sometimes this will be a direct mapping, * but sometimes not. We may have to use the short name, etc. * * INPUT * lpUniPath -> pointer UNICODE path (NULL terminated) * lpAnsiPath -> pointer to buffer to hold ANSI path * cchBuf -> size of ANSI buffer, in characters * * OUTPUT * * lpAnsiPath buffer contains ANSI representation of lpUniPath */
void PifMgr_WCtoMBPath(LPWSTR lpUniPath, LPSTR lpAnsiPath, UINT cchBuf ) { WCHAR awchPath[ MAX_PATH ]; // Should be bigger than any PIF string
CHAR achPath[ MAX_PATH ]; // Should be bigger than any PIF string
UINT cchAnsi = 0; HRESULT hr;
FunctionName(PifMgr_WCtoMBPath);
// Try converting to Ansi and then converting back and comparing.
// If we get back exactly what we started with, this is the "simple"
// case.
cchAnsi = WideCharToMultiByte( CP_ACP, 0, lpUniPath, -1, achPath, ARRAYSIZE(achPath), NULL, NULL );
if (cchAnsi && (cchAnsi<=cchBuf)) {
// Now try converting back
MultiByteToWideChar( CP_ACP, 0, achPath, -1, awchPath, ARRAYSIZE(awchPath) );
if (lstrcmp(lpUniPath,awchPath)==0) {
// We're done...copy over the string.
hr = StringCchCopyA( lpAnsiPath, cchBuf, achPath ); if (FAILED(hr)) { *lpAnsiPath = '\0'; } return;
}
// Well, the string has some unmappable UNICODE
// character in it, so try option #2 -- using the
// short path name.
goto TryShortPathName;
} else { int cch;
TryShortPathName: // Hmmm, the best we can do is to use the short path name and map
// it to ANSI.
cch = GetShortPathName(lpUniPath, awchPath, ARRAYSIZE(awchPath)); if (cch == 0 || cch >= ARRAYSIZE(awchPath)) { *lpAnsiPath = '\0'; return; }
cch = WideCharToMultiByte( CP_ACP, 0, awchPath, -1, lpAnsiPath, cchBuf, NULL, NULL ); if (cch == 0) { *lpAnsiPath = '\0'; return; } } } #endif
#endif // X86
|