📄 util.c
字号:
/*
* MAPI Utility 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <stdio.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "winerror.h"
#include "winternl.h"
#include "objbase.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "mapival.h"
#include "xcmc.h"
#include "msi.h"
WINE_DEFAULT_DEBUG_CHANNEL(mapi);
static const BYTE digitsToHex[] = {
0,1,2,3,4,5,6,7,8,9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,14,15,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,
14,15 };
/**************************************************************************
* ScInitMapiUtil (MAPI32.33)
*
* Initialise Mapi utility functions.
*
* PARAMS
* ulReserved [I] Reserved, pass 0.
*
* RETURNS
* Success: S_OK. Mapi utility functions may be called.
* Failure: MAPI_E_INVALID_PARAMETER, if ulReserved is not 0.
*
* NOTES
* Your application does not need to call this function unless it does not
* call MAPIInitialize()/MAPIUninitialize().
*/
SCODE WINAPI ScInitMapiUtil(ULONG ulReserved)
{
FIXME("(0x%08x)stub!\n", ulReserved);
if (ulReserved)
return MAPI_E_INVALID_PARAMETER;
return S_OK;
}
/**************************************************************************
* DeinitMapiUtil (MAPI32.34)
*
* Uninitialise Mapi utility functions.
*
* PARAMS
* None.
*
* RETURNS
* Nothing.
*
* NOTES
* Your application does not need to call this function unless it does not
* call MAPIInitialize()/MAPIUninitialize().
*/
VOID WINAPI DeinitMapiUtil(void)
{
FIXME("()stub!\n");
}
typedef LPVOID *LPMAPIALLOCBUFFER;
/**************************************************************************
* MAPIAllocateBuffer (MAPI32.12)
* MAPIAllocateBuffer@8 (MAPI32.13)
*
* Allocate a block of memory.
*
* PARAMS
* cbSize [I] Size of the block to allocate in bytes
* lppBuffer [O] Destination for pointer to allocated memory
*
* RETURNS
* Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
* length cbSize bytes.
* Failure: MAPI_E_INVALID_PARAMETER, if lppBuffer is NULL.
* MAPI_E_NOT_ENOUGH_MEMORY, if the memory allocation fails.
*
* NOTES
* Memory allocated with this function should be freed with MAPIFreeBuffer().
* Further allocations of memory may be linked to the pointer returned using
* MAPIAllocateMore(). Linked allocations are freed when the initial pointer
* is feed.
*/
SCODE WINAPI MAPIAllocateBuffer(ULONG cbSize, LPVOID *lppBuffer)
{
LPMAPIALLOCBUFFER lpBuff;
TRACE("(%d,%p)\n", cbSize, lppBuffer);
if (!lppBuffer)
return E_INVALIDARG;
lpBuff = HeapAlloc(GetProcessHeap(), 0, cbSize + sizeof(*lpBuff));
if (!lpBuff)
return MAPI_E_NOT_ENOUGH_MEMORY;
TRACE("initial allocation:%p, returning %p\n", lpBuff, lpBuff + 1);
*lpBuff++ = NULL;
*lppBuffer = lpBuff;
return S_OK;
}
/**************************************************************************
* MAPIAllocateMore (MAPI32.14)
* MAPIAllocateMore@12 (MAPI32.15)
*
* Allocate a block of memory linked to a previous allocation.
*
* PARAMS
* cbSize [I] Size of the block to allocate in bytes
* lpOrig [I] Initial allocation to link to, from MAPIAllocateBuffer()
* lppBuffer [O] Destination for pointer to allocated memory
*
* RETURNS
* Success: S_OK. *lppBuffer is filled with a pointer to a memory block of
* length cbSize bytes.
* Failure: MAPI_E_INVALID_PARAMETER, if lpOrig or lppBuffer is invalid.
* MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
*
* NOTES
* Memory allocated with this function and stored in *lppBuffer is freed
* when lpOrig is passed to MAPIFreeBuffer(). It should not be freed independently.
*/
SCODE WINAPI MAPIAllocateMore(ULONG cbSize, LPVOID lpOrig, LPVOID *lppBuffer)
{
LPMAPIALLOCBUFFER lpBuff = lpOrig;
TRACE("(%d,%p,%p)\n", cbSize, lpOrig, lppBuffer);
if (!lppBuffer || !lpBuff || !--lpBuff)
return E_INVALIDARG;
/* Find the last allocation in the chain */
while (*lpBuff)
{
TRACE("linked:%p->%p\n", lpBuff, *lpBuff);
lpBuff = *lpBuff;
}
if (SUCCEEDED(MAPIAllocateBuffer(cbSize, lppBuffer)))
{
*lpBuff = ((LPMAPIALLOCBUFFER)*lppBuffer) - 1;
TRACE("linking %p->%p\n", lpBuff, *lpBuff);
}
return *lppBuffer ? S_OK : MAPI_E_NOT_ENOUGH_MEMORY;
}
/**************************************************************************
* MAPIFreeBuffer (MAPI32.16)
* MAPIFreeBuffer@4 (MAPI32.17)
*
* Free a block of memory and any linked allocations associated with it.
*
* PARAMS
* lpBuffer [I] Memory to free, returned from MAPIAllocateBuffer()
*
* RETURNS
* S_OK.
*/
ULONG WINAPI MAPIFreeBuffer(LPVOID lpBuffer)
{
LPMAPIALLOCBUFFER lpBuff = lpBuffer;
TRACE("(%p)\n", lpBuffer);
if (lpBuff && --lpBuff)
{
while (lpBuff)
{
LPVOID lpFree = lpBuff;
lpBuff = *lpBuff;
TRACE("linked:%p->%p, freeing %p\n", lpFree, lpBuff, lpFree);
HeapFree(GetProcessHeap(), 0, lpFree);
}
}
return S_OK;
}
/**************************************************************************
* WrapProgress@20 (MAPI32.41)
*/
HRESULT WINAPI WrapProgress(PVOID unk1, PVOID unk2, PVOID unk3, PVOID unk4, PVOID unk5)
{
/* Native does not implement this function */
return MAPI_E_NO_SUPPORT;
}
/*************************************************************************
* HrThisThreadAdviseSink@8 (MAPI32.42)
*
* Ensure that an advise sink is only notified in its originating thread.
*
* PARAMS
* lpSink [I] IMAPIAdviseSink interface to be protected
* lppNewSink [I] Destination for wrapper IMAPIAdviseSink interface
*
* RETURNS
* Success: S_OK. *lppNewSink contains a new sink to use in place of lpSink.
* Failure: E_INVALIDARG, if any parameter is invalid.
*/
HRESULT WINAPI HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink, LPMAPIADVISESINK* lppNewSink)
{
FIXME("(%p,%p)semi-stub\n", lpSink, lppNewSink);
if (!lpSink || !lppNewSink)
return E_INVALIDARG;
/* Don't wrap the sink for now, just copy it */
*lppNewSink = lpSink;
IMAPIAdviseSink_AddRef(lpSink);
return S_OK;
}
/*************************************************************************
* FBinFromHex (MAPI32.44)
*
* Create an array of binary data from a string.
*
* PARAMS
* lpszHex [I] String to convert to binary data
* lpOut [O] Destination for resulting binary data
*
* RETURNS
* Success: TRUE. lpOut contains the decoded binary data.
* Failure: FALSE, if lpszHex does not represent a binary string.
*
* NOTES
* - lpOut must be at least half the length of lpszHex in bytes.
* - Although the Mapi headers prototype this function as both
* Ascii and Unicode, there is only one (Ascii) implementation. This
* means that lpszHex is treated as an Ascii string (i.e. a single NUL
* character in the byte stream terminates the string).
*/
BOOL WINAPI FBinFromHex(LPWSTR lpszHex, LPBYTE lpOut)
{
LPSTR lpStr = (LPSTR)lpszHex;
TRACE("(%p,%p)\n", lpszHex, lpOut);
while (*lpStr)
{
if (lpStr[0] < '0' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - '0'] == 0xff ||
lpStr[1] < '0' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - '0'] == 0xff)
return FALSE;
*lpOut++ = (digitsToHex[lpStr[0] - '0'] << 4) | digitsToHex[lpStr[1] - '0'];
lpStr += 2;
}
return TRUE;
}
/*************************************************************************
* HexFromBin (MAPI32.45)
*
* Create a string from an array of binary data.
*
* PARAMS
* lpHex [I] Binary data to convert to string
* iCount [I] Length of lpHex in bytes
* lpszOut [O] Destination for resulting hex string
*
* RETURNS
* Nothing.
*
* NOTES
* - lpszOut must be at least 2 * iCount + 1 bytes characters long.
* - Although the Mapi headers prototype this function as both
* Ascii and Unicode, there is only one (Ascii) implementation. This
* means that the resulting string is not properly NUL terminated
* if the caller expects it to be a Unicode string.
*/
void WINAPI HexFromBin(LPBYTE lpHex, int iCount, LPWSTR lpszOut)
{
static const char hexDigits[] = { "0123456789ABCDEF" };
LPSTR lpStr = (LPSTR)lpszOut;
TRACE("(%p,%d,%p)\n", lpHex, iCount, lpszOut);
while (iCount-- > 0)
{
*lpStr++ = hexDigits[*lpHex >> 4];
*lpStr++ = hexDigits[*lpHex & 0xf];
lpHex++;
}
*lpStr = '\0';
}
/*************************************************************************
* SwapPlong@8 (MAPI32.47)
*
* Swap the bytes in a ULONG array.
*
* PARAMS
* lpData [O] Array to swap bytes in
* ulLen [I] Number of ULONG element to swap the bytes of
*
* RETURNS
* Nothing.
*/
VOID WINAPI SwapPlong(PULONG lpData, ULONG ulLen)
{
ULONG i;
for (i = 0; i < ulLen; i++)
lpData[i] = RtlUlongByteSwap(lpData[i]);
}
/*************************************************************************
* SwapPword@8 (MAPI32.48)
*
* Swap the bytes in a USHORT array.
*
* PARAMS
* lpData [O] Array to swap bytes in
* ulLen [I] Number of USHORT element to swap the bytes of
*
* RETURNS
* Nothing.
*/
VOID WINAPI SwapPword(PUSHORT lpData, ULONG ulLen)
{
ULONG i;
for (i = 0; i < ulLen; i++)
lpData[i] = RtlUshortByteSwap(lpData[i]);
}
/**************************************************************************
* MNLS_lstrlenW@4 (MAPI32.62)
*
* Calculate the length of a Unicode string.
*
* PARAMS
* lpszStr [I] String to calculate the length of
*
* RETURNS
* The length of lpszStr in Unicode characters.
*/
ULONG WINAPI MNLS_lstrlenW(LPCWSTR lpszStr)
{
TRACE("(%s)\n", debugstr_w(lpszStr));
return strlenW(lpszStr);
}
/*************************************************************************
* MNLS_lstrcmpW@8 (MAPI32.63)
*
* Compare two Unicode strings.
*
* PARAMS
* lpszLeft [I] First string to compare
* lpszRight [I] Second string to compare
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
* lpszLeft is less than, the same, or greater than lpszRight.
*/
INT WINAPI MNLS_lstrcmpW(LPCWSTR lpszLeft, LPCWSTR lpszRight)
{
TRACE("(%s,%s)\n", debugstr_w(lpszLeft), debugstr_w(lpszRight));
return strcmpW(lpszLeft, lpszRight);
}
/*************************************************************************
* MNLS_lstrcpyW@8 (MAPI32.64)
*
* Copy a Unicode string to another string.
*
* PARAMS
* lpszDest [O] Destination string
* lpszSrc [I] Source string
*
* RETURNS
* The length lpszDest in Unicode characters.
*/
ULONG WINAPI MNLS_lstrcpyW(LPWSTR lpszDest, LPCWSTR lpszSrc)
{
ULONG len;
TRACE("(%p,%s)\n", lpszDest, debugstr_w(lpszSrc));
len = (strlenW(lpszSrc) + 1) * sizeof(WCHAR);
memcpy(lpszDest, lpszSrc, len);
return len;
}
/*************************************************************************
* MNLS_CompareStringW@12 (MAPI32.65)
*
* Compare two Unicode strings.
*
* PARAMS
* dwCp [I] Code page for the comparison
* lpszLeft [I] First string to compare
* lpszRight [I] Second string to compare
*
* RETURNS
* CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN, indicating that
* lpszLeft is less than, the same, or greater than lpszRight.
*/
INT WINAPI MNLS_CompareStringW(DWORD dwCp, LPCWSTR lpszLeft, LPCWSTR lpszRight)
{
INT ret;
TRACE("0x%08x,%s,%s\n", dwCp, debugstr_w(lpszLeft), debugstr_w(lpszRight));
ret = MNLS_lstrcmpW(lpszLeft, lpszRight);
return ret < 0 ? CSTR_LESS_THAN : ret ? CSTR_GREATER_THAN : CSTR_EQUAL;
}
/**************************************************************************
* FEqualNames@8 (MAPI32.72)
*
* Compare two Mapi names.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -