You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
867 lines
19 KiB
867 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1994-1999 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
common.cxx
|
|
|
|
Abstract:
|
|
|
|
common functions across all spooler components
|
|
|
|
Author:
|
|
|
|
Steve Kiraly (SteveKi)
|
|
|
|
Revision History:
|
|
|
|
Felix Maxa (AMaxa) 19 Apr 2001
|
|
Added StrCatSystemPath
|
|
|
|
--*/
|
|
#include "spllibp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "splcom.h"
|
|
|
|
extern "C"
|
|
DWORD
|
|
WINAPIV
|
|
StrCatAlloc(
|
|
IN OUT LPCTSTR *ppszString,
|
|
...
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine concatenates a set of null terminated strings
|
|
and returns a pointer to the new string. It's the callers
|
|
responsibility to release the returned string with a call
|
|
to FreeSplMem(); The last argument must be a NULL
|
|
to signify the end of the argument list.
|
|
|
|
Arguments:
|
|
|
|
ppszString - pointer where to return pointer to newly created
|
|
string which is the concatenation of the passed
|
|
in strings.
|
|
... - variable number of string to concatenate.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS if new concatenated string is returned,
|
|
or ERROR_XXX if an error occurred.
|
|
|
|
Notes:
|
|
|
|
The caller must pass valid strings as arguments to this routine,
|
|
if an integer or other parameter is passed the routine will either
|
|
crash or fail abnormally. Since this is an internal routine
|
|
we are not in try except block for performance reasons.
|
|
|
|
Usage
|
|
|
|
--*/
|
|
{
|
|
UINT uTotalLen = 0;
|
|
DWORD dwRetval = ERROR_INVALID_PARAMETER;
|
|
LPTSTR pszString = NULL;
|
|
LPCTSTR pszTemp = NULL;
|
|
va_list pArgs;
|
|
|
|
//
|
|
// Validate the pointer where to return the buffer.
|
|
//
|
|
if (ppszString)
|
|
{
|
|
dwRetval = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Keep the callers from getting random value on failure.
|
|
//
|
|
*ppszString = NULL;
|
|
|
|
//
|
|
// Get pointer to argument frame.
|
|
//
|
|
va_start(pArgs, ppszString);
|
|
|
|
//
|
|
// Tally up all the strings.
|
|
//
|
|
for ( ; ; )
|
|
{
|
|
//
|
|
// Get pointer to the next argument.
|
|
//
|
|
pszTemp = va_arg(pArgs, LPCTSTR);
|
|
|
|
if (!pszTemp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Sum all the string lengths.
|
|
//
|
|
uTotalLen = uTotalLen + _tcslen(pszTemp);
|
|
}
|
|
|
|
//
|
|
// Need space for the null terminator.
|
|
//
|
|
uTotalLen = uTotalLen + 1;
|
|
|
|
//
|
|
// Allocate the space for the sum of all the strings.
|
|
//
|
|
pszString = (LPTSTR)AllocSplMem(uTotalLen * sizeof(TCHAR));
|
|
|
|
if (pszString)
|
|
{
|
|
*pszString = L'\0';
|
|
|
|
//
|
|
// Reset the pointer to the argument frame.
|
|
//
|
|
va_start(pArgs, ppszString);
|
|
|
|
//
|
|
// Concatenate all the strings.
|
|
//
|
|
for ( ; ; )
|
|
{
|
|
pszTemp = va_arg(pArgs, LPCTSTR);
|
|
|
|
if (!pszTemp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
StringCchCat(pszString, uTotalLen, pszTemp);
|
|
}
|
|
|
|
//
|
|
// Copy back the string pointer to the caller.
|
|
//
|
|
*ppszString = pszString;
|
|
}
|
|
else
|
|
{
|
|
dwRetval = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
va_end(pArgs);
|
|
}
|
|
|
|
//
|
|
// Set the last error in case the caller forgets to.
|
|
//
|
|
if (dwRetval != ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwRetval);
|
|
}
|
|
|
|
return dwRetval;
|
|
}
|
|
|
|
extern "C"
|
|
DWORD
|
|
WINAPIV
|
|
StrNCatBuff(
|
|
IN LPTSTR pszBuffer,
|
|
IN UINT cchBuffer,
|
|
...
|
|
)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine concatenates a set of null terminated strings
|
|
into the provided buffer. The last argument must be a NULL
|
|
to signify the end of the argument list.
|
|
|
|
Arguments:
|
|
|
|
pszBuffer - pointer buffer where to place the concatenated
|
|
string.
|
|
cchBuffer - character count of the provided buffer including
|
|
the null terminator.
|
|
... - variable number of string to concatenate.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS if new concatenated string is returned,
|
|
or ERROR_XXX if an error occurred.
|
|
|
|
Notes:
|
|
|
|
The caller must pass valid strings as arguments to this routine,
|
|
if an integer or other parameter is passed the routine will either
|
|
crash or fail abnormally. Since this is an internal routine
|
|
we are not in try except block for performance reasons.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwRetval = ERROR_INVALID_PARAMETER;
|
|
LPCTSTR pszTemp = NULL;
|
|
LPTSTR pszDest = NULL;
|
|
va_list pArgs;
|
|
|
|
//
|
|
// Validate the pointer where to return the buffer.
|
|
//
|
|
if (pszBuffer && cchBuffer)
|
|
{
|
|
//
|
|
// Assume success.
|
|
//
|
|
dwRetval = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Get pointer to argument frame.
|
|
//
|
|
va_start(pArgs, cchBuffer);
|
|
|
|
//
|
|
// Get temp destination pointer.
|
|
//
|
|
pszDest = pszBuffer;
|
|
|
|
//
|
|
// Insure we have space for the null terminator.
|
|
//
|
|
cchBuffer--;
|
|
|
|
//
|
|
// Collect all the arguments.
|
|
//
|
|
for ( ; ; )
|
|
{
|
|
//
|
|
// Get pointer to the next argument.
|
|
//
|
|
pszTemp = va_arg(pArgs, LPCTSTR);
|
|
|
|
if (!pszTemp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Copy the data into the destination buffer.
|
|
//
|
|
for ( ; cchBuffer; cchBuffer-- )
|
|
{
|
|
if (!(*pszDest = *pszTemp))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pszDest++, pszTemp++;
|
|
}
|
|
|
|
//
|
|
// If were unable to write all the strings to the buffer,
|
|
// set the error code and nuke the incomplete copied strings.
|
|
//
|
|
if (!cchBuffer && pszTemp && *pszTemp)
|
|
{
|
|
dwRetval = ERROR_INVALID_PARAMETER;
|
|
*pszBuffer = _T('\0');
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Terminate the buffer always.
|
|
//
|
|
*pszDest = _T('\0');
|
|
|
|
va_end(pArgs);
|
|
}
|
|
|
|
//
|
|
// Set the last error in case the caller forgets to.
|
|
//
|
|
if (dwRetval != ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwRetval);
|
|
}
|
|
|
|
return dwRetval;
|
|
|
|
}
|
|
|
|
extern "C"
|
|
LPTSTR
|
|
WINAPI
|
|
SubChar(
|
|
IN LPCTSTR pszIn,
|
|
IN TCHAR cIn,
|
|
IN TCHAR cOut
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Replaces all instances of cIn in pszIn with cOut.
|
|
|
|
Arguments:
|
|
|
|
pszIn - input string
|
|
cIn - character to replace with cOut
|
|
cOut - character that replaces cIn
|
|
|
|
Return Value:
|
|
|
|
If successful, returns a pointer to an allocated buffer containing the
|
|
output string. If the return value is NULL, SubChar has fails and
|
|
GetLastError() will return the error.
|
|
|
|
Notes:
|
|
|
|
An output buffer is allocated (and contains NULL) even if pszOut is NULL.
|
|
|
|
--*/
|
|
{
|
|
LPTSTR pszReturn = NULL;
|
|
LPTSTR pszOut = NULL;
|
|
|
|
if (cIn && pszIn)
|
|
{
|
|
if ((pszOut = pszReturn = (LPTSTR) AllocSplMem((_tcslen(pszIn) + 1)*sizeof(TCHAR))))
|
|
{
|
|
for (; *pszIn ; ++pszIn, ++pszOut)
|
|
{
|
|
*pszOut = (*pszIn == cIn) ? cOut : *pszIn;
|
|
}
|
|
*pszOut = *pszIn;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return pszReturn;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
GetLastErrorAsHResult
|
|
|
|
Routine Description:
|
|
|
|
Returns the last error as an HRESULT assuming a failure.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
An HRESULT.
|
|
|
|
--*/
|
|
EXTERN_C
|
|
HRESULT
|
|
GetLastErrorAsHResult(
|
|
VOID
|
|
)
|
|
{
|
|
return HResultFromWin32(GetLastError());
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
GetFileNamePart
|
|
|
|
Routine Description:
|
|
|
|
Get the file name portion of a path.
|
|
|
|
Arguments:
|
|
|
|
pszFullPath - Full path to a file
|
|
ppszFileName - File name
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
EXTERN_C
|
|
HRESULT
|
|
GetFileNamePart(
|
|
IN PCWSTR pszFullPath,
|
|
OUT PCWSTR *ppszFileName
|
|
)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
WCHAR szfname[_MAX_FNAME] = {0};
|
|
|
|
hRetval = pszFullPath && ppszFileName ? S_OK : E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
_wsplitpath(pszFullPath, NULL, NULL, szfname, NULL);
|
|
*ppszFileName = wcsstr(pszFullPath, szfname);
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
GetLastErrorAsHResultAndFail
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the last error as HRESULT, and if there was no last error,
|
|
returns E_UNEXPECTED.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
EXTERN_C
|
|
HRESULT
|
|
GetLastErrorAsHResultAndFail(
|
|
void
|
|
)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
|
|
hRetval = GetLastErrorAsHResult();
|
|
|
|
if (S_OK == hRetval)
|
|
{
|
|
hRetval = E_UNEXPECTED;
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
HResultFromWin32
|
|
|
|
Routine Description:
|
|
|
|
Returns the last error as an HRESULT assuming a failure.
|
|
|
|
Arguments:
|
|
|
|
dwError - Win32 error code
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
EXTERN_C
|
|
HRESULT
|
|
HResultFromWin32(
|
|
IN DWORD dwError
|
|
)
|
|
{
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
}
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine allocates a string which is the concatenation:
|
|
Directory\pszFile. Directory is Windir, SystemRoot, CurrentDir,
|
|
SystemWindowsDir, depending on the edir input argument.
|
|
|
|
Arguments:
|
|
|
|
pszFile - file name
|
|
eDir - enumeration, tells the function what directory to concatenate
|
|
ppszFullPath - pointer where to return pointer to newly created string
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS if new concatenated string is returned,
|
|
or ERROR_XXX if an error occurred.
|
|
|
|
Notes:
|
|
|
|
The caller must use FreeSplMem to free the string returned by this function
|
|
|
|
--*/
|
|
EXTERN_C
|
|
DWORD
|
|
WINAPI
|
|
StrCatSystemPath(
|
|
IN LPCTSTR pszFile,
|
|
IN EStrCatDir eDir,
|
|
OUT LPTSTR *ppszFullPath
|
|
)
|
|
{
|
|
DWORD Error = ERROR_INVALID_PARAMETER;
|
|
|
|
//
|
|
// Validate arguments
|
|
//
|
|
if (pszFile && ppszFullPath)
|
|
{
|
|
DWORD cchNeeded;
|
|
|
|
*ppszFullPath = NULL;
|
|
|
|
//
|
|
// Get the number of chars needed to hold the system directory. The returned
|
|
// number accounts for the NULL terminator. GetCurrentDirectory is different than
|
|
// the other function, because if takes the size of the buffer as the first
|
|
// argument.
|
|
//
|
|
cchNeeded = eDir == kWindowsDir ? GetWindowsDirectory(NULL, 0) :
|
|
eDir == kSystemWindowsDir ? GetSystemWindowsDirectory(NULL, 0) :
|
|
eDir == kSystemDir ? GetSystemDirectory(NULL, 0) :
|
|
GetCurrentDirectory(0, NULL);
|
|
|
|
Error = cchNeeded ? ERROR_SUCCESS : GetLastError();
|
|
|
|
if (Error == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Calculate the size of the buffer needed. Note that cchNeeded already
|
|
// includes the NULL terminator.
|
|
// length(directory) + whack + length(pszFile)
|
|
//
|
|
cchNeeded = cchNeeded + 1 + _tcslen(pszFile);
|
|
|
|
*ppszFullPath = static_cast<LPTSTR>(AllocSplMem(cchNeeded * sizeof(TCHAR)));
|
|
|
|
Error = *ppszFullPath ? ERROR_SUCCESS : GetLastError();
|
|
|
|
if (Error == ERROR_SUCCESS)
|
|
{
|
|
DWORD cchTemp;
|
|
|
|
cchTemp = eDir == kWindowsDir ? GetWindowsDirectory(*ppszFullPath, cchNeeded) :
|
|
eDir == kSystemWindowsDir ? GetSystemWindowsDirectory(*ppszFullPath, cchNeeded) :
|
|
eDir == kSystemDir ? GetSystemDirectory(*ppszFullPath, cchNeeded) :
|
|
GetCurrentDirectory(cchNeeded, *ppszFullPath);
|
|
if (cchTemp)
|
|
{
|
|
StringCchCat(*ppszFullPath, cchNeeded, _T("\\"));
|
|
StringCchCat(*ppszFullPath, cchNeeded, pszFile);
|
|
}
|
|
else
|
|
{
|
|
Error = GetLastError();
|
|
|
|
FreeSplMem(*ppszFullPath);
|
|
|
|
*ppszFullPath = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine converts a unicode string to an ansi string. The caller
|
|
must free the ansi string using "delete [] pszAnsi".
|
|
|
|
Arguments:
|
|
|
|
pszUnicode - pointer to NULL terminated unicode string
|
|
ppszAnsi - pointer where to return pointer to newly created string
|
|
|
|
Returns:
|
|
|
|
S_OK - operation was successful and *ppszAnsi can be used
|
|
or any other HRESULT if an error occurred.
|
|
|
|
--*/
|
|
EXTERN_C
|
|
HRESULT
|
|
UnicodeToAnsiWithAlloc(
|
|
IN LPCWSTR pszUnicode,
|
|
OUT LPSTR *ppszAnsi
|
|
)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppszAnsi)
|
|
{
|
|
*ppszAnsi = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
if (pszUnicode)
|
|
{
|
|
INT rc;
|
|
|
|
rc = WideCharToMultiByte(CP_THREAD_ACP,
|
|
0,
|
|
pszUnicode,
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (rc)
|
|
{
|
|
*ppszAnsi = new CHAR[rc];
|
|
|
|
if (*ppszAnsi)
|
|
{
|
|
rc = WideCharToMultiByte(CP_THREAD_ACP,
|
|
0,
|
|
pszUnicode,
|
|
-1,
|
|
*ppszAnsi,
|
|
rc,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (!rc)
|
|
{
|
|
hr = GetLastErrorAsHResult();
|
|
|
|
delete [] *ppszAnsi;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastErrorAsHResult();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This routine converts an ansi string to a unicode string. The caller
|
|
must free the unicode string using "delete [] pszUnicode".
|
|
|
|
Arguments:
|
|
|
|
pszAnsi - pointer to NULL terminated ansi string
|
|
ppszUnicode - pointer where to return pointer to newly created string
|
|
|
|
Returns:
|
|
|
|
S_OK - operation was successful and *ppszUnicode can be used
|
|
or any other HRESULT if an error occurred.
|
|
|
|
--*/
|
|
EXTERN_C
|
|
HRESULT
|
|
AnsiToUnicodeWithAlloc(
|
|
IN LPCSTR pszAnsi,
|
|
OUT LPWSTR *ppszUnicode
|
|
)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (ppszUnicode)
|
|
{
|
|
*ppszUnicode = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
if (pszAnsi)
|
|
{
|
|
INT rc;
|
|
|
|
rc = MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
pszAnsi,
|
|
-1,
|
|
NULL,
|
|
0);
|
|
|
|
if (rc)
|
|
{
|
|
*ppszUnicode = new WCHAR[rc];
|
|
|
|
if (*ppszUnicode)
|
|
{
|
|
rc = MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
pszAnsi,
|
|
-1,
|
|
*ppszUnicode,
|
|
rc);
|
|
|
|
if (!rc)
|
|
{
|
|
hr = GetLastErrorAsHResult();
|
|
|
|
delete [] *ppszUnicode;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastErrorAsHResult();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
StatusFromHResult
|
|
|
|
Description:
|
|
|
|
This function returns a win32 error code from an HRESULT if possible and
|
|
it failed, if it is not a win32 error code, it just returns the error code,
|
|
otherwise it returns ERROR_SUCCESS.
|
|
|
|
Arguments:
|
|
|
|
hr - The HRESULT.
|
|
|
|
Returns:
|
|
|
|
The status equivalent of the hresult.
|
|
|
|
--*/
|
|
EXTERN_C
|
|
DWORD
|
|
StatusFromHResult(
|
|
IN HRESULT hr
|
|
)
|
|
{
|
|
DWORD Status = ERROR_SUCCESS;
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
|
|
{
|
|
Status = HRESULT_CODE(hr);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Kind of wacky, should we have a table here for reasonably translatable HResults?
|
|
//
|
|
Status = hr;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
BoolFromHResult
|
|
|
|
Description:
|
|
|
|
This function take an HRESULT input, if the HRESULT is a failure, it sets
|
|
the last error and returns false, otherwise it returns TRUE.
|
|
|
|
Arguments:
|
|
|
|
hr - The HRESULT.
|
|
|
|
Returns:
|
|
|
|
A BOOLEAN, Sets the last error
|
|
|
|
--*/
|
|
EXTERN_C
|
|
BOOL
|
|
BoolFromHResult(
|
|
IN HRESULT hr
|
|
)
|
|
{
|
|
DWORD Status = StatusFromHResult(hr);
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
SetLastError(Status);
|
|
}
|
|
|
|
return Status == ERROR_SUCCESS;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
BoolFromStatus
|
|
|
|
Description:
|
|
|
|
This function sets the last error to the given win32 error code if it is not
|
|
error success. It returns the corresponding error result.
|
|
|
|
Arguments:
|
|
|
|
Status - The Win32 error code.
|
|
|
|
Returns:
|
|
|
|
A BOOLEAN, Sets the last error
|
|
|
|
--*/
|
|
EXTERN_C
|
|
BOOL
|
|
BoolFromStatus(
|
|
IN DWORD Status
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (ERROR_SUCCESS != Status)
|
|
{
|
|
SetLastError(Status);
|
|
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|