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.

1171 lines
33 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. forms.c
  5. Abstract:
  6. This module provides all the public exported APIs relating to the
  7. Driver-based Spooler Apis for the Local Print Providor
  8. SplAddForm
  9. SplDeleteForm
  10. SplSetForm
  11. SplGetForm
  12. SplEnumForms
  13. Support Functions in forms.c - (Warning! Do Not Add to this list!!)
  14. Author:
  15. Dave Snipp (DaveSn) 15-Mar-1991
  16. Revision History:
  17. --*/
  18. #include <precomp.h>
  19. #include <offsets.h>
  20. VOID
  21. BroadcastChangeForms(
  22. PINISPOOLER pIniSpooler);
  23. DWORD
  24. BroadcastChangeFormsThread(
  25. PINISPOOLER pIniSpooler);
  26. typedef struct _REG_FORM_INFO {
  27. SIZEL Size;
  28. RECTL ImageableArea;
  29. DWORD cFormOrder;
  30. DWORD Flags;
  31. } REG_FORM_INFO, *PREG_FORM_INFO;
  32. // These figures are accurate to .001 mm
  33. // There are 25.4 mm per inch
  34. BUILTIN_FORM BuiltInForms[] = {
  35. 0, IDS_FORM_LETTER, 215900, 279400, 0, 0, 215900, 279400,
  36. 0, IDS_FORM_LETTER_SMALL, 215900, 279400, 0, 0, 215900, 279400,
  37. 0, IDS_FORM_TABLOID, 279400, 431800, 0, 0, 279400, 431800,
  38. 0, IDS_FORM_LEDGER, 431800, 279400, 0, 0, 431800, 279400,
  39. 0, IDS_FORM_LEGAL, 215900, 355600, 0, 0, 215900, 355600,
  40. 0, IDS_FORM_STATEMENT, 139700, 215900, 0, 0, 139700, 215900,
  41. 0, IDS_FORM_EXECUTIVE, 184150, 266700, 0, 0, 184150, 266700,
  42. 0, IDS_FORM_A3, 297000, 420000, 0, 0, 297000, 420000,
  43. 0, IDS_FORM_A4, 210000, 297000, 0, 0, 210000, 297000,
  44. 0, IDS_FORM_A4_SMALL, 210000, 297000, 0, 0, 210000, 297000,
  45. 0, IDS_FORM_A5, 148000, 210000, 0, 0, 148000, 210000,
  46. 0, IDS_FORM_B4, 257000, 364000, 0, 0, 257000, 364000,
  47. 0, IDS_FORM_B5, 182000, 257000, 0, 0, 182000, 257000,
  48. 0, IDS_FORM_FOLIO, 215900, 330200, 0, 0, 215900, 330200,
  49. 0, IDS_FORM_QUARTO, 215000, 275000, 0, 0, 215000, 275000,
  50. 0, IDS_FORM_10X14, 254000, 355600, 0, 0, 254000, 355600,
  51. 0, IDS_FORM_11X17, 279400, 431800, 0, 0, 279400, 431800,
  52. 0, IDS_FORM_NOTE, 215900, 279400, 0, 0, 215900, 279400,
  53. 0, IDS_FORM_ENVELOPE9, 98425, 225425, 0, 0, 98425, 225425,
  54. 0, IDS_FORM_ENVELOPE10, 104775, 241300, 0, 0, 104775, 241300,
  55. 0, IDS_FORM_ENVELOPE11, 114300, 263525, 0, 0, 114300, 263525,
  56. 0, IDS_FORM_ENVELOPE12, 120650, 279400, 0, 0, 120650, 279400,
  57. 0, IDS_FORM_ENVELOPE14, 127000, 292100, 0, 0, 127000, 292100,
  58. 0, IDS_FORM_ENVELOPE_CSIZE_SHEET, 431800, 558800, 0, 0, 431800, 558800,
  59. 0, IDS_FORM_ENVELOPE_DSIZE_SHEET, 558800, 863600, 0, 0, 558800, 863600,
  60. 0, IDS_FORM_ENVELOPE_ESIZE_SHEET, 863600,1117600, 0, 0, 863600,1117600,
  61. 0, IDS_FORM_ENVELOPE_DL, 110000, 220000, 0, 0, 110000, 220000,
  62. 0, IDS_FORM_ENVELOPE_C5, 162000, 229000, 0, 0, 162000, 229000,
  63. 0, IDS_FORM_ENVELOPE_C3, 324000, 458000, 0, 0, 324000, 458000,
  64. 0, IDS_FORM_ENVELOPE_C4, 229000, 324000, 0, 0, 229000, 324000,
  65. 0, IDS_FORM_ENVELOPE_C6, 114000, 162000, 0, 0, 114000, 162000,
  66. 0, IDS_FORM_ENVELOPE_C65, 114000, 229000, 0, 0, 114000, 229000,
  67. 0, IDS_FORM_ENVELOPE_B4, 250000, 353000, 0, 0, 250000, 353000,
  68. 0, IDS_FORM_ENVELOPE_B5, 176000, 250000, 0, 0, 176000, 250000,
  69. 0, IDS_FORM_ENVELOPE_B6, 176000, 125000, 0, 0, 176000, 125000,
  70. 0, IDS_FORM_ENVELOPE, 110000, 230000, 0, 0, 110000, 230000,
  71. 0, IDS_FORM_ENVELOPE_MONARCH, 98425, 190500, 0, 0, 98425, 190500,
  72. 0, IDS_FORM_SIX34_ENVELOPE, 92075, 165100, 0, 0, 92075, 165100,
  73. 0, IDS_FORM_US_STD_FANFOLD, 377825, 279400, 0, 0, 377825, 279400,
  74. 0, IDS_FORM_GMAN_STD_FANFOLD, 215900, 304800, 0, 0, 215900, 304800,
  75. 0, IDS_FORM_GMAN_LEGAL_FANFOLD, 215900, 330200, 0, 0, 215900, 330200,
  76. // Predefined forms currently availble only in Win95. Included here
  77. // for compatibility.
  78. 0, IDS_FORM_ISO_B4, 250000, 353000, 0, 0, 250000, 353000,
  79. 0, IDS_FORM_JAPANESE_POSTCARD, 100000, 148000, 0, 0, 100000, 148000,
  80. 0, IDS_FORM_9X11, 228600, 279400, 0, 0, 228600, 279400,
  81. 0, IDS_FORM_10X11, 254000, 279400, 0, 0, 254000, 279400,
  82. 0, IDS_FORM_15X11, 381000, 279400, 0, 0, 381000, 279400,
  83. 0, IDS_FORM_ENV_INVITE, 220000, 220000, 0, 0, 220000, 220000,
  84. 0, IDS_FORM_RESERVED_48, 1,1, 0, 0, 1, 1,
  85. 0, IDS_FORM_RESERVED_49, 1,1, 0, 0, 1, 1,
  86. 0, IDS_FORM_LETTER_EXTRA, 241300, 304800, 0, 0, 241300, 304800,
  87. 0, IDS_FORM_LEGAL_EXTRA, 241300, 381000, 0, 0, 241300, 381000,
  88. 0, IDS_FORM_TABLOID_EXTRA, 304800, 457200, 0, 0, 304800, 457200,
  89. 0, IDS_FORM_A4_EXTRA, 235458, 322326, 0, 0, 235458, 322326,
  90. 0, IDS_FORM_LETTER_TRANSVERSE, 215900, 279400, 0, 0, 215900, 279400,
  91. 0, IDS_FORM_A4_TRANSVERSE, 210000, 297000, 0, 0, 210000, 297000,
  92. 0, IDS_FORM_LETTER_EXTRA_TRANSVERSE, 241300, 304800, 0, 0, 241300, 304800,
  93. 0, IDS_FORM_A_PLUS, 227000, 356000, 0, 0, 227000, 356000,
  94. 0, IDS_FORM_B_PLUS, 305000, 487000, 0, 0, 305000, 487000,
  95. 0, IDS_FORM_LETTER_PLUS, 215900, 322326, 0, 0, 215900, 322326,
  96. 0, IDS_FORM_A4_PLUS, 210000, 330000, 0, 0, 210000, 330000,
  97. 0, IDS_FORM_A5_TRANSVERSE, 148000, 210000, 0, 0, 148000, 210000,
  98. 0, IDS_FORM_B5_TRANSVERSE, 182000, 257000, 0, 0, 182000, 257000,
  99. 0, IDS_FORM_A3_EXTRA, 322000, 445000, 0, 0, 322000, 445000,
  100. 0, IDS_FORM_A5_EXTRA, 174000, 235000, 0, 0, 174000, 235000,
  101. 0, IDS_FORM_B5_EXTRA, 201000, 276000, 0, 0, 201000, 276000,
  102. 0, IDS_FORM_A2, 420000, 594000, 0, 0, 420000, 594000,
  103. 0, IDS_FORM_A3_TRANSVERSE, 297000, 420000, 0, 0, 297000, 420000,
  104. 0, IDS_FORM_A3_EXTRA_TRANSVERSE, 322000, 445000, 0, 0, 322000, 445000,
  105. 0, IDS_FORM_DBL_JAPANESE_POSTCARD, 200000, 148000, 0, 0, 200000, 148000,
  106. 0, IDS_FORM_A6, 105000, 148000, 0, 0, 105000, 148000,
  107. 0, IDS_FORM_JENV_KAKU2, 240000, 332000, 0, 0, 240000, 332000,
  108. 0, IDS_FORM_JENV_KAKU3, 216000, 277000, 0, 0, 216000, 277000,
  109. 0, IDS_FORM_JENV_CHOU3, 120000, 235000, 0, 0, 120000, 235000,
  110. 0, IDS_FORM_JENV_CHOU4, 90000, 205000, 0, 0, 90000, 205000,
  111. 0, IDS_FORM_LETTER_ROTATED, 279400, 215900, 0, 0, 279400, 215900,
  112. 0, IDS_FORM_A3_ROTATED, 420000, 297000, 0, 0, 420000, 297000,
  113. 0, IDS_FORM_A4_ROTATED, 297000, 210000, 0, 0, 297000, 210000,
  114. 0, IDS_FORM_A5_ROTATED, 210000, 148000, 0, 0, 210000, 148000,
  115. 0, IDS_FORM_B4_JIS_ROTATED, 364000, 257000, 0, 0, 364000, 257000,
  116. 0, IDS_FORM_B5_JIS_ROTATED, 257000, 182000, 0, 0, 257000, 182000,
  117. 0, IDS_FORM_JAPANESE_POSTCARD_ROTATED, 148000, 100000, 0, 0, 148000, 100000,
  118. 0, IDS_FORM_DBL_JAPANESE_POSTCARD_ROTATED, 148000, 200000, 0, 0, 148000, 200000,
  119. 0, IDS_FORM_A6_ROTATED, 148000, 105000, 0, 0, 148000, 105000,
  120. 0, IDS_FORM_JENV_KAKU2_ROTATED, 332000, 240000, 0, 0, 332000, 240000,
  121. 0, IDS_FORM_JENV_KAKU3_ROTATED, 277000, 216000, 0, 0, 277000, 216000,
  122. 0, IDS_FORM_JENV_CHOU3_ROTATED, 235000, 120000, 0, 0, 235000, 120000,
  123. 0, IDS_FORM_JENV_CHOU4_ROTATED, 205000, 90000, 0, 0, 205000, 90000,
  124. 0, IDS_FORM_B6_JIS, 128000, 182000, 0, 0, 128000, 182000,
  125. 0, IDS_FORM_B6_JIS_ROTATED, 182000, 128000, 0, 0, 182000, 128000,
  126. 0, IDS_FORM_12X11, 304932, 279521, 0, 0, 304932, 279521,
  127. 0, IDS_FORM_JENV_YOU4, 105000, 235000, 0, 0, 105000, 235000,
  128. 0, IDS_FORM_JENV_YOU4_ROTATED, 235000, 105000, 0, 0, 235000, 105000,
  129. 0, IDS_FORM_P16K, 188000, 260000, 0, 0, 188000, 260000,
  130. 0, IDS_FORM_P32K, 130000, 184000, 0, 0, 130000, 184000,
  131. 0, IDS_FORM_P32KBIG, 140000, 203000, 0, 0, 140000, 203000,
  132. 0, IDS_FORM_PENV_1, 102000, 165000, 0, 0, 102000, 165000,
  133. 0, IDS_FORM_PENV_2, 102000, 176000, 0, 0, 102000, 176000,
  134. 0, IDS_FORM_PENV_3, 125000, 176000, 0, 0, 125000, 176000,
  135. 0, IDS_FORM_PENV_4, 110000, 208000, 0, 0, 110000, 208000,
  136. 0, IDS_FORM_PENV_5, 110000, 220000, 0, 0, 110000, 220000,
  137. 0, IDS_FORM_PENV_6, 120000, 230000, 0, 0, 120000, 230000,
  138. 0, IDS_FORM_PENV_7, 160000, 230000, 0, 0, 160000, 230000,
  139. 0, IDS_FORM_PENV_8, 120000, 309000, 0, 0, 120000, 309000,
  140. 0, IDS_FORM_PENV_9, 229000, 324000, 0, 0, 229000, 324000,
  141. 0, IDS_FORM_PENV_10, 324000, 458000, 0, 0, 324000, 458000,
  142. 0, IDS_FORM_P16K_ROTATED, 260000, 188000, 0, 0, 260000, 188000,
  143. 0, IDS_FORM_P32K_ROTATED, 184000, 130000, 0, 0, 184000, 130000,
  144. 0, IDS_FORM_P32KBIG_ROTATED, 203000, 140000, 0, 0, 203000, 140000,
  145. 0, IDS_FORM_PENV_1_ROTATED, 165000, 102000, 0, 0, 165000, 102000,
  146. 0, IDS_FORM_PENV_2_ROTATED, 176000, 102000, 0, 0, 176000, 102000,
  147. 0, IDS_FORM_PENV_3_ROTATED, 176000, 125000, 0, 0, 176000, 125000,
  148. 0, IDS_FORM_PENV_4_ROTATED, 208000, 110000, 0, 0, 208000, 110000,
  149. 0, IDS_FORM_PENV_5_ROTATED, 220000, 110000, 0, 0, 220000, 110000,
  150. 0, IDS_FORM_PENV_6_ROTATED, 230000, 120000, 0, 0, 230000, 120000,
  151. 0, IDS_FORM_PENV_7_ROTATED, 230000, 160000, 0, 0, 230000, 160000,
  152. 0, IDS_FORM_PENV_8_ROTATED, 309000, 120000, 0, 0, 309000, 120000,
  153. 0, IDS_FORM_PENV_9_ROTATED, 324000, 229000, 0, 0, 324000, 229000,
  154. 0, IDS_FORM_PENV_10_ROTATED, 458000, 324000, 0, 0, 458000, 324000,
  155. 0, 0, 0, 0, 0, 0, 0, 0
  156. };
  157. PINIFORM
  158. CreateFormEntry(
  159. LPWSTR pFormName,
  160. SIZEL Size,
  161. RECTL *pImageableArea,
  162. DWORD Type,
  163. DWORD cFormOrder,
  164. PINISPOOLER pIniSpooler
  165. )
  166. /*++
  167. Routine Description:
  168. Creates a Form entry, and insert it into the right place in
  169. pIniSpooler.
  170. Arguments:
  171. pFormName - Name of Form.
  172. Size - Size of form.
  173. pImageableArea - Area of form that the printer can print to.
  174. Type - Type of form (usually indicates if BUILTIN form).
  175. cFormOrder - Where the form should be inserted for user-defined forms,
  176. form order increases from beginning to end.
  177. If this value is -1, generate a new cFormOrder for this form.
  178. (Put it at the end.)
  179. Return Value:
  180. pIniForm - Created form, NULL = error.
  181. Notes:
  182. This routine ensures that forms are put in proper order so that
  183. EnumForms always returns them in the same order. We do this by
  184. scanning the list and inserting the new form such that all forms
  185. with cFormOrder =< the current on are to the left of it.
  186. This routine updates pIniSpooler->pIniForm (inserts or appends) and
  187. updates pIniSpooler->cFormOrderMax if necessary.
  188. i.e., 0 0 0 2 3 4 6
  189. ^
  190. New 0 inserted here.
  191. --*/
  192. {
  193. DWORD cb;
  194. PINIFORM pIniForm, pForm;
  195. cb = sizeof(INIFORM) + wcslen(pFormName)*sizeof(WCHAR) + sizeof(WCHAR);
  196. if ( pIniForm = AllocSplMem(cb) ) {
  197. pIniForm->pName = wcscpy((LPWSTR)(pIniForm+1), pFormName);
  198. pIniForm->pNext = NULL;
  199. pIniForm->signature = IFO_SIGNATURE;
  200. pIniForm->Size = Size;
  201. pIniForm->ImageableArea = *pImageableArea;
  202. pIniForm->Type = Type;
  203. pIniForm->cFormOrder = cFormOrder;
  204. //
  205. // This code will insert the item in order, but will always never
  206. // insert before the first item. The built-in forms are always
  207. // at the front so this is not an issue.
  208. //
  209. if ( pForm = pIniSpooler->pShared->pIniForm ) {
  210. for( ; pForm->pNext; pForm = pForm->pNext ){
  211. //
  212. // If the next form is greater than the one we want
  213. // to insert, then insert it right now.
  214. //
  215. if( pForm->pNext->cFormOrder > cFormOrder ){
  216. //
  217. // The current from should be inserted here.
  218. //
  219. break;
  220. }
  221. }
  222. //
  223. // Link it up.
  224. //
  225. pIniForm->pNext = pForm->pNext;
  226. pForm->pNext = pIniForm;
  227. } else {
  228. pIniSpooler->pShared->pIniForm = pIniForm;
  229. }
  230. //
  231. // If the added form has a higher count than the current global
  232. // count, update the global.
  233. //
  234. if( cFormOrder > pIniSpooler->cFormOrderMax ){
  235. pIniSpooler->cFormOrderMax = cFormOrder;
  236. }
  237. }
  238. return pIniForm;
  239. }
  240. BOOL
  241. InitializeForms(
  242. PINISPOOLER pIniSpooler
  243. )
  244. {
  245. PBUILTIN_FORM pBuiltInForm;
  246. HKEY hFormsKey;
  247. DWORD cUserDefinedForms;
  248. WCHAR FormName[MAX_PATH];
  249. WCHAR FormBuffer[FORM_NAME_LEN+1];
  250. DWORD cchFormName;
  251. REG_FORM_INFO RegFormInfo;
  252. DWORD cbRegFormInfo;
  253. DWORD dwError;
  254. BOOL bUpgradeTried = FALSE;
  255. BOOL bStatus = TRUE;
  256. WORD PrimaryLangId = PRIMARYLANGID( GetSystemDefaultLangID( ));
  257. if (pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL)
  258. {
  259. for( pBuiltInForm = BuiltInForms; pBuiltInForm->NameId; pBuiltInForm++ ) {
  260. FormBuffer[0] = 0;
  261. LoadString( hInst,
  262. pBuiltInForm->NameId,
  263. FormBuffer,
  264. FORM_NAME_LEN+1 );
  265. if ( CreateFormEntry( FormBuffer,
  266. pBuiltInForm->Size,
  267. &pBuiltInForm->ImageableArea,
  268. FORM_BUILTIN,
  269. 0,
  270. pIniSpooler ) == NULL)
  271. {
  272. bStatus = FALSE;
  273. break;
  274. }
  275. }
  276. }
  277. if ( bStatus )
  278. {
  279. //
  280. // Now see if there are any user-defined forms in the registry:
  281. //
  282. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  283. pIniSpooler->pszRegistryForms,
  284. 0,
  285. KEY_READ | KEY_WRITE,
  286. &hFormsKey) == NO_ERROR ) {
  287. for( cUserDefinedForms = 0; TRUE; ++cUserDefinedForms ){
  288. Retry:
  289. cchFormName = COUNTOF( FormName );
  290. cbRegFormInfo = sizeof( RegFormInfo );
  291. dwError = RegEnumValue( hFormsKey,
  292. cUserDefinedForms,
  293. (LPWSTR)FormName,
  294. &cchFormName,
  295. NULL,
  296. NULL,
  297. (LPBYTE)&RegFormInfo,
  298. &cbRegFormInfo );
  299. if( dwError ){
  300. break;
  301. }
  302. //
  303. // We will attempt the upgrade only if
  304. // we are on the first item,
  305. // the size is incorrect, and
  306. // we haven't tried upgrading once in the function before.
  307. //
  308. if( !cUserDefinedForms &&
  309. cbRegFormInfo != sizeof( RegFormInfo ) &&
  310. !bUpgradeTried ){
  311. Upgrade35Forms( hFormsKey, pIniSpooler );
  312. bUpgradeTried = TRUE;
  313. goto Retry;
  314. }
  315. if ( CreateFormEntry( FormName,
  316. RegFormInfo.Size,
  317. &RegFormInfo.ImageableArea,
  318. RegFormInfo.Flags,
  319. RegFormInfo.cFormOrder,
  320. pIniSpooler ) == NULL )
  321. {
  322. bStatus = FALSE;
  323. break;
  324. }
  325. }
  326. RegCloseKey( hFormsKey );
  327. hFormsKey = NULL;
  328. }
  329. }
  330. return bStatus;
  331. }
  332. DWORD
  333. GetFormSize(
  334. PINIFORM pIniForm,
  335. DWORD Level
  336. )
  337. {
  338. DWORD cb;
  339. switch (Level) {
  340. case 1:
  341. cb=sizeof(FORM_INFO_1) +
  342. wcslen(pIniForm->pName)*sizeof(WCHAR) + sizeof(WCHAR);
  343. break;
  344. default:
  345. cb = 0;
  346. break;
  347. }
  348. return cb;
  349. }
  350. // We are being a bit naughty here as we are not sure exactly how much
  351. // memory to allocate for the source strings. We will just assume that
  352. // FORM_INFO_1 is the biggest structure around for the moment.
  353. LPBYTE
  354. CopyIniFormToForm(
  355. PINIFORM pIniForm,
  356. DWORD Level,
  357. LPBYTE pFormInfo,
  358. LPBYTE pEnd
  359. )
  360. {
  361. LPWSTR SourceStrings[sizeof(FORM_INFO_1)/sizeof(LPWSTR)];
  362. LPWSTR *pSourceStrings=SourceStrings;
  363. LPFORM_INFO_1 pFormInfo1=(LPFORM_INFO_1)pFormInfo;
  364. DWORD *pOffsets;
  365. switch (Level) {
  366. case 1:
  367. pOffsets = FormInfo1Strings;
  368. break;
  369. default:
  370. return pEnd;
  371. }
  372. switch (Level) {
  373. case 1:
  374. *pSourceStrings++=pIniForm->pName;
  375. pEnd = PackStrings(SourceStrings, pFormInfo, pOffsets, pEnd);
  376. pFormInfo1->Flags |= pIniForm->Type;
  377. pFormInfo1->Size = pIniForm->Size;
  378. pFormInfo1->ImageableArea = pIniForm->ImageableArea;
  379. break;
  380. default:
  381. return pEnd;
  382. }
  383. return pEnd;
  384. }
  385. /* Checks for logically impossible sizes.
  386. */
  387. BOOL
  388. ValidateForm(
  389. LPBYTE pForm
  390. )
  391. {
  392. LPFORM_INFO_1 pFormInfo = (LPFORM_INFO_1)pForm;
  393. DWORD Error = NO_ERROR;
  394. if( !pForm ||
  395. (pFormInfo->Flags != FORM_USER &&
  396. pFormInfo->Flags != FORM_BUILTIN &&
  397. pFormInfo->Flags != FORM_PRINTER)) {
  398. Error = ERROR_INVALID_PARAMETER;
  399. } else
  400. /* Make sure name isn't longer than GDI DEVMODE specifies:
  401. */
  402. if( ( !pFormInfo->pName ) ||
  403. ( !pFormInfo->pName[0] ) ||
  404. ( wcslen( pFormInfo->pName ) > FORM_NAME_LEN )){
  405. Error = ERROR_INVALID_FORM_NAME;
  406. } else
  407. if( ( pFormInfo->Size.cx <= 0 ) /* Check for negative width */
  408. ||( pFormInfo->Size.cy <= 0 ) /* ... and height */
  409. /* Check for strange imageable area:
  410. */
  411. || (pFormInfo->ImageableArea.right < 0)
  412. || (pFormInfo->ImageableArea.left < 0)
  413. || (pFormInfo->ImageableArea.bottom < 0)
  414. || (pFormInfo->ImageableArea.top < 0)
  415. ||( pFormInfo->ImageableArea.right <= pFormInfo->ImageableArea.left )
  416. ||( pFormInfo->ImageableArea.bottom <= pFormInfo->ImageableArea.top ) ) {
  417. Error = ERROR_INVALID_FORM_SIZE;
  418. }
  419. if( Error != NO_ERROR ) {
  420. SetLastError(Error);
  421. return FALSE;
  422. }
  423. return TRUE;
  424. }
  425. BOOL
  426. SplAddForm(
  427. HANDLE hPrinter,
  428. DWORD Level,
  429. LPBYTE pForm
  430. )
  431. {
  432. LPFORM_INFO_1 pFormInfo;
  433. PINIFORM pIniForm;
  434. HKEY hFormsKey;
  435. REG_FORM_INFO RegFormInfo;
  436. DWORD Status;
  437. PSPOOL pSpool = (PSPOOL)hPrinter;
  438. PINISPOOLER pIniSpooler;
  439. HANDLE hToken = INVALID_HANDLE_VALUE;
  440. if (!ValidateSpoolHandle( pSpool, 0 )) {
  441. return(FALSE);
  442. }
  443. pIniSpooler = pSpool->pIniSpooler;
  444. if (Level != 1) {
  445. return FALSE;
  446. }
  447. if (!ValidateForm(pForm)) {
  448. /* ValidateForm sets the appropriate error code:
  449. */
  450. return FALSE;
  451. }
  452. if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
  453. SERVER_ACCESS_ADMINISTER,
  454. NULL, NULL, pIniSpooler )) {
  455. return FALSE;
  456. }
  457. EnterSplSem();
  458. pFormInfo = (LPFORM_INFO_1)pForm;
  459. pIniForm = FindForm(pFormInfo->pName, pIniSpooler);
  460. /* If there's already a form by this name, don't go on:
  461. */
  462. if (pIniForm) {
  463. /* Is there a better error code than this?? */
  464. SetLastError(ERROR_FILE_EXISTS);
  465. LeaveSplSem();
  466. return FALSE;
  467. }
  468. //
  469. // Revert to LocalSystem, since a regular user cannot do this CreateKey call.
  470. //
  471. hToken = RevertToPrinterSelf();
  472. Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pIniSpooler->pszRegistryForms, 0, NULL, 0,
  473. KEY_WRITE, NULL, &hFormsKey, NULL);
  474. if (Status == NO_ERROR) {
  475. RegFormInfo.Size = pFormInfo->Size;
  476. RegFormInfo.ImageableArea = pFormInfo->ImageableArea;
  477. RegFormInfo.cFormOrder = pIniSpooler->cFormOrderMax + 1;
  478. RegFormInfo.Flags = pFormInfo->Flags;
  479. Status = RegSetValueEx( hFormsKey, pFormInfo->pName, 0, REG_BINARY,
  480. (LPBYTE)&RegFormInfo, sizeof RegFormInfo );
  481. RegCloseKey( hFormsKey );
  482. if ( Status == NO_ERROR ) {
  483. CreateFormEntry( pFormInfo->pName,
  484. pFormInfo->Size,
  485. &pFormInfo->ImageableArea,
  486. RegFormInfo.Flags,
  487. RegFormInfo.cFormOrder,
  488. pIniSpooler );
  489. SetPrinterChange( NULL,
  490. NULL,
  491. NULL,
  492. PRINTER_CHANGE_ADD_FORM,
  493. pIniSpooler );
  494. BroadcastChangeForms( pIniSpooler );
  495. }
  496. }
  497. ImpersonatePrinterClient( hToken );
  498. RunForEachSpooler( NULL, DsUpdateAllDriverKeys);
  499. LeaveSplSem();
  500. if ( Status != NO_ERROR )
  501. SetLastError( Status );
  502. SplLogEvent( pIniSpooler,
  503. LOG_INFO,
  504. MSG_FORM_ADDED,
  505. FALSE,
  506. pFormInfo->pName,
  507. NULL );
  508. return ( Status == NO_ERROR );
  509. }
  510. BOOL
  511. DeleteFormEntry(
  512. PINIFORM pIniForm,
  513. PINISPOOLER pIniSpooler
  514. )
  515. {
  516. PINIFORM *ppCurForm;
  517. ppCurForm = &pIniSpooler->pShared->pIniForm;
  518. while (*ppCurForm != pIniForm)
  519. ppCurForm = &(*ppCurForm)->pNext;
  520. *ppCurForm = (*ppCurForm)->pNext;
  521. FreeSplMem(pIniForm);
  522. return TRUE;
  523. }
  524. BOOL
  525. SplDeleteForm(
  526. HANDLE hPrinter,
  527. LPWSTR pFormName
  528. )
  529. {
  530. HKEY hFormsKey;
  531. DWORD Status;
  532. PINIFORM pIniForm;
  533. PSPOOL pSpool = (PSPOOL) hPrinter;
  534. HANDLE hToken = INVALID_HANDLE_VALUE;
  535. PINISPOOLER pIniSpooler;
  536. if (!ValidateSpoolHandle( pSpool, 0 )) {
  537. return(FALSE);
  538. }
  539. pIniSpooler = pSpool->pIniSpooler;
  540. if (!pFormName) {
  541. SetLastError(ERROR_INVALID_PARAMETER);
  542. return FALSE;
  543. }
  544. if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
  545. SERVER_ACCESS_ADMINISTER,
  546. NULL, NULL, pIniSpooler )) {
  547. return FALSE;
  548. }
  549. EnterSplSem();
  550. pIniForm = FindForm(pFormName, pIniSpooler);
  551. if (!pIniForm || ((pIniForm->Type == FORM_BUILTIN) &&
  552. pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL)) {
  553. SetLastError( pIniForm ?
  554. ERROR_INVALID_PARAMETER :
  555. ERROR_INVALID_FORM_NAME );
  556. LeaveSplSem();
  557. return FALSE;
  558. }
  559. hToken = RevertToPrinterSelf();
  560. Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pIniSpooler->pszRegistryForms, 0,
  561. KEY_WRITE, &hFormsKey);
  562. if (Status == NO_ERROR) {
  563. Status = RegDeleteValue(hFormsKey, pFormName);
  564. RegCloseKey(hFormsKey);
  565. if (Status == NO_ERROR) {
  566. DeleteFormEntry(pIniForm , pIniSpooler );
  567. SetPrinterChange(NULL,
  568. NULL,
  569. NULL,
  570. PRINTER_CHANGE_DELETE_FORM,
  571. pIniSpooler);
  572. BroadcastChangeForms(pIniSpooler);
  573. RunForEachSpooler( NULL, DsUpdateAllDriverKeys);
  574. }
  575. }
  576. if(hToken != INVALID_HANDLE_VALUE)
  577. {
  578. ImpersonatePrinterClient( hToken );
  579. }
  580. LeaveSplSem();
  581. if (Status != NO_ERROR)
  582. SetLastError(Status);
  583. SplLogEvent( pIniSpooler,
  584. LOG_INFO,
  585. MSG_FORM_DELETED,
  586. FALSE,
  587. pFormName,
  588. NULL );
  589. return (Status == NO_ERROR);
  590. }
  591. BOOL
  592. SplGetForm(
  593. HANDLE hPrinter,
  594. LPWSTR pFormName,
  595. DWORD Level,
  596. LPBYTE pForm,
  597. DWORD cbBuf,
  598. LPDWORD pcbNeeded
  599. )
  600. {
  601. PINIFORM pIniForm;
  602. DWORD cb;
  603. LPBYTE pEnd;
  604. PSPOOL pSpool = (PSPOOL)hPrinter;
  605. PINISPOOLER pIniSpooler;
  606. if (!ValidateSpoolHandle(pSpool, 0 )) {
  607. return(FALSE);
  608. }
  609. if (!pSpool->pIniPrinter ||
  610. !pSpool->pIniSpooler ||
  611. (pSpool->pIniPrinter->signature != IP_SIGNATURE)) {
  612. SetLastError(ERROR_INVALID_HANDLE);
  613. return FALSE;
  614. }
  615. EnterSplSem();
  616. SPLASSERT(pSpool->pIniSpooler->signature == ISP_SIGNATURE);
  617. pIniSpooler = pSpool->pIniSpooler;
  618. cb=0;
  619. if (pIniForm=FindForm(pFormName, pIniSpooler)) {
  620. cb=GetFormSize(pIniForm, Level);
  621. *pcbNeeded=cb;
  622. if (cb > cbBuf) {
  623. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  624. LeaveSplSem();
  625. SplOutSem();
  626. return FALSE;
  627. }
  628. pEnd=pForm+cbBuf;
  629. CopyIniFormToForm(pIniForm, Level, pForm, pEnd);
  630. } else {
  631. SetLastError( ERROR_INVALID_FORM_NAME );
  632. }
  633. LeaveSplSem();
  634. SplOutSem();
  635. return !!pIniForm;
  636. }
  637. BOOL
  638. SplSetForm(
  639. HANDLE hPrinter,
  640. LPWSTR pFormName,
  641. DWORD Level,
  642. LPBYTE pForm
  643. )
  644. {
  645. HKEY hFormsKey;
  646. DWORD Status;
  647. PINIFORM pIniForm;
  648. LPFORM_INFO_1 pFormInfo;
  649. REG_FORM_INFO RegFormInfo;
  650. PINISPOOLER pIniSpooler;
  651. PSPOOL pSpool = (PSPOOL)hPrinter;
  652. //
  653. // Validate this Printer Handle
  654. // Disallow Mask: PRINTER_HANDLE_SERVER
  655. //
  656. if (!ValidateSpoolHandle( pSpool , 0 )) {
  657. return(FALSE);
  658. }
  659. pIniSpooler = pSpool->pIniSpooler;
  660. if (Level != 1) {
  661. SetLastError(ERROR_INVALID_LEVEL);
  662. return FALSE;
  663. }
  664. if (!ValidateForm(pForm)) {
  665. /* ValidateForm sets the appropriate error code:
  666. */
  667. return FALSE;
  668. }
  669. if ( !ValidateObjectAccess(SPOOLER_OBJECT_SERVER,
  670. SERVER_ACCESS_ADMINISTER,
  671. NULL, NULL, pIniSpooler )) {
  672. return FALSE;
  673. }
  674. EnterSplSem();
  675. SPLASSERT( pIniSpooler->signature == ISP_SIGNATURE );
  676. pFormInfo = (LPFORM_INFO_1)pForm;
  677. pIniForm = FindForm(pFormName, pIniSpooler);
  678. if (!pIniForm || (pIniForm->Type == FORM_BUILTIN) || (pFormInfo->Flags & FORM_BUILTIN)) {
  679. SetLastError( pIniForm ?
  680. ERROR_INVALID_PARAMETER :
  681. ERROR_INVALID_FORM_NAME );
  682. LeaveSplSem();
  683. return FALSE;
  684. }
  685. Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pIniSpooler->pszRegistryForms, 0,
  686. KEY_WRITE, &hFormsKey);
  687. if (Status == NO_ERROR) {
  688. RegFormInfo.Size = pFormInfo->Size;
  689. RegFormInfo.ImageableArea = pFormInfo->ImageableArea;
  690. RegFormInfo.Flags = pFormInfo->Flags;
  691. Status = RegSetValueEx(hFormsKey, pFormInfo->pName, 0, REG_BINARY,
  692. (LPBYTE)&RegFormInfo, sizeof RegFormInfo);
  693. RegCloseKey(hFormsKey);
  694. }
  695. if (Status == NO_ERROR) {
  696. pIniForm->Size = pFormInfo->Size;
  697. pIniForm->ImageableArea = pFormInfo->ImageableArea;
  698. pIniForm->Type = pFormInfo->Flags;
  699. SetPrinterChange(NULL,
  700. NULL,
  701. NULL,
  702. PRINTER_CHANGE_SET_FORM,
  703. pIniSpooler);
  704. BroadcastChangeForms(pIniSpooler);
  705. }
  706. LeaveSplSem();
  707. return (Status == NO_ERROR);
  708. }
  709. BOOL
  710. SplEnumForms(
  711. HANDLE hPrinter,
  712. DWORD Level,
  713. LPBYTE pForm,
  714. DWORD cbBuf,
  715. LPDWORD pcbNeeded,
  716. LPDWORD pcReturned
  717. )
  718. {
  719. PINIFORM pIniForm;
  720. DWORD cb;
  721. LPBYTE pEnd;
  722. PSPOOL pSpool = (PSPOOL)hPrinter;
  723. PINISPOOLER pIniSpooler;
  724. if (!ValidateSpoolHandle(pSpool, 0 )) {
  725. return FALSE;
  726. }
  727. *pcReturned=0;
  728. EnterSplSem();
  729. pIniSpooler = pSpool->pIniSpooler;
  730. SPLASSERT( ( pIniSpooler != NULL ) &&
  731. ( pIniSpooler->signature == ISP_SIGNATURE ));
  732. cb=0;
  733. pIniForm=pIniSpooler->pShared->pIniForm;
  734. while (pIniForm) {
  735. cb+=GetFormSize(pIniForm, Level);
  736. pIniForm=pIniForm->pNext;
  737. }
  738. *pcbNeeded=cb;
  739. if (cb > cbBuf) {
  740. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  741. LeaveSplSem();
  742. SplOutSem();
  743. return FALSE;
  744. }
  745. pIniForm=pIniSpooler->pShared->pIniForm;
  746. pEnd=pForm+cbBuf;
  747. while (pIniForm) {
  748. pEnd = CopyIniFormToForm(pIniForm, Level, pForm, pEnd);
  749. switch (Level) {
  750. case 1:
  751. pForm+=sizeof(FORM_INFO_1);
  752. break;
  753. }
  754. pIniForm=pIniForm->pNext;
  755. (*pcReturned)++;
  756. }
  757. LeaveSplSem();
  758. SplOutSem();
  759. return TRUE;
  760. }
  761. DWORD dwBroadcastChangeFormsThread = 0;
  762. VOID
  763. BroadcastChangeForms(
  764. PINISPOOLER pIniSpooler)
  765. /*++
  766. Routine Description:
  767. Notify all applications that their devmode may have changed (when
  768. a form is changed).
  769. Arguments:
  770. Return Value:
  771. --*/
  772. {
  773. PINIPRINTER pIniPrinter;
  774. WCHAR PrinterName[ MAX_UNC_PRINTER_NAME ];
  775. UINT MachineNameLen;
  776. SplInSem();
  777. if( !( pIniSpooler->SpoolerFlags & SPL_FORMS_CHANGE )) {
  778. return;
  779. }
  780. INCSPOOLERREF( pIniSpooler );
  781. ++dwBroadcastChangeFormsThread;
  782. if ( pIniSpooler != pLocalIniSpooler ) {
  783. //
  784. // For Non Local Printers prepend the Machine Name
  785. //
  786. wsprintf( PrinterName, L"%ws\\", pIniSpooler->pMachineName );
  787. } else {
  788. PrinterName[0] = L'\0';
  789. }
  790. MachineNameLen = wcslen( PrinterName ) ;
  791. for( pIniPrinter = pIniSpooler->pIniPrinter;
  792. pIniPrinter;
  793. pIniPrinter = pIniPrinter->pNext ) {
  794. wcscpy ( &PrinterName[MachineNameLen], pIniPrinter->pName );
  795. //
  796. // Stress testing has shown that SendNotifyMessage can take
  797. // a long time to return, so leave critical section.
  798. //
  799. INCPRINTERREF( pIniPrinter );
  800. LeaveSplSem();
  801. SplOutSem();
  802. SendNotifyMessage(HWND_BROADCAST,
  803. WM_DEVMODECHANGE,
  804. 0,
  805. (LPARAM)PrinterName);
  806. EnterSplSem();
  807. DECPRINTERREF( pIniPrinter );
  808. }
  809. DECSPOOLERREF( pIniSpooler );
  810. }
  811. VOID
  812. Upgrade35Forms(
  813. IN HKEY hFormsKey,
  814. IN OUT PINISPOOLER pIniSpooler
  815. )
  816. /*++
  817. Routine Description:
  818. Upgrade the forms entries in hFormsKey to include an extra DWORD
  819. FormOrder value. This value is used to determine the order of
  820. user-defined forms (built-in forms always go in the front). In
  821. the upgrade case, we assign the order based on the registry order
  822. (this is arbitrary).
  823. It is necessary to keep pIniSpooler->pIniForm in the same order
  824. to ensure EnumForms returns them in the same order, since drivers
  825. call EnumForms and assign index numbers to these forms. If the
  826. order is different, the indicies will change, and dmPaperSize in
  827. the DEVMODE will point to a different paper size.
  828. If forms are added (either by the user or by the driver when it has
  829. new paper sizes), they will be placed at the end of the list so that
  830. previous indicies do not change. If forms are deleted, then some
  831. indicies will change, and the printout will use the incorrect form
  832. (later we will add FORM_INFO_2 which returns a unique, non-changing
  833. index).
  834. Arguments:
  835. hFormsKey - Key pointing to 3.5, 3.1 forms that need to be updated.
  836. pIniSpooler - Current spooler.
  837. Return Value:
  838. VOID
  839. Notes:
  840. pIniSpooler->cFormsOrderMax updated.
  841. --*/
  842. {
  843. DWORD cUserDefinedForms;
  844. WCHAR FormName[MAX_PATH];
  845. DWORD cchFormName;
  846. REG_FORM_INFO RegFormInfo;
  847. DWORD cbRegFormInfo;
  848. //
  849. // Read in the old FORM info, which lacks the cFormOrder and/or Flags, then
  850. // write it out with the new cFormOrder and/or Flags.
  851. //
  852. for( cUserDefinedForms = 0;
  853. TRUE;
  854. ++cUserDefinedForms ){
  855. cchFormName = COUNTOF( FormName );
  856. cbRegFormInfo = sizeof( RegFormInfo );
  857. if( RegEnumValue( hFormsKey,
  858. cUserDefinedForms,
  859. (LPWSTR)FormName,
  860. &cchFormName,
  861. NULL,
  862. NULL,
  863. (LPBYTE)&RegFormInfo,
  864. &cbRegFormInfo ) != NO_ERROR ){
  865. break;
  866. }
  867. RegFormInfo.cFormOrder = cUserDefinedForms;
  868. RegFormInfo.Flags = FORM_USER;
  869. //
  870. // Write it out with the new value cFormOrderMax value.
  871. //
  872. RegSetValueEx( hFormsKey,
  873. (LPWSTR)FormName,
  874. 0,
  875. REG_BINARY,
  876. (LPBYTE)&RegFormInfo,
  877. sizeof( RegFormInfo ));
  878. }
  879. pIniSpooler->cFormOrderMax = cUserDefinedForms - 1;
  880. }