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.

1010 lines
34 KiB

  1. /*++
  2. Copyright (c) 1992-1993 Microsoft Corporation
  3. Module Name:
  4. ConvPrt.c
  5. Abstract:
  6. This module contains:
  7. NetpConvertPrintDestArrayCharSet
  8. NetpConvertPrintDestCharSet
  9. NetpConvertPrintJobArrayCharSet
  10. NetpConvertPrintJobCharSet
  11. NetpConvertPrintQArrayCharSet
  12. NetpConvertPrintQCharSet
  13. This routines may be used for UNICODE-to-ANSI conversion, or
  14. ANSI-to-UNICODE conversion. The routines assume the structures are
  15. in native format for both input and output.
  16. Author:
  17. John Rogers (JohnRo) 20-Jul-1992
  18. Environment:
  19. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  20. Requires ANSI C extensions: slash-slash comments, long external names.
  21. Notes:
  22. Beware that many of the parameters to the functions in this file
  23. are implicitly used by the various COPY_ and CONVERT_ macros:
  24. IN LPVOID FromInfo
  25. OUT LPVOID ToInfo
  26. IN BOOL ToUnicode
  27. IN OUT LPBYTE * ToStringAreaPtr
  28. Revision History:
  29. 20-Jul-1992 JohnRo
  30. Created for RAID 10324: net print vs. UNICODE.
  31. 16-Dec-1992 JohnRo
  32. DosPrint API cleanup.
  33. Allow use of these routines for setinfo APIs.
  34. Added NetpConvertPrintQArrayCharSet.
  35. 07-Apr-1993 JohnRo
  36. RAID 5670: "NET PRINT \\server\share" gives err 124 (bad level) on NT.
  37. 14-Apr-1993 JohnRo
  38. RAID 6167: avoid _access violation or assert with WFW print server.
  39. 01-Feb-2001 JSchwart
  40. Moved from netlib
  41. --*/
  42. // These must be included first:
  43. #include <nt.h> // NTSTATUS
  44. #include <ntrtl.h> // RtlUnicodeToOemN
  45. #include <windef.h> // IN, DWORD, etc.
  46. #include <lmcons.h> // NET_API_STATUS.
  47. // These may be included in any order:
  48. #include <align.h> // POINTER_IS_ALIGNED(), ALIGN_ equates.
  49. #include <debuglib.h> // IF_DEBUG().
  50. #include <netdebug.h> // NetpAssert(), NetpKdPrint(()), etc.
  51. #include <prefix.h> // PREFIX_ equates.
  52. #include <string.h> // memcpy().
  53. #include <strucinf.h> // My prototypes.
  54. #include <tstring.h> // NetpCopy{type}To{type}().
  55. #include <rxprint.h> // Print structures
  56. #include "convprt.h" // Prototypes
  57. #include "dosprtp.h" // NetpIsPrintQLevelValid
  58. VOID
  59. NetpCopyWStrToStrDBCSN(
  60. OUT LPSTR Dest, // string in default LAN codepage
  61. IN LPWSTR Src,
  62. IN DWORD MaxStringSize
  63. );
  64. #define COPY_DWORD( typedefRoot, fieldName ) \
  65. { \
  66. if (ToUnicode) { \
  67. P ## typedefRoot ## A srcStruct = FromInfo; \
  68. P ## typedefRoot ## W destStruct = ToInfo; \
  69. NetpAssert( sizeof( destStruct->fieldName ) == sizeof( DWORD ) ); \
  70. NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( DWORD ) ); \
  71. destStruct->fieldName = srcStruct->fieldName; \
  72. } else { \
  73. P ## typedefRoot ## W srcStruct = FromInfo; \
  74. P ## typedefRoot ## A destStruct = ToInfo; \
  75. NetpAssert( sizeof( destStruct->fieldName ) == sizeof( DWORD ) ); \
  76. NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( DWORD ) ); \
  77. destStruct->fieldName = srcStruct->fieldName; \
  78. } \
  79. }
  80. #define COPY_WORD( typedefRoot, fieldName ) \
  81. { \
  82. if (ToUnicode) { \
  83. P ## typedefRoot ## A srcStruct = FromInfo; \
  84. P ## typedefRoot ## W destStruct = ToInfo; \
  85. NetpAssert( sizeof( destStruct->fieldName ) == sizeof( WORD ) ); \
  86. NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( WORD ) ); \
  87. destStruct->fieldName = srcStruct->fieldName; \
  88. } else { \
  89. P ## typedefRoot ## W srcStruct = FromInfo; \
  90. P ## typedefRoot ## A destStruct = ToInfo; \
  91. NetpAssert( sizeof( destStruct->fieldName ) == sizeof( WORD ) ); \
  92. NetpAssert( sizeof( srcStruct->fieldName ) == sizeof( WORD ) ); \
  93. destStruct->fieldName = srcStruct->fieldName; \
  94. } \
  95. }
  96. #define COPY_FIXED_PART_WITHOUT_STRUCT( dataType ) \
  97. { \
  98. (VOID) memcpy( \
  99. ToInfo, /* dest */ \
  100. FromInfo, /* src */ \
  101. sizeof( dataType ) ); /* size */ \
  102. }
  103. #define CONVERT_CHAR_ARRAY( typedefRoot, fieldName ) \
  104. { \
  105. if (ToUnicode) { \
  106. P ## typedefRoot ## A structA = FromInfo; \
  107. P ## typedefRoot ## W structW = ToInfo; \
  108. NetpCopyStrToWStr( \
  109. structW->fieldName, /* dest */ \
  110. structA->fieldName); /* src */ \
  111. } else { \
  112. P ## typedefRoot ## A structA = ToInfo; \
  113. P ## typedefRoot ## W structW = FromInfo; \
  114. NetpCopyWStrToStrDBCSN( \
  115. structA->fieldName, /* dest */ \
  116. structW->fieldName, /* src */ \
  117. sizeof(structA->fieldName));/*max bytes to copy*/ \
  118. } \
  119. }
  120. #define CONVERT_OPTIONAL_STRING( typedefRoot, fieldName ) \
  121. { \
  122. NetpAssert( ToStringAreaPtr != NULL ); \
  123. NetpAssert( (*ToStringAreaPtr) != NULL ); \
  124. if (ToUnicode) { \
  125. P ## typedefRoot ## A structA = FromInfo; \
  126. P ## typedefRoot ## W structW = ToInfo; \
  127. LPSTR Src = structA->fieldName; \
  128. NetpAssert( POINTER_IS_ALIGNED(*ToStringAreaPtr, ALIGN_WCHAR) ); \
  129. if (Src == NULL) { \
  130. structW->fieldName = NULL; \
  131. } else { \
  132. LPWSTR Dest; \
  133. DWORD DestSize; \
  134. DestSize = (strlen(Src)+1) * sizeof(WCHAR); \
  135. Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
  136. *ToStringAreaPtr = (LPVOID) Dest; \
  137. structW->fieldName = Dest; \
  138. NetpCopyStrToWStr( Dest, Src ); \
  139. } \
  140. } else { \
  141. P ## typedefRoot ## W structW = FromInfo; \
  142. P ## typedefRoot ## A structA = ToInfo; \
  143. LPWSTR Src = structW->fieldName; \
  144. if (Src == NULL) { \
  145. structA->fieldName = NULL; \
  146. } else { \
  147. LPSTR Dest; \
  148. DWORD DestSize; \
  149. DestSize = (NetpUnicodeToDBCSLen(Src)+1); \
  150. Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
  151. *ToStringAreaPtr = (LPVOID) Dest; \
  152. structA->fieldName = Dest; \
  153. NetpCopyWStrToStrDBCS( Dest, Src ); \
  154. } \
  155. } \
  156. }
  157. #define CONVERT_OPTIONAL_STRING_TO_REQ( typedefRoot, fieldName ) \
  158. { \
  159. NetpAssert( ToStringAreaPtr != NULL ); \
  160. NetpAssert( (*ToStringAreaPtr) != NULL ); \
  161. if (ToUnicode) { \
  162. P ## typedefRoot ## A structA = FromInfo; \
  163. P ## typedefRoot ## W structW = ToInfo; \
  164. LPWSTR Dest; \
  165. DWORD DestSize; \
  166. LPSTR Src = structA->fieldName; \
  167. NetpAssert( POINTER_IS_ALIGNED(*ToStringAreaPtr, ALIGN_WCHAR) ); \
  168. if (Src == NULL) { \
  169. Src = ""; \
  170. } \
  171. DestSize = (strlen(Src)+1) * sizeof(WCHAR); \
  172. Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
  173. *ToStringAreaPtr = (LPVOID) Dest; \
  174. structW->fieldName = Dest; \
  175. NetpCopyStrToWStr( Dest, Src ); \
  176. } else { \
  177. P ## typedefRoot ## A structA = ToInfo; \
  178. P ## typedefRoot ## W structW = FromInfo; \
  179. LPSTR Dest; \
  180. DWORD DestSize; \
  181. LPWSTR Src = structW->fieldName; \
  182. if (Src == NULL) { \
  183. Src = L""; \
  184. } \
  185. DestSize = (NetpUnicodeToDBCSLen(Src)+1); \
  186. Dest = (LPVOID) ( (*ToStringAreaPtr) - DestSize ); \
  187. *ToStringAreaPtr = (LPVOID) Dest; \
  188. structA->fieldName = Dest; \
  189. NetpCopyWStrToStrDBCS( Dest, Src ); \
  190. } \
  191. }
  192. #define CONVERT_CHAR_ARRAY_WITHOUT_STRUCT( ) \
  193. { \
  194. if (ToUnicode) { \
  195. NetpCopyStrToWStr( ToInfo, FromInfo ); \
  196. } else { \
  197. NetpCopyWStrToStrDBCS( ToInfo, FromInfo ); \
  198. } \
  199. }
  200. #define CONVERT_CHAR_PTR_WITHOUT_STRUCT( ) \
  201. { \
  202. if (ToUnicode) { \
  203. NetpCopyStrToWStr( ToInfo, FromInfo ); \
  204. } else { \
  205. NetpCopyWStrToStrDBCS( ToInfo, FromInfo ); \
  206. } \
  207. }
  208. NET_API_STATUS
  209. NetpConvertPrintDestCharSet(
  210. IN DWORD Level,
  211. IN BOOL AddOrSetInfoApi,
  212. IN LPVOID FromInfo,
  213. OUT LPVOID ToInfo,
  214. IN BOOL ToUnicode,
  215. IN OUT LPBYTE * ToStringAreaPtr OPTIONAL
  216. )
  217. {
  218. IF_DEBUG( CONVPRT ) {
  219. NetpKdPrint(( PREFIX_NETLIB "NetpConvertPrintDestCharSet: "
  220. "level " FORMAT_DWORD ":\n", Level ));
  221. }
  222. if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
  223. return (ERROR_INVALID_PARAMETER);
  224. }
  225. switch (Level) {
  226. case 0 :
  227. //
  228. // No structure for this level.
  229. // Only field is name, which is in the fixed part itself.
  230. //
  231. CONVERT_CHAR_ARRAY_WITHOUT_STRUCT( );
  232. break;
  233. case 1 :
  234. CONVERT_CHAR_ARRAY( PRDINFO, szName );
  235. CONVERT_CHAR_ARRAY( PRDINFO, szUserName );
  236. COPY_WORD( PRDINFO, uJobId );
  237. COPY_WORD( PRDINFO, fsStatus );
  238. CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO, pszStatus );
  239. COPY_WORD( PRDINFO, time );
  240. break;
  241. case 2 :
  242. //
  243. // No structure for this level.
  244. // Only field is pointer to name.
  245. //
  246. CONVERT_CHAR_PTR_WITHOUT_STRUCT( );
  247. break;
  248. case 3 :
  249. CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszPrinterName );
  250. CONVERT_OPTIONAL_STRING( PRDINFO3, pszUserName );
  251. CONVERT_OPTIONAL_STRING( PRDINFO3, pszLogAddr );
  252. COPY_WORD( PRDINFO3, uJobId );
  253. COPY_WORD( PRDINFO3, fsStatus );
  254. CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszStatus );
  255. CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszComment );
  256. CONVERT_OPTIONAL_STRING_TO_REQ( PRDINFO3, pszDrivers );
  257. COPY_WORD( PRDINFO3, time );
  258. // No need to copy pad1.
  259. break;
  260. default :
  261. return (ERROR_INVALID_LEVEL);
  262. }
  263. return (NO_ERROR);
  264. } // NetpConvertPrintDestCharSet
  265. NET_API_STATUS
  266. NetpConvertPrintDestArrayCharSet(
  267. IN DWORD Level,
  268. IN BOOL AddOrSetInfoApi,
  269. IN LPVOID FromInfo,
  270. OUT LPVOID ToInfo,
  271. IN BOOL ToUnicode,
  272. IN OUT LPBYTE * ToStringAreaPtr OPTIONAL,
  273. IN DWORD DestCount
  274. )
  275. {
  276. NET_API_STATUS ApiStatus;
  277. DWORD DestsLeft;
  278. DWORD FromEntrySize, ToEntrySize;
  279. LPVOID FromDest = FromInfo;
  280. LPVOID ToDest = ToInfo;
  281. if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
  282. return (ERROR_INVALID_PARAMETER);
  283. }
  284. ApiStatus = NetpPrintDestStructureInfo (
  285. Level,
  286. PARMNUM_ALL,
  287. TRUE, // yes, we want native sizes.
  288. AddOrSetInfoApi,
  289. (ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
  290. NULL, // don't need data desc 16
  291. NULL, // don't need data desc 32
  292. NULL, // don't need data desc SMB
  293. NULL, // don't need max total size
  294. & FromEntrySize, // yes, we want fixed entry size
  295. NULL ); // don't need string size
  296. if (ApiStatus != NO_ERROR) {
  297. return (ApiStatus);
  298. }
  299. NetpAssert( FromEntrySize > 0 );
  300. ApiStatus = NetpPrintDestStructureInfo (
  301. Level,
  302. PARMNUM_ALL,
  303. TRUE, // yes, we want native sizes.
  304. AddOrSetInfoApi,
  305. (ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
  306. NULL, // don't need data desc 16
  307. NULL, // don't need data desc 32
  308. NULL, // don't need data desc SMB
  309. NULL, // don't need max total size
  310. & ToEntrySize, // yes, we want fixed entry size
  311. NULL ); // don't need string size
  312. NetpAssert( ApiStatus == NO_ERROR );
  313. NetpAssert( ToEntrySize > 0 );
  314. for (DestsLeft = DestCount; DestsLeft>0; --DestsLeft) {
  315. ApiStatus = NetpConvertPrintDestCharSet(
  316. Level, // info level (for print Dest APIs)
  317. AddOrSetInfoApi,
  318. FromDest,
  319. ToDest,
  320. ToUnicode,
  321. ToStringAreaPtr ); // update and move string area
  322. //
  323. // This can only fail because of bad parameters. If that's
  324. // the case, every call in this loop will fail so bail out.
  325. //
  326. if (ApiStatus != NO_ERROR)
  327. {
  328. NetpAssert( ApiStatus == NO_ERROR );
  329. break;
  330. }
  331. FromDest = (((LPBYTE) FromDest) + FromEntrySize);
  332. ToDest = (((LPBYTE) ToDest) + ToEntrySize );
  333. }
  334. return (NO_ERROR);
  335. } // NetpConvertPrintDestArrayCharSet
  336. NET_API_STATUS
  337. NetpConvertPrintJobCharSet(
  338. IN DWORD Level,
  339. IN BOOL AddOrSetInfoApi,
  340. IN LPVOID FromInfo,
  341. OUT LPVOID ToInfo,
  342. IN BOOL ToUnicode,
  343. IN OUT LPBYTE * ToStringAreaPtr OPTIONAL
  344. )
  345. {
  346. IF_DEBUG( CONVPRT ) {
  347. NetpKdPrint(( PREFIX_NETLIB "NetpConvertPrintJobCharSet: "
  348. "level " FORMAT_DWORD ":\n", Level ));
  349. }
  350. if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
  351. return (ERROR_INVALID_PARAMETER);
  352. }
  353. switch (Level) {
  354. case 0 :
  355. COPY_FIXED_PART_WITHOUT_STRUCT( WORD );
  356. break;
  357. case 1 :
  358. COPY_WORD( PRJINFO, uJobId );
  359. CONVERT_CHAR_ARRAY( PRJINFO, szUserName );
  360. CONVERT_CHAR_ARRAY( PRJINFO, szNotifyName );
  361. CONVERT_CHAR_ARRAY( PRJINFO, szDataType );
  362. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO, pszParms );
  363. COPY_WORD( PRJINFO, uPosition );
  364. COPY_WORD( PRJINFO, fsStatus );
  365. CONVERT_OPTIONAL_STRING( PRJINFO, pszStatus );
  366. COPY_DWORD( PRJINFO, ulSubmitted );
  367. COPY_DWORD( PRJINFO, ulSize );
  368. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO, pszComment );
  369. break;
  370. case 2 :
  371. COPY_WORD( PRJINFO2, uJobId );
  372. COPY_WORD( PRJINFO2, uPriority );
  373. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO2, pszUserName );
  374. COPY_WORD( PRJINFO2, uPosition );
  375. COPY_WORD( PRJINFO2, fsStatus );
  376. COPY_DWORD( PRJINFO2, ulSubmitted );
  377. COPY_DWORD( PRJINFO2, ulSize );
  378. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO2, pszComment );
  379. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO2, pszDocument );
  380. break;
  381. case 3 :
  382. COPY_WORD( PRJINFO3, uJobId );
  383. COPY_WORD( PRJINFO3, uPriority );
  384. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszUserName );
  385. COPY_WORD( PRJINFO3, uPosition );
  386. COPY_WORD( PRJINFO3, fsStatus );
  387. COPY_DWORD( PRJINFO3, ulSubmitted );
  388. COPY_DWORD( PRJINFO3, ulSize );
  389. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszComment );
  390. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszDocument );
  391. CONVERT_OPTIONAL_STRING( PRJINFO3, pszNotifyName );
  392. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszDataType );
  393. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszParms );
  394. CONVERT_OPTIONAL_STRING( PRJINFO3, pszStatus );
  395. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszQueue );
  396. CONVERT_OPTIONAL_STRING_TO_REQ( PRJINFO3, pszQProcName );
  397. CONVERT_OPTIONAL_STRING( PRJINFO3, pszDriverName );
  398. #if DBG
  399. {
  400. if (ToUnicode) {
  401. PPRJINFO3A p3 = FromInfo;
  402. NetpAssert( p3->pDriverData == NULL );
  403. } else {
  404. PPRJINFO3W p3 = FromInfo;
  405. NetpAssert( p3->pDriverData == NULL );
  406. }
  407. }
  408. #endif
  409. CONVERT_OPTIONAL_STRING( PRJINFO3, pszPrinterName );
  410. break;
  411. default :
  412. return (ERROR_INVALID_LEVEL);
  413. }
  414. return (NO_ERROR);
  415. } // NetpConvertPrintJobCharSet
  416. NET_API_STATUS
  417. NetpConvertPrintJobArrayCharSet(
  418. IN DWORD Level,
  419. IN BOOL AddOrSetInfoApi,
  420. IN LPVOID FromInfo,
  421. OUT LPVOID ToInfo,
  422. IN BOOL ToUnicode,
  423. IN OUT LPBYTE * ToStringAreaPtr OPTIONAL,
  424. IN DWORD JobCount
  425. )
  426. {
  427. NET_API_STATUS ApiStatus;
  428. DWORD FromEntrySize, ToEntrySize;
  429. LPVOID FromJob = FromInfo; // job structure
  430. DWORD JobsLeft;
  431. LPVOID ToJob = ToInfo; // job structure
  432. if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
  433. return (ERROR_INVALID_PARAMETER);
  434. }
  435. ApiStatus = NetpPrintJobStructureInfo (
  436. Level,
  437. PARMNUM_ALL,
  438. TRUE, // yes, we want native sizes.
  439. AddOrSetInfoApi,
  440. (ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
  441. NULL, // don't need data desc 16
  442. NULL, // don't need data desc 32
  443. NULL, // don't need data desc SMB
  444. NULL, // don't need max total size
  445. & FromEntrySize, // yes, we want fixed entry size
  446. NULL ); // don't need string size
  447. if (ApiStatus != NO_ERROR) {
  448. return (ApiStatus);
  449. }
  450. NetpAssert( FromEntrySize > 0 );
  451. ApiStatus = NetpPrintJobStructureInfo (
  452. Level,
  453. PARMNUM_ALL,
  454. TRUE, // yes, we want native sizes.
  455. AddOrSetInfoApi,
  456. (ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
  457. NULL, // don't need data desc 16
  458. NULL, // don't need data desc 32
  459. NULL, // don't need data desc SMB
  460. NULL, // don't need max total size
  461. & ToEntrySize, // yes, we want fixed entry size
  462. NULL ); // don't need string size
  463. NetpAssert( ApiStatus == NO_ERROR );
  464. NetpAssert( ToEntrySize > 0 );
  465. for (JobsLeft = JobCount; JobsLeft>0; --JobsLeft) {
  466. ApiStatus = NetpConvertPrintJobCharSet(
  467. Level, // info level (for print job APIs)
  468. AddOrSetInfoApi,
  469. FromJob,
  470. ToJob,
  471. ToUnicode,
  472. ToStringAreaPtr ); // update and move string area
  473. //
  474. // This can only fail because of bad parameters. If that's
  475. // the case, every call in this loop will fail so bail out.
  476. //
  477. if (ApiStatus != NO_ERROR)
  478. {
  479. NetpAssert( ApiStatus == NO_ERROR );
  480. break;
  481. }
  482. FromJob = (((LPBYTE) FromJob) + FromEntrySize);
  483. ToJob = (((LPBYTE) ToJob ) + ToEntrySize );
  484. if ((LPBYTE)*ToStringAreaPtr < (LPBYTE)ToJob)
  485. return (ERROR_MORE_DATA) ;
  486. }
  487. return (NO_ERROR);
  488. } // NetpConvertPrintJobArrayCharSet
  489. NET_API_STATUS
  490. NetpConvertPrintQCharSet(
  491. IN DWORD Level,
  492. IN BOOL AddOrSetInfoApi,
  493. IN LPVOID FromInfo,
  494. OUT LPVOID ToInfo,
  495. IN BOOL ToUnicode,
  496. IN OUT LPBYTE * ToStringAreaPtr OPTIONAL
  497. )
  498. {
  499. NET_API_STATUS ApiStatus;
  500. DWORD FromEntrySize, ToEntrySize;
  501. IF_DEBUG( CONVPRT ) {
  502. NetpKdPrint(( PREFIX_NETLIB "NetpConvertPrintQCharSet: "
  503. "level " FORMAT_DWORD ":\n", Level ));
  504. }
  505. if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
  506. return (ERROR_INVALID_PARAMETER);
  507. }
  508. ApiStatus = NetpPrintQStructureInfo (
  509. Level,
  510. PARMNUM_ALL,
  511. TRUE, // yes, we want native sizes.
  512. AddOrSetInfoApi,
  513. (ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
  514. NULL, // don't need data desc 16
  515. NULL, // don't need data desc 32
  516. NULL, // don't need data desc SMB
  517. NULL, // don't need aux desc 16
  518. NULL, // don't need aux desc 32
  519. NULL, // don't need aux desc SMB
  520. NULL, // don't need max total size
  521. & ToEntrySize, // yes, we want fixed entry size
  522. NULL ); // don't need string size
  523. if (ApiStatus != NO_ERROR) {
  524. return (ApiStatus);
  525. }
  526. NetpAssert( ToEntrySize > 0 );
  527. ApiStatus = NetpPrintQStructureInfo (
  528. Level,
  529. PARMNUM_ALL,
  530. TRUE, // yes, we want native sizes.
  531. AddOrSetInfoApi,
  532. (ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
  533. NULL, // don't need data desc 16
  534. NULL, // don't need data desc 32
  535. NULL, // don't need data desc SMB
  536. NULL, // don't need aux desc 16
  537. NULL, // don't need aux desc 32
  538. NULL, // don't need aux desc SMB
  539. NULL, // don't need max total size
  540. & FromEntrySize, // yes, we want fixed entry size
  541. NULL ); // don't need string size
  542. NetpAssert( ApiStatus == NO_ERROR );
  543. NetpAssert( FromEntrySize > 0 );
  544. switch (Level) {
  545. case 0 :
  546. //
  547. // No structure for this level.
  548. // Only field is queue name, which is in the fixed part itself.
  549. //
  550. CONVERT_CHAR_ARRAY_WITHOUT_STRUCT( );
  551. break;
  552. case 1 : /*FALLTHROUGH*/
  553. case 2 :
  554. CONVERT_CHAR_ARRAY( PRQINFO, szName );
  555. // No need to copy pad1.
  556. COPY_WORD( PRQINFO, uPriority );
  557. COPY_WORD( PRQINFO, uStartTime );
  558. COPY_WORD( PRQINFO, uUntilTime );
  559. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszSepFile );
  560. CONVERT_OPTIONAL_STRING( PRQINFO, pszPrProc );
  561. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszDestinations );
  562. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszParms );
  563. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO, pszComment );
  564. COPY_WORD( PRQINFO, fsStatus );
  565. COPY_WORD( PRQINFO, cJobs );
  566. if (Level == 2) {
  567. NET_API_STATUS ApiStatus;
  568. LPVOID FromArray, ToArray; // job structures
  569. DWORD JobCount;
  570. if (ToUnicode) {
  571. PPRQINFOA pq = FromInfo;
  572. JobCount = pq->cJobs;
  573. } else {
  574. PPRQINFOW pq = FromInfo;
  575. JobCount = pq->cJobs;
  576. }
  577. FromArray = ( ((LPBYTE) FromInfo) + FromEntrySize );
  578. ToArray = ( ((LPBYTE) ToInfo ) + ToEntrySize );
  579. ApiStatus = NetpConvertPrintJobArrayCharSet(
  580. 1, // job info level
  581. AddOrSetInfoApi,
  582. FromArray,
  583. ToArray,
  584. ToUnicode,
  585. ToStringAreaPtr, // update and move string area
  586. JobCount );
  587. if ( ApiStatus != NO_ERROR )
  588. return (ApiStatus) ;
  589. }
  590. break;
  591. case 3 : /*FALLTHROUGH*/
  592. case 4 :
  593. {
  594. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszName );
  595. COPY_WORD( PRQINFO3, uPriority );
  596. COPY_WORD( PRQINFO3, uStartTime );
  597. COPY_WORD( PRQINFO3, uUntilTime );
  598. // No need to copy pad3.
  599. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszSepFile );
  600. CONVERT_OPTIONAL_STRING( PRQINFO3, pszPrProc );
  601. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszParms );
  602. CONVERT_OPTIONAL_STRING_TO_REQ( PRQINFO3, pszComment );
  603. COPY_WORD( PRQINFO3, fsStatus );
  604. COPY_WORD( PRQINFO3, cJobs );
  605. CONVERT_OPTIONAL_STRING( PRQINFO3, pszPrinters );
  606. CONVERT_OPTIONAL_STRING( PRQINFO3, pszDriverName );
  607. #if DBG
  608. if (ToUnicode) {
  609. PPRQINFO3A pq = FromInfo;
  610. NetpAssert( pq->pDriverData == NULL );
  611. } else {
  612. PPRQINFO3W pq = FromInfo;
  613. NetpAssert( pq->pDriverData == NULL );
  614. }
  615. #endif
  616. if (Level == 4) {
  617. NET_API_STATUS ApiStatus;
  618. LPVOID FromFirstJob,ToFirstJob; // job structures
  619. DWORD JobCount;
  620. FromFirstJob = ( ((LPBYTE) FromInfo) + FromEntrySize );
  621. ToFirstJob = ( ((LPBYTE) ToInfo ) + ToEntrySize );
  622. if (ToUnicode) {
  623. PPRQINFO3A pq = FromInfo;
  624. JobCount = pq->cJobs;
  625. } else {
  626. PPRQINFO3W pq = FromInfo;
  627. JobCount = pq->cJobs;
  628. }
  629. ApiStatus = NetpConvertPrintJobArrayCharSet(
  630. 2, // job info level
  631. AddOrSetInfoApi,
  632. FromFirstJob,
  633. ToFirstJob,
  634. ToUnicode,
  635. ToStringAreaPtr,
  636. JobCount );
  637. NetpAssert( ApiStatus == NO_ERROR );
  638. }
  639. }
  640. break;
  641. case 5 :
  642. //
  643. // No structure for this level.
  644. // Only field is queue name, which is just a pointer in the fixed part.
  645. //
  646. CONVERT_CHAR_PTR_WITHOUT_STRUCT( );
  647. break;
  648. default :
  649. return (ERROR_INVALID_LEVEL);
  650. }
  651. return (NO_ERROR);
  652. } // NetpConvertPrintQCharSet
  653. NET_API_STATUS
  654. NetpConvertPrintQArrayCharSet(
  655. IN DWORD QLevel,
  656. IN BOOL AddOrSetInfoApi,
  657. IN LPVOID FromInfo,
  658. OUT LPVOID ToInfo,
  659. IN BOOL ToUnicode,
  660. IN OUT LPBYTE * ToStringAreaPtr OPTIONAL,
  661. IN DWORD QCount
  662. )
  663. {
  664. NET_API_STATUS ApiStatus;
  665. DWORD FromQEntrySize, ToQEntrySize;
  666. DWORD FromJobEntrySize, ToJobEntrySize;
  667. LPVOID FromQ = FromInfo; // Q structure
  668. DWORD JobLevel;
  669. DWORD QsLeft;
  670. LPVOID ToQ = ToInfo; // Q structure
  671. if ( (FromInfo == NULL) || (ToInfo == NULL) ) {
  672. return (ERROR_INVALID_PARAMETER);
  673. }
  674. ApiStatus = NetpPrintQStructureInfo (
  675. QLevel,
  676. PARMNUM_ALL,
  677. TRUE, // yes, we want native sizes.
  678. AddOrSetInfoApi,
  679. (ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
  680. NULL, // don't need data desc 16
  681. NULL, // don't need data desc 32
  682. NULL, // don't need data desc SMB
  683. NULL, // don't need aux desc 16
  684. NULL, // don't need aux desc 32
  685. NULL, // don't need aux desc SMB
  686. NULL, // don't need max total size
  687. & FromQEntrySize, // yes, we want fixed entry size
  688. NULL ); // don't need string size
  689. if (ApiStatus != NO_ERROR) {
  690. return (ApiStatus);
  691. }
  692. NetpAssert( FromQEntrySize > 0 );
  693. ApiStatus = NetpPrintQStructureInfo (
  694. QLevel,
  695. PARMNUM_ALL,
  696. TRUE, // yes, we want native sizes.
  697. AddOrSetInfoApi,
  698. (ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
  699. NULL, // don't need data desc 16
  700. NULL, // don't need data desc 32
  701. NULL, // don't need data desc SMB
  702. NULL, // don't need aux desc 16
  703. NULL, // don't need aux desc 32
  704. NULL, // don't need aux desc SMB
  705. NULL, // don't need max total size
  706. & ToQEntrySize, // yes, we want fixed entry size
  707. NULL ); // don't need string size
  708. NetpAssert( ApiStatus == NO_ERROR );
  709. NetpAssert( ToQEntrySize > 0 );
  710. // Figure-out job-level associated with this queue info level.
  711. switch (QLevel) {
  712. case 2:
  713. JobLevel = 1;
  714. break;
  715. case 4:
  716. JobLevel = 2;
  717. break;
  718. default:
  719. // No jobs for this Q info level.
  720. JobLevel = (DWORD)-1;
  721. }
  722. if (JobLevel != (DWORD)-1) {
  723. ApiStatus = NetpPrintJobStructureInfo (
  724. JobLevel,
  725. PARMNUM_ALL,
  726. TRUE, // yes, we want native sizes.
  727. AddOrSetInfoApi,
  728. (ToUnicode ? sizeof(CHAR) : sizeof(WCHAR) ), // FROM char size
  729. NULL, // don't need data desc 16
  730. NULL, // don't need data desc 32
  731. NULL, // don't need data desc SMB
  732. NULL, // don't need max total size
  733. & FromJobEntrySize, // yes, we want fixed entry size
  734. NULL ); // don't need string size
  735. NetpAssert( ApiStatus == NO_ERROR );
  736. NetpAssert( FromJobEntrySize > 0 );
  737. ApiStatus = NetpPrintJobStructureInfo (
  738. JobLevel,
  739. PARMNUM_ALL,
  740. TRUE, // yes, we want native sizes.
  741. AddOrSetInfoApi,
  742. (ToUnicode ? sizeof(WCHAR) : sizeof(CHAR) ), // TO char size
  743. NULL, // don't need data desc 16
  744. NULL, // don't need data desc 32
  745. NULL, // don't need data desc SMB
  746. NULL, // don't need max total size
  747. & ToJobEntrySize, // yes, we want fixed entry size
  748. NULL ); // don't need string size
  749. NetpAssert( ApiStatus == NO_ERROR );
  750. NetpAssert( ToJobEntrySize > 0 );
  751. }
  752. for (QsLeft = QCount; QsLeft>0; --QsLeft) {
  753. DWORD JobCount;
  754. // Convert 1 queue structure and 0 or more job structures.
  755. ApiStatus = NetpConvertPrintQCharSet(
  756. QLevel, // info level (for print Q APIs)
  757. AddOrSetInfoApi,
  758. FromQ,
  759. ToQ,
  760. ToUnicode,
  761. ToStringAreaPtr ); // update and move string area
  762. if (ApiStatus != NO_ERROR)
  763. {
  764. NetpAssert( ApiStatus == NO_ERROR);
  765. break;
  766. }
  767. // Bump pointers to start of next fixed queue structure.
  768. // To do this, we need to find out how many jobs there are.
  769. JobCount = NetpJobCountForQueue(
  770. QLevel, // Q info level
  771. FromQ, // Q fixed structure
  772. !ToUnicode ); // does input have UNICODE strings?
  773. // Bump past this queue structure.
  774. FromQ = (((LPBYTE) FromQ) + FromQEntrySize);
  775. ToQ = (((LPBYTE) ToQ ) + ToQEntrySize );
  776. // Bump past jobs (if any).
  777. if (JobCount > 0) {
  778. NetpAssert( JobLevel != (DWORD)-1 );
  779. FromQ = ( ((LPBYTE) FromQ) + (FromJobEntrySize * JobCount) );
  780. ToQ = ( ((LPBYTE) ToQ ) + (ToJobEntrySize * JobCount) );
  781. }
  782. }
  783. return (NO_ERROR);
  784. } // NetpConvertPrintQArrayCharSet
  785. VOID
  786. NetpCopyWStrToStrDBCSN(
  787. OUT LPSTR Dest,
  788. IN LPWSTR Src,
  789. IN DWORD MaxBytesInString
  790. )
  791. /*++
  792. Routine Description:
  793. NetpCopyWStrToStr copies characters from a source string
  794. to a destination, converting as it copies them.
  795. Arguments:
  796. Dest - is an LPSTR indicating where the converted characters are to go.
  797. This string will be in the default codepage for the LAN.
  798. Src - is in LPWSTR indicating the source string.
  799. MaxBytesInString - indicates the maximum number of bytes to copy
  800. Return Value:
  801. None.
  802. --*/
  803. {
  804. NTSTATUS NtStatus;
  805. LONG Index;
  806. NetpAssert( Dest != NULL );
  807. NetpAssert( Src != NULL );
  808. NetpAssert( ((LPVOID)Dest) != ((LPVOID)Src) );
  809. NetpAssert( ROUND_UP_POINTER( Src, ALIGN_WCHAR ) == Src );
  810. NtStatus = RtlUnicodeToOemN(
  811. Dest, // Destination string
  812. MaxBytesInString-1, // Destination string length
  813. &Index, // Last char in translated string
  814. Src, // Source string
  815. wcslen(Src)*sizeof(WCHAR) // Length of source string
  816. );
  817. Dest[Index] = '\0';
  818. NetpAssert( NT_SUCCESS(NtStatus) );
  819. } // NetpCopyWStrToStrDBCSN
  820. DWORD
  821. NetpJobCountForQueue(
  822. IN DWORD QueueLevel,
  823. IN LPVOID Queue,
  824. IN BOOL HasUnicodeStrings
  825. )
  826. {
  827. NetpAssert( NetpIsPrintQLevelValid( QueueLevel, FALSE ) );
  828. NetpAssert( Queue != NULL );
  829. if (QueueLevel == 2) {
  830. if (HasUnicodeStrings) {
  831. PPRQINFOW pq = Queue;
  832. return (pq->cJobs);
  833. } else {
  834. PPRQINFOA pq = Queue;
  835. return (pq->cJobs);
  836. }
  837. } else if (QueueLevel == 4) {
  838. if (HasUnicodeStrings) {
  839. PPRQINFO3W pq = Queue;
  840. return (pq->cJobs);
  841. } else {
  842. PPRQINFO3A pq = Queue;
  843. return (pq->cJobs);
  844. }
  845. } else {
  846. return (0);
  847. }
  848. /*NOTREACHED*/
  849. } // NetpJobCountForQueue