Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1424 lines
52 KiB

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright 1997-2003 Microsoft Corporation. All Rights Reserved.
  7. //
  8. // FILE: TTYUI.cpp
  9. //
  10. //
  11. // PURPOSE: Main file for TTY UI user mode module.
  12. //
  13. //
  14. // Functions:
  15. //
  16. //
  17. //
  18. //
  19. // PLATFORMS: Windows 2000, Windows XP, Windows Server 2003
  20. //
  21. //
  22. #include <WINDOWS.H>
  23. #include <ASSERT.H>
  24. #include <PRSHT.H>
  25. #include <COMPSTUI.H>
  26. #include <WINDDIUI.H>
  27. #include <PRINTOEM.H>
  28. #include <stdlib.h>
  29. #include <TCHAR.H>
  30. #include <WINSPOOL.H>
  31. #include "resource.h"
  32. #include "TTYUI.h"
  33. #include "ttyuihlp.h"
  34. #include "debug.h"
  35. #include <STRSAFE.H>
  36. ////////////////////////////////////////////////////////
  37. // INTERNAL GLOBALS
  38. ////////////////////////////////////////////////////////
  39. HINSTANCE ghInstance = NULL;
  40. ////////////////////////////////////////////////////////
  41. // INTERNAL PROTOTYPES
  42. ////////////////////////////////////////////////////////
  43. INT_PTR CALLBACK DevPropPageProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  44. INT_PTR CALLBACK DevPropPage2Proc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  45. BOOL HexStringToBinary(LPBYTE lpHex, LPBYTE lpBinary,
  46. DWORD nHexLen, // num bytes in src buffer lpHex.
  47. DWORD nBinaryLen, // num bytes in dest buffer lpBinary
  48. DWORD * lpnBinBytes); // num bytes written to dest buffer lpBinary
  49. BOOL BinaryToHexString(LPBYTE lpBinary, LPBYTE lpHex,
  50. DWORD nBinaryLen, // num bytes to process in lpBinary
  51. DWORD nHexLen); // num bytes in dest buffer lpHex.
  52. void VinitMyStuff(
  53. PGLOBALSTRUCT pGlobals, // points to private structure for static storage
  54. BOOL bSave // save to registry instead of reading from...
  55. ) ;
  56. void vSetGetCodePage(HWND hDlg,
  57. INT *piCodePage,
  58. BOOL bMode) ; // TRUE: Set, FALSE: Get code page.
  59. BOOL PrintUIHelp(
  60. UINT uMsg,
  61. HWND hDlg,
  62. WPARAM wParam,
  63. LPARAM lParam,
  64. PGLOBALSTRUCT pGlobals
  65. ) ;
  66. BOOL InitHelpfileName(PGLOBALSTRUCT pGlobals) ;
  67. PWSTR PwstrCreateQualifiedName(
  68. HANDLE hHeap,
  69. PWSTR pDir,
  70. PWSTR pFile
  71. );
  72. // Need to export these functions as c declarations.
  73. extern "C" {
  74. //////////////////////////////////////////////////////////////////////////
  75. // Function: DllMain
  76. //
  77. // Description: Dll entry point for initialization..
  78. //
  79. //
  80. // Comments:
  81. //
  82. //
  83. // History:
  84. // 1/27/97 APresley Created.
  85. //
  86. //////////////////////////////////////////////////////////////////////////
  87. BOOL WINAPI DllMain(HINSTANCE hInst, WORD wReason, LPVOID lpReserved)
  88. {
  89. switch(wReason)
  90. {
  91. case DLL_PROCESS_ATTACH:
  92. // VERBOSE(DLLTEXT("Process attach.\r\n"));
  93. // Save DLL instance for use later.
  94. ghInstance = hInst;
  95. break;
  96. case DLL_THREAD_ATTACH:
  97. // VERBOSE(DLLTEXT("Thread attach.\r\n"));
  98. break;
  99. case DLL_PROCESS_DETACH:
  100. // VERBOSE(DLLTEXT("Process detach.\r\n"));
  101. break;
  102. case DLL_THREAD_DETACH:
  103. // VERBOSE(DLLTEXT("Thread detach.\r\n"));
  104. break;
  105. }
  106. return TRUE;
  107. }
  108. BOOL APIENTRY OEMGetInfo(IN DWORD dwInfo, OUT PVOID pBuffer, IN DWORD cbSize,
  109. OUT PDWORD pcbNeeded)
  110. {
  111. // VERBOSE(DLLTEXT("OEMGetInfo(%#x) entry.\r\n"), dwInfo);
  112. // Validate parameters.
  113. if( ( (OEMGI_GETSIGNATURE != dwInfo)
  114. &&
  115. (OEMGI_GETINTERFACEVERSION != dwInfo)
  116. &&
  117. (OEMGI_GETVERSION != dwInfo)
  118. )
  119. ||
  120. (NULL == pcbNeeded)
  121. )
  122. {
  123. WARNING(ERRORTEXT("OEMGetInfo() ERROR_INVALID_PARAMETER.\r\n"));
  124. // Did not write any bytes.
  125. if(NULL != pcbNeeded)
  126. *pcbNeeded = 0;
  127. // Return invalid parameter error.
  128. SetLastError(ERROR_INVALID_PARAMETER);
  129. return FALSE;
  130. }
  131. // Need/wrote 4 bytes.
  132. *pcbNeeded = 4;
  133. // Validate buffer size. Minimum size is four bytes.
  134. if( (NULL == pBuffer)
  135. ||
  136. (4 > cbSize)
  137. )
  138. {
  139. WARNING(ERRORTEXT("OEMGetInfo() ERROR_INSUFFICIENT_BUFFER.\r\n"));
  140. // Return insufficient buffer size.
  141. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  142. return FALSE;
  143. }
  144. // Write information to buffer.
  145. switch(dwInfo)
  146. {
  147. case OEMGI_GETSIGNATURE:
  148. *(LPDWORD)pBuffer = OEM_SIGNATURE;
  149. break;
  150. case OEMGI_GETINTERFACEVERSION:
  151. *(LPDWORD)pBuffer = PRINTER_OEMINTF_VERSION;
  152. break;
  153. case OEMGI_GETVERSION:
  154. *(LPDWORD)pBuffer = OEM_VERSION;
  155. break;
  156. }
  157. return TRUE;
  158. }
  159. LRESULT APIENTRY OEMDevicePropertySheets(PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam)
  160. {
  161. LRESULT lResult = CPSUI_CANCEL ;
  162. LONG lRet;
  163. VERBOSE(DLLTEXT("OEMDevicePropertySheets() entry.\r\n"));
  164. // Validate parameters.
  165. if( (NULL == pPSUIInfo)
  166. ||
  167. (PROPSHEETUI_INFO_VERSION != pPSUIInfo->Version)
  168. )
  169. {
  170. VERBOSE(ERRORTEXT("OEMDevicePropertySheets() ERROR_INVALID_PARAMETER.\r\n"));
  171. // Return invalid parameter error.
  172. SetLastError(ERROR_INVALID_PARAMETER);
  173. return -1;
  174. }
  175. // Do action.
  176. switch(pPSUIInfo->Reason)
  177. {
  178. case PROPSHEETUI_REASON_INIT:
  179. {
  180. PROPSHEETPAGE Page;
  181. // Init property page.
  182. memset(&Page, 0, sizeof(PROPSHEETPAGE));
  183. Page.dwSize = sizeof(PROPSHEETPAGE);
  184. Page.dwFlags = PSP_DEFAULT;
  185. Page.hInstance = ghInstance;
  186. Page.pszTemplate = MAKEINTRESOURCE(IDD_DEV_PROPPAGE);
  187. Page.pfnDlgProc = DevPropPageProc;
  188. // allocate structure to hold static data for
  189. // PropertySheet Dialog function
  190. pPSUIInfo->UserData =
  191. Page.lParam = (LPARAM)HeapAlloc(
  192. ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hOEMHeap,
  193. HEAP_ZERO_MEMORY , sizeof(GLOBALSTRUCT) );
  194. if(!Page.lParam)
  195. return -1; // HeapAlloc failed.
  196. ((PGLOBALSTRUCT)Page.lParam)->hPrinter =
  197. ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hPrinter ;
  198. ((PGLOBALSTRUCT)Page.lParam)->hOEMHeap =
  199. ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hOEMHeap ;
  200. // Add property sheets.
  201. lResult = (pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet,
  202. CPSFUNC_ADD_PROPSHEETPAGE, (LPARAM)&Page, 0) > 0 ? TRUE : FALSE);
  203. Page.pszTemplate = MAKEINTRESOURCE(IDD_DEV_PROPPAGE2);
  204. Page.pfnDlgProc = DevPropPage2Proc;
  205. // Add another property sheet.
  206. if(lResult)
  207. {
  208. lResult = (pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet,
  209. CPSFUNC_ADD_PROPSHEETPAGE, (LPARAM)&Page, 0) > 0 ? TRUE : FALSE);
  210. }
  211. pPSUIInfo->Result = lResult;
  212. lRet = (lResult) ? 1 : -1 ;
  213. }
  214. break;
  215. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  216. {
  217. PPROPSHEETUI_INFO_HEADER pHeader = (PPROPSHEETUI_INFO_HEADER) lParam;
  218. pHeader->pTitle = (LPTSTR)PROP_TITLE;
  219. lResult = TRUE;
  220. lRet = (lResult) ? 1 : -1 ;
  221. }
  222. break;
  223. case PROPSHEETUI_REASON_GET_ICON:
  224. // No icon
  225. lResult = 0;
  226. lRet = (lResult) ? 1 : -1 ;
  227. break;
  228. case PROPSHEETUI_REASON_SET_RESULT:
  229. {
  230. PSETRESULT_INFO pInfo = (PSETRESULT_INFO) lParam;
  231. lResult = pInfo->Result;
  232. pPSUIInfo->Result = lResult;
  233. lRet = 1 ;
  234. }
  235. break;
  236. case PROPSHEETUI_REASON_DESTROY:
  237. if(pPSUIInfo->UserData)
  238. HeapFree(
  239. ((POEMUIPSPARAM)(pPSUIInfo->lParamInit))->hOEMHeap,
  240. 0 , (void *)pPSUIInfo->UserData );
  241. lResult = TRUE;
  242. lRet = (lResult) ? 1 : -1 ;
  243. break;
  244. default:
  245. lRet = -1 ;
  246. }
  247. // pPSUIInfo->Result = lResult;
  248. return lRet;
  249. }
  250. } // End of extern "C"
  251. //////////////////////////////////////////////////////////////////////////
  252. // Function: DevPropPageProc
  253. //
  254. // Description: Generic property page procedure.
  255. //
  256. //
  257. //
  258. //
  259. // Comments:
  260. //
  261. //
  262. // History:
  263. // 02/12/97 APresley Created.
  264. //
  265. //////////////////////////////////////////////////////////////////////////
  266. INT_PTR CALLBACK DevPropPageProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  267. {
  268. // RECT rcMargin ; // temp storage during conversions.
  269. PGLOBALSTRUCT pGlobals; // points to private structure for static storage
  270. PREGSTRUCT pMyStuff; // sebset of pGlobals
  271. TCHAR szIntString[MAX_INT_FIELD_WIDTH + 2] ;
  272. BYTE szString[MAX_CMD_LEN + 1] ;
  273. BOOL bStatus = FALSE;
  274. switch (uiMsg)
  275. {
  276. case WM_INITDIALOG:
  277. pGlobals = (PGLOBALSTRUCT) ((PROPSHEETPAGE *)lParam)->lParam ;
  278. if(!pGlobals)
  279. return FALSE ;
  280. pMyStuff = &pGlobals->regStruct ;
  281. // at WM_INITDIALOG time, lParam points to PROPSHEETPAGE.
  282. // extract and save ptr to GLOBALSTRUCT for future ref.
  283. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pGlobals) ;
  284. VinitMyStuff( pGlobals, FALSE) ;
  285. SendDlgItemMessage(hDlg, IDC_EDIT10, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  286. SendDlgItemMessage(hDlg, IDC_EDIT11, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  287. SendDlgItemMessage(hDlg, IDC_EDIT12, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  288. SendDlgItemMessage(hDlg, IDC_EDIT13, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  289. SendDlgItemMessage(hDlg, IDC_EDIT14, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0);
  290. SendDlgItemMessage(hDlg, IDC_EDIT15, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0);
  291. SendDlgItemMessage(hDlg, IDC_EDIT16, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0);
  292. SendDlgItemMessage(hDlg, IDC_EDIT17, EM_LIMITTEXT, MAX_INT_FIELD_WIDTH, 0);
  293. if(pMyStuff->bIsMM)
  294. CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO1) ;
  295. else
  296. {
  297. CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO2, IDC_RADIO2) ;
  298. // convert RECT values to inches
  299. pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 100, 254) ;
  300. pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 100, 254) ;
  301. pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 100, 254) ;
  302. pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 100, 254) ;
  303. }
  304. // convert int to ascii string
  305. _itot(pMyStuff->rcMargin.left, szIntString, RADIX ) ;
  306. SetDlgItemText(hDlg, IDC_EDIT14, szIntString);
  307. _itot(pMyStuff->rcMargin.top, szIntString, RADIX) ;
  308. SetDlgItemText(hDlg, IDC_EDIT15, szIntString);
  309. _itot(pMyStuff->rcMargin.right, szIntString, RADIX) ;
  310. SetDlgItemText(hDlg, IDC_EDIT16, szIntString);
  311. _itot(pMyStuff->rcMargin.bottom, szIntString, RADIX) ;
  312. SetDlgItemText(hDlg, IDC_EDIT17, szIntString);
  313. //** init other edit boxes with corresponding command strings from registry
  314. if(BinaryToHexString(pMyStuff->BeginJob.strCmd, szString,
  315. pMyStuff->BeginJob.dwLen, MAX_CMD_LEN + 1))
  316. SetDlgItemTextA(hDlg, IDC_EDIT10, (LPCSTR)szString);
  317. if(BinaryToHexString(pMyStuff->EndJob.strCmd, szString,
  318. pMyStuff->EndJob.dwLen, MAX_CMD_LEN + 1) )
  319. SetDlgItemTextA(hDlg, IDC_EDIT11, (LPCSTR)szString);
  320. if(BinaryToHexString(pMyStuff->PaperSelect.strCmd, szString,
  321. pMyStuff->PaperSelect.dwLen, MAX_CMD_LEN + 1) )
  322. SetDlgItemTextA(hDlg, IDC_EDIT12, (LPCSTR)szString);
  323. if(BinaryToHexString(pMyStuff->FeedSelect.strCmd, szString,
  324. pMyStuff->FeedSelect.dwLen, MAX_CMD_LEN + 1) )
  325. SetDlgItemTextA(hDlg, IDC_EDIT13, (LPCSTR)szString);
  326. break;
  327. case WM_NOTIFY:
  328. pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ;
  329. if(!pGlobals)
  330. return FALSE ;
  331. pMyStuff = &pGlobals->regStruct ;
  332. switch (((LPNMHDR)lParam)->code) // type of notification message
  333. {
  334. case PSN_SETACTIVE:
  335. break;
  336. case PSN_KILLACTIVE:
  337. // formerly case IDC_BUTTON1:
  338. // convert user command to binary and back to
  339. // verify proper entry.
  340. {
  341. //** extract all command strings
  342. GetDlgItemTextA(hDlg, IDC_EDIT10, (LPSTR)szString, MAX_CMD_LEN + 1);
  343. HexStringToBinary(szString, pMyStuff->BeginJob.strCmd,
  344. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->BeginJob.dwLen) ;
  345. GetDlgItemTextA(hDlg, IDC_EDIT11, (LPSTR)szString, MAX_CMD_LEN + 1);
  346. HexStringToBinary(szString, pMyStuff->EndJob.strCmd,
  347. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->EndJob.dwLen) ;
  348. GetDlgItemTextA(hDlg, IDC_EDIT12, (LPSTR)szString, MAX_CMD_LEN + 1);
  349. HexStringToBinary(szString, pMyStuff->PaperSelect.strCmd,
  350. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->PaperSelect.dwLen) ;
  351. GetDlgItemTextA(hDlg, IDC_EDIT13, (LPSTR)szString, MAX_CMD_LEN + 1);
  352. HexStringToBinary(szString, pMyStuff->FeedSelect.strCmd,
  353. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->FeedSelect.dwLen) ;
  354. // reinitialize edit boxes with binary translated strings.
  355. if(BinaryToHexString(pMyStuff->BeginJob.strCmd, szString,
  356. pMyStuff->BeginJob.dwLen, MAX_CMD_LEN + 1))
  357. SetDlgItemTextA(hDlg, IDC_EDIT10, (LPCSTR)szString);
  358. if(BinaryToHexString(pMyStuff->EndJob.strCmd, szString,
  359. pMyStuff->EndJob.dwLen, MAX_CMD_LEN + 1) )
  360. SetDlgItemTextA(hDlg, IDC_EDIT11, (LPCSTR)szString);
  361. if(BinaryToHexString(pMyStuff->PaperSelect.strCmd, szString,
  362. pMyStuff->PaperSelect.dwLen, MAX_CMD_LEN + 1) )
  363. SetDlgItemTextA(hDlg, IDC_EDIT12, (LPCSTR)szString);
  364. if(BinaryToHexString(pMyStuff->FeedSelect.strCmd, szString,
  365. pMyStuff->FeedSelect.dwLen, MAX_CMD_LEN + 1) )
  366. SetDlgItemTextA(hDlg, IDC_EDIT13, (LPCSTR)szString);
  367. }
  368. break;
  369. case PSN_APPLY:
  370. {
  371. // MessageBox(hDlg, szString, "TTY settings", MB_OK);
  372. // load numbers in edit boxes into rcMargin
  373. GetDlgItemText(hDlg, IDC_EDIT14, szIntString, MAX_INT_FIELD_WIDTH + 1);
  374. pMyStuff->rcMargin.left = _ttoi(szIntString) ;
  375. GetDlgItemText(hDlg, IDC_EDIT15, szIntString, MAX_INT_FIELD_WIDTH + 1);
  376. pMyStuff->rcMargin.top = _ttoi(szIntString) ;
  377. GetDlgItemText(hDlg, IDC_EDIT16, szIntString, MAX_INT_FIELD_WIDTH + 1);
  378. pMyStuff->rcMargin.right = _ttoi(szIntString) ;
  379. GetDlgItemText(hDlg, IDC_EDIT17, szIntString, MAX_INT_FIELD_WIDTH + 1);
  380. pMyStuff->rcMargin.bottom = _ttoi(szIntString) ;
  381. if(!pMyStuff->bIsMM )
  382. {
  383. // convert RECT values from inches back to mm
  384. pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 254, 100) ;
  385. pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 254, 100) ;
  386. pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 254, 100) ;
  387. pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 254, 100) ;
  388. }
  389. //** extract all command strings
  390. GetDlgItemTextA(hDlg, IDC_EDIT10, (LPSTR)szString, MAX_CMD_LEN + 1);
  391. HexStringToBinary(szString, pMyStuff->BeginJob.strCmd,
  392. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->BeginJob.dwLen) ;
  393. GetDlgItemTextA(hDlg, IDC_EDIT11, (LPSTR)szString, MAX_CMD_LEN + 1);
  394. HexStringToBinary(szString, pMyStuff->EndJob.strCmd,
  395. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->EndJob.dwLen) ;
  396. GetDlgItemTextA(hDlg, IDC_EDIT12, (LPSTR)szString, MAX_CMD_LEN + 1);
  397. HexStringToBinary(szString, pMyStuff->PaperSelect.strCmd,
  398. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->PaperSelect.dwLen) ;
  399. GetDlgItemTextA(hDlg, IDC_EDIT13, (LPSTR)szString, MAX_CMD_LEN + 1);
  400. HexStringToBinary(szString, pMyStuff->FeedSelect.strCmd,
  401. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->FeedSelect.dwLen) ;
  402. // reinitialize edit boxes with binary translated strings.
  403. if(BinaryToHexString(pMyStuff->BeginJob.strCmd, szString,
  404. pMyStuff->BeginJob.dwLen, MAX_CMD_LEN + 1))
  405. SetDlgItemTextA(hDlg, IDC_EDIT10, (LPCSTR)szString);
  406. if(BinaryToHexString(pMyStuff->EndJob.strCmd, szString,
  407. pMyStuff->EndJob.dwLen, MAX_CMD_LEN + 1) )
  408. SetDlgItemTextA(hDlg, IDC_EDIT11, (LPCSTR)szString);
  409. if(BinaryToHexString(pMyStuff->PaperSelect.strCmd, szString,
  410. pMyStuff->PaperSelect.dwLen, MAX_CMD_LEN + 1) )
  411. SetDlgItemTextA(hDlg, IDC_EDIT12, (LPCSTR)szString);
  412. if(BinaryToHexString(pMyStuff->FeedSelect.strCmd, szString,
  413. pMyStuff->FeedSelect.dwLen, MAX_CMD_LEN + 1) )
  414. SetDlgItemTextA(hDlg, IDC_EDIT13, (LPCSTR)szString);
  415. // store MyStuff in registry.
  416. VinitMyStuff(pGlobals, TRUE) ;
  417. }
  418. break;
  419. case PSN_RESET:
  420. break;
  421. }
  422. break;
  423. case WM_COMMAND:
  424. pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ;
  425. if(!pGlobals)
  426. return FALSE ;
  427. pMyStuff = &pGlobals->regStruct ;
  428. if(HIWORD(wParam) == EN_CHANGE)
  429. // type of notification message
  430. {
  431. switch(LOWORD(wParam))
  432. {
  433. case IDC_EDIT10:
  434. case IDC_EDIT11:
  435. case IDC_EDIT12:
  436. case IDC_EDIT13:
  437. case IDC_EDIT14:
  438. case IDC_EDIT15:
  439. case IDC_EDIT16:
  440. case IDC_EDIT17:
  441. PropSheet_Changed(GetParent( hDlg ), hDlg);
  442. break;
  443. default:
  444. break;
  445. }
  446. }
  447. switch(LOWORD(wParam))
  448. {
  449. case IDC_RADIO1: // convert to MM
  450. {
  451. if(!pMyStuff->bIsMM )
  452. {
  453. // assume all values are inches
  454. // convert to mm. and store in edit boxes.
  455. // load numbers in edit boxes into rcMargin
  456. GetDlgItemText(hDlg, IDC_EDIT14, szIntString, MAX_INT_FIELD_WIDTH + 1);
  457. pMyStuff->rcMargin.left = _ttoi(szIntString) ;
  458. GetDlgItemText(hDlg, IDC_EDIT15, szIntString, MAX_INT_FIELD_WIDTH + 1);
  459. pMyStuff->rcMargin.top = _ttoi(szIntString) ;
  460. GetDlgItemText(hDlg, IDC_EDIT16, szIntString, MAX_INT_FIELD_WIDTH + 1);
  461. pMyStuff->rcMargin.right = _ttoi(szIntString) ;
  462. GetDlgItemText(hDlg, IDC_EDIT17, szIntString, MAX_INT_FIELD_WIDTH + 1);
  463. pMyStuff->rcMargin.bottom = _ttoi(szIntString) ;
  464. // convert RECT values from inches back to mm
  465. pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 254, 100) ;
  466. pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 254, 100) ;
  467. pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 254, 100) ;
  468. pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 254, 100) ;
  469. // load numbers from rcMargin into edit boxes
  470. _itot(pMyStuff->rcMargin.left, szIntString, RADIX ) ;
  471. SetDlgItemText(hDlg, IDC_EDIT14, szIntString);
  472. _itot(pMyStuff->rcMargin.top, szIntString, RADIX) ;
  473. SetDlgItemText(hDlg, IDC_EDIT15, szIntString);
  474. _itot(pMyStuff->rcMargin.right, szIntString, RADIX) ;
  475. SetDlgItemText(hDlg, IDC_EDIT16, szIntString);
  476. _itot(pMyStuff->rcMargin.bottom, szIntString, RADIX) ;
  477. SetDlgItemText(hDlg, IDC_EDIT17, szIntString);
  478. pMyStuff->bIsMM = TRUE ;
  479. }
  480. }
  481. break;
  482. case IDC_RADIO2: // convert to inches
  483. {
  484. if(pMyStuff->bIsMM )
  485. {
  486. // assume all values are mm
  487. // convert to inches. and store in edit boxes.
  488. // load numbers in edit boxes into rcMargin
  489. GetDlgItemText(hDlg, IDC_EDIT14, szIntString, MAX_INT_FIELD_WIDTH + 1);
  490. pMyStuff->rcMargin.left = _ttoi(szIntString) ;
  491. GetDlgItemText(hDlg, IDC_EDIT15, szIntString, MAX_INT_FIELD_WIDTH + 1);
  492. pMyStuff->rcMargin.top = _ttoi(szIntString) ;
  493. GetDlgItemText(hDlg, IDC_EDIT16, szIntString, MAX_INT_FIELD_WIDTH + 1);
  494. pMyStuff->rcMargin.right = _ttoi(szIntString) ;
  495. GetDlgItemText(hDlg, IDC_EDIT17, szIntString, MAX_INT_FIELD_WIDTH + 1);
  496. pMyStuff->rcMargin.bottom = _ttoi(szIntString) ;
  497. // convert RECT values from mm back to inches
  498. pMyStuff->rcMargin.left = MulDiv(pMyStuff->rcMargin.left, 100, 254) ;
  499. pMyStuff->rcMargin.top = MulDiv(pMyStuff->rcMargin.top, 100, 254) ;
  500. pMyStuff->rcMargin.right = MulDiv(pMyStuff->rcMargin.right, 100, 254) ;
  501. pMyStuff->rcMargin.bottom = MulDiv(pMyStuff->rcMargin.bottom, 100, 254) ;
  502. // load numbers from rcMargin into edit boxes
  503. _itot(pMyStuff->rcMargin.left, szIntString, RADIX ) ;
  504. SetDlgItemText(hDlg, IDC_EDIT14, szIntString);
  505. _itot(pMyStuff->rcMargin.top, szIntString, RADIX) ;
  506. SetDlgItemText(hDlg, IDC_EDIT15, szIntString);
  507. _itot(pMyStuff->rcMargin.right, szIntString, RADIX) ;
  508. SetDlgItemText(hDlg, IDC_EDIT16, szIntString);
  509. _itot(pMyStuff->rcMargin.bottom, szIntString, RADIX) ;
  510. SetDlgItemText(hDlg, IDC_EDIT17, szIntString);
  511. pMyStuff->bIsMM = FALSE ;
  512. }
  513. }
  514. break;
  515. }
  516. break;
  517. case WM_HELP:
  518. case WM_CONTEXTMENU:
  519. pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ;
  520. if(!pGlobals)
  521. return FALSE ;
  522. // pMyStuff = &pGlobals->regStruct ;
  523. bStatus = PrintUIHelp(uiMsg, hDlg, wParam, lParam, pGlobals) ;
  524. break;
  525. }
  526. return bStatus ;
  527. }
  528. void VinitMyStuff(
  529. PGLOBALSTRUCT pGlobals, // points to private structure for static storage
  530. BOOL bSave // save to registry instead of reading from...
  531. )
  532. {
  533. PREGSTRUCT pMyStuff; // sebset of pGlobals
  534. DWORD dwStatus, cbNeeded, dwType ;
  535. LPTSTR pValueName = TEXT("TTY DeviceConfig");
  536. // these strings must match strings in ttyud.cpp - OEMEnablePDEV()
  537. pMyStuff = &pGlobals->regStruct ;
  538. if(bSave) // save to registry
  539. {
  540. if(--pGlobals->dwUseCount)
  541. return ;
  542. // you are the last property page to perform
  543. // shutdown routine. Save MyStuff to registry.
  544. SetPrinterData(
  545. pGlobals->hPrinter, // handle of printer object
  546. pValueName, // address of value name
  547. REG_BINARY, // flag for value type
  548. (LPBYTE)pMyStuff , // address of array that specifies printer data
  549. sizeof(REGSTRUCT) // size, in bytes, of array
  550. );
  551. return ;
  552. }
  553. // read from registry
  554. if(pGlobals->dwUseCount)
  555. {
  556. pGlobals->dwUseCount++ ;
  557. return ;
  558. }
  559. dwStatus = GetPrinterData(
  560. pGlobals->hPrinter, // handle of printer object saved previously.
  561. pValueName, // address of value name
  562. &dwType, // address receiving value type
  563. (LPBYTE)pMyStuff, // address of array of bytes that receives data
  564. sizeof(REGSTRUCT), // size, in bytes, of array
  565. &cbNeeded // address of variable
  566. // with number of bytes retrieved (or required)
  567. );
  568. if (dwStatus != ERROR_SUCCESS || pMyStuff->dwVersion != TTYSTRUCT_VER
  569. || dwType != REG_BINARY
  570. || cbNeeded != sizeof(REGSTRUCT))
  571. {
  572. // Init secret block with defaults
  573. pMyStuff->dwVersion = TTYSTRUCT_VER ;
  574. // version stamp to avoid incompatible structures.
  575. pMyStuff->bIsMM = TRUE ; // default to mm units
  576. // read margin values from registry and store into temp RECT
  577. pMyStuff->iCodePage = 1252 ;
  578. pMyStuff->rcMargin.left = pMyStuff->rcMargin.top =
  579. pMyStuff->rcMargin.right = pMyStuff->rcMargin.bottom = 0 ;
  580. pMyStuff->BeginJob.dwLen =
  581. pMyStuff->EndJob.dwLen =
  582. pMyStuff->PaperSelect.dwLen =
  583. pMyStuff->FeedSelect.dwLen =
  584. pMyStuff->Sel_10_cpi.dwLen =
  585. pMyStuff->Sel_12_cpi.dwLen =
  586. pMyStuff->Sel_17_cpi.dwLen =
  587. pMyStuff->Bold_ON.dwLen =
  588. pMyStuff->Bold_OFF.dwLen =
  589. pMyStuff->Underline_ON.dwLen =
  590. pMyStuff->Underline_OFF.dwLen = 0 ;
  591. // more fields here!
  592. pMyStuff->dwGlyphBufSiz =
  593. pMyStuff->dwSpoolBufSiz = 0 ;
  594. pMyStuff->aubGlyphBuf =
  595. pMyStuff->aubSpoolBuf = NULL ;
  596. }
  597. InitHelpfileName(pGlobals) ;
  598. pGlobals->dwUseCount = 1 ;
  599. return ;
  600. }
  601. BOOL BinaryToHexString(LPBYTE lpBinary, LPBYTE lpHex,
  602. DWORD nBinaryLen, // num bytes to process in lpBinary
  603. DWORD nHexLen) // num bytes in dest buffer lpHex.
  604. {
  605. // how do I translate TCHAR to ascii?
  606. // use Set GetDlgItemTextA
  607. // add NULL termination to lpHex
  608. // return FALSE if dest buffer exhausted
  609. DWORD dwSrc, dwDst ;
  610. BOOL bHexmode = FALSE ;
  611. BYTE Nibble ;
  612. for(dwSrc = dwDst = 0 ; dwSrc < nBinaryLen ; dwSrc++)
  613. {
  614. if(lpBinary[dwSrc] < 0x21 || lpBinary[dwSrc] > 0x7e
  615. || lpBinary[dwSrc] == '<')
  616. {
  617. // enter hexmode if not already
  618. if(!bHexmode)
  619. {
  620. if(dwDst + 5 > nHexLen)
  621. return(FALSE);
  622. lpHex[dwDst++] = '<' ;
  623. bHexmode = TRUE ;
  624. }
  625. else if(dwDst + 4 > nHexLen)
  626. return(FALSE);
  627. Nibble = (lpBinary[dwSrc] >> 4) & 0x0f ;
  628. if(Nibble < 0x0a)
  629. lpHex[dwDst++] = '0' + Nibble ;
  630. else
  631. lpHex[dwDst++] = 'A' + Nibble - 0x0a ;
  632. // loNibble
  633. Nibble = lpBinary[dwSrc] & 0x0f ;
  634. if(Nibble < 0x0a)
  635. lpHex[dwDst++] = '0' + Nibble ;
  636. else
  637. lpHex[dwDst++] = 'A' + Nibble - 0x0a ;
  638. }
  639. else
  640. {
  641. // exit hexmode if not already
  642. if(bHexmode)
  643. {
  644. lpHex[dwDst++] = '>' ;
  645. bHexmode = FALSE ;
  646. }
  647. if(dwDst + 2 > nHexLen)
  648. return(FALSE);
  649. lpHex[dwDst++] = lpBinary[dwSrc];
  650. }
  651. }
  652. if(bHexmode)
  653. {
  654. lpHex[dwDst++] = '>' ;
  655. bHexmode = FALSE ;
  656. }
  657. lpHex[dwDst] = '\0' ; // null terminate string.
  658. return(TRUE);
  659. }
  660. BOOL HexStringToBinary(LPBYTE lpHex, LPBYTE lpBinary,
  661. DWORD nHexLen, // num bytes in src buffer lpHex.
  662. DWORD nBinaryLen, // num bytes in dest buffer lpBinary
  663. DWORD * lpnBinBytes) // num bytes written to dest buffer lpBinary
  664. {
  665. // how do I translate TCHAR to ascii?
  666. // use Set GetDlgItemTextA
  667. // return FALSE if dest buffer exhausted
  668. DWORD dwSrc, dwDst ;
  669. BOOL bHexmode = FALSE, bHiByte ;
  670. BYTE Nibble ;
  671. lpHex[nHexLen - 1] = '\0' ; // null terminate src string
  672. // to prevent overrun accidents.
  673. for(dwSrc = dwDst = 0 ; lpHex[dwSrc] ; dwSrc++)
  674. {
  675. if(bHexmode) // hexmode processing:
  676. // recognize only 0-9, a-f, A-F and >
  677. // all other chars are ignored.
  678. {
  679. if(lpHex[dwSrc] >= '0' && lpHex[dwSrc] <= '9')
  680. {
  681. // digits
  682. Nibble = lpHex[dwSrc] - '0' ;
  683. }
  684. else if(lpHex[dwSrc] >= 'a' && lpHex[dwSrc] <= 'f')
  685. {
  686. // lower case hex digits
  687. Nibble = 0x0a + lpHex[dwSrc] - 'a' ;
  688. }
  689. else if(lpHex[dwSrc] >= 'A' && lpHex[dwSrc] <= 'F')
  690. {
  691. // upper case hex digits
  692. Nibble = 0x0a + lpHex[dwSrc] - 'A' ;
  693. }
  694. else if(lpHex[dwSrc] == '>')
  695. {
  696. bHexmode = FALSE ;
  697. continue; // do not attempt to save anything.
  698. }
  699. else
  700. continue; // totally ignore unexpected characters.
  701. if(bHiByte)
  702. {
  703. lpBinary[dwDst] = Nibble << 4 ;
  704. bHiByte = FALSE ;
  705. }
  706. else // lowByte processing
  707. {
  708. if(dwDst + 1 > nBinaryLen)
  709. {
  710. *lpnBinBytes = dwDst ;
  711. return(FALSE);
  712. }
  713. lpBinary[dwDst++] |= Nibble ;
  714. bHiByte = TRUE ;
  715. }
  716. }
  717. else if(lpHex[dwSrc] == '<')
  718. {
  719. bHiByte = bHexmode = TRUE ;
  720. }
  721. else
  722. {
  723. if(dwDst + 1 > nBinaryLen)
  724. {
  725. *lpnBinBytes = dwDst ;
  726. return(FALSE);
  727. }
  728. lpBinary[dwDst++] = lpHex[dwSrc] ;
  729. }
  730. }
  731. *lpnBinBytes = dwDst ;
  732. return(TRUE);
  733. }
  734. // revised version for drop down list box
  735. void vSetGetCodePage(HWND hDlg,
  736. INT *piCodePage,
  737. BOOL bMode) // TRUE: Set, FALSE: Get code page.
  738. {
  739. typedef struct
  740. {
  741. INT iCodepage ; // store this value in registry
  742. } CODEPAGE ;
  743. #define NUM_CODEPAGES 14
  744. CODEPAGE codepage[NUM_CODEPAGES] ;
  745. DWORD dwI ;
  746. codepage[0].iCodepage = -1 ; // CP437.gtt "United States"
  747. codepage[1].iCodepage = 850 ; // use 850 instead of -2 (IBM CP850.gtt "Multilingual - Latin 1"
  748. codepage[2].iCodepage = -3 ; // CP863.gtt "Canadian French"
  749. codepage[3].iCodepage = -10 ; // 950.gtt Traditional Chinese
  750. codepage[4].iCodepage = -16 ; // 936.gtt Simplified Chinese
  751. codepage[5].iCodepage = -17 ; // 932.gtt Japanese
  752. codepage[6].iCodepage = -18 ; // 949.gtt Korean
  753. codepage[7].iCodepage = 1250; // Eastern European
  754. codepage[8].iCodepage = 1251; // Cyrillic
  755. codepage[9].iCodepage = 1252; // US (ANSI)
  756. codepage[10].iCodepage = 1253; // Greek
  757. codepage[11].iCodepage = 1254; // Turkish
  758. codepage[12].iCodepage = 852; // Slavic - Latin 2
  759. codepage[13].iCodepage = 857; // Turkish IBM
  760. /*
  761. codepage[17].iCodepage = 1255; // Hebrew
  762. codepage[18].iCodepage = 1256; // Arabic
  763. codepage[19].iCodepage = 1257; // Baltic
  764. codepage[20].iCodepage = 1258; // Vietnamese
  765. codepage[4].iCodepage = -11 ; // 949_ISC.gtt
  766. codepage[5].iCodepage = -12 ; // 932_JIS.gtt
  767. codepage[6].iCodepage = -13 ; // 932_JISA.gtt
  768. codepage[7].iCodepage = -14 ; // 950_NS86.gtt
  769. codepage[8].iCodepage = -15 ; // 950_TCA.gtt
  770. */
  771. if(bMode)
  772. {
  773. dwI = (DWORD)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_GETCURSEL, 0, 0);
  774. if (dwI == CB_ERR)
  775. dwI = 0 ;
  776. *piCodePage = codepage[dwI].iCodepage ;
  777. }
  778. else // need to initialize list box selection.
  779. {
  780. for(dwI = 0 ; dwI < NUM_CODEPAGES ; dwI++)
  781. {
  782. if(codepage[dwI].iCodepage == *piCodePage)
  783. break;
  784. }
  785. dwI %= NUM_CODEPAGES ;
  786. SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, dwI, NULL);
  787. }
  788. }
  789. INT_PTR CALLBACK DevPropPage2Proc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  790. {
  791. PGLOBALSTRUCT pGlobals; // points to private structure for static storage
  792. PREGSTRUCT pMyStuff; // sebset of pGlobals
  793. BYTE szString[MAX_CMD_LEN + 1] ;
  794. TCHAR tbuffer[MAX_CMD_LEN] ;
  795. DWORD dwI ;
  796. BOOL bStatus = FALSE;
  797. switch (uiMsg)
  798. {
  799. case WM_INITDIALOG:
  800. pGlobals = (PGLOBALSTRUCT) ((PROPSHEETPAGE *)lParam)->lParam ;
  801. if(!pGlobals)
  802. return FALSE ;
  803. pMyStuff = &pGlobals->regStruct ;
  804. // at WM_INITDIALOG time, lParam points to PROPSHEETPAGE.
  805. // extract and save ptr to GLOBALSTRUCT for future ref.
  806. SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pGlobals) ;
  807. VinitMyStuff( pGlobals, FALSE) ;
  808. SendDlgItemMessage(hDlg, IDC_EDIT1, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  809. SendDlgItemMessage(hDlg, IDC_EDIT2, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  810. SendDlgItemMessage(hDlg, IDC_EDIT3, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  811. SendDlgItemMessage(hDlg, IDC_EDIT6, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  812. SendDlgItemMessage(hDlg, IDC_EDIT7, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  813. SendDlgItemMessage(hDlg, IDC_EDIT8, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  814. SendDlgItemMessage(hDlg, IDC_EDIT9, EM_LIMITTEXT, MAX_CMD_LEN, 0);
  815. for(dwI = FIRSTSTRINGID ; dwI <= LASTSTRINGID ; dwI++)
  816. {
  817. LoadString( ((PROPSHEETPAGE *)lParam)->hInstance, (UINT)dwI, tbuffer, MAX_CMD_LEN);
  818. (DWORD)SendDlgItemMessage(hDlg, IDC_COMBO1, CB_ADDSTRING, 0, (LPARAM)tbuffer);
  819. }
  820. vSetGetCodePage(hDlg, &pMyStuff->iCodePage, FALSE) ; // Get code page.
  821. //** init other edit boxes with corresponding command strings from registry
  822. if(BinaryToHexString(pMyStuff->Sel_10_cpi.strCmd, szString,
  823. pMyStuff->Sel_10_cpi.dwLen, MAX_CMD_LEN + 1))
  824. SetDlgItemTextA(hDlg, IDC_EDIT1, (LPCSTR)szString);
  825. if(BinaryToHexString(pMyStuff->Sel_12_cpi.strCmd, szString,
  826. pMyStuff->Sel_12_cpi.dwLen, MAX_CMD_LEN + 1) )
  827. SetDlgItemTextA(hDlg, IDC_EDIT2, (LPCSTR)szString);
  828. if(BinaryToHexString(pMyStuff->Sel_17_cpi.strCmd, szString,
  829. pMyStuff->Sel_17_cpi.dwLen, MAX_CMD_LEN + 1) )
  830. SetDlgItemTextA(hDlg, IDC_EDIT3, (LPCSTR)szString);
  831. if(BinaryToHexString(pMyStuff->Bold_ON.strCmd, szString,
  832. pMyStuff->Bold_ON.dwLen, MAX_CMD_LEN + 1) )
  833. SetDlgItemTextA(hDlg, IDC_EDIT6, (LPCSTR)szString);
  834. if(BinaryToHexString(pMyStuff->Bold_OFF.strCmd, szString,
  835. pMyStuff->Bold_OFF.dwLen, MAX_CMD_LEN + 1) )
  836. SetDlgItemTextA(hDlg, IDC_EDIT7, (LPCSTR)szString);
  837. if(BinaryToHexString(pMyStuff->Underline_ON.strCmd, szString,
  838. pMyStuff->Underline_ON.dwLen, MAX_CMD_LEN + 1) )
  839. SetDlgItemTextA(hDlg, IDC_EDIT8, (LPCSTR)szString);
  840. if(BinaryToHexString(pMyStuff->Underline_OFF.strCmd, szString,
  841. pMyStuff->Underline_OFF.dwLen, MAX_CMD_LEN + 1) )
  842. SetDlgItemTextA(hDlg, IDC_EDIT9, (LPCSTR)szString);
  843. break;
  844. case WM_NOTIFY:
  845. pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ;
  846. if(!pGlobals)
  847. return FALSE ;
  848. pMyStuff = &pGlobals->regStruct ;
  849. switch (((LPNMHDR)lParam)->code) // type of notification message
  850. {
  851. case PSN_SETACTIVE:
  852. break;
  853. case PSN_KILLACTIVE:
  854. // case IDC_BUTTON1:
  855. // convert user command to binary and back to
  856. // verify proper entry.
  857. {
  858. //** extract all command strings
  859. GetDlgItemTextA(hDlg, IDC_EDIT1, (LPSTR)szString, MAX_CMD_LEN + 1);
  860. HexStringToBinary(szString, pMyStuff->Sel_10_cpi.strCmd,
  861. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_10_cpi.dwLen) ;
  862. GetDlgItemTextA(hDlg, IDC_EDIT2, (LPSTR)szString, MAX_CMD_LEN + 1);
  863. HexStringToBinary(szString, pMyStuff->Sel_12_cpi.strCmd,
  864. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_12_cpi.dwLen) ;
  865. GetDlgItemTextA(hDlg, IDC_EDIT3, (LPSTR)szString, MAX_CMD_LEN + 1);
  866. HexStringToBinary(szString, pMyStuff->Sel_17_cpi.strCmd,
  867. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_17_cpi.dwLen) ;
  868. GetDlgItemTextA(hDlg, IDC_EDIT6, (LPSTR)szString, MAX_CMD_LEN + 1);
  869. HexStringToBinary(szString, pMyStuff->Bold_ON.strCmd,
  870. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_ON.dwLen) ;
  871. GetDlgItemTextA(hDlg, IDC_EDIT7, (LPSTR)szString, MAX_CMD_LEN + 1);
  872. HexStringToBinary(szString, pMyStuff->Bold_OFF.strCmd,
  873. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_OFF.dwLen) ;
  874. GetDlgItemTextA(hDlg, IDC_EDIT8, (LPSTR)szString, MAX_CMD_LEN + 1);
  875. HexStringToBinary(szString, pMyStuff->Underline_ON.strCmd,
  876. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_ON.dwLen) ;
  877. GetDlgItemTextA(hDlg, IDC_EDIT9, (LPSTR)szString, MAX_CMD_LEN + 1);
  878. HexStringToBinary(szString, pMyStuff->Underline_OFF.strCmd,
  879. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_OFF.dwLen) ;
  880. // reinitialize edit boxes with binary translated strings.
  881. if(BinaryToHexString(pMyStuff->Sel_10_cpi.strCmd, szString,
  882. pMyStuff->Sel_10_cpi.dwLen, MAX_CMD_LEN + 1))
  883. SetDlgItemTextA(hDlg, IDC_EDIT1, (LPCSTR)szString);
  884. if(BinaryToHexString(pMyStuff->Sel_12_cpi.strCmd, szString,
  885. pMyStuff->Sel_12_cpi.dwLen, MAX_CMD_LEN + 1) )
  886. SetDlgItemTextA(hDlg, IDC_EDIT2, (LPCSTR)szString);
  887. if(BinaryToHexString(pMyStuff->Sel_17_cpi.strCmd, szString,
  888. pMyStuff->Sel_17_cpi.dwLen, MAX_CMD_LEN + 1) )
  889. SetDlgItemTextA(hDlg, IDC_EDIT3, (LPCSTR)szString);
  890. if(BinaryToHexString(pMyStuff->Bold_ON.strCmd, szString,
  891. pMyStuff->Bold_ON.dwLen, MAX_CMD_LEN + 1) )
  892. SetDlgItemTextA(hDlg, IDC_EDIT6, (LPCSTR)szString);
  893. if(BinaryToHexString(pMyStuff->Bold_OFF.strCmd, szString,
  894. pMyStuff->Bold_OFF.dwLen, MAX_CMD_LEN + 1) )
  895. SetDlgItemTextA(hDlg, IDC_EDIT7, (LPCSTR)szString);
  896. if(BinaryToHexString(pMyStuff->Underline_ON.strCmd, szString,
  897. pMyStuff->Underline_ON.dwLen, MAX_CMD_LEN + 1) )
  898. SetDlgItemTextA(hDlg, IDC_EDIT8, (LPCSTR)szString);
  899. if(BinaryToHexString(pMyStuff->Underline_OFF.strCmd, szString,
  900. pMyStuff->Underline_OFF.dwLen, MAX_CMD_LEN + 1) )
  901. SetDlgItemTextA(hDlg, IDC_EDIT9, (LPCSTR)szString);
  902. }
  903. break;
  904. case PSN_APPLY:
  905. {
  906. // set code page
  907. vSetGetCodePage(hDlg, &pMyStuff->iCodePage, TRUE) ;
  908. //** extract all command strings
  909. GetDlgItemTextA(hDlg, IDC_EDIT1, (LPSTR)szString, MAX_CMD_LEN + 1);
  910. HexStringToBinary(szString, pMyStuff->Sel_10_cpi.strCmd,
  911. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_10_cpi.dwLen) ;
  912. GetDlgItemTextA(hDlg, IDC_EDIT2, (LPSTR)szString, MAX_CMD_LEN + 1);
  913. HexStringToBinary(szString, pMyStuff->Sel_12_cpi.strCmd,
  914. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_12_cpi.dwLen) ;
  915. GetDlgItemTextA(hDlg, IDC_EDIT3, (LPSTR)szString, MAX_CMD_LEN + 1);
  916. HexStringToBinary(szString, pMyStuff->Sel_17_cpi.strCmd,
  917. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Sel_17_cpi.dwLen) ;
  918. GetDlgItemTextA(hDlg, IDC_EDIT6, (LPSTR)szString, MAX_CMD_LEN + 1);
  919. HexStringToBinary(szString, pMyStuff->Bold_ON.strCmd,
  920. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_ON.dwLen) ;
  921. GetDlgItemTextA(hDlg, IDC_EDIT7, (LPSTR)szString, MAX_CMD_LEN + 1);
  922. HexStringToBinary(szString, pMyStuff->Bold_OFF.strCmd,
  923. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Bold_OFF.dwLen) ;
  924. GetDlgItemTextA(hDlg, IDC_EDIT8, (LPSTR)szString, MAX_CMD_LEN + 1);
  925. HexStringToBinary(szString, pMyStuff->Underline_ON.strCmd,
  926. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_ON.dwLen) ;
  927. GetDlgItemTextA(hDlg, IDC_EDIT9, (LPSTR)szString, MAX_CMD_LEN + 1);
  928. HexStringToBinary(szString, pMyStuff->Underline_OFF.strCmd,
  929. MAX_CMD_LEN + 1, MAX_CMD_LEN, &pMyStuff->Underline_OFF.dwLen) ;
  930. // reinitialize edit boxes with binary translated strings.
  931. if(BinaryToHexString(pMyStuff->Sel_10_cpi.strCmd, szString,
  932. pMyStuff->Sel_10_cpi.dwLen, MAX_CMD_LEN + 1))
  933. SetDlgItemTextA(hDlg, IDC_EDIT1, (LPCSTR)szString);
  934. if(BinaryToHexString(pMyStuff->Sel_12_cpi.strCmd, szString,
  935. pMyStuff->Sel_12_cpi.dwLen, MAX_CMD_LEN + 1) )
  936. SetDlgItemTextA(hDlg, IDC_EDIT2, (LPCSTR)szString);
  937. if(BinaryToHexString(pMyStuff->Sel_17_cpi.strCmd, szString,
  938. pMyStuff->Sel_17_cpi.dwLen, MAX_CMD_LEN + 1) )
  939. SetDlgItemTextA(hDlg, IDC_EDIT3, (LPCSTR)szString);
  940. if(BinaryToHexString(pMyStuff->Bold_ON.strCmd, szString,
  941. pMyStuff->Bold_ON.dwLen, MAX_CMD_LEN + 1) )
  942. SetDlgItemTextA(hDlg, IDC_EDIT6, (LPCSTR)szString);
  943. if(BinaryToHexString(pMyStuff->Bold_OFF.strCmd, szString,
  944. pMyStuff->Bold_OFF.dwLen, MAX_CMD_LEN + 1) )
  945. SetDlgItemTextA(hDlg, IDC_EDIT7, (LPCSTR)szString);
  946. if(BinaryToHexString(pMyStuff->Underline_ON.strCmd, szString,
  947. pMyStuff->Underline_ON.dwLen, MAX_CMD_LEN + 1) )
  948. SetDlgItemTextA(hDlg, IDC_EDIT8, (LPCSTR)szString);
  949. if(BinaryToHexString(pMyStuff->Underline_OFF.strCmd, szString,
  950. pMyStuff->Underline_OFF.dwLen, MAX_CMD_LEN + 1) )
  951. SetDlgItemTextA(hDlg, IDC_EDIT9, (LPCSTR)szString);
  952. // store MyStuff in registry.
  953. VinitMyStuff(pGlobals, TRUE) ;
  954. }
  955. break;
  956. case PSN_RESET:
  957. break;
  958. }
  959. break;
  960. case WM_COMMAND:
  961. pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ;
  962. if(!pGlobals)
  963. return FALSE ;
  964. pMyStuff = &pGlobals->regStruct ;
  965. if(HIWORD(wParam) == EN_CHANGE)
  966. // type of notification message
  967. {
  968. switch(LOWORD(wParam))
  969. {
  970. case IDC_EDIT1:
  971. case IDC_EDIT2:
  972. case IDC_EDIT3:
  973. case IDC_EDIT6:
  974. case IDC_EDIT7:
  975. case IDC_EDIT8:
  976. case IDC_EDIT9:
  977. PropSheet_Changed(GetParent( hDlg ), hDlg);
  978. break;
  979. default:
  980. break;
  981. }
  982. }
  983. if(HIWORD(wParam) == CBN_SELCHANGE &&
  984. LOWORD(wParam) == IDC_COMBO1)
  985. PropSheet_Changed(GetParent( hDlg ), hDlg);
  986. if(HIWORD(wParam) == BN_CLICKED &&
  987. LOWORD(wParam) == IDC_CHKBOX1)
  988. PropSheet_Changed(GetParent( hDlg ), hDlg);
  989. break;
  990. case WM_HELP:
  991. case WM_CONTEXTMENU:
  992. pGlobals = (PGLOBALSTRUCT)GetWindowLongPtr(hDlg, DWLP_USER ) ;
  993. if(!pGlobals)
  994. return FALSE ;
  995. bStatus = PrintUIHelp(uiMsg, hDlg, wParam, lParam, pGlobals) ;
  996. break;
  997. }
  998. return bStatus;
  999. }
  1000. BOOL InitHelpfileName(PGLOBALSTRUCT pGlobals)
  1001. {
  1002. DWORD cbNeeded = 0;
  1003. PDRIVER_INFO_3 pdrvInfo3 = NULL;
  1004. GetPrinterDriver(pGlobals->hPrinter, NULL, 3, NULL, 0, &cbNeeded) ;
  1005. if (! (pdrvInfo3 = (PDRIVER_INFO_3)HeapAlloc(pGlobals->hOEMHeap, HEAP_ZERO_MEMORY,cbNeeded)))
  1006. return(FALSE); // Alloc failed
  1007. if(!GetPrinterDriver(pGlobals->hPrinter, NULL, 3, (LPBYTE)pdrvInfo3,
  1008. cbNeeded, &cbNeeded)){
  1009. if(NULL != pdrvInfo3 )
  1010. HeapFree(pGlobals->hOEMHeap, HEAP_ZERO_MEMORY,pdrvInfo3);
  1011. return(FALSE) ; // failed to initialize path
  1012. }
  1013. pGlobals->pwHelpFile = PwstrCreateQualifiedName(
  1014. pGlobals->hOEMHeap,
  1015. pdrvInfo3->pDriverPath,
  1016. TEXT("ttyui.hlp")
  1017. ) ;
  1018. return(TRUE);
  1019. }
  1020. PWSTR
  1021. PwstrCreateQualifiedName(
  1022. HANDLE hHeap,
  1023. PWSTR pDir,
  1024. PWSTR pFile
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. Create a fully qualified name for the directory and file name passed in.
  1029. Arguments:
  1030. pDir - Points to the path
  1031. pFile - Points to file name
  1032. hHeap - Points to the heap to allocate the returned string from.
  1033. Return Value:
  1034. Pointer to the fully qualified name.
  1035. --*/
  1036. {
  1037. DWORD dwLen, dwLenQualName;
  1038. PWSTR pBasename, pQualifiedName = NULL;
  1039. HRESULT hr = S_FALSE;
  1040. //
  1041. // Figure out the len of the directory
  1042. //
  1043. if (pBasename = wcsrchr(pDir, TEXT(PATH_SEPARATOR)))
  1044. {
  1045. pBasename++;
  1046. }
  1047. else
  1048. {
  1049. WARNING(ERRORTEXT("PwstrCreateQualifiedName(): Invalid path name.\r\n"));
  1050. return NULL;
  1051. }
  1052. dwLen = (DWORD)(pBasename - pDir) ; // number of WCHARS
  1053. dwLenQualName = dwLen + wcslen(pFile) + 1;
  1054. //
  1055. // Concatenate the input directory with the base filename
  1056. //
  1057. if (! (pQualifiedName = (PWSTR)HeapAlloc(hHeap, HEAP_ZERO_MEMORY,sizeof(WCHAR) *
  1058. dwLenQualName)))
  1059. {
  1060. WARNING(ERRORTEXT("PwstrCreateQualifiedName(): Memory allocation failed.\r\n"));
  1061. return NULL;
  1062. }
  1063. wcsncpy(pQualifiedName, pDir, dwLen);
  1064. hr = StringCchCatW(pQualifiedName, dwLenQualName, pFile);
  1065. if ( SUCCEEDED (hr) )
  1066. {
  1067. return pQualifiedName;
  1068. }
  1069. //
  1070. // If control reaches here, something went wrong while doing cat.
  1071. //
  1072. if ( pQualifiedName )
  1073. {
  1074. //
  1075. // If HeapAlloc succeeded but StringCchCat failed.
  1076. //
  1077. HeapFree ( hHeap, 0, pQualifiedName );
  1078. pQualifiedName = NULL;
  1079. }
  1080. return NULL;
  1081. }
  1082. /*++
  1083. Routine Name:
  1084. PrintUIHlep
  1085. Routine Description:
  1086. All dialogs and property sheets call this routine
  1087. to handle help. It is important that control ID's
  1088. are unique to this project for this to work.
  1089. Arguments:
  1090. UINT uMsg,
  1091. HWND hDlg,
  1092. WPARAM wParam,
  1093. LPARAM lParam
  1094. Return Value:
  1095. TRUE if help message was dislayed, FALSE if message not handled,
  1096. --*/
  1097. BOOL
  1098. PrintUIHelp(
  1099. UINT uMsg,
  1100. HWND hDlg,
  1101. WPARAM wParam,
  1102. LPARAM lParam,
  1103. PGLOBALSTRUCT pGlobals // points to private structure for static storage
  1104. )
  1105. {
  1106. BOOL bStatus = FALSE;
  1107. switch( uMsg ){
  1108. case WM_HELP:
  1109. bStatus = WinHelp(
  1110. (HWND) ((LPHELPINFO) lParam)->hItemHandle,
  1111. pGlobals->pwHelpFile,
  1112. HELP_WM_HELP,
  1113. (ULONG_PTR) (LPTSTR)aHelpIDs );
  1114. break;
  1115. case WM_CONTEXTMENU:
  1116. bStatus = WinHelp(
  1117. (HWND)wParam,
  1118. pGlobals->pwHelpFile,
  1119. HELP_CONTEXTMENU,
  1120. (ULONG_PTR) (LPTSTR)aHelpIDs );
  1121. break;
  1122. }
  1123. return bStatus;
  1124. }