698 lines
17 KiB
C++
698 lines
17 KiB
C++
/*****************************************************************************\
|
|
* MODULE: util.c
|
|
*
|
|
* This module contains utility routines.
|
|
*
|
|
*
|
|
* Copyright (C) 1996-1997 Microsoft Corporation
|
|
* Copyright (C) 1996-1997 Hewlett Packard
|
|
*
|
|
* History:
|
|
* 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT
|
|
*
|
|
\*****************************************************************************/
|
|
#include "precomp.h"
|
|
#include "priv.h"
|
|
|
|
#ifdef NOT_IMPLEMENTED
|
|
|
|
// NOTE: The shell-extensions don't seem to be necessary at the moment.
|
|
//
|
|
// 15-Oct-1996 : ChrisWil
|
|
//
|
|
|
|
int APIENTRY ShexDllMain(
|
|
HINSTANCE hInstance,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved);
|
|
|
|
#endif
|
|
|
|
/*****************************************************************************\
|
|
* utlInternalValidatePrinterHandle
|
|
*
|
|
* Returns the port-handle if the specified printer-handle is a valid.
|
|
*
|
|
\*****************************************************************************/
|
|
PCINETMONPORT utlInternalValidatePrinterHandle(
|
|
HANDLE hPrinter,
|
|
BOOL bAllowDeletePending,
|
|
PBOOL pbDeletePending)
|
|
{
|
|
LPINET_HPRINTER pPrt;
|
|
PCINETMONPORT pIniPort = NULL;
|
|
|
|
if (pbDeletePending)
|
|
*pbDeletePending = FALSE;
|
|
|
|
_try {
|
|
|
|
if ((pPrt = (LPINET_HPRINTER)hPrinter)) {
|
|
|
|
if ((pPrt->dwSignature == IPO_SIGNATURE) &&
|
|
!(pPrt->dwStatus & PP_ZOMBIE)) {
|
|
|
|
pIniPort = (PCINETMONPORT) pPrt->hPort;
|
|
|
|
if (pbDeletePending) {
|
|
*pbDeletePending = pIniPort->bDeletePending();
|
|
}
|
|
|
|
if (!bAllowDeletePending) {
|
|
if (pIniPort->bDeletePending()) {
|
|
pIniPort = NULL;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} _except(1) {
|
|
|
|
pIniPort = NULL;
|
|
}
|
|
|
|
if (pIniPort == NULL) {
|
|
|
|
DBG_MSG(DBG_LEV_ERROR, (TEXT("Call: utlValidatePrinterHandle: Invalid Handle: Handle(%08lX)"), hPrinter));
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
return pIniPort;
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* utlValidatePrinterHandle
|
|
*
|
|
* Returns the port-handle if the specified printer-handle is a valid.
|
|
*
|
|
\*****************************************************************************/
|
|
PCINETMONPORT utlValidatePrinterHandle(
|
|
HANDLE hPrinter)
|
|
{
|
|
return utlInternalValidatePrinterHandle (hPrinter, FALSE, NULL);
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* utlValidatePrinterHandleForClose
|
|
*
|
|
* Returns the port-handle if the specified printer-handle is a valid.
|
|
*
|
|
\*****************************************************************************/
|
|
PCINETMONPORT utlValidatePrinterHandleForClose(
|
|
HANDLE hPrinter,
|
|
PBOOL pbDeletePending)
|
|
{
|
|
return utlInternalValidatePrinterHandle (hPrinter, TRUE, pbDeletePending);
|
|
}
|
|
|
|
|
|
#ifdef WINNT32
|
|
/*****************************************************************************\
|
|
* utlValidateXcvPrinterHandle
|
|
*
|
|
* Returns the port-handle if the specified printer-handle is a valid.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR utlValidateXcvPrinterHandle(
|
|
HANDLE hPrinter)
|
|
{
|
|
LPINET_XCV_HPRINTER pPrt;
|
|
LPTSTR lpszPortName = NULL;
|
|
|
|
|
|
_try {
|
|
|
|
if ((pPrt = (LPINET_XCV_HPRINTER)hPrinter)) {
|
|
|
|
if ((pPrt->dwSignature == IPO_XCV_SIGNATURE)) {
|
|
|
|
lpszPortName = pPrt->lpszName;
|
|
}
|
|
}
|
|
|
|
} _except(1) {
|
|
|
|
lpszPortName = NULL;
|
|
}
|
|
|
|
if (lpszPortName == NULL) {
|
|
|
|
DBG_MSG(DBG_LEV_ERROR, (TEXT("Call: utlValidateXcvPrinterHandle: Invalid Handle: Handle(%08lX)"), hPrinter));
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
}
|
|
|
|
return lpszPortName;
|
|
}
|
|
#endif
|
|
|
|
|
|
/********************************************************************************
|
|
|
|
Name:
|
|
EncodeUnicodePrinterName
|
|
|
|
Description:
|
|
|
|
Encode the printer name to avoid special characters, also encode any chars
|
|
with ASC code between 0x80 and 0xffff. This is to avoid the conversion betwwen
|
|
different codepages when the client and the server have different language
|
|
packages.
|
|
|
|
The difference between this function and EncodePrinterName in Spllib is that
|
|
this function does not encode ' ', '$' and other special ANSI characters.
|
|
|
|
Arguments:
|
|
|
|
lpText: the normal text string
|
|
lpHTMLStr: the buf provided by the caller to store the encoded string
|
|
if it is NULL, the function will return a FALSE
|
|
lpdwSize: Pointer to the size of the buffer (in characters)
|
|
|
|
Return Value:
|
|
|
|
If the function succeeds, the return value is TRUE;
|
|
If the function fails, the return value is FALSE. To get extended error
|
|
information, call GetLastError.
|
|
|
|
********************************************************************************/
|
|
BOOL EncodeUnicodePrinterName (LPCTSTR lpText, LPTSTR lpHTMLStr, LPDWORD lpdwSize)
|
|
{
|
|
#define MAXLEN_PER_CHAR 6
|
|
#define BIN2ASC(bCode,lpHTMLStr) *lpHTMLStr++ = HexToAsc ((bCode) >> 4);\
|
|
*lpHTMLStr++ = HexToAsc ((bCode) & 0xf)
|
|
|
|
DWORD dwLen;
|
|
BYTE bCode;
|
|
|
|
if (!lpText || !lpdwSize) {
|
|
SetLastError (ERROR_INVALID_DATA);
|
|
return FALSE;
|
|
}
|
|
|
|
dwLen = MAXLEN_PER_CHAR * lstrlen (lpText) + 1;
|
|
|
|
if (!lpHTMLStr || *lpdwSize < dwLen) {
|
|
SetLastError (ERROR_INSUFFICIENT_BUFFER);
|
|
*lpdwSize = dwLen;
|
|
return FALSE;
|
|
}
|
|
|
|
while (*lpText) {
|
|
if ((DWORD) (*lpText) > 0xff ) {
|
|
// Encode as ~0hhll hh is the high byte, ll is the low byte
|
|
*lpHTMLStr++ = TEXT ('~');
|
|
*lpHTMLStr++ = TEXT ('0');
|
|
|
|
// Get the high byte
|
|
bCode = (*lpText & 0xff00) >> 8;
|
|
BIN2ASC(bCode,lpHTMLStr);
|
|
|
|
// Get the low byte
|
|
bCode = (*lpText & 0xff);
|
|
BIN2ASC(bCode,lpHTMLStr);
|
|
}
|
|
else if ((DWORD) (*lpText) > 0x7f) {
|
|
// Encode as ~xx
|
|
*lpHTMLStr++ = TEXT ('~');
|
|
bCode = *lpText & 0xff;
|
|
BIN2ASC(bCode,lpHTMLStr);
|
|
}
|
|
else {
|
|
*lpHTMLStr++ = *lpText;
|
|
}
|
|
lpText++;
|
|
}
|
|
*lpHTMLStr = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* utlParseHostShare
|
|
*
|
|
* Parses the PortName (http://host[:port][/][/share]) into its
|
|
* post/Share/Port components.
|
|
*
|
|
* We accept six formats
|
|
* 1. http://server
|
|
* 2. http://server:port
|
|
* 3. http://server/
|
|
* 4. http://server:port/
|
|
* 5. http://server/share
|
|
* 6. http://server:port/share
|
|
*
|
|
* This routine returns allocated pointers that must be freed by the caller.
|
|
*
|
|
\*****************************************************************************/
|
|
BOOL utlParseHostShare(
|
|
LPCTSTR lpszPortName,
|
|
LPTSTR *lpszHost,
|
|
LPTSTR *lpszShare,
|
|
LPINTERNET_PORT lpPort,
|
|
LPBOOL lpbHTTPS)
|
|
{
|
|
LPTSTR lpszPrt;
|
|
LPTSTR lpszTmp;
|
|
LPTSTR lpszPos;
|
|
BOOL bRet = FALSE;
|
|
|
|
|
|
// Initialize the return buffers to NULL.
|
|
//
|
|
*lpszHost = NULL;
|
|
*lpszShare = NULL;
|
|
*lpPort = 0;
|
|
|
|
// Parse the host-name and the share name. The pszPortName is
|
|
// currently in the format of http://host[:portnumber]/share. We will parse
|
|
// this from left->right since the share-name can be a path (we
|
|
// wouldn't really know the exact length). However, we do know the
|
|
// location for the host-name, and anything after that should be
|
|
// the share-name.
|
|
//
|
|
// First find the ':'. The host-name should begin two "//" after
|
|
// that.
|
|
//
|
|
if (lpszPrt = memAllocStr(lpszPortName)) {
|
|
static TCHAR szHttp[] = TEXT ("http://");
|
|
static TCHAR szHttps[] = TEXT ("https://");
|
|
|
|
lpszTmp = NULL;
|
|
|
|
if (!_tcsnicmp (lpszPrt, szHttp, COUNTOF (szHttp) - 1)) {
|
|
lpszTmp = lpszPrt + COUNTOF (szHttp) - 1;
|
|
*lpbHTTPS = FALSE;
|
|
}
|
|
else if (!_tcsnicmp (lpszPrt, szHttps, COUNTOF (szHttps) - 1)) {
|
|
lpszTmp = lpszPrt + COUNTOF (szHttps) - 1;
|
|
*lpbHTTPS = TRUE;
|
|
}
|
|
|
|
if (lpszTmp) {
|
|
|
|
lpszPos = utlStrChr(lpszTmp, TEXT(':'));
|
|
if (lpszPos) {
|
|
//This url has a port number, we need to parse it
|
|
*lpszPos++ = 0;
|
|
|
|
*lpszHost = memAllocStr(lpszTmp);
|
|
*lpPort = (INTERNET_PORT) _ttol (lpszPos);
|
|
lpszTmp = lpszPos;
|
|
|
|
if (lpszPos = utlStrChr(lpszTmp, TEXT('/'))) {
|
|
*lpszShare = memAllocStr(++lpszPos);
|
|
}
|
|
else {
|
|
*lpszShare = memAllocStr(TEXT (""));
|
|
}
|
|
}
|
|
else {
|
|
// Use the default port number: 80
|
|
|
|
if (lpszPos = utlStrChr(lpszTmp, TEXT('/'))) {
|
|
*lpszPos++ = TEXT('\0');
|
|
|
|
*lpszHost = memAllocStr(lpszTmp);
|
|
*lpszShare = memAllocStr(lpszPos);
|
|
}
|
|
else {
|
|
// The whole thing is a host name
|
|
*lpszHost = memAllocStr(lpszTmp);
|
|
*lpszShare = memAllocStr(TEXT (""));
|
|
|
|
}
|
|
}
|
|
|
|
#ifdef WINNT32
|
|
|
|
if (*lpszShare) {
|
|
|
|
//
|
|
// Let's check if we need to encode the share name
|
|
//
|
|
|
|
INT iMode = IS_TEXT_UNICODE_ASCII16;
|
|
|
|
if (IsTextUnicode ((LPVOID) *lpszShare, lstrlen (*lpszShare) * sizeof (WCHAR), &iMode) == 0) {
|
|
|
|
// The text string is a unicode string contains non-ASCII characters
|
|
// We need to encode the URL into ansi strings
|
|
|
|
DWORD dwSize;
|
|
BOOL bConversion = FALSE;
|
|
LPWSTR pszEncodedName = NULL;
|
|
|
|
EncodeUnicodePrinterName (*lpszShare, NULL, &dwSize);
|
|
|
|
if ((pszEncodedName = (LPWSTR) memAlloc (sizeof (WCHAR) * dwSize))) {
|
|
|
|
if (EncodeUnicodePrinterName (*lpszShare, pszEncodedName, &dwSize)) {
|
|
memFreeStr (*lpszShare);
|
|
*lpszShare = pszEncodedName;
|
|
bConversion = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!bConversion) {
|
|
memFreeStr (pszEncodedName);
|
|
memFreeStr (*lpszShare);
|
|
*lpszShare = NULL;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (*lpszHost && *lpszShare) {
|
|
|
|
bRet = TRUE;
|
|
|
|
} else {
|
|
|
|
// Don't worry that we could be freeing a NULL pointer.
|
|
// The mem-routines check this.
|
|
//
|
|
memFreeStr(*lpszHost);
|
|
memFreeStr(*lpszShare);
|
|
|
|
*lpszHost = NULL;
|
|
*lpszShare = NULL;
|
|
}
|
|
}
|
|
|
|
memFreeStr(lpszPrt);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* utlStrChr
|
|
*
|
|
* Looks for the first location where (c) resides.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR utlStrChr(
|
|
LPCTSTR cs,
|
|
TCHAR c)
|
|
{
|
|
while (*cs != TEXT('\0')) {
|
|
|
|
if (*cs == c)
|
|
return (LPTSTR)cs;
|
|
|
|
cs++;
|
|
}
|
|
|
|
// Fail to find c in cs.
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* utlStrChrR
|
|
*
|
|
* Looks for first occurrence of (c) starting from the end of the buffer.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR utlStrChrR(
|
|
LPCTSTR cs,
|
|
TCHAR c)
|
|
{
|
|
LPTSTR ct;
|
|
|
|
ct = (LPTSTR)cs + (lstrlen(cs) - 1);
|
|
|
|
while (ct >= cs) {
|
|
|
|
if (*ct == c)
|
|
return ct;
|
|
|
|
ct--;
|
|
}
|
|
|
|
// Fail to find c in cs.
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* utlPackStrings
|
|
*
|
|
*
|
|
\*****************************************************************************/
|
|
LPBYTE utlPackStrings(
|
|
LPTSTR *pSource,
|
|
LPBYTE pDest,
|
|
LPDWORD pDestOffsets,
|
|
LPBYTE pEnd)
|
|
{
|
|
while (*pDestOffsets != (DWORD)-1) {
|
|
|
|
if (*pSource) {
|
|
|
|
pEnd -= (lstrlen(*pSource) * sizeof(TCHAR)) + sizeof(TCHAR);
|
|
|
|
*(LPTSTR *)(pDest + *pDestOffsets) = lstrcpy((LPTSTR)pEnd, *pSource);
|
|
|
|
} else {
|
|
|
|
*(LPTSTR *)(pDest + *pDestOffsets) = TEXT('\0');
|
|
}
|
|
|
|
pSource++;
|
|
pDestOffsets++;
|
|
}
|
|
|
|
return pEnd;
|
|
}
|
|
|
|
|
|
/*****************************************************************************\
|
|
* utlStrSize
|
|
*
|
|
* Returns the number of bytes needed to store a string including the NULL
|
|
* terminator.
|
|
*
|
|
\*****************************************************************************/
|
|
int utlStrSize(
|
|
LPCTSTR lpszStr)
|
|
{
|
|
return (lpszStr ? ((lstrlen(lpszStr) + 1) * sizeof(TCHAR)) : 0);
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* utlRegGetVal
|
|
*
|
|
* Retrieves the registry-value for the specified key.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR utlRegGetVal(
|
|
HKEY hKey,
|
|
LPCTSTR lpszKey)
|
|
{
|
|
DWORD dwType;
|
|
DWORD cbSize;
|
|
LONG lRet;
|
|
LPTSTR lpszStr;
|
|
|
|
|
|
dwType = 0;
|
|
cbSize = 0;
|
|
|
|
lRet = RegQueryValueEx(hKey, lpszKey, NULL, &dwType, NULL, &cbSize);
|
|
|
|
if (lRet == ERROR_SUCCESS && cbSize > 0) {
|
|
|
|
if (lpszStr = (LPTSTR)memAlloc(cbSize)) {
|
|
|
|
lRet = RegQueryValueEx(hKey, lpszKey, NULL, &dwType, (LPBYTE)lpszStr, &cbSize);
|
|
|
|
if (lRet == ERROR_SUCCESS)
|
|
return lpszStr;
|
|
|
|
memFreeStr(lpszStr);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
#ifdef WINNT32
|
|
|
|
/*++
|
|
|
|
Routine Description
|
|
|
|
Determines whether or not a machine name contains the local machine name.
|
|
|
|
Localspl enum calls fail if pName != local machine name (\\Machine).
|
|
Remote enum provider is then called. The remote enum provider must check
|
|
if the UNC name refers to the local machine, and fail if it does to avoid
|
|
endless recursion.
|
|
|
|
Arguments:
|
|
|
|
LPWSTR pName - UNC name.
|
|
|
|
Return Value:
|
|
|
|
TRUE: pName == \\szMachineName\...
|
|
- or -
|
|
pName == \\szMachineName
|
|
|
|
FALSE: anything else
|
|
|
|
Author: swilson
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
MyUNCName(
|
|
LPTSTR pNameStart
|
|
)
|
|
{
|
|
LPTSTR pMachine = g_szMachine;
|
|
LPTSTR pName;
|
|
DWORD i;
|
|
|
|
if (!pNameStart || !*pNameStart) // This differs from MyName(), which returns TRUE
|
|
return FALSE;
|
|
|
|
if (*pNameStart == L'\\' && *(pNameStart + 1) == L'\\') {
|
|
for (i = 0 , pName = pNameStart + 2 ; i < g_cOtherNames ; ++i , pName = pNameStart + 2) {
|
|
for(pMachine = g_ppszOtherNames[i] ;
|
|
*pName && towupper(*pName) == towupper(*pMachine) ;
|
|
++pName, ++pMachine)
|
|
;
|
|
|
|
if(!*pMachine && (!*pName || *pName == L'\\'))
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL MyName(
|
|
LPCTSTR pName)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
|
|
if (!pName || !*pName)
|
|
return TRUE;
|
|
|
|
if (*pName == L'\\' && *(pName+1) == L'\\') {
|
|
|
|
if (!lstrcmpi(pName, g_szMachine))
|
|
return TRUE;
|
|
|
|
while ( dwIndex < g_cOtherNames ) {
|
|
|
|
if ( !lstrcmpi(pName+2, g_ppszOtherNames[dwIndex]) )
|
|
return TRUE;
|
|
++dwIndex;
|
|
}
|
|
}
|
|
|
|
|
|
SetLastError( ERROR_INVALID_NAME );
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
BOOL MyServer(
|
|
LPCTSTR pName)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
|
|
if (!pName || !*pName)
|
|
return FALSE;
|
|
|
|
if (!lstrcmpi(pName, g_szMachine))
|
|
return TRUE;
|
|
|
|
if (!lstrcmpi(pName, TEXT ("localhost")))
|
|
return TRUE;
|
|
|
|
#ifdef WINNT32
|
|
while ( dwIndex < g_cOtherNames ) {
|
|
|
|
if ( !lstrcmpi(pName, g_ppszOtherNames[dwIndex]) )
|
|
return TRUE;
|
|
++dwIndex;
|
|
}
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_NAME );
|
|
return FALSE;
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
* GetUserName
|
|
*
|
|
* Retrieves the username for the current logged on thread.
|
|
*
|
|
\*****************************************************************************/
|
|
LPTSTR
|
|
GetUserName(VOID)
|
|
{
|
|
DWORD cbSize;
|
|
LPTSTR lpszUser;
|
|
|
|
|
|
// Initialize the count and retrieve the number of characters
|
|
// necessary for the username.
|
|
//
|
|
cbSize = 0;
|
|
GetUserName(NULL, &cbSize);
|
|
|
|
|
|
// If we were not able to retrieve a valid-count, then allocate
|
|
// an empty string to return from this call.
|
|
//
|
|
if (cbSize) {
|
|
|
|
if (lpszUser = (LPTSTR)memAlloc(cbSize * sizeof(TCHAR))) {
|
|
|
|
if (GetUserName(lpszUser, &cbSize) == FALSE) {
|
|
|
|
*lpszUser = TEXT('\0');
|
|
|
|
goto log_error;
|
|
}
|
|
|
|
} else {
|
|
|
|
DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : GetUserName : Out of memory")));
|
|
}
|
|
|
|
} else {
|
|
|
|
lpszUser = memAllocStr(TEXT("Unknown"));
|
|
|
|
log_error:
|
|
|
|
DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : GetUserName Failed %d"), GetLastError()));
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
}
|
|
|
|
return lpszUser;
|
|
}
|
|
|
|
VOID
|
|
EndBrowserSession (
|
|
VOID)
|
|
{
|
|
g_pcsEndBrowserSessionLock->Lock();
|
|
|
|
InetInternetSetOption(NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
|
|
|
|
g_pcsEndBrowserSessionLock->Unlock();
|
|
}
|
|
|