/*++ Copyright (c) 1996 Microsoft Corporation Module Name: util.cpp Abstract: This module contains utility routines for the fax transport provider. Author: Wesley Witt (wesw) 13-Aug-1996 Revision History: 20/10/99 -danl- Fix GetServerName as GetServerNameFromPrinterName. dd-mm-yy -author- description --*/ #include "faxxp.h" #include "debugex.h" #pragma hdrstop // // globals // BOOL oleInitialized; LPVOID MapiMemAlloc( SIZE_T Size ) /*++ Routine Description: Memory allocator. Arguments: Size - Number of bytes to allocate. Return Value: Pointer to the allocated memory or NULL for failure. --*/ { LPVOID ptr=NULL; HRESULT hResult; // [Win64bug] gpfnAllocateBuffer should accpet size_t as allocating size hResult = gpfnAllocateBuffer( DWORD(Size), &ptr ); if (S_OK == hResult) { ZeroMemory( ptr, Size ); } return ptr; } LPVOID MapiMemReAlloc( LPVOID ptr, SIZE_T Size ) /*++ Routine Description: Memory re-allocator. Arguments: ptr - pre-allocated buffer Size - Number of bytes to allocate. Return Value: Pointer to the allocated memory or NULL for failure. --*/ { LPVOID NewPtr = NULL; HRESULT hResult; // [Win64bug] gpfnAllocateBuffer should accpet size_t as allocating size hResult = gpfnAllocateMore( DWORD(Size), ptr, &NewPtr ); if (S_OK == hResult) { ZeroMemory( NewPtr, Size ); } return NewPtr; } VOID MapiMemFree( LPVOID ptr ) /*++ Routine Description: Memory de-allocator. Arguments: ptr - Pointer to the memory block. Return Value: None. --*/ { if (ptr) { gpfnFreeBuffer( ptr ); } } PVOID MyEnumPrinters( LPTSTR pServerName, DWORD level, OUT PDWORD pcPrinters ) /*++ Routine Description: Wrapper function for spooler API EnumPrinters Arguments: pServerName - Specifies the name of the print server level - Level of PRINTER_INFO_x structure pcPrinters - Returns the number of printers enumerated Return Value: Pointer to an array of PRINTER_INFO_x structures NULL if there is an error --*/ { DBG_ENTER(TEXT("MyEnumPrinters")); PBYTE pPrinterInfo = NULL; DWORD cb; // first, we give no printer information buffer, so the function fails, but returns // in cb the number of bytes needed. then we allocate enough memory, // and call the function again, this time with all of the needed parameters. if (! EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, pServerName, level, NULL, 0, &cb, pcPrinters) //the call failed && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) //this is the reason for failing && (pPrinterInfo = (PBYTE)MemAlloc(cb)) //we managed to allocate more memory && EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, pServerName, level, pPrinterInfo, cb, &cb, pcPrinters)) //and now the call succeded { return pPrinterInfo; } MemFree(pPrinterInfo); return NULL; } HRESULT WINAPI OpenServiceProfileSection( LPMAPISUP pSupObj, LPPROFSECT * ppProfSectObj ) /*++ Routine Description: This function opens the profile section of this service, where the properties of a FAX provider (AB, MS, or XP) are stored. Arguments: pSupObj - Pointer to the provider support object ppProfSectObj - Where we return a pointer to the service profile section of the provider Return Value: An HRESULT. --*/ { HRESULT hResult; DBG_ENTER(TEXT("OpenServiceProfileSection"),hResult); SPropTagArray sptService = { 1, { PR_SERVICE_UID } }; LPPROFSECT pProvProfSectObj; ULONG cValues; LPSPropValue pProp; // // Get the PROVIDER profile section // hResult = pSupObj->OpenProfileSection( NULL, MAPI_MODIFY, &pProvProfSectObj ); if (SUCCEEDED(hResult)) { // Get the UID of the profile section of the service where this provider is installed hResult = pProvProfSectObj->GetProps (&sptService, FALSE, &cValues, &pProp); if (SUCCEEDED(hResult)) { if (S_OK == hResult) { // Now, with the obtained UID, open the profile section of the service hResult = pSupObj->OpenProfileSection ((LPMAPIUID)pProp->Value.bin.lpb, MAPI_MODIFY, ppProfSectObj); } else { hResult = E_FAIL; } MemFree( pProp ); } pProvProfSectObj->Release(); } return hResult; } LPTSTR RemoveLastNode( LPTSTR Path ) /*++ Routine Description: Removes the last node from a path string. Arguments: Path - Path string. Return Value: Pointer to the path string. --*/ { LPTSTR Pstr = NULL; if (Path == NULL || Path[0] == 0) { return Path; } Pstr = _tcsrchr(Path,TEXT('\\')); if( Pstr && (*_tcsinc(Pstr)) == '\0' ) { // the last character is a backslash, truncate it... _tcsset(Pstr,TEXT('\0')); Pstr = _tcsdec(Path,Pstr); } Pstr = _tcsrchr(Path,TEXT('\\')); if( Pstr ) { _tcsnset(_tcsinc(Pstr),TEXT('\0'),1); } return Path; } PDEVMODE GetPerUserDevmode( LPTSTR PrinterName ) { PDEVMODE DevMode = NULL; LONG Size; PRINTER_DEFAULTS PrinterDefaults; HANDLE hPrinter; PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = PRINTER_READ; if (!OpenPrinter( PrinterName, &hPrinter, &PrinterDefaults )) { DebugPrint(( TEXT("OpenPrinter() failed, ec=%d"), ::GetLastError() )); return NULL; } Size = DocumentProperties( NULL, hPrinter, PrinterName, NULL, NULL, 0 ); if (Size < 0) { goto exit; } DevMode = (PDEVMODE) MemAlloc( Size ); if (DevMode == NULL) { goto exit; } Size = DocumentProperties( NULL, hPrinter, PrinterName, DevMode, NULL, DM_OUT_BUFFER ); if (Size < 0) { MemFree( DevMode ); DevMode = NULL; goto exit; } exit: ClosePrinter( hPrinter ); return DevMode; } DWORD GetDwordProperty( LPSPropValue pProps, DWORD PropId ) { if (PROP_TYPE(pProps[PropId].ulPropTag) == PT_ERROR) { return 0; } return pProps[PropId].Value.ul; } DWORD GetBinaryProperty( LPSPropValue pProps, DWORD PropId, OUT LPVOID Buffer, DWORD SizeOfBuffer ) { if (PROP_TYPE(pProps[PropId].ulPropTag) == PT_ERROR) { return 0; } if (pProps[PropId].Value.bin.cb > SizeOfBuffer) { return 0; } CopyMemory( Buffer, pProps[PropId].Value.bin.lpb, pProps[PropId].Value.bin.cb ); return pProps[PropId].Value.bin.cb; } PVOID MyGetPrinter( LPTSTR PrinterName, DWORD level ) /*++ Routine Description: Wrapper function for GetPrinter spooler API Arguments: hPrinter - Identifies the printer in question level - Specifies the level of PRINTER_INFO_x structure requested Return Value: Pointer to a PRINTER_INFO_x structure, NULL if there is an error --*/ { DBG_ENTER(TEXT("MyGetPrinter")); HANDLE hPrinter; PBYTE pPrinterInfo = NULL; DWORD cbNeeded; PRINTER_DEFAULTS PrinterDefaults; PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = PRINTER_READ; //PRINTER_ALL_ACCESS; if (!OpenPrinter( PrinterName, &hPrinter, &PrinterDefaults )) { CALL_FAIL (GENERAL_ERR, TEXT("OpenPrinter"), ::GetLastError()); return NULL; } if (!GetPrinter( hPrinter, level, NULL, 0, &cbNeeded ) && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER && (pPrinterInfo = (PBYTE) MemAlloc( cbNeeded )) && GetPrinter( hPrinter, level, pPrinterInfo, cbNeeded, &cbNeeded )) { ClosePrinter( hPrinter ); return pPrinterInfo; } ClosePrinter( hPrinter ); MemFree( pPrinterInfo ); return NULL; } BOOL GetServerNameFromPrinterName( LPTSTR lptszPrinterName, LPTSTR *pptszServerName ) /*++ Routine Description: retrieve the server name given a printer name Arguments: [in] lptszPrinterName - Identifies the printer in question [out] lptszServerName - Address of pointer to output string buffer. NULL indicates local server. The caller is responsible to free the buffer which pointer is given in this parameter. Return Value: BOOL: TRUE - operation succeeded , FALSE: failed --*/ { BOOL bRes = FALSE; DBG_ENTER(TEXT("GetServerNameFromPrinterName"),bRes); PPRINTER_INFO_2 ppi2 = NULL; LPTSTR lptstrBuffer = NULL; if (lptszPrinterName) { if (ppi2 = (PPRINTER_INFO_2) MyGetPrinter(lptszPrinterName,2)) { bRes = GetServerNameFromPrinterInfo(ppi2,&lptstrBuffer); MemFree(ppi2); if (bRes) { *pptszServerName = lptstrBuffer; } } } return bRes; } LPTSTR ConvertAStringToTString(LPCSTR lpcstrSource) { LPTSTR lptstrDestination; if (!lpcstrSource) return NULL; #ifdef UNICODE lptstrDestination = AnsiStringToUnicodeString( lpcstrSource ); #else // !UNICODE lptstrDestination = StringDup( lpcstrSource ); #endif // UNICODE return lptstrDestination; } LPSTR ConvertTStringToAString(LPCTSTR lpctstrSource) { LPSTR lpstrDestination; if (!lpctstrSource) return NULL; #ifdef UNICODE lpstrDestination = UnicodeStringToAnsiString( lpctstrSource ); #else // !UNICODE lpstrDestination = StringDup( lpctstrSource ); #endif // UNICODE return lpstrDestination; } void ErrorMsgBox( HINSTANCE hInstance, DWORD dwMsgId ) /*++ Routine Description: Display error message box Arguments: hInstance - [in] resource instance handle dwMsgId - [in] string resource ID Return Value: none --*/ { TCHAR* ptCaption=NULL; TCHAR tszCaption[MAX_PATH]; TCHAR tszMessage[MAX_PATH]; DBG_ENTER(TEXT("ErrorMsgBox")); if(!LoadString( hInstance, IDS_FAX_MESSAGE, tszCaption, sizeof(tszCaption) / sizeof(tszCaption[0]))) { CALL_FAIL(GENERAL_ERR, TEXT("LoadString"), ::GetLastError()); } else { ptCaption = tszCaption; } if(!LoadString( hInstance, dwMsgId, tszMessage, sizeof(tszMessage) / sizeof(tszMessage[0]))) { CALL_FAIL(GENERAL_ERR, TEXT("LoadString"), ::GetLastError()); Assert(FALSE); return; } MessageBeep(MB_ICONEXCLAMATION); AlignedMessageBox(NULL, tszMessage, ptCaption, MB_OK | MB_ICONERROR); }