Implement DoesStringRoundTripW,@371-3,@392.
Move a couple of string functions into string.c
reg.c \
regstream.c \
shlwapi_main.c \
+ stopwatch.c \
string.c \
thread.c \
url.c \
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
-#include "ddeml.h"
#include "docobj.h"
#include "exdisp.h"
#include "shlguid.h"
extern HMODULE SHLWAPI_hcomdlg32;
extern HMODULE SHLWAPI_hcomctl32;
extern HMODULE SHLWAPI_hmpr;
-extern HMODULE SHLWAPI_hmlang;
extern HMODULE SHLWAPI_hurlmon;
extern HMODULE SHLWAPI_hversion;
/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
static fnpSHBrowseForFolderW pSHBrowseForFolderW;
-typedef HRESULT (WINAPI *fnpConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
-static fnpConvertINetUnicodeToMultiByte pConvertINetUnicodeToMultiByte;
typedef BOOL (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
static fnpPlaySoundW pPlaySoundW;
typedef DWORD (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
/*************************************************************************
* @ [SHLWAPI.15]
*
- * Unicode version of SHLWAPI_14.
+ * Unicode version of GetAcceptLanguagesA.
*/
HRESULT WINAPI GetAcceptLanguagesW(
LPWSTR langbuf,
{
char xguid[40];
INT iLen = SHStringFromGUIDA(guid, xguid, cchMax);
-
+
if (iLen)
MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax);
return iLen;
return TRUE;
}
-/*************************************************************************
- * @ [SHLWAPI.162]
- *
- * Remove a hanging lead byte from the end of a string, if present.
- *
- * PARAMS
- * lpStr [I] String to check for a hanging lead byte
- * size [I] Length of lpStr
- *
- * RETURNS
- * Success: The new length of the string. Any hanging lead bytes are removed.
- * Failure: 0, if any parameters are invalid.
- */
-DWORD WINAPI SHTruncateString(LPSTR lpStr, DWORD size)
-{
- if (lpStr && size)
- {
- LPSTR lastByte = lpStr + size - 1;
-
- while(lpStr < lastByte)
- lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
-
- if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
- {
- *lpStr = '\0';
- size--;
- }
- return size;
- }
- return 0;
-}
-
/*************************************************************************
* @ [SHLWAPI.163]
*
return 1;
}
-/*************************************************************************
- * @ [SHLWAPI.215]
- *
- * NOTES
- * check me!
- */
-DWORD WINAPI SHAnsiToUnicode(
- LPCSTR lpStrSrc,
- LPWSTR lpwStrDest,
- int len)
-{
- INT len_a, ret;
-
- len_a = lstrlenA(lpStrSrc);
- ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
- TRACE("%s %s %d, ret=%d\n",
- debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
- return ret;
-}
-
-/*************************************************************************
- * @ [SHLWAPI.218]
- *
- * WideCharToMultiByte with support for multiple codepages.
- *
- * PARAMS
- * CodePage [I] Code page to use for the conversion
- * lpSrcStr [I] Source Unicode string to convert
- * lpDstStr [O] Destination for converted Ascii string
- * lpnMultiCharCount [O] Input length of lpDstStr/destination for length of lpDstStr
- *
- * RETURNS
- * Success: The number of characters that result from the conversion.
- * Failure: 0.
- */
-INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
- LPINT lpnMultiCharCount)
-{
- WCHAR emptyW[] = { '\0' };
- int len , reqLen;
- LPSTR mem;
-
- if (!lpDstStr || !lpnMultiCharCount)
- return 0;
-
- if (!lpSrcStr)
- lpSrcStr = emptyW;
-
- *lpDstStr = '\0';
-
- len = strlenW(lpSrcStr) + 1;
-
- switch (CodePage)
- {
- case CP_WINUNICODE:
- CodePage = CP_UTF8; /* Fall through... */
- case 0x0000C350: /* FIXME: CP_ #define */
- case CP_UTF7:
- case CP_UTF8:
- {
- DWORD dwMode = 0;
- INT nWideCharCount = len - 1;
-
- GET_FUNC(pConvertINetUnicodeToMultiByte, mlang, "ConvertINetUnicodeToMultiByte", 0);
- if (!pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
- lpnMultiCharCount))
- return 0;
-
- if (nWideCharCount < len - 1)
- {
- mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
- if (!mem)
- return 0;
-
- *lpnMultiCharCount = 0;
-
- if (pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
- {
- SHTruncateString(mem, *lpnMultiCharCount);
- lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
- return *lpnMultiCharCount + 1;
- }
- HeapFree(GetProcessHeap(), 0, mem);
- return *lpnMultiCharCount;
- }
- lpDstStr[*lpnMultiCharCount] = '\0';
- return *lpnMultiCharCount;
- }
- break;
- default:
- break;
- }
-
- reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
- *lpnMultiCharCount, NULL, NULL);
-
- if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
- if (reqLen)
- {
- mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
- if (mem)
- {
- reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
- reqLen, NULL, NULL);
-
- reqLen = SHTruncateString(mem, *lpnMultiCharCount);
- reqLen++;
-
- lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
-
- HeapFree(GetProcessHeap(), 0, mem);
- }
- }
- }
- return reqLen;
-}
-
-/*************************************************************************
- * @ [SHLWAPI.217]
- *
- * WideCharToMultiByte with support for multiple codepages.
- *
- * PARAMS
- * lpSrcStr [I] Source Unicode string to convert
- * lpDstStr [O] Destination for converted Ascii string
- * lpnMultiCharCount [O] Input length of lpDstStr/destination for length of lpDstStr
- *
- * RETURNS
- * See SHUnicodeToAnsiCP
-
- * NOTES
- * This function simply calls SHUnicodeToAnsiCP with CodePage = CP_ACP.
- */
-INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
-{
- INT myint = MultiCharCount;
-
- return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, &myint);
-}
-
typedef struct {
REFIID refid;
DWORD indx;
return DefWindowProcA(hWnd, uMessage, wParam, lParam);
}
-/*************************************************************************
- * @ [SHLWAPI.241]
- *
- */
-DWORD WINAPI StopWatchMode()
-{
- FIXME("()stub\n");
- return /* 0xabba1243 */ 0;
-}
-
/*************************************************************************
* @ [SHLWAPI.257]
*
return hRet;
}
-/*************************************************************************
- * @ [SHLWAPI.364]
- *
- * Copy one string to another, up to a given length.
- *
- * PARAMS
- * lpszSrc [I] Source string to copy
- * lpszDst [O] Destination for copied string
- * iLen [I] Number of characters to copy
- *
- * RETURNS
- * TRUE.
- */
-DWORD WINAPI DoesStringRoundTripA(LPCSTR lpszSrc, LPSTR lpszDst, INT iLen)
-{
- lstrcpynA(lpszDst, lpszSrc, iLen);
- return TRUE;
-}
-
/*************************************************************************
* @ [SHLWAPI.370]
*
239 stdcall -noname SHUnregisterClassesW(ptr ptr long)
240 stdcall -noname SHDefWindowProc(long long long long)
241 stdcall -noname StopWatchMode()
-242 stub -noname StopWatchFlush
-243 stub -noname StopWatchA
-244 stub -noname StopWatchW
-245 stub -noname StopWatch_TimerHandler
+242 stdcall -noname StopWatchFlush()
+243 stdcall -noname StopWatchA(long str long long long)
+244 stdcall -noname StopWatchW(long wstr long long long)
+245 stdcall -noname StopWatch_TimerHandler(ptr ptr long ptr)
246 stub -noname StopWatch_CheckMsg
-247 stub -noname StopWatch_MarkFrameStart
-248 stub -noname StopWatch_MarkSameFramStart
-249 stub -noname StopWatch_MarkJavaStop
-250 stub -noname GetPerfTime
+247 stdcall -noname StopWatch_MarkFrameStart(str)
+248 stub -noname StopWatch_MarkSameFrameStart
+249 stdcall -noname StopWatch_MarkJavaStop(wstr ptr long)
+250 stdcall -noname GetPerfTime()
251 stub -noname StopWatch_DispatchTime
-252 stub -noname StopWatch_SetMsgLastLocation
+252 stdcall -noname StopWatch_SetMsgLastLocation(long)
253 stub -noname StopWatchExA
254 stub -noname StopWatchExW
255 stub -noname EventTraceHandler
361 stdcall @(wstr ptr long) kernel32.GetShortPathNameW
362 stdcall @(ptr ptr) advapi32.GetUserNameW
363 stdcall -noname SHInvokeCommand(ptr ptr ptr long)
-364 stdcall -noname DoesStringRoundTripA(str str long)
-365 stub -noname DoesStringRoundTripW
+364 stdcall -noname DoesStringRoundTripA(str ptr long)
+365 stdcall -noname DoesStringRoundTripW(wstr ptr long)
366 stdcall @(long long ptr ptr ptr ptr ptr ptr) advapi32.RegEnumValueW
367 stdcall @(wstr wstr ptr long wstr) kernel32.WritePrivateProfileStructW
368 stdcall @(wstr wstr ptr long wstr) kernel32.GetPrivateProfileStructW
369 stdcall @(wstr wstr ptr ptr long long ptr wstr ptr ptr) kernel32.CreateProcessW
370 stdcall -noname ExtractIconWrapW(long wstr long)
-371 stub -noname DdeInitializeWrapW
-372 stub -noname DdeCreateStringHandleWrapW
-373 stub -noname DdeQueryStringWrapW
+371 stdcall -noname DdeInitializeWrapW(ptr ptr long long) user32.DdeInitializeW
+372 stdcall -noname DdeCreateStringHandleWrapW(long ptr long) user32.DdeCreateStringHandleW
+373 stdcall -noname DdeQueryStringWrapW(long ptr wstr long long) user32.DdeQueryStringW
374 stub -noname SHCheckDiskForMediaA
375 stub -noname SHCheckDiskForMediaW
376 stdcall -noname MLGetUILanguage() # kernel32.GetUserDefaultUILanguage
389 stdcall -noname GetSaveFileNameWrapW(ptr)
390 stdcall -noname WNetRestoreConnectionWrapW(long wstr)
391 stdcall -noname WNetGetLastErrorWrapW(ptr ptr long ptr long)
-392 stub -noname EndDialogWrap
+392 stdcall -noname EndDialogWrap(ptr ptr) user32.EndDialog
393 stdcall @(long ptr long ptr long) user32.CreateDialogIndirectParamW
394 stdcall @(long ptr long ptr long) user32.CreateDialogIndirectParamA
395 stub -noname MLWinHelpA
--- /dev/null
+/*
+ * Stopwatch Functions
+ *
+ * Copyright 2004 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTES
+ * These functions probably never need to be implemented unless we
+ * A) Rewrite explorer from scratch, and
+ * B) Want to use a substandard API to tune its performance.
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "wine/unicode.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winreg.h"
+#define NO_SHLWAPI_STREAM
+#include "shlwapi.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+/*************************************************************************
+ * @ [SHLWAPI.241]
+ *
+ * Get the current performance monitoring mode.
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * The current performance monitoring mode. This is zero if monitoring
+ * is disabled (the default).
+ *
+ * NOTES
+ * If this function returns 0, no further StopWatch functions should be called.
+ */
+DWORD WINAPI StopWatchMode()
+{
+ FIXME("() stub!\n");
+ return 0;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.242]
+ *
+ * Write captured performance nodes to a log file.
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * Nothing.
+ */
+void WINAPI StopWatchFlush()
+{
+ FIXME("() stub!\n");
+}
+
+
+/*************************************************************************
+ * @ [SHLWAPI.243]
+ *
+ * Write a performance event to a log file
+ *
+ * PARAMS
+ * dwClass [I] Class of event
+ * lpszStr [I] Text of event to log
+ * dwUnknown [I] Unknown
+ * dwMode [I] Mode flags
+ * dwTimeStamp [I] Timestamp
+ *
+ * RETURNS
+ * Success: ERROR_SUCCESS.
+ * Failure: A standard Win32 error code indicating the failure.
+ */
+DWORD WINAPI StopWatchA(DWORD dwClass, LPCSTR lpszStr, DWORD dwUnknown,
+ DWORD dwMode, DWORD dwTimeStamp)
+{
+ FIXME("(%ld,%s,%ld,%ld,%ld) stub!\n", dwClass, debugstr_a(lpszStr),
+ dwUnknown, dwMode, dwTimeStamp);
+ return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.244]
+ *
+ * See StopWatchA.
+ */
+DWORD WINAPI StopWatchW(DWORD dwClass, LPCWSTR lpszStr, DWORD dwUnknown,
+ DWORD dwMode, DWORD dwTimeStamp)
+{
+ char szBuff[MAX_PATH];
+
+ if(!WideCharToMultiByte(0, 0, lpszStr, -1, szBuff, MAX_PATH, 0, 0))
+ return ERROR_NOT_ENOUGH_MEMORY;
+
+ return StopWatchA(dwClass, szBuff, dwUnknown, dwMode, dwTimeStamp);
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.245]
+ *
+ * Log a shell frame event.
+ *
+ * PARAMS
+ * hWnd [I] Window having the event
+ * pvUnknown1 [I] Unknown
+ * bUnknown2 [I] Unknown
+ * pClassWnd [I] Window of class to log
+ *
+ * RETURNS
+ * Nothing.
+ */
+void WINAPI StopWatch_TimerHandler(HWND hWnd, PVOID pvUnknown1, BOOL bUnknown2, HWND *pClassWnd)
+{
+ FIXME("(%p,%p,%d,%p) stub!\n", hWnd, pvUnknown1, bUnknown2 ,pClassWnd);
+}
+
+/* FIXME: Parameters for @246:StopWatch_CheckMsg unknown */
+
+/*************************************************************************
+ * @ [SHLWAPI.247]
+ *
+ * Log the start of an applet.
+ *
+ * PARAMS
+ * lpszName [I] Name of the applet
+ *
+ * RETURNS
+ * Nothing.
+ */
+void WINAPI StopWatch_MarkFrameStart(LPCSTR lpszName)
+{
+ FIXME("(%s) stub!\n", debugstr_a(lpszName));
+}
+
+/* FIXME: Parameters for @248:StopWatch_MarkSameFrameStart unknown */
+
+/*************************************************************************
+ * @ [SHLWAPI.249]
+ *
+ * Log a java applet stopping.
+ *
+ * PARAMS
+ * lpszEvent [I] Name of the event (applet)
+ * hWnd [I] Window running the applet
+ * dwReserved [I] Unused
+ *
+ * RETURNS
+ * Nothing.
+ */
+void WINAPI StopWatch_MarkJavaStop(LPCWSTR lpszEvent, HWND hWnd, DWORD dwReserved)
+{
+ FIXME("(%s,%p,0x%08lx) stub!\n", debugstr_w(lpszEvent), hWnd, dwReserved);
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.250]
+ *
+ * Read the performance counter.
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * The low 32 bits of the current performance counter reading.
+ */
+DWORD WINAPI GetPerfTime()
+{
+ static LONG64 iCounterFreq = 0;
+ LARGE_INTEGER iCounter;
+
+ TRACE("()\n");
+
+ if (!iCounterFreq)
+ QueryPerformanceFrequency((LARGE_INTEGER*)&iCounterFreq);
+
+ QueryPerformanceCounter(&iCounter);
+ iCounter.QuadPart = iCounter.QuadPart * 1000 / iCounterFreq;
+ return iCounter.u.LowPart;
+}
+
+/* FIXME: Parameters for @251:StopWatch_DispatchTime unknown */
+
+/*************************************************************************
+ * @ [SHLWAPI.252]
+ *
+ * Set an as yet unidentified performance value.
+ *
+ * PARAMS
+ * dwUnknown [I] Value to set
+ *
+ * RETURNS
+ * dwUnknown.
+ */
+DWORD WINAPI StopWatch_SetMsgLastLocation(DWORD dwUnknown)
+{
+ FIXME("(%ld) stub!\n", dwUnknown);
+
+ return dwUnknown;
+}
+
+/* FIXME: Parameters for @253:StopWatchExA, 254:StopWatchExW unknown */
#include "wingdi.h"
#include "winuser.h"
#include "shlobj.h"
+#include "ddeml.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
+/* Get a function pointer from a DLL handle */
+#define GET_FUNC(func, module, name, fail) \
+ do { \
+ if (!func) { \
+ if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
+ func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
+ if (!func) return fail; \
+ } \
+ } while (0)
+
+extern HMODULE SHLWAPI_hmlang;
+
+typedef HRESULT (WINAPI *fnpConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
+static fnpConvertINetUnicodeToMultiByte pConvertINetUnicodeToMultiByte;
+
static HRESULT WINAPI _SHStrDupAA(LPCSTR,LPSTR*);
static HRESULT WINAPI _SHStrDupAW(LPCWSTR,LPSTR*);
return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
}
+/*************************************************************************
+ * @ [SHLWAPI.162]
+ *
+ * Remove a hanging lead byte from the end of a string, if present.
+ *
+ * PARAMS
+ * lpStr [I] String to check for a hanging lead byte
+ * size [I] Length of lpStr
+ *
+ * RETURNS
+ * Success: The new length of the string. Any hanging lead bytes are removed.
+ * Failure: 0, if any parameters are invalid.
+ */
+DWORD WINAPI SHTruncateString(LPSTR lpStr, DWORD size)
+{
+ if (lpStr && size)
+ {
+ LPSTR lastByte = lpStr + size - 1;
+
+ while(lpStr < lastByte)
+ lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
+
+ if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
+ {
+ *lpStr = '\0';
+ size--;
+ }
+ return size;
+ }
+ return 0;
+}
+
/*************************************************************************
* @ [SHLWAPI.203]
*
return ch;
}
+
+/*************************************************************************
+ * @ [SHLWAPI.215]
+ *
+ * Convert an Ascii string to Unicode.
+ *
+ * PARAMS
+ * lpSrcStr [I] Source Ascii string to convert
+ * lpDstStr [O] Destination for converted Unicode string
+ * iLen [I] Length of lpDstStr
+ *
+ * RETURNS
+ * The return value of the MultiByteToWideChar() function called on lpSrcStr.
+ */
+DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
+{
+ DWORD dwRet;
+
+ dwRet = MultiByteToWideChar(CP_ACP, 0, lpSrcStr, -1, lpDstStr, iLen);
+ TRACE("%s->%s,ret=%ld\n", debugstr_a(lpSrcStr), debugstr_w(lpDstStr), dwRet);
+ return dwRet;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.218]
+ *
+ * Convert a Unicode string to Ascii.
+ *
+ * PARAMS
+ * CodePage [I] Code page to use for the conversion
+ * lpSrcStr [I] Source Unicode string to convert
+ * lpDstStr [O] Destination for converted Ascii string
+ * lpiLen [I/O] Input length of lpDstStr/destination for length of lpDstStr
+ *
+ * RETURNS
+ * Success: The number of characters that result from the conversion.
+ * Failure: 0.
+ */
+INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
+ LPINT lpiLen)
+{
+ WCHAR emptyW[] = { '\0' };
+ int len , reqLen;
+ LPSTR mem;
+
+ if (!lpDstStr || !lpiLen)
+ return 0;
+
+ if (!lpSrcStr)
+ lpSrcStr = emptyW;
+
+ *lpDstStr = '\0';
+
+ len = strlenW(lpSrcStr) + 1;
+
+ switch (CodePage)
+ {
+ case CP_WINUNICODE:
+ CodePage = CP_UTF8; /* Fall through... */
+ case 0x0000C350: /* FIXME: CP_ #define */
+ case CP_UTF7:
+ case CP_UTF8:
+ {
+ DWORD dwMode = 0;
+ INT nWideCharCount = len - 1;
+
+ GET_FUNC(pConvertINetUnicodeToMultiByte, mlang, "ConvertINetUnicodeToMultiByte", 0);
+ if (!pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
+ lpiLen))
+ return 0;
+
+ if (nWideCharCount < len - 1)
+ {
+ mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpiLen);
+ if (!mem)
+ return 0;
+
+ *lpiLen = 0;
+
+ if (pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpiLen))
+ {
+ SHTruncateString(mem, *lpiLen);
+ lstrcpynA(lpDstStr, mem, *lpiLen + 1);
+ return *lpiLen + 1;
+ }
+ HeapFree(GetProcessHeap(), 0, mem);
+ return *lpiLen;
+ }
+ lpDstStr[*lpiLen] = '\0';
+ return *lpiLen;
+ }
+ break;
+ default:
+ break;
+ }
+
+ reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
+ *lpiLen, NULL, NULL);
+
+ if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
+ if (reqLen)
+ {
+ mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
+ if (mem)
+ {
+ reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
+ reqLen, NULL, NULL);
+
+ reqLen = SHTruncateString(mem, *lpiLen);
+ reqLen++;
+
+ lstrcpynA(lpDstStr, mem, *lpiLen);
+
+ HeapFree(GetProcessHeap(), 0, mem);
+ }
+ }
+ }
+ return reqLen;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.217]
+ *
+ * Convert a Unicode string to Ascii.
+ *
+ * PARAMS
+ * lpSrcStr [I] Source Unicode string to convert
+ * lpDstStr [O] Destination for converted Ascii string
+ * iLen [O] Length of lpDstStr in characters
+ *
+ * RETURNS
+ * See SHUnicodeToAnsiCP
+
+ * NOTES
+ * This function simply calls SHUnicodeToAnsiCP() with CodePage = CP_ACP.
+ */
+INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
+{
+ INT myint = iLen;
+
+ return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, &myint);
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.364]
+ *
+ * Determine if an Ascii string converts to Unicode and back identically.
+ *
+ * PARAMS
+ * lpSrcStr [I] Source Unicode string to convert
+ * lpDst [O] Destination for resulting Ascii string
+ * iLen [I] Length of lpDst in characters
+ *
+ * RETURNS
+ * TRUE, since Ascii strings always convert identically.
+ */
+BOOL WINAPI DoesStringRoundTripA(LPCSTR lpSrcStr, LPSTR lpDst, INT iLen)
+{
+ lstrcpynA(lpDst, lpSrcStr, iLen);
+ return TRUE;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.365]
+ *
+ * Determine if a Unicode string converts to Ascii and back identically.
+ *
+ * PARAMS
+ * lpSrcStr [I] Source Unicode string to convert
+ * lpDst [O] Destination for resulting Ascii string
+ * iLen [I] Length of lpDst in characters
+ *
+ * RETURNS
+ * TRUE, if lpSrcStr converts to Ascii and back identically,
+ * FALSE otherwise.
+ */
+BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen)
+{
+ WCHAR szBuff[MAX_PATH];
+
+ SHUnicodeToAnsi(lpSrcStr, lpDst, iLen);
+ SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
+ return !strcmpW(lpSrcStr, szBuff);
+}