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.

1006 lines
31 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: OEMUI.cpp
  9. //
  10. //
  11. // PURPOSE: Main file for OEM UI test module.
  12. //
  13. //
  14. // Functions:
  15. //
  16. //
  17. //
  18. //
  19. // PLATFORMS: Windows 2000, Windows XP, Windows Server 2003
  20. //
  21. //
  22. #include "precomp.h"
  23. #include "resource.h"
  24. #include "debug.h"
  25. #include "oemui.h"
  26. // StrSafe.h needs to be included last
  27. // to disallow bad string functions.
  28. #include <STRSAFE.H>
  29. ////////////////////////////////////////////////////////
  30. // INTERNAL MACROS and DEFINES
  31. ////////////////////////////////////////////////////////
  32. typedef struct _tagCBUserData
  33. {
  34. HANDLE hComPropSheet;
  35. HANDLE hPropPage;
  36. POEMUIPSPARAM pOEMUIParam;
  37. PFNCOMPROPSHEET pfnComPropSheet;
  38. } CBUSERDATA, *PCBUSERDATA;
  39. ////////////////////////////////////////////////////////
  40. // INTERNAL PROTOTYPES
  41. ////////////////////////////////////////////////////////
  42. static HRESULT hrDocumentPropertyPage(DWORD dwMode, POEMCUIPPARAM pOEMUIParam);
  43. static HRESULT hrPrinterPropertyPage(DWORD dwMode, POEMCUIPPARAM pOEMUIParam);
  44. LONG APIENTRY OEMPrinterUICallBack(PCPSUICBPARAM pCallbackParam, POEMCUIPPARAM pOEMUIParam);
  45. LONG APIENTRY OEMDocUICallBack(PCPSUICBPARAM pCallbackParam, POEMCUIPPARAM pOEMUIParam);
  46. LONG APIENTRY OEMDocUICallBack2(PCPSUICBPARAM pCallbackParam);
  47. INT_PTR CALLBACK DevicePropPageProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  48. static BOOL AddCustomUIHelp (HANDLE hPrinter, HANDLE hHeap, HANDLE hModule, POPTITEM pOptItem, DWORD HelpIndex, DWORD HelpFile);
  49. static POIEXT CreateOIExt(HANDLE hHeap);
  50. static POPTITEM CreateOptItems(HANDLE hHeap, DWORD dwOptItems);
  51. static void InitOptItems(POPTITEM pOptItems, DWORD dwOptItems);
  52. static POPTTYPE CreateOptType(HANDLE hHeap, WORD wOptParams);
  53. static PTSTR GetHelpFile (HANDLE hPrinter, HANDLE hHeap, HANDLE hModule, UINT uResource);
  54. static PTSTR GetStringResource(HANDLE hHeap, HANDLE hModule, UINT uResource);
  55. LPBYTE WrapGetPrinterDriver (HANDLE hHeap, HANDLE hPrinter, DWORD dwLevel);
  56. ////////////////////////////////////////////////////////////////////////////////
  57. //
  58. // Initializes OptItems to display OEM device or document property UI.
  59. // Called via IOemUI::CommonUIProp
  60. //
  61. HRESULT hrOEMPropertyPage(DWORD dwMode, POEMCUIPPARAM pOEMUIParam)
  62. {
  63. HRESULT hResult = S_OK;
  64. VERBOSE(DLLTEXT("hrOEMPropertyPage(%d) entry.\r\n"), dwMode);
  65. // Validate parameters.
  66. if( (OEMCUIP_DOCPROP != dwMode)
  67. &&
  68. (OEMCUIP_PRNPROP != dwMode)
  69. )
  70. {
  71. ERR(ERRORTEXT("hrOEMPropertyPage() ERROR_INVALID_PARAMETER.\r\n"));
  72. VERBOSE(DLLTEXT("\tdwMode = %d, pOEMUIParam = %#lx.\r\n"), dwMode, pOEMUIParam);
  73. // Return invalid parameter error.
  74. SetLastError(ERROR_INVALID_PARAMETER);
  75. return E_FAIL;
  76. }
  77. switch(dwMode)
  78. {
  79. case OEMCUIP_DOCPROP:
  80. hResult = hrDocumentPropertyPage(dwMode, pOEMUIParam);
  81. break;
  82. case OEMCUIP_PRNPROP:
  83. hResult = hrPrinterPropertyPage(dwMode, pOEMUIParam);
  84. break;
  85. default:
  86. // Should never reach this!
  87. ERR(ERRORTEXT("hrOEMPropertyPage() Invalid dwMode, %d"), dwMode);
  88. SetLastError(ERROR_INVALID_PARAMETER);
  89. hResult = E_FAIL;
  90. break;
  91. }
  92. return hResult;
  93. }
  94. ////////////////////////////////////////////////////////////////////////////////
  95. //
  96. // Initializes OptItems to display OEM document property UI.
  97. //
  98. static HRESULT hrDocumentPropertyPage(DWORD dwMode, POEMCUIPPARAM pOEMUIParam)
  99. {
  100. if(NULL == pOEMUIParam->pOEMOptItems)
  101. {
  102. // Fill in the number of OptItems to create for OEM document property UI.
  103. pOEMUIParam->cOEMOptItems = 1;
  104. VERBOSE(DLLTEXT("hrDocumentPropertyPage() requesting %d number of items.\r\n"), pOEMUIParam->cOEMOptItems);
  105. }
  106. else
  107. {
  108. POEMDEV pOEMDev = (POEMDEV) pOEMUIParam->pOEMDM;
  109. VERBOSE(DLLTEXT("hrDocumentPropertyPage() fill out %d items.\r\n"), pOEMUIParam->cOEMOptItems);
  110. // Init UI Callback reference.
  111. pOEMUIParam->OEMCUIPCallback = OEMDocUICallBack;
  112. // Init OEMOptItmes.
  113. InitOptItems(pOEMUIParam->pOEMOptItems, pOEMUIParam->cOEMOptItems);
  114. // Fill out tree view items.
  115. // New section.
  116. pOEMUIParam->pOEMOptItems[0].Level = 1;
  117. pOEMUIParam->pOEMOptItems[0].Flags = OPTIF_COLLAPSE;
  118. pOEMUIParam->pOEMOptItems[0].pName = GetStringResource(pOEMUIParam->hOEMHeap, pOEMUIParam->hModule, IDS_ADV_SECTION);
  119. pOEMUIParam->pOEMOptItems[0].Sel = pOEMDev->dwAdvancedData;
  120. pOEMUIParam->pOEMOptItems[0].pOptType= CreateOptType(pOEMUIParam->hOEMHeap, 2);
  121. //
  122. //Setup the Optional Item
  123. //
  124. pOEMUIParam->pOEMOptItems[0].pOptType->Type = TVOT_UDARROW;
  125. pOEMUIParam->pOEMOptItems[0].pOptType->pOptParam[1].IconID = 0;
  126. pOEMUIParam->pOEMOptItems[0].pOptType->pOptParam[1].lParam = 100;
  127. //
  128. //Allows You to apply Customised help to this Control.
  129. //
  130. //Notes:
  131. // You must use a fully qualified path for pHelpFile
  132. // OPTITEM Flags member must have OPTIF_HAS_POIEXT flag set. This indicates that the data in OIEXT is valid.
  133. // OPTITEM is allocated on the Heap see (AddCustomUIHelp, GetHelpFile, CreateOIExt)
  134. //
  135. AddCustomUIHelp (pOEMUIParam->hPrinter,
  136. pOEMUIParam->hOEMHeap,
  137. pOEMUIParam->hModule,
  138. &(pOEMUIParam->pOEMOptItems[0]),
  139. CUSDRV_HELPTOPIC_2, IDS_HELPFILE);
  140. }
  141. return S_OK;
  142. }
  143. ////////////////////////////////////////////////////////////////////////////////
  144. //
  145. // Initializes OptItems to display OEM printer property UI.
  146. //
  147. static HRESULT hrPrinterPropertyPage(DWORD dwMode, POEMCUIPPARAM pOEMUIParam)
  148. {
  149. if(NULL == pOEMUIParam->pOEMOptItems)
  150. {
  151. // Fill in the number of OptItems to create for OEM printer property UI.
  152. pOEMUIParam->cOEMOptItems = 1;
  153. VERBOSE(DLLTEXT("hrPrinterPropertyPage() requesting %d number of items.\r\n"), pOEMUIParam->cOEMOptItems);
  154. }
  155. else
  156. {
  157. //
  158. //This is the second time we are called Now setup the optional items.
  159. //
  160. DWORD dwError;
  161. DWORD dwDeviceValue;
  162. DWORD dwType;
  163. DWORD dwNeeded;
  164. VERBOSE(DLLTEXT("hrPrinterPropertyPage() fill out %d items.\r\n"), pOEMUIParam->cOEMOptItems);
  165. // Get device settings value from printer.
  166. dwError = GetPrinterData(pOEMUIParam->hPrinter, OEMUI_VALUE, &dwType, (PBYTE) &dwDeviceValue,
  167. sizeof(dwDeviceValue), &dwNeeded);
  168. if( (ERROR_SUCCESS != dwError)
  169. ||
  170. (dwDeviceValue > 100)
  171. )
  172. {
  173. // Failed to get the device value or value is invalid, just use the default.
  174. dwDeviceValue = 0;
  175. }
  176. // Init UI Callback reference.
  177. pOEMUIParam->OEMCUIPCallback = OEMPrinterUICallBack;
  178. // Init OEMOptItmes.
  179. InitOptItems(pOEMUIParam->pOEMOptItems, pOEMUIParam->cOEMOptItems);
  180. // Fill out tree view items.
  181. // New section.
  182. pOEMUIParam->pOEMOptItems[0].Level = 1;
  183. pOEMUIParam->pOEMOptItems[0].Flags = OPTIF_COLLAPSE;
  184. pOEMUIParam->pOEMOptItems[0].pName = GetStringResource(pOEMUIParam->hOEMHeap, pOEMUIParam->hModule, IDS_DEV_SECTION);
  185. pOEMUIParam->pOEMOptItems[0].Sel = dwDeviceValue;
  186. pOEMUIParam->pOEMOptItems[0].pOptType = CreateOptType(pOEMUIParam->hOEMHeap, 2);
  187. //
  188. //Setup the Optional Item
  189. //
  190. pOEMUIParam->pOEMOptItems[0].pOptType->Type = TVOT_UDARROW;
  191. pOEMUIParam->pOEMOptItems[0].pOptType->pOptParam[1].IconID = 0;
  192. pOEMUIParam->pOEMOptItems[0].pOptType->pOptParam[1].lParam = 100;
  193. //
  194. //Allows You to apply Customised help to this Control
  195. //
  196. AddCustomUIHelp (pOEMUIParam->hPrinter,
  197. pOEMUIParam->hOEMHeap,
  198. pOEMUIParam->hModule,
  199. &(pOEMUIParam->pOEMOptItems[0]),
  200. CUSDRV_HELPTOPIC_1,
  201. IDS_HELPFILE);
  202. }
  203. return S_OK;
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////
  206. //
  207. // Adds property page to Document property sheet. Called via IOemUI::DocumentPropertySheets
  208. //
  209. HRESULT hrOEMDocumentPropertySheets(PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam,
  210. IPrintOemDriverUI* pOEMHelp)
  211. {
  212. LONG_PTR lResult;
  213. VERBOSE(DLLTEXT("OEMDocumentPropertySheets() entry.\r\n"));
  214. // Validate parameters.
  215. if( (NULL == pPSUIInfo)
  216. ||
  217. (PROPSHEETUI_INFO_VERSION != pPSUIInfo->Version)
  218. )
  219. {
  220. ERR(ERRORTEXT("OEMDocumentPropertySheets() ERROR_INVALID_PARAMETER.\r\n"));
  221. // Return invalid parameter error.
  222. SetLastError(ERROR_INVALID_PARAMETER);
  223. return E_FAIL;
  224. }
  225. // Do action.
  226. switch(pPSUIInfo->Reason)
  227. {
  228. case PROPSHEETUI_REASON_INIT:
  229. {
  230. DWORD dwSheets = 0;
  231. PCBUSERDATA pUserData;
  232. POEMUIPSPARAM pOEMUIParam = (POEMUIPSPARAM) pPSUIInfo->lParamInit;
  233. HANDLE hHeap = pOEMUIParam->hOEMHeap;
  234. HANDLE hModule = pOEMUIParam->hModule;
  235. POEMDEV pOEMDev = (POEMDEV) pOEMUIParam->pOEMDM;
  236. COMPROPSHEETUI Sheet;
  237. // Init property page.
  238. memset(&Sheet, 0, sizeof(COMPROPSHEETUI));
  239. Sheet.cbSize = sizeof(COMPROPSHEETUI);
  240. Sheet.Flags = CPSUIF_UPDATE_PERMISSION;
  241. Sheet.hInstCaller = ghInstance;
  242. Sheet.pCallerName = GetStringResource(hHeap, ghInstance, IDS_NAME);
  243. Sheet.pHelpFile = NULL;
  244. Sheet.pfnCallBack = OEMDocUICallBack2;
  245. Sheet.pDlgPage = CPSUI_PDLGPAGE_TREEVIEWONLY;
  246. Sheet.cOptItem = 1;
  247. Sheet.IconID = IDI_CPSUI_PRINTER;
  248. Sheet.pOptItemName = GetStringResource(hHeap, ghInstance, IDS_SECTION);
  249. Sheet.CallerVersion = 0x100;
  250. Sheet.OptItemVersion = 0x100;
  251. // Init user data.
  252. pUserData = (PCBUSERDATA) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(CBUSERDATA));
  253. pUserData->hComPropSheet = pPSUIInfo->hComPropSheet;
  254. pUserData->pfnComPropSheet = pPSUIInfo->pfnComPropSheet;
  255. pUserData->pOEMUIParam = pOEMUIParam;
  256. Sheet.UserData = (ULONG_PTR) pUserData;
  257. // Create OptItems for page.
  258. Sheet.pOptItem = CreateOptItems(hHeap, Sheet.cOptItem);
  259. // Initialize OptItems
  260. Sheet.pOptItem[0].Level = 1;
  261. Sheet.pOptItem[0].Flags = OPTIF_COLLAPSE;
  262. Sheet.pOptItem[0].pName = GetStringResource(hHeap, ghInstance, IDS_SECTION);
  263. Sheet.pOptItem[0].Sel = pOEMDev->dwDriverData;
  264. Sheet.pOptItem[0].pOptType = CreateOptType(hHeap, 2);
  265. //
  266. //Set the UI prop of this OPTYPE item.
  267. //
  268. Sheet.pOptItem[0].pOptType->Type = TVOT_UDARROW;
  269. Sheet.pOptItem[0].pOptType->pOptParam[1].IconID = 0;
  270. Sheet.pOptItem[0].pOptType->pOptParam[1].lParam = 100;
  271. //
  272. //Allows You to apply Customised help to this Control.
  273. //See Function : AddCustomUIHelp, For more details on implamentation.
  274. //
  275. AddCustomUIHelp (pOEMUIParam->hPrinter,
  276. hHeap,
  277. hModule,
  278. &(Sheet.pOptItem[0]),
  279. CUSDRV_HELPTOPIC_1,
  280. IDS_HELPFILE);
  281. // Adds the property sheets.
  282. lResult = pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet, CPSFUNC_ADD_PCOMPROPSHEETUI,
  283. (LPARAM)&Sheet, (LPARAM)&dwSheets);
  284. }
  285. break;
  286. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  287. {
  288. PPROPSHEETUI_INFO_HEADER pHeader = (PPROPSHEETUI_INFO_HEADER) lParam;
  289. pHeader->pTitle = (LPTSTR)PROP_TITLE;
  290. lResult = TRUE;
  291. }
  292. break;
  293. case PROPSHEETUI_REASON_GET_ICON:
  294. // No icon
  295. lResult = 0;
  296. break;
  297. case PROPSHEETUI_REASON_SET_RESULT:
  298. {
  299. PSETRESULT_INFO pInfo = (PSETRESULT_INFO) lParam;
  300. lResult = pInfo->Result;
  301. }
  302. break;
  303. case PROPSHEETUI_REASON_DESTROY:
  304. lResult = TRUE;
  305. break;
  306. }
  307. pPSUIInfo->Result = lResult;
  308. return S_OK;
  309. }
  310. ////////////////////////////////////////////////////////////////////////////////
  311. //
  312. // Adds property page to printer property sheet. Called via IOemUI::DevicePropertySheets
  313. //
  314. HRESULT hrOEMDevicePropertySheets(PPROPSHEETUI_INFO pPSUIInfo, LPARAM lParam)
  315. {
  316. LONG_PTR lResult;
  317. VERBOSE(DLLTEXT("hrOEMDevicePropertySheets(%#x, %#x) entry\r\n"), pPSUIInfo, lParam);
  318. // Validate parameters.
  319. if( (NULL == pPSUIInfo)
  320. ||
  321. (PROPSHEETUI_INFO_VERSION != pPSUIInfo->Version)
  322. )
  323. {
  324. ERR(ERRORTEXT("hrOEMDevicePropertySheets() ERROR_INVALID_PARAMETER.\r\n"));
  325. // Return invalid parameter error.
  326. SetLastError(ERROR_INVALID_PARAMETER);
  327. return E_FAIL;
  328. }
  329. Dump(pPSUIInfo);
  330. // Do action.
  331. switch(pPSUIInfo->Reason)
  332. {
  333. case PROPSHEETUI_REASON_INIT:
  334. {
  335. PROPSHEETPAGE Page;
  336. // Init property page.
  337. memset(&Page, 0, sizeof(PROPSHEETPAGE));
  338. Page.dwSize = sizeof(PROPSHEETPAGE);
  339. Page.dwFlags = PSP_DEFAULT;
  340. Page.hInstance = ghInstance;
  341. Page.pszTemplate = MAKEINTRESOURCE(IDD_DEVICE_PROPPAGE);
  342. Page.pfnDlgProc = DevicePropPageProc;
  343. // Add property sheets.
  344. lResult = pPSUIInfo->pfnComPropSheet(pPSUIInfo->hComPropSheet, CPSFUNC_ADD_PROPSHEETPAGE, (LPARAM)&Page, 0);
  345. VERBOSE(DLLTEXT("hrOEMDevicePropertySheets() pfnComPropSheet returned %d.\r\n"), lResult);
  346. }
  347. break;
  348. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  349. {
  350. PPROPSHEETUI_INFO_HEADER pHeader = (PPROPSHEETUI_INFO_HEADER) lParam;
  351. pHeader->pTitle = (LPTSTR)PROP_TITLE;
  352. lResult = TRUE;
  353. }
  354. break;
  355. case PROPSHEETUI_REASON_GET_ICON:
  356. // No icon
  357. lResult = 0;
  358. break;
  359. case PROPSHEETUI_REASON_SET_RESULT:
  360. {
  361. PSETRESULT_INFO pInfo = (PSETRESULT_INFO) lParam;
  362. lResult = pInfo->Result;
  363. }
  364. break;
  365. case PROPSHEETUI_REASON_DESTROY:
  366. lResult = TRUE;
  367. break;
  368. }
  369. pPSUIInfo->Result = lResult;
  370. return S_OK;
  371. }
  372. ////////////////////////////////////////////////////////////////////////////////
  373. //
  374. // OptItems call back for OEM printer property UI.
  375. //
  376. LONG APIENTRY OEMPrinterUICallBack(PCPSUICBPARAM pCallbackParam, POEMCUIPPARAM pOEMUIParam)
  377. {
  378. LONG lReturn = CPSUICB_ACTION_NONE;
  379. POEMDEV pOEMDev = (POEMDEV) pOEMUIParam->pOEMDM;
  380. VERBOSE(DLLTEXT("OEMPrinterUICallBack() entry, Reason is %d.\r\n"), pCallbackParam->Reason);
  381. switch(pCallbackParam->Reason)
  382. {
  383. case CPSUICB_REASON_APPLYNOW:
  384. {
  385. DWORD dwDriverValue = pOEMUIParam->pOEMOptItems[0].Sel;
  386. // Store OptItems state in printer data.
  387. SetPrinterData(pOEMUIParam->hPrinter, OEMUI_VALUE, REG_DWORD, (PBYTE) &dwDriverValue, sizeof(DWORD));
  388. }
  389. break;
  390. default:
  391. break;
  392. }
  393. return lReturn;
  394. }
  395. ////////////////////////////////////////////////////////////////////////////////
  396. //
  397. // Call back for OEM device property UI.
  398. //
  399. INT_PTR CALLBACK DevicePropPageProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  400. {
  401. switch (uiMsg)
  402. {
  403. case WM_COMMAND:
  404. switch(HIWORD(wParam))
  405. {
  406. case BN_CLICKED:
  407. switch(LOWORD(wParam))
  408. {
  409. case IDC_CALIBRATE:
  410. // Just display a message that the printer is calibrated,
  411. // since we don't acutally calibrate anything.
  412. {
  413. TCHAR szName[MAX_PATH];
  414. TCHAR szCalibrated[MAX_PATH];
  415. LoadString(ghInstance, IDS_NAME, szName, sizeof(szName)/sizeof(szName[0]));
  416. LoadString(ghInstance, IDS_CALIBRATED, szCalibrated, sizeof(szCalibrated)/sizeof(szCalibrated[0]));
  417. MessageBox(hDlg, szCalibrated, szName, MB_OK);
  418. }
  419. break;
  420. }
  421. break;
  422. default:
  423. return FALSE;
  424. }
  425. return TRUE;
  426. case WM_NOTIFY:
  427. {
  428. switch (((LPNMHDR)lParam)->code) // type of notification message
  429. {
  430. case PSN_SETACTIVE:
  431. break;
  432. case PSN_KILLACTIVE:
  433. break;
  434. case PSN_APPLY:
  435. break;
  436. case PSN_RESET:
  437. break;
  438. }
  439. }
  440. break;
  441. }
  442. return FALSE;
  443. }
  444. ////////////////////////////////////////////////////////////////////////////////
  445. //
  446. // OptItems call back for OEM document property UI.
  447. //
  448. LONG APIENTRY OEMDocUICallBack(PCPSUICBPARAM pCallbackParam, POEMCUIPPARAM pOEMUIParam)
  449. {
  450. LONG lReturn = CPSUICB_ACTION_NONE;
  451. POEMDEV pOEMDev = (POEMDEV) pOEMUIParam->pOEMDM;
  452. VERBOSE(DLLTEXT("OEMDocUICallBack() entry, Reason is %d.\r\n"), pCallbackParam->Reason);
  453. switch(pCallbackParam->Reason)
  454. {
  455. case CPSUICB_REASON_APPLYNOW:
  456. // Store OptItems state in DEVMODE.
  457. pOEMDev->dwAdvancedData = pOEMUIParam->pOEMOptItems[0].Sel;
  458. break;
  459. case CPSUICB_REASON_KILLACTIVE:
  460. pOEMDev->dwAdvancedData = pOEMUIParam->pOEMOptItems[0].Sel;
  461. break;
  462. case CPSUICB_REASON_SETACTIVE:
  463. if(pOEMUIParam->pOEMOptItems[0].Sel != pOEMDev->dwAdvancedData)
  464. {
  465. pOEMUIParam->pOEMOptItems[0].Sel = pOEMDev->dwAdvancedData;
  466. pOEMUIParam->pOEMOptItems[0].Flags |= OPTIF_CHANGED;
  467. lReturn = CPSUICB_ACTION_OPTIF_CHANGED;
  468. }
  469. break;
  470. default:
  471. break;
  472. }
  473. return lReturn;
  474. }
  475. LONG APIENTRY OEMDocUICallBack2(PCPSUICBPARAM pCallbackParam)
  476. {
  477. LONG lReturn = CPSUICB_ACTION_NONE;
  478. PCBUSERDATA pUserData = (PCBUSERDATA) pCallbackParam->UserData;
  479. POEMDEV pOEMDev = (POEMDEV) pUserData->pOEMUIParam->pOEMDM;
  480. VERBOSE(DLLTEXT("OEMDocUICallBack2() entry, Reason is %d.\r\n"), pCallbackParam->Reason);
  481. switch(pCallbackParam->Reason)
  482. {
  483. case CPSUICB_REASON_APPLYNOW:
  484. pOEMDev->dwDriverData = pCallbackParam->pOptItem[0].Sel;
  485. pUserData->pfnComPropSheet(pUserData->hComPropSheet, CPSFUNC_SET_RESULT,
  486. (LPARAM)pUserData->hPropPage,
  487. (LPARAM)CPSUI_OK);
  488. break;
  489. case CPSUICB_REASON_KILLACTIVE:
  490. pOEMDev->dwDriverData = pCallbackParam->pOptItem[0].Sel;
  491. break;
  492. case CPSUICB_REASON_SETACTIVE:
  493. if(pCallbackParam->pOptItem[0].Sel != pOEMDev->dwDriverData)
  494. {
  495. pCallbackParam->pOptItem[0].Sel = pOEMDev->dwDriverData;
  496. pCallbackParam->pOptItem[0].Flags |= OPTIF_CHANGED;
  497. lReturn = CPSUICB_ACTION_OPTIF_CHANGED;
  498. }
  499. break;
  500. default:
  501. break;
  502. }
  503. return lReturn;
  504. }
  505. ////////////////////////////////////////////////////////////////////////////////
  506. //
  507. // Creates and Initializes OptItems.
  508. //
  509. static POPTITEM CreateOptItems(HANDLE hHeap, DWORD dwOptItems)
  510. {
  511. POPTITEM pOptItems = NULL;
  512. // Allocate memory for OptItems;
  513. pOptItems = (POPTITEM) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(OPTITEM) * dwOptItems);
  514. if(NULL != pOptItems)
  515. {
  516. InitOptItems(pOptItems, dwOptItems);
  517. }
  518. else
  519. {
  520. ERR(ERRORTEXT("CreateOptItems() failed to allocate memory for OPTITEMs!\r\n"));
  521. }
  522. return pOptItems;
  523. }
  524. ////////////////////////////////////////////////////////////////////////////////
  525. //
  526. // Initializes OptItems.
  527. //
  528. static void InitOptItems(POPTITEM pOptItems, DWORD dwOptItems)
  529. {
  530. VERBOSE(DLLTEXT("InitOptItems() entry.\r\n"));
  531. // Zero out memory.
  532. memset(pOptItems, 0, sizeof(OPTITEM) * dwOptItems);
  533. // Set each OptItem's size, and Public DM ID.
  534. for(DWORD dwCount = 0; dwCount < dwOptItems; dwCount++)
  535. {
  536. pOptItems[dwCount].cbSize = sizeof(OPTITEM);
  537. pOptItems[dwCount].DMPubID = DMPUB_NONE;
  538. }
  539. }
  540. ////////////////////////////////////////////////////////////////////////////////
  541. //
  542. // Adds Custom help top a OPTTYPE UI item.
  543. //
  544. // Note :
  545. // The OPTITEM member HelpIndex must be set the the correct HELP ID number.
  546. // HelpIndex is the index that you assigned in the hlp file to this item of help.
  547. // The OPTITEM, pOIExt member must point to a valid OIEXT structure.
  548. // The phelpfile is member of OIEXT must have the fully qualified path to the driver file.
  549. //
  550. //
  551. // It is also possible to overide common help items in UNIDRIVE via the HelpIndex in the GPD.
  552. // For further information on using HelpIndex in the GPD see the relavent section in the DDK
  553. // It is not possible to custimse help however via the PPD. The OPTITEM must be modified in the OEM Plugin.
  554. //
  555. static BOOL AddCustomUIHelp (HANDLE hPrinter, HANDLE hHeap, HANDLE hModule,
  556. POPTITEM pOptItem, DWORD HelpIndex, DWORD HelpFile)
  557. {
  558. VERBOSE(DLLTEXT("AddCustomUIHelp() entry.\r\n"));
  559. POIEXT pOIExt = NULL;
  560. //
  561. //Allocate a new OIEXT structure on the heap
  562. //
  563. if (pOptItem->pOIExt == NULL)
  564. {
  565. pOptItem->pOIExt = CreateOIExt(hHeap);
  566. }
  567. if ( pOptItem->pOIExt == NULL )
  568. {
  569. ERR(ERRORTEXT("AddCustomUIHelp() Error Allocation Failed.\r\n"));
  570. return FALSE;
  571. }
  572. pOIExt = pOptItem->pOIExt;
  573. //
  574. //Set to the full absolute path of the driver file.
  575. //(It should be in the Printer Driver Directrory in most cases)
  576. //This String needs to be allocated on the heap (The Driver will clean it up).
  577. //
  578. pOIExt->pHelpFile = GetHelpFile (hPrinter, hHeap, hModule, HelpFile);
  579. //
  580. //Set to show tha there is a valid OIEXT structure and data
  581. //
  582. pOptItem->Flags |= OPTIF_HAS_POIEXT;
  583. //
  584. //This needs to be set if you have ansi strings in your help file. (NOTE!)
  585. //
  586. //pOiExt->Flags |= OIEXTF_ANSI_STRING;
  587. //
  588. //Add the help this the index in the .hlp file.
  589. //
  590. pOptItem->HelpIndex = HelpIndex;
  591. return TRUE;
  592. }
  593. ////////////////////////////////////////////////////////////////////////////////
  594. //
  595. // Allocates and initializes OIEXT for OptItem.
  596. //
  597. static POIEXT CreateOIExt(HANDLE hHeap)
  598. {
  599. POIEXT pOiExt = NULL;
  600. VERBOSE(DLLTEXT("CreateOIExt() entry.\r\n"));
  601. // Allocate memory from the heap for the OPTTYPE; the driver will take care of clean up.
  602. pOiExt = (POIEXT) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(OIEXT));
  603. if(NULL != pOiExt)
  604. {
  605. //
  606. // Initialize OPTTYPE. (These members are setup by AddCustomUIHelp)
  607. //
  608. pOiExt->cbSize = sizeof(OIEXT);
  609. pOiExt->Flags = 0;
  610. pOiExt->hInstCaller = NULL;
  611. pOiExt->pHelpFile = NULL;
  612. }
  613. return pOiExt;
  614. }
  615. ////////////////////////////////////////////////////////////////////////////////
  616. //
  617. // Allocates and initializes OptType for OptItem.
  618. //
  619. static POPTTYPE CreateOptType(HANDLE hHeap, WORD wOptParams)
  620. {
  621. POPTTYPE pOptType = NULL;
  622. VERBOSE(DLLTEXT("CreateOptType() entry.\r\n"));
  623. // Allocate memory from the heap for the OPTTYPE; the driver will take care of clean up.
  624. pOptType = (POPTTYPE) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(OPTTYPE));
  625. if(NULL != pOptType)
  626. {
  627. // Initialize OPTTYPE.
  628. pOptType->cbSize = sizeof(OPTTYPE);
  629. pOptType->Count = wOptParams;
  630. // Allocate memory from the heap for the OPTPARAMs for the OPTTYPE.
  631. pOptType->pOptParam = (POPTPARAM) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, wOptParams * sizeof(OPTPARAM));
  632. if(NULL != pOptType->pOptParam)
  633. {
  634. // Initialize the OPTPARAMs.
  635. for(WORD wCount = 0; wCount < wOptParams; wCount++)
  636. {
  637. pOptType->pOptParam[wCount].cbSize = sizeof(OPTPARAM);
  638. }
  639. }
  640. else
  641. {
  642. ERR(ERRORTEXT("CreateOptType() failed to allocated memory for OPTPARAMs!\r\n"));
  643. // Free allocated memory and return NULL.
  644. HeapFree(hHeap, 0, pOptType);
  645. pOptType = NULL;
  646. }
  647. }
  648. else
  649. {
  650. ERR(ERRORTEXT("CreateOptType() failed to allocated memory for OPTTYPE!\r\n"));
  651. }
  652. return pOptType;
  653. }
  654. ////////////////////////////////////////////////////////////////////////////////
  655. //
  656. // Allocates space on the heap and gets the help file name from the resource file.
  657. // Note you need to allocate this on the heap so that it stays allocated as long as the driver UI is loaded.
  658. // The OPTITEM->pOIExt ref this data.
  659. //
  660. static PTSTR GetHelpFile (HANDLE hPrinter, HANDLE hHeap, HANDLE hModule, UINT uResource)
  661. {
  662. DWORD nResult = 0;
  663. DWORD dwSize = MAX_PATH;
  664. PTSTR pszString = NULL;
  665. PTSTR pszTemp = NULL;
  666. PDRIVER_INFO_2 pDriverInfo = NULL;
  667. VERBOSE(DLLTEXT("GetHelpFile (%#x, %#x, %d) entered.\r\n"), hHeap, hModule, uResource);
  668. //
  669. // Allocate buffer for string resource from heap;
  670. //
  671. pszTemp = (PTSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize * sizeof(TCHAR));
  672. pDriverInfo = (PDRIVER_INFO_2)WrapGetPrinterDriver (hHeap, hPrinter, 2);
  673. //
  674. //Get the Full Driver Dir from pDriverPath it must include the \version\
  675. //
  676. if(NULL != pszTemp && pDriverInfo && pDriverInfo->pDriverPath)
  677. {
  678. HRESULT hCopy;
  679. hCopy = StringCchCopy(pszTemp, dwSize, pDriverInfo->pDriverPath);
  680. if(FAILED(hCopy))
  681. {
  682. ERR(ERRORTEXT("StringCchCopy() failed to copy driver path to temp buffer!\r\n"));
  683. }
  684. pszString = _tcsrchr (pszTemp, _T('\\') ) + 1;
  685. }
  686. //
  687. //The Help file is installed with the driver in the version drictory.
  688. //
  689. if(NULL != pszString)
  690. {
  691. //
  692. //The Buffer size is in characters for the unicode version of LoadString
  693. //
  694. nResult = LoadString((HMODULE)hModule, uResource, pszString, (dwSize - _tcslen(pszTemp)) );
  695. }
  696. else
  697. {
  698. ERR(ERRORTEXT("GetStringResource() failed to allocate string buffer!\r\n"));
  699. }
  700. if(nResult > 0)
  701. {
  702. //
  703. //Reallocate this so that we don't waist space on the heap (free any non used heap in MAX_PATH)
  704. //
  705. pszString = (PTSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, pszTemp, (_tcslen(pszTemp) + 1) * sizeof(TCHAR));
  706. if(NULL == pszString)
  707. {
  708. pszTemp = pszString;
  709. ERR(ERRORTEXT("GetStringResource() HeapReAlloc() of string retrieved failed! (Last Error was %d)\r\n"), GetLastError());
  710. }
  711. }
  712. else
  713. {
  714. ERR(ERRORTEXT("LoadString() returned %d! (Last Error was %d)\r\n"), nResult, GetLastError());
  715. ERR(ERRORTEXT("GetStringResource() failed to load string resource %d!\r\n"), uResource);
  716. pszString = NULL;
  717. }
  718. //
  719. //Clean up the Driverinfo that was allocated. It is not needed. (Always free this it is only temp data)
  720. //
  721. if (pDriverInfo)
  722. {
  723. HeapFree(hHeap, 0, pDriverInfo);
  724. }
  725. return pszString;
  726. }
  727. ////////////////////////////////////////////////////////////////////////////////////
  728. //
  729. // Retrieves pointer to a String resource.
  730. //
  731. static PTSTR GetStringResource(HANDLE hHeap, HANDLE hModule, UINT uResource)
  732. {
  733. int nResult;
  734. DWORD dwSize = MAX_PATH;
  735. PTSTR pszString = NULL;
  736. VERBOSE(DLLTEXT("GetStringResource(%#x, %#x, %d) entered.\r\n"), hHeap, hModule, uResource);
  737. // Allocate buffer for string resource from heap; let the driver clean it up.
  738. pszString = (PTSTR) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize * sizeof(TCHAR));
  739. if(NULL != pszString)
  740. {
  741. // Load string resource; resize after loading so as not to waste memory.
  742. nResult = LoadString((HMODULE)hModule, uResource, pszString, dwSize);
  743. if(nResult > 0)
  744. {
  745. PTSTR pszTemp;
  746. VERBOSE(DLLTEXT("LoadString() returned %d!\r\n"), nResult);
  747. VERBOSE(DLLTEXT("String load was \"%s\".\r\n"), pszString);
  748. pszTemp = (PTSTR) HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, pszString, (nResult + 1) * sizeof(TCHAR));
  749. if(NULL != pszTemp)
  750. {
  751. pszString = pszTemp;
  752. }
  753. else
  754. {
  755. ERR(ERRORTEXT("GetStringResource() HeapReAlloc() of string retrieved failed! (Last Error was %d)\r\n"), GetLastError());
  756. }
  757. }
  758. else
  759. {
  760. ERR(ERRORTEXT("LoadString() returned %d! (Last Error was %d)\r\n"), nResult, GetLastError());
  761. ERR(ERRORTEXT("GetStringResource() failed to load string resource %d!\r\n"), uResource);
  762. pszString = NULL;
  763. }
  764. }
  765. else
  766. {
  767. ERR(ERRORTEXT("GetStringResource() failed to allocate string buffer!\r\n"));
  768. }
  769. return pszString;
  770. }
  771. ////////////////////////////////////////////////////////////////////////////////////
  772. //
  773. // Wrapper to help retrive the PrinterDriverInfo,
  774. // Note the MEM is orphaned by this call on success
  775. //
  776. LPBYTE WrapGetPrinterDriver (HANDLE hHeap, HANDLE hPrinter, DWORD dwLevel)
  777. {
  778. //
  779. //Get the PrinterINFO so that we know where the driver help file is.
  780. //
  781. BOOL bGet = TRUE;
  782. DWORD dwSize = 0;
  783. DWORD dwNeeded = 0;
  784. DWORD dwError = ERROR_SUCCESS;
  785. DWORD dwLoop = 0;
  786. LPBYTE pBuffer = NULL;
  787. do
  788. {
  789. if(!bGet && (dwError == ERROR_INSUFFICIENT_BUFFER ) )
  790. {
  791. dwSize = dwNeeded;
  792. if (pBuffer)
  793. {
  794. PBYTE pTemp;
  795. pTemp = (LPBYTE)HeapReAlloc (hHeap, HEAP_ZERO_MEMORY, (LPVOID)pBuffer, dwSize);
  796. if(NULL != pTemp)
  797. {
  798. pBuffer = pTemp;
  799. }
  800. }
  801. else
  802. {
  803. pBuffer = (LPBYTE)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, dwSize);
  804. }
  805. }
  806. bGet = GetPrinterDriver(hPrinter, NULL, dwLevel, pBuffer, dwSize, &dwNeeded);
  807. dwError = GetLastError();
  808. } while (!bGet && (dwLoop++ < 4));
  809. if(!bGet)
  810. {
  811. if (pBuffer)
  812. {
  813. HeapFree(hHeap, 0, pBuffer);
  814. pBuffer = NULL;
  815. }
  816. ERR(ERRORTEXT("GetPrinterDriver(%p, %d, %p, %d) failed with error %d."),
  817. hPrinter, dwLevel, pBuffer, dwError);
  818. }
  819. return pBuffer;
  820. }