diff --git a/dlls/shlwapi/Makefile.in b/dlls/shlwapi/Makefile.in index f5eee2e2a52..a2f1d67a4c2 100644 --- a/dlls/shlwapi/Makefile.in +++ b/dlls/shlwapi/Makefile.in @@ -17,6 +17,7 @@ C_SRCS = \ reg.c \ regstream.c \ shlwapi_main.c \ + stopwatch.c \ string.c \ thread.c \ url.c \ diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c index 99a182172e7..394a4233dcf 100644 --- a/dlls/shlwapi/ordinal.c +++ b/dlls/shlwapi/ordinal.c @@ -34,7 +34,6 @@ #include "winbase.h" #include "winuser.h" #include "winnls.h" -#include "ddeml.h" #include "docobj.h" #include "exdisp.h" #include "shlguid.h" @@ -70,7 +69,6 @@ extern HMODULE SHLWAPI_hwinmm; extern HMODULE SHLWAPI_hcomdlg32; extern HMODULE SHLWAPI_hcomctl32; extern HMODULE SHLWAPI_hmpr; -extern HMODULE SHLWAPI_hmlang; extern HMODULE SHLWAPI_hurlmon; extern HMODULE SHLWAPI_hversion; @@ -86,8 +84,6 @@ static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00}; /* 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); @@ -585,7 +581,7 @@ HRESULT WINAPI GetAcceptLanguagesA( /************************************************************************* * @ [SHLWAPI.15] * - * Unicode version of SHLWAPI_14. + * Unicode version of GetAcceptLanguagesA. */ HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, @@ -670,7 +666,7 @@ INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax) { char xguid[40]; INT iLen = SHStringFromGUIDA(guid, xguid, cchMax); - + if (iLen) MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax); return iLen; @@ -1168,38 +1164,6 @@ BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen) 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] * @@ -2176,148 +2140,6 @@ DWORD WINAPI FDSA_DeleteItem( 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; @@ -2514,16 +2336,6 @@ LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM return DefWindowProcA(hWnd, uMessage, wParam, lParam); } -/************************************************************************* - * @ [SHLWAPI.241] - * - */ -DWORD WINAPI StopWatchMode() -{ - FIXME("()stub\n"); - return /* 0xabba1243 */ 0; -} - /************************************************************************* * @ [SHLWAPI.257] * @@ -3357,25 +3169,6 @@ HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST 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] * diff --git a/dlls/shlwapi/shlwapi.spec b/dlls/shlwapi/shlwapi.spec index c67e8003d7d..ce556fc9e30 100644 --- a/dlls/shlwapi/shlwapi.spec +++ b/dlls/shlwapi/shlwapi.spec @@ -239,17 +239,17 @@ 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,16 +361,16 @@ 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,7 +389,7 @@ 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 diff --git a/dlls/shlwapi/stopwatch.c b/dlls/shlwapi/stopwatch.c new file mode 100644 index 00000000000..173d9a0c50b --- /dev/null +++ b/dlls/shlwapi/stopwatch.c @@ -0,0 +1,228 @@ +/* + * 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 +#include +#include + +#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 */ diff --git a/dlls/shlwapi/string.c b/dlls/shlwapi/string.c index a6bae527c57..186406dab14 100644 --- a/dlls/shlwapi/string.c +++ b/dlls/shlwapi/string.c @@ -38,11 +38,27 @@ #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*); @@ -2389,6 +2405,38 @@ LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax) 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] * @@ -2429,3 +2477,189 @@ char WINAPI SHStripMneumonicA(LPCSTR lpszStr) 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); +}