Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1298 lines
30 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
Utils.cpp
Abstract:
Provides utility functions for the entire poject
Author:
Eran Yariv (EranY) Dec, 1999
Revision History:
--*/
#include "stdafx.h"
#define __FILE_ID__ 10
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CClientConsoleApp theApp;
DWORD
LoadResourceString (
CString &cstr,
int ResId
)
/*++
Routine name : LoadResourceString
Routine description:
Loads a string from the resource
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
cstr [out] - String buffer
ResId [in ] - String resource id
Return Value:
Standard win32 error code
--*/
{
BOOL bRes;
DWORD dwRes = ERROR_SUCCESS;
try
{
bRes = cstr.LoadString (ResId);
}
catch (CMemoryException *pException)
{
DBG_ENTER(TEXT("LoadResourceString"), dwRes);
TCHAR wszCause[1024];
pException->GetErrorMessage (wszCause, 1024);
pException->Delete ();
VERBOSE (EXCEPTION_ERR,
TEXT("CString::LoadString caused exception : %s"),
wszCause);
dwRes = ERROR_NOT_ENOUGH_MEMORY;
PopupError (dwRes);
return dwRes;
}
if (!bRes)
{
dwRes = ERROR_NOT_FOUND;
PopupError (dwRes);
return dwRes;
}
return dwRes;
} // LoadResourceString
CString
DWORDLONG2String (
DWORDLONG dwlData
)
/*++
Routine name : DWORDLONG2String
Routine description:
Converts a 64-bit unsigned number to string
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
dwlData [in] - Number to convert
Return Value:
Output string
--*/
{
CString cstrResult;
cstrResult.Format (TEXT("0x%016I64x"), dwlData);
return cstrResult;
} // DWORDLONG2String
CString
DWORD2String (
DWORD dwData
)
/*++
Routine name : DWORD2String
Routine description:
Converts a 32-bit unsigned number to string
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
dwData [in] - Number to convert
Return Value:
Output string
--*/
{
CString cstrResult;
cstrResult.Format (TEXT("%ld"), dwData);
return cstrResult;
} // DWORD2String
DWORD
Win32Error2String(
DWORD dwWin32Err,
CString& strError
)
/*++
Routine name : Win32Error2String
Routine description:
Format a Win32 error code to a string
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
dwWin32Err [in] - Win32 error code
strError [out] - Result string
Return Value:
error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("Win32Error2String"));
LPTSTR lpszError=NULL;
//
// Create descriptive error text
//
if (!FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwWin32Err,
0,
(TCHAR *)&lpszError,
0,
NULL))
{
//
// Failure to format the message
//
dwRes = GetLastError ();
CALL_FAIL (RESOURCE_ERR, TEXT("FormatMessage"), dwRes);
return dwRes;
}
try
{
strError = lpszError;
}
catch (...)
{
LocalFree (lpszError);
return ERROR_NOT_ENOUGH_MEMORY;
}
LocalFree (lpszError);
return dwRes;
} // Win32Error2String
DWORD
LoadDIBImageList (
CImageList &iml,
int iResourceId,
DWORD dwImageWidth,
COLORREF crMask
)
/*++
Routine name : LoadDIBImageList
Routine description:
Loads an image list from the resource, retaining 24-bit colors
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
iml [out] - Image list buffer
iResourceId [in ] - Image list bitmap resource id
dwImageWidth [in ] - Image width (pixels)
crMask [in ] - Color key (transparent mask)
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("LoadDIBImageList"), dwRes);
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(iResourceId), RT_BITMAP);
if (hInst)
{
HIMAGELIST hIml = ImageList_LoadImage ( hInst,
MAKEINTRESOURCE(iResourceId),
dwImageWidth,
0,
crMask,
IMAGE_BITMAP,
LR_DEFAULTCOLOR);
if (hIml)
{
if (!iml.Attach (hIml))
{
dwRes = ERROR_GEN_FAILURE;
CALL_FAIL (WINDOW_ERR, TEXT("CImageList::Attach"), dwRes);
DeleteObject (hIml);
}
}
else
{
//
// ImageList_LoadImage() failed
//
dwRes = GetLastError();
CALL_FAIL (WINDOW_ERR, _T("ImageList_LoadImage"), dwRes);
}
}
else
{
//
// AfxFindResourceHandle() failed
//
dwRes = GetLastError();
CALL_FAIL (WINDOW_ERR, _T("AfxFindResourceHandle"), dwRes);
}
return dwRes;
} // LoadDIBImageList
#define BUILD_THREAD_DEATH_TIMEOUT INFINITE
DWORD
WaitForThreadDeathOrShutdown (
HANDLE hThread
)
/*++
Routine name : WaitForThreadDeathOrShutdown
Routine description:
Waits for a thread to end.
Also processes windows messages in the background.
Stops waiting if the application is shutting down.
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
hThread [in] - Handle to thread
Return Value:
Standard Win23 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("WaitForThreadDeathOrShutdown"), dwRes);
for (;;)
{
//
// We wait on the thread handle and the shutdown event (which ever comes first)
//
HANDLE hWaitHandles[2];
hWaitHandles[0] = hThread;
hWaitHandles[1] = CClientConsoleDoc::GetShutdownEvent ();
if (NULL == hWaitHandles[1])
{
//
// We're shutting down
//
return dwRes;
}
DWORD dwStart = GetTickCount ();
VERBOSE (DBG_MSG,
TEXT("Entering WaitForMultipleObjects (timeout = %ld)"),
BUILD_THREAD_DEATH_TIMEOUT);
//
// Wait now....
//
dwRes = MsgWaitForMultipleObjects(
sizeof (hWaitHandles) / sizeof(hWaitHandles[0]), // Num of wait objects
hWaitHandles, // Array of wait objects
FALSE, // Wait for either one
BUILD_THREAD_DEATH_TIMEOUT, // Timeout
QS_ALLINPUT); // Accept messages
DWORD dwRes2 = GetLastError();
VERBOSE (DBG_MSG,
TEXT("Leaving WaitForMultipleObjects after waiting for %ld millisecs"),
GetTickCount() - dwStart);
switch (dwRes)
{
case WAIT_FAILED:
dwRes = dwRes2;
if (ERROR_INVALID_HANDLE == dwRes)
{
//
// The thread is dead
//
VERBOSE (DBG_MSG, TEXT("Thread is dead (ERROR_INVALID_HANDLE)"));
dwRes = ERROR_SUCCESS;
}
goto exit;
case WAIT_OBJECT_0:
//
// The thread is not running
//
VERBOSE (DBG_MSG, TEXT("Thread is dead (WAIT_OBJECT_0)"));
dwRes = ERROR_SUCCESS;
goto exit;
case WAIT_OBJECT_0 + 1:
//
// Shutdown is now in progress
//
VERBOSE (DBG_MSG, TEXT("Shutdown in progress"));
dwRes = ERROR_SUCCESS;
goto exit;
case WAIT_OBJECT_0 + 2:
//
// System message (WM_xxx) in our queue
//
MSG msg;
if (TRUE == ::GetMessage (&msg, NULL, NULL, NULL))
{
VERBOSE (DBG_MSG,
TEXT("System message (0x%x)- deferring to AfxWndProc"),
msg.message);
CMainFrame *pFrm = GetFrm();
if (!pFrm)
{
//
// Shutdown in progress
//
goto exit;
}
if (msg.message != WM_KICKIDLE &&
!pFrm->PreTranslateMessage(&msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
else
{
//
// Got WM_QUIT
//
AfxPostQuitMessage (0);
dwRes = ERROR_SUCCESS;
goto exit;
}
break;
case WAIT_TIMEOUT:
//
// Thread won't die !!!
//
VERBOSE (DBG_MSG,
TEXT("Wait timeout (%ld millisecs)"),
BUILD_THREAD_DEATH_TIMEOUT);
goto exit;
default:
//
// What's this???
//
VERBOSE (DBG_MSG,
TEXT("Unknown error (%ld)"),
dwRes);
ASSERTION_FAILURE;
goto exit;
}
}
exit:
return dwRes;
} // WaitForThreadDeathOrShutdown
DWORD
GetUniqueFileName (
LPCTSTR lpctstrExt,
CString &cstrResult
)
/*++
Routine name : GetUniqueFileName
Routine description:
Generates a unique file name
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
lpctstrExt [in] - File extension
cstrResult [out] - Result file name
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("GetUniqueFileName"), dwRes);
TCHAR szDir[MAX_PATH];
//
// Get path to temp dir
//
if (!GetTempPath (MAX_PATH, szDir))
{
dwRes = GetLastError ();
CALL_FAIL (FILE_ERR, TEXT("GetTempPath"), dwRes);
return dwRes;
}
//
// Try out indices - start with a random index and advance (cyclic) by 1.
// We're calling rand() 3 times here because we want to get a larger
// range than 0..RAND_MAX (=32768)
//
DWORD dwStartIndex = DWORD((DWORDLONG)(rand()) *
(DWORDLONG)(rand()) *
(DWORDLONG)(rand())
);
for (DWORD dwIndex = dwStartIndex+1; dwIndex != dwStartIndex; dwIndex++)
{
try
{
cstrResult.Format (TEXT("%s%s%08x%08x.%s"),
szDir,
CONSOLE_PREVIEW_TIFF_PREFIX,
GetCurrentProcessId(),
dwIndex,
lpctstrExt);
}
catch (CMemoryException *pException)
{
TCHAR wszCause[1024];
pException->GetErrorMessage (wszCause, 1024);
pException->Delete ();
VERBOSE (EXCEPTION_ERR,
TEXT("CString::Format caused exception : %s"),
wszCause);
dwRes = ERROR_NOT_ENOUGH_MEMORY;
return dwRes;
}
HANDLE hFile = CreateFile( cstrResult,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
dwRes = GetLastError ();
if (ERROR_FILE_EXISTS == dwRes)
{
//
// Try next index id
//
dwRes = ERROR_SUCCESS;
continue;
}
CALL_FAIL (FILE_ERR, TEXT("CreateFile"), dwRes);
return dwRes;
}
//
// Success - close the file (leave it with size 0)
//
CloseHandle (hFile);
return dwRes;
}
//
// We just scanned 4GB file names and all were busy - impossible.
//
ASSERTION_FAILURE;
dwRes = ERROR_GEN_FAILURE;
return dwRes;
} // GetUniqueFileName
DWORD
CopyTiffFromServer (
CServerNode *pServer,
DWORDLONG dwlMsgId,
FAX_ENUM_MESSAGE_FOLDER Folder,
CString &cstrTiff
)
/*++
Routine name : CopyTiffFromServer
Routine description:
Copies a TIFF file from the server's archive / queue
Author:
Eran Yariv (EranY), Jan, 2000
Arguments:
pServer [in] - Pointer to the server node
dwlMsgId [in] - Id of job / message
Folder [in] - Folder of message / job
cstrTiff [out] - Name of TIFF file that arrived from the server
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("CopyTiffFromServer"), dwRes);
//
// Create a temporary file name for the TIFF
//
dwRes = GetUniqueFileName (FAX_TIF_FILE_EXT, cstrTiff);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("GetUniqueFileName"), dwRes);
return dwRes;
}
HANDLE hFax;
dwRes = pServer->GetConnectionHandle (hFax);
if (ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("CServerNode::GetConnectionHandle"), dwRes);
goto exit;
}
{
START_RPC_TIME(TEXT("FaxGetMessageTiff"));
if (!FaxGetMessageTiff (hFax,
dwlMsgId,
Folder,
cstrTiff))
{
dwRes = GetLastError ();
END_RPC_TIME(TEXT("FaxGetMessageTiff"));
pServer->SetLastRPCError (dwRes);
CALL_FAIL (RPC_ERR, TEXT("FaxGetMessageTiff"), dwRes);
goto exit;
}
END_RPC_TIME(TEXT("FaxGetMessageTiff"));
}
ASSERTION (ERROR_SUCCESS == dwRes);
exit:
if (ERROR_SUCCESS != dwRes)
{
DeleteFile (cstrTiff);
}
return dwRes;
} // CopyTiffFromServer
DWORD
GetDllVersion (
LPCTSTR lpszDllName
)
/*++
Routine Description:
Returns the version information for a DLL exporting "DllGetVersion".
DllGetVersion is exported by the shell DLLs (specifically COMCTRL32.DLL).
Arguments:
lpszDllName - The name of the DLL to get version information from.
Return Value:
The version is retuned as DWORD where:
HIWORD ( version DWORD ) = Major Version
LOWORD ( version DWORD ) = Minor Version
Use the macro PACKVERSION to comapre versions.
If the DLL does not export "DllGetVersion" the function returns 0.
--*/
{
DWORD dwVersion = 0;
DBG_ENTER(TEXT("GetDllVersion"), dwVersion, TEXT("%s"), lpszDllName);
HINSTANCE hinstDll;
hinstDll = LoadLibrary(lpszDllName);
if(hinstDll)
{
DLLGETVERSIONPROC pDllGetVersion;
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
// Because some DLLs may not implement this function, you
// must test for it explicitly. Depending on the particular
// DLL, the lack of a DllGetVersion function may
// be a useful indicator of the version.
if(pDllGetVersion)
{
DLLVERSIONINFO dvi;
HRESULT hr;
ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
hr = (*pDllGetVersion)(&dvi);
if(SUCCEEDED(hr))
{
dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
}
}
FreeLibrary(hinstDll);
}
return dwVersion;
} // GetDllVersion
DWORD
ReadRegistryString(
LPCTSTR lpszSection, // in
LPCTSTR lpszKey, // in
CString& cstrValue // out
)
/*++
Routine name : ReadRegistryString
Routine description:
read string from registry
Author:
Alexander Malysh (AlexMay), Feb, 2000
Arguments:
lpszSection [in] - section
lpszKey [in] - key
out [out] - value
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("ReadRegistryString"), dwRes);
HKEY hKey;
dwRes = RegOpenKeyEx( HKEY_CURRENT_USER, lpszSection, 0, KEY_QUERY_VALUE, &hKey);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx"), dwRes);
return dwRes;
}
DWORD dwType;
TCHAR tchData[1024];
DWORD dwDataSize = sizeof(tchData);
dwRes = RegQueryValueEx( hKey, lpszKey, 0, &dwType, (BYTE*)tchData, &dwDataSize);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RegQueryValueEx"), dwRes);
goto exit;
}
if(REG_SZ != dwType)
{
dwRes = ERROR_BADDB;
goto exit;
}
try
{
cstrValue = tchData;
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::operator="), dwRes);
goto exit;
}
exit:
dwRes = RegCloseKey( hKey );
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RegCloseKey"), dwRes);
return dwRes;
}
return dwRes;
} // ReadRegistryString
DWORD
WriteRegistryString(
LPCTSTR lpszSection, // in
LPCTSTR lpszKey, // in
CString& cstrValue // in
)
/*++
Routine name : WriteRegistryString
Routine description:
write string to the regostry
Author:
Alexander Malysh (AlexMay), Feb, 2000
Arguments:
lpszSection [in] - section
lpszKey [in] - key
out [in] - value
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("WriteRegistryString"), dwRes);
HKEY hKey;
dwRes = RegOpenKeyEx( HKEY_CURRENT_USER, lpszSection, 0, KEY_SET_VALUE, &hKey);
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RegOpenKeyEx"), dwRes);
return dwRes;
}
LPCTSTR lpData = (LPCTSTR)cstrValue;
dwRes = RegSetValueEx( hKey,
lpszKey,
0,
REG_SZ,
(BYTE*)lpData,
(1 + cstrValue.GetLength()) * sizeof (TCHAR));
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RegSetValueEx"), dwRes);
goto exit;
}
exit:
dwRes = RegCloseKey( hKey );
if(ERROR_SUCCESS != dwRes)
{
CALL_FAIL (GENERAL_ERR, TEXT("RegCloseKey"), dwRes);
return dwRes;
}
return dwRes;
} // WriteRegistryString
DWORD
FaxSizeFormat(
DWORDLONG dwlSize, // in
CString& cstrValue // out
)
/*++
Routine name : FaxSizeFormat
Routine description:
format string of file size
Author:
Alexander Malysh (AlexMay), Feb, 2000
Arguments:
wdlSize [in] - size
out [out] - formatted string
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("FaxSizeFormat"), dwRes);
if(dwlSize > 0 && dwlSize < 1024)
{
dwlSize = 1;
}
else
{
dwlSize = dwlSize / (DWORDLONG)1024;
}
try
{
cstrValue.Format (TEXT("%I64d"), dwlSize);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
return dwRes;
}
//
// format the number
//
int nFormatRes;
TCHAR tszNumber[100];
nFormatRes = GetNumberFormat(LOCALE_USER_DEFAULT, // locale
0, // options
cstrValue, // input number string
NULL, // formatting information
tszNumber, // output buffer
sizeof(tszNumber) / sizeof(tszNumber[0]) // size of output buffer
);
if(0 == nFormatRes)
{
dwRes = GetLastError();
CALL_FAIL (GENERAL_ERR, TEXT("GetNumberFormat"), dwRes);
return dwRes;
}
//
// get decimal separator
//
TCHAR tszDec[10];
nFormatRes = GetLocaleInfo(LOCALE_USER_DEFAULT, // locale identifier
LOCALE_SDECIMAL, // information type
tszDec, // information buffer
sizeof(tszDec) / sizeof(tszDec[0]) // size of buffer
);
if(0 == nFormatRes)
{
dwRes = GetLastError();
CALL_FAIL (GENERAL_ERR, TEXT("GetLocaleInfo"), dwRes);
return dwRes;
}
//
// cut the string on the decimal separator
//
TCHAR* pSeparator = _tcsstr(tszNumber, tszDec);
if(NULL != pSeparator)
{
*pSeparator = TEXT('\0');
}
try
{
TCHAR szFormat[64] = {0};
#ifdef UNICODE
if(theApp.IsRTLUI())
{
//
// Size field always should be LTR
// Add LEFT-TO-RIGHT OVERRIDE (LRO)
//
szFormat[0] = UNICODE_LRO;
}
#endif
_tcscat(szFormat, TEXT("%s KB"));
cstrValue.Format (szFormat, tszNumber);
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::Format"), dwRes);
return dwRes;
}
return dwRes;
} // FaxSizeFormat
DWORD
HtmlHelpTopic(
HWND hWnd,
TCHAR* tszHelpTopic
)
/*++
Routine name : HtmlHelpTopic
Routine description:
open HTML Help topic
Author:
Alexander Malysh (AlexMay), Mar, 2000
Arguments:
hWnd [in] - window handler
tszHelpTopic [in] - help topic
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("HtmlHelpTopic"), dwRes);
if(!tszHelpTopic)
{
ASSERTION_FAILURE;
return ERROR_INVALID_PARAMETER;
}
//
// get help file name
//
TCHAR tszHelpFile[2 * MAX_PATH] = {0};
_sntprintf(tszHelpFile,
ARR_SIZE(tszHelpFile) - 1,
TEXT("%s.%s%s"),
theApp.m_pszExeName, // application name (FxsClnt)
FAX_HTML_HELP_EXT, // help file extension (CHM)
tszHelpTopic); // help topic
SetLastError(0);
HtmlHelp(NULL, tszHelpFile, HH_DISPLAY_TOPIC, NULL);
dwRes = GetLastError();
if(ERROR_DLL_NOT_FOUND == dwRes ||
ERROR_MOD_NOT_FOUND == dwRes ||
ERROR_PROC_NOT_FOUND == dwRes)
{
AlignedAfxMessageBox(IDS_ERR_NO_HTML_HELP);
}
return dwRes;
}
DWORD
GetAppLoadPath(
CString& cstrLoadPath
)
/*++
Routine name : GetAppLoadPath
Routine description:
The directory from which the application loaded
Author:
Alexander Malysh (AlexMay), Feb, 2000
Arguments:
cstrLoadPath [out] - the directory
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("GetAppLoadPath"), dwRes);
TCHAR tszFullPath[MAX_PATH+1]={0};
DWORD dwGetRes = GetModuleFileName(NULL, tszFullPath, ARR_SIZE(tszFullPath)-1);
if(0 == dwGetRes)
{
dwRes = GetLastError();
CALL_FAIL (FILE_ERR, TEXT("GetModuleFileName"), dwRes);
return dwRes;
}
//
// cut file name
//
TCHAR* ptchFile = _tcsrchr(tszFullPath, TEXT('\\'));
ASSERTION(ptchFile);
ptchFile = _tcsinc(ptchFile);
*ptchFile = TEXT('\0');
try
{
cstrLoadPath = tszFullPath;
}
catch(...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("CString::operator="), dwRes);
return dwRes;
}
return dwRes;
} // GetAppLoadPath
DWORD
GetPrintersInfo(
PRINTER_INFO_2*& pPrinterInfo2,
DWORD& dwNumPrinters
)
/*++
Routine name : GetPrintersInfo
Routine description:
enumerate printers and get printers info
Author:
Alexander Malysh (AlexMay), Feb, 2000
Arguments:
pPrinterInfo2 [out] - printer info structure array
dwNumPrinters [out] - number of printers
Return Value:
Standard Win32 error code
--*/
{
DWORD dwRes = ERROR_SUCCESS;
DBG_ENTER(TEXT("GetPrintersInfo"), dwRes);
//
// First call, just collect required sizes
//
DWORD dwRequiredSize;
if (!EnumPrinters ( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL, // Local server
2, // Info level
NULL, // Initial buffer
0, // Initial buffer size
&dwRequiredSize,
&dwNumPrinters))
{
DWORD dwEnumRes = GetLastError ();
if (ERROR_INSUFFICIENT_BUFFER != dwEnumRes)
{
dwRes = dwEnumRes;
CALL_FAIL (RESOURCE_ERR, TEXT("EnumPrinters"), dwRes);
return dwRes;
}
}
//
// Allocate buffer for printers list
//
try
{
pPrinterInfo2 = (PRINTER_INFO_2 *) new BYTE[dwRequiredSize];
}
catch (...)
{
dwRes = ERROR_NOT_ENOUGH_MEMORY;
CALL_FAIL (MEM_ERR, TEXT("new BYTE[dwRequiredSize]"), dwRes);
return dwRes;
}
//
// 2nd call, get the printers list
//
if (!EnumPrinters ( PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
NULL, // Local server
2, // Info level
(LPBYTE)pPrinterInfo2, // Buffer
dwRequiredSize, // Buffer size
&dwRequiredSize,
&dwNumPrinters))
{
dwRes = GetLastError ();
CALL_FAIL (RESOURCE_ERR, TEXT("EnumPrinters"), dwRes);
SAFE_DELETE_ARRAY (pPrinterInfo2);
return dwRes;
}
if (!dwNumPrinters)
{
VERBOSE(DBG_MSG, TEXT("No printers in this machine"));
}
return dwRes;
} // GetPrintersInfo
UINT_PTR
CALLBACK
OFNHookProc(
HWND hdlg, // handle to child dialog box
UINT uiMsg, // message identifier
WPARAM wParam, // message parameter
LPARAM lParam // message parameter
)
/*++
Routine name : OFNHookProc
Routine description:
Callback function that is used with the
Explorer-style Open and Save As dialog boxes.
Refer MSDN for more info.
--*/
{
UINT_PTR nRes = 0;
if(WM_NOTIFY == uiMsg)
{
LPOFNOTIFY pOfNotify = (LPOFNOTIFY)lParam;
if(CDN_FILEOK == pOfNotify->hdr.code)
{
if(_tcslen(pOfNotify->lpOFN->lpstrFile) > (MAX_PATH-10))
{
AlignedAfxMessageBox(IDS_SAVE_AS_TOO_LONG, MB_OK | MB_ICONEXCLAMATION);
SetWindowLong(hdlg, DWLP_MSGRESULT, 1);
nRes = 1;
}
}
}
return nRes;
}
int
AlignedAfxMessageBox(
LPCTSTR lpszText,
UINT nType,
UINT nIDHelp
)
/*++
Routine name : AlignedAfxMessageBox
Routine description:
Display message box with correct reading order
Arguments:
AfxMessageBox() arguments
Return Value:
MessageBox() result
--*/
{
if(IsRTLUILanguage())
{
nType |= MB_RTLREADING | MB_RIGHT;
}
return AfxMessageBox(lpszText, nType, nIDHelp);
}
int
AlignedAfxMessageBox(
UINT nIDPrompt,
UINT nType,
UINT nIDHelp
)
/*++
Routine name : AlignedAfxMessageBox
Routine description:
Display message box with correct reading order
Arguments:
AfxMessageBox() arguments
Return Value:
MessageBox() result
--*/
{
if(IsRTLUILanguage())
{
nType |= MB_RTLREADING | MB_RIGHT;
}
return AfxMessageBox(nIDPrompt, nType, nIDHelp);
}
HINSTANCE
GetResourceHandle()
{
return GetResInst(FAX_CONSOLE_RESOURCE_DLL, NULL);
}