Reorganise/minor tidyup of ordinal functions.
Implement StrCmpLogicalW,StrFormatByteSizeA/W,StrFormatByteSize64A,
SHCreateStreamWrapper.
Fix some output .spec parameters from str to ptr.
Fix definition of StrFormatByteSize functions.
diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c
index 3c9b148..3a2a7b3 100644
--- a/dlls/shlwapi/ordinal.c
+++ b/dlls/shlwapi/ordinal.c
@@ -46,12 +46,21 @@
#include "winreg.h"
#include "winuser.h"
#include "wine/debug.h"
-#include "ordinal.h"
#include "shlwapi.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; \
+ if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
+ } \
+ } while (0)
+
+/* DLL handles for late bound calls */
extern HINSTANCE shlwapi_hInstance;
extern HMODULE SHLWAPI_hshell32;
extern HMODULE SHLWAPI_hwinmm;
@@ -70,61 +79,7 @@
/* following is GUID for IPersistMoniker::GetClassID -- see _174 */
static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
-/* The following schemes were identified in the native version of
- * SHLWAPI.DLL version 5.50
- */
-typedef enum {
- URL_SCHEME_INVALID = -1,
- URL_SCHEME_UNKNOWN = 0,
- URL_SCHEME_FTP,
- URL_SCHEME_HTTP,
- URL_SCHEME_GOPHER,
- URL_SCHEME_MAILTO,
- URL_SCHEME_NEWS,
- URL_SCHEME_NNTP,
- URL_SCHEME_TELNET,
- URL_SCHEME_WAIS,
- URL_SCHEME_FILE,
- URL_SCHEME_MK,
- URL_SCHEME_HTTPS,
- URL_SCHEME_SHELL,
- URL_SCHEME_SNEWS,
- URL_SCHEME_LOCAL,
- URL_SCHEME_JAVASCRIPT,
- URL_SCHEME_VBSCRIPT,
- URL_SCHEME_ABOUT,
- URL_SCHEME_RES,
- URL_SCHEME_MAXVALUE
-} URL_SCHEME;
-
-typedef struct {
- URL_SCHEME scheme_number;
- LPCSTR scheme_name;
-} SHL_2_inet_scheme;
-
-static const SHL_2_inet_scheme shlwapi_schemes[] = {
- {URL_SCHEME_FTP, "ftp"},
- {URL_SCHEME_HTTP, "http"},
- {URL_SCHEME_GOPHER, "gopher"},
- {URL_SCHEME_MAILTO, "mailto"},
- {URL_SCHEME_NEWS, "news"},
- {URL_SCHEME_NNTP, "nntp"},
- {URL_SCHEME_TELNET, "telnet"},
- {URL_SCHEME_WAIS, "wais"},
- {URL_SCHEME_FILE, "file"},
- {URL_SCHEME_MK, "mk"},
- {URL_SCHEME_HTTPS, "https"},
- {URL_SCHEME_SHELL, "shell"},
- {URL_SCHEME_SNEWS, "snews"},
- {URL_SCHEME_LOCAL, "local"},
- {URL_SCHEME_JAVASCRIPT, "javascript"},
- {URL_SCHEME_VBSCRIPT, "vbscript"},
- {URL_SCHEME_ABOUT, "about"},
- {URL_SCHEME_RES, "res"},
- {0, 0}
-};
-
-/* function pointers for GET_FUNC macro; these need to be global because of gcc bug */
+/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
static LPITEMIDLIST (WINAPI *pSHBrowseForFolderW)(LPBROWSEINFOW);
static HRESULT (WINAPI *pConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
static BOOL (WINAPI *pPlaySoundW)(LPCWSTR, HMODULE, DWORD);
@@ -160,189 +115,6 @@
*/
/*************************************************************************
- * @ [SHLWAPI.1]
- *
- * Identifies the Internet "scheme" in the passed string. ASCII based.
- * Also determines start and length of item after the ':'
- */
-DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
-{
- DWORD cnt;
- const SHL_2_inet_scheme *inet_pro;
-
- y->fcncde = URL_SCHEME_INVALID;
- if (y->size != 0x18) return E_INVALIDARG;
- /* FIXME: leading white space generates error of 0x80041001 which
- * is undefined
- */
- if (*x <= ' ') return 0x80041001;
- cnt = 0;
- y->sizep1 = 0;
- y->ap1 = x;
- while (*x) {
- if (*x == ':') {
- y->sizep1 = cnt;
- cnt = -1;
- y->ap2 = x+1;
- break;
- }
- x++;
- cnt++;
- }
-
- /* check for no scheme in string start */
- /* (apparently schemes *must* be larger than a single character) */
- if ((*x == '\0') || (y->sizep1 <= 1)) {
- y->ap1 = 0;
- return 0x80041001;
- }
-
- /* found scheme, set length of remainder */
- y->sizep2 = lstrlenA(y->ap2);
-
- /* see if known scheme and return indicator number */
- y->fcncde = URL_SCHEME_UNKNOWN;
- inet_pro = shlwapi_schemes;
- while (inet_pro->scheme_name) {
- if (!strncasecmp(inet_pro->scheme_name, y->ap1,
- min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
- y->fcncde = inet_pro->scheme_number;
- break;
- }
- inet_pro++;
- }
- return S_OK;
-}
-
-/*************************************************************************
- * @ [SHLWAPI.2]
- *
- * Identifies the Internet "scheme" in the passed string. UNICODE based.
- * Also determines start and length of item after the ':'
- */
-DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
-{
- DWORD cnt;
- const SHL_2_inet_scheme *inet_pro;
- LPSTR cmpstr;
- INT len;
-
- y->fcncde = URL_SCHEME_INVALID;
- if (y->size != 0x18) return E_INVALIDARG;
- /* FIXME: leading white space generates error of 0x80041001 which
- * is undefined
- */
- if (*x <= L' ') return 0x80041001;
- cnt = 0;
- y->sizep1 = 0;
- y->ap1 = x;
- while (*x) {
- if (*x == L':') {
- y->sizep1 = cnt;
- cnt = -1;
- y->ap2 = x+1;
- break;
- }
- x++;
- cnt++;
- }
-
- /* check for no scheme in string start */
- /* (apparently schemes *must* be larger than a single character) */
- if ((*x == L'\0') || (y->sizep1 <= 1)) {
- y->ap1 = 0;
- return 0x80041001;
- }
-
- /* found scheme, set length of remainder */
- y->sizep2 = lstrlenW(y->ap2);
-
- /* see if known scheme and return indicator number */
- len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
- cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
- WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
- y->fcncde = URL_SCHEME_UNKNOWN;
- inet_pro = shlwapi_schemes;
- while (inet_pro->scheme_name) {
- if (!strncasecmp(inet_pro->scheme_name, cmpstr,
- min(len, lstrlenA(inet_pro->scheme_name)))) {
- y->fcncde = inet_pro->scheme_number;
- break;
- }
- inet_pro++;
- }
- HeapFree(GetProcessHeap(), 0, cmpstr);
- return S_OK;
-}
-
-/*************************************************************************
- * @ [SHLWAPI.3]
- *
- * Determine if a file exists locally and is of an executable type.
- *
- * PARAMS
- * lpszFile [O] File to search for
- * dwWhich [I] Type of executable to search for
- *
- * RETURNS
- * TRUE If the file was found. lpszFile contains the file name.
- * FALSE Otherwise.
- *
- * NOTES
- * lpszPath is modified in place and must be at least MAX_PATH in length.
- * If the function returns FALSE, the path is modified to its orginal state.
- * If the given path contains an extension or dwWhich is 0, executable
- * extensions are not checked.
- *
- * Ordinals 3-6 are a classic case of MS exposing limited functionality to
- * users (here through PathFindOnPath) and keeping advanced functionality for
- * their own developers exclusive use. Monopoly, anyone?
- */
-BOOL WINAPI SHLWAPI_3(LPSTR lpszFile,DWORD dwWhich)
-{
- return SHLWAPI_PathFindLocalExeA(lpszFile,dwWhich);
-}
-
-/*************************************************************************
- * @ [SHLWAPI.4]
- *
- * Unicode version of SHLWAPI_3.
- */
-BOOL WINAPI SHLWAPI_4(LPWSTR lpszFile,DWORD dwWhich)
-{
- return SHLWAPI_PathFindLocalExeW(lpszFile,dwWhich);
-}
-
-/*************************************************************************
- * @ [SHLWAPI.5]
- *
- * Search a range of paths for a specific type of executable.
- *
- * PARAMS
- * lpszFile [O] File to search for
- * lppszOtherDirs [I] Other directories to look in
- * dwWhich [I] Type of executable to search for
- *
- * RETURNS
- * Success: TRUE. The path to the executable is stored in sFile.
- * Failure: FALSE. The path to the executable is unchanged.
- */
-BOOL WINAPI SHLWAPI_5(LPSTR lpszFile,LPCSTR *lppszOtherDirs,DWORD dwWhich)
-{
- return SHLWAPI_PathFindOnPathExA(lpszFile,lppszOtherDirs,dwWhich);
-}
-
-/*************************************************************************
- * @ [SHLWAPI.6]
- *
- * Unicode version of SHLWAPI_5.
- */
-BOOL WINAPI SHLWAPI_6(LPWSTR lpszFile,LPCWSTR *lppszOtherDirs,DWORD dwWhich)
-{
- return SHLWAPI_PathFindOnPathExW(lpszFile,lppszOtherDirs,dwWhich);
-}
-
-/*************************************************************************
* SHLWAPI_DupSharedHandle
*
* Internal implemetation of SHLWAPI_11.
diff --git a/dlls/shlwapi/path.c b/dlls/shlwapi/path.c
index fe06174..1b2db26 100644
--- a/dlls/shlwapi/path.c
+++ b/dlls/shlwapi/path.c
@@ -35,11 +35,22 @@
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/debug.h"
-#include "ordinal.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
-/* function pointers for GET_FUNC macro; these need to be global because of gcc bug */
+/* 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; \
+ if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
+ } \
+ } while (0)
+
+/* DLL handles for late bound calls */
+extern HMODULE SHLWAPI_hshell32;
+
+/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
static BOOL (WINAPI *pIsNetDrive)(DWORD);
/*************************************************************************
@@ -1035,33 +1046,11 @@
}
/*************************************************************************
- * SHLWAPI_PathFindLocalExeA
+ * @ [SHLWAPI.4]
*
- * Internal implementation of SHLWAPI_3.
+ * Unicode version of SHLWAPI_3.
*/
-BOOL WINAPI SHLWAPI_PathFindLocalExeA (LPSTR lpszPath, DWORD dwWhich)
-{
- BOOL bRet = FALSE;
-
- TRACE("(%s,%ld)\n", debugstr_a(lpszPath), dwWhich);
-
- if (lpszPath)
- {
- WCHAR szPath[MAX_PATH];
- MultiByteToWideChar(0,0,lpszPath,-1,szPath,MAX_PATH);
- bRet = SHLWAPI_PathFindLocalExeW(szPath, dwWhich);
- if (bRet)
- WideCharToMultiByte(0,0,szPath,-1,lpszPath,MAX_PATH,0,0);
- }
- return bRet;
-}
-
-/*************************************************************************
- * SHLWAPI_PathFindLocalExeW
- *
- * Internal implementation of SHLWAPI_4.
- */
-BOOL WINAPI SHLWAPI_PathFindLocalExeW (LPWSTR lpszPath, DWORD dwWhich)
+BOOL WINAPI SHLWAPI_4(LPWSTR lpszPath,DWORD dwWhich)
{
static const WCHAR pszExts[7][5] = { { '.', 'p', 'i', 'f', '0'},
{ '.', 'c', 'o', 'm', '0'},
@@ -1101,6 +1090,46 @@
}
/*************************************************************************
+ * @ [SHLWAPI.3]
+ *
+ * Determine if a file exists locally and is of an executable type.
+ *
+ * PARAMS
+ * lpszPath [O] File to search for
+ * dwWhich [I] Type of executable to search for
+ *
+ * RETURNS
+ * TRUE If the file was found. lpszFile contains the file name.
+ * FALSE Otherwise.
+ *
+ * NOTES
+ * lpszPath is modified in place and must be at least MAX_PATH in length.
+ * If the function returns FALSE, the path is modified to its orginal state.
+ * If the given path contains an extension or dwWhich is 0, executable
+ * extensions are not checked.
+ *
+ * Ordinals 3-6 are a classic case of MS exposing limited functionality to
+ * users (here through PathFindOnPath) and keeping advanced functionality for
+ * their own developers exclusive use. Monopoly, anyone?
+ */
+BOOL WINAPI SHLWAPI_3(LPSTR lpszPath,DWORD dwWhich)
+{
+ BOOL bRet = FALSE;
+
+ TRACE("(%s,%ld)\n", debugstr_a(lpszPath), dwWhich);
+
+ if (lpszPath)
+ {
+ WCHAR szPath[MAX_PATH];
+ MultiByteToWideChar(0,0,lpszPath,-1,szPath,MAX_PATH);
+ bRet = SHLWAPI_4(szPath, dwWhich);
+ if (bRet)
+ WideCharToMultiByte(0,0,szPath,-1,lpszPath,MAX_PATH,0,0);
+ }
+ return bRet;
+}
+
+/*************************************************************************
* SHLWAPI_PathFindInOtherDirs
*
* Internal helper for SHLWAPI_PathFindOnPathExA/W.
@@ -1120,7 +1149,7 @@
GetSystemDirectoryW(buff, MAX_PATH);
if (!PathAppendW(buff, lpszFile))
return FALSE;
- if (SHLWAPI_PathFindLocalExeW(buff, dwWhich))
+ if (SHLWAPI_4(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
@@ -1128,7 +1157,7 @@
GetWindowsDirectoryW(buff, MAX_PATH);
if (!PathAppendW(buff, szSystem ) || !PathAppendW(buff, lpszFile))
return FALSE;
- if (SHLWAPI_PathFindLocalExeW(buff, dwWhich))
+ if (SHLWAPI_4(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
@@ -1136,7 +1165,7 @@
GetWindowsDirectoryW(buff, MAX_PATH);
if (!PathAppendW(buff, lpszFile))
return FALSE;
- if (SHLWAPI_PathFindLocalExeW(buff, dwWhich))
+ if (SHLWAPI_4(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
@@ -1167,7 +1196,7 @@
if (!PathAppendW(buff, lpszFile))
return FALSE;
- if (SHLWAPI_PathFindLocalExeW(buff, dwWhich))
+ if (SHLWAPI_4(buff, dwWhich))
{
strcpyW(lpszFile, buff);
free(lpszPATH);
@@ -1178,13 +1207,21 @@
return FALSE;
}
-
/*************************************************************************
- * SHLWAPI_PathFindOnPathExA
+ * @ [SHLWAPI.5]
*
- * Internal implementation of SHLWAPI_5
+ * Search a range of paths for a specific type of executable.
+ *
+ * PARAMS
+ * lpszFile [O] File to search for
+ * lppszOtherDirs [I] Other directories to look in
+ * dwWhich [I] Type of executable to search for
+ *
+ * RETURNS
+ * Success: TRUE. The path to the executable is stored in sFile.
+ * Failure: FALSE. The path to the executable is unchanged.
*/
-BOOL WINAPI SHLWAPI_PathFindOnPathExA(LPSTR lpszFile, LPCSTR *lppszOtherDirs, DWORD dwWhich)
+BOOL WINAPI SHLWAPI_5(LPSTR lpszFile,LPCSTR *lppszOtherDirs,DWORD dwWhich)
{
WCHAR szFile[MAX_PATH];
WCHAR buff[MAX_PATH];
@@ -1206,7 +1243,7 @@
{
MultiByteToWideChar(0,0,*lpszOtherPath,-1,szOther,MAX_PATH);
PathCombineW(buff, szOther, szFile);
- if (SHLWAPI_PathFindLocalExeW(buff, dwWhich))
+ if (SHLWAPI_4(buff, dwWhich))
{
WideCharToMultiByte(0,0,buff,-1,lpszFile,MAX_PATH,0,0);
return TRUE;
@@ -1224,11 +1261,11 @@
}
/*************************************************************************
- * SHLWAPI_PathFindOnPathExW
+ * @ [SHLWAPI.6]
*
- * Internal implementation of SHLWAPI_6.
+ * Unicode version of SHLWAPI_5.
*/
-BOOL WINAPI SHLWAPI_PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs, DWORD dwWhich)
+BOOL WINAPI SHLWAPI_6(LPWSTR lpszFile,LPCWSTR *lppszOtherDirs,DWORD dwWhich)
{
WCHAR buff[MAX_PATH];
@@ -1244,7 +1281,7 @@
while (lpszOtherPath && *lpszOtherPath && (*lpszOtherPath)[0])
{
PathCombineW(buff, *lpszOtherPath, lpszFile);
- if (SHLWAPI_PathFindLocalExeW(buff, dwWhich))
+ if (SHLWAPI_4(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
@@ -1272,7 +1309,7 @@
BOOL WINAPI PathFindOnPathA(LPSTR lpszFile, LPCSTR *lppszOtherDirs)
{
TRACE("(%s,%p)\n", debugstr_a(lpszFile), lppszOtherDirs);
- return SHLWAPI_PathFindOnPathExA(lpszFile, lppszOtherDirs, 0);
+ return SHLWAPI_5(lpszFile, lppszOtherDirs, 0);
}
/*************************************************************************
@@ -1280,10 +1317,10 @@
*
* See PathFindOnPathA.
*/
-BOOL WINAPI PathFindOnPathW (LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
+BOOL WINAPI PathFindOnPathW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
{
TRACE("(%s,%p)\n", debugstr_w(lpszFile), lppszOtherDirs);
- return SHLWAPI_PathFindOnPathExW(lpszFile,lppszOtherDirs, 0);
+ return SHLWAPI_6(lpszFile,lppszOtherDirs, 0);
}
/*************************************************************************
@@ -1837,47 +1874,6 @@
}
/*************************************************************************
- * PathIsURLA [SHLWAPI.@]
- *
- * Check if the given path is a URL.
- *
- * PARAMS
- * lpszPath [I] Path to check.
- *
- * RETURNS
- * TRUE if lpszPath is a URL.
- * FALSE if lpszPath is NULL or not a URL.
- */
-BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
-{
- UNKNOWN_SHLWAPI_1 base;
- DWORD res1;
-
- if (!lpstrPath || !*lpstrPath) return FALSE;
-
- /* get protocol */
- base.size = sizeof(base);
- res1 = SHLWAPI_1(lpstrPath, &base);
- return (base.fcncde > 0);
-}
-
-/*************************************************************************
- * PathIsURLW [SHLWAPI.@]
- */
-BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
-{
- UNKNOWN_SHLWAPI_2 base;
- DWORD res1;
-
- if (!lpstrPath || !*lpstrPath) return FALSE;
-
- /* get protocol */
- base.size = sizeof(base);
- res1 = SHLWAPI_2(lpstrPath, &base);
- return (base.fcncde > 0);
-}
-
-/*************************************************************************
* PathIsContentTypeA [SHLWAPI.@]
*
* Determine if a file is of a given registered content type.
diff --git a/dlls/shlwapi/regstream.c b/dlls/shlwapi/regstream.c
index 64400f8..49f3a3b 100644
--- a/dlls/shlwapi/regstream.c
+++ b/dlls/shlwapi/regstream.c
@@ -505,3 +505,43 @@
}
return iStrmRet;
}
+
+/*************************************************************************
+ * SHCreateStreamWrapper [SHLWAPI.@]
+ *
+ * Create a stream on a block of memory.
+ *
+ * PARAMS
+ * lpbData [I] Memory block to create the stream on
+ * dwDataLen [I] Length of data block
+ * dwReserved [I] Reserved, Must be 0.
+ * lppStream [O] Destination for stream object
+ *
+ * RETURNS
+ * Success: S_OK. lppStream contains the new stream object.
+ * Failure: E_INVALIDARG, if any parameters are invalid,
+ * E_OUTOFMEMORY if memory allocation fails.
+ *
+ * NOTES
+ * The stream assumes ownership of the memory passed to it.
+ */
+HRESULT WINAPI SHCreateStreamWrapper(LPBYTE lpbData, DWORD dwDataLen,
+ DWORD dwReserved, IStream **lppStream)
+{
+ IStream* lpStream;
+
+ if (lppStream)
+ *lppStream = NULL;
+
+ if(dwReserved || !lppStream)
+ return E_INVALIDARG;
+
+ lpStream = IStream_Create((HKEY)0, lpbData, dwDataLen);
+
+ if(!lpStream)
+ return E_OUTOFMEMORY;
+
+ IStream_QueryInterface(lpStream, &IID_IStream, (void**)lppStream);
+ IStream_Release(lpStream);
+ return S_OK;
+}
diff --git a/dlls/shlwapi/shlwapi.spec b/dlls/shlwapi/shlwapi.spec
index 193bb9d..cbd02e0 100644
--- a/dlls/shlwapi/shlwapi.spec
+++ b/dlls/shlwapi/shlwapi.spec
@@ -623,10 +623,10 @@
@ stdcall StrCpyW (ptr wstr) StrCpyW
@ stdcall StrDupA (str) StrDupA
@ stdcall StrDupW (wstr) StrDupW
-@ stdcall StrFormatByteSizeA(long str long) StrFormatByteSizeA
-@ stdcall StrFormatByteSizeW(long wstr long) StrFormatByteSizeW
-@ stdcall StrFromTimeIntervalA(str long long long) StrFromTimeIntervalA
-@ stdcall StrFromTimeIntervalW(wstr long long long) StrFromTimeIntervalW
+@ stdcall StrFormatByteSizeA(long ptr long) StrFormatByteSizeA
+@ stdcall StrFormatByteSizeW(long long ptr long) StrFormatByteSizeW
+@ stdcall StrFromTimeIntervalA(ptr long long long) StrFromTimeIntervalA
+@ stdcall StrFromTimeIntervalW(ptr long long long) StrFromTimeIntervalW
@ stdcall StrIsIntlEqualA(long str str long) StrIsIntlEqualA
@ stdcall StrIsIntlEqualW(long wstr wstr long) StrIsIntlEqualW
@ stdcall StrNCatA(str str long) StrNCatA
@@ -711,7 +711,7 @@
@ stdcall SHCreateStreamOnFileA(str long ptr) SHCreateStreamOnFileA
@ stdcall SHCreateStreamOnFileW(wstr long ptr) SHCreateStreamOnFileW
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr) SHCreateStreamOnFileEx
-@ stub SHCreateStreamWrapper
+@ stdcall SHCreateStreamWrapper(ptr ptr long ptr) SHCreateStreamWrapper
@ stdcall SHGetThreadRef (ptr) SHGetThreadRef
@ stdcall SHRegDuplicateHKey (long) SHRegDuplicateHKey
@ stdcall SHRegSetPathA(long str str str long) SHRegSetPathA
@@ -722,6 +722,7 @@
@ stdcall SHSkipJunction(ptr ptr) SHSkipJunction
@ stdcall SHStrDupA (str ptr) SHStrDupA
@ stdcall SHStrDupW (wstr ptr) SHStrDupW
-@ stub StrFormatByteSize64A
+@ stdcall StrFormatByteSize64A(long long ptr long) StrFormatByteSize64A
@ stdcall StrFormatKBSizeA(long long str long) StrFormatKBSizeA
@ stdcall StrFormatKBSizeW(long long wstr long) StrFormatKBSizeW
+@ stdcall StrCmpLogicalW(wstr wstr) StrCmpLogicalW
diff --git a/dlls/shlwapi/string.c b/dlls/shlwapi/string.c
index 45db498..fe466eb 100644
--- a/dlls/shlwapi/string.c
+++ b/dlls/shlwapi/string.c
@@ -23,6 +23,7 @@
#include "wine/port.h"
#include <ctype.h>
+#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -1494,40 +1495,6 @@
}
/*************************************************************************
- * StrFormatByteSizeA [SHLWAPI.@]
- */
-LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
-{ char buf[64];
- TRACE("%lx %p %i\n", dw, pszBuf, cchBuf);
- if ( dw<1024L )
- { sprintf (buf,"%ld bytes", dw);
- }
- else if ( dw<1048576L)
- { sprintf (buf,"%3.1f KB", (FLOAT)dw/1024);
- }
- else if ( dw < 1073741824L)
- { sprintf (buf,"%3.1f MB", (FLOAT)dw/1048576L);
- }
- else
- { sprintf (buf,"%3.1f GB", (FLOAT)dw/1073741824L);
- }
- lstrcpynA (pszBuf, buf, cchBuf);
- return pszBuf;
-}
-
-/*************************************************************************
- * StrFormatByteSizeW [SHLWAPI.@]
- */
-LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
-{
- char buf[64];
- StrFormatByteSizeA( dw, buf, sizeof(buf) );
- if (!MultiByteToWideChar( CP_ACP, 0, buf, -1, pszBuf, cchBuf ) && cchBuf)
- pszBuf[cchBuf-1] = 0;
- return pszBuf;
-}
-
-/*************************************************************************
* StrFormatKBSizeA [SHLWAPI.@]
*
* Create a formatted string containing a byte count in Kilobytes.
@@ -2123,3 +2090,212 @@
}
return lpszDest;
}
+
+/*************************************************************************
+ * StrCmpLogicalW [SHLWAPI.@]
+ *
+ * Compare two strings, ignoring case and comparing digits as numbers.
+ *
+ * PARAMS
+ * lpszStr [I] First string to compare
+ * lpszComp [I] Second string to compare
+ * iLen [I] Length to compare
+ *
+ * RETURNS
+ * TRUE If the strings are equal.
+ * FALSE Otherwise.
+ */
+INT WINAPI StrCmpLogicalW(LPCWSTR lpszStr, LPCWSTR lpszComp)
+{
+ INT iDiff;
+
+ TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
+
+ if (lpszStr && lpszComp)
+ {
+ while (*lpszStr)
+ {
+ if (!*lpszComp)
+ return 1;
+ else if (isdigitW(*lpszStr))
+ {
+ int iStr, iComp;
+
+ if (!isdigitW(*lpszComp))
+ return -1;
+
+ /* Compare the numbers */
+ StrToIntExW(lpszStr, 0, &iStr);
+ StrToIntExW(lpszComp, 0, &iComp);
+
+ if (iStr < iComp)
+ return -1;
+ else if (iStr > iComp)
+ return 1;
+
+ /* Skip */
+ while (isdigitW(*lpszStr))
+ lpszStr++;
+ while (isdigitW(*lpszComp))
+ lpszComp++;
+ }
+ else if (isdigitW(*lpszComp))
+ return 1;
+ else
+ {
+ iDiff = SHLWAPI_ChrCmpHelperA(*lpszStr,*lpszComp,NORM_IGNORECASE);
+ if (iDiff > 0)
+ return 1;
+ else if (iDiff < 0)
+ return -1;
+
+ lpszStr++;
+ lpszComp++;
+ }
+ }
+ if (*lpszComp)
+ return -1;
+ }
+ return 0;
+}
+
+/* Structure for formatting byte strings */
+typedef struct tagSHLWAPI_BYTEFORMATS
+{
+ LONGLONG dLimit;
+ double dDivisor;
+ double dNormaliser;
+ LPCSTR lpszFormat;
+ CHAR wPrefix;
+} SHLWAPI_BYTEFORMATS;
+
+/*************************************************************************
+ * StrFormatByteSize64A [SHLWAPI.@]
+ *
+ * Create a string containing an abbreviated byte count of up to 2^63-1.
+ *
+ * PARAMS
+ * llBytes [I] Byte size to format
+ * lpszDest [I] Destination for formatted string
+ * cchMax [I] Size of lpszDest
+ *
+ * RETURNS
+ * lpszDest.
+ *
+ * NOTES
+ * There is no StrFormatByteSize64W function, it is called StrFormatByteSizeW.
+ */
+LPSTR WINAPI StrFormatByteSize64A(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
+{
+ static const char szBytes[] = "%ld bytes";
+ static const char sz3_0[] = "%3.0f";
+ static const char sz3_1[] = "%3.1f";
+ static const char sz3_2[] = "%3.2f";
+
+ static const SHLWAPI_BYTEFORMATS bfFormats[] =
+ {
+ { 10240, 10.24, 100.0, sz3_2, 'K' }, /* 10 KB */
+ { 102400, 102.4, 10.0, sz3_1, 'K' }, /* 100 KB */
+ { 1024000, 1024.0, 1.0, sz3_0, 'K' }, /* 1000 KB */
+ { 10485760, 10485.76, 100.0, sz3_2, 'M' }, /* 10 MB */
+ { 104857600, 104857.6, 10.0, sz3_1, 'M' }, /* 100 MB */
+ { 1048576000, 1048576.0, 1.0, sz3_0, 'M' }, /* 1000 MB */
+ { 10737418240, 10737418.24, 100.0, sz3_2, 'G' }, /* 10 GB */
+ { 107374182400, 107374182.4, 10.0, sz3_1, 'G' }, /* 100 GB */
+ { 1073741824000, 1073741824.0, 1.0, sz3_0, 'G' }, /* 1000 GB */
+ { 10995116277760, 10485.76, 100.0, sz3_2, 'T' }, /* 10 TB */
+ { 109951162777600, 104857.6, 10.0, sz3_1, 'T' }, /* 100 TB */
+ { 1099511627776000, 1048576.0, 1.0, sz3_0, 'T' }, /* 1000 TB */
+ { 11258999068426240, 10737418.24, 100.00, sz3_2, 'P' }, /* 10 PB */
+ { 112589990684262400, 107374182.4, 10.00, sz3_1, 'P' }, /* 100 PB */
+ { 1125899906842624000, 1073741824.0, 1.00, sz3_0, 'P' }, /* 1000 PB */
+ { 0, 10995116277.76, 100.00, sz3_2, 'E' } /* EB's, catch all */
+ };
+ char szBuff[32];
+ char szAdd[4];
+ double dBytes;
+ UINT i = 0;
+
+ TRACE("(%lld,%p,%d)\n", llBytes, lpszDest, cchMax);
+
+ if (!lpszDest || !cchMax)
+ return lpszDest;
+
+ if (llBytes < 1024) /* 1K */
+ {
+ snprintf (lpszDest, cchMax, szBytes, (long)llBytes);
+ return lpszDest;
+ }
+
+ /* Note that if this loop completes without finding a match, i will be
+ * pointing at the last entry, which is a catch all for > 1000 PB
+ */
+ while (i < sizeof(bfFormats) / sizeof(SHLWAPI_BYTEFORMATS) - 1)
+ {
+ if (llBytes < bfFormats[i].dLimit)
+ break;
+ i++;
+ }
+ /* Above 1 TB we encounter problems with FP accuracy. So for amounts above
+ * this number we integer shift down by 1 MB first. The table above has
+ * the divisors scaled down from the '< 10 TB' entry onwards, to account
+ * for this. We also add a small fudge factor to get the correct result for
+ * counts that lie exactly on a 1024 byte boundary.
+ */
+ if (i > 8)
+ dBytes = (double)(llBytes >> 20) + 0.001; /* Scale down by I MB */
+ else
+ dBytes = (double)llBytes + 0.00001;
+
+ dBytes = floor(dBytes / bfFormats[i].dDivisor) / bfFormats[i].dNormaliser;
+
+ sprintf(szBuff, bfFormats[i].lpszFormat, dBytes);
+ szAdd[0] = ' ';
+ szAdd[1] = bfFormats[i].wPrefix;
+ szAdd[2] = 'B';
+ szAdd[3] = '\0';
+ strcat(szBuff, szAdd);
+ strncpy(lpszDest, szBuff, cchMax);
+ return lpszDest;
+}
+
+/*************************************************************************
+ * StrFormatByteSizeW [SHLWAPI.@]
+ *
+ * See StrFormatByteSize64A.
+ */
+LPWSTR WINAPI StrFormatByteSizeW(LONGLONG llBytes, LPWSTR lpszDest,
+ UINT cchMax)
+{
+ char szBuff[32];
+
+ StrFormatByteSize64A(llBytes, szBuff, sizeof(szBuff));
+
+ if (lpszDest)
+ MultiByteToWideChar(CP_ACP, 0, szBuff, -1, lpszDest, cchMax);
+ return lpszDest;
+}
+
+/*************************************************************************
+ * StrFormatByteSizeA [SHLWAPI.@]
+ *
+ * Create a string containing an abbreviated byte count of up to 2^31-1.
+ *
+ * PARAMS
+ * dwBytes [I] Byte size to format
+ * lpszDest [I] Destination for formatted string
+ * cchMax [I] Size of lpszDest
+ *
+ * RETURNS
+ * lpszDest.
+ *
+ * NOTES
+ * The ASCII and Unicode versions of this function accept a different
+ * integer size for dwBytes. See StrFormatByteSize64A.
+ */
+LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax)
+{
+ TRACE("(%ld,%p,%d)\n", dwBytes, lpszDest, cchMax);
+
+ return StrFormatByteSize64A(dwBytes, lpszDest, cchMax);
+}
diff --git a/dlls/shlwapi/thread.c b/dlls/shlwapi/thread.c
index 0a3f187..4b97af2 100644
--- a/dlls/shlwapi/thread.c
+++ b/dlls/shlwapi/thread.c
@@ -30,14 +30,26 @@
#define NO_SHLWAPI_STREAM
#define NO_SHLWAPI_USER
#include "shlwapi.h"
-#include "ordinal.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
-extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */
+/* 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; \
+ if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
+ } \
+ } while (0)
+/* DLL handles for late bound calls */
+extern HMODULE SHLWAPI_hshell32;
+
+/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown**);
+extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */
+
DWORD WINAPI SHLWAPI_23(REFGUID,LPSTR,INT);
/**************************************************************************
diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c
index 7a0048e..387ae9d 100644
--- a/dlls/shlwapi/url.c
+++ b/dlls/shlwapi/url.c
@@ -30,10 +30,63 @@
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/debug.h"
-#include "ordinal.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
+/* The following schemes were identified in the native version of
+ * SHLWAPI.DLL version 5.50
+ */
+typedef enum {
+ URL_SCHEME_INVALID = -1,
+ URL_SCHEME_UNKNOWN = 0,
+ URL_SCHEME_FTP,
+ URL_SCHEME_HTTP,
+ URL_SCHEME_GOPHER,
+ URL_SCHEME_MAILTO,
+ URL_SCHEME_NEWS,
+ URL_SCHEME_NNTP,
+ URL_SCHEME_TELNET,
+ URL_SCHEME_WAIS,
+ URL_SCHEME_FILE,
+ URL_SCHEME_MK,
+ URL_SCHEME_HTTPS,
+ URL_SCHEME_SHELL,
+ URL_SCHEME_SNEWS,
+ URL_SCHEME_LOCAL,
+ URL_SCHEME_JAVASCRIPT,
+ URL_SCHEME_VBSCRIPT,
+ URL_SCHEME_ABOUT,
+ URL_SCHEME_RES,
+ URL_SCHEME_MAXVALUE
+} URL_SCHEME;
+
+typedef struct {
+ URL_SCHEME scheme_number;
+ LPCSTR scheme_name;
+} SHL_2_inet_scheme;
+
+static const SHL_2_inet_scheme shlwapi_schemes[] = {
+ {URL_SCHEME_FTP, "ftp"},
+ {URL_SCHEME_HTTP, "http"},
+ {URL_SCHEME_GOPHER, "gopher"},
+ {URL_SCHEME_MAILTO, "mailto"},
+ {URL_SCHEME_NEWS, "news"},
+ {URL_SCHEME_NNTP, "nntp"},
+ {URL_SCHEME_TELNET, "telnet"},
+ {URL_SCHEME_WAIS, "wais"},
+ {URL_SCHEME_FILE, "file"},
+ {URL_SCHEME_MK, "mk"},
+ {URL_SCHEME_HTTPS, "https"},
+ {URL_SCHEME_SHELL, "shell"},
+ {URL_SCHEME_SNEWS, "snews"},
+ {URL_SCHEME_LOCAL, "local"},
+ {URL_SCHEME_JAVASCRIPT, "javascript"},
+ {URL_SCHEME_VBSCRIPT, "vbscript"},
+ {URL_SCHEME_ABOUT, "about"},
+ {URL_SCHEME_RES, "res"},
+ {0, 0}
+};
+
typedef struct {
LPCWSTR pScheme; /* [out] start of scheme */
DWORD szScheme; /* [out] size of scheme (until colon) */
@@ -56,6 +109,24 @@
USERPASS,
} WINE_URL_SCAN_TYPE;
+typedef struct {
+ INT size; /* [in] (always 0x18) */
+ LPCSTR ap1; /* [out] start of scheme */
+ INT sizep1; /* [out] size of scheme (until colon) */
+ LPCSTR ap2; /* [out] pointer following first colon */
+ INT sizep2; /* [out] size of remainder */
+ INT fcncde; /* [out] function match of p1 (0 if unknown) */
+} UNKNOWN_SHLWAPI_1;
+
+typedef struct {
+ INT size; /* [in] (always 0x18) */
+ LPCWSTR ap1; /* [out] start of scheme */
+ INT sizep1; /* [out] size of scheme (until colon) */
+ LPCWSTR ap2; /* [out] pointer following first colon */
+ INT sizep2; /* [out] size of remainder */
+ INT fcncde; /* [out] function match of p1 (0 if unknown) */
+} UNKNOWN_SHLWAPI_2;
+
static const CHAR hexDigits[] = "0123456789ABCDEF";
static const WCHAR fileW[] = {'f','i','l','e','\0'};
@@ -186,6 +257,122 @@
/*************************************************************************
+ * @ [SHLWAPI.1]
+ *
+ * Identifies the Internet "scheme" in the passed string. ASCII based.
+ * Also determines start and length of item after the ':'
+ */
+DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
+{
+ DWORD cnt;
+ const SHL_2_inet_scheme *inet_pro;
+
+ y->fcncde = URL_SCHEME_INVALID;
+ if (y->size != 0x18) return E_INVALIDARG;
+ /* FIXME: leading white space generates error of 0x80041001 which
+ * is undefined
+ */
+ if (*x <= ' ') return 0x80041001;
+ cnt = 0;
+ y->sizep1 = 0;
+ y->ap1 = x;
+ while (*x) {
+ if (*x == ':') {
+ y->sizep1 = cnt;
+ cnt = -1;
+ y->ap2 = x+1;
+ break;
+ }
+ x++;
+ cnt++;
+ }
+
+ /* check for no scheme in string start */
+ /* (apparently schemes *must* be larger than a single character) */
+ if ((*x == '\0') || (y->sizep1 <= 1)) {
+ y->ap1 = 0;
+ return 0x80041001;
+ }
+
+ /* found scheme, set length of remainder */
+ y->sizep2 = lstrlenA(y->ap2);
+
+ /* see if known scheme and return indicator number */
+ y->fcncde = URL_SCHEME_UNKNOWN;
+ inet_pro = shlwapi_schemes;
+ while (inet_pro->scheme_name) {
+ if (!strncasecmp(inet_pro->scheme_name, y->ap1,
+ min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
+ y->fcncde = inet_pro->scheme_number;
+ break;
+ }
+ inet_pro++;
+ }
+ return S_OK;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.2]
+ *
+ * Identifies the Internet "scheme" in the passed string. UNICODE based.
+ * Also determines start and length of item after the ':'
+ */
+DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
+{
+ DWORD cnt;
+ const SHL_2_inet_scheme *inet_pro;
+ LPSTR cmpstr;
+ INT len;
+
+ y->fcncde = URL_SCHEME_INVALID;
+ if (y->size != 0x18) return E_INVALIDARG;
+ /* FIXME: leading white space generates error of 0x80041001 which
+ * is undefined
+ */
+ if (*x <= L' ') return 0x80041001;
+ cnt = 0;
+ y->sizep1 = 0;
+ y->ap1 = x;
+ while (*x) {
+ if (*x == L':') {
+ y->sizep1 = cnt;
+ cnt = -1;
+ y->ap2 = x+1;
+ break;
+ }
+ x++;
+ cnt++;
+ }
+
+ /* check for no scheme in string start */
+ /* (apparently schemes *must* be larger than a single character) */
+ if ((*x == L'\0') || (y->sizep1 <= 1)) {
+ y->ap1 = 0;
+ return 0x80041001;
+ }
+
+ /* found scheme, set length of remainder */
+ y->sizep2 = lstrlenW(y->ap2);
+
+ /* see if known scheme and return indicator number */
+ len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
+ cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
+ WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
+ y->fcncde = URL_SCHEME_UNKNOWN;
+ inet_pro = shlwapi_schemes;
+ while (inet_pro->scheme_name) {
+ if (!strncasecmp(inet_pro->scheme_name, cmpstr,
+ min(len, lstrlenA(inet_pro->scheme_name)))) {
+ y->fcncde = inet_pro->scheme_number;
+ break;
+ }
+ inet_pro++;
+ }
+ HeapFree(GetProcessHeap(), 0, cmpstr);
+ return S_OK;
+}
+
+/*************************************************************************
* UrlCanonicalizeA [SHLWAPI.@]
*
* Uses the W version to do job.
@@ -1753,3 +1940,44 @@
}
return ret;
}
+
+/*************************************************************************
+ * PathIsURLA [SHLWAPI.@]
+ *
+ * Check if the given path is a URL.
+ *
+ * PARAMS
+ * lpszPath [I] Path to check.
+ *
+ * RETURNS
+ * TRUE if lpszPath is a URL.
+ * FALSE if lpszPath is NULL or not a URL.
+ */
+BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
+{
+ UNKNOWN_SHLWAPI_1 base;
+ DWORD res1;
+
+ if (!lpstrPath || !*lpstrPath) return FALSE;
+
+ /* get protocol */
+ base.size = sizeof(base);
+ res1 = SHLWAPI_1(lpstrPath, &base);
+ return (base.fcncde > 0);
+}
+
+/*************************************************************************
+ * PathIsURLW [SHLWAPI.@]
+ */
+BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
+{
+ UNKNOWN_SHLWAPI_2 base;
+ DWORD res1;
+
+ if (!lpstrPath || !*lpstrPath) return FALSE;
+
+ /* get protocol */
+ base.size = sizeof(base);
+ res1 = SHLWAPI_2(lpstrPath, &base);
+ return (base.fcncde > 0);
+}
diff --git a/include/shlwapi.h b/include/shlwapi.h
index 2201ac8..f7856dd 100644
--- a/include/shlwapi.h
+++ b/include/shlwapi.h
@@ -709,8 +709,17 @@
#define SHStrDup WINELIB_NAME_AW(SHStrDup)
LPSTR WINAPI StrFormatByteSizeA (DWORD,LPSTR,UINT);
-LPWSTR WINAPI StrFormatByteSizeW (DWORD,LPWSTR,UINT);
-#define StrFormatByteSize WINELIB_NAME_AW(StrFormatByteSize)
+
+/* A/W Pairing is broken for this function */
+LPSTR WINAPI StrFormatByteSize64A (LONGLONG,LPSTR,UINT);
+LPWSTR WINAPI StrFormatByteSizeW (LONGLONG,LPWSTR,UINT);
+#ifndef __WINE__
+#ifdef UNICODE
+#define StrFormatByteSize StrFormatByteSizeW
+#else
+#define StrFormatByteSize StrFormatByteSize64A
+#endif
+#endif
int WINAPI StrFromTimeIntervalA(LPSTR,UINT,DWORD,int);
int WINAPI StrFromTimeIntervalW(LPWSTR,UINT,DWORD,int);