Source code of Windows XP (NT5)
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.

614 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. Prop.c
  6. Abstract:
  7. Handles new entry points to document and device properties.
  8. Public Entrypoints:
  9. DocumentPropertySheets
  10. DevicePropertySheets
  11. Author:
  12. Albert Ting (AlbertT) 25-Sept-1995
  13. Steve Kiraly (SteveKi) 02-Feb-1996
  14. Environment:
  15. User Mode -Win32
  16. Revision History:
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #include "client.h"
  21. #include "winddiui.h"
  22. //
  23. // UI user data structure definition.
  24. //
  25. typedef struct _UIUserData
  26. {
  27. HANDLE hModule;
  28. LPWSTR pszTitle;
  29. } UIUserData;
  30. BOOL
  31. CreateUIUserData(
  32. IN OUT UIUserData **pData,
  33. IN HANDLE hPrinter
  34. )
  35. /*++
  36. Routine Description:
  37. This function creates the UI user data and loads the printer
  38. driver UI module.
  39. Arguments:
  40. pData pointer to where to return the pointer to the UI user data
  41. hPrinter handle to the open printer
  42. Return Value:
  43. TRUE the UI user data was alloceted, FALSE error occurred.
  44. --*/
  45. {
  46. SPLASSERT( pData );
  47. //
  48. // Allocate the UI user data.
  49. //
  50. *pData = AllocSplMem( sizeof( UIUserData ) );
  51. if( *pData )
  52. {
  53. //
  54. // The title is not allocated initaly.
  55. //
  56. (*pData)->pszTitle = NULL;
  57. //
  58. // Load the printer driver UI module.
  59. //
  60. (*pData)->hModule = LoadPrinterDriver( hPrinter );
  61. if( !(*pData)->hModule )
  62. {
  63. FreeSplMem( *pData );
  64. *pData = NULL;
  65. }
  66. }
  67. return !!*pData;
  68. }
  69. VOID
  70. DestroyUIUserData(
  71. IN UIUserData **pData
  72. )
  73. /*++
  74. Routine Description:
  75. This function destroys the UI user data and unloads the printer
  76. driver UI module.
  77. Arguments:
  78. pData pointer to the UI user data
  79. Return Value:
  80. Nothing.
  81. --*/
  82. {
  83. if( pData && *pData )
  84. {
  85. if( (*pData)->hModule )
  86. {
  87. RefCntUnloadDriver( (*pData)->hModule, TRUE );
  88. (*pData)->hModule = NULL;
  89. }
  90. if( (*pData)->pszTitle )
  91. {
  92. FreeSplMem( (*pData)->pszTitle );
  93. (*pData)->pszTitle = NULL;
  94. }
  95. FreeSplMem( *pData );
  96. *pData = NULL;
  97. }
  98. }
  99. VOID
  100. CreatePrinterFriendlyName(
  101. IN UIUserData *pData,
  102. IN LPCWSTR pszName
  103. )
  104. /*++
  105. Routine Description:
  106. This function creates the printer friendly name and stores
  107. the new name in the UIUserData.
  108. Arguments:
  109. pData pointer to the UI user data
  110. pszName pointer to the unfriendly printer name
  111. Return Value:
  112. Nothing. If the operation fails the unfriendly name is used.
  113. --*/
  114. {
  115. UINT nSize = 0;
  116. HINSTANCE hModule = NULL;
  117. BOOL bStatus = FALSE;
  118. //
  119. // Load printui, which knows how to format the friendly name.
  120. //
  121. hModule = LoadLibrary( szPrintUIDll );
  122. if( hModule )
  123. {
  124. typedef BOOL (*pfConstructPrinterFriendlyName)( LPCWSTR, LPWSTR, UINT * );
  125. pfConstructPrinterFriendlyName pfn;
  126. pfn = (pfConstructPrinterFriendlyName)GetProcAddress( hModule, szConstructPrinterFriendlyName );
  127. if( pfn )
  128. {
  129. //
  130. // Query for the friendly name size.
  131. //
  132. if( !pfn( pszName, NULL, &nSize ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  133. {
  134. //
  135. // Allocate the friendly name buffer.
  136. //
  137. pData->pszTitle = AllocSplMem( (nSize+1) * sizeof(WCHAR) );
  138. if( pData->pszTitle )
  139. {
  140. //
  141. // Get the printer friendly name.
  142. //
  143. bStatus = pfn( pszName, pData->pszTitle, &nSize );
  144. }
  145. }
  146. }
  147. //
  148. // Release the library.
  149. //
  150. FreeLibrary( hModule );
  151. }
  152. //
  153. // Something failed use the unfriendly name.
  154. //
  155. if( !bStatus )
  156. {
  157. FreeSplMem( pData->pszTitle );
  158. pData->pszTitle = AllocSplStr( pszName );
  159. }
  160. }
  161. BOOL
  162. FixUpDEVMODEName(
  163. PDOCUMENTPROPERTYHEADER pDPHdr
  164. )
  165. /*++
  166. Routine Description:
  167. This function fixed up the returned DEVMODE with friendly printer name
  168. in the dmDeviceName field (cut off at 31 character as CCHDEVICENAME)
  169. Arguments:
  170. pDPHdr - Pointer to the DOCUMENTPROPERTYHEADER structure
  171. Return Value:
  172. TRUE if frendly name is copied, FALSE otherwise
  173. Author:
  174. 08-Jul-1996 Mon 13:36:09 created -by- Daniel Chou (danielc)
  175. Revision History:
  176. --*/
  177. {
  178. PPRINTER_INFO_2 pPI2 = NULL;
  179. DWORD cbNeed = 0;
  180. DWORD cbRet = 0;
  181. BOOL bCopy = FALSE;
  182. if ((pDPHdr->fMode & (DM_COPY | DM_UPDATE)) &&
  183. (!(pDPHdr->fMode & DM_NOPERMISSION)) &&
  184. (pDPHdr->pdmOut) &&
  185. (!GetPrinter(pDPHdr->hPrinter, 2, NULL, 0, &cbNeed)) &&
  186. (GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
  187. (pPI2 = AllocSplMem(cbNeed)) &&
  188. (GetPrinter(pDPHdr->hPrinter, 2, (LPBYTE)pPI2, cbNeed, &cbRet)) &&
  189. (cbNeed == cbRet)) {
  190. wcsncpy(pDPHdr->pdmOut->dmDeviceName,
  191. pPI2->pPrinterName,
  192. CCHDEVICENAME - 1);
  193. pDPHdr->pdmOut->dmDeviceName[CCHDEVICENAME - 1] = L'\0';
  194. bCopy = TRUE;
  195. }
  196. if (pPI2) {
  197. FreeSplMem(pPI2);
  198. }
  199. return(bCopy);
  200. }
  201. LONG_PTR
  202. DevicePropertySheets(
  203. PPROPSHEETUI_INFO pCPSUIInfo,
  204. LPARAM lParam
  205. )
  206. /*++
  207. Routine Description:
  208. Adds the device specific printer pages. This replaces
  209. PrinterProperties.
  210. Arguments:
  211. pCPSUIInfo - pointer to common ui info header.
  212. lParam - user defined lparam, see compstui for details.
  213. \nt\public\oak\inc\compstui.h
  214. Return Value:
  215. Returns > 0 if success
  216. Returns <= 0 if failure
  217. --*/
  218. {
  219. PDEVICEPROPERTYHEADER pDevPropHdr = NULL;
  220. PPROPSHEETUI_INFO_HEADER pCPSUIInfoHdr = NULL;
  221. PSETRESULT_INFO pSetResultInfo = NULL;
  222. LONG_PTR lResult = FALSE;
  223. HANDLE hModule = NULL;
  224. INT_FARPROC pfn = NULL;
  225. extern HANDLE hInst;
  226. DBGMSG( DBG_TRACE, ("DrvDevicePropertySheets\n") );
  227. //
  228. // Ony compstui requests, are acknowledged.
  229. //
  230. if (pCPSUIInfo) {
  231. if ((!(pDevPropHdr = (PDEVICEPROPERTYHEADER)pCPSUIInfo->lParamInit)) ||
  232. (pDevPropHdr->cbSize < sizeof(DEVICEPROPERTYHEADER))) {
  233. SetLastError(ERROR_INVALID_PARAMETER);
  234. return 0;
  235. }
  236. switch (pCPSUIInfo->Reason) {
  237. case PROPSHEETUI_REASON_INIT:
  238. DBGMSG( DBG_TRACE, ( "DrvDevicePropertySheets PROPSHEETUI_REASON_INIT\n") );
  239. //
  240. // Create the UI User data.
  241. //
  242. if( CreateUIUserData( &(UIUserData *)(pCPSUIInfo->UserData), pDevPropHdr->hPrinter ) ){
  243. if( ((UIUserData *)(pCPSUIInfo->UserData))->hModule ){
  244. //
  245. // Get the driver property sheet entry.
  246. //
  247. if ((pfn = (INT_FARPROC)GetProcAddress( ((UIUserData *)(pCPSUIInfo->UserData))->hModule, szDrvDevPropSheets))) {
  248. //
  249. // Before calling into the driver to add pages make sure the proper
  250. // fusion activation context is set.
  251. //
  252. lResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  253. CPSFUNC_SET_FUSION_CONTEXT,
  254. (LPARAM)ACTCTX_EMPTY,
  255. (LPARAM)0);
  256. //
  257. // Common ui will call the driver to add it's sheets.
  258. //
  259. lResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  260. CPSFUNC_ADD_PFNPROPSHEETUI,
  261. (LPARAM)pfn,
  262. pCPSUIInfo->lParamInit );
  263. }
  264. }
  265. }
  266. //
  267. // If something failed ensure we free the library
  268. // if it was loaded.
  269. //
  270. if( lResult <= 0 ){
  271. DBGMSG( DBG_TRACE, ( "DrvDevicePropertySheets PROPSHEETUI_REASON_INIT failed with %d\n", lResult ) );
  272. DestroyUIUserData( &(UIUserData *)(pCPSUIInfo->UserData) );
  273. }
  274. break;
  275. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  276. DBGMSG( DBG_TRACE, ( "DrvDevicePropertySheets PROPSHEETUI_REASON_GET_INFO_HEADER\n") );
  277. pCPSUIInfoHdr = (PPROPSHEETUI_INFO_HEADER)lParam;
  278. CreatePrinterFriendlyName( (UIUserData *)(pCPSUIInfo->UserData), pDevPropHdr->pszPrinterName );
  279. pCPSUIInfoHdr->pTitle = ((UIUserData *)(pCPSUIInfo->UserData))->pszTitle;
  280. pCPSUIInfoHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW;
  281. pCPSUIInfoHdr->hInst = hInst;
  282. pCPSUIInfoHdr->IconID = IDI_CPSUI_PRINTER;
  283. lResult = TRUE;
  284. break;
  285. case PROPSHEETUI_REASON_SET_RESULT:
  286. DBGMSG( DBG_TRACE, ( "DrvDevicePropertySheets PROPSHEETUI_REASON_SET_RESULT\n") );
  287. pSetResultInfo = (PSETRESULT_INFO)lParam;
  288. pCPSUIInfo->Result = pSetResultInfo->Result;
  289. lResult = TRUE;
  290. break;
  291. case PROPSHEETUI_REASON_DESTROY:
  292. DBGMSG( DBG_TRACE, ( "DrvDevicePropertySheets PROPSHEETUI_REASON_DESTROY\n") );
  293. DestroyUIUserData( &(UIUserData *)(pCPSUIInfo->UserData) );
  294. lResult = TRUE;
  295. break;
  296. }
  297. }
  298. return lResult;
  299. }
  300. LONG_PTR
  301. DocumentPropertySheets(
  302. PPROPSHEETUI_INFO pCPSUIInfo,
  303. LPARAM lParam
  304. )
  305. /*++
  306. Routine Description:
  307. Adds the document property pages. This replaces DocumentProperties
  308. and Advanced DocumentProperties.
  309. Arguments:
  310. pCPSUIInfo - pointer to common ui info header.
  311. lParam - user defined lparam, see compstui for details.
  312. \nt\public\oak\inc\compstui.h
  313. Return Value:
  314. Returns > 0 if success
  315. Returns <= 0 if failure
  316. --*/
  317. {
  318. PDOCUMENTPROPERTYHEADER pDocPropHdr = NULL;
  319. PPROPSHEETUI_INFO_HEADER pCPSUIInfoHdr = NULL;
  320. PSETRESULT_INFO pSetResultInfo = NULL;
  321. LONG_PTR lResult = FALSE;
  322. HANDLE hModule = NULL;
  323. INT_FARPROC pfn = NULL;
  324. extern HANDLE hInst;
  325. DBGMSG( DBG_TRACE, ("DrvDocumentPropertySheets\n") );
  326. //
  327. // Ony compstui requests, are acknowledged.
  328. //
  329. if (pCPSUIInfo) {
  330. if ((!(pDocPropHdr = (PDOCUMENTPROPERTYHEADER)pCPSUIInfo->lParamInit)) ||
  331. (pDocPropHdr->cbSize < sizeof(PDOCUMENTPROPERTYHEADER))) {
  332. SetLastError(ERROR_INVALID_PARAMETER);
  333. return 0;
  334. }
  335. switch (pCPSUIInfo->Reason) {
  336. case PROPSHEETUI_REASON_INIT:
  337. DBGMSG( DBG_TRACE, ( "DrvDocumentPropertySheets PROPSHEETUI_REASON_INIT\n") );
  338. if (!(pDocPropHdr->fMode & DM_PROMPT)) {
  339. SetLastError(ERROR_INVALID_PARAMETER);
  340. return 0;
  341. }
  342. //
  343. // Create the UI User data.
  344. //
  345. if( CreateUIUserData( &(UIUserData *)(pCPSUIInfo->UserData), pDocPropHdr->hPrinter ) ){
  346. if( ((UIUserData *)(pCPSUIInfo->UserData))->hModule ){
  347. if (pfn = (INT_FARPROC)GetProcAddress( ((UIUserData *)(pCPSUIInfo->UserData))->hModule, szDrvDocPropSheets)) {
  348. //
  349. // Before calling into the driver to add pages make sure the proper
  350. // fusion activation context is set.
  351. //
  352. lResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  353. CPSFUNC_SET_FUSION_CONTEXT,
  354. (LPARAM)ACTCTX_EMPTY,
  355. (LPARAM)0);
  356. //
  357. // Common ui will call the driver to add it's sheets.
  358. //
  359. lResult = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
  360. CPSFUNC_ADD_PFNPROPSHEETUI,
  361. (LPARAM)pfn,
  362. pCPSUIInfo->lParamInit );
  363. }
  364. }
  365. }
  366. //
  367. // If something failed ensure we free the library
  368. // if it was loaded.
  369. //
  370. if( lResult <= 0 ){
  371. DBGMSG( DBG_TRACE, ( "DrvDocumentPropertySheets PROPSHEETUI_REASON_INIT failed with %d\n", lResult ) );
  372. DestroyUIUserData( &(UIUserData *)(pCPSUIInfo->UserData) );
  373. }
  374. break;
  375. case PROPSHEETUI_REASON_GET_INFO_HEADER:
  376. DBGMSG( DBG_TRACE, ( "DrvDocumentPropertySheets PROPSHEETUI_REASON_GET_INFO_HEADER\n") );
  377. pCPSUIInfoHdr = (PPROPSHEETUI_INFO_HEADER)lParam;
  378. CreatePrinterFriendlyName( (UIUserData *)(pCPSUIInfo->UserData), pDocPropHdr->pszPrinterName );
  379. pCPSUIInfoHdr->pTitle = ((UIUserData *)(pCPSUIInfo->UserData))->pszTitle;
  380. pCPSUIInfoHdr->Flags = PSUIHDRF_PROPTITLE | PSUIHDRF_NOAPPLYNOW;
  381. pCPSUIInfoHdr->hInst = hInst;
  382. pCPSUIInfoHdr->IconID = IDI_CPSUI_PRINTER;
  383. lResult = TRUE;
  384. break;
  385. case PROPSHEETUI_REASON_SET_RESULT:
  386. DBGMSG( DBG_TRACE, ( "DrvDocumentPropertySheets PROPSHEETUI_REASON_SET_RESULT\n") );
  387. pSetResultInfo = (PSETRESULT_INFO)lParam;
  388. if ((pCPSUIInfo->Result = pSetResultInfo->Result) > 0) {
  389. FixUpDEVMODEName(pDocPropHdr);
  390. }
  391. lResult = TRUE;
  392. break;
  393. case PROPSHEETUI_REASON_DESTROY:
  394. DBGMSG( DBG_TRACE, ( "DrvDocumentPropertySheets PROPSHEETUI_REASON_DESTROY\n") );
  395. DestroyUIUserData( &(UIUserData*)(pCPSUIInfo->UserData) );
  396. lResult = TRUE;
  397. break;
  398. }
  399. //
  400. // If a null pointer to common ui info header then
  401. // call the driver directly.
  402. //
  403. } else {
  404. lResult = -1;
  405. if ((!(pDocPropHdr = (PDOCUMENTPROPERTYHEADER)lParam)) ||
  406. (pDocPropHdr->cbSize < sizeof(PDOCUMENTPROPERTYHEADER))) {
  407. SetLastError(ERROR_INVALID_PARAMETER);
  408. return lResult;
  409. }
  410. if (pDocPropHdr->fMode & DM_PROMPT) {
  411. SetLastError(ERROR_INVALID_PARAMETER);
  412. } else if ((hModule = LoadPrinterDriver(pDocPropHdr->hPrinter)) &&
  413. (pfn = (INT_FARPROC)GetProcAddress(hModule, szDrvDocPropSheets))) {
  414. if ((lResult = (*pfn)(NULL, pDocPropHdr)) > 0) {
  415. FixUpDEVMODEName(pDocPropHdr);
  416. }
  417. } else {
  418. SetLastError(ERROR_INVALID_HANDLE);
  419. }
  420. if (hModule) {
  421. RefCntUnloadDriver(hModule, TRUE);
  422. }
  423. }
  424. return lResult;
  425. }