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.

612 lines
20 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. prtcovpg.c
  5. Abstract
  6. Three componants of the composite page description file:
  7. 1) A header describing the other two componants.
  8. 2) An embebbed meta file of the page description objects.
  9. 3) Text strings (or resource ID's of string data
  10. requiring substitution of user data passed in to the
  11. function).
  12. Routine parses componants of composite page description file as
  13. created by the Windows NT "FaxCover" application; renders the
  14. objects to the DC, if hdc is not NULL.
  15. Author:
  16. Julia J. Robinson
  17. Revision History:
  18. Julia J. Robinson 6-7-96
  19. Julia J. Robinson 9-20-96 Allow passing paper size and orientation.
  20. Environment:
  21. Windows NT
  22. --*/
  23. #include <windows.h>
  24. #include <commdlg.h>
  25. #include <winspool.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <tchar.h>
  29. #include "prtcovpg.h"
  30. #include "resource.h"
  31. #define INITIAL_SIZE_OF_STRING_BUFFER 64
  32. #define NOTE_INDEX 22 // Index of "{Note}" in the InsertionTitle array.
  33. BYTE UNICODE_Signature[20]= {0x46,0x41,0x58,0x43,0x4F,0x56,0x45,0x52,0x2D,0x56,0x45,0x52,0x30,0x30,0x35,0x77,0x87,0x00,0x00,0x00};
  34. //
  35. // Resource ID's corresponding to fields of USERDATA.
  36. //
  37. WORD InsertionTagResourceID[]=
  38. {
  39. IDS_PROP_RP_NAME, // "{Recipient Name}"
  40. IDS_PROP_RP_FXNO, // "{Recipient Fax Number}"
  41. IDS_PROP_RP_COMP, // "{Recipient's Company}"
  42. IDS_PROP_RP_ADDR, // "{Recipient's Street Address}"
  43. IDS_PROP_RP_CITY, // "{Recipient's City}"
  44. IDS_PROP_RP_STAT, // "{Recipient's State}"
  45. IDS_PROP_RP_ZIPC, // "{Recipient's Zip Code}"
  46. IDS_PROP_RP_CTRY, // "{Recipient's Country}"
  47. IDS_PROP_RP_TITL, // "{Recipient's Title}"
  48. IDS_PROP_RP_DEPT, // "{Recipient's Department}"
  49. IDS_PROP_RP_OFFI, // "{Recipient's Office Location}"
  50. IDS_PROP_RP_HTEL, // "{Recipient's Home Telephone #}"
  51. IDS_PROP_RP_OTEL, // "{Recipient's Office Telephone #}"
  52. IDS_PROP_SN_NAME, // "{Sender Name}"
  53. IDS_PROP_SN_FXNO, // "{Sender Fax #}"
  54. IDS_PROP_SN_COMP, // "{Sender's Company}"
  55. IDS_PROP_SN_ADDR, // "{Sender's Address}"
  56. IDS_PROP_SN_TITL, // "{Sender's Title}"
  57. IDS_PROP_SN_DEPT, // "{Sender's Department}"
  58. IDS_PROP_SN_OFFI, // "{Sender's Office Location}"
  59. IDS_PROP_SN_HTEL, // "{Sender's Home Telephone #}"
  60. IDS_PROP_SN_OTEL, // "{Sender's Office Telephone #}"
  61. IDS_PROP_MS_NOTE, // "{Note}"
  62. IDS_PROP_MS_SUBJ, // "{Subject}"
  63. IDS_PROP_MS_TSNT, // "{Time Sent}"
  64. IDS_PROP_MS_NOPG, // "{# of Pages}"
  65. IDS_PROP_RP_TOLS, // "{To: List}"
  66. IDS_PROP_RP_CCLS // "{Cc: List}"
  67. };
  68. DWORD WINAPI
  69. PrintCoverPage(
  70. HDC hDC,
  71. PCOVERPAGEFIELDS UserData,
  72. LPTSTR CompositeFileName,
  73. PCOVDOCINFO pCovDocInfo
  74. )
  75. /*++
  76. Arguments:
  77. hDC - Device context. If NULL, we just read the file and set *pFlags
  78. UserData - pointer to a structure containing user data
  79. for text insertions. May be NULL.
  80. CompositeFileName - Name of the file created by the page editor,
  81. containing the META file.
  82. pCovDocInfo - pointer to structure contining information about the cover page file.
  83. This includes
  84. pCovDocInfo->NoteRect
  85. - Coordinates of the "Note" insertion rectangle, returned
  86. in device coordinates. This will be all 0 if hDC is NULL
  87. pCovDocInfo->Flags
  88. - Returns bitwise OR of the following (or more):
  89. COVFP_NOTE if .cov file contains a Note field.
  90. COVFP_SUBJECT if .cov file contains a Subject field.
  91. COVFP_NUMPAGES if .cov file contains Num Pages field.
  92. pCovDocInfo->PaperSize
  93. - may use in DEVMODE as dmPaperSize
  94. pCovDocInfo->Orientation
  95. - may use in DEVMODE as dmOrientation
  96. pCovDocInfo->NoteFont
  97. - Logfont structure to be used in rendering the NOTE.
  98. This will be meaningless if hDC is NULL.
  99. --*/
  100. {
  101. ENHMETAHEADER MetaFileHeader;
  102. UINT HeaderSize;
  103. LPBYTE pMetaFileBuffer = NULL;
  104. const BYTE *pConstMetaFileBuffer;
  105. DWORD rVal = ERROR_SUCCESS;
  106. INT TextBoxNbr;
  107. COLORREF PreviousColor;
  108. INT PreviousMapMode;
  109. HFONT hThisFont = NULL;
  110. HGDIOBJ hPreviousFont;
  111. DWORD NbrBytesRead;
  112. RECT ClientRect;
  113. RECT ClipRect;
  114. RECT TextRect;
  115. RECT NoteRect;
  116. CONST RECT *pClipRect;
  117. HRGN ClipRegion = NULL;
  118. int CRComplexity; // return value of SelectClipRegion
  119. POINT OldWindowOrg; // return value of SetWindowOrg()
  120. POINT OldViewPortOrg; // return value of SetViewPortOrg()
  121. TEXTBOX TextBox; // buffer for reading in a TEXTBOX
  122. HENHMETAFILE MetaFileHandle;
  123. HANDLE CompositeFileHandle = INVALID_HANDLE_VALUE;
  124. COMPOSITEFILEHEADER CompositeFileHeader;
  125. DWORD FullPrinterWidth; // PHYSICALWIDTH
  126. DWORD FullPrinterHeight; // PHYSICALHEIGHT
  127. DWORD PrinterUnitsX; // PHYSICALWIDTH - (width of margins)
  128. DWORD PrinterUnitsY; // PHYSICALHEIGHT - (height of margins)
  129. INT HeightDrawn; // return value of DrawText()
  130. INT ReadBufferSize; // size of buffer for reading in strings.
  131. INT ThisBufSize; // size buffer needed for current text string.
  132. LPTSTR pStringReadIn = NULL; // buffer for reading in strings.
  133. LPTSTR pWhichTextToRender; // pStringReadIn v. ArrayOfData[i]
  134. INT i; // loop index
  135. LPTSTR * ArrayOfData; // uses pointers in UserData as ragged array.
  136. int CallersDCState = 0; // returned by SaveDC
  137. int MyDCState = 0; // returned by SaveDC
  138. DWORD ThisBit; // Flag field for current index.
  139. DWORD Flags; // Return these if pFlags != NULL.
  140. WORD MoreWords[3]; // Scale, PaperSize, and Orientation
  141. LOGFONT NoteFont; // Logfont structure found in the NOTE box
  142. __try {
  143. //
  144. // Initialize return values, handles, and pointers.
  145. //
  146. NoteRect.left = 0;
  147. NoteRect.right = 0;
  148. NoteRect.top = 0;
  149. NoteRect.bottom = 0;
  150. Flags = 0;
  151. hThisFont = NULL;
  152. CompositeFileHandle = INVALID_HANDLE_VALUE;
  153. MyDCState = 0;
  154. CallersDCState = 0;
  155. //
  156. // Initialize a Pointer so that
  157. //
  158. // ArrayOfData[0] ===== pUserData->RecName ,
  159. // ArrayOfData[1] ===== pUserData->RecFaxNumber ,
  160. // ... etc. ...
  161. if (UserData){
  162. ArrayOfData = &UserData->RecName;
  163. }
  164. ZeroMemory( &CompositeFileHeader, sizeof(CompositeFileHeader) );
  165. ZeroMemory( &TextBox, sizeof(TextBox) );
  166. //
  167. // Open the composite data file.
  168. //
  169. CompositeFileHandle = CreateFile(
  170. CompositeFileName,
  171. GENERIC_READ,
  172. FILE_SHARE_READ,
  173. NULL,
  174. OPEN_EXISTING,
  175. FILE_ATTRIBUTE_NORMAL,
  176. NULL
  177. );
  178. if (CompositeFileHandle == INVALID_HANDLE_VALUE) {
  179. rVal = GetLastError();
  180. goto exit;
  181. }
  182. if ((!ReadFile( CompositeFileHandle, &CompositeFileHeader, sizeof(CompositeFileHeader), &NbrBytesRead, NULL )) ||
  183. sizeof(CompositeFileHeader) != NbrBytesRead)
  184. {
  185. rVal = GetLastError();
  186. goto exit;
  187. }
  188. //
  189. // Check the 20-byte signature in the header to see if the file
  190. // contains ANSI or UNICODE strings.
  191. //
  192. if (memcmp( UNICODE_Signature, CompositeFileHeader.Signature, 20 )){
  193. rVal = ERROR_BAD_FORMAT;
  194. goto exit;
  195. }
  196. //
  197. // Extract the embedded META file from the composite file and move
  198. // into meta file buffer
  199. //
  200. pMetaFileBuffer = (LPBYTE) malloc( CompositeFileHeader.EmfSize );
  201. if (!pMetaFileBuffer){
  202. rVal = ERROR_NOT_ENOUGH_MEMORY;
  203. goto exit;
  204. }
  205. if ((!ReadFile( CompositeFileHandle, pMetaFileBuffer, CompositeFileHeader.EmfSize, &NbrBytesRead, NULL ) ||
  206. CompositeFileHeader.EmfSize != NbrBytesRead))
  207. {
  208. rVal = GetLastError();
  209. goto exit;
  210. }
  211. if (hDC) { // Rendering
  212. //
  213. // Save Device Context state
  214. //
  215. CallersDCState = SaveDC( hDC );
  216. if (CallersDCState == 0) {
  217. rVal = GetLastError();
  218. goto exit;
  219. }
  220. //
  221. // Set the client rectangle dimensions for display of the meta file
  222. //
  223. FullPrinterWidth = GetDeviceCaps( hDC, PHYSICALWIDTH );
  224. PrinterUnitsX = FullPrinterWidth - 2 * GetDeviceCaps( hDC, PHYSICALOFFSETX );
  225. FullPrinterHeight = GetDeviceCaps( hDC, PHYSICALHEIGHT );
  226. PrinterUnitsY = FullPrinterHeight - 2 * GetDeviceCaps( hDC, PHYSICALOFFSETY );
  227. ClientRect.top = CompositeFileHeader.CoverPageSize.cy / 2 ;
  228. ClientRect.left = -CompositeFileHeader.CoverPageSize.cx / 2;
  229. ClientRect.right = CompositeFileHeader.CoverPageSize.cx / 2;
  230. ClientRect.bottom = -CompositeFileHeader.CoverPageSize.cy / 2;
  231. //
  232. // Set device context appropriately for rendering both text and metafile.
  233. //
  234. PreviousMapMode = SetMapMode( hDC, MM_LOENGLISH );
  235. if (PreviousMapMode == 0) {
  236. rVal = GetLastError();
  237. goto exit;
  238. }
  239. if (!SetWindowOrgEx( hDC, 0, 0, &OldWindowOrg )) {
  240. rVal = GetLastError();
  241. goto exit;
  242. }
  243. if (!SetViewportOrgEx( hDC, PrinterUnitsX/2, PrinterUnitsY/2, &OldViewPortOrg )) {
  244. rVal = GetLastError();
  245. goto exit;
  246. }
  247. ClipRect = ClientRect;
  248. pClipRect = &ClipRect;
  249. LPtoDP( hDC, (POINT*)&ClipRect, 2 );
  250. ClipRegion = CreateRectRgnIndirect( pClipRect );
  251. CRComplexity = SelectClipRgn( hDC, ClipRegion );
  252. MyDCState = SaveDC( hDC );
  253. if (!CompositeFileHeader.EmfSize){
  254. //
  255. // No objects to render.
  256. //
  257. rVal = ERROR_NO_MORE_FILES;
  258. goto exit;
  259. }
  260. pConstMetaFileBuffer = pMetaFileBuffer;
  261. //
  262. // Create an enhanced metafile, in memory, from the data in the buffer.
  263. //
  264. MetaFileHandle = SetEnhMetaFileBits(
  265. CompositeFileHeader.EmfSize,
  266. pConstMetaFileBuffer
  267. );
  268. if (!MetaFileHandle) {
  269. rVal = GetLastError();
  270. goto exit;
  271. }
  272. //
  273. // verify the metafile header.
  274. //
  275. HeaderSize = GetEnhMetaFileHeader(
  276. MetaFileHandle,
  277. sizeof(ENHMETAHEADER),
  278. &MetaFileHeader
  279. );
  280. //
  281. // Check header size is at least 0x64 -> NT4 or greater version of ENHMETAHEADER
  282. //
  283. if (HeaderSize < 0x64){
  284. rVal = ERROR_INVALID_DATA;
  285. DeleteEnhMetaFile( MetaFileHandle );
  286. goto exit;
  287. }
  288. //
  289. // Render the MetaFile
  290. //
  291. if (!PlayEnhMetaFile( hDC, MetaFileHandle, &ClientRect )) {
  292. rVal = GetLastError();
  293. }
  294. //
  295. // Release the metafile handle and free the buffer.
  296. //
  297. DeleteEnhMetaFile( MetaFileHandle );
  298. if (rVal != ERROR_SUCCESS) {
  299. //
  300. // PlayEnhMetaFile failed.
  301. //
  302. goto exit;
  303. }
  304. //
  305. // Set Device Context for rendering text.
  306. // Undo any changes that occurred when rendering the metafile.
  307. //
  308. RestoreDC( hDC, MyDCState );
  309. MyDCState = 0;
  310. if (CLR_INVALID == SetBkMode( hDC, TRANSPARENT)){
  311. rVal = GetLastError();
  312. goto exit;
  313. }
  314. }
  315. //
  316. // Initialize buffer for reading in strings.
  317. //
  318. ReadBufferSize = INITIAL_SIZE_OF_STRING_BUFFER;
  319. pStringReadIn = (LPTSTR) malloc( ReadBufferSize );
  320. if (!pStringReadIn) {
  321. rVal = GetLastError();
  322. goto exit;
  323. }
  324. //
  325. // Read in Text Box objects from the composite file and print out the text.
  326. //
  327. pWhichTextToRender = NULL;
  328. for (TextBoxNbr=0; TextBoxNbr < (INT) CompositeFileHeader.NbrOfTextRecords; ++TextBoxNbr){
  329. if ((!ReadFile( CompositeFileHandle, &TextBox, sizeof(TEXTBOX), &NbrBytesRead, NULL)) ||
  330. NbrBytesRead != sizeof(TEXTBOX))
  331. {
  332. rVal = GetLastError();
  333. goto exit;
  334. }
  335. //
  336. // Check buffer size, lock buffer, and
  337. // read in variable length string of text.
  338. //
  339. ThisBufSize = sizeof(TCHAR) * (TextBox.NumStringBytes + sizeof(TCHAR));
  340. if (ReadBufferSize < ThisBufSize) {
  341. pStringReadIn = realloc( pStringReadIn, ThisBufSize );
  342. if (!pStringReadIn) {
  343. rVal = GetLastError();
  344. goto exit;
  345. }
  346. }
  347. if ((!ReadFile( CompositeFileHandle, (void*)pStringReadIn, TextBox.NumStringBytes, &NbrBytesRead, NULL)) ||
  348. NbrBytesRead != TextBox.NumStringBytes)
  349. {
  350. rVal = GetLastError();
  351. goto exit;
  352. }
  353. pStringReadIn[TextBox.NumStringBytes / sizeof(TCHAR)] = 0;
  354. if (hDC) {
  355. //
  356. // Correct position of text box.
  357. //
  358. TextRect.top = max( TextBox.PositionOfTextBox.top, TextBox.PositionOfTextBox.bottom );
  359. TextRect.left = min( TextBox.PositionOfTextBox.left, TextBox.PositionOfTextBox.right );
  360. TextRect.bottom = min( TextBox.PositionOfTextBox.top, TextBox.PositionOfTextBox.bottom );
  361. TextRect.right = max( TextBox.PositionOfTextBox.left, TextBox.PositionOfTextBox.right );
  362. pWhichTextToRender = pStringReadIn;
  363. }
  364. if (TextBox.ResourceID) {
  365. //
  366. // Text box contains a FAX PROPERTY field.
  367. // Find appropriate field of USERDATA for this resource ID.
  368. //
  369. for (i=0,ThisBit=1; i<NUM_INSERTION_TAGS; ++i,ThisBit<<=1) {
  370. if (TextBox.ResourceID == InsertionTagResourceID[i]){
  371. pWhichTextToRender = UserData ? ArrayOfData[i] : NULL;
  372. //
  373. // Set Flags bit to indicate this FAX PROPERTY field is present.
  374. //
  375. Flags |= ThisBit;
  376. break;
  377. }
  378. }
  379. if (TextBox.ResourceID == IDS_PROP_MS_NOTE && hDC) {
  380. //
  381. // NOTE field found. Return its rectangle in device coordinates.
  382. // Return its LOGFONT with height adjusted for device coordinates.
  383. //
  384. NoteRect = TextRect;
  385. LPtoDP( hDC, (POINT*)&NoteRect, 2 );
  386. NoteFont = TextBox.FontDefinition;
  387. NoteFont.lfHeight = (LONG)MulDiv(
  388. (int)NoteFont.lfHeight,
  389. GetDeviceCaps( hDC, LOGPIXELSY ),
  390. 100
  391. );
  392. }
  393. }
  394. if (hDC && pWhichTextToRender) {
  395. //
  396. // Set text color and font for rendering text.
  397. //
  398. PreviousColor = SetTextColor( hDC, TextBox.TextColor );
  399. if (PreviousColor == CLR_INVALID){
  400. rVal = GetLastError();
  401. goto exit;
  402. }
  403. hThisFont = CreateFontIndirect( &(TextBox.FontDefinition) );
  404. if (!hThisFont) {
  405. rVal = GetLastError();
  406. goto exit;
  407. }
  408. hPreviousFont = SelectObject( hDC, hThisFont );
  409. if (!hPreviousFont) {
  410. rVal = GetLastError();
  411. goto exit;
  412. }
  413. //
  414. // Render the text.
  415. //
  416. HeightDrawn = DrawText(
  417. hDC,
  418. pWhichTextToRender,
  419. -1,
  420. &TextRect,
  421. DT_NOPREFIX | DT_WORDBREAK | (UINT)TextBox.TextAlignment
  422. );
  423. if (!HeightDrawn) {
  424. rVal = GetLastError();
  425. goto exit;
  426. }
  427. //
  428. // Restore previous font and release the handle to the selected font
  429. //
  430. SelectObject( hDC, (HFONT)hPreviousFont );
  431. SetTextColor( hDC, PreviousColor );
  432. DeleteObject( hThisFont );
  433. }
  434. } // Ends loop over all textboxes.
  435. //
  436. // Read on to get Orientation and PaperSize
  437. //
  438. if ((!ReadFile( CompositeFileHandle, MoreWords, 3*sizeof(WORD), &NbrBytesRead, NULL )) ||
  439. NbrBytesRead != 3 * sizeof(WORD))
  440. {
  441. rVal = GetLastError();
  442. goto exit;
  443. }
  444. } __except(EXCEPTION_EXECUTE_HANDLER) {
  445. rVal = GetExceptionCode();
  446. }
  447. exit:
  448. if (hThisFont) {
  449. DeleteObject( hThisFont );
  450. }
  451. if (pStringReadIn) {
  452. free( pStringReadIn );
  453. }
  454. if (pMetaFileBuffer) {
  455. free( pMetaFileBuffer );
  456. }
  457. if (CompositeFileHandle != INVALID_HANDLE_VALUE){
  458. CloseHandle( CompositeFileHandle );
  459. }
  460. if( MyDCState ){
  461. RestoreDC( hDC, MyDCState );
  462. }
  463. if( CallersDCState ){
  464. RestoreDC( hDC, CallersDCState );
  465. }
  466. if (rVal == 0 && pCovDocInfo != NULL) {
  467. pCovDocInfo->Flags = Flags;
  468. pCovDocInfo->NoteRect = NoteRect;
  469. pCovDocInfo->PaperSize = (short) MoreWords[1];
  470. pCovDocInfo->Orientation = (short) MoreWords[2];
  471. pCovDocInfo->NoteFont = NoteFont;
  472. }
  473. if (ClipRegion) {
  474. DeleteObject( ClipRegion );
  475. }
  476. return rVal;
  477. }