Sample Code
Windows Driver Samples/ Generic Text-Only Driver/ C++/ ui/ ttyui.cpp/
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright 1997-2003 Microsoft Corporation. All Rights Reserved. // // FILE: TTYUI.cpp // // PURPOSE: Main file for TTY UI user mode module. // #include <WINDOWS.H> #include <ASSERT.H> #include <PRSHT.H> #include <COMPSTUI.H> #include <WINDDIUI.H> #include <PRINTOEM.H> #include <stdlib.h> #include <TCHAR.H> #include <WINSPOOL.H> #include "resource.h" #include "TTYUI.h" #include "ttyuihlp.h" #include "debug.h" #include <INTSAFE.H> #include <STRSAFE.H> // This indicates to Prefast that this is a usermode driver file. _Analysis_mode_(_Analysis_code_type_user_driver_); //////////////////////////////////////////////////////// // INTERNAL GLOBALS //////////////////////////////////////////////////////// HINSTANCE ghInstance = NULL; //////////////////////////////////////////////////////// // INTERNAL PROTOTYPES //////////////////////////////////////////////////////// INT_PTR CALLBACK DevPropPageProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DevPropPage2Proc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam); BOOL HexStringToBinary( _In_reads_bytes_(nHexLen) LPBYTE lpHex, _Out_writes_bytes_(nBinaryLen) LPBYTE lpBinary, DWORD nHexLen, // num bytes in src buffer lpHex. DWORD nBinaryLen, // num bytes in dest buffer lpBinary _Out_ DWORD *lpnBinBytes // num bytes written to dest buffer lpBinary ); BOOL BinaryToHexString( _In_reads_bytes_(nBinaryLen) LPBYTE lpBinary, _Out_writes_bytes_(nHexLen) LPBYTE lpHex, DWORD nBinaryLen, // num bytes to process in lpBinary DWORD nHexLen // num bytes in dest buffer lpHex. ); void VinitMyStuff( PGLOBALSTRUCT pGlobals, // points to private structure for static storage BOOL bSave // save to registry instead of reading from... ) ; void vSetGetCodePage(HWND hDlg, INT *piCodePage, BOOL bMode) ; // TRUE: Set, FALSE: Get code page. BOOL PrintUIHelp( UINT uMsg, HWND hDlg, WPARAM wParam, LPARAM lParam, PGLOBALSTRUCT pGlobals ) ; BOOL InitHelpfileName(PGLOBALSTRUCT pGlobals) ; PWSTR PwstrCreateQualifiedName( HANDLE hHeap, PCWSTR pDir, PCWSTR pFile ); ////////////////////////////////////////////////////////////////////////// // Function: DllMain // // Description: Dll entry point for initialization.. // // // Comments: // // ////////////////////////////////////////////////////////////////////////// BOOL WINAPI DllMain(HINSTANCE hInst, WORD wReason, LPVOID lpReserved) { UNREFERENCED_PARAMETER(lpReserved); switch(wReason) { case DLL_PROCESS_ATTACH: // VERBOSE(DLLTEXT("Process attach.\r\n")); // Save DLL instance for use later. ghInstance = hInst; break; case DLL_THREAD_ATTACH: // VERBOSE(DLLTEXT("Thread attach.\r\n")); break; case DLL_PROCESS_DETACH: // VERBOSE(DLLTEXT("Process detach.\r\n")); break; case DLL_THREAD_DETACH: // VERBOSE(DLLTEXT("Thread detach.\r\n")); break; } return TRUE; } BOOL TextUIGetInfo(IN DWORD dwInfo, OUT PVOID pBuffer, IN DWORD cbSize, OUT PDWORD pcbNeeded) { // VERBOSE(DLLTEXT("OEMGetInfo(%#x) entry.\r\n"), dwInfo); // Validate parameters. if( ( (OEMGI_GETSIGNATURE != dwInfo) && (OEMGI_GETINTERFACEVERSION != dwInfo) && (OEMGI_GETVERSION != dwInfo) ) || (NULL == pcbNeeded) ) { WARNING(ERRORTEXT("TextUIGetInfo() ERROR_INVALID_PARAMETER.\r\n")); // Did not write any bytes. if(NULL != pcbNeeded) *pcbNeeded = 0; // Return invalid parameter error. SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } // Need/wrote 4 bytes. *pcbNeeded = 4; // Validate buffer size. Minimum size is four bytes. if( (NULL == pBuffer) || (4 > cbSize) ) { WARNING(ERRORTEXT("TextUIGetInfo() ERROR_INSUFFICIENT_BUFFER.\r\n")); // Return insufficient buffer size. SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } // Write information to buffer. switch(dwInfo) { case OEMGI_GETSIGNATURE: *(LPDWORD)pBuffer = OEM_SIGNATURE; break; case OEMGI_GETINTERFACEVERSION: *(LPDWORD)pBuffer = PRINTER_OEMINTF_VERSION; break; case OEMGI_GETVERSION: *(LPDWORD)pBuffer = OEM_VERSION; break; } return TRUE; } LRESULT TextUIDevicePropertySheets(PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam) { LRESULT lResult = CPSUI_CANCEL ; LRESULT lRet; VERBOSE(DLLTEXT("TextUIDevicePropertySheets() entry.\r\n")); // Validate parameters. if( (NULL == pPSUIInfo) || (PROPSHEETUI_INFO_VERSION != pPSUIInfo->Version) ) { VERBOSE(ERRORTEXT("TextUIDevicePropertySheets() ERROR_INVALID_PARAMETER.\r\n")); // Return invalid parameter error. SetLastError(ERROR_INVALID_PARAMETER); return -1; } // Do action. switch(pPSUIInfo->Reason) { case PROPSHEETUI_REASON_INIT: { PROPSHEETPAGE Page; // Init property page. memset(&Page, 0, sizeof(PROPSHEETPAGE)); Page.dwSize = sizeof(PROPSHEETPAGE); Page.dwFlags = PSP_DEFAULT; Page.hInstance = ghInstance; Page.pszTemplate = MAKEINTRESOURCE(IDD_DEV_PROPPAGE); Page.pfnDlgProc = DevPropPageProc; // allocate structure to hold static data for // PropertySheet Dialog function pPSUIInfo->UserData = Page.lParam = (LPARAM)HeapAlloc( ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hOEMHeap, HEAP_ZERO_MEMORY , sizeof(GLOBALSTRUCT) ); if(!Page.lParam) return -1; // HeapAlloc failed. ((PGLOBALSTRUCT)Page.lParam)->hPrinter = ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hPrinter ; ((PGLOBALSTRUCT)Page.lParam)->hOEMHeap = ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hOEMHeap ; // Add property sheets. lResult = (pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet, CPSFUNC_ADD_PROPSHEETPAGE, (LPARAM)&Page, 0) > 0 ? TRUE : FALSE); Page.pszTemplate = MAKEINTRESOURCE(IDD_DEV_PROPPAGE2); Page.pfnDlgProc = DevPropPage2Proc; // Add another property sheet. if(lResult) { lResult = (pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet, CPSFUNC_ADD_PROPSHEETPAGE, (LPARAM)&Page, 0) > 0 ? TRUE : FALSE); } pPSUIInfo->Result = lResult; lRet = (lResult) ? 1 : -1 ; } break; case PROPSHEETUI_REASON_GET_INFO_HEADER: { PPROPSHEETUI_INFO_HEADER pHeader = (PPROPSHEETUI_INFO_HEADER) lParam; pHeader->pTitle = (LPTSTR)PROP_TITLE; lResult = TRUE; lRet = (lResult) ? 1 : -1 ; } break; case PROPSHEETUI_REASON_GET_ICON: // No icon lResult = 0; lRet = (lResult) ? 1 : -1 ; break; case PROPSHEETUI_REASON_SET_RESULT: { PSETRESULT_INFO pInfo = (PSETRESULT_INFO) lParam; lResult = pInfo->Result; pPSUIInfo->Result = lResult; lRet = 1 ; } break; case PROPSHEETUI_REASON_DESTROY: if(pPSUIInfo->UserData) HeapFree( ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hOEMHeap, 0 , (void *)pPSUIInfo->UserData ); lResult = TRUE; lRet = (lResult) ? 1 : -1 ; break; default: lRet = -1 ; } // pPSUIInfo->Result = lResult; return lRet; } ////////////////////////////////////////////////////////////////////////// // Function: DevPropPageProc // // Description: Generic property page procedure. // // // // // Comments: // // ////////////////////////////////////////////////////////////////////////// INT_PTR CALLBACK DevPropPageProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { // RECT rcMargin ; // temp storage during conversions. PGLOBALSTRUCT pGlobals; // points to private structure for static storage PREGSTRUCT pMyStuff; // sebset of pGlobals TCHAR szIntString[MAX_INT_FIELD_WIDTH + 2] = { 0 }; BYTE szString[MAX_CMD_LEN + 1] = { 0 }; BOOL bStatus = FALSE; switch (uiMsg) { case WM_INITDIALOG: pGlobals = (PGLOBALSTRUCT) ((PROPSHEETPAGE *)lParam)->lParam ; if(!pGlobals) return FALSE ; pMyStuff = &pGlobals->regStruct ; // at WM_INITDIALOG time, lParam points to PROPSHEETPAGE. // extract and save ptr to GLOBALSTRUCT for future ref. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pGlobals) ; VinitMyStuff( pGlobals, FALSE) ; SendDlgItemMessage(hDlg, IDC_EDIT10, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT11, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT12, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT13, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT14, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0); SendDlgItemMessage(hDlg, IDC_EDIT15, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0); SendDlgItemMessage(hDlg, IDC_EDIT16, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0); SendDlgItemMessage(hDlg, IDC_EDIT17, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0); if(pMyStuff->bIsMM) CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1) ; else { CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2) ; // convert RECT values to inches pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 100, 254) ; pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 100, 254) ; pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 100, 254) ; pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 100, 254) ; } // convert int to ascii string _itot_s(pMyStuff->rcMargin.left, szIntString, RADIX ) ; SetDlgItemText(hDlg, IDC_EDIT14, szIntString); _itot_s(pMyStuff->rcMargin.top, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT15, szIntString); _itot_s(pMyStuff->rcMargin.right, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT16, szIntString); _itot_s(pMyStuff->rcMargin.bottom, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT17, szIntString); //** init other edit boxes with corresponding command strings from registry if(BinaryToHexString(pMyStuff->BeginJob.strCmd, szString, pMyStuff->BeginJob.dwLen, MAX_CMD_LEN + 1)) SetDlgItemTextA(hDlg, IDC_EDIT10, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->EndJob.strCmd, szString, pMyStuff->EndJob.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT11, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->PaperSelect.strCmd, szString, pMyStuff->PaperSelect.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT12, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->FeedSelect.strCmd, szString, pMyStuff->FeedSelect.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT13, (LPCSTR)szString); break; case WM_NOTIFY: pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ; if(!pGlobals) return FALSE ; pMyStuff = &pGlobals->regStruct ; switch (((LPNMHDR)lParam)->code) // type of notification message { case PSN_SETACTIVE: break; case PSN_KILLACTIVE: // formerly case IDC_BUTTON1: // convert user command to binary and back to // verify proper entry. { //** extract all command strings GetDlgItemTextA(hDlg, IDC_EDIT10, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->BeginJob.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->BeginJob.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT11, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->EndJob.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->EndJob.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT12, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->PaperSelect.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->PaperSelect.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT13, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->FeedSelect.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->FeedSelect.dwLen) ; // reinitialize edit boxes with binary translated strings. if(BinaryToHexString(pMyStuff->BeginJob.strCmd, szString, pMyStuff->BeginJob.dwLen, MAX_CMD_LEN + 1)) SetDlgItemTextA(hDlg, IDC_EDIT10, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->EndJob.strCmd, szString, pMyStuff->EndJob.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT11, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->PaperSelect.strCmd, szString, pMyStuff->PaperSelect.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT12, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->FeedSelect.strCmd, szString, pMyStuff->FeedSelect.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT13, (LPCSTR)szString); } break; case PSN_APPLY: { // MessageBox(hDlg, szString, "TTY settings", MB_OK); // load numbers in edit boxes into rcMargin GetDlgItemText(hDlg, IDC_EDIT14, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.left = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT15, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.top = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT16, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.right = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT17, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.bottom = _ttoi(szIntString) ; if(!pMyStuff->bIsMM ) { // convert RECT values from inches back to mm pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 254, 100) ; pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 254, 100) ; pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 254, 100) ; pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 254, 100) ; } //** extract all command strings GetDlgItemTextA(hDlg, IDC_EDIT10, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->BeginJob.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->BeginJob.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT11, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->EndJob.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->EndJob.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT12, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->PaperSelect.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->PaperSelect.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT13, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->FeedSelect.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->FeedSelect.dwLen) ; // reinitialize edit boxes with binary translated strings. if(BinaryToHexString(pMyStuff->BeginJob.strCmd, szString, pMyStuff->BeginJob.dwLen, MAX_CMD_LEN + 1)) SetDlgItemTextA(hDlg, IDC_EDIT10, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->EndJob.strCmd, szString, pMyStuff->EndJob.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT11, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->PaperSelect.strCmd, szString, pMyStuff->PaperSelect.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT12, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->FeedSelect.strCmd, szString, pMyStuff->FeedSelect.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT13, (LPCSTR)szString); // store MyStuff in registry. VinitMyStuff(pGlobals, TRUE) ; } break; case PSN_RESET: break; } break; case WM_COMMAND: pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ; if(!pGlobals) return FALSE ; pMyStuff = &pGlobals->regStruct ; if(HIWORD(wParam) == EN_CHANGE) // type of notification message { switch(LOWORD(wParam)) { case IDC_EDIT10: case IDC_EDIT11: case IDC_EDIT12: case IDC_EDIT13: case IDC_EDIT14: case IDC_EDIT15: case IDC_EDIT16: case IDC_EDIT17: PropSheet_Changed(GetParent( hDlg ), hDlg); break; default: break; } } switch(LOWORD(wParam)) { case IDC_RADIO1: // convert to MM { if(!pMyStuff->bIsMM ) { // assume all values are inches // convert to mm. and store in edit boxes. // load numbers in edit boxes into rcMargin GetDlgItemText(hDlg, IDC_EDIT14, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.left = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT15, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.top = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT16, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.right = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT17, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.bottom = _ttoi(szIntString) ; // convert RECT values from inches back to mm pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 254, 100) ; pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 254, 100) ; pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 254, 100) ; pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 254, 100) ; // load numbers from rcMargin into edit boxes _itot_s(pMyStuff->rcMargin.left, szIntString, RADIX ) ; SetDlgItemText(hDlg, IDC_EDIT14, szIntString); _itot_s(pMyStuff->rcMargin.top, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT15, szIntString); _itot_s(pMyStuff->rcMargin.right, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT16, szIntString); _itot_s(pMyStuff->rcMargin.bottom, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT17, szIntString); pMyStuff->bIsMM = TRUE ; } } break; case IDC_RADIO2: // convert to inches { if(pMyStuff->bIsMM ) { // assume all values are mm // convert to inches. and store in edit boxes. // load numbers in edit boxes into rcMargin GetDlgItemText(hDlg, IDC_EDIT14, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.left = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT15, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.top = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT16, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.right = _ttoi(szIntString) ; GetDlgItemText(hDlg, IDC_EDIT17, szIntString, MAX_INT_FIELD_WIDTH + 1); pMyStuff->rcMargin.bottom = _ttoi(szIntString) ; // convert RECT values from mm back to inches pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 100, 254) ; pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 100, 254) ; pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 100, 254) ; pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 100, 254) ; // load numbers from rcMargin into edit boxes _itot_s(pMyStuff->rcMargin.left, szIntString, RADIX ) ; SetDlgItemText(hDlg, IDC_EDIT14, szIntString); _itot_s(pMyStuff->rcMargin.top, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT15, szIntString); _itot_s(pMyStuff->rcMargin.right, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT16, szIntString); _itot_s(pMyStuff->rcMargin.bottom, szIntString, RADIX) ; SetDlgItemText(hDlg, IDC_EDIT17, szIntString); pMyStuff->bIsMM = FALSE ; } } break; } break; case WM_HELP: case WM_CONTEXTMENU: pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ; if(!pGlobals) return FALSE ; // pMyStuff = &pGlobals->regStruct ; bStatus = PrintUIHelp(uiMsg, hDlg, wParam, lParam, pGlobals) ; break; } return bStatus ; } void VinitMyStuff( PGLOBALSTRUCT pGlobals, // points to private structure for static storage BOOL bSave // save to registry instead of reading from... ) { PREGSTRUCT pMyStuff; // sebset of pGlobals DWORD dwStatus, cbNeeded, dwType ; LPTSTR pValueName = TEXT("TTY DeviceConfig"); // these strings must match strings in ttyud.cpp - OEMEnablePDEV() pMyStuff = &pGlobals->regStruct ; if(bSave) // save to registry { if(--pGlobals->dwUseCount) return ; // you are the last property page to perform // shutdown routine. Save MyStuff to registry. SetPrinterData( pGlobals->hPrinter, // handle of printer object pValueName, // address of value name REG_BINARY, // flag for value type (LPBYTE)pMyStuff , // address of array that specifies printer data sizeof(REGSTRUCT) // size, in bytes, of array ); return ; } // read from registry if(pGlobals->dwUseCount) { pGlobals->dwUseCount++ ; return ; } dwStatus = GetPrinterData( pGlobals->hPrinter, // handle of printer object saved previously. pValueName, // address of value name &dwType, // address receiving value type (LPBYTE)pMyStuff, // address of array of bytes that receives data sizeof(REGSTRUCT), // size, in bytes, of array &cbNeeded // address of variable // with number of bytes retrieved (or required) ); if (dwStatus != ERROR_SUCCESS || pMyStuff->dwVersion != TTYSTRUCT_VER || dwType != REG_BINARY || cbNeeded != sizeof(REGSTRUCT)) { // Init secret block with defaults pMyStuff->dwVersion = TTYSTRUCT_VER ; // version stamp to avoid incompatible structures. pMyStuff->bIsMM = TRUE ; // default to mm units // read margin values from registry and store into temp RECT pMyStuff->iCodePage = 1252 ; pMyStuff->rcMargin.left = pMyStuff->rcMargin.top = pMyStuff->rcMargin.right = pMyStuff->rcMargin.bottom = 0 ; pMyStuff->BeginJob.dwLen = pMyStuff->EndJob.dwLen = pMyStuff->PaperSelect.dwLen = pMyStuff->FeedSelect.dwLen = pMyStuff->Sel_10_cpi.dwLen = pMyStuff->Sel_12_cpi.dwLen = pMyStuff->Sel_17_cpi.dwLen = pMyStuff->Bold_ON.dwLen = pMyStuff->Bold_OFF.dwLen = pMyStuff->Underline_ON.dwLen = pMyStuff->Underline_OFF.dwLen = 0 ; // more fields here! pMyStuff->dwGlyphBufSiz = pMyStuff->dwSpoolBufSiz = 0 ; pMyStuff->aubGlyphBuf = pMyStuff->aubSpoolBuf = NULL ; } InitHelpfileName(pGlobals) ; pGlobals->dwUseCount = 1 ; return ; } BOOL BinaryToHexString( _In_reads_bytes_(nBinaryLen) LPBYTE lpBinary, _Out_writes_bytes_(nHexLen) LPBYTE lpHex, DWORD nBinaryLen, // num bytes to process in lpBinary DWORD nHexLen // num bytes in dest buffer lpHex. ) { // how do I translate TCHAR to ascii? // use Set GetDlgItemTextA // add NULL termination to lpHex // return FALSE if dest buffer exhausted DWORD dwSrc, dwDst ; BOOL bHexmode = FALSE ; BYTE Nibble ; for(dwSrc = dwDst = 0 ; dwSrc < nBinaryLen ; dwSrc++) { if(lpBinary[dwSrc] < 0x21 || lpBinary[dwSrc] > 0x7e || lpBinary[dwSrc] == '<') { // enter hexmode if not already if(!bHexmode) { if(dwDst + 5 > nHexLen) return(FALSE); lpHex[dwDst++] = '<' ; bHexmode = TRUE ; } else if(dwDst + 4 > nHexLen) return(FALSE); Nibble = (lpBinary[dwSrc] >> 4) & 0x0f ; if(Nibble < 0x0a) lpHex[dwDst++] = '0' + Nibble ; else lpHex[dwDst++] = 'A' + Nibble - 0x0a ; // loNibble Nibble = lpBinary[dwSrc] & 0x0f ; if(Nibble < 0x0a) lpHex[dwDst++] = '0' + Nibble ; else lpHex[dwDst++] = 'A' + Nibble - 0x0a ; } else { // exit hexmode if not already if(bHexmode) { lpHex[dwDst++] = '>' ; bHexmode = FALSE ; } if(dwDst + 2 > nHexLen) return(FALSE); lpHex[dwDst++] = lpBinary[dwSrc]; } } if(bHexmode) { lpHex[dwDst++] = '>' ; bHexmode = FALSE ; } #pragma prefast(suppress:__WARNING_WRITE_OVERRUN, "The loop explicitly ensures that this is safe.") lpHex[dwDst] = '\0' ; // null terminate string. return(TRUE); } BOOL HexStringToBinary( _In_reads_bytes_(nHexLen) LPBYTE lpHex, _Out_writes_bytes_(nBinaryLen) LPBYTE lpBinary, DWORD nHexLen, // num bytes in src buffer lpHex. DWORD nBinaryLen, // num bytes in dest buffer lpBinary _Out_ DWORD *lpnBinBytes // num bytes written to dest buffer lpBinary ) { // how do I translate TCHAR to ascii? // use Set GetDlgItemTextA // return FALSE if dest buffer exhausted DWORD dwSrc, dwDst ; BOOL bHexmode = FALSE, bHiByte = TRUE; BYTE Nibble ; #pragma prefast(suppress:__WARNING_READ_OVERRUN, "&& short-circuiting doesn't appear to work for this warning.") for(dwSrc = dwDst = 0 ; (dwSrc < nHexLen) && lpHex[dwSrc] ; dwSrc++) { if(bHexmode) // hexmode processing: // recognize only 0-9, a-f, A-F and > // all other chars are ignored. { if(lpHex[dwSrc] >= '0' && lpHex[dwSrc] <= '9') { // digits Nibble = lpHex[dwSrc] - '0' ; } else if(lpHex[dwSrc] >= 'a' && lpHex[dwSrc] <= 'f') { // lower case hex digits Nibble = 0x0a + lpHex[dwSrc] - 'a' ; } else if(lpHex[dwSrc] >= 'A' && lpHex[dwSrc] <= 'F') { // upper case hex digits Nibble = 0x0a + lpHex[dwSrc] - 'A' ; } else if(lpHex[dwSrc] == '>') { bHexmode = FALSE ; continue; // do not attempt to save anything. } else continue; // totally ignore unexpected characters. if(bHiByte) { lpBinary[dwDst] = Nibble << 4 ; bHiByte = FALSE ; } else // lowByte processing { if(dwDst + 1 > nBinaryLen) { *lpnBinBytes = dwDst ; return(FALSE); } lpBinary[dwDst++] |= Nibble ; bHiByte = TRUE ; } } else if(lpHex[dwSrc] == '<') { bHiByte = bHexmode = TRUE ; } else { if(dwDst + 1 > nBinaryLen) { *lpnBinBytes = dwDst ; return(FALSE); } lpBinary[dwDst++] = lpHex[dwSrc] ; } } *lpnBinBytes = dwDst ; return(TRUE); } // revised version for drop down list box void vSetGetCodePage(HWND hDlg, INT *piCodePage, BOOL bMode) // TRUE: Set, FALSE: Get code page. { typedef struct { INT iCodepage ; // store this value in registry } CODEPAGE ; #define NUM_CODEPAGES 14 CODEPAGE codepage[NUM_CODEPAGES] ; DWORD dwI ; codepage[0].iCodepage = -1 ; // CP437.gtt "United States" codepage[1].iCodepage = 850 ; // use 850 instead of -2 (IBM CP850.gtt "Multilingual - Latin 1" codepage[2].iCodepage = -3 ; // CP863.gtt "Canadian French" codepage[3].iCodepage = -10 ; // 950.gtt Traditional Chinese codepage[4].iCodepage = -16 ; // 936.gtt Simplified Chinese codepage[5].iCodepage = -17 ; // 932.gtt Japanese codepage[6].iCodepage = -18 ; // 949.gtt Korean codepage[7].iCodepage = 1250; // Eastern European codepage[8].iCodepage = 1251; // Cyrillic codepage[9].iCodepage = 1252; // US (ANSI) codepage[10].iCodepage = 1253; // Greek codepage[11].iCodepage = 1254; // Turkish codepage[12].iCodepage = 852; // Slavic - Latin 2 codepage[13].iCodepage = 857; // Turkish IBM /* codepage[17].iCodepage = 1255; // Hebrew codepage[18].iCodepage = 1256; // Arabic codepage[19].iCodepage = 1257; // Baltic codepage[20].iCodepage = 1258; // Vietnamese codepage[4].iCodepage = -11 ; // 949_ISC.gtt codepage[5].iCodepage = -12 ; // 932_JIS.gtt codepage[6].iCodepage = -13 ; // 932_JISA.gtt codepage[7].iCodepage = -14 ; // 950_NS86.gtt codepage[8].iCodepage = -15 ; // 950_TCA.gtt */ if(bMode) { dwI = (DWORD)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, 0, 0); if (dwI == CB_ERR) dwI = 0 ; *piCodePage = codepage[dwI].iCodepage ; } else // need to initialize list box selection. { for(dwI = 0 ; dwI < NUM_CODEPAGES ; dwI++) { if(codepage[dwI].iCodepage == *piCodePage) break; } dwI %= NUM_CODEPAGES ; SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, dwI, NULL); } } INT_PTR CALLBACK DevPropPage2Proc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { PGLOBALSTRUCT pGlobals; // points to private structure for static storage PREGSTRUCT pMyStuff; // sebset of pGlobals BYTE szString[MAX_CMD_LEN + 1] ; TCHAR tbuffer[MAX_CMD_LEN] ; DWORD dwI ; BOOL bStatus = FALSE; #pragma prefast(push) #pragma prefast(disable:__WARNING_ANSI_APICALL, "This sample exclusively uses ANSI strings for its UI hex strings.") switch (uiMsg) { case WM_INITDIALOG: pGlobals = (PGLOBALSTRUCT) ((PROPSHEETPAGE *)lParam)->lParam ; if(!pGlobals) return FALSE ; pMyStuff = &pGlobals->regStruct ; // at WM_INITDIALOG time, lParam points to PROPSHEETPAGE. // extract and save ptr to GLOBALSTRUCT for future ref. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pGlobals) ; VinitMyStuff( pGlobals, FALSE) ; SendDlgItemMessage(hDlg, IDC_EDIT1, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT2, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT3, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT6, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT7, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT8, EM_LIMITTEXT, MAX_CMD_LEN, 0); SendDlgItemMessage(hDlg, IDC_EDIT9, EM_LIMITTEXT, MAX_CMD_LEN, 0); for(dwI = FIRSTSTRINGID ; dwI <= LASTSTRINGID ; dwI++) { LoadString( ((PROPSHEETPAGE *)lParam)->hInstance, (UINT)dwI, tbuffer, MAX_CMD_LEN); (DWORD)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)tbuffer); } vSetGetCodePage(hDlg, &pMyStuff->iCodePage, FALSE) ; // Get code page. //** init other edit boxes with corresponding command strings from registry if(BinaryToHexString(pMyStuff->Sel_10_cpi.strCmd, szString, pMyStuff->Sel_10_cpi.dwLen, MAX_CMD_LEN + 1)) SetDlgItemTextA(hDlg, IDC_EDIT1, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Sel_12_cpi.strCmd, szString, pMyStuff->Sel_12_cpi.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT2, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Sel_17_cpi.strCmd, szString, pMyStuff->Sel_17_cpi.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT3, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Bold_ON.strCmd, szString, pMyStuff->Bold_ON.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT6, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Bold_OFF.strCmd, szString, pMyStuff->Bold_OFF.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT7, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Underline_ON.strCmd, szString, pMyStuff->Underline_ON.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT8, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Underline_OFF.strCmd, szString, pMyStuff->Underline_OFF.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT9, (LPCSTR)szString); break; case WM_NOTIFY: pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ; if(!pGlobals) return FALSE ; pMyStuff = &pGlobals->regStruct ; switch (((LPNMHDR)lParam)->code) // type of notification message { case PSN_SETACTIVE: break; case PSN_KILLACTIVE: // case IDC_BUTTON1: // convert user command to binary and back to // verify proper entry. { //** extract all command strings GetDlgItemTextA(hDlg, IDC_EDIT1, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Sel_10_cpi.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_10_cpi.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT2, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Sel_12_cpi.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_12_cpi.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT3, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Sel_17_cpi.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_17_cpi.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT6, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Bold_ON.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_ON.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT7, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Bold_OFF.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_OFF.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT8, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Underline_ON.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_ON.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT9, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Underline_OFF.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_OFF.dwLen) ; // reinitialize edit boxes with binary translated strings. if(BinaryToHexString(pMyStuff->Sel_10_cpi.strCmd, szString, pMyStuff->Sel_10_cpi.dwLen, MAX_CMD_LEN + 1)) SetDlgItemTextA(hDlg, IDC_EDIT1, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Sel_12_cpi.strCmd, szString, pMyStuff->Sel_12_cpi.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT2, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Sel_17_cpi.strCmd, szString, pMyStuff->Sel_17_cpi.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT3, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Bold_ON.strCmd, szString, pMyStuff->Bold_ON.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT6, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Bold_OFF.strCmd, szString, pMyStuff->Bold_OFF.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT7, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Underline_ON.strCmd, szString, pMyStuff->Underline_ON.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT8, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Underline_OFF.strCmd, szString, pMyStuff->Underline_OFF.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT9, (LPCSTR)szString); } break; case PSN_APPLY: { // set code page vSetGetCodePage(hDlg, &pMyStuff->iCodePage, TRUE) ; //** extract all command strings GetDlgItemTextA(hDlg, IDC_EDIT1, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Sel_10_cpi.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_10_cpi.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT2, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Sel_12_cpi.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_12_cpi.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT3, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Sel_17_cpi.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_17_cpi.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT6, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Bold_ON.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_ON.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT7, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Bold_OFF.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_OFF.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT8, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Underline_ON.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_ON.dwLen) ; GetDlgItemTextA(hDlg, IDC_EDIT9, (LPSTR)szString, MAX_CMD_LEN + 1); HexStringToBinary(szString, pMyStuff->Underline_OFF.strCmd, MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_OFF.dwLen) ; // reinitialize edit boxes with binary translated strings. if(BinaryToHexString(pMyStuff->Sel_10_cpi.strCmd, szString, pMyStuff->Sel_10_cpi.dwLen, MAX_CMD_LEN + 1)) SetDlgItemTextA(hDlg, IDC_EDIT1, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Sel_12_cpi.strCmd, szString, pMyStuff->Sel_12_cpi.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT2, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Sel_17_cpi.strCmd, szString, pMyStuff->Sel_17_cpi.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT3, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Bold_ON.strCmd, szString, pMyStuff->Bold_ON.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT6, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Bold_OFF.strCmd, szString, pMyStuff->Bold_OFF.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT7, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Underline_ON.strCmd, szString, pMyStuff->Underline_ON.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT8, (LPCSTR)szString); if(BinaryToHexString(pMyStuff->Underline_OFF.strCmd, szString, pMyStuff->Underline_OFF.dwLen, MAX_CMD_LEN + 1) ) SetDlgItemTextA(hDlg, IDC_EDIT9, (LPCSTR)szString); // store MyStuff in registry. VinitMyStuff(pGlobals, TRUE) ; } break; case PSN_RESET: break; } break; case WM_COMMAND: pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ; if(!pGlobals) return FALSE ; pMyStuff = &pGlobals->regStruct ; if(HIWORD(wParam) == EN_CHANGE) // type of notification message { switch(LOWORD(wParam)) { case IDC_EDIT1: case IDC_EDIT2: case IDC_EDIT3: case IDC_EDIT6: case IDC_EDIT7: case IDC_EDIT8: case IDC_EDIT9: PropSheet_Changed(GetParent( hDlg ), hDlg); break; default: break; } } if(HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMBO1) PropSheet_Changed(GetParent( hDlg ), hDlg); if(HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_CHKBOX1) PropSheet_Changed(GetParent( hDlg ), hDlg); break; case WM_HELP: case WM_CONTEXTMENU: pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ; if(!pGlobals) return FALSE ; bStatus = PrintUIHelp(uiMsg, hDlg, wParam, lParam, pGlobals) ; break; } #pragma prefast(pop) return bStatus; } BOOL InitHelpfileName(PGLOBALSTRUCT pGlobals) { DWORD cbNeeded = 0; PDRIVER_INFO_3 pdrvInfo3 = NULL; GetPrinterDriver(pGlobals->hPrinter, NULL, 3, NULL, 0, &cbNeeded) ; if ((pdrvInfo3 = (PDRIVER_INFO_3)HeapAlloc(pGlobals->hOEMHeap, HEAP_ZERO_MEMORY,cbNeeded)) == NULL) return(FALSE); // Alloc failed if(!GetPrinterDriver(pGlobals->hPrinter, NULL, 3, (LPBYTE)pdrvInfo3, cbNeeded, &cbNeeded)){ if(NULL != pdrvInfo3 ) HeapFree(pGlobals->hOEMHeap, HEAP_ZERO_MEMORY,pdrvInfo3); return(FALSE) ; // failed to initialize path } pGlobals->pwHelpFile = PwstrCreateQualifiedName( pGlobals->hOEMHeap, pdrvInfo3->pDriverPath, TEXT("ttyui.hlp") ) ; return(TRUE); } PWSTR PwstrCreateQualifiedName( HANDLE hHeap, PCWSTR pDir, PCWSTR pFile ) /*++ Routine Description: Create a fully qualified name for the directory and file name passed in. Arguments: pDir - Points to the path pFile - Points to file name hHeap - Points to the heap to allocate the returned string from. Return Value: Pointer to the fully qualified name. --*/ { size_t cbLen, cbLenQualName; size_t cbQualifiedName = 0; PWSTR pBasename, pQualifiedName = NULL; HRESULT hr = S_FALSE; // // Figure out the len of the directory // if ((pBasename = (_TCHAR*) wcsrchr(pDir, TEXT(PATH_SEPARATOR))) != NULL) { pBasename++; } else { WARNING(ERRORTEXT("PwstrCreateQualifiedName(): Invalid path name.\r\n")); return NULL; } cbLen = pBasename - pDir; // number of WCHARS // Concatenate the input directory with the base filename if (! SUCCEEDED(SizeTAdd(cbLen, wcslen(pFile), &cbLenQualName)) || ! SUCCEEDED(SizeTAdd(cbLenQualName, 1, &cbLenQualName)) || ! SUCCEEDED(SizeTMult(sizeof(WCHAR), cbLenQualName, &cbQualifiedName)) ) { WARNING(ERRORTEXT("PwstrCreateQualifiedName(): Arithmetic Overflow\r\n")); return NULL; } if ((pQualifiedName = (PWSTR)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cbQualifiedName)) == NULL) { WARNING(ERRORTEXT("PwstrCreateQualifiedName(): Memory allocation failed.\r\n")); return NULL; } StringCchCopyN(pQualifiedName, cbLenQualName, pDir, cbLen); pQualifiedName[cbLen - 1] = 0; hr = StringCchCatW(pQualifiedName, cbLenQualName, pFile); if ( SUCCEEDED (hr) ) { return pQualifiedName; } // // If control reaches here, something went wrong while doing cat. // if ( pQualifiedName ) { // // If HeapAlloc succeeded but StringCchCat failed. // HeapFree ( hHeap, 0, pQualifiedName ); pQualifiedName = NULL; } return NULL; } /*++ Routine Name: PrintUIHlep Routine Description: All dialogs and property sheets call this routine to handle help. It is important that control ID's are unique to this project for this to work. Arguments: UINT uMsg, HWND hDlg, WPARAM wParam, LPARAM lParam Return Value: TRUE if help message was dislayed, FALSE if message not handled, --*/ BOOL PrintUIHelp( UINT uMsg, HWND hDlg, WPARAM wParam, LPARAM lParam, PGLOBALSTRUCT pGlobals // points to private structure for static storage ) { UNREFERENCED_PARAMETER(hDlg); BOOL bStatus = FALSE; switch( uMsg ){ case WM_HELP: bStatus = WinHelp( (HWND) ((LPHELPINFO) lParam)->hItemHandle, pGlobals->pwHelpFile, HELP_WM_HELP, (ULONG_PTR) (LPTSTR)aHelpIDs ); break; case WM_CONTEXTMENU: bStatus = WinHelp( (HWND)wParam, pGlobals->pwHelpFile, HELP_CONTEXTMENU, (ULONG_PTR) (LPTSTR)aHelpIDs ); break; } return bStatus; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials