📄 utilities.cpp
字号:
/***************************************************************************
* UTILITIES.CPP
*
* Shared helper functions and routines.
*
* Copyright ?999-2004; Microsoft Corporation. All rights reserved.
* Written by Microsoft Developer Support Office Integration (PSS DSOI)
*
* This code is provided via KB 311765 as a sample. It is not a formal
* product and has not been tested with all containers or servers. Use it
* for educational purposes only. See the EULA.TXT file included in the
* KB download for full terms of use and restrictions.
*
* THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
*
***************************************************************************/
#include "dsoframer.h"
#include <afxwin.h>
#include <tchar.h>
#include <wininet.h>
#include <afxinet.h>
////////////////////////////////////////////////////////////////////////
// Core Utility Functions
//
////////////////////////////////////////////////////////////////////////
// Heap Allocation (Private Heap)
//
extern HANDLE v_hPrivateHeap;
STDAPI_(LPVOID) DsoMemAlloc(DWORD cbSize)
{
CHECK_NULL_RETURN(v_hPrivateHeap, NULL);
return HeapAlloc(v_hPrivateHeap, HEAP_ZERO_MEMORY, cbSize);
}
STDAPI_(void) DsoMemFree(LPVOID ptr)
{
if ((v_hPrivateHeap) && (ptr))
HeapFree(v_hPrivateHeap, 0, ptr);
}
int __cdecl _purecall(){__asm{int 3}; return 0;}
////////////////////////////////////////////////////////////////////////
// Global String Functions
//
////////////////////////////////////////////////////////////////////////
// DsoConvertToUnicodeEx
//
STDAPI DsoConvertToUnicodeEx(LPCSTR pszMbcsString, DWORD cbMbcsLen, LPWSTR pwszUnicode, DWORD cbUniLen, UINT uiCodePage)
{
DWORD cbRet;
UINT iCode = CP_ACP;
if (IsValidCodePage(uiCodePage))
iCode = uiCodePage;
CHECK_NULL_RETURN(pwszUnicode, E_POINTER);
pwszUnicode[0] = L'\0';
CHECK_NULL_RETURN(pszMbcsString, E_POINTER);
CHECK_NULL_RETURN(cbMbcsLen, E_INVALIDARG);
CHECK_NULL_RETURN(cbUniLen, E_INVALIDARG);
cbRet = MultiByteToWideChar(iCode, 0, pszMbcsString, cbMbcsLen, pwszUnicode, cbUniLen);
if (cbRet == 0) return E_WIN32_LASTERROR;
pwszUnicode[cbRet] = L'\0';
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// DsoConvertToMBCSEx
//
STDAPI DsoConvertToMBCSEx(LPCWSTR pwszUnicodeString, DWORD cbUniLen, LPSTR pszMbcsString, DWORD cbMbcsLen, UINT uiCodePage)
{
DWORD cbRet;
UINT iCode = CP_ACP;
if (IsValidCodePage(uiCodePage))
iCode = uiCodePage;
CHECK_NULL_RETURN(pszMbcsString, E_POINTER);
pszMbcsString[0] = L'\0';
CHECK_NULL_RETURN(pwszUnicodeString, E_POINTER);
CHECK_NULL_RETURN(cbMbcsLen, E_INVALIDARG);
CHECK_NULL_RETURN(cbUniLen, E_INVALIDARG);
cbRet = WideCharToMultiByte(iCode, 0, pwszUnicodeString, -1, pszMbcsString, cbMbcsLen, NULL, NULL);
if (cbRet == 0) return E_WIN32_LASTERROR;
pszMbcsString[cbRet] = '\0';
return S_OK;
}
////////////////////////////////////////////////////////////////////////
// DsoConvertToLPWSTR
//
// Takes a MBCS string and returns a LPWSTR allocated on private heap.
//
STDAPI_(LPWSTR) DsoConvertToLPWSTR(LPCSTR pszMbcsString)
{
LPWSTR pwsz = NULL;
UINT cblen, cbnew;
if ((pszMbcsString) &&
((cblen = lstrlen(pszMbcsString)) > 0))
{
cbnew = ((cblen + 1) * sizeof(WCHAR));
if ((pwsz = (LPWSTR)DsoMemAlloc(cbnew)) != NULL)
{
if (FAILED(DsoConvertToUnicodeEx(pszMbcsString, cblen, pwsz, cbnew, GetACP())))
{
DsoMemFree(pwsz);
pwsz = NULL;
}
}
}
return pwsz;
}
////////////////////////////////////////////////////////////////////////
// DsoConvertToMBCS
//
// Takes a WCHAR string and returns a LPSTR on the private heap.
//
STDAPI_(LPSTR) DsoConvertToMBCS(LPCWSTR pwszUnicodeString)
{
LPSTR psz = NULL;
UINT cblen, cbnew;
if ((pwszUnicodeString) &&
((cblen = lstrlenW(pwszUnicodeString)) > 0))
{
cbnew = ((cblen + 1) * sizeof(WCHAR));
if ((psz = (LPSTR)DsoMemAlloc(cbnew)) != NULL)
{
if (FAILED(DsoConvertToMBCSEx(pwszUnicodeString, cblen, psz, cbnew, GetACP())))
{
DsoMemFree(psz); psz = NULL;
}
}
}
return psz;
}
////////////////////////////////////////////////////////////////////////
// DsoConvertToBSTR
//
// Takes a MBCS string and returns a BSTR. NULL is returned if the
// function fails or the string is empty.
//
STDAPI_(BSTR) DsoConvertToBSTR(LPCSTR pszMbcsString)
{
BSTR bstr = NULL;
LPWSTR pwsz = DsoConvertToLPWSTR(pszMbcsString);
if (pwsz)
{
bstr = SysAllocString(pwsz);
DsoMemFree(pwsz);
}
return bstr;
}
////////////////////////////////////////////////////////////////////////
// DsoConvertToLPOLESTR
//
// Returns Unicode string in COM Task Memory (CoTaskMemAlloc).
//
STDAPI_(LPWSTR) DsoConvertToLPOLESTR(LPCWSTR pwszUnicodeString)
{
LPWSTR pwsz;
UINT cblen;
CHECK_NULL_RETURN(pwszUnicodeString, NULL);
cblen = lstrlenW(pwszUnicodeString);
pwsz = (LPWSTR)CoTaskMemAlloc((cblen * sizeof(WCHAR)) + 2);
if (pwsz)
{
memcpy(pwsz, pwszUnicodeString, (cblen * sizeof(WCHAR)));
pwsz[cblen] = L'\0'; // Make sure it is NULL terminated.
}
return pwsz;
}
////////////////////////////////////////////////////////////////////////
// DsoCopyString
//
// Duplicates the string into private heap string.
//
STDAPI_(LPWSTR) DsoCopyString(LPCWSTR pwszString)
{
LPWSTR pwsz;
UINT cblen;
CHECK_NULL_RETURN(pwszString, NULL);
cblen = lstrlenW(pwszString);
pwsz = (LPWSTR)DsoMemAlloc((cblen * sizeof(WCHAR)) + 2);
if (pwsz)
{
memcpy(pwsz, pwszString, (cblen * sizeof(WCHAR)));
pwsz[cblen] = L'\0'; // Make sure it is NULL terminated.
}
return pwsz;
}
////////////////////////////////////////////////////////////////////////
// DsoCopyStringCat
//
STDAPI_(LPWSTR) DsoCopyStringCat(LPCWSTR pwszString1, LPCWSTR pwszString2)
{return DsoCopyStringCatEx(pwszString1, 1, &pwszString2);}
////////////////////////////////////////////////////////////////////////
// DsoCopyStringCatEx
//
// Duplicates the string into private heap string and appends one or more
// strings to the end (concatenation).
//
STDAPI_(LPWSTR) DsoCopyStringCatEx(LPCWSTR pwszBaseString, UINT cStrs, LPCWSTR *ppwszStrs)
{
LPWSTR pwsz;
UINT i, cblenb, cblent;
UINT *pcblens;
// We assume you have a base string to start with. If not, we return NULL...
if ((pwszBaseString == NULL) ||
((cblenb = lstrlenW(pwszBaseString)) < 1))
return NULL;
// If we have nothing to append, just do a plain copy...
if ((cStrs == 0) || (ppwszStrs == NULL))
return DsoCopyString(pwszBaseString);
// Determine the size of the final string by finding the lengths
// of each. We create an array of sizes to use later on...
cblent = cblenb;
pcblens = new UINT[cStrs];
CHECK_NULL_RETURN(pcblens, NULL);
for (i = 0; i < cStrs; i++)
{
pcblens[i] = lstrlenW(ppwszStrs[i]);
cblent += pcblens[i];
}
// If we have data to append, create the new string and append the
// data by copying them in place. We expect UTF-16 Unicode strings
// for this to work, but this should be normal...
if (cblent > cblenb)
{
pwsz = (LPWSTR)DsoMemAlloc(((cblent + 1) * sizeof(WCHAR)));
CHECK_NULL_RETURN(pwsz, NULL);
memcpy(pwsz, pwszBaseString, (cblenb * sizeof(WCHAR)));
cblent = cblenb;
for (i = 0; i < cStrs; i++)
{
memcpy((pwsz + cblent), ppwszStrs[i], (pcblens[i] * sizeof(WCHAR)));
cblent += pcblens[i];
}
}
else pwsz = DsoCopyString(pwszBaseString);
delete [] pcblens;
return pwsz;
}
////////////////////////////////////////////////////////////////////////
// DsoCLSIDtoLPSTR
//
STDAPI_(LPSTR) DsoCLSIDtoLPSTR(REFCLSID clsid)
{
LPSTR psz = NULL;
LPWSTR pwsz;
if (SUCCEEDED(StringFromCLSID(clsid, &pwsz)))
{
psz = DsoConvertToMBCS(pwsz);
CoTaskMemFree(pwsz);
}
return psz;
}
///////////////////////////////////////////////////////////////////////////////////
// DsoCompareStringsEx
//
// Calls CompareString API using Unicode version (if available on OS). Otherwise,
// we have to thunk strings down to MBCS to compare. This is fairly inefficient for
// Win9x systems that don't handle Unicode, but hey...this is only a sample.
//
STDAPI_(UINT) DsoCompareStringsEx(LPCWSTR pwsz1, INT cch1, LPCWSTR pwsz2, INT cch2)
{
UINT iret;
LCID lcid = GetThreadLocale();
UINT cblen1, cblen2;
// Check that valid parameters are passed and then contain somethimg...
if ((pwsz1 == NULL) || (cch1 == 0) ||
((cblen1 = ((cch1 > 0) ? cch1 : lstrlenW(pwsz1))) == 0))
return CSTR_LESS_THAN;
if ((pwsz2 == NULL) || (cch2 == 0) ||
((cblen2 = ((cch2 > 0) ? cch2 : lstrlenW(pwsz2))) == 0))
return CSTR_GREATER_THAN;
// If the string is of the same size, then we do quick compare to test for
// equality (this is slightly faster than calling the API, but only if we
// expect the calls to find an equal match)...
if (cblen1 == cblen2)
{
for (iret = 0; iret < cblen1; iret++)
{
if (pwsz1[iret] == pwsz2[iret])
continue;
if (((pwsz1[iret] >= 'A') && (pwsz1[iret] <= 'Z')) &&
((pwsz1[iret] + ('a' - 'A')) == pwsz2[iret]))
continue;
if (((pwsz2[iret] >= 'A') && (pwsz2[iret] <= 'Z')) &&
((pwsz2[iret] + ('a' - 'A')) == pwsz1[iret]))
continue;
break; // don't continue if we can't quickly match...
}
// If we made it all the way, then they are equal...
if (iret == cblen1)
return CSTR_EQUAL;
}
// Now ask the OS to check the strings and give us its read. (We prefer checking
// in Unicode since this is faster and we may have strings that can't be thunked
// down to the local ANSI code page)...
if (v_fUnicodeAPI)
{
iret = CompareStringW(lcid, NORM_IGNORECASE | NORM_IGNOREWIDTH, pwsz1, cblen1, pwsz2, cblen2);
}
else
{
// If we are on Win9x, we don't have much of choice (thunk the call)...
LPSTR psz1 = DsoConvertToMBCS(pwsz1);
LPSTR psz2 = DsoConvertToMBCS(pwsz2);
iret = CompareStringA(lcid, NORM_IGNORECASE, psz1, -1, psz2, -1);
DsoMemFree(psz2);
DsoMemFree(psz1);
}
return iret;
}
////////////////////////////////////////////////////////////////////////
// URL Helpers
//
////////////////////////////////////////////////////////////////////////
// General Functions (checks to see if we can recognize type)
//
STDAPI_(BOOL) LooksLikeUNC(LPCWSTR pwsz)
{
return ((pwsz) && (*pwsz == L'\\') && (*(pwsz + 1) == L'\\') && (*(pwsz + 2) != L'\\'));
}
STDAPI_(BOOL) LooksLikeLocalFile(LPCWSTR pwsz)
{
return ((pwsz) &&
(((*pwsz > 64) && (*pwsz < 91)) || ((*pwsz > 96) && (*pwsz < 123))) &&
(*(pwsz + 1) == L':') && (*(pwsz + 2) == L'\\'));
}
STDAPI_(BOOL) LooksLikeHTTP(LPCWSTR pwsz)
{
return ((pwsz) && ((*pwsz == L'H') || (*pwsz == L'h')) &&
((*(pwsz + 1) == L'T') || (*(pwsz + 1) == L't')) &&
((*(pwsz + 2) == L'T') || (*(pwsz + 2) == L't')) &&
((*(pwsz + 3) == L'P') || (*(pwsz + 3) == L'p')) &&
((*(pwsz + 4) == L':') || (((*(pwsz + 4) == L'S') || (*(pwsz + 4) == L's')) && (*(pwsz + 5) == L':'))));
}
STDAPI_(BOOL) LooksLikeFTP(LPCWSTR pwsz)
{
return ((pwsz) && ((*pwsz == L'F') || (*pwsz == L'f')) &&
((*(pwsz + 1) == L'T') || (*(pwsz + 1) == L't')) &&
((*(pwsz + 2) == L'P') || (*(pwsz + 2) == L'p')) &&
((*(pwsz + 3) == L':') ));
}
////////////////////////////////////////////////////////////////////////
// GetTempPathForURLDownload
//
// Constructs a temp path for a downloaded file. Note we scan the URL
// to find the name of the file so we can use its exention for server
// association (in case it is a non-docfile -- like RTF) and also
// create our own subfolder to try and avoid name conflicts in temp
// folder itself.
//
STDAPI_(BOOL) GetTempPathForURLDownload(WCHAR* pwszURL, WCHAR** ppwszLocalFile)
{
DWORD dw;
LPWSTR pwszTPath = NULL;
LPWSTR pwszTFile = NULL;
CHAR szTmpPath[MAX_PATH];
// Do a little parameter checking and find length of the URL...
if (!(pwszURL) || ((dw = lstrlenW(pwszURL)) < 6) ||
!(LooksLikeHTTP(pwszURL)) || !(ppwszLocalFile))
return FALSE;
*ppwszLocalFile = NULL;
if (GetTempPath(MAX_PATH, szTmpPath))
{
DWORD dwtlen = lstrlen(szTmpPath);
if (dwtlen > 0 && szTmpPath[dwtlen-1] != '\\')
lstrcat(szTmpPath, "\\");
lstrcat(szTmpPath, "DSOWebOffice");
if (CreateDirectory(szTmpPath, NULL) || GetLastError() == ERROR_ALREADY_EXISTS)
{
lstrcat(szTmpPath, "\\");
pwszTPath = DsoConvertToLPWSTR(szTmpPath);
}
}
if (pwszTPath)
{
if (pwszTFile = DsoCopyString(pwszURL))
{
LPWSTR pwszT = pwszTFile;
while (*(++pwszT))
if (*pwszT == L'?'){*pwszT = L'\0'; break;}
while (*(--pwszT))
if (*pwszT == L'/'){++pwszT; break;}
*ppwszLocalFile = DsoCopyStringCat(pwszTPath, pwszT);
DsoMemFree(pwszTFile);
}
DsoMemFree(pwszTPath);
}
return (BOOL)(*ppwszLocalFile);
}
////////////////////////////////////////////////////////////////////////
// URLDownloadFile
//
// Does a simple URLMON download of file (no save back to server allowed),
// and no dependent files will be downloaded (just one temp file).
//
#include "dsoframer.h"
#include "msoffice.h"
#include <atlbase.h>
#include <atlconv.h>
#include <afxdisp.h>
#define toHex(x) (((BYTE)(x)) > 9 ? (BYTE)((BYTE)(x) + 55) : (BYTE)((BYTE)(x) + 48))
STDAPI URLDownloadFile(LPUNKNOWN punk, WCHAR* pwszURL, WCHAR* pwszLocalFile)
{
/* typedef HRESULT (WINAPI *PFN_URLDTFW)(LPUNKNOWN, LPCWSTR, LPCWSTR, DWORD, LPUNKNOWN);
static PFN_URLDTFW pfnURLDownloadToFileW = NULL;
HMODULE hUrlmon;
if (pfnURLDownloadToFileW == NULL)
{
if (hUrlmon = LoadLibrary("URLMON.DLL"))
pfnURLDownloadToFileW = (PFN_URLDTFW)GetProcAddress(hUrlmon, "URLDownloadToFileW");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -