4454 lines
116 KiB
C
4454 lines
116 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
wizard.c
|
||
|
||
Abstract:
|
||
|
||
Send fax wizard dialogs
|
||
|
||
Environment:
|
||
|
||
Fax driver user interface
|
||
|
||
Revision History:
|
||
|
||
01/19/96 -davidx-
|
||
Created it.
|
||
|
||
mm/dd/yy -author-
|
||
description
|
||
|
||
--*/
|
||
|
||
#include "faxui.h"
|
||
#include "tapiutil.h"
|
||
#include "prtcovpg.h"
|
||
#include "tiff.h"
|
||
#include "cwabutil.h"
|
||
#include <shellapi.h>
|
||
|
||
#include <imm.h>
|
||
|
||
#ifdef FAX_SCAN_ENABLED
|
||
|
||
#define TWRESMIN 0
|
||
#define TWRESMAX 1
|
||
#define TWRESSCAL 2
|
||
#define TWRESCUR 3
|
||
#define TWRESDEFAULT 4
|
||
#define TWRESCLOSEST 5
|
||
|
||
#define AUTOSCANPREV 0
|
||
#define AUTOSCANFINAL 1
|
||
#define CUSTOMSCAN 2
|
||
#define CANCELLED 3
|
||
#define FINALCANCELLED 4
|
||
#define AUTOSCANSHEETFED 5
|
||
#define CUSTOMDIGITALCAMERA 6
|
||
#define DCCANCELLED 7
|
||
|
||
#define Align(p, x) (((x) & ((p)-1)) ? (((x) & ~((p)-1)) + p) : (x))
|
||
|
||
#define WM_PAGE_COMPLETE (WM_USER+1000)
|
||
|
||
#define NUM_IFD_ENTRIES 18
|
||
|
||
#define IFD_SUBFILETYPE 0 // 254
|
||
#define IFD_IMAGEWIDTH 1 // 256
|
||
#define IFD_IMAGELENGTH 2 // 257
|
||
#define IFD_BITSPERSAMPLE 3 // 258
|
||
#define IFD_COMPRESSION 4 // 259
|
||
#define IFD_PHOTOMETRIC 5 // 262
|
||
#define IFD_FILLORDER 6 // 266
|
||
#define IFD_STRIPOFFSETS 7 // 273
|
||
#define IFD_SAMPLESPERPIXEL 8 // 277
|
||
#define IFD_ROWSPERSTRIP 9 // 278
|
||
#define IFD_STRIPBYTECOUNTS 10 // 279
|
||
#define IFD_XRESOLUTION 11 // 281
|
||
#define IFD_YRESOLUTION 12 // 282
|
||
#define IFD_GROUP3OPTIONS 13 // 292
|
||
#define IFD_RESOLUTIONUNIT 14 // 296
|
||
#define IFD_PAGENUMBER 15 // 297
|
||
#define IFD_SOFTWARE 16 // 305
|
||
#define IFD_CLEANFAXDATA 17 // 327
|
||
|
||
|
||
typedef struct {
|
||
WORD wIFDEntries;
|
||
TIFF_TAG ifd[NUM_IFD_ENTRIES];
|
||
DWORD nextIFDOffset;
|
||
DWORD filler;
|
||
DWORD xresNum;
|
||
DWORD xresDenom;
|
||
DWORD yresNum;
|
||
DWORD yresDenom;
|
||
CHAR software[32];
|
||
} FAXIFD, *PFAXIFD;
|
||
|
||
|
||
#define SoftwareStr "Windows NT Fax Driver"
|
||
#define DRIVER_SIGNATURE 'xafD'
|
||
|
||
FAXIFD FaxIFDTemplate = {
|
||
|
||
NUM_IFD_ENTRIES,
|
||
|
||
{
|
||
{ TIFFTAG_SUBFILETYPE, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_IMAGEWIDTH, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_IMAGELENGTH, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_BITSPERSAMPLE, TIFF_SHORT, 1, 1 },
|
||
{ TIFFTAG_COMPRESSION, TIFF_SHORT, 1, COMPRESSION_NONE },
|
||
{ TIFFTAG_PHOTOMETRIC, TIFF_SHORT, 1, PHOTOMETRIC_MINISWHITE },
|
||
{ TIFFTAG_FILLORDER, TIFF_SHORT, 1, FILLORDER_MSB2LSB },
|
||
{ TIFFTAG_STRIPOFFSETS, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_SAMPLESPERPIXEL, TIFF_SHORT, 1, 1 },
|
||
{ TIFFTAG_ROWSPERSTRIP, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_XRESOLUTION, TIFF_RATIONAL, 1, 0 },
|
||
{ TIFFTAG_YRESOLUTION, TIFF_RATIONAL, 1, 0 },
|
||
{ TIFFTAG_GROUP3OPTIONS, TIFF_LONG, 1, 0 },
|
||
{ TIFFTAG_RESOLUTIONUNIT, TIFF_SHORT, 1, RESUNIT_INCH },
|
||
{ TIFFTAG_PAGENUMBER, TIFF_SHORT, 2, 0 },
|
||
{ TIFFTAG_SOFTWARE, TIFF_ASCII, sizeof(SoftwareStr)+1, 0 },
|
||
{ TIFFTAG_CLEANFAXDATA, TIFF_SHORT, 1, 0 },
|
||
},
|
||
|
||
0,
|
||
DRIVER_SIGNATURE,
|
||
0,
|
||
1,
|
||
0,
|
||
1,
|
||
SoftwareStr
|
||
};
|
||
|
||
#endif
|
||
|
||
|
||
|
||
VOID
|
||
FillInPropertyPage(
|
||
PROPSHEETPAGE *psp,
|
||
INT dlgId,
|
||
DLGPROC dlgProc,
|
||
PUSERMEM pUserMem,
|
||
INT TitleId,
|
||
INT SubTitleId
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Fill out a PROPSHEETPAGE structure with the supplied parameters
|
||
|
||
Arguments:
|
||
|
||
psp - Points to the PROPSHEETPAGE structure to be filled out
|
||
dlgId - Dialog template resource ID
|
||
dlgProc - Dialog procedure
|
||
pUserMem - Pointer to the user mode memory structure
|
||
TitleId - resource id for wizard subtitle
|
||
SubTitleId - resource id for wizard subtitle
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
LPTSTR WizardTitle;
|
||
LPTSTR WizardSubTitle;
|
||
|
||
|
||
psp->dwSize = sizeof(PROPSHEETPAGE);
|
||
//
|
||
// Don't show titles if it's the first or last page
|
||
//
|
||
if (TitleId==0 && SubTitleId ==0) {
|
||
psp->dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;;
|
||
} else {
|
||
psp->dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
|
||
}
|
||
psp->hInstance = ghInstance;
|
||
psp->pszTemplate = MAKEINTRESOURCE(dlgId);
|
||
psp->pfnDlgProc = dlgProc;
|
||
psp->lParam = (LPARAM) pUserMem;
|
||
|
||
WizardTitle = MemAlloc(200* sizeof(TCHAR) );
|
||
WizardSubTitle = MemAlloc(200* sizeof(TCHAR) );
|
||
LoadString(ghInstance,TitleId,WizardTitle,200);
|
||
LoadString(ghInstance,SubTitleId,WizardSubTitle,200);
|
||
|
||
psp->pszHeaderTitle = WizardTitle;
|
||
psp->pszHeaderSubTitle = WizardSubTitle;
|
||
}
|
||
|
||
|
||
|
||
LPTSTR
|
||
GetTextStringValue(
|
||
HWND hwnd
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve the string value in a text field
|
||
|
||
Arguments:
|
||
|
||
hwnd - Handle to a text window
|
||
|
||
Return Value:
|
||
|
||
Pointer to a string representing the current content of the text field
|
||
NULL if the text field is empty or if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
INT length;
|
||
LPTSTR pString;
|
||
|
||
//
|
||
// Find out how many characters are in the text field
|
||
// and allocate enough memory to hold the string value
|
||
//
|
||
|
||
if ((length = GetWindowTextLength(hwnd)) == 0 ||
|
||
(pString = MemAlloc(sizeof(TCHAR) * (length + 1))) == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Actually retrieve the string value
|
||
//
|
||
|
||
if (GetWindowText(hwnd, pString, length + 1) == 0) {
|
||
|
||
MemFree(pString);
|
||
return NULL;
|
||
}
|
||
|
||
return pString;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
LimitTextFields(
|
||
HWND hDlg,
|
||
INT *pLimitInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Limit the maximum length for a number of text fields
|
||
|
||
Arguments:
|
||
|
||
hDlg - Specifies the handle to the dialog window
|
||
pLimitInfo - Array of text field control IDs and their maximum length
|
||
ID for the 1st text field, maximum length for the 1st text field
|
||
ID for the 2nd text field, maximum length for the 2nd text field
|
||
...
|
||
0
|
||
Note: The maximum length counts the NUL-terminator.
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
while (*pLimitInfo != 0) {
|
||
|
||
SendDlgItemMessage(hDlg, pLimitInfo[0], EM_SETLIMITTEXT, pLimitInfo[1]-1, 0);
|
||
pLimitInfo += 2;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
SaveLastRecipientInfo(
|
||
LPTSTR pName,
|
||
LPTSTR pAreaCode,
|
||
LPTSTR pPhoneNumber,
|
||
DWORD countryId,
|
||
BOOL useDialingRules
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Save the information about the last recipient in the registry
|
||
|
||
Arguments:
|
||
|
||
pName - Specifies the recipient name
|
||
pAreaCode - Specifies the recipient area code
|
||
pPhoneNumber - Specifies the recipient phone number
|
||
countryId - Specifies the recipient country ID
|
||
useDialingRules - Whether use dialing rules is checked
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hRegKey;
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READWRITE)) {
|
||
|
||
SetRegistryString(hRegKey, REGVAL_LAST_RECNAME, pName);
|
||
SetRegistryString(hRegKey, REGVAL_LAST_RECNUMBER, pPhoneNumber);
|
||
SetRegistryDword(hRegKey, REGVAL_USE_DIALING_RULES, useDialingRules);
|
||
|
||
if (useDialingRules) {
|
||
SetRegistryString(hRegKey, REGVAL_LAST_RECAREACODE, pAreaCode);
|
||
SetRegistryDword(hRegKey, REGVAL_LAST_COUNTRYID, countryId);
|
||
}
|
||
RegCloseKey(hRegKey);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
RestoreLastRecipientInfo(
|
||
HWND hDlg,
|
||
PDWORD pCountryId
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Restore the information about the last recipient from the registry
|
||
|
||
Arguments:
|
||
|
||
hDlg - Specifies a handle to the fax recipient wizard page
|
||
pCountryId - Returns the last selected country ID
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
HKEY hRegKey;
|
||
LPTSTR buffer;
|
||
//TCHAR buffer[MAX_STRING_LEN];
|
||
|
||
*pCountryId = GetDefaultCountryID();
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READONLY)) {
|
||
|
||
buffer = GetRegistryString(hRegKey, REGVAL_LAST_RECNAME, TEXT(""));
|
||
if (buffer) {
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_NAME_EDIT, buffer);
|
||
MemFree(buffer);
|
||
}
|
||
|
||
buffer = GetRegistryString(hRegKey, REGVAL_LAST_RECAREACODE, TEXT(""));
|
||
if (buffer) {
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_AREA_CODE_EDIT, buffer);
|
||
MemFree(buffer);
|
||
}
|
||
|
||
buffer = GetRegistryString(hRegKey, REGVAL_LAST_RECNUMBER, TEXT(""));
|
||
if (buffer) {
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_NUMBER_EDIT, buffer);
|
||
MemFree(buffer);
|
||
}
|
||
|
||
CheckDlgButton(hDlg,
|
||
IDC_USE_DIALING_RULES,
|
||
GetRegistryDword(hRegKey, REGVAL_USE_DIALING_RULES));
|
||
|
||
*pCountryId = GetRegistryDword(hRegKey, REGVAL_LAST_COUNTRYID);
|
||
|
||
RegCloseKey(hRegKey);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
PUSERMEM
|
||
CommonWizardProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam,
|
||
DWORD buttonFlags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Common procedure for handling wizard pages:
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
buttonFlags - Indicate which buttons should be enabled
|
||
|
||
Return Value:
|
||
|
||
NULL - Message is processed and the dialog procedure should return FALSE
|
||
Otherwise - Message is not completely processed and
|
||
The return value is a pointer to the user mode memory structure
|
||
|
||
--*/
|
||
|
||
{
|
||
PUSERMEM pUserMem;
|
||
|
||
switch (message) {
|
||
|
||
case WM_INITDIALOG:
|
||
|
||
//
|
||
// Store the pointer to user mode memory structure
|
||
//
|
||
|
||
lParam = ((PROPSHEETPAGE *) lParam)->lParam;
|
||
pUserMem = (PUSERMEM) lParam;
|
||
Assert(ValidPDEVUserMem(pUserMem));
|
||
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
|
||
break;
|
||
|
||
case WM_NOTIFY:
|
||
|
||
pUserMem = (PUSERMEM) GetWindowLongPtr(hDlg, DWLP_USER);
|
||
Assert(ValidPDEVUserMem(pUserMem));
|
||
|
||
switch (((NMHDR *) lParam)->code) {
|
||
|
||
case PSN_WIZFINISH:
|
||
|
||
pUserMem->finishPressed = TRUE;
|
||
break;
|
||
|
||
case PSN_SETACTIVE:
|
||
|
||
PropSheet_SetWizButtons(GetParent(hDlg), buttonFlags);
|
||
break;
|
||
|
||
case PSN_RESET:
|
||
case PSN_WIZBACK:
|
||
case PSN_WIZNEXT:
|
||
case PSN_KILLACTIVE:
|
||
case LVN_KEYDOWN:
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
return NULL;
|
||
}
|
||
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
|
||
pUserMem = (PUSERMEM) GetWindowLongPtr(hDlg, DWLP_USER);
|
||
Assert(ValidPDEVUserMem(pUserMem));
|
||
break;
|
||
|
||
default:
|
||
|
||
return NULL;
|
||
}
|
||
|
||
return pUserMem;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* IsStringACSII
|
||
*
|
||
* Purpose:
|
||
* This function determines whether a string contains ONLY ASCII characters.
|
||
*
|
||
* Arguments:
|
||
* ptszString - points to the string to test.
|
||
*
|
||
* Returns:
|
||
* TRUE - indicates that the string contains only ASCII characters.
|
||
*
|
||
*/
|
||
|
||
BOOL IsStringASCII( LPTSTR ptszString )
|
||
{
|
||
BOOL fReturnValue = (BOOL) TRUE;
|
||
|
||
// Determine whether the contents of the edit control are legal.
|
||
|
||
while ( (*ptszString != (TCHAR) TEXT('\0')) &&
|
||
( fReturnValue == (BOOL) TRUE) )
|
||
{
|
||
if ( (*ptszString < (TCHAR) 0x0020) || (*ptszString > (TCHAR) MAXCHAR) )
|
||
{
|
||
// The string contains at least one non-ASCII character.
|
||
|
||
fReturnValue = (BOOL) FALSE;
|
||
}
|
||
|
||
ptszString = _tcsinc( ptszString );
|
||
} // end of while loop
|
||
|
||
return ( fReturnValue );
|
||
}
|
||
|
||
|
||
|
||
INT
|
||
GetCurrentRecipient(
|
||
HWND hDlg,
|
||
PRECIPIENT *ppRecipient
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Extract the current recipient information in the dialog
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to the fax recipient wizard page
|
||
ppRecipient - Buffer to receive a pointer to a newly created RECIPIENT structure
|
||
NULL if caller is only interested in the validity of recipient info
|
||
|
||
Return Value:
|
||
|
||
= 0 if successful
|
||
> 0 error message string resource ID otherwise
|
||
< 0 other error conditions
|
||
|
||
--*/
|
||
|
||
{
|
||
LPLINECOUNTRYENTRY pLineCountryEntry;
|
||
DWORD countryId, countryCode;
|
||
PRECIPIENT pRecipient;
|
||
TCHAR areaCode[MAX_RECIPIENT_NUMBER];
|
||
TCHAR phoneNumber[MAX_RECIPIENT_NUMBER];
|
||
INT nameLen, areaCodeLen, numberLen;
|
||
LPTSTR pName, pAddress;
|
||
INT useDialingRules;
|
||
|
||
//
|
||
// Default value in case of error
|
||
//
|
||
|
||
if (ppRecipient)
|
||
*ppRecipient = NULL;
|
||
|
||
//
|
||
// Find the current country code
|
||
//
|
||
|
||
countryCode = 0;
|
||
pLineCountryEntry = NULL;
|
||
countryId = GetCountryListBoxSel(GetDlgItem(hDlg, IDC_CHOOSE_COUNTRY_COMBO));
|
||
useDialingRules = IsDlgButtonChecked(hDlg, IDC_USE_DIALING_RULES);
|
||
|
||
if ((useDialingRules == BST_CHECKED) &&
|
||
(pLineCountryEntry = FindCountry(countryId)))
|
||
{
|
||
countryCode = pLineCountryEntry->dwCountryCode;
|
||
}
|
||
|
||
nameLen = GetWindowTextLength(GetDlgItem(hDlg, IDC_CHOOSE_NAME_EDIT));
|
||
areaCodeLen = GetWindowTextLength(GetDlgItem(hDlg, IDC_CHOOSE_AREA_CODE_EDIT));
|
||
numberLen = GetWindowTextLength(GetDlgItem(hDlg, IDC_CHOOSE_NUMBER_EDIT));
|
||
|
||
//
|
||
// Validate the edit text fields
|
||
//
|
||
|
||
if (nameLen <= 0)
|
||
return IDS_BAD_RECIPIENT_NAME;
|
||
|
||
if (numberLen <= 0 || numberLen >= MAX_RECIPIENT_NUMBER)
|
||
return IDS_BAD_RECIPIENT_NUMBER;
|
||
|
||
if ((areaCodeLen <= 0 && AreaCodeRules(pLineCountryEntry) == AREACODE_REQUIRED) ||
|
||
(areaCodeLen >= MAX_RECIPIENT_NUMBER))
|
||
{
|
||
return IDS_BAD_RECIPIENT_AREACODE;
|
||
}
|
||
|
||
if (ppRecipient == NULL)
|
||
return 0;
|
||
|
||
//
|
||
// Calculate the amount of memory space we need and allocate it
|
||
//
|
||
|
||
pRecipient = MemAllocZ(sizeof(RECIPIENT));
|
||
pName = MemAllocZ((nameLen + 1) * sizeof(TCHAR));
|
||
pAddress = MemAllocZ((areaCodeLen + numberLen + 20) * sizeof(TCHAR));
|
||
|
||
if (!pRecipient || !pName || !pAddress) {
|
||
|
||
MemFree(pRecipient);
|
||
MemFree(pName);
|
||
MemFree(pAddress);
|
||
return -1;
|
||
}
|
||
|
||
*ppRecipient = pRecipient;
|
||
pRecipient->pName = pName;
|
||
pRecipient->pAddress = pAddress;
|
||
|
||
//
|
||
// Get the recipient's name
|
||
//
|
||
|
||
GetWindowText(GetDlgItem(hDlg, IDC_CHOOSE_NAME_EDIT), pName, nameLen+1);
|
||
|
||
//
|
||
// Get the recipient's number
|
||
// AddressType
|
||
// [+ CountryCode Space]
|
||
// [( AreaCode ) Space]
|
||
// SubscriberNumber
|
||
//
|
||
|
||
GetWindowText(GetDlgItem(hDlg, IDC_CHOOSE_AREA_CODE_EDIT), areaCode, MAX_RECIPIENT_NUMBER);
|
||
|
||
if ( IsStringASCII( areaCode ) == (BOOL) FALSE )
|
||
{
|
||
return ( (INT) IDS_ERROR_AREA_CODE );
|
||
}
|
||
|
||
GetWindowText(GetDlgItem(hDlg, IDC_CHOOSE_NUMBER_EDIT), phoneNumber, MAX_RECIPIENT_NUMBER);
|
||
|
||
if ( IsStringASCII( phoneNumber ) == (BOOL) FALSE )
|
||
{
|
||
return ( (INT) IDS_ERROR_FAX_NUMBER );
|
||
}
|
||
|
||
AssemblePhoneNumber(pAddress,
|
||
countryCode,
|
||
areaCode,
|
||
phoneNumber);
|
||
|
||
//
|
||
// Save the information about the last recipient as a convenience
|
||
//
|
||
|
||
SaveLastRecipientInfo(pName,
|
||
areaCode,
|
||
phoneNumber,
|
||
countryId,
|
||
useDialingRules == BST_CHECKED);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
InitRecipientListView(
|
||
HWND hwndLV
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize the recipient list view on the first page of Send Fax wizard
|
||
|
||
Arguments:
|
||
|
||
hwndLV - Window handle to the list view control
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
LV_COLUMN lvc;
|
||
RECT rect;
|
||
TCHAR buffer[MAX_TITLE_LEN];
|
||
|
||
if (hwndLV == NULL)
|
||
return;
|
||
|
||
GetClientRect(hwndLV, &rect);
|
||
|
||
ZeroMemory(&lvc, sizeof(lvc));
|
||
|
||
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
||
lvc.fmt = LVCFMT_LEFT;
|
||
lvc.pszText = buffer;
|
||
lvc.cx = (rect.right - rect.left) / 2;
|
||
|
||
lvc.iSubItem = 0;
|
||
LoadString(ghInstance, IDS_COLUMN_RECIPIENT_NAME, buffer, MAX_TITLE_LEN);
|
||
|
||
if (ListView_InsertColumn(hwndLV, 0, &lvc) == -1)
|
||
Error(("ListView_InsertColumn failed\n"));
|
||
|
||
lvc.cx -= GetSystemMetrics(SM_CXVSCROLL);
|
||
lvc.iSubItem = 1;
|
||
LoadString(ghInstance, IDS_COLUMN_RECIPIENT_NUMBER, buffer, MAX_TITLE_LEN);
|
||
|
||
if (ListView_InsertColumn(hwndLV, 1, &lvc) == -1)
|
||
Error(("ListView_InsertColumn failed\n"));
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
InsertRecipientListItem(
|
||
HWND hwndLV,
|
||
PRECIPIENT pRecipient
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Insert an item into the recipient list view
|
||
|
||
Arguments:
|
||
|
||
hwndLV - Window handle to the recipient list view
|
||
pRecipient - Specifies the recipient to be inserted
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
LV_ITEM lvi;
|
||
INT index;
|
||
|
||
ZeroMemory(&lvi, sizeof(lvi));
|
||
|
||
lvi.mask = LVIF_PARAM | LVIF_TEXT | LVIF_STATE;
|
||
lvi.lParam = (LPARAM) pRecipient;
|
||
lvi.pszText = pRecipient->pName;
|
||
lvi.state = lvi.stateMask = LVIS_SELECTED;
|
||
|
||
if ((index = ListView_InsertItem(hwndLV, &lvi)) == -1) {
|
||
|
||
Error(("ListView_InsertItem failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
lvi.mask = LVIF_TEXT;
|
||
lvi.iItem = index;
|
||
lvi.iSubItem = 1;
|
||
lvi.pszText = pRecipient->pAddress;
|
||
|
||
if (! ListView_SetItem(hwndLV, &lvi))
|
||
Error(("ListView_SetItem failed\n"));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
PRECIPIENT
|
||
GetRecipientListItem(
|
||
HWND hwndLV,
|
||
INT index
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Retrieve the recipient associated with an item in the list view
|
||
|
||
Arguments:
|
||
|
||
hwndLV - Window handle to the recipient list view
|
||
index - Specifies the index of the interested item
|
||
|
||
Return Value:
|
||
|
||
Pointer to the requested recipient information
|
||
NULL if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
LV_ITEM lvi;
|
||
|
||
ZeroMemory(&lvi, sizeof(lvi));
|
||
lvi.mask = LVIF_PARAM;
|
||
lvi.iItem = index;
|
||
|
||
if (ListView_GetItem(hwndLV, &lvi))
|
||
return (PRECIPIENT) lvi.lParam;
|
||
|
||
Error(("ListView_GetItem failed\n"));
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
INT
|
||
AddRecipient(
|
||
HWND hDlg,
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Add the current recipient information entered by the user
|
||
into the recipient list
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to the fax recipient wizard page
|
||
pUserMem - Points to user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
Same meaning as return value from GetCurrentRecipient, i.e.
|
||
= 0 if successful
|
||
> 0 error message string resource ID otherwise
|
||
< 0 other error conditions
|
||
|
||
--*/
|
||
|
||
{
|
||
PRECIPIENT pRecipient;
|
||
INT errId;
|
||
HWND hwndLV;
|
||
|
||
//
|
||
// Collect information about the current recipient
|
||
//
|
||
|
||
if ((errId = GetCurrentRecipient(hDlg, &pRecipient)) != 0)
|
||
return errId;
|
||
|
||
//
|
||
// Insert the current recipient to the recipient list
|
||
//
|
||
|
||
if ((hwndLV = GetDlgItem(hDlg, IDC_CHOOSE_RECIPIENT_LIST)) &&
|
||
InsertRecipientListItem(hwndLV, pRecipient))
|
||
{
|
||
errId = 0;
|
||
pRecipient->pNext = pUserMem->pRecipients;
|
||
pUserMem->pRecipients = pRecipient;
|
||
|
||
//
|
||
// Clear the name and number fields after successfully
|
||
// adding the recipient to the internal list
|
||
//
|
||
|
||
SetWindowText(GetDlgItem(hDlg, IDC_CHOOSE_NAME_EDIT), TEXT(""));
|
||
SetWindowText(GetDlgItem(hDlg, IDC_CHOOSE_AREA_CODE_EDIT), TEXT(""));
|
||
SetWindowText(GetDlgItem(hDlg, IDC_CHOOSE_NUMBER_EDIT), TEXT(""));
|
||
|
||
//CheckDlgButton(hDlg, IDC_USE_DIALING_RULES, FALSE);
|
||
|
||
} else {
|
||
|
||
FreeRecipient(pRecipient);
|
||
errId = -1;
|
||
}
|
||
|
||
return errId;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
DoAddressBook(
|
||
HWND hDlg,
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Display the MAPI address book dialog
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to the fax recipient wizard page
|
||
pUserMem - Points to user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
HWND hwndLV;
|
||
BOOL result;
|
||
PRECIPIENT pNewRecip = NULL;
|
||
PRECIPIENT tmpRecip;
|
||
|
||
if (! pUserMem->lpWabInit &&
|
||
! (pUserMem->lpWabInit = InitializeWAB(ghInstance)))
|
||
{
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_ADDRBOOK), FALSE);
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Get a handle to the recipient list window
|
||
//
|
||
|
||
if (! (hwndLV = GetDlgItem(hDlg, IDC_CHOOSE_RECIPIENT_LIST)))
|
||
return FALSE;
|
||
|
||
//
|
||
// Add current recipient to the list if necessary
|
||
//
|
||
|
||
AddRecipient(hDlg, pUserMem);
|
||
|
||
result = CallWabAddress(
|
||
hDlg,
|
||
pUserMem,
|
||
&pNewRecip
|
||
);
|
||
|
||
FreeRecipientList(pUserMem);
|
||
|
||
pUserMem->pRecipients = pNewRecip;
|
||
|
||
ListView_DeleteAllItems(hwndLV);
|
||
|
||
for (tmpRecip = pNewRecip; tmpRecip; tmpRecip = tmpRecip->pNext) {
|
||
InsertRecipientListItem(hwndLV, tmpRecip);
|
||
}
|
||
|
||
if (!result) {
|
||
DisplayMessageDialog( hDlg, MB_OK, 0, IDS_BAD_ADDRESS_TYPE );
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
ValidateRecipients(
|
||
HWND hDlg,
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Validate the list of fax recipients entered by the user
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to the fax recipient wizard page
|
||
pUserMem - Points to user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
INT errId;
|
||
|
||
//
|
||
// Add current recipient to the list if necessary
|
||
//
|
||
|
||
errId = AddRecipient(hDlg, pUserMem);
|
||
|
||
//
|
||
// There must be at least one recipient
|
||
//
|
||
|
||
if (pUserMem->pRecipients)
|
||
return TRUE;
|
||
|
||
//
|
||
// Display an error message
|
||
//
|
||
|
||
if (errId > 0)
|
||
DisplayMessageDialog(hDlg, 0, 0, errId);
|
||
else
|
||
MessageBeep(MB_OK);
|
||
|
||
//
|
||
// Set current focus to the appropriate text field as a convenience
|
||
//
|
||
|
||
switch (errId) {
|
||
|
||
case IDS_ERROR_FAX_NUMBER:
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_NUMBER_EDIT, L"");
|
||
case IDS_BAD_RECIPIENT_NUMBER:
|
||
|
||
errId = IDC_CHOOSE_NUMBER_EDIT;
|
||
break;
|
||
|
||
case IDS_ERROR_AREA_CODE:
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_AREA_CODE_EDIT, L"");
|
||
case IDS_BAD_RECIPIENT_AREACODE:
|
||
|
||
errId = IDC_CHOOSE_AREA_CODE_EDIT;
|
||
break;
|
||
|
||
case IDS_BAD_RECIPIENT_NAME:
|
||
default:
|
||
|
||
errId = IDC_CHOOSE_NAME_EDIT;
|
||
break;
|
||
}
|
||
|
||
SetFocus(GetDlgItem(hDlg, errId));
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
PRECIPIENT *
|
||
FindRecipient(
|
||
PUSERMEM pUserMem,
|
||
PRECIPIENT pRecipient
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Check if the specified recipient is in the list of recipients
|
||
|
||
Arguments:
|
||
|
||
pUserMem - Points to user mode memory structure
|
||
pRecipient - Specifies the recipient to be found
|
||
|
||
Return Value:
|
||
|
||
Address of the link pointer to the specified recipient
|
||
NULL if the specified recipient is not found
|
||
|
||
--*/
|
||
|
||
{
|
||
PRECIPIENT pCurrent, *ppPrevNext;
|
||
|
||
//
|
||
// Search for the specified recipient in the list
|
||
//
|
||
|
||
ppPrevNext = (PRECIPIENT *) &pUserMem->pRecipients;
|
||
pCurrent = pUserMem->pRecipients;
|
||
|
||
while (pCurrent && pCurrent != pRecipient) {
|
||
|
||
ppPrevNext = (PRECIPIENT *) &pCurrent->pNext;
|
||
pCurrent = pCurrent->pNext;
|
||
}
|
||
|
||
//
|
||
// Return the address of the link pointer to the specified recipient
|
||
// or NULL if the specified recipient is not found
|
||
//
|
||
|
||
return pCurrent ? ppPrevNext : NULL;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
RemoveRecipient(
|
||
HWND hDlg,
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Remove the currently selected recipient from the recipient list
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to the fax recipient wizard page
|
||
pUserMem - Points to user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
PRECIPIENT pRecipient, *ppPrevNext;
|
||
INT selIndex;
|
||
HWND hwndLV;
|
||
|
||
//
|
||
// Get the currently selected recipient, and
|
||
// Find the current recipient in the list, then
|
||
// Delete the current recipient and select the next one below it
|
||
//
|
||
|
||
if ((hwndLV = GetDlgItem(hDlg, IDC_CHOOSE_RECIPIENT_LIST)) &&
|
||
(selIndex = ListView_GetNextItem(hwndLV, -1, LVNI_ALL|LVNI_SELECTED)) != -1 &&
|
||
(pRecipient = GetRecipientListItem(hwndLV, selIndex)) &&
|
||
(ppPrevNext = FindRecipient(pUserMem, pRecipient)) &&
|
||
ListView_DeleteItem(hwndLV, selIndex))
|
||
{
|
||
ListView_SetItemState(hwndLV,
|
||
selIndex,
|
||
LVIS_SELECTED|LVIS_FOCUSED,
|
||
LVIS_SELECTED|LVIS_FOCUSED);
|
||
|
||
//
|
||
// Delete the recipient from the internal list
|
||
//
|
||
|
||
*ppPrevNext = pRecipient->pNext;
|
||
FreeRecipient(pRecipient);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
MessageBeep(MB_ICONHAND);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
LocationListInit(
|
||
HWND hDlg,
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize the list of TAPI locations
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to "Compose New Fax" wizard window
|
||
pUserMem - Pointer to user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
HWND hwndList;
|
||
DWORD index;
|
||
LRESULT listIdx;
|
||
LPTSTR pLocationName, pSelectedName = NULL;
|
||
LPLINETRANSLATECAPS pTranslateCaps = NULL;
|
||
LPLINELOCATIONENTRY pLocationEntry;
|
||
|
||
//
|
||
// For remote printers, hide the location combo-box
|
||
//
|
||
|
||
if (! pUserMem->isLocalPrinter) {
|
||
|
||
ShowWindow(GetDlgItem(hDlg, IDC_LOCATION_PROMPT), SW_HIDE);
|
||
ShowWindow(GetDlgItem(hDlg, IDC_LOCATION_LIST), SW_HIDE);
|
||
ShowWindow(GetDlgItem(hDlg, IDC_TAPI_PROPS), SW_HIDE);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Get the list of locations from TAPI and use it
|
||
// to initialize the location combo-box.
|
||
//
|
||
|
||
if ((hwndList = GetDlgItem(hDlg, IDC_LOCATION_LIST)) &&
|
||
(pTranslateCaps = GetTapiLocationInfo(hDlg)))
|
||
{
|
||
SendMessage(hwndList, CB_RESETCONTENT, 0, 0);
|
||
|
||
pLocationEntry = (LPLINELOCATIONENTRY)
|
||
((PBYTE) pTranslateCaps + pTranslateCaps->dwLocationListOffset);
|
||
|
||
for (index=0; index < pTranslateCaps->dwNumLocations; index++) {
|
||
|
||
pLocationName = (LPTSTR)
|
||
((PBYTE) pTranslateCaps + pLocationEntry->dwLocationNameOffset);
|
||
|
||
if (pLocationEntry->dwPermanentLocationID == pTranslateCaps->dwCurrentLocationID)
|
||
pSelectedName = pLocationName;
|
||
|
||
listIdx = SendMessage(hwndList, CB_INSERTSTRING, 0, (LPARAM) pLocationName);
|
||
|
||
if (listIdx != CB_ERR) {
|
||
|
||
SendMessage(hwndList,
|
||
CB_SETITEMDATA,
|
||
listIdx,
|
||
pLocationEntry->dwPermanentLocationID);
|
||
}
|
||
|
||
pLocationEntry++;
|
||
}
|
||
|
||
if (pSelectedName != NULL)
|
||
SendMessage(hwndList, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) pSelectedName);
|
||
}
|
||
|
||
MemFree(pTranslateCaps);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
LocationListSelChange(
|
||
HWND hDlg
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Change the default TAPI location
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to "Compose New Fax" wizard window
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
HWND hwndList;
|
||
LRESULT selIndex;
|
||
DWORD locationID;
|
||
|
||
if ((hwndList = GetDlgItem(hDlg, IDC_LOCATION_LIST)) &&
|
||
(selIndex = SendMessage(hwndList, CB_GETCURSEL, 0, 0)) != CB_ERR &&
|
||
(locationID = (DWORD)SendMessage(hwndList, CB_GETITEMDATA, selIndex, 0)) != CB_ERR)
|
||
{
|
||
SetCurrentLocation(locationID);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
UpdateCountryCombobox(
|
||
HWND hDlg,
|
||
DWORD countryId
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Update the country/region combobox
|
||
|
||
Arguments:
|
||
|
||
hDlg - Handle to recipient wizard page
|
||
countryId - country id
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
HWND hwndUseDialingRultes = GetDlgItem(hDlg, IDC_USE_DIALING_RULES);
|
||
HWND hwndDialingLocation = GetDlgItem(hDlg, IDC_LOCATION_LIST);
|
||
HWND hwndDialingLocationStatic = GetDlgItem(hDlg, IDC_LOCATION_PROMPT);
|
||
HWND hwndLocation = GetDlgItem(hDlg, IDC_CHOOSE_COUNTRY_COMBO);
|
||
HWND hwndLocationStatic = GetDlgItem(hDlg, IDC_STATIC_CHOOSE_COUNTRY_COMBO);
|
||
HWND hwndProp = GetDlgItem(hDlg, IDC_TAPI_PROPS);
|
||
static int OldCountryCode = 0;
|
||
|
||
if (IsDlgButtonChecked(hDlg, IDC_USE_DIALING_RULES) != BST_CHECKED) {
|
||
//
|
||
// user unchecked use dialing rules
|
||
// remember the old country code and area code and clear out the UI
|
||
//
|
||
OldCountryCode = GetCountryListBoxSel(hwndLocation);
|
||
if (OldCountryCode == -1) {
|
||
OldCountryCode = countryId != -1 ? countryId : 0;
|
||
}
|
||
SendMessage(hwndLocation, CB_RESETCONTENT, FALSE, 0);
|
||
EnableWindow(hwndLocation, FALSE);
|
||
EnableWindow(hwndLocationStatic, FALSE);
|
||
EnableWindow(hwndDialingLocation, FALSE);
|
||
EnableWindow(hwndDialingLocationStatic, FALSE);
|
||
EnableWindow(hwndProp, FALSE);
|
||
}
|
||
else {
|
||
//
|
||
// user checked use dialing rules
|
||
// enable country combo, restore settings
|
||
//
|
||
EnableWindow(hwndLocation, TRUE);
|
||
EnableWindow(hwndLocationStatic, TRUE);
|
||
InitCountryListBox(GetDlgItem(hDlg, IDC_CHOOSE_COUNTRY_COMBO),
|
||
GetDlgItem(hDlg, IDC_CHOOSE_AREA_CODE_EDIT),
|
||
countryId != -1 ? countryId : OldCountryCode);
|
||
EnableWindow(hwndDialingLocation, TRUE);
|
||
EnableWindow(hwndDialingLocationStatic, TRUE);
|
||
EnableWindow(hwndProp, TRUE);
|
||
}
|
||
|
||
SelChangeCountryListBox(GetDlgItem(hDlg, IDC_CHOOSE_COUNTRY_COMBO),
|
||
GetDlgItem(hDlg, IDC_CHOOSE_AREA_CODE_EDIT));
|
||
}
|
||
|
||
INT_PTR
|
||
CALLBACK
|
||
firstdlgproc(
|
||
HWND hDlg,
|
||
UINT iMsg,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
{
|
||
switch(iMsg) {
|
||
case WM_INITDIALOG:
|
||
CheckDlgButton(hDlg, IDC_EDIT_USERINFO_NOW, TRUE);
|
||
return TRUE;
|
||
|
||
case WM_COMMAND:
|
||
switch(LOWORD( wParam )) {
|
||
case IDOK:
|
||
if (IsDlgButtonChecked(hDlg, IDC_EDIT_USERINFO_NOW) == BST_CHECKED) {
|
||
EndDialog( hDlg, IDYES );
|
||
}
|
||
else {
|
||
EndDialog( hDlg, IDNO );
|
||
}
|
||
return TRUE;
|
||
}
|
||
break;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
INT_PTR
|
||
CALLBACK
|
||
firstprintdlgproc(
|
||
HWND hDlg,
|
||
UINT iMsg,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
{
|
||
switch(iMsg) {
|
||
|
||
case WM_COMMAND:
|
||
EndDialog( hDlg, LOWORD( wParam ));
|
||
break;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
DoFirstTimeInitStuff(
|
||
HWND hDlg,
|
||
BOOL bWelcomePage
|
||
)
|
||
{
|
||
BOOL bInitialized = TRUE;
|
||
HKEY hRegKey;
|
||
// TCHAR MessageBuffer[1024],TitleBuffer[100];
|
||
SHELLEXECUTEINFO shellExeInfo = {
|
||
sizeof(SHELLEXECUTEINFO),
|
||
SEE_MASK_NOCLOSEPROCESS,
|
||
hDlg,
|
||
L"Open",
|
||
L"rundll32",
|
||
L"shell32.dll,Control_RunDLL fax.cpl",
|
||
NULL,
|
||
SW_SHOWNORMAL,
|
||
};
|
||
|
||
TCHAR ScratchCmdLine[MAX_PATH];
|
||
PCTSTR PrinterCmdLine = TEXT("rundll32.exe printui.dll,PrintUIEntry /il");
|
||
STARTUPINFO si;
|
||
PROCESS_INFORMATION pi;
|
||
|
||
//
|
||
// print or fax first time?
|
||
//
|
||
if (bWelcomePage && !GetEnvironmentVariable(TEXT("NTFaxSendNote"), NULL, 0)) {
|
||
DWORD PrinterCount = 1;
|
||
PRINTER_INFO_4 *pPrinterInfo4;
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READONLY)) {
|
||
|
||
bInitialized = GetRegistryDword(hRegKey, REGVAL_PRINTER_INITIALIZED);
|
||
RegCloseKey(hRegKey);
|
||
|
||
}
|
||
|
||
if (bInitialized) {
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
//
|
||
// if there is more than one printer don't confuse the user by asking
|
||
// to add a printer since one is already installed.
|
||
//
|
||
pPrinterInfo4 = MyEnumPrinters(
|
||
NULL,
|
||
4,
|
||
&PrinterCount,
|
||
PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS);
|
||
|
||
if (pPrinterInfo4) {
|
||
MemFree(pPrinterInfo4);
|
||
if (PrinterCount > 1) {
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READWRITE)) {
|
||
|
||
SetRegistryDword(hRegKey, REGVAL_PRINTER_INITIALIZED , 1);
|
||
RegCloseKey(hRegKey);
|
||
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
}
|
||
|
||
|
||
if (DialogBoxParam(ghInstance,
|
||
MAKEINTRESOURCE( IDD_WIZFIRSTTIMEPRINT ),
|
||
hDlg,
|
||
firstprintdlgproc,
|
||
(LPARAM)NULL) != IDOK) {
|
||
//
|
||
// if they said "print", then launch the add/remove printer wizard
|
||
//
|
||
ZeroMemory(&si,sizeof(si));
|
||
GetStartupInfo(&si);
|
||
lstrcpy(ScratchCmdLine,PrinterCmdLine);
|
||
if (CreateProcess(
|
||
NULL,
|
||
ScratchCmdLine,
|
||
NULL,
|
||
NULL,
|
||
FALSE,
|
||
DETACHED_PROCESS,
|
||
NULL,
|
||
NULL,
|
||
&si,
|
||
&pi
|
||
)) {
|
||
CloseHandle( pi.hThread );
|
||
CloseHandle( pi.hProcess );
|
||
}
|
||
|
||
return(FALSE);
|
||
} else {
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READWRITE)) {
|
||
|
||
SetRegistryDword(hRegKey, REGVAL_PRINTER_INITIALIZED , 1);
|
||
RegCloseKey(hRegKey);
|
||
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
} else if (!bWelcomePage) {
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READONLY)) {
|
||
|
||
bInitialized = GetRegistryDword(hRegKey, REGVAL_WIZARD_INITIALIZED);
|
||
RegCloseKey(hRegKey);
|
||
|
||
}
|
||
|
||
if (bInitialized) {
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
//
|
||
// show the user a dialog
|
||
//
|
||
if (DialogBoxParam(ghInstance,
|
||
MAKEINTRESOURCE( IDD_WIZFIRSTTIME ),
|
||
hDlg,
|
||
firstdlgproc,
|
||
(LPARAM)NULL) == IDYES) {
|
||
//
|
||
// if they said yes, then launch the control panel applet
|
||
//
|
||
if (!ShellExecuteEx(&shellExeInfo)) {
|
||
DisplayMessageDialog(hDlg, 0, 0, IDS_ERR_CPL_LAUNCH);
|
||
return FALSE;
|
||
}
|
||
|
||
WaitForSingleObject( shellExeInfo.hProcess, INFINITE );
|
||
CloseHandle( shellExeInfo.hProcess ) ;
|
||
|
||
}
|
||
|
||
//
|
||
// set the reg key so this doesn't come up again
|
||
//
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READWRITE)) {
|
||
|
||
SetRegistryDword(hRegKey, REGVAL_WIZARD_INITIALIZED , 1 );
|
||
RegCloseKey(hRegKey);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return(TRUE);
|
||
|
||
}
|
||
|
||
INT_PTR
|
||
RecipientWizProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog procedure for the first wizard page: selecting the fax recipient
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
|
||
Return Value:
|
||
|
||
Depends on the message parameter
|
||
|
||
--*/
|
||
|
||
#define UpdateAddToListButton() \
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_ADD), GetCurrentRecipient(hDlg, NULL) == 0)
|
||
|
||
#define UpdateRemoveFromListButton(__BoolFlag) \
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_REMOVE),__BoolFlag)
|
||
|
||
{
|
||
PUSERMEM pUserMem;
|
||
DWORD countryId;
|
||
INT cmd;
|
||
NMHDR *pNMHdr;
|
||
|
||
DWORD dwErrorCode;
|
||
|
||
HANDLE hEditControl;
|
||
|
||
TCHAR tszBuffer[MAX_STRING_LEN];
|
||
|
||
//
|
||
// Maximum length for various text fields
|
||
//
|
||
|
||
static INT textLimits[] = {
|
||
|
||
IDC_CHOOSE_NAME_EDIT, 64,
|
||
IDC_CHOOSE_AREA_CODE_EDIT, 11,
|
||
IDC_CHOOSE_NUMBER_EDIT, 51,
|
||
0
|
||
};
|
||
|
||
//
|
||
// Handle common messages shared by all wizard pages
|
||
//
|
||
|
||
if (! (pUserMem = CommonWizardProc(hDlg, message, wParam, lParam, PSWIZB_BACK | PSWIZB_NEXT)))
|
||
return FALSE;
|
||
|
||
switch (message) {
|
||
|
||
case WM_INITDIALOG:
|
||
|
||
//
|
||
// check if the user has run the wizard before so they can fill in the coverpage info.
|
||
//
|
||
DoFirstTimeInitStuff(hDlg, FALSE);
|
||
|
||
//
|
||
// tapi is asynchronously initialized, wait for it to finish spinning up.
|
||
//
|
||
WaitForSingleObject( pUserMem->hTapiEvent, INFINITE );
|
||
|
||
//
|
||
// Restore the last recipient information as a convenience
|
||
//
|
||
|
||
RestoreLastRecipientInfo(hDlg, &countryId);
|
||
|
||
//
|
||
// Initialize the list of countries
|
||
//
|
||
|
||
UpdateCountryCombobox(hDlg, countryId);
|
||
|
||
//
|
||
// Check if MAPI is installed - we need it for address book features
|
||
//
|
||
|
||
// if (! IsMapiAvailable())
|
||
// EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_ADDRBOOK), FALSE);
|
||
|
||
LimitTextFields(hDlg, textLimits);
|
||
|
||
//
|
||
// Initialize the recipient list view
|
||
//
|
||
|
||
InitRecipientListView(GetDlgItem(hDlg, IDC_CHOOSE_RECIPIENT_LIST));
|
||
|
||
//
|
||
// Initialize the location combo-box
|
||
//
|
||
|
||
LocationListInit(hDlg, pUserMem);
|
||
|
||
// Disable the IME for the area code edit control.
|
||
|
||
hEditControl = GetDlgItem( hDlg, IDC_CHOOSE_AREA_CODE_EDIT );
|
||
|
||
if ( hEditControl != (HWND) INVALID_HANDLE_VALUE )
|
||
{
|
||
ImmAssociateContext( hEditControl, (HIMC) NULL );
|
||
}
|
||
|
||
// Disable the IME for the fax phone number edit control.
|
||
|
||
hEditControl = GetDlgItem( hDlg, IDC_CHOOSE_NUMBER_EDIT );
|
||
|
||
if ( hEditControl != (HWND) INVALID_HANDLE_VALUE )
|
||
{
|
||
ImmAssociateContext( hEditControl, (HIMC) NULL );
|
||
}
|
||
|
||
break;
|
||
|
||
case WM_NOTIFY:
|
||
|
||
pNMHdr = (NMHDR *) lParam;
|
||
|
||
switch (pNMHdr->code) {
|
||
|
||
case LVN_KEYDOWN:
|
||
|
||
if (pNMHdr->hwndFrom == GetDlgItem(hDlg, IDC_CHOOSE_RECIPIENT_LIST) &&
|
||
((LV_KEYDOWN *) pNMHdr)->wVKey == VK_DELETE)
|
||
{
|
||
RemoveRecipient(hDlg, pUserMem);
|
||
}
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
|
||
if (! ValidateRecipients(hDlg, pUserMem)) {
|
||
|
||
//
|
||
// Validate the list of recipients and prevent the user
|
||
// from advancing to the next page if there is a problem
|
||
//
|
||
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
break;
|
||
|
||
case PSN_SETACTIVE:
|
||
//
|
||
// make sure the remove button has the correct state
|
||
//
|
||
UpdateRemoveFromListButton(pUserMem->pRecipients ? TRUE : FALSE);
|
||
break;
|
||
}
|
||
|
||
return FALSE;
|
||
|
||
case WM_COMMAND:
|
||
|
||
cmd = GET_WM_COMMAND_CMD(wParam, lParam);
|
||
|
||
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
||
|
||
case IDC_CHOOSE_COUNTRY_COMBO:
|
||
|
||
if (cmd == CBN_SELCHANGE) {
|
||
|
||
//
|
||
// Update the area code edit box if necessary
|
||
//
|
||
|
||
SelChangeCountryListBox(GetDlgItem(hDlg, IDC_CHOOSE_COUNTRY_COMBO),
|
||
GetDlgItem(hDlg, IDC_CHOOSE_AREA_CODE_EDIT));
|
||
|
||
UpdateAddToListButton();
|
||
|
||
}
|
||
break;
|
||
|
||
case IDC_CHOOSE_NAME_EDIT:
|
||
|
||
if (cmd == EN_CHANGE)
|
||
{
|
||
UpdateAddToListButton();
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case IDC_CHOOSE_AREA_CODE_EDIT:
|
||
|
||
if (cmd == EN_CHANGE)
|
||
{
|
||
UpdateAddToListButton();
|
||
|
||
// Look for DBCS in the edit control.
|
||
|
||
// Read the text from the edit control.
|
||
|
||
if ( GetDlgItemText( hDlg, IDC_CHOOSE_AREA_CODE_EDIT, tszBuffer,
|
||
MAX_STRING_LEN ) != 0 )
|
||
{
|
||
// Determine whether the contents of the edit control are legal.
|
||
|
||
if ( IsStringASCII( tszBuffer ) != (BOOL) TRUE )
|
||
{
|
||
LoadString(ghInstance, IDS_ERROR_AREA_CODE,
|
||
tszBuffer, MAX_STRING_LEN);
|
||
|
||
MessageBox( hDlg, tszBuffer, NULL,
|
||
(UINT) (MB_ICONSTOP | MB_OK) );
|
||
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_AREA_CODE_EDIT, L"");
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
dwErrorCode = GetLastError();
|
||
|
||
if ( dwErrorCode != (DWORD) ERROR_SUCCESS )
|
||
{
|
||
// Error reading the edit control.
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case IDC_CHOOSE_NUMBER_EDIT:
|
||
|
||
if (cmd == EN_CHANGE)
|
||
{
|
||
UpdateAddToListButton();
|
||
|
||
// Look for DBCS in the edit control.
|
||
|
||
// Read the text from the edit control.
|
||
|
||
if ( GetDlgItemText( hDlg, IDC_CHOOSE_NUMBER_EDIT, tszBuffer,
|
||
MAX_STRING_LEN ) != 0 )
|
||
{
|
||
// Determine whether the contents of the edit control are legal.
|
||
|
||
if ( IsStringASCII( tszBuffer ) != (BOOL) TRUE )
|
||
{
|
||
LoadString(ghInstance, IDS_ERROR_FAX_NUMBER,
|
||
tszBuffer, MAX_STRING_LEN);
|
||
|
||
MessageBox( hDlg, tszBuffer, NULL,
|
||
(UINT) (MB_ICONSTOP | MB_OK) );
|
||
|
||
SetDlgItemText(hDlg, IDC_CHOOSE_NUMBER_EDIT, L"");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
dwErrorCode = GetLastError();
|
||
|
||
if ( dwErrorCode != (DWORD) ERROR_SUCCESS )
|
||
{
|
||
// Error reading the edit control.
|
||
}
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
case IDC_USE_DIALING_RULES:
|
||
|
||
UpdateCountryCombobox(hDlg, -1);
|
||
UpdateAddToListButton();
|
||
|
||
break;
|
||
|
||
case IDC_CHOOSE_ADDRBOOK:
|
||
|
||
DoAddressBook(hDlg, pUserMem);
|
||
UpdateRemoveFromListButton(pUserMem->pRecipients ? TRUE : FALSE);
|
||
break;
|
||
|
||
case IDC_TAPI_PROPS:
|
||
|
||
DoTapiProps(hDlg);
|
||
LocationListInit(hDlg, pUserMem);
|
||
break;
|
||
|
||
case IDC_LOCATION_LIST:
|
||
|
||
if (cmd == CBN_SELCHANGE)
|
||
LocationListSelChange(hDlg);
|
||
break;
|
||
|
||
case IDC_CHOOSE_ADD:
|
||
|
||
if ((cmd = AddRecipient(hDlg, pUserMem)) != 0) {
|
||
|
||
if (cmd > 0)
|
||
DisplayMessageDialog(hDlg, 0, 0, cmd);
|
||
else
|
||
MessageBeep(MB_OK);
|
||
|
||
} else {
|
||
SetFocus(GetDlgItem(hDlg, IDC_CHOOSE_NAME_EDIT));
|
||
//
|
||
// enable the remove button
|
||
//
|
||
UpdateRemoveFromListButton(TRUE);
|
||
}
|
||
break;
|
||
case IDC_CHOOSE_REMOVE:
|
||
RemoveRecipient(hDlg, pUserMem);
|
||
//
|
||
// disable the remove button if there are no more recipients
|
||
//
|
||
if (!pUserMem->pRecipients) {
|
||
UpdateRemoveFromListButton(FALSE);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
ValidateSelectedCoverPage(
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
If a cover page is selected, then do the following:
|
||
if the cover page file is a link resolve it
|
||
check if the cover page file contains note/subject fields
|
||
|
||
Arguments:
|
||
|
||
pUserMem - Points to user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
TCHAR filename[MAX_PATH];
|
||
COVDOCINFO covDocInfo;
|
||
DWORD ec;
|
||
|
||
if (ResolveShortcut(pUserMem->coverPage, filename))
|
||
_tcscpy(pUserMem->coverPage, filename);
|
||
|
||
Verbose(("Cover page selected: %ws\n", pUserMem->coverPage));
|
||
|
||
ec = PrintCoverPage(NULL, NULL, pUserMem->coverPage, &covDocInfo);
|
||
if (!ec) {
|
||
|
||
pUserMem->noteSubjectFlag = covDocInfo.Flags;
|
||
pUserMem->cpPaperSize = covDocInfo.PaperSize;
|
||
pUserMem->cpOrientation = covDocInfo.Orientation;
|
||
|
||
} else {
|
||
|
||
Error(("Cannot examine cover page file '%ws': %d\n",
|
||
pUserMem->coverPage,
|
||
ec));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
INT_PTR
|
||
CoverPageWizProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog procedure for the second wizard page:
|
||
selecting cover page and setting other fax options
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
|
||
Return Value:
|
||
|
||
Depends on the message parameter
|
||
|
||
--*/
|
||
|
||
{
|
||
static INT textLimits[] = {
|
||
|
||
IDC_CHOOSE_CP_SUBJECT, 256,
|
||
IDC_CHOOSE_CP_NOTE, 8192,
|
||
0
|
||
};
|
||
|
||
PUSERMEM pUserMem;
|
||
PDMPRIVATE pdmPrivate;
|
||
WORD cmdId;
|
||
HKEY hRegKey;
|
||
|
||
|
||
|
||
//
|
||
// Handle common messages shared by all wizard pages
|
||
//
|
||
|
||
if (! (pUserMem = CommonWizardProc(hDlg, message, wParam, lParam, PSWIZB_BACK|PSWIZB_NEXT)))
|
||
return FALSE;
|
||
|
||
//
|
||
// Handle anything specific to the current wizard page
|
||
//
|
||
|
||
pdmPrivate = &pUserMem->devmode.dmPrivate;
|
||
|
||
switch (message) {
|
||
|
||
case WM_INITDIALOG:
|
||
|
||
//
|
||
// Retrieve the most recently used cover page settings
|
||
//
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READONLY)) {
|
||
LPTSTR tmp;
|
||
pdmPrivate->sendCoverPage =
|
||
GetRegistryDword(hRegKey, REGVAL_SEND_COVERPG);
|
||
|
||
tmp = GetRegistryString(hRegKey, REGVAL_COVERPG, TEXT("") );
|
||
if (tmp) {
|
||
lstrcpy(pUserMem->coverPage, tmp );
|
||
MemFree(tmp);
|
||
}
|
||
RegCloseKey(hRegKey);
|
||
}
|
||
|
||
//
|
||
// Initialize the list of cover pages
|
||
//
|
||
|
||
WaitForSingleObject( pUserMem->hFaxSvcEvent, INFINITE );
|
||
if (pUserMem->pCPInfo = AllocCoverPageInfo(pUserMem->hPrinter, pUserMem->ServerCPOnly)) {
|
||
|
||
InitCoverPageList(pUserMem->pCPInfo,
|
||
GetDlgItem(hDlg, IDC_CHOOSE_CP_LIST),
|
||
pUserMem->coverPage);
|
||
}
|
||
|
||
//
|
||
// Indicate whether cover page should be sent
|
||
//
|
||
|
||
if (SendDlgItemMessage(hDlg, IDC_CHOOSE_CP_LIST, CB_GETCOUNT, 0, 0) <= 0) {
|
||
pdmPrivate->sendCoverPage = FALSE;
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_CHECK), FALSE);
|
||
}
|
||
|
||
CheckDlgButton(hDlg, IDC_CHOOSE_CP_CHECK, pdmPrivate->sendCoverPage);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_LIST), pdmPrivate->sendCoverPage);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_SUBJECT), pdmPrivate->sendCoverPage);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_SUBJECT), pdmPrivate->sendCoverPage);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_NOTE), pdmPrivate->sendCoverPage);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_NOTE), pdmPrivate->sendCoverPage);
|
||
|
||
//
|
||
// make sure the user selects a coverpage if this is the fax send utility
|
||
//
|
||
if (GetEnvironmentVariable(TEXT("NTFaxSendNote"), NULL, 0)) {
|
||
pdmPrivate->sendCoverPage = TRUE;
|
||
CheckDlgButton(hDlg, IDC_CHOOSE_CP_CHECK, TRUE);
|
||
// hide the checkbox
|
||
MyHideWindow(GetDlgItem(hDlg,IDC_CHOOSE_CP_CHECK) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_LIST), TRUE);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_SUBJECT), TRUE);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_SUBJECT), TRUE);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_NOTE), TRUE);
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_NOTE), TRUE);
|
||
} else {
|
||
MyHideWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_NOCHECK) );
|
||
}
|
||
|
||
LimitTextFields(hDlg, textLimits);
|
||
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
switch (cmdId = GET_WM_COMMAND_ID(wParam, lParam)) {
|
||
|
||
case IDC_CHOOSE_CP_CHECK:
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP), IsDlgButtonChecked(hDlg, cmdId) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_LIST), IsDlgButtonChecked(hDlg, cmdId) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_SUBJECT), IsDlgButtonChecked(hDlg, cmdId) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_SUBJECT), IsDlgButtonChecked(hDlg, cmdId) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_CHOOSE_CP_NOTE), IsDlgButtonChecked(hDlg, cmdId) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_CHOOSE_CP_NOTE), IsDlgButtonChecked(hDlg, cmdId) );
|
||
|
||
break;
|
||
|
||
|
||
};
|
||
|
||
break;
|
||
|
||
case WM_NOTIFY:
|
||
|
||
if (((NMHDR *) lParam)->code == PSN_WIZNEXT) {
|
||
|
||
//
|
||
// Remember the cover page settings selected
|
||
//
|
||
|
||
pUserMem->noteSubjectFlag = 0;
|
||
pUserMem->cpPaperSize = 0;
|
||
pUserMem->cpOrientation = 0;
|
||
pdmPrivate->sendCoverPage = IsDlgButtonChecked(hDlg, IDC_CHOOSE_CP_CHECK);
|
||
|
||
GetSelectedCoverPage(pUserMem->pCPInfo,
|
||
GetDlgItem(hDlg, IDC_CHOOSE_CP_LIST),
|
||
pUserMem->coverPage);
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READWRITE)) {
|
||
|
||
SetRegistryDword(hRegKey, REGVAL_SEND_COVERPG, pdmPrivate->sendCoverPage);
|
||
SetRegistryString(hRegKey, REGVAL_COVERPG, pUserMem->coverPage);
|
||
RegCloseKey(hRegKey);
|
||
}
|
||
|
||
//
|
||
// If a cover page is selected, then do the following:
|
||
// if the cover page file is a link resolve it
|
||
// check if the cover page file contains note/subject fields
|
||
//
|
||
|
||
if (pdmPrivate->sendCoverPage)
|
||
ValidateSelectedCoverPage(pUserMem);
|
||
|
||
//
|
||
// Collect the current values of other dialog controls
|
||
//
|
||
|
||
if (pUserMem->pSubject) MemFree(pUserMem->pSubject);
|
||
if (pUserMem->pNoteMessage) MemFree(pUserMem->pNoteMessage);
|
||
pUserMem->pSubject = GetTextStringValue(GetDlgItem(hDlg, IDC_CHOOSE_CP_SUBJECT));
|
||
pUserMem->pNoteMessage = GetTextStringValue(GetDlgItem(hDlg, IDC_CHOOSE_CP_NOTE));
|
||
|
||
//
|
||
// If the current application is "Send Note" utility, then
|
||
// the note field must not be empty.
|
||
//
|
||
|
||
if (pUserMem->pSubject == NULL &&
|
||
pUserMem->pNoteMessage == NULL &&
|
||
GetEnvironmentVariable(TEXT("NTFaxSendNote"), NULL, 0))
|
||
{
|
||
DisplayMessageDialog(hDlg, 0, 0, IDS_NOTE_SUBJECT_EMPTY);
|
||
SetFocus(GetDlgItem(hDlg, IDC_CHOOSE_CP_SUBJECT));
|
||
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, -1);
|
||
return TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
INT_PTR
|
||
FaxOptsWizProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog procedure for the first wizard page: entering subject and note information
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
|
||
Return Value:
|
||
|
||
Depends on the message parameter
|
||
|
||
--*/
|
||
|
||
{
|
||
//
|
||
// Maximum length for various text fields
|
||
//
|
||
|
||
static INT textLimits[] = {
|
||
|
||
IDC_WIZ_FAXOPTS_BILLING, 16,
|
||
0
|
||
};
|
||
|
||
PUSERMEM pUserMem;
|
||
PDMPRIVATE pdmPrivate;
|
||
WORD cmdId;
|
||
// TCHAR TimeFormat[32];
|
||
TCHAR Is24H[2], IsRTL[2], *pszTimeFormat = TEXT("h : mm tt");
|
||
static HWND hTimeControl;
|
||
SYSTEMTIME st;
|
||
|
||
if (! (pUserMem = CommonWizardProc(hDlg, message, wParam, lParam, PSWIZB_BACK|PSWIZB_NEXT)))
|
||
return FALSE;
|
||
|
||
|
||
pdmPrivate = &pUserMem->devmode.dmPrivate;
|
||
switch (message) {
|
||
|
||
case WM_INITDIALOG:
|
||
|
||
|
||
//LoadString(ghInstance,IDS_WIZ_TIME_FORMAT,TimeFormat,sizeof(TimeFormat));
|
||
hTimeControl = GetDlgItem(hDlg, IDC_WIZ_FAXOPTS_SENDTIME);
|
||
|
||
if (GetLocaleInfo( LOCALE_USER_DEFAULT,LOCALE_ITIME, Is24H,sizeof(Is24H) ) && Is24H[0] == TEXT('1')) {
|
||
pszTimeFormat = TEXT("H : mm");
|
||
}
|
||
else if (GetLocaleInfo( LOCALE_USER_DEFAULT,LOCALE_ITIMEMARKPOSN, IsRTL,sizeof(IsRTL) ) && IsRTL[0] == TEXT('1')) {
|
||
pszTimeFormat = TEXT("tt h : mm");
|
||
}
|
||
|
||
LimitTextFields(hDlg, textLimits);
|
||
|
||
DateTime_SetFormat( hTimeControl,pszTimeFormat );
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
// restore time to send controls
|
||
//
|
||
cmdId = (pdmPrivate->whenToSend == SENDFAX_AT_CHEAP) ? IDC_WIZ_FAXOPTS_DISCOUNT :
|
||
(pdmPrivate->whenToSend == SENDFAX_AT_TIME) ? IDC_WIZ_FAXOPTS_SPECIFIC :
|
||
IDC_WIZ_FAXOPTS_ASAP;
|
||
|
||
CheckDlgButton(hDlg, cmdId, TRUE);
|
||
|
||
EnableWindow(hTimeControl, (cmdId == IDC_WIZ_FAXOPTS_SPECIFIC) );
|
||
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_FAXOPTS_DATE), (cmdId == IDC_WIZ_FAXOPTS_SPECIFIC) );
|
||
|
||
GetLocalTime(&st);
|
||
st.wHour = pdmPrivate->sendAtTime.Hour;
|
||
st.wMinute = pdmPrivate->sendAtTime.Minute;
|
||
DateTime_SetSystemtime( hTimeControl, GDT_VALID, &st );
|
||
|
||
SetDlgItemText(hDlg, IDC_WIZ_FAXOPTS_BILLING, pdmPrivate->billingCode);
|
||
|
||
return TRUE;
|
||
|
||
case WM_NOTIFY:
|
||
|
||
if (((NMHDR *) lParam)->code == PSN_WIZNEXT) {
|
||
//
|
||
// retrieve the billing code
|
||
//
|
||
if (! GetDlgItemText(hDlg, IDC_WIZ_FAXOPTS_BILLING, pdmPrivate->billingCode, MAX_BILLING_CODE)) {
|
||
pdmPrivate->billingCode[0] = NUL;
|
||
}
|
||
|
||
//
|
||
// retrieve the sending time
|
||
//
|
||
pdmPrivate->whenToSend = IsDlgButtonChecked(hDlg,IDC_WIZ_FAXOPTS_DISCOUNT) ? SENDFAX_AT_CHEAP :
|
||
IsDlgButtonChecked(hDlg,IDC_WIZ_FAXOPTS_SPECIFIC) ? SENDFAX_AT_TIME :
|
||
SENDFAX_ASAP;
|
||
|
||
if (pdmPrivate->whenToSend == SENDFAX_AT_TIME) {
|
||
DWORD rVal;
|
||
SYSTEMTIME SendTime;
|
||
TCHAR TimeBuffer[128];
|
||
|
||
|
||
//
|
||
// get specific time
|
||
//
|
||
rVal = DateTime_GetSystemtime(hTimeControl, &SendTime);
|
||
pdmPrivate->sendAtTime.Hour = SendTime.wHour;
|
||
pdmPrivate->sendAtTime.Minute = SendTime.wMinute;
|
||
|
||
|
||
rVal = GetDateFormat(
|
||
LOCALE_SYSTEM_DEFAULT,
|
||
0,
|
||
&SendTime,
|
||
NULL,
|
||
TimeBuffer,
|
||
sizeof(TimeBuffer)
|
||
);
|
||
|
||
TimeBuffer[rVal - 1] = TEXT(' ');
|
||
|
||
GetTimeFormat(
|
||
LOCALE_SYSTEM_DEFAULT,
|
||
0,
|
||
&SendTime,
|
||
NULL,
|
||
&TimeBuffer[rVal],
|
||
sizeof(TimeBuffer)
|
||
);
|
||
|
||
Verbose(("faxui - Fax Send time %ws", TimeBuffer));
|
||
}
|
||
|
||
}
|
||
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
switch (cmdId = GET_WM_COMMAND_ID(wParam, lParam)) {
|
||
|
||
case IDC_WIZ_FAXOPTS_SPECIFIC:
|
||
case IDC_WIZ_FAXOPTS_DISCOUNT:
|
||
case IDC_WIZ_FAXOPTS_ASAP:
|
||
EnableWindow(hTimeControl, (cmdId == IDC_WIZ_FAXOPTS_SPECIFIC) );
|
||
EnableWindow(GetDlgItem(hDlg, IDC_STATIC_FAXOPTS_DATE), (cmdId == IDC_WIZ_FAXOPTS_SPECIFIC) );
|
||
|
||
break;
|
||
|
||
};
|
||
|
||
break;
|
||
default:
|
||
return FALSE;
|
||
} ;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
#ifdef FAX_SCAN_ENABLED
|
||
|
||
BOOL
|
||
CloseDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_IDENTITY * TwIdentity
|
||
);
|
||
|
||
BOOL
|
||
OpenDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_IDENTITY * TwIdentity
|
||
);
|
||
|
||
BOOL
|
||
DisableDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_USERINTERFACE * TwUserInterface
|
||
);
|
||
|
||
BOOL
|
||
EnableDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_USERINTERFACE * TwUserInterface
|
||
);
|
||
|
||
BOOL
|
||
SetCapability(
|
||
PUSERMEM pUserMem,
|
||
USHORT Capability,
|
||
USHORT Type,
|
||
LPVOID Value
|
||
);
|
||
|
||
|
||
BOOL
|
||
Scan_SetCapabilities(
|
||
PUSERMEM pUserMem
|
||
);
|
||
|
||
#define WM_SCAN_INIT WM_APP
|
||
#define WM_SCAN_OPENDSM WM_APP+1
|
||
#define WM_SCAN_CLOSEDSM WM_APP+2
|
||
#define WM_SCAN_GETDEFAULT WM_APP+3
|
||
#define WM_SCAN_GETFIRST WM_APP+4
|
||
#define WM_SCAN_GETNEXT WM_APP+5
|
||
|
||
#define WM_SCAN_OPENDS WM_APP+10
|
||
#define WM_SCAN_CLOSEDS WM_APP+11
|
||
#define WM_SCAN_ENABLEDS WM_APP+12
|
||
#define WM_SCAN_DISABLEDS WM_APP+13
|
||
|
||
#define WM_SCAN_CONTROLGET WM_APP+20
|
||
#define WM_SCAN_CONTROLGETDEF WM_APP+21
|
||
#define WM_SCAN_CONTROLRESET WM_APP+22
|
||
#define WM_SCAN_CONTROLSET WM_APP+23
|
||
#define WM_SCAN_CONTROLENDXFER WM_APP+24
|
||
|
||
#define WM_SCAN_IMAGEGET WM_APP+30
|
||
|
||
#define Scan_Init(_pUserMem) (SendMessage(_pUserMem->hWndTwain, WM_SCAN_INIT,0,(LPARAM)_pUserMem))
|
||
#define Scan_OpenDSM(_pUserMem) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_OPENDSM,0,(LPARAM)&_pUserMem->hWndTwain))
|
||
#define Scan_CloseDSM(_pUserMem) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_CLOSEDSM,0,(LPARAM)&_pUserMem->hWndTwain))
|
||
|
||
#define Scan_GetDefault(_pUserMem,_TwIdentity) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_GETDEFAULT,0,(LPARAM)_TwIdentity))
|
||
#define Scan_GetFirst(_pUserMem,_TwIdentity) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_GETFIRST,0,(LPARAM)_TwIdentity))
|
||
#define Scan_GetNext(_pUserMem,_TwIdentity) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_GETNEXT,0,(LPARAM)_TwIdentity))
|
||
|
||
#define Scan_OpenDS(_pUserMem,_TwIdentity) (SendMessage(_pUserMem->hWndTwain, WM_SCAN_OPENDS,0,(LPARAM)_TwIdentity))
|
||
#define Scan_CloseDS(_pUserMem,_TwIdentity) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_CLOSEDS,0,(LPARAM)_TwIdentity))
|
||
#define Scan_EnableDS(_pUserMem,_TwUi) (SendMessage(_pUserMem->hWndTwain, WM_SCAN_ENABLEDS,0,(LPARAM)_TwUi))
|
||
#define Scan_DisableDS(_pUserMem,_TwUi) (SendMessage(_pUserMem->hWndTwain, WM_SCAN_DISABLEDS,0,(LPARAM)_TwUi))
|
||
|
||
#define Scan_ControlGet(_pUserMem,_What,_Data) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_CONTROLGET,(WPARAM)_What,(LPARAM)_Data))
|
||
#define Scan_ControlGetDef(_pUserMem,_What,_Data) (SendMessage(_pUserMem->hWndTwain, WM_SCAN_CONTROLGETDEF,(WPARAM)_What,(LPARAM)_Data))
|
||
#define Scan_ControlReset(_pUserMem,_What,_Data) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_CONTROLRESET,(WPARAM)_What,(LPARAM)_Data))
|
||
#define Scan_ControlSet(_pUserMem,_What,_Data) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_CONTROLSET,(WPARAM)_What,(LPARAM)_Data))
|
||
#define Scan_ControlEndXfer(_pUserMem,_What,_Data) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_CONTROLENDXFER,(WPARAM)_What,(LPARAM)_Data))
|
||
|
||
#define Scan_ImageGet(_pUserMem,_What,_Data) ((DWORD)SendMessage(_pUserMem->hWndTwain, WM_SCAN_IMAGEGET,(WPARAM)_What,(LPARAM)_Data))
|
||
|
||
//#define WM_SCAN_GETEVENT WM_APP+7
|
||
|
||
|
||
|
||
DWORD
|
||
CallTwain(
|
||
PUSERMEM pUserMem,
|
||
TW_UINT32 DG,
|
||
TW_UINT16 DAT,
|
||
TW_UINT16 MSG,
|
||
TW_MEMREF pData
|
||
)
|
||
{
|
||
DWORD TwResult = 0;
|
||
TW_STATUS TwStatus = {0};
|
||
|
||
__try {
|
||
|
||
TwResult = pUserMem->pDsmEntry(
|
||
&pUserMem->AppId,
|
||
NULL,
|
||
DG,
|
||
DAT,
|
||
MSG,
|
||
pData
|
||
);
|
||
|
||
if (TwResult) {
|
||
|
||
pUserMem->pDsmEntry(
|
||
&pUserMem->AppId,
|
||
NULL,
|
||
DG_CONTROL,
|
||
DAT_STATUS,
|
||
MSG_GET,
|
||
(TW_MEMREF) &TwStatus
|
||
);
|
||
if (TwStatus.ConditionCode) {
|
||
TwResult = TwStatus.ConditionCode;
|
||
}
|
||
|
||
Verbose(( "CallTwain failed, ec=%d\n", TwResult ));
|
||
}
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
//
|
||
// for some reason we crashed, so return the exception code
|
||
//
|
||
|
||
TwResult = GetExceptionCode();
|
||
Verbose(( "CallTwain crashed, ec=0x%08x\n", TwResult ));
|
||
|
||
}
|
||
|
||
return TwResult;
|
||
}
|
||
|
||
|
||
DWORD
|
||
CallTwainDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_UINT32 DG,
|
||
TW_UINT16 DAT,
|
||
TW_UINT16 MSG,
|
||
TW_MEMREF pData
|
||
)
|
||
{
|
||
DWORD TwResult = 0;
|
||
TW_STATUS TwStatus = {0};
|
||
|
||
__try {
|
||
|
||
TwResult = pUserMem->pDsmEntry(
|
||
&pUserMem->AppId,
|
||
&pUserMem->DataSource,
|
||
DG,
|
||
DAT,
|
||
MSG,
|
||
pData
|
||
);
|
||
|
||
if (TwResult) {
|
||
|
||
pUserMem->pDsmEntry(
|
||
&pUserMem->AppId,
|
||
&pUserMem->DataSource,
|
||
DG_CONTROL,
|
||
DAT_STATUS,
|
||
MSG_GET,
|
||
(TW_MEMREF) &TwStatus
|
||
);
|
||
if (TwStatus.ConditionCode) {
|
||
TwResult = TwStatus.ConditionCode;
|
||
}
|
||
|
||
//Verbose(( "CallTwainDataSource failed, ec=%d\n", TwResult ));
|
||
}
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
//
|
||
// for some reason we crashed, so return the exception code
|
||
//
|
||
|
||
TwResult = GetExceptionCode();
|
||
Verbose(( "CallTwainDataSource crashed, ec=0x%08x\n", TwResult ));
|
||
|
||
}
|
||
|
||
return TwResult;
|
||
}
|
||
|
||
|
||
LRESULT
|
||
WINAPI
|
||
TwainWndProc(
|
||
HWND hwnd,
|
||
UINT uMsg,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
{
|
||
DWORD TwResult = 0;
|
||
static PUSERMEM pUserMem = NULL;
|
||
|
||
switch (uMsg) {
|
||
|
||
case WM_SCAN_INIT:
|
||
pUserMem = (PUSERMEM)lParam;
|
||
return(TRUE);
|
||
break;
|
||
|
||
case WM_SCAN_OPENDSM :
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_PARENT,
|
||
MSG_OPENDSM,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_OPENDSM (DAT_PARENT) failed, ec = %d\n", TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
case WM_SCAN_CLOSEDSM:
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_PARENT,
|
||
MSG_CLOSEDSM,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_CLOSEDSM (DAT_PARENT) failed, ec = %d\n", TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
case WM_SCAN_GETDEFAULT:
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_IDENTITY,
|
||
MSG_GETDEFAULT,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GETDEFAULT (DAT_IDENTITY) failed, ec = %d\n", TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
case WM_SCAN_GETFIRST:
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_IDENTITY,
|
||
MSG_GETFIRST,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GETFIRST (DAT_IDENTITY) failed, ec = %d\n", TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
case WM_SCAN_GETNEXT:
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_IDENTITY,
|
||
MSG_GETNEXT,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS && TwResult != TWRC_ENDOFLIST) {
|
||
Verbose(( "MSG_GETNEXT (DAT_IDENTITY) failed, ec = %d\n", TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
case WM_SCAN_OPENDS:
|
||
if (OpenDataSource( pUserMem, (TW_IDENTITY *)lParam ) &&
|
||
Scan_SetCapabilities( pUserMem )) {
|
||
return TRUE;
|
||
}
|
||
return(FALSE);
|
||
|
||
case WM_SCAN_CLOSEDS:
|
||
return (CloseDataSource( pUserMem, (TW_IDENTITY *)lParam ));
|
||
|
||
case WM_SCAN_ENABLEDS:
|
||
return (EnableDataSource( pUserMem, (TW_USERINTERFACE *)lParam ));
|
||
|
||
case WM_SCAN_DISABLEDS:
|
||
return (DisableDataSource( pUserMem, (TW_USERINTERFACE *)lParam ));
|
||
|
||
case WM_SCAN_CONTROLGET:
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
(TW_UINT16)wParam,
|
||
MSG_GET,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GET (%d)failed, ec = %d\n", wParam, TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
case WM_SCAN_CONTROLGETDEF:
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
(TW_UINT16)wParam,
|
||
MSG_GETDEFAULT,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GETDEFAULT (%d)failed, ec = %d\n", wParam, TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
case WM_SCAN_CONTROLRESET:
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
(TW_UINT16)wParam,
|
||
MSG_RESET,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_RESET (%d)failed, ec = %d\n", wParam, TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
case WM_SCAN_CONTROLSET:
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
(TW_UINT16)wParam,
|
||
MSG_SET,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_SET (%d)failed, ec = %d\n", wParam, TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
case WM_SCAN_CONTROLENDXFER:
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
(TW_UINT16)wParam,
|
||
MSG_ENDXFER,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_ENDXFER (%d)failed, ec = %d\n", wParam, TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
case WM_SCAN_IMAGEGET:
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_IMAGE,
|
||
(TW_UINT16)wParam,
|
||
MSG_GET,
|
||
(TW_MEMREF) lParam
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GET (DAT_IMAGEINFO) failed, ec = %d\n", TwResult ));
|
||
}
|
||
return(TwResult);
|
||
break;
|
||
|
||
default:
|
||
|
||
return DefWindowProc( hwnd, uMsg, wParam, lParam );
|
||
|
||
|
||
};
|
||
|
||
Assert(FALSE);
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
|
||
DWORD
|
||
TwainMessagePumpThread(
|
||
PUSERMEM pUserMem
|
||
)
|
||
{
|
||
WNDCLASS wc;
|
||
MSG msg;
|
||
HWND hWnd;
|
||
DWORD WaitObj;
|
||
TW_EVENT TwEvent;
|
||
DWORD TwResult;
|
||
|
||
|
||
wc.style = CS_OWNDC;
|
||
wc.lpfnWndProc = (WNDPROC)TwainWndProc;
|
||
wc.cbClsExtra = 0;
|
||
wc.cbWndExtra = 0;
|
||
wc.hInstance = ghInstance;
|
||
wc.hIcon = NULL;
|
||
wc.hCursor = NULL;
|
||
wc.hbrBackground = NULL;
|
||
wc.lpszMenuName = NULL;
|
||
wc.lpszClassName = L"FaxWizTwainWindow";
|
||
|
||
if (RegisterClass( &wc ) == 0) {
|
||
SetEvent( pUserMem->hEvent );
|
||
return 0;
|
||
}
|
||
|
||
hWnd = CreateWindow(
|
||
L"FaxWizTwainWindow",
|
||
L"FaxWizTwainWindow",
|
||
WS_DISABLED,
|
||
0,
|
||
0,
|
||
0,
|
||
0,
|
||
NULL,
|
||
NULL,
|
||
ghInstance,
|
||
NULL
|
||
);
|
||
if (hWnd == NULL) {
|
||
SetEvent( pUserMem->hEvent );
|
||
return 0;
|
||
}
|
||
|
||
pUserMem->hWndTwain = hWnd;
|
||
|
||
Scan_Init(pUserMem);
|
||
|
||
SetEvent( pUserMem->hEvent );
|
||
|
||
while (TRUE) {
|
||
WaitObj = MsgWaitForMultipleObjectsEx( 1, &pUserMem->hEventQuit, INFINITE, QS_ALLINPUT, 0 );
|
||
if (WaitObj == WAIT_OBJECT_0) {
|
||
return 0;
|
||
}
|
||
|
||
// PeekMessage instead of GetMessage so we drain the message queue
|
||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE )) {
|
||
if (msg.message == WM_QUIT) {
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
if (pUserMem->TwainAvail) {
|
||
|
||
TwEvent.pEvent = (TW_MEMREF) &msg;
|
||
TwEvent.TWMessage = MSG_NULL;
|
||
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_EVENT,
|
||
MSG_PROCESSEVENT,
|
||
(TW_MEMREF) &TwEvent
|
||
);
|
||
|
||
//if (TwResult != TWRC_SUCCESS && TwResult != TWRC_NOTDSEVENT) {
|
||
// Verbose(( "MSG_PROCESSEVENT (DAT_EVENT) failed, ec=%d\n", TwResult ));
|
||
//}
|
||
|
||
switch (TwEvent.TWMessage) {
|
||
case MSG_XFERREADY:
|
||
//
|
||
// transition from state 5 to state 6
|
||
//
|
||
Verbose(( "received MSG_XFERREADY, setting hEventXfer\n" ));
|
||
SetEvent( pUserMem->hEventXfer );
|
||
break;
|
||
|
||
case MSG_CLOSEDSREQ:
|
||
//
|
||
// transition from state 5 to 4 to 3
|
||
//
|
||
|
||
pUserMem->TwainCancelled = TRUE;
|
||
Verbose(( "received MSG_CLOSEDSREQ, setting hEventXfer\n" ));
|
||
SetEvent( pUserMem->hEventXfer );
|
||
break;
|
||
|
||
case MSG_NULL:
|
||
break;
|
||
}
|
||
|
||
if (TwResult == TWRC_NOTDSEVENT) {
|
||
TranslateMessage( &msg );
|
||
DispatchMessage( &msg );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
VOID
|
||
TerminateTwain(
|
||
PUSERMEM pUserMem
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
|
||
Verbose(( "entering TerminateTwain, state = %d\n", pUserMem->State ));
|
||
|
||
//Scan_CloseDS( pUserMem, &pUserMem->DataSource );
|
||
CloseDataSource( pUserMem, &pUserMem->DataSource );
|
||
|
||
if (pUserMem->State == 3) {
|
||
|
||
TwResult = Scan_CloseDSM( pUserMem );
|
||
|
||
if (TwResult == TWRC_SUCCESS) {
|
||
pUserMem->State = 2;
|
||
Verbose(( "entering state 2\n" ));
|
||
}
|
||
}
|
||
|
||
if (pUserMem->hWndTwain) {
|
||
DestroyWindow( pUserMem->hWndTwain );
|
||
}
|
||
|
||
SetEvent( pUserMem->hEventQuit );
|
||
|
||
WaitForSingleObject( pUserMem->hThread, INFINITE );
|
||
|
||
if (pUserMem->hTwain) {
|
||
FreeLibrary( pUserMem->hTwain );
|
||
}
|
||
|
||
CloseHandle( pUserMem->hThread );
|
||
}
|
||
|
||
|
||
#if 0
|
||
BOOL
|
||
SetCapability(
|
||
PUSERMEM pUserMem,
|
||
USHORT Capability,
|
||
USHORT Type,
|
||
LPVOID Value
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
TW_CAPABILITY TwCapability;
|
||
TW_ONEVALUE *TwOneValue;
|
||
TW_FIX32 *TwFix32;
|
||
|
||
|
||
|
||
TwCapability.Cap = Capability;
|
||
TwCapability.ConType = TWON_ONEVALUE;
|
||
TwCapability.hContainer = GlobalAlloc( GHND, sizeof(TW_ONEVALUE) );
|
||
|
||
TwOneValue = (TW_ONEVALUE*) GlobalLock( TwCapability.hContainer );
|
||
|
||
TwOneValue->ItemType = Type;
|
||
|
||
if (Type == TWTY_FIX32) {
|
||
TwFix32 = (TW_FIX32*)Value;
|
||
CopyMemory( &TwOneValue->Item, TwFix32, sizeof(TW_FIX32) );
|
||
} else {
|
||
TwOneValue->Item = (DWORD)Value;
|
||
}
|
||
|
||
GlobalUnlock( TwCapability.hContainer );
|
||
|
||
//
|
||
// bugbug called in opendatasource
|
||
//
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_CAPABILITY,
|
||
MSG_SET,
|
||
(TW_MEMREF) &TwCapability
|
||
);
|
||
|
||
GlobalFree( TwCapability.hContainer );
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "Could not set capability 0x%04x\n", Capability ));
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
#else
|
||
BOOL
|
||
SetCapability(
|
||
PUSERMEM pUserMem,
|
||
USHORT Capability,
|
||
USHORT Type,
|
||
LPVOID Value
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
TW_CAPABILITY TwCapability;
|
||
TW_ONEVALUE *TwOneValue;
|
||
TW_FIX32 *TwFix32;
|
||
|
||
|
||
|
||
TwCapability.Cap = Capability;
|
||
TwCapability.ConType = TWON_ONEVALUE;
|
||
TwCapability.hContainer = GlobalAlloc( GHND, sizeof(TW_ONEVALUE) );
|
||
|
||
TwOneValue = (TW_ONEVALUE*) GlobalLock( TwCapability.hContainer );
|
||
|
||
TwOneValue->ItemType = Type;
|
||
|
||
if (Type == TWTY_FIX32) {
|
||
TwFix32 = (TW_FIX32*)Value;
|
||
CopyMemory( &TwOneValue->Item, TwFix32, sizeof(TW_FIX32) );
|
||
} else {
|
||
TwOneValue->Item = PtrToUlong(Value);
|
||
}
|
||
|
||
GlobalUnlock( TwCapability.hContainer );
|
||
|
||
//
|
||
// bugbug called in opendatasource
|
||
//
|
||
TwResult = Scan_ControlSet(pUserMem, DAT_CAPABILITY, &TwCapability);
|
||
|
||
GlobalFree( TwCapability.hContainer );
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "Could not set capability 0x%04x\n", Capability ));
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
|
||
float
|
||
FIX32ToFloat(
|
||
TW_FIX32 fix32
|
||
)
|
||
{
|
||
float floater;
|
||
floater = (float) fix32.Whole + (float) fix32.Frac / (float) 65536.0;
|
||
return floater;
|
||
}
|
||
|
||
|
||
BOOL
|
||
OpenDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_IDENTITY * TwIdentity
|
||
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
|
||
Verbose(( "entering OpenDataSource, state = %d\n", pUserMem->State ));
|
||
|
||
if (pUserMem->State == 3) {
|
||
|
||
//
|
||
// open the data source
|
||
//
|
||
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_IDENTITY,
|
||
MSG_OPENDS,
|
||
(TW_MEMREF) TwIdentity
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
return FALSE;
|
||
}
|
||
|
||
pUserMem->State = 4;
|
||
Verbose(( "entering state 4\n" ));
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
BOOL
|
||
Scan_SetCapabilities(
|
||
PUSERMEM pUserMem
|
||
)
|
||
{
|
||
//
|
||
// set the capabilities
|
||
//
|
||
|
||
SetCapability( pUserMem, CAP_XFERCOUNT, TWTY_INT16, (LPVOID)1 );
|
||
SetCapability( pUserMem, ICAP_PIXELTYPE, TWTY_INT16, (LPVOID)TWPT_BW );
|
||
SetCapability( pUserMem, ICAP_BITDEPTH, TWTY_INT16, (LPVOID)1 );
|
||
SetCapability( pUserMem, ICAP_BITORDER, TWTY_INT16, (LPVOID)TWBO_MSBFIRST );
|
||
SetCapability( pUserMem, ICAP_PIXELFLAVOR, TWTY_INT16, (LPVOID)TWPF_VANILLA );
|
||
SetCapability( pUserMem, ICAP_XFERMECH, TWTY_INT16, (LPVOID)TWSX_MEMORY );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
EnableDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_USERINTERFACE *TwUserInterface
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
|
||
if (pUserMem->State == 4) {
|
||
|
||
ResetEvent( pUserMem->hEventXfer );
|
||
|
||
//
|
||
// enable the data source's user interface
|
||
//
|
||
|
||
pUserMem->TwainCancelled = FALSE;
|
||
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_USERINTERFACE,
|
||
MSG_ENABLEDS,
|
||
(TW_MEMREF) TwUserInterface
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_ENABLEDS (DAT_USERINTERFACE) failed, ec=%d\n",TwResult ));
|
||
return FALSE;
|
||
}
|
||
|
||
pUserMem->State = 5;
|
||
|
||
Verbose(( "entering state 5\n" ));
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL
|
||
DisableDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_USERINTERFACE * TwUserInterface
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
|
||
Verbose(( "entering DisableDataSource, state = %d\n",pUserMem->State ));
|
||
|
||
if (pUserMem->State == 5) {
|
||
|
||
//
|
||
// disable the data source
|
||
//
|
||
|
||
TwResult = CallTwainDataSource(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_USERINTERFACE,
|
||
MSG_DISABLEDS,
|
||
(TW_MEMREF) TwUserInterface
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_DISABLEDS (DAT_USERINTERFACE) failed, ec = %d\n", TwResult ));
|
||
return FALSE;
|
||
}
|
||
|
||
pUserMem->State = 4;
|
||
|
||
Verbose(( "entering state 4\n" ));
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
CloseDataSource(
|
||
PUSERMEM pUserMem,
|
||
TW_IDENTITY * TwIdentity
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
|
||
Verbose(( "entering CloseDataSource, state = %d\n",pUserMem->State ));
|
||
|
||
if (pUserMem->State == 4) {
|
||
|
||
//
|
||
// close the data source
|
||
//
|
||
|
||
TwResult = CallTwain(
|
||
pUserMem,
|
||
DG_CONTROL,
|
||
DAT_IDENTITY,
|
||
MSG_CLOSEDS,
|
||
(TW_MEMREF) TwIdentity
|
||
);
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_CLOSEDS (DAT_IDENTIFY) failed, ec = %d\n", TwResult ));
|
||
return FALSE;
|
||
}
|
||
|
||
pUserMem->State = 3;
|
||
|
||
Verbose(( "entering state 3\n" ));
|
||
}
|
||
|
||
Verbose(( "leaving CloseDataSource, state = %d\n",pUserMem->State ));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
InitializeTwain(
|
||
PUSERMEM pUserMem
|
||
)
|
||
{
|
||
BOOL Rval = FALSE;
|
||
DWORD TwResult;
|
||
DWORD ThreadId;
|
||
|
||
|
||
HKEY hKey;
|
||
hKey = OpenRegistryKey( HKEY_LOCAL_MACHINE, REGKEY_SOFTWARE, FALSE, REG_READONLY );
|
||
if (hKey) {
|
||
if (GetRegistryDword( hKey, REGVAL_SCANNER_SUPPORT ) != 0) {
|
||
RegCloseKey( hKey );
|
||
return FALSE;
|
||
}
|
||
RegCloseKey( hKey );
|
||
}
|
||
|
||
pUserMem->State = 1;
|
||
Verbose(( "entering state 1\n" ));
|
||
|
||
pUserMem->hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
pUserMem->hEventQuit = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
pUserMem->hEventXfer = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
|
||
pUserMem->hThread = CreateThread(
|
||
NULL,
|
||
0,
|
||
(LPTHREAD_START_ROUTINE)TwainMessagePumpThread,
|
||
pUserMem,
|
||
0,
|
||
&ThreadId
|
||
);
|
||
if (!pUserMem->hThread) {
|
||
goto exit;
|
||
}
|
||
|
||
WaitForSingleObject( pUserMem->hEvent, INFINITE );
|
||
|
||
if (pUserMem->hWndTwain == NULL) {
|
||
goto exit;
|
||
}
|
||
|
||
pUserMem->hTwain = LoadLibrary( L"twain_32.dll" );
|
||
if (pUserMem->hTwain) {
|
||
pUserMem->pDsmEntry = (DSMENTRYPROC) GetProcAddress( pUserMem->hTwain, "DSM_Entry" );
|
||
}
|
||
|
||
if (pUserMem->pDsmEntry == NULL) {
|
||
goto exit;
|
||
}
|
||
|
||
pUserMem->State = 2;
|
||
|
||
Verbose(( "entering state 2\n" ));
|
||
|
||
//
|
||
// open the data source manager
|
||
//
|
||
|
||
pUserMem->AppId.Id = 0;
|
||
pUserMem->AppId.Version.MajorNum = 1;
|
||
pUserMem->AppId.Version.MinorNum = 0;
|
||
pUserMem->AppId.Version.Language = TWLG_USA;
|
||
pUserMem->AppId.Version.Country = TWCY_USA;
|
||
strcpy( pUserMem->AppId.Version.Info, "Fax Print Wizard" );
|
||
pUserMem->AppId.ProtocolMajor = TWON_PROTOCOLMAJOR;
|
||
pUserMem->AppId.ProtocolMinor = TWON_PROTOCOLMINOR;
|
||
pUserMem->AppId.SupportedGroups = DG_IMAGE | DG_CONTROL;
|
||
strcpy( pUserMem->AppId.Manufacturer, "Microsoft" );
|
||
strcpy( pUserMem->AppId.ProductFamily, "Windows" );
|
||
strcpy( pUserMem->AppId.ProductName, "Windows" );
|
||
|
||
TwResult = Scan_OpenDSM( pUserMem );
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_OPENDSM (DAT_PARENT) failed, ec = %d\n", TwResult ));
|
||
goto exit;
|
||
}
|
||
|
||
pUserMem->State = 3;
|
||
|
||
Verbose(( "entering state 3\n" ));
|
||
|
||
//
|
||
// select the default data source
|
||
//
|
||
|
||
TwResult = Scan_GetDefault(pUserMem, &pUserMem->DataSource);
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GETDEFAULT (DAT_IDENTITY) failed, ec = %d\n", TwResult ));
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// return success
|
||
//
|
||
|
||
Rval = TRUE;
|
||
pUserMem->TwainAvail = TRUE;
|
||
|
||
exit:
|
||
|
||
if (!Rval) {
|
||
|
||
//
|
||
// part of the initialization failed
|
||
// so lets clean everything up before exiting
|
||
//
|
||
|
||
TerminateTwain( pUserMem );
|
||
}
|
||
|
||
return Rval;
|
||
}
|
||
|
||
|
||
DWORD
|
||
ScanningThread(
|
||
PUSERMEM pUserMem
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
TW_SETUPMEMXFER TwSetupMemXfer;
|
||
TW_IMAGEMEMXFER TwImageMemXfer;
|
||
TW_PENDINGXFERS TwPendingXfers;
|
||
TW_USERINTERFACE TwUserInterface;
|
||
TW_IMAGEINFO TwImageInfo;
|
||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
TIFF_HEADER TiffHdr;
|
||
DWORD FileBytes = 0;
|
||
DWORD BytesWritten;
|
||
LPBYTE Buffer1 = NULL;
|
||
LPBYTE CurrBuffer;
|
||
LPBYTE p = NULL;
|
||
DWORD LineSize;
|
||
DWORD i;
|
||
DWORD Lines;
|
||
LPBYTE ScanBuffer = NULL;
|
||
DWORD IfdOffset;
|
||
DWORD NextIfdSeekPoint;
|
||
WORD NumDirEntries;
|
||
DWORD DataOffset;
|
||
BOOL FirstTime = TRUE;
|
||
|
||
|
||
Verbose(( "Entering ScanningThread, state = %d\n", pUserMem->State ));
|
||
pUserMem->TwainActive = TRUE;
|
||
|
||
if (pUserMem->State == 5) {
|
||
|
||
while (pUserMem->State == 5) {
|
||
//
|
||
// wait for the MSG_XFERREADY message to be
|
||
// delivered to the message pump. this moves
|
||
// us to state 6
|
||
//
|
||
|
||
WaitForSingleObject( pUserMem->hEventXfer, INFINITE );
|
||
ResetEvent( pUserMem->hEventXfer );
|
||
Verbose(( "hEventXfer signalled\n" ));
|
||
if (pUserMem->TwainCancelled) {
|
||
Verbose(( "twain cancelled\n" ));
|
||
TwUserInterface.ShowUI = FALSE;
|
||
TwUserInterface.ModalUI = FALSE;
|
||
TwUserInterface.hParent = NULL;
|
||
Scan_DisableDS(pUserMem, &TwUserInterface);
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// get the image info
|
||
//
|
||
|
||
TwResult = Scan_ImageGet(pUserMem,DAT_IMAGEINFO,&TwImageInfo);
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GET (DAT_IMAGEINFO) failed, ec=%d\n", TwResult ));
|
||
goto exit;
|
||
}
|
||
|
||
//
|
||
// we only allow monochrome images
|
||
//
|
||
|
||
if (TwImageInfo.BitsPerPixel > 1) {
|
||
|
||
DisplayMessageDialog( NULL,
|
||
MB_ICONASTERISK | MB_OK | MB_SETFOREGROUND,
|
||
IDS_SCAN_ERROR_TITLE,
|
||
IDS_SCAN_ERROR_BW );
|
||
|
||
//
|
||
// go back to state 5
|
||
//
|
||
|
||
TwResult = Scan_ControlReset(pUserMem,DAT_PENDINGXFERS,&TwPendingXfers);
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_RESET (DAT_PENDINGXFERS) failed, ec=%d\n", TwResult ));
|
||
goto exit;
|
||
}
|
||
|
||
} else {
|
||
pUserMem->State = 6;
|
||
Verbose(( "entering state 6\n" ));
|
||
}
|
||
}
|
||
|
||
//
|
||
// setup the memory buffer sizes
|
||
//
|
||
|
||
TwResult = Scan_ControlGet(pUserMem,DAT_SETUPMEMXFER, &TwSetupMemXfer);
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_GET (DAT_SETUPMEMXFER) failed, ec=%d\n", TwResult ));
|
||
goto exit;
|
||
}
|
||
|
||
Buffer1 = (LPBYTE) MemAlloc( TwSetupMemXfer.Preferred );
|
||
|
||
TwImageMemXfer.Compression = TWON_DONTCARE16;
|
||
TwImageMemXfer.BytesPerRow = TWON_DONTCARE32;
|
||
TwImageMemXfer.Columns = TWON_DONTCARE32;
|
||
TwImageMemXfer.Rows = TWON_DONTCARE32;
|
||
TwImageMemXfer.XOffset = TWON_DONTCARE32;
|
||
TwImageMemXfer.YOffset = TWON_DONTCARE32;
|
||
TwImageMemXfer.BytesWritten = TWON_DONTCARE32;
|
||
TwImageMemXfer.Memory.Flags = TWMF_APPOWNS | TWMF_POINTER;
|
||
TwImageMemXfer.Memory.Length = TwSetupMemXfer.Preferred;
|
||
TwImageMemXfer.Memory.TheMem = Buffer1;
|
||
}
|
||
|
||
Verbose(( "begin transferring image... " ));
|
||
Verbose(( "entering state 7, TwResult = %d\n", TwResult ));
|
||
|
||
while (TwResult != TWRC_XFERDONE) {
|
||
try_again:
|
||
pUserMem->State = 7;
|
||
|
||
TwResult = Scan_ImageGet(pUserMem,DAT_IMAGEMEMXFER,&TwImageMemXfer);
|
||
|
||
if (TwResult == 0) {
|
||
if (ScanBuffer == NULL) {
|
||
ScanBuffer = VirtualAlloc(
|
||
NULL,
|
||
TwImageMemXfer.BytesPerRow * (TwImageInfo.ImageLength + 16),
|
||
MEM_COMMIT,
|
||
PAGE_READWRITE
|
||
);
|
||
if (ScanBuffer == NULL) {
|
||
goto exit;
|
||
}
|
||
p = ScanBuffer;
|
||
}
|
||
CopyMemory( p, Buffer1, TwImageMemXfer.BytesWritten );
|
||
p += TwImageMemXfer.BytesWritten;
|
||
FileBytes += TwImageMemXfer.BytesWritten;
|
||
} else if ( TwResult != TWRC_XFERDONE) {
|
||
Verbose(( "MGS_GET (DAT_IMAGEMEMXFER) failed, ec = %d ", TwResult ));
|
||
goto exit;
|
||
}
|
||
}
|
||
|
||
|
||
Assert( TwResult == TWRC_XFERDONE );
|
||
|
||
if (!ScanBuffer || !FileBytes) {
|
||
//
|
||
// we didn't really scan anything...
|
||
//
|
||
Verbose(( "asked for tranfer, but nothing was transferred\n" ));
|
||
if (FirstTime) {
|
||
FirstTime = FALSE;
|
||
goto try_again;
|
||
}
|
||
|
||
TwResult = Scan_ControlEndXfer(pUserMem,DAT_PENDINGXFERS, &TwPendingXfers);
|
||
|
||
pUserMem->State = 5;
|
||
|
||
//
|
||
// disable the data source's user interface
|
||
//
|
||
|
||
TwUserInterface.ShowUI = FALSE;
|
||
TwUserInterface.ModalUI = FALSE;
|
||
TwUserInterface.hParent = NULL;
|
||
|
||
Scan_DisableDS(pUserMem, &TwUserInterface);
|
||
|
||
pUserMem->State = 4;
|
||
|
||
Verbose(( "entering state 4\n" ));
|
||
|
||
goto exit;
|
||
}
|
||
|
||
pUserMem->PageCount += 1;
|
||
|
||
Verbose(( "...finished transferring image\n" ));
|
||
|
||
hFile = CreateFile(
|
||
pUserMem->FileName,
|
||
GENERIC_READ | GENERIC_WRITE,
|
||
0,
|
||
NULL,
|
||
OPEN_EXISTING,
|
||
0,
|
||
NULL
|
||
);
|
||
if (hFile == INVALID_HANDLE_VALUE) {
|
||
Verbose(( "CreateFile failed, ec=%d\n", GetLastError() ));
|
||
goto exit;
|
||
}
|
||
|
||
if (pUserMem->PageCount == 1) {
|
||
TiffHdr.Identifier = TIFF_LITTLEENDIAN;
|
||
TiffHdr.Version = TIFF_VERSION;
|
||
TiffHdr.IFDOffset = 0;
|
||
WriteFile( hFile, &TiffHdr, sizeof(TiffHdr), &BytesWritten, NULL );
|
||
} else {
|
||
ReadFile( hFile, &TiffHdr, sizeof(TiffHdr), &BytesWritten, NULL );
|
||
NextIfdSeekPoint = TiffHdr.IFDOffset;
|
||
while (NextIfdSeekPoint) {
|
||
SetFilePointer( hFile, NextIfdSeekPoint, NULL, FILE_BEGIN );
|
||
ReadFile( hFile, &NumDirEntries, sizeof(NumDirEntries), &BytesWritten, NULL );
|
||
SetFilePointer( hFile, NumDirEntries*sizeof(TIFF_TAG), NULL, FILE_CURRENT );
|
||
ReadFile( hFile, &NextIfdSeekPoint, sizeof(NextIfdSeekPoint), &BytesWritten, NULL );
|
||
}
|
||
}
|
||
|
||
NextIfdSeekPoint = SetFilePointer( hFile, 0, NULL, FILE_CURRENT ) - sizeof(NextIfdSeekPoint);
|
||
SetFilePointer( hFile, 0, NULL, FILE_END );
|
||
DataOffset = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
|
||
|
||
LineSize = TwImageInfo.ImageWidth / 8;
|
||
LineSize += (TwImageInfo.ImageWidth % 8) ? 1 : 0;
|
||
|
||
Lines = FileBytes / TwImageMemXfer.BytesPerRow;
|
||
|
||
CurrBuffer = ScanBuffer;
|
||
for (i=0; i<Lines; i++) {
|
||
WriteFile( hFile, CurrBuffer, LineSize, &BytesWritten, NULL );
|
||
CurrBuffer += TwImageMemXfer.BytesPerRow;
|
||
}
|
||
|
||
IfdOffset = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
|
||
|
||
FaxIFDTemplate.xresNum = (DWORD) FIX32ToFloat( TwImageInfo.XResolution );
|
||
FaxIFDTemplate.yresNum = (DWORD) FIX32ToFloat( TwImageInfo.YResolution );
|
||
|
||
FaxIFDTemplate.ifd[IFD_PAGENUMBER].DataOffset = MAKELONG( pUserMem->PageCount-1, 0);
|
||
FaxIFDTemplate.ifd[IFD_IMAGEWIDTH].DataOffset = TwImageInfo.ImageWidth;
|
||
FaxIFDTemplate.ifd[IFD_IMAGELENGTH].DataOffset = Lines;
|
||
FaxIFDTemplate.ifd[IFD_ROWSPERSTRIP].DataOffset = Lines;
|
||
FaxIFDTemplate.ifd[IFD_STRIPBYTECOUNTS].DataOffset = Lines * LineSize;
|
||
FaxIFDTemplate.ifd[IFD_STRIPOFFSETS].DataOffset = DataOffset;
|
||
FaxIFDTemplate.ifd[IFD_XRESOLUTION].DataOffset = IfdOffset + FIELD_OFFSET( FAXIFD, xresNum );
|
||
FaxIFDTemplate.ifd[IFD_YRESOLUTION].DataOffset = IfdOffset + FIELD_OFFSET( FAXIFD, yresNum );
|
||
FaxIFDTemplate.ifd[IFD_SOFTWARE].DataOffset = IfdOffset + FIELD_OFFSET( FAXIFD, software );
|
||
|
||
WriteFile( hFile, &FaxIFDTemplate, sizeof(FaxIFDTemplate), &BytesWritten, NULL );
|
||
|
||
SetFilePointer( hFile, NextIfdSeekPoint, NULL, FILE_BEGIN );
|
||
WriteFile( hFile, &IfdOffset, sizeof(DWORD), &BytesWritten, NULL );
|
||
|
||
//
|
||
// end the transfer
|
||
//
|
||
|
||
TwResult = Scan_ControlEndXfer(pUserMem,DAT_PENDINGXFERS, &TwPendingXfers);
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
Verbose(( "MSG_ENDXFER (DAT_PENDINGXFERS) failed, ec=%d\n", TwResult ));
|
||
goto exit;
|
||
}
|
||
|
||
pUserMem->State = 5;
|
||
Verbose(( "entering state 5\n" ));
|
||
|
||
//
|
||
// disable the data source's user interface
|
||
//
|
||
|
||
TwUserInterface.ShowUI = FALSE;
|
||
TwUserInterface.ModalUI = FALSE;
|
||
TwUserInterface.hParent = NULL;
|
||
|
||
Scan_DisableDS(pUserMem, &TwUserInterface);
|
||
|
||
pUserMem->State = 4;
|
||
|
||
Verbose(( "entering state 4\n" ));
|
||
|
||
PostMessage( pUserMem->hDlgScan, WM_PAGE_COMPLETE, 0, 0 );
|
||
|
||
exit:
|
||
if (ScanBuffer) {
|
||
VirtualFree( ScanBuffer, 0, MEM_RELEASE);
|
||
}
|
||
|
||
if (hFile != INVALID_HANDLE_VALUE) {
|
||
CloseHandle( hFile );
|
||
}
|
||
|
||
MemFree( Buffer1 );
|
||
|
||
Verbose(( "leaving scanning thread, state = %d\n", pUserMem->State ));
|
||
|
||
pUserMem->TwainActive = FALSE;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
BOOL
|
||
EnumerateDataSources(
|
||
PUSERMEM pUserMem,
|
||
HWND ComboBox,
|
||
HWND StaticText
|
||
)
|
||
{
|
||
DWORD TwResult;
|
||
TW_IDENTITY TwIdentity;
|
||
TW_IDENTITY *pDataSource;
|
||
DWORD i;
|
||
DWORD Count = 0;
|
||
|
||
|
||
TwResult = Scan_GetFirst( pUserMem, &TwIdentity );
|
||
|
||
if (TwResult != TWRC_SUCCESS) {
|
||
return FALSE;
|
||
}
|
||
|
||
do {
|
||
i = (DWORD)SendMessageA( ComboBox, CB_ADDSTRING, 0, (LPARAM)TwIdentity.ProductName );
|
||
|
||
pDataSource = (TW_IDENTITY*) MemAlloc( sizeof(TW_IDENTITY) );
|
||
if (pDataSource) {
|
||
CopyMemory( pDataSource, &TwIdentity, sizeof(TW_IDENTITY) );
|
||
SendMessageA( ComboBox, CB_SETITEMDATA, i, (LPARAM)pDataSource );
|
||
}
|
||
|
||
Count += 1;
|
||
|
||
TwResult = Scan_GetNext( pUserMem, &TwIdentity );
|
||
|
||
} while (TwResult == 0);
|
||
|
||
i = (DWORD)SendMessageA( ComboBox, CB_FINDSTRINGEXACT, 0, (LPARAM)pUserMem->DataSource.ProductName );
|
||
if (i == CB_ERR) {
|
||
i = 0;
|
||
}
|
||
|
||
SendMessageA( ComboBox, CB_SETCURSEL, i, 0 );
|
||
|
||
if (Count == 1) {
|
||
EnableWindow( StaticText, FALSE );
|
||
EnableWindow( ComboBox, FALSE );
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
INT_PTR
|
||
ScanWizProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog procedure for the first wizard page: entering subject and note information
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
|
||
Return Value:
|
||
|
||
Depends on the message parameter
|
||
|
||
--*/
|
||
|
||
{
|
||
PUSERMEM pUserMem;
|
||
HANDLE hThread;
|
||
DWORD ThreadId;
|
||
WCHAR TempPath[MAX_PATH];
|
||
//TW_PENDINGXFERS TwPendingXfers;
|
||
TW_USERINTERFACE TwUserInterface;
|
||
|
||
|
||
pUserMem = (PUSERMEM) GetWindowLongPtr(hDlg, DWLP_USER);
|
||
|
||
switch (message) {
|
||
|
||
case WM_INITDIALOG:
|
||
lParam = ((PROPSHEETPAGE *) lParam)->lParam;
|
||
pUserMem = (PUSERMEM) lParam;
|
||
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
|
||
if (GetEnvironmentVariable(L"NTFaxSendNote", TempPath, sizeof(TempPath)) == 0 || TempPath[0] != L'1') {
|
||
pUserMem->TwainAvail = FALSE;
|
||
return TRUE;
|
||
}
|
||
if (pUserMem->TwainAvail) {
|
||
EnumerateDataSources( pUserMem, GetDlgItem( hDlg, IDC_DATA_SOURCE ), GetDlgItem( hDlg, IDC_STATIC_DATA_SOURCE) );
|
||
} else {
|
||
pUserMem->TwainAvail = FALSE;
|
||
return TRUE;
|
||
}
|
||
if (GetTempPath( sizeof(TempPath)/sizeof(WCHAR), TempPath )) {
|
||
if (GetTempFileName( TempPath, L"fax", 0, pUserMem->FileName )) {
|
||
SetEnvironmentVariable( L"ScanTifName", pUserMem->FileName );
|
||
}
|
||
}
|
||
pUserMem->hDlgScan = hDlg;
|
||
return TRUE;
|
||
|
||
case WM_NOTIFY:
|
||
switch ( ((NMHDR *) lParam)->code) {
|
||
case PSN_SETACTIVE:
|
||
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_NEXT);
|
||
if (!pUserMem->TwainAvail) {
|
||
//
|
||
// jump to next page
|
||
//
|
||
SetWindowLongPtr( hDlg, DWLP_MSGRESULT, -1 );
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
break;
|
||
case PSN_WIZNEXT:
|
||
|
||
if (!pUserMem->PageCount) {
|
||
//
|
||
// we didn't actually scan any pages
|
||
//
|
||
DeleteFile( pUserMem->FileName ) ;
|
||
SetEnvironmentVariable( L"ScanTifName", NULL );
|
||
|
||
}
|
||
|
||
//Scan_CloseDS( pUserMem, &pUserMem->DataSource );
|
||
CloseDataSource( pUserMem, &pUserMem->DataSource );
|
||
Assert(pUserMem->State == 3);
|
||
pUserMem->State = 3;
|
||
|
||
SetWindowLongPtr( hDlg, DWLP_MSGRESULT, IDD_WIZARD_FAXOPTS );
|
||
return TRUE;
|
||
break;
|
||
case PSN_QUERYCANCEL:
|
||
//
|
||
// we didn't actually scan any pages
|
||
//
|
||
DeleteFile( pUserMem->FileName ) ;
|
||
if (pUserMem->TwainActive) {
|
||
|
||
TwUserInterface.ShowUI = FALSE;
|
||
TwUserInterface.ModalUI = FALSE;
|
||
TwUserInterface.hParent = NULL;
|
||
DisableDataSource( pUserMem, &TwUserInterface );
|
||
|
||
}
|
||
|
||
CloseDataSource( pUserMem, &pUserMem->DataSource );
|
||
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
case WM_PAGE_COMPLETE:
|
||
SetDlgItemInt( hDlg, IDC_PAGE_COUNT, pUserMem->PageCount, FALSE );
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
if (HIWORD(wParam) == CBN_SELCHANGE) {
|
||
TW_IDENTITY *pDataSource;
|
||
DWORD i;
|
||
|
||
|
||
i = (DWORD)SendDlgItemMessage( hDlg, IDC_DATA_SOURCE, CB_GETCURSEL, 0, 0 );
|
||
pDataSource = (TW_IDENTITY *) SendDlgItemMessage( hDlg, IDC_DATA_SOURCE, CB_GETITEMDATA, i, 0 );
|
||
|
||
CopyMemory( &pUserMem->DataSource, pDataSource, sizeof(TW_IDENTITY) );
|
||
}
|
||
|
||
if (HIWORD(wParam) == BN_CLICKED) {
|
||
|
||
//
|
||
// scan a page
|
||
//
|
||
TW_USERINTERFACE TwUserInterface;
|
||
|
||
TwUserInterface.ShowUI = TRUE;
|
||
TwUserInterface.ModalUI = TRUE;
|
||
TwUserInterface.hParent = GetParent(pUserMem->hDlgScan);
|
||
|
||
if ( !pUserMem->TwainActive
|
||
&& Scan_OpenDS( pUserMem, &pUserMem->DataSource)
|
||
//&& Scan_SetCapabilities( pUserMem )
|
||
&& Scan_EnableDS( pUserMem, &TwUserInterface )) {
|
||
|
||
EnableWindow( GetDlgItem( hDlg, IDC_DATA_SOURCE ), FALSE );
|
||
|
||
hThread = CreateThread(
|
||
NULL,
|
||
0,
|
||
(LPTHREAD_START_ROUTINE)ScanningThread,
|
||
pUserMem,
|
||
0,
|
||
&ThreadId
|
||
);
|
||
if (hThread) {
|
||
CloseHandle( hThread );
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case WM_DESTROY:
|
||
if (pUserMem->TwainAvail) {
|
||
TerminateTwain( pUserMem );
|
||
}
|
||
break;
|
||
/* case WM_ACTIVATE:
|
||
if (LOWORD(wParam) == WA_ACTIVE) {
|
||
if (!pUserMem->TwainActive) {
|
||
EnableWindow( hDlg, TRUE );
|
||
return TRUE;
|
||
}
|
||
} */
|
||
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
LPTSTR
|
||
FormatTime(
|
||
WORD Hour,
|
||
WORD Minute,
|
||
LPTSTR Buffer,
|
||
DWORD BufferSize)
|
||
{
|
||
SYSTEMTIME SystemTime;
|
||
|
||
ZeroMemory(&SystemTime,sizeof(SystemTime));
|
||
SystemTime.wHour = Hour;
|
||
SystemTime.wMinute = Minute;
|
||
GetTimeFormat(LOCALE_USER_DEFAULT,
|
||
TIME_NOSECONDS,
|
||
&SystemTime,
|
||
NULL,
|
||
Buffer,
|
||
BufferSize
|
||
);
|
||
|
||
return Buffer;
|
||
}
|
||
|
||
|
||
INT_PTR
|
||
FinishWizProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog procedure for the last wizard page:
|
||
give user a chance to confirm or cancel the dialog.
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
|
||
Return Value:
|
||
|
||
Depends on the message parameter
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PUSERMEM pUserMem;
|
||
TCHAR RecipientNameBuffer[64];
|
||
TCHAR RecipientNumberBuffer[64];
|
||
TCHAR TmpTimeBuffer[64];
|
||
TCHAR TimeBuffer[64];
|
||
TCHAR SendTimeBuffer[64];
|
||
TCHAR NoneBuffer[64];
|
||
LPTSTR SenderName;
|
||
TCHAR CoverpageBuffer[64];
|
||
LPTSTR Coverpage;
|
||
HKEY hKey;
|
||
|
||
if (! (pUserMem = CommonWizardProc(hDlg, message, wParam, lParam, PSWIZB_BACK|PSWIZB_FINISH)) )
|
||
return FALSE;
|
||
|
||
switch (message) {
|
||
|
||
|
||
case WM_NOTIFY:
|
||
if (((NMHDR *) lParam)->code != PSN_SETACTIVE) break;
|
||
case WM_INITDIALOG:
|
||
LoadString(ghInstance,IDS_NONE,NoneBuffer,sizeof(NoneBuffer)/sizeof(TCHAR) );
|
||
|
||
//
|
||
// large title font on last page
|
||
//
|
||
SetWindowFont(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_READY), pUserMem->hLargeFont, TRUE);
|
||
|
||
//
|
||
// set the sender name if it exists
|
||
//
|
||
if ( (hKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO,TRUE) ) &&
|
||
(SenderName = GetRegistryString(hKey,REGVAL_FULLNAME,TEXT("")) )
|
||
) {
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_FROM, SenderName );
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_FROM),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_FROM),TRUE);
|
||
MemFree(SenderName);
|
||
} else {
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_FROM, NoneBuffer );
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_FROM),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_FROM),FALSE);
|
||
}
|
||
|
||
//
|
||
// set the recipient name
|
||
//
|
||
if (pUserMem->pRecipients && pUserMem->pRecipients->pNext) {
|
||
//
|
||
// more than one user, just put "Multiple" in the text
|
||
//
|
||
LoadString(ghInstance,IDS_MULTIPLE_RECIPIENTS,RecipientNameBuffer,sizeof(RecipientNameBuffer)/sizeof(TCHAR) );
|
||
LoadString(ghInstance,IDS_MULTIPLE_RECIPIENTS,RecipientNumberBuffer,sizeof(RecipientNumberBuffer)/sizeof(TCHAR) );
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_TO, RecipientNameBuffer );
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_NUMBER, RecipientNumberBuffer );
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_TO),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_TO),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_NUMBER),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_NUMBER),FALSE);
|
||
} else {
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_TO, pUserMem->pRecipients->pName );
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_NUMBER, pUserMem->pRecipients->pAddress );
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_TO),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_TO),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_NUMBER),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_NUMBER),TRUE);
|
||
}
|
||
|
||
//
|
||
// when to send
|
||
//
|
||
switch (pUserMem->devmode.dmPrivate.whenToSend) {
|
||
case SENDFAX_AT_TIME:
|
||
LoadString(ghInstance,IDS_SEND_SPECIFIC,TmpTimeBuffer,sizeof(TmpTimeBuffer)/sizeof(TCHAR) );
|
||
wsprintf(SendTimeBuffer,
|
||
TmpTimeBuffer,
|
||
FormatTime(pUserMem->devmode.dmPrivate.sendAtTime.Hour,
|
||
pUserMem->devmode.dmPrivate.sendAtTime.Minute,
|
||
TimeBuffer,
|
||
sizeof(TimeBuffer)) );
|
||
break;
|
||
case SENDFAX_AT_CHEAP:
|
||
LoadString(ghInstance,IDS_SEND_DISCOUNT,SendTimeBuffer,sizeof(SendTimeBuffer)/sizeof(TCHAR) );
|
||
break;
|
||
case SENDFAX_ASAP:
|
||
LoadString(ghInstance,IDS_SEND_ASAP,SendTimeBuffer,sizeof(SendTimeBuffer)/sizeof(TCHAR) );
|
||
};
|
||
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_TIME, SendTimeBuffer );
|
||
|
||
//
|
||
// Coverpage
|
||
//
|
||
if (pUserMem->devmode.dmPrivate.sendCoverPage) {
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_COVERPG),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_SUBJECT),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_COVERPG),TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_SUBJECT),TRUE);
|
||
|
||
//
|
||
// format the coverpage for display to the user
|
||
//
|
||
|
||
// drop path
|
||
Coverpage = _tcsrchr(pUserMem->coverPage,TEXT(PATH_SEPARATOR));
|
||
if (!Coverpage) {
|
||
Coverpage = pUserMem->coverPage;
|
||
} else {
|
||
Coverpage++;
|
||
}
|
||
_tcscpy(CoverpageBuffer,Coverpage);
|
||
|
||
// crop file extension
|
||
Coverpage = _tcschr(CoverpageBuffer,TEXT(FILENAME_EXT));
|
||
|
||
if (Coverpage && *Coverpage) {
|
||
*Coverpage = (TCHAR) NUL;
|
||
}
|
||
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_COVERPG, CoverpageBuffer );
|
||
if (pUserMem->pSubject) {
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_SUBJECT, pUserMem->pSubject );
|
||
} else {
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_SUBJECT),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_SUBJECT),FALSE);
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_SUBJECT, NoneBuffer );
|
||
}
|
||
} else {
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_COVERPG, NoneBuffer );
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_SUBJECT, NoneBuffer );
|
||
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_COVERPG),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_SUBJECT),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_COVERPG),FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_SUBJECT),FALSE);
|
||
}
|
||
|
||
//
|
||
// Billing Code
|
||
//
|
||
if (pUserMem->devmode.dmPrivate.billingCode[0]) {
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_BILLING), TRUE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_BILLING),TRUE);
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_BILLING, pUserMem->devmode.dmPrivate.billingCode );
|
||
} else {
|
||
EnableWindow(GetDlgItem(hDlg,IDC_STATIC_WIZ_CONGRATS_BILLING), FALSE);
|
||
EnableWindow(GetDlgItem(hDlg,IDC_WIZ_CONGRATS_BILLING), FALSE);
|
||
SetDlgItemText(hDlg, IDC_WIZ_CONGRATS_BILLING, NoneBuffer );
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
default:
|
||
return FALSE;
|
||
} ;
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
INT_PTR
|
||
WelcomeWizProc(
|
||
HWND hDlg,
|
||
UINT message,
|
||
WPARAM wParam,
|
||
LPARAM lParam
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dialog procedure for the last wizard page:
|
||
give user a chance to confirm or cancel the dialog.
|
||
|
||
Arguments:
|
||
|
||
hDlg - Identifies the wizard page
|
||
message - Specifies the message
|
||
wParam - Specifies additional message-specific information
|
||
lParam - Specifies additional message-specific information
|
||
|
||
Return Value:
|
||
|
||
Depends on the message parameter
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PUSERMEM pUserMem;
|
||
|
||
if (! (pUserMem = CommonWizardProc(hDlg, message, wParam, lParam, PSWIZB_NEXT)))
|
||
return FALSE;
|
||
|
||
switch (message) {
|
||
|
||
case WM_INITDIALOG:
|
||
//
|
||
// set the large fonts
|
||
//
|
||
SetWindowFont(GetDlgItem(hDlg,IDC_WIZ_WELCOME_TITLE), pUserMem->hLargeFont, TRUE);
|
||
|
||
//
|
||
// show this text only if we're running the send wizard
|
||
//
|
||
if (!GetEnvironmentVariable(TEXT("NTFaxSendNote"), NULL, 0)) {
|
||
MyHideWindow(GetDlgItem(hDlg,IDC_WIZ_WELCOME_FAXSEND) );
|
||
MyHideWindow(GetDlgItem(hDlg,IDC_WIZ_WELCOME_FAXSEND_CONT) );
|
||
}
|
||
|
||
return TRUE;
|
||
} ;
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
GetFakeRecipientInfo(
|
||
PUSERMEM pUserMem,
|
||
DWORD nRecipients
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Skip send fax wizard and get faked recipient information from the registry
|
||
|
||
Arguments:
|
||
|
||
pUserMem - Points to the user mode memory structure
|
||
nRecipients - Total number of faked recipient entries
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
LPTSTR pRecipientEntry;
|
||
DWORD index;
|
||
TCHAR buffer[MAX_STRING_LEN];
|
||
BOOL success = FALSE;
|
||
HKEY hRegKey;
|
||
|
||
//
|
||
// Retrieve information about the next fake recipient entry
|
||
//
|
||
|
||
Verbose(("Send Fax Wizard skipped...\n"));
|
||
|
||
if (hRegKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO, REG_READWRITE))
|
||
index = GetRegistryDword(hRegKey, REGVAL_STRESS_INDEX);
|
||
else
|
||
index = 0;
|
||
|
||
if (index >= nRecipients)
|
||
index = 0;
|
||
|
||
wsprintf(buffer, TEXT("FakeRecipient%d"), index);
|
||
pRecipientEntry = GetPrinterDataStr(pUserMem->hPrinter, buffer);
|
||
|
||
if (hRegKey) {
|
||
|
||
//
|
||
// Update an index so that next time around we'll pick a different fake recipient
|
||
//
|
||
|
||
if (++index >= nRecipients)
|
||
index = 0;
|
||
|
||
SetRegistryDword(hRegKey, REGVAL_STRESS_INDEX, index);
|
||
RegCloseKey(hRegKey);
|
||
}
|
||
|
||
//
|
||
// Each fake recipient entry is a REG_MULTI_SZ of the following format:
|
||
// recipient name #1
|
||
// recipient fax number #1
|
||
// recipient name #2
|
||
// recipient fax number #2
|
||
// ...
|
||
//
|
||
|
||
if (pRecipientEntry) {
|
||
|
||
__try {
|
||
|
||
PRECIPIENT pRecipient;
|
||
LPTSTR pName, pAddress, p = pRecipientEntry;
|
||
|
||
while (*p) {
|
||
|
||
pName = p;
|
||
pAddress = pName + _tcslen(pName) + 1;
|
||
p = pAddress + _tcslen(pAddress) + 1;
|
||
|
||
pRecipient = MemAllocZ(sizeof(RECIPIENT));
|
||
pName = DuplicateString(pName);
|
||
|
||
pAddress = DuplicateString(pAddress);
|
||
|
||
if (!pRecipient || !pName || !pAddress) {
|
||
|
||
Error(("Invalid fake recipient information\n"));
|
||
MemFree(pRecipient);
|
||
MemFree(pName);
|
||
MemFree(pAddress);
|
||
break;
|
||
}
|
||
|
||
pRecipient->pNext = pUserMem->pRecipients;
|
||
pUserMem->pRecipients = pRecipient;
|
||
pRecipient->pName = pName;
|
||
pRecipient->pAddress = pAddress;
|
||
}
|
||
|
||
} __finally {
|
||
|
||
if (success = (pUserMem->pRecipients != NULL)) {
|
||
|
||
//
|
||
// Determine whether a cover page should be used
|
||
//
|
||
|
||
LPTSTR pCoverPage;
|
||
|
||
pCoverPage = GetPrinterDataStr(pUserMem->hPrinter, TEXT("FakeCoverPage"));
|
||
|
||
if (pUserMem->devmode.dmPrivate.sendCoverPage = (pCoverPage != NULL))
|
||
CopyString(pUserMem->coverPage, pCoverPage, MAX_PATH);
|
||
|
||
MemFree(pCoverPage);
|
||
}
|
||
}
|
||
}
|
||
|
||
MemFree(pRecipientEntry);
|
||
return success;
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
SendFaxWizard(
|
||
PUSERMEM pUserMem
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Present the Send Fax Wizard to the user. This is invoked
|
||
during CREATEDCPRE document event.
|
||
|
||
Arguments:
|
||
|
||
pUserMem - Points to the user mode memory structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error or the user pressed Cancel.
|
||
|
||
--*/
|
||
#ifdef FAX_SCAN_ENABLED
|
||
#define NUM_PAGES 6 // Number of wizard pages
|
||
#else
|
||
#define NUM_PAGES 5 // Number of wizard pages
|
||
#endif
|
||
|
||
{
|
||
PROPSHEETPAGE *ppsp;
|
||
PROPSHEETHEADER psh;
|
||
INT result;
|
||
DWORD nRecipients;
|
||
HDC hdc;
|
||
int i;
|
||
LOGFONT LargeFont;
|
||
NONCLIENTMETRICS ncm = {0};
|
||
TCHAR FontName[100];
|
||
TCHAR FontSize[30];
|
||
int iFontSize;
|
||
DWORD ThreadId;
|
||
HANDLE hThread;
|
||
|
||
|
||
Assert(pUserMem->pRecipients == NULL);
|
||
|
||
//
|
||
// A shortcut to skip fax wizard for debugging/testing purposes
|
||
//
|
||
|
||
if (nRecipients = GetPrinterDataDWord(pUserMem->hPrinter, TEXT("FakeRecipientCount"), 0))
|
||
return GetFakeRecipientInfo(pUserMem, nRecipients);
|
||
|
||
Verbose(("Presenting Send Fax Wizard...\n"));
|
||
|
||
if (! (ppsp = MemAllocZ(sizeof(PROPSHEETPAGE) * NUM_PAGES))) {
|
||
|
||
Error(("Memory allocation failed\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// fire off a thread to do some slow stuff later on in the wizard.
|
||
//
|
||
pUserMem->hFaxSvcEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||
pUserMem->hTapiEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||
#ifdef FAX_SCAN_ENABLED
|
||
pUserMem->hTwainEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
|
||
|
||
if (!pUserMem->hFaxSvcEvent || !pUserMem->hTapiEvent || !pUserMem->hTwainEvent) {
|
||
Error(("CreateEvent for async events failed\n"));
|
||
return FALSE;
|
||
}
|
||
#else
|
||
if (!pUserMem->hFaxSvcEvent || !pUserMem->hTapiEvent) {
|
||
Error(("CreateEvent for async events failed\n"));
|
||
return FALSE;
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
hThread = CreateThread(NULL,0,AsyncWizardThread,pUserMem,0,&ThreadId);
|
||
if (hThread) {
|
||
CloseHandle(hThread);
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Fill out one PROPSHEETPAGE structure for every page:
|
||
// The first page is a welcome page
|
||
// The first page is for choose the fax recipient
|
||
// The second page is for choosing cover page, subject and note
|
||
// The third page is for entering time to send and other options
|
||
// The fourth page is for scanning pages
|
||
// The last page gives the user a chance to confirm or cancel the dialog
|
||
//
|
||
|
||
FillInPropertyPage( ppsp, IDD_WIZARD_WELCOME, WelcomeWizProc, pUserMem ,0,0);
|
||
FillInPropertyPage( ppsp+1, IDD_WIZARD_CHOOSE_WHO, RecipientWizProc, pUserMem ,IDS_WIZ_RECIPIENT_TITLE,IDS_WIZ_RECIPIENT_SUB);
|
||
|
||
//
|
||
// set second page title correctly if we're running as faxsend or from file print
|
||
if (!GetEnvironmentVariable(TEXT("NTFaxSendNote"), NULL, 0)) {
|
||
FillInPropertyPage( ppsp+2, IDD_WIZARD_CHOOSE_CP, CoverPageWizProc, pUserMem ,IDS_WIZ_COVERPAGE_TITLE_2,IDS_WIZ_COVERPAGE_SUB_2 );
|
||
}
|
||
else {
|
||
FillInPropertyPage( ppsp+2, IDD_WIZARD_CHOOSE_CP, CoverPageWizProc, pUserMem ,IDS_WIZ_COVERPAGE_TITLE_1,IDS_WIZ_COVERPAGE_SUB_1 );
|
||
}
|
||
|
||
|
||
#ifdef FAX_SCAN_ENABLED
|
||
FillInPropertyPage( ppsp+3, IDD_WIZARD_SCAN, ScanWizProc, pUserMem ,IDS_WIZ_SCAN_TITLE,IDS_WIZ_SCAN_SUB);
|
||
FillInPropertyPage( ppsp+4, IDD_WIZARD_FAXOPTS, FaxOptsWizProc, pUserMem ,IDS_WIZ_FAXOPTS_TITLE,IDS_WIZ_FAXOPTS_SUB);
|
||
FillInPropertyPage( ppsp+5, IDD_WIZARD_CONGRATS, FinishWizProc, pUserMem ,0,0);
|
||
#else
|
||
FillInPropertyPage( ppsp+3, IDD_WIZARD_FAXOPTS, FaxOptsWizProc, pUserMem ,IDS_WIZ_FAXOPTS_TITLE,IDS_WIZ_FAXOPTS_SUB);
|
||
FillInPropertyPage( ppsp+4, IDD_WIZARD_CONGRATS, FinishWizProc, pUserMem ,0,0);
|
||
#endif
|
||
|
||
//
|
||
// Fill out the PROPSHEETHEADER structure
|
||
//
|
||
|
||
ZeroMemory(&psh, sizeof(psh));
|
||
|
||
psh.dwSize = sizeof(PROPSHEETHEADER);
|
||
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_WIZARD | PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER;
|
||
psh.hwndParent = GetActiveWindow();
|
||
psh.hInstance = ghInstance;
|
||
psh.hIcon = NULL;
|
||
psh.pszCaption = TEXT("");
|
||
psh.nPages = NUM_PAGES;
|
||
psh.nStartPage = 0;
|
||
psh.ppsp = ppsp;
|
||
psh.pszbmHeader = MAKEINTRESOURCE(IDB_FAXWIZ_WATERMARK);
|
||
psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK_16);
|
||
|
||
if(hdc = GetDC(NULL)) {
|
||
if(GetDeviceCaps(hdc,BITSPIXEL) >= 8) {
|
||
psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK_256);
|
||
}
|
||
ReleaseDC(NULL,hdc);
|
||
}
|
||
|
||
|
||
//
|
||
// get the large fonts for wizard97
|
||
//
|
||
ncm.cbSize = sizeof(ncm);
|
||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
||
|
||
CopyMemory((LPVOID* )&LargeFont,(LPVOID *) &ncm.lfMessageFont,sizeof(LargeFont) );
|
||
|
||
|
||
LoadString(ghInstance,IDS_LARGEFONT_NAME,FontName,sizeof(FontName)/sizeof(TCHAR) );
|
||
LoadString(ghInstance,IDS_LARGEFONT_SIZE,FontSize,sizeof(FontSize)/sizeof(TCHAR) );
|
||
|
||
iFontSize = _tcstoul( FontSize, NULL, 10 );
|
||
|
||
// make sure we at least have some basic font
|
||
if (*FontName == 0 || iFontSize == 0) {
|
||
lstrcpy(FontName,TEXT("MS Shell Dlg") );
|
||
iFontSize = 18;
|
||
}
|
||
|
||
lstrcpy(LargeFont.lfFaceName, FontName);
|
||
LargeFont.lfWeight = FW_BOLD;
|
||
|
||
if (hdc = GetDC(NULL)) {
|
||
LargeFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * iFontSize / 72);
|
||
pUserMem->hLargeFont = CreateFontIndirect(&LargeFont);
|
||
ReleaseDC( NULL, hdc);
|
||
}
|
||
|
||
|
||
//
|
||
// Display the wizard pages
|
||
//
|
||
if (PropertySheet(&psh) > 0)
|
||
result = pUserMem->finishPressed;
|
||
else
|
||
result = FALSE;
|
||
|
||
//
|
||
// Cleanup properly before exiting
|
||
//
|
||
|
||
//
|
||
// free headings
|
||
//
|
||
for (i = 0; i< NUM_PAGES; i++) {
|
||
MemFree( (PVOID)(ppsp+i)->pszHeaderTitle );
|
||
MemFree( (PVOID)(ppsp+i)->pszHeaderSubTitle );
|
||
}
|
||
|
||
if (pUserMem->lpWabInit) {
|
||
|
||
UnInitializeWAB( pUserMem->lpWabInit);
|
||
}
|
||
|
||
DeinitTapiService();
|
||
MemFree(ppsp);
|
||
|
||
DeleteObject(pUserMem->hLargeFont);
|
||
|
||
FreeCoverPageInfo(pUserMem->pCPInfo);
|
||
pUserMem->pCPInfo = NULL;
|
||
|
||
#ifdef FAX_SCAN_ENABLED
|
||
//
|
||
// if the user pressed cancel, cleanup leftover scanned file.
|
||
//
|
||
if (!pUserMem->finishPressed && pUserMem->TwainAvail && pUserMem->FileName) {
|
||
DeleteFile( pUserMem->FileName ) ;
|
||
SetEnvironmentVariable( L"ScanTifName", NULL );
|
||
}
|
||
#endif
|
||
|
||
Verbose(("Wizard finished...\n"));
|
||
return result;
|
||
}
|