Commit 91ec8e14 authored by Jon Griffiths's avatar Jon Griffiths Committed by Alexandre Julliard

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.
parent 95e5c921
......@@ -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 @@ static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
/* 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 @@ static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO*);
*/
/*************************************************************************
* @ [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.
......
......@@ -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 @@ int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
}
/*************************************************************************
* 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 @@ BOOL WINAPI SHLWAPI_PathFindLocalExeW (LPWSTR lpszPath, DWORD dwWhich)
}
/*************************************************************************
* @ [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 @@ static BOOL WINAPI SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
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 @@ static BOOL WINAPI SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
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 @@ static BOOL WINAPI SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
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 @@ static BOOL WINAPI SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
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 @@ static BOOL WINAPI SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
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 @@ BOOL WINAPI SHLWAPI_PathFindOnPathExA(LPSTR lpszFile, LPCSTR *lppszOtherDirs, DW
{
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 @@ BOOL WINAPI SHLWAPI_PathFindOnPathExA(LPSTR lpszFile, LPCSTR *lppszOtherDirs, DW
}
/*************************************************************************
* 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 @@ BOOL WINAPI SHLWAPI_PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs,
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 SHLWAPI_PathFindOnPathExW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs,
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 @@ BOOL WINAPI PathFindOnPathA(LPSTR lpszFile, LPCSTR *lppszOtherDirs)
*
* 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 @@ BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
}
/*************************************************************************
* 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.
......
......@@ -505,3 +505,43 @@ IStream * WINAPI SHLWAPI_12(LPBYTE lpbData, DWORD dwDataLen)
}
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;
}
......@@ -623,10 +623,10 @@ init SHLWAPI_LibMain
@ 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 @@ init SHLWAPI_LibMain
@ 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 @@ init SHLWAPI_LibMain
@ 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
......@@ -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 @@ HRESULT WINAPI StrRetToStrW(LPSTRRET pstr, const ITEMIDLIST * pidl, LPWSTR* ppsz
}
/*************************************************************************
* 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 @@ LPWSTR WINAPI SHLWAPI_400(LPWSTR lpszDest, LPCWSTR lpszSrc, int iLen)
}
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);
}
......@@ -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);
/**************************************************************************
......
......@@ -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 @@ typedef enum {
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 @@ static BOOL URL_JustLocation(LPCWSTR str)
/*************************************************************************
* @ [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 @@ HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut,
}
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);
}
......@@ -709,8 +709,17 @@ HRESULT WINAPI SHStrDupW(LPCWSTR,WCHAR**);
#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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment