/*++ Copyright (c) 1996 Microsoft Corporation Module Name: docprop.c Abstract: Implemetation of DDI entry points: DrvDocumentPropertySheets DrvDocumentProperties DrvAdvancedDocumentProperties DrvConvertDevMode Environment: Fax driver user interface Revision History: 01/09/96 -davidx- Created it. mm/dd/yy -author- description --*/ #include "faxui.h" #include "forms.h" #include "libproto.h" #include "faxhelp.h" INT_PTR FaxOptionsProc(HWND, UINT, WPARAM, LPARAM); LONG SimpleDocumentProperties(PDOCUMENTPROPERTYHEADER); BOOL GenerateFormsList(PUIDATA); BOOL AddDocPropPages(PUIDATA, LPTSTR); LPTSTR GetHelpFilename(PUIDATA); BOOL SaveUserInfo(PDRVDEVMODE); BOOL SaveUserInfo(PDRVDEVMODE pDM) { HKEY hKey; if ((hKey = GetUserInfoRegKey(REGKEY_FAX_USERINFO,FALSE))) { SetRegistryString( hKey, REGVAL_BILLING_CODE, pDM->dmPrivate.billingCode ); SetRegistryString( hKey, REGVAL_MAILBOX , pDM->dmPrivate.emailAddress ); RegCloseKey(hKey); return TRUE; } return FALSE; } LONG DrvDocumentPropertySheets( PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam ) /*++ Routine Description: Display "Document Properties" property sheets Arguments: pPSUIInfo - Pointer to a PROPSHEETUI_INFO structure lParam - Pointer to a DOCUMENTPROPERTYHEADER structure Return Value: > 0 if successful, <= 0 if failed [Note:] Please refer to WinNT DDK/SDK documentation for more details. --*/ { PDOCUMENTPROPERTYHEADER pDPHdr; PUIDATA pUiData; int iRet = -1; // // Do not execute any code before this initialization // if(!InitializeDll()) { return iRet; } // // Validate input parameters // pPSUIInfo = NULL is a special case: don't need to display the dialog // if (! (pDPHdr = (PDOCUMENTPROPERTYHEADER) (pPSUIInfo ? pPSUIInfo->lParamInit : lParam))) { Assert(FALSE); return -1; } if (pPSUIInfo == NULL) { return SimpleDocumentProperties(pDPHdr); } Verbose(("DrvDocumentPropertySheets: %d\n", pPSUIInfo->Reason)); // // Create a UIDATA structure if necessary // pUiData = (pPSUIInfo->Reason == PROPSHEETUI_REASON_INIT) ? FillUiData(pDPHdr->hPrinter, pDPHdr->pdmIn) : (PUIDATA) pPSUIInfo->UserData; if (!ValidUiData(pUiData)) { goto exit; } // // Handle various cases for which this function might be called // switch (pPSUIInfo->Reason) { case PROPSHEETUI_REASON_INIT: pUiData->hasPermission = ((pDPHdr->fMode & DM_NOPERMISSION) == 0); pUiData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet; pUiData->hComPropSheet = pPSUIInfo->hComPropSheet; if (pDPHdr->fMode & DM_USER_DEFAULT) { pUiData->configDefault = TRUE; } // // Find online help filename // GetHelpFilename(pUiData); // // Add our pages to the property sheet // if (GenerateFormsList(pUiData) && AddDocPropPages(pUiData, pDPHdr->pszPrinterName)) { pPSUIInfo->UserData = (DWORD_PTR) pUiData; pPSUIInfo->Result = CPSUI_CANCEL; iRet = 1; goto exit; } // // Clean up properly in case of an error // HeapDestroy(pUiData->hheap); break; case PROPSHEETUI_REASON_GET_INFO_HEADER: { PPROPSHEETUI_INFO_HEADER pPSUIHdr; pPSUIHdr = (PPROPSHEETUI_INFO_HEADER) lParam; pPSUIHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW; pPSUIHdr->pTitle = pDPHdr->pszPrinterName; pPSUIHdr->hInst = g_hResource; pPSUIHdr->IconID = IDI_CPSUI_PRINTER2; } iRet = 1; goto exit; case PROPSHEETUI_REASON_SET_RESULT: // // Copy the new devmode back into the output buffer provided by the caller // Always return the smaller of current and input devmode // { PSETRESULT_INFO pSRInfo = (PSETRESULT_INFO) lParam; Verbose(("Set result: %d\n", pSRInfo->Result)); if (pSRInfo->Result == CPSUI_OK && (pDPHdr->fMode & (DM_COPY|DM_UPDATE))) { if (!ConvertDevmodeOut( (PDEVMODE) &pUiData->devmode, pDPHdr->pdmIn, pDPHdr->pdmOut, pDPHdr->cbOut)) { goto exit; } SaveUserInfo(&pUiData->devmode); } pPSUIInfo->Result = pSRInfo->Result; } iRet = 1; goto exit; case PROPSHEETUI_REASON_DESTROY: // // Cleanup properly before exiting // HeapDestroy(pUiData->hheap); iRet = 1; goto exit; } exit: return iRet; } // DrvDocumentPropertySheets LONG DoDocumentProperties( HWND hwnd, HANDLE hPrinter, LPTSTR pPrinterName, PDEVMODE pdmOutput, PDEVMODE pdmInput, DWORD fMode ) /*++ Arguments: hwnd - Handle to the parent window of the document properties dialog box. hPrinter - Handle to a printer object. pPrinterName - Points to a null-terminated string that specifies the name of the device for which the document properties dialog box should be displayed. pdmOutput - Points to a DEVMODE structure that receives the document properties data specified by the user. pdmInput - Points to a DEVMODE structure that initializes the dialog box controls. This parameter can be NULL. fmode - Specifies a mask of flags that determine which operations the function performs. Return Value: > 0 if successful = 0 if canceled < 0 if error --*/ { DOCUMENTPROPERTYHEADER docPropHdr; DWORD result; // // Initialize a DOCUMENTPROPERTYHEADER structure // memset(&docPropHdr, 0, sizeof(docPropHdr)); docPropHdr.cbSize = sizeof(docPropHdr); docPropHdr.hPrinter = hPrinter; docPropHdr.pszPrinterName = pPrinterName; docPropHdr.pdmIn = pdmInput; docPropHdr.pdmOut = pdmOutput; docPropHdr.fMode = fMode; // // Don't need to get compstui involved when the dialog is not displayed // if ((fMode & DM_PROMPT) == 0) return SimpleDocumentProperties(&docPropHdr); CallCompstui(hwnd, DrvDocumentPropertySheets, (LPARAM) &docPropHdr, &result); return result; } LONG DrvDocumentProperties( HWND hwnd, HANDLE hPrinter, LPTSTR pPrinterName, PDEVMODE pdmOutput, PDEVMODE pdmInput, DWORD fMode ) /*++ Routine Description: Set the public members of a DEVMODE structure for a print document [Note:] Please refer to WinNT DDK/SDK documentation for more details. This is the old entry point for the spooler. Even though no one should be using this, do it for compatibility. --*/ { LONG result; Verbose(("Entering DrvDocumentProperties: fMode = %x...\n", fMode)); // // Do not execute any code before this initialization // if(!InitializeDll()) { return IDCANCEL; } // // Check if caller is asking querying for size // if (fMode == 0 || pdmOutput == NULL) return sizeof(DRVDEVMODE); // // Call the common routine shared with DrvAdvancedDocumentProperties // result = DoDocumentProperties(hwnd, hPrinter, pPrinterName, pdmOutput, pdmInput, fMode); return (result > 0) ? IDOK : (result == 0) ? IDCANCEL : result; } LONG DrvAdvancedDocumentProperties( HWND hwnd, HANDLE hPrinter, LPTSTR pPrinterName, PDEVMODE pdmOutput, PDEVMODE pdmInput ) /*++ Routine Description: Set the private members of a DEVMODE structure. In this release, this function is almost identical to DrvDocumentProperties above with a few minor exceptions [Note:] Please refer to WinNT DDK/SDK documentation for more details. This is the old entry point for the spooler. Even though no one should be using this, do it for compatibility. --*/ { Verbose(("Entering DrvAdvancedDocumentProperties...\n")); // // Do not execute any code before this initialization // if(!InitializeDll()) { return -1; } // // Return the number of bytes required if pdmOutput is NULL // if (pdmOutput == NULL) return sizeof(DRVDEVMODE); // // Otherwise, call the common routine shared with DrvDocumentProperties // return DoDocumentProperties(hwnd, hPrinter, pPrinterName, pdmOutput, pdmInput, DM_COPY|DM_PROMPT|DM_ADVANCED) > 0; } BOOL DrvConvertDevMode( LPTSTR pPrinterName, PDEVMODE pdmIn, PDEVMODE pdmOut, PLONG pcbNeeded, DWORD fMode ) /*++ Routine Description: Use by SetPrinter and GetPrinter to convert devmodes Arguments: pPrinterName - Points to printer name string pdmIn - Points to the input devmode pdmOut - Points to the output devmode buffer pcbNeeded - Specifies the size of output buffer on input On output, this is the size of output devmode fMode - Specifies what function to perform Return Value: TRUE if successful FALSE otherwise and an error code is logged --*/ { static DRIVER_VERSION_INFO versionInfo = { // Current driver version number and private devmode size DRIVER_VERSION, sizeof(DMPRIVATE), // 3.51 driver version number and private devmode size // NOTE: We don't have a 3.51 driver - use current version number and devmode size. DRIVER_VERSION, sizeof(DMPRIVATE) }; INT result; HANDLE hPrinter; Verbose(("Entering DrvConvertDevMode: %x...\n", fMode)); // // Do not execute any code before this initialization // if(!InitializeDll()) { return FALSE; } // // Call a library routine to handle the common cases // result = CommonDrvConvertDevmode(pPrinterName, pdmIn, pdmOut, pcbNeeded, fMode, &versionInfo); // // If not handled by the library routine, we only need to worry // about the case when fMode is CDM_DRIVER_DEFAULT // if (result == CDM_RESULT_NOT_HANDLED && fMode == CDM_DRIVER_DEFAULT) { // // Return driver default devmode // if (OpenPrinter(pPrinterName, &hPrinter, NULL)) { PDRVDEVMODE pdmDefault = (PDRVDEVMODE) pdmOut; DriverDefaultDevmode(pdmDefault, pPrinterName, hPrinter); pdmDefault->dmPrivate.flags |= FAXDM_DRIVER_DEFAULT; result = CDM_RESULT_TRUE; ClosePrinter(hPrinter); } else Error(("OpenPrinter failed: %d\n", GetLastError())); } return (result == CDM_RESULT_TRUE); } LONG SimpleDocumentProperties( PDOCUMENTPROPERTYHEADER pDPHdr ) /*++ Routine Description: Handle simple "Document Properties" where we don't need to display a dialog and therefore don't have to have common UI library involved Arguments: pDPHdr - Points to a DOCUMENTPROPERTYHEADER structure Return Value: > 0 if successful, <= 0 otherwise --*/ { PUIDATA pUiData; int iRet = -1; // // Check if the caller is interested in the size only // pDPHdr->cbOut = sizeof(DRVDEVMODE); if (pDPHdr->fMode == 0 || pDPHdr->pdmOut == NULL) { return pDPHdr->cbOut; } // // Create a UIDATA structure // if (! (pUiData = FillUiData(pDPHdr->hPrinter, pDPHdr->pdmIn))) { return iRet; } // // Copy the devmode back into the output buffer provided by the caller // Always return the smaller of current and input devmode // if (pDPHdr->fMode & (DM_COPY | DM_UPDATE)) { if (ConvertDevmodeOut((PDEVMODE) &pUiData->devmode, pDPHdr->pdmIn, pDPHdr->pdmOut, pDPHdr->cbOut)) { iRet = 1; } } HeapDestroy(pUiData->hheap); return iRet; } BOOL AddDocPropPages( PUIDATA pUiData, LPTSTR pPrinterName ) /*++ Routine Description: Add our "Document Properties" pages to the property sheet Arguments: pUiData - Points to our UIDATA structure pPrinterName - Specifies the printer name Return Value: TRUE if successful, FALSE otherwise --*/ { PROPSHEETPAGE psp = {0}; HANDLE hActCtx; // // "Document Properties" dialog only has one tab - "Fax Options" // psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = 0; psp.hInstance = g_hResource; psp.lParam = (LPARAM) pUiData; psp.pszTemplate = MAKEINTRESOURCE(IDD_DOCPROP); psp.pfnDlgProc = FaxOptionsProc; // // Need to add a Activation Context so that Compstui will create the property page using // ComCtl v6 (i.e. so it will / can be Themed). // hActCtx = GetFaxActivationContext(); if (INVALID_HANDLE_VALUE != hActCtx) { pUiData->pfnComPropSheet(pUiData->hComPropSheet, CPSFUNC_SET_FUSION_CONTEXT, (LPARAM)hActCtx, 0); } pUiData->hFaxOptsPage = (HANDLE) pUiData->pfnComPropSheet(pUiData->hComPropSheet, CPSFUNC_ADD_PROPSHEETPAGE, (LPARAM) &psp, 0); return (pUiData->hFaxOptsPage != NULL); } BOOL GenerateFormsList( PUIDATA pUiData ) /*++ Routine Description: Generate the list of forms supported by the fax driver Arguments: pUiData - Points to our UIDATA structure Return Value: TRUE if successful, FALSE if there is an error --*/ { PFORM_INFO_1 pFormsDB; DWORD cForms, count; // // Get a list of forms in the forms database // pFormsDB = GetFormsDatabase(pUiData->hPrinter, &cForms); if (pFormsDB == NULL || cForms == 0) { Error(("Couldn't get system forms\n")); return FALSE; } // // Enumerate the list of supported forms // pUiData->cForms = count = EnumPaperSizes(NULL, pFormsDB, cForms, DC_PAPERS); Assert(count != GDI_ERROR); pUiData->pFormNames = HeapAlloc(pUiData->hheap, 0, sizeof(TCHAR) * count * CCHPAPERNAME); pUiData->pPapers = HeapAlloc(pUiData->hheap, 0, sizeof(WORD) * count); if (!pUiData->pFormNames || !pUiData->pPapers) { if(pUiData->pFormNames) { HeapFree(pUiData->hheap, 0, pUiData->pFormNames); } if(pUiData->pPapers) { HeapFree(pUiData->hheap, 0, pUiData->pPapers); } MemFree(pFormsDB); return FALSE; } EnumPaperSizes(pUiData->pFormNames, pFormsDB, cForms, DC_PAPERNAMES); EnumPaperSizes(pUiData->pPapers, pFormsDB, cForms, DC_PAPERS); MemFree(pFormsDB); return TRUE; } LPTSTR GetHelpFilename( PUIDATA pUiData ) /*++ Routine Description: Return the driver's help filename string Arguments: pUiData - Points to our UIDATA structure Return Value: Pointer to the driver help filename, NULL if error --*/ { PDRIVER_INFO_3 pDriverInfo3 = NULL; PVOID pHelpFile = NULL; // // Attempt to get help file name using the new DRIVER_INFO_3 // if (pDriverInfo3 = MyGetPrinterDriver(pUiData->hPrinter, 3)) { if ((pDriverInfo3->pHelpFile != NULL) && (pHelpFile = HeapAlloc(pUiData->hheap, 0, SizeOfString(pDriverInfo3->pHelpFile)))) { _tcscpy(pHelpFile, pDriverInfo3->pHelpFile); } MemFree(pDriverInfo3); } // // If DRIVER_INFO_3 isn't supported, get help file name the old fashion way // if (pHelpFile == NULL) { if (!(pHelpFile = HeapAlloc(pUiData->hheap, 0, SizeOfString(FAXCFG_HELP_FILENAME))) ) { pHelpFile = NULL; } else { _tcscpy(pHelpFile, FAXCFG_HELP_FILENAME); } } Verbose(("Driver help filename: %ws\n", pHelpFile)); return (pUiData->pHelpFile = pHelpFile); }