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
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);
|
|
}
|