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.

6136 lines
159 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. win32 provider (win32spl)
  6. Abstract:
  7. Author:
  8. DaveSn
  9. Environment:
  10. User Mode -Win32
  11. Revision History:
  12. Matthew A Felton (Mattfe) July 16 1994
  13. Added Caching for remote NT printers
  14. MattFe Jan 1995 CleanUp DeletePrinterConnection ( for memory allocation errors )
  15. SWilson May 1996 Added RemoteEnumPrinterData & RemoteDeletePrinterData
  16. SWilson Dec 1996 Added RemoteDeletePrinterDataEx, RemoteGetPrinterDataEx,
  17. RemoteSetPrinterDataEx, RemoteEnumPrinterDataEx,
  18. RemoteEnumPrinterKey, RemoteDeletePrinterKey
  19. --*/
  20. #include <precomp.h>
  21. #pragma hdrstop
  22. DWORD
  23. RpcValidate(
  24. );
  25. BOOL
  26. RemoteFindFirstPrinterChangeNotification(
  27. HANDLE hPrinter,
  28. DWORD fdwFlags,
  29. DWORD fdwOptions,
  30. HANDLE hNotify,
  31. PDWORD pfdwStatus,
  32. PVOID pvReserved0,
  33. PVOID pvReserved1);
  34. BOOL
  35. RemoteFindClosePrinterChangeNotification(
  36. HANDLE hPrinter);
  37. BOOL
  38. RemoteRefreshPrinterChangeNotification(
  39. HANDLE hPrinter,
  40. DWORD dwColor,
  41. PVOID pPrinterNotifyRefresh,
  42. PVOID* ppPrinterNotifyInfo);
  43. DWORD
  44. RemoteSendRecvBidiData(
  45. IN HANDLE hPrinter,
  46. IN LPCTSTR pAction,
  47. IN PBIDI_REQUEST_CONTAINER pReqData,
  48. OUT PBIDI_RESPONSE_CONTAINER* ppResData
  49. );
  50. LPWSTR
  51. AnsiToUnicodeStringWithAlloc(
  52. LPSTR pAnsi
  53. );
  54. HANDLE hInst; /* DLL instance handle, used for resources */
  55. #define MAX_PRINTER_INFO2 1000
  56. HANDLE hNetApi;
  57. NET_API_STATUS (*pfnNetServerEnum)();
  58. NET_API_STATUS (*pfnNetShareEnum)();
  59. NET_API_STATUS (*pfnNetWkstaUserGetInfo)();
  60. NET_API_STATUS (*pfnNetWkstaGetInfo)();
  61. NET_API_STATUS (*pfnNetServerGetInfo)();
  62. NET_API_STATUS (*pfnNetApiBufferFree)();
  63. WCHAR szPrintProvidorName[80];
  64. WCHAR szPrintProvidorDescription[80];
  65. WCHAR szPrintProvidorComment[80];
  66. WCHAR *szLoggedOnDomain=L"Logged on Domain";
  67. WCHAR *szRegistryConnections=L"Printers\\Connections";
  68. WCHAR *szRegistryPath=NULL;
  69. WCHAR *szRegistryPortNames=L"PortNames";
  70. PWCHAR pszRemoteRegistryPrinters = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers\\%ws\\PrinterDriverData";
  71. WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+3];
  72. LPWSTR *gppszOtherNames; // Contains szMachineName, DNS name, and all other machine name forms
  73. DWORD gcOtherNames;
  74. WCHAR *szVersion=L"Version";
  75. WCHAR *szName=L"Name";
  76. WCHAR *szConfigurationFile=L"Configuration File";
  77. WCHAR *szDataFile=L"Data File";
  78. WCHAR *szDriver=L"Driver";
  79. WCHAR *szDevices=L"Devices";
  80. WCHAR *szPrinterPorts=L"PrinterPorts";
  81. WCHAR *szPorts=L"Ports";
  82. WCHAR *szComma = L",";
  83. WCHAR *szRegistryRoot = L"System\\CurrentControlSet\\Control\\Print";
  84. WCHAR *szMajorVersion = L"MajorVersion";
  85. WCHAR *szMinorVersion = L"MinorVersion";
  86. // kernel mode is 2.
  87. DWORD cThisMajorVersion = SPOOLER_VERSION;
  88. DWORD cThisMinorVersion = 0;
  89. BOOL bRpcPipeCleanup = FALSE;
  90. BOOL gbMachineInDomain = FALSE;
  91. SPLCLIENT_INFO_1 gSplClientInfo1;
  92. DWORD gdwThisGetVersion;
  93. LPWSTR szEnvironment = LOCAL_ENVIRONMENT;
  94. CRITICAL_SECTION SpoolerSection;
  95. //
  96. // Note indented calls have some Cache Effect.
  97. //
  98. PRINTPROVIDOR PrintProvidor = { CacheOpenPrinter,
  99. SetJob,
  100. GetJob,
  101. EnumJobs,
  102. AddPrinter,
  103. DeletePrinter,
  104. SetPrinter,
  105. CacheGetPrinter,
  106. EnumPrinters,
  107. RemoteAddPrinterDriver,
  108. EnumPrinterDrivers,
  109. CacheGetPrinterDriver,
  110. RemoteGetPrinterDriverDirectory,
  111. DeletePrinterDriver,
  112. AddPrintProcessor,
  113. EnumPrintProcessors,
  114. GetPrintProcessorDirectory,
  115. DeletePrintProcessor,
  116. EnumPrintProcessorDatatypes,
  117. StartDocPrinter,
  118. StartPagePrinter,
  119. WritePrinter,
  120. EndPagePrinter,
  121. AbortPrinter,
  122. ReadPrinter,
  123. RemoteEndDocPrinter,
  124. AddJob,
  125. ScheduleJob,
  126. CacheGetPrinterData,
  127. SetPrinterData,
  128. WaitForPrinterChange,
  129. CacheClosePrinter,
  130. AddForm,
  131. DeleteForm,
  132. CacheGetForm,
  133. SetForm,
  134. CacheEnumForms,
  135. EnumMonitors,
  136. RemoteEnumPorts,
  137. RemoteAddPort,
  138. RemoteConfigurePort,
  139. RemoteDeletePort,
  140. CreatePrinterIC,
  141. PlayGdiScriptOnPrinterIC,
  142. DeletePrinterIC,
  143. AddPrinterConnection,
  144. DeletePrinterConnection,
  145. PrinterMessageBox,
  146. AddMonitor,
  147. DeleteMonitor,
  148. CacheResetPrinter,
  149. NULL,
  150. RemoteFindFirstPrinterChangeNotification,
  151. RemoteFindClosePrinterChangeNotification,
  152. RemoteAddPortEx,
  153. NULL,
  154. RemoteRefreshPrinterChangeNotification,
  155. NULL,
  156. NULL,
  157. SetPort,
  158. RemoteEnumPrinterData,
  159. RemoteDeletePrinterData,
  160. NULL, // Clustering
  161. NULL, // Clustering
  162. NULL, // Clustering
  163. RemoteSetPrinterDataEx,
  164. CacheGetPrinterDataEx,
  165. CacheEnumPrinterDataEx,
  166. CacheEnumPrinterKey,
  167. RemoteDeletePrinterDataEx,
  168. RemoteDeletePrinterKey,
  169. SeekPrinter,
  170. DeletePrinterDriverEx,
  171. AddPerMachineConnection,
  172. DeletePerMachineConnection,
  173. EnumPerMachineConnections,
  174. RemoteXcvData,
  175. AddPrinterDriverEx,
  176. NULL,
  177. NULL,
  178. NULL,
  179. NULL,
  180. NULL,
  181. NULL,
  182. RemoteSendRecvBidiData,
  183. NULL,
  184. };
  185. #ifdef DEBUG_BIND_CREF
  186. VOID InitDebug( VOID );
  187. #endif
  188. BOOL
  189. DllMain(
  190. HANDLE hModule,
  191. DWORD dwReason,
  192. LPVOID lpRes
  193. )
  194. {
  195. if (dwReason != DLL_PROCESS_ATTACH)
  196. return TRUE;
  197. #ifdef DEBUG_BIND_CREF
  198. InitDebug();
  199. #endif
  200. hInst = hModule;
  201. InitializeCriticalSection(&SpoolerSection);
  202. DisableThreadLibraryCalls(hModule);
  203. return TRUE;
  204. UNREFERENCED_PARAMETER( lpRes );
  205. }
  206. PWCHAR gpSystemDir = NULL;
  207. PWCHAR gpWin32SplDir = NULL;
  208. BOOL
  209. InitializePrintProvidor(
  210. LPPRINTPROVIDOR pPrintProvidor,
  211. DWORD cbPrintProvidor,
  212. LPWSTR pFullRegistryPath
  213. )
  214. {
  215. DWORD i;
  216. WCHAR SystemDir[MAX_PATH];
  217. DWORD ReturnValue = TRUE;
  218. UINT Index;
  219. OSVERSIONINFO OSVersionInfo;
  220. SYSTEM_INFO SystemInfo;
  221. if (!pFullRegistryPath || !*pFullRegistryPath) {
  222. SetLastError(ERROR_INVALID_PARAMETER);
  223. return FALSE;
  224. }
  225. // DbgInit();
  226. if ( !GetPrintSystemVersion() ) {
  227. DBGMSG( DBG_WARNING, ("GetPrintSystemVersion ERROR %d\n", GetLastError() ));
  228. return FALSE;
  229. }
  230. if (!(szRegistryPath = AllocSplStr(pFullRegistryPath)))
  231. return FALSE;
  232. szPrintProvidorName[0] = L'\0';
  233. szPrintProvidorDescription[0] = L'\0';
  234. szPrintProvidorComment[0] = L'\0';
  235. if (!LoadString(hInst, IDS_WINDOWS_NT_REMOTE_PRINTERS,
  236. szPrintProvidorName,
  237. sizeof(szPrintProvidorName) / sizeof(*szPrintProvidorName)))
  238. return FALSE;
  239. if (!LoadString(hInst, IDS_MICROSOFT_WINDOWS_NETWORK,
  240. szPrintProvidorDescription,
  241. sizeof(szPrintProvidorDescription) / sizeof(*szPrintProvidorDescription)))
  242. return FALSE;
  243. if (!LoadString(hInst, IDS_REMOTE_PRINTERS,
  244. szPrintProvidorComment,
  245. sizeof(szPrintProvidorComment) / sizeof(*szPrintProvidorComment)))
  246. return FALSE;
  247. if ((hNetApi = LoadLibrary(L"netapi32.dll"))) {
  248. pfnNetServerEnum = (NET_API_STATUS (*)())GetProcAddress(hNetApi, "NetServerEnum");
  249. pfnNetShareEnum = (NET_API_STATUS (*)())GetProcAddress(hNetApi, "NetShareEnum");
  250. pfnNetWkstaUserGetInfo = (NET_API_STATUS (*)())GetProcAddress(hNetApi, "NetWkstaUserGetInfo");
  251. pfnNetWkstaGetInfo = (NET_API_STATUS (*)())GetProcAddress(hNetApi, "NetWkstaGetInfo");
  252. pfnNetApiBufferFree = (NET_API_STATUS (*)())GetProcAddress(hNetApi, "NetApiBufferFree");
  253. pfnNetServerGetInfo = (NET_API_STATUS (*)())GetProcAddress(hNetApi, "NetServerGetInfo");
  254. if ( pfnNetServerEnum == NULL ||
  255. pfnNetShareEnum == NULL ||
  256. pfnNetWkstaUserGetInfo == NULL ||
  257. pfnNetWkstaGetInfo == NULL ||
  258. pfnNetApiBufferFree == NULL ||
  259. pfnNetServerGetInfo == NULL ) {
  260. DBGMSG( DBG_WARNING, ("Failed GetProcAddres on Net Api's %d\n", GetLastError() ));
  261. return FALSE;
  262. }
  263. } else {
  264. DBGMSG(DBG_WARNING,
  265. ("Failed LoadLibrary( netapi32.dll ) %d\n", GetLastError() ));
  266. return FALSE;
  267. }
  268. if (!BoolFromHResult(AreWeOnADomain(&gbMachineInDomain))) {
  269. DBGMSG(DBG_WARNING, ("Failed to determine if we are on a domain (%d).\n", GetLastError()));
  270. return FALSE;
  271. }
  272. memcpy(pPrintProvidor, &PrintProvidor, min(sizeof(PRINTPROVIDOR),
  273. cbPrintProvidor));
  274. QueryTrustedDriverInformation();
  275. szMachineName[0] = szMachineName[1] = L'\\';
  276. i = MAX_COMPUTERNAME_LENGTH + 1;
  277. gdwThisGetVersion = GetVersion();
  278. GetSystemInfo(&SystemInfo);
  279. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
  280. if (!GetComputerName(szMachineName+2, &i) ||
  281. !GetVersionEx(&OSVersionInfo) ||
  282. !(gSplClientInfo1.pMachineName = AllocSplStr(szMachineName)) )
  283. return FALSE;
  284. BuildOtherNamesFromMachineName(&gppszOtherNames, &gcOtherNames);
  285. gSplClientInfo1.dwSize = sizeof(gSplClientInfo1);
  286. gSplClientInfo1.dwBuildNum = OSVersionInfo.dwBuildNumber;
  287. gSplClientInfo1.dwMajorVersion = cThisMajorVersion;
  288. gSplClientInfo1.dwMinorVersion = cThisMinorVersion;
  289. gSplClientInfo1.pUserName = NULL;
  290. gSplClientInfo1.wProcessorArchitecture = SystemInfo.wProcessorArchitecture;
  291. if ( InitializePortNames() != NO_ERROR )
  292. return FALSE;
  293. Index = GetSystemDirectory(SystemDir, COUNTOF(SystemDir));
  294. if ( Index == 0 ) {
  295. return FALSE;
  296. }
  297. gpSystemDir = AllocSplStr( SystemDir );
  298. if ( gpSystemDir == NULL ) {
  299. return FALSE;
  300. }
  301. wcscpy( &SystemDir[Index], szWin32SplDirectory );
  302. gpWin32SplDir = AllocSplStr( SystemDir );
  303. if ( gpWin32SplDir == NULL ) {
  304. return FALSE;
  305. }
  306. return TRUE;
  307. }
  308. DWORD
  309. InitializePortNames(
  310. )
  311. {
  312. LONG Status;
  313. HKEY hkeyPath;
  314. HKEY hkeyPortNames;
  315. WCHAR Buffer[MAX_PATH];
  316. DWORD cchBuffer;
  317. DWORD i;
  318. DWORD dwReturnValue;
  319. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szRegistryPath, 0,
  320. KEY_READ, &hkeyPath );
  321. dwReturnValue = Status;
  322. if( Status == NO_ERROR ) {
  323. Status = RegOpenKeyEx( hkeyPath, szRegistryPortNames, 0,
  324. KEY_READ, &hkeyPortNames );
  325. if( Status == NO_ERROR ) {
  326. i = 0;
  327. while( Status == NO_ERROR ) {
  328. cchBuffer = COUNTOF( Buffer );
  329. Status = RegEnumValue( hkeyPortNames, i, Buffer, &cchBuffer,
  330. NULL, NULL, NULL, NULL );
  331. if( Status == NO_ERROR )
  332. CreatePortEntry( Buffer, &pIniFirstPort );
  333. i++;
  334. }
  335. /* We expect RegEnumKeyEx to return ERROR_NO_MORE_ITEMS
  336. * when it gets to the end of the keys, so reset the status:
  337. */
  338. if( Status == ERROR_NO_MORE_ITEMS )
  339. Status = NO_ERROR;
  340. RegCloseKey( hkeyPortNames );
  341. } else {
  342. DBGMSG( DBG_INFO, ( "RegOpenKeyEx (%ws) failed: Error = %d\n",
  343. szRegistryPortNames, Status ) );
  344. }
  345. RegCloseKey( hkeyPath );
  346. } else {
  347. DBGMSG( DBG_WARNING, ( "RegOpenKeyEx (%ws) failed: Error = %d\n",
  348. szRegistryPath, Status ) );
  349. }
  350. if ( dwReturnValue != NO_ERROR ) {
  351. SetLastError( dwReturnValue );
  352. }
  353. return dwReturnValue;
  354. }
  355. BOOL
  356. EnumerateFavouritePrinters(
  357. LPWSTR pDomain,
  358. DWORD Level,
  359. DWORD cbStruct,
  360. LPDWORD pOffsets,
  361. LPBYTE pPrinter,
  362. DWORD cbBuf,
  363. LPDWORD pcbNeeded,
  364. LPDWORD pcReturned
  365. )
  366. {
  367. HKEY hClientKey = NULL;
  368. HKEY hKey1=NULL;
  369. DWORD cPrinters, cbData;
  370. WCHAR PrinterName[ MAX_UNC_PRINTER_NAME ];
  371. DWORD cReturned, TotalcbNeeded, cbNeeded, cTotalReturned;
  372. DWORD Error=0;
  373. DWORD BufferSize=cbBuf;
  374. HANDLE hPrinter;
  375. DWORD Status;
  376. WCHAR szBuffer[MAX_PATH];
  377. HKEY hPrinterConnectionsKey;
  378. DBGMSG( DBG_TRACE, ("EnumerateFavouritePrinters called\n"));
  379. *pcbNeeded = 0;
  380. *pcReturned = 0;
  381. hClientKey = GetClientUserHandle(KEY_READ);
  382. if ( hClientKey == NULL ) {
  383. DBGMSG( DBG_WARNING, ("EnumerateFavouritePrinters GetClientUserHandle failed error %d\n", GetLastError() ));
  384. return FALSE;
  385. }
  386. Status = RegOpenKeyEx(hClientKey, szRegistryConnections, 0,
  387. KEY_READ, &hKey1);
  388. if ( Status != ERROR_SUCCESS ) {
  389. RegCloseKey(hClientKey);
  390. SetLastError( Status );
  391. DBGMSG( DBG_WARNING, ("EnumerateFavouritePrinters RegOpenKeyEx failed error %d\n", GetLastError() ));
  392. return FALSE;
  393. }
  394. cReturned = cbNeeded = TotalcbNeeded = cTotalReturned = 0;
  395. for( cPrinters = 0;
  396. cbData = COUNTOF( PrinterName ),
  397. RegEnumKeyEx(hKey1,
  398. cPrinters,
  399. PrinterName,
  400. &cbData,
  401. NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
  402. ++cPrinters ){
  403. //
  404. // Check if the key belongs to us.
  405. //
  406. Status = RegOpenKeyEx( hKey1,
  407. PrinterName,
  408. 0,
  409. KEY_READ,
  410. &hPrinterConnectionsKey );
  411. if( Status != ERROR_SUCCESS ){
  412. continue;
  413. }
  414. cbData = sizeof(szBuffer);
  415. //
  416. // If there is a Provider value, and it doesn't match win32spl.dll,
  417. // then fail the call.
  418. //
  419. // If the provider value isn't there, succeed for backward
  420. // compatibility.
  421. //
  422. Status = RegQueryValueEx( hPrinterConnectionsKey,
  423. L"Provider",
  424. NULL,
  425. NULL,
  426. (LPBYTE)szBuffer,
  427. &cbData );
  428. RegCloseKey( hPrinterConnectionsKey );
  429. //
  430. // If the key exists but we failed to read it, or the
  431. // provider entry is incorrect, then don't enumerate it back.
  432. //
  433. // For backward compatibility, if the key doesn't exist,
  434. // we assume it belongs to win32spl.dll.
  435. //
  436. if( Status != ERROR_SUCCESS ){
  437. if( Status != ERROR_FILE_NOT_FOUND ){
  438. continue;
  439. }
  440. } else {
  441. if( _wcsicmp( szBuffer, L"win32spl.dll" )){
  442. continue;
  443. }
  444. }
  445. FormatRegistryKeyForPrinter(PrinterName, PrinterName);
  446. // Do not fail if any of these calls fails, because we want
  447. // to return whatever we can find.
  448. if (MyUNCName(PrinterName)) // Roaming profiles can create connections to local printers
  449. continue;
  450. if (CacheOpenPrinter(PrinterName, &hPrinter, NULL)) {
  451. if (CacheGetPrinter(hPrinter, Level, pPrinter, BufferSize, &cbNeeded)) {
  452. if (Level == 2) {
  453. ((PPRINTER_INFO_2)pPrinter)->Attributes |= PRINTER_ATTRIBUTE_NETWORK;
  454. ((PPRINTER_INFO_2)pPrinter)->Attributes &= ~PRINTER_ATTRIBUTE_LOCAL;
  455. }
  456. else if (Level == 5) {
  457. ((PPRINTER_INFO_5)pPrinter)->Attributes |= PRINTER_ATTRIBUTE_NETWORK;
  458. ((PPRINTER_INFO_5)pPrinter)->Attributes &= ~PRINTER_ATTRIBUTE_LOCAL;
  459. }
  460. cTotalReturned++;
  461. pPrinter += cbStruct;
  462. if (cbNeeded <= BufferSize)
  463. BufferSize -= cbNeeded;
  464. TotalcbNeeded += cbNeeded;
  465. } else {
  466. DWORD Error;
  467. if ((Error = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) {
  468. if (cbNeeded <= BufferSize)
  469. BufferSize -= cbNeeded;
  470. TotalcbNeeded += cbNeeded;
  471. } else {
  472. DBGMSG( DBG_WARNING, ( "GetPrinter( %ws ) failed: Error %d\n",
  473. PrinterName, Error ) );
  474. }
  475. }
  476. CacheClosePrinter(hPrinter);
  477. } else {
  478. DBGMSG( DBG_WARNING, ( "CacheOpenPrinter( %ws ) failed: Error %d\n",
  479. PrinterName, GetLastError( ) ) );
  480. }
  481. }
  482. RegCloseKey(hKey1);
  483. if (hClientKey) {
  484. RegCloseKey(hClientKey);
  485. }
  486. *pcbNeeded = TotalcbNeeded;
  487. *pcReturned = cTotalReturned;
  488. if (TotalcbNeeded > cbBuf) {
  489. DBGMSG( DBG_TRACE, ("EnumerateFavouritePrinters returns ERROR_INSUFFICIENT_BUFFER\n"));
  490. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  491. return FALSE;
  492. }
  493. return TRUE;
  494. }
  495. DWORD
  496. RpcValidate(
  497. VOID
  498. )
  499. /*++
  500. Routine Description:
  501. Validates that the call came from local machine. We do not want this function
  502. to call IsLocalCall in spoolss. IsLocalCall does a CheckTokenMembership to
  503. look at the network sid. This breaks scenarios like the following:
  504. W2k client prints to W2k server. The port monitor is Intel Network.
  505. Port Monitor. The start doc call originating from the client (thread token
  506. has the network bit set) will try to do OpenPrinter on the port name:
  507. \\intel-box\port in the spooler on the server. The call gets routed
  508. to win32spl. The line below will allow the call to get through.
  509. Arguments:
  510. None.
  511. Return Value:
  512. ERROR_SUCCESS - Call was local and we should RPC out.
  513. ERROR_INVALID_PARAMETER - Call was not local and shouldn't RPC out
  514. since we may get into an infinite loop.
  515. --*/
  516. {
  517. return IsNamedPipeRpcCall() ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS;
  518. }
  519. #define SIZEOFPARAM1 1
  520. #define SIZEOFPARAM2 3
  521. #define SIZEOFASCIIZ 1
  522. #define SAFECOUNT (SIZEOFPARAM1 + SIZEOFPARAM2 + SIZEOFASCIIZ)
  523. BOOL
  524. EnumerateDomainPrinters(
  525. LPWSTR pDomain,
  526. DWORD Level,
  527. DWORD cbStruct,
  528. LPDWORD pOffsets,
  529. LPBYTE pPrinter,
  530. DWORD cbBuf,
  531. LPDWORD pcbNeeded,
  532. LPDWORD pcReturned
  533. )
  534. {
  535. DWORD i, j, NoReturned, Total, OuterLoopCount;
  536. DWORD rc = 0;
  537. PSERVER_INFO_101 pserver_info_101;
  538. DWORD ReturnValue=FALSE;
  539. WCHAR string[3*MAX_PATH];
  540. PPRINTER_INFO_1 pPrinterInfo1;
  541. DWORD cb=cbBuf;
  542. LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
  543. LPBYTE pEnd;
  544. DWORD ServerType;
  545. BOOL bServerFound = FALSE, bMarshall;
  546. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters called\n"));
  547. string[0] = string[1] = '\\';
  548. *pcbNeeded = *pcReturned = 0;
  549. if (!(*pfnNetServerEnum)(NULL, 101, (LPBYTE *)&pserver_info_101, -1,
  550. &NoReturned, &Total,
  551. SV_TYPE_PRINTQ_SERVER | SV_TYPE_WFW,
  552. pDomain, NULL)) {
  553. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters NetServerEnum returned %d\n", NoReturned));
  554. //
  555. // First Look try NT Servers, then if that Fails Look at the WorkStations
  556. //
  557. for ( ServerType = ( SV_TYPE_SERVER_NT | SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL ), OuterLoopCount = 0;
  558. bServerFound == FALSE && OuterLoopCount < 2;
  559. ServerType = SV_TYPE_NT, OuterLoopCount++ ) {
  560. //
  561. // Loop Through looking for a print server that will return a good browse list
  562. //
  563. for ( i = 0; i < NoReturned; i++ ) {
  564. if ( pserver_info_101[i].sv101_type & ServerType ) {
  565. wcscpy( &string[2], pserver_info_101[i].sv101_name );
  566. RpcTryExcept {
  567. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters Trying %ws ENUM_NETWORK type %x\n", string, ServerType ));
  568. if ( !(rc = RpcValidate()) &&
  569. !(rc = RpcEnumPrinters(PRINTER_ENUM_NETWORK,
  570. string,
  571. 1, pPrinter,
  572. cbBuf, pcbNeeded,
  573. pcReturned) ,
  574. rc = UpdateBufferSize(PrinterInfo1Fields,
  575. sizeof(PRINTER_INFO_1),
  576. pcbNeeded,
  577. cbBuf,
  578. rc,
  579. pcReturned)) ) {
  580. if ( bMarshall = MarshallUpStructuresArray(pPrinter, *pcReturned, PrinterInfo1Fields,
  581. sizeof(PRINTER_INFO_1), RPC_CALL)) {
  582. //
  583. // pPrinter must point after lats structure in array.
  584. // More structures needs to be added by the other providers.
  585. //
  586. pPrinter += (*pcReturned) * cbStruct;
  587. }
  588. if (!bMarshall) {
  589. bServerFound = TRUE;
  590. break;
  591. }
  592. //
  593. // Only return success if we found some data.
  594. //
  595. if ( *pcReturned != 0 ) {
  596. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters %ws ENUM_NETWORK Success %d returned\n", string, *pcReturned ));
  597. bServerFound = TRUE;
  598. break;
  599. }
  600. } else if (rc == ERROR_INSUFFICIENT_BUFFER) {
  601. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters %ws ENUM_NETWORK ERROR_INSUFFICIENT_BUFFER\n", string ));
  602. bServerFound = TRUE;
  603. break;
  604. }
  605. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  606. DBGMSG( DBG_TRACE,( "Failed to connect to Print Server%ws\n",
  607. pserver_info_101[i].sv101_name ) );
  608. } RpcEndExcept
  609. } else {
  610. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters %ws type %x not type %x\n", pserver_info_101[i].sv101_name, pserver_info_101[i].sv101_type, ServerType));
  611. }
  612. }
  613. }
  614. pPrinterInfo1 = (PPRINTER_INFO_1)pPrinter;
  615. pEnd = (LPBYTE)pPrinterInfo1 + cb - *pcbNeeded;
  616. for ( i = 0; i < NoReturned; i++ ) {
  617. wcscpy( string, szPrintProvidorName );
  618. wcscat( string, L"!" ); //SIZEOFPARAM1
  619. if ( pDomain )
  620. wcsncat(string,pDomain,sizeof(string)/sizeof(WCHAR)-wcslen(pserver_info_101[i].sv101_name)-SAFECOUNT);
  621. wcscat( string, L"!\\\\" ); //SIZEOFPARAM2
  622. wcscat( string, pserver_info_101[i].sv101_name );
  623. cb = wcslen(pserver_info_101[i].sv101_name)*sizeof(WCHAR) + sizeof(WCHAR) +
  624. wcslen(string)*sizeof(WCHAR) + sizeof(WCHAR) +
  625. wcslen(szLoggedOnDomain)*sizeof(WCHAR) + sizeof(WCHAR) +
  626. sizeof(PRINTER_INFO_1);
  627. (*pcbNeeded) += cb;
  628. if ( cbBuf >= *pcbNeeded ) {
  629. (*pcReturned)++;
  630. pPrinterInfo1->Flags = PRINTER_ENUM_CONTAINER | PRINTER_ENUM_ICON3;
  631. SourceStrings[0] = pserver_info_101[i].sv101_name;
  632. SourceStrings[1] = string;
  633. SourceStrings[2] = szLoggedOnDomain;
  634. pEnd = PackStrings( SourceStrings, (LPBYTE)pPrinterInfo1,
  635. PrinterInfo1Strings, pEnd );
  636. pPrinterInfo1++;
  637. }
  638. }
  639. (*pfnNetApiBufferFree)((LPVOID)pserver_info_101);
  640. if ( cbBuf < *pcbNeeded ) {
  641. DBGMSG( DBG_TRACE, ("EnumerateDomainPrinters returns ERROR_INSUFFICIENT_BUFFER\n"));
  642. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  643. return FALSE;
  644. }
  645. }
  646. return TRUE;
  647. }
  648. BOOL
  649. EnumerateDomains(
  650. PRINTER_INFO_1 *pPrinter,
  651. DWORD cbBuf,
  652. LPDWORD pcbNeeded,
  653. LPDWORD pcReturned,
  654. LPBYTE pEnd
  655. )
  656. {
  657. DWORD i, NoReturned, Total;
  658. DWORD cb;
  659. SERVER_INFO_100 *pNames;
  660. PWKSTA_INFO_100 pWkstaInfo = NULL;
  661. LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
  662. WCHAR string[3*MAX_PATH];
  663. DBGMSG( DBG_TRACE, ("EnumerateDomains pPrinter %x cbBuf %d pcbNeeded %x pcReturned %x pEnd %x\n",
  664. pPrinter, cbBuf, pcbNeeded, pcReturned, pEnd ));
  665. *pcReturned = 0;
  666. *pcbNeeded = 0;
  667. if (!(*pfnNetServerEnum)(NULL, 100, (LPBYTE *)&pNames, -1,
  668. &NoReturned, &Total, SV_TYPE_DOMAIN_ENUM,
  669. NULL, NULL)) {
  670. DBGMSG( DBG_TRACE, ("EnumerateDomains - NetServerEnum returned %d\n", NoReturned));
  671. (*pfnNetWkstaGetInfo)(NULL, 100, (LPBYTE *)&pWkstaInfo);
  672. DBGMSG( DBG_TRACE, ("EnumerateDomains - NetWkstaGetInfo returned pWkstaInfo %x\n", pWkstaInfo));
  673. for (i=0; i<NoReturned; i++) {
  674. wcscpy(string, szPrintProvidorName);
  675. wcscat(string, L"!");
  676. wcscat(string, pNames[i].sv100_name);
  677. cb = wcslen(pNames[i].sv100_name)*sizeof(WCHAR) + sizeof(WCHAR) +
  678. wcslen(string)*sizeof(WCHAR) + sizeof(WCHAR) +
  679. wcslen(szLoggedOnDomain)*sizeof(WCHAR) + sizeof(WCHAR) +
  680. sizeof(PRINTER_INFO_1);
  681. (*pcbNeeded)+=cb;
  682. if (cbBuf >= *pcbNeeded) {
  683. (*pcReturned)++;
  684. pPrinter->Flags = PRINTER_ENUM_CONTAINER | PRINTER_ENUM_ICON2;
  685. /* Set the PRINTER_ENUM_EXPAND flag for the user's logon domain
  686. */
  687. if (!lstrcmpi(pNames[i].sv100_name,
  688. pWkstaInfo->wki100_langroup))
  689. pPrinter->Flags |= PRINTER_ENUM_EXPAND;
  690. SourceStrings[0]=pNames[i].sv100_name;
  691. SourceStrings[1]=string;
  692. SourceStrings[2]=szLoggedOnDomain;
  693. pEnd = PackStrings(SourceStrings, (LPBYTE)pPrinter,
  694. PrinterInfo1Strings, pEnd);
  695. pPrinter++;
  696. }
  697. }
  698. (*pfnNetApiBufferFree)((LPVOID)pNames);
  699. (*pfnNetApiBufferFree)((LPVOID)pWkstaInfo);
  700. if (cbBuf < *pcbNeeded) {
  701. DBGMSG( DBG_TRACE, ("EnumerateDomains returns ERROR_INSUFFICIENT_BUFFER\n"));
  702. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  703. return FALSE;
  704. }
  705. return TRUE;
  706. }
  707. return TRUE;
  708. }
  709. BOOL
  710. EnumeratePrintShares(
  711. LPWSTR pDomain,
  712. LPWSTR pServer,
  713. DWORD Level,
  714. DWORD cbStruct,
  715. LPDWORD pOffsets,
  716. LPBYTE pPrinter,
  717. DWORD cbBuf,
  718. LPDWORD pcbNeeded,
  719. LPDWORD pcReturned
  720. )
  721. {
  722. DWORD i, NoReturned, Total;
  723. DWORD cb;
  724. SHARE_INFO_1 *pNames;
  725. LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
  726. WCHAR string[MAX_UNC_PRINTER_NAME] = {0};
  727. PRINTER_INFO_1 *pPrinterInfo1 = (PRINTER_INFO_1 *)pPrinter;
  728. LPBYTE pEnd=pPrinter+cbBuf;
  729. WCHAR FullName[MAX_UNC_PRINTER_NAME] = {0};
  730. DBGMSG( DBG_TRACE, ("EnumeratePrintShares\n"));
  731. *pcReturned = 0;
  732. *pcbNeeded = 0;
  733. if (!(*pfnNetShareEnum)(pServer, 1, (LPBYTE *)&pNames, -1,
  734. &NoReturned, &Total, NULL)) {
  735. DBGMSG( DBG_TRACE, ("EnumeratePrintShares NetShareEnum returned %d\n", NoReturned));
  736. for (i=0; i<NoReturned; i++) {
  737. if (pNames[i].shi1_type == STYPE_PRINTQ) {
  738. DWORD dwRet;
  739. if(((dwRet = StrNCatBuff(string ,
  740. MAX_UNC_PRINTER_NAME,
  741. pNames[i].shi1_netname,
  742. L",",
  743. pNames[i].shi1_remark,
  744. NULL
  745. )) != ERROR_SUCCESS) ||
  746. ((dwRet = StrNCatBuff(FullName,
  747. MAX_UNC_PRINTER_NAME,
  748. pServer,
  749. L"\\",
  750. pNames[i].shi1_netname,
  751. NULL
  752. )) != ERROR_SUCCESS))
  753. {
  754. SetLastError(dwRet);
  755. return(FALSE);
  756. }
  757. cb = wcslen(FullName)*sizeof(WCHAR) + sizeof(WCHAR) +
  758. wcslen(string)*sizeof(WCHAR) + sizeof(WCHAR) +
  759. wcslen(szLoggedOnDomain)*sizeof(WCHAR) + sizeof(WCHAR) +
  760. sizeof(PRINTER_INFO_1);
  761. (*pcbNeeded)+=cb;
  762. if (cbBuf >= *pcbNeeded) {
  763. (*pcReturned)++;
  764. pPrinterInfo1->Flags = PRINTER_ENUM_ICON8;
  765. SourceStrings[0]=string;
  766. SourceStrings[1]=FullName;
  767. SourceStrings[2]=szLoggedOnDomain;
  768. pEnd = PackStrings(SourceStrings, (LPBYTE)pPrinterInfo1,
  769. PrinterInfo1Strings, pEnd);
  770. pPrinterInfo1++;
  771. }
  772. }
  773. }
  774. (*pfnNetApiBufferFree)((LPVOID)pNames);
  775. if ( cbBuf < *pcbNeeded ) {
  776. DBGMSG( DBG_TRACE, ("EnumeratePrintShares returns ERROR_INSUFFICIENT_BUFFER\n"));
  777. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  778. return FALSE;
  779. }
  780. return TRUE;
  781. }
  782. return TRUE;
  783. }
  784. BOOL
  785. EnumPrinters(
  786. DWORD Flags,
  787. LPWSTR Name,
  788. DWORD Level,
  789. LPBYTE pPrinter,
  790. DWORD cbBuf,
  791. LPDWORD pcbNeeded,
  792. LPDWORD pcReturned
  793. )
  794. {
  795. BOOL ReturnValue = FALSE;
  796. DWORD cbStruct, cb;
  797. DWORD *pOffsets;
  798. FieldInfo *pFieldInfo;
  799. DWORD NoReturned=0, i, rc;
  800. LPBYTE pKeepPrinter = pPrinter;
  801. BOOL OutOfMemory = FALSE;
  802. PPRINTER_INFO_1 pPrinter1=(PPRINTER_INFO_1)pPrinter;
  803. PWSTR pszFullName = NULL;
  804. WCHAR *pDomain, *pServer;
  805. DBGMSG( DBG_TRACE, ("EnumPrinters Flags %x pName %x Level %d pPrinter %x cbBuf %d pcbNeeded %x pcReturned %x\n",
  806. Flags, Name, Level, pPrinter, cbBuf, pcbNeeded, pcReturned ));
  807. *pcReturned = 0;
  808. *pcbNeeded = 0;
  809. switch (Level) {
  810. case STRESSINFOLEVEL:
  811. pOffsets = PrinterInfoStressOffsets;
  812. pFieldInfo = PrinterInfoStressFields;
  813. cbStruct = sizeof(PRINTER_INFO_STRESS);
  814. break;
  815. case 1:
  816. pOffsets = PrinterInfo1Offsets;
  817. pFieldInfo = PrinterInfo1Fields;
  818. cbStruct = sizeof(PRINTER_INFO_1);
  819. break;
  820. case 2:
  821. pOffsets = PrinterInfo2Offsets;
  822. pFieldInfo = PrinterInfo2Fields;
  823. cbStruct = sizeof(PRINTER_INFO_2);
  824. break;
  825. case 4:
  826. //
  827. // There are no local printers in win32spl, and connections
  828. // are handled by the router.
  829. //
  830. return TRUE;
  831. case 5:
  832. pOffsets = PrinterInfo5Offsets;
  833. pFieldInfo = PrinterInfo5Fields;
  834. cbStruct = sizeof(PRINTER_INFO_5);
  835. break;
  836. default:
  837. SetLastError( ERROR_INVALID_LEVEL );
  838. DBGMSG( DBG_TRACE, ("EnumPrinters failed ERROR_INVALID_LEVEL\n"));
  839. return FALSE;
  840. }
  841. if ( Flags & PRINTER_ENUM_NAME ) {
  842. if (!Name && (Level == 1)) {
  843. LPWSTR SourceStrings[sizeof(PRINTER_INFO_1)/sizeof(LPWSTR)];
  844. LPWSTR *pSourceStrings=SourceStrings;
  845. cb = wcslen(szPrintProvidorName)*sizeof(WCHAR) + sizeof(WCHAR) +
  846. wcslen(szPrintProvidorDescription)*sizeof(WCHAR) + sizeof(WCHAR) +
  847. wcslen(szPrintProvidorComment)*sizeof(WCHAR) + sizeof(WCHAR) +
  848. sizeof(PRINTER_INFO_1);
  849. *pcbNeeded=cb;
  850. if ( cb > cbBuf ) {
  851. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  852. DBGMSG( DBG_TRACE, ("EnumPrinters returns ERROR_INSUFFICIENT_BUFFER\n"));
  853. return FALSE;
  854. }
  855. *pcReturned = 1;
  856. pPrinter1->Flags = PRINTER_ENUM_CONTAINER |
  857. PRINTER_ENUM_ICON1 |
  858. PRINTER_ENUM_EXPAND;
  859. *pSourceStrings++=szPrintProvidorDescription;
  860. *pSourceStrings++=szPrintProvidorName;
  861. *pSourceStrings++=szPrintProvidorComment;
  862. PackStrings( SourceStrings, pPrinter, PrinterInfo1Strings,
  863. pPrinter+cbBuf );
  864. DBGMSG( DBG_TRACE, ("EnumPrinters returns Success just Provider Info\n"));
  865. return TRUE;
  866. }
  867. if (Name && *Name && (Level == 1)) {
  868. if (!(pszFullName = AllocSplStr(Name)))
  869. return FALSE;
  870. pServer = NULL;
  871. pDomain = wcschr(pszFullName, L'!');
  872. if (pDomain) {
  873. *pDomain++ = 0;
  874. pServer = wcschr(pDomain, L'!');
  875. if (pServer)
  876. *pServer++ = 0;
  877. }
  878. if (!lstrcmpi(pszFullName, szPrintProvidorName)) {
  879. ReturnValue = !pServer ? !pDomain ? EnumerateDomains((PRINTER_INFO_1 *)pPrinter,
  880. cbBuf, pcbNeeded,
  881. pcReturned, pPrinter+cbBuf)
  882. : EnumerateDomainPrinters(pDomain,
  883. Level, cbStruct,
  884. pOffsets, pPrinter, cbBuf,
  885. pcbNeeded, pcReturned)
  886. : EnumeratePrintShares(pDomain, pServer, Level,
  887. cbStruct, pOffsets, pPrinter,
  888. cbBuf, pcbNeeded, pcReturned);
  889. FreeSplMem(pszFullName);
  890. return(ReturnValue);
  891. }
  892. FreeSplMem(pszFullName);
  893. }
  894. if ( !VALIDATE_NAME(Name) || MyUNCName(Name)) {
  895. SetLastError(ERROR_INVALID_NAME);
  896. return FALSE;
  897. }
  898. if (pPrinter)
  899. memset(pPrinter, 0, cbBuf);
  900. RpcTryExcept {
  901. if ( (rc = RpcValidate()) ||
  902. (rc = RpcEnumPrinters(Flags,
  903. Name,
  904. Level, pPrinter,
  905. cbBuf, pcbNeeded,
  906. pcReturned),
  907. rc = UpdateBufferSize(pFieldInfo,
  908. cbStruct,
  909. pcbNeeded,
  910. cbBuf,
  911. rc,
  912. pcReturned)) ) {
  913. SetLastError(rc);
  914. // ReturnValue = FALSE;
  915. return FALSE;
  916. } else {
  917. ReturnValue = TRUE;
  918. }
  919. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  920. DBGMSG( DBG_TRACE, ( "Failed to connect to Print Server%ws\n", Name ) );
  921. *pcbNeeded = 0;
  922. *pcReturned = 0;
  923. SetLastError(RpcExceptionCode());
  924. // ReturnValue = FALSE;
  925. return FALSE;
  926. } RpcEndExcept
  927. if(! MarshallUpStructuresArray(pPrinter, *pcReturned, pFieldInfo, cbStruct, RPC_CALL) ) {
  928. return FALSE;
  929. }
  930. i = *pcReturned;
  931. while (i--) {
  932. if (Level == 2) {
  933. ((PPRINTER_INFO_2)pPrinter)->Attributes |=
  934. PRINTER_ATTRIBUTE_NETWORK;
  935. ((PPRINTER_INFO_2)pPrinter)->Attributes &=
  936. ~PRINTER_ATTRIBUTE_LOCAL;
  937. }
  938. if (Level == 5) {
  939. ((PPRINTER_INFO_5)pPrinter)->Attributes |=
  940. PRINTER_ATTRIBUTE_NETWORK;
  941. ((PPRINTER_INFO_5)pPrinter)->Attributes &=
  942. ~PRINTER_ATTRIBUTE_LOCAL;
  943. }
  944. pPrinter += cbStruct;
  945. }
  946. } else if (Flags & PRINTER_ENUM_REMOTE) {
  947. if (Level != 1) {
  948. SetLastError(ERROR_INVALID_LEVEL);
  949. ReturnValue = FALSE;
  950. } else {
  951. ReturnValue = EnumerateDomainPrinters(NULL, Level,
  952. cbStruct, pOffsets,
  953. pPrinter, cbBuf,
  954. pcbNeeded, pcReturned);
  955. }
  956. } else if (Flags & PRINTER_ENUM_CONNECTIONS) {
  957. ReturnValue = EnumerateFavouritePrinters(NULL, Level,
  958. cbStruct, pOffsets,
  959. pPrinter, cbBuf,
  960. pcbNeeded, pcReturned);
  961. }
  962. return ReturnValue;
  963. }
  964. BOOL
  965. RemoteOpenPrinter(
  966. LPWSTR pPrinterName,
  967. LPHANDLE phPrinter,
  968. LPPRINTER_DEFAULTS pDefault,
  969. BOOL CallLMOpenPrinter
  970. )
  971. {
  972. DWORD RpcReturnValue;
  973. BOOL ReturnValue = FALSE;
  974. DEVMODE_CONTAINER DevModeContainer;
  975. SPLCLIENT_CONTAINER SplClientContainer;
  976. SPLCLIENT_INFO_1 SplClientInfo;
  977. HANDLE hPrinter;
  978. PWSPOOL pSpool;
  979. DWORD Status = 0;
  980. DWORD RpcError = 0;
  981. DWORD dwIndex;
  982. WCHAR UserName[MAX_PATH+1];
  983. HANDLE hSplPrinter, hIniSpooler, hDevModeChgInfo;
  984. if ( !VALIDATE_NAME(pPrinterName) ||
  985. MyUNCName(pPrinterName) ) {
  986. SetLastError(ERROR_INVALID_NAME);
  987. return FALSE;
  988. }
  989. // enable named pipe timeouts
  990. if (bRpcPipeCleanup == FALSE) {
  991. EnterSplSem();
  992. if (bRpcPipeCleanup == FALSE) {
  993. bRpcPipeCleanup = TRUE;
  994. LeaveSplSem();
  995. (VOID)RpcMgmtEnableIdleCleanup();
  996. } else {
  997. LeaveSplSem();
  998. }
  999. }
  1000. if (pDefault && pDefault->pDevMode) {
  1001. DevModeContainer.cbBuf = pDefault->pDevMode->dmSize +
  1002. pDefault->pDevMode->dmDriverExtra;
  1003. DevModeContainer.pDevMode = (LPBYTE)pDefault->pDevMode;
  1004. } else {
  1005. DevModeContainer.cbBuf = 0;
  1006. DevModeContainer.pDevMode = NULL;
  1007. }
  1008. if ( CallLMOpenPrinter ) {
  1009. //
  1010. // Now check if we have an entry in the
  1011. // downlevel cache. We don't want to hit the wire, search the whole net
  1012. // and fail if we know that the printer is LM. if the printer is LM
  1013. // try and succeed
  1014. //
  1015. EnterSplSem();
  1016. dwIndex = FindEntryinWin32LMCache(pPrinterName);
  1017. LeaveSplSem();
  1018. if (dwIndex != -1) {
  1019. ReturnValue = LMOpenPrinter(pPrinterName, phPrinter, pDefault);
  1020. if (ReturnValue) {
  1021. return TRUE ;
  1022. }
  1023. //
  1024. // Delete Entry in Cache
  1025. EnterSplSem();
  1026. DeleteEntryfromWin32LMCache(pPrinterName);
  1027. LeaveSplSem();
  1028. }
  1029. }
  1030. CopyMemory((LPBYTE)&SplClientInfo,
  1031. (LPBYTE)&gSplClientInfo1,
  1032. sizeof(SplClientInfo));
  1033. dwIndex = sizeof(UserName)/sizeof(UserName[0]) - 1;
  1034. if ( !GetUserName(UserName, &dwIndex) ) {
  1035. goto Cleanup;
  1036. }
  1037. SplClientInfo.pUserName = UserName;
  1038. SplClientContainer.ClientInfo.pClientInfo1 = &SplClientInfo;
  1039. SplClientContainer.Level = 1;
  1040. RpcTryExcept {
  1041. EnterSplSem();
  1042. pSpool = AllocWSpool();
  1043. LeaveSplSem();
  1044. if ( pSpool != NULL ) {
  1045. pSpool->pName = AllocSplStr( pPrinterName );
  1046. if ( pSpool->pName != NULL ) {
  1047. pSpool->Status = Status;
  1048. if ( CopypDefaultTopSpool( pSpool, pDefault ) ) {
  1049. RpcReturnValue = RpcValidate();
  1050. if ( RpcReturnValue == ERROR_SUCCESS )
  1051. RpcReturnValue = RpcOpenPrinterEx(
  1052. pPrinterName,
  1053. &hPrinter,
  1054. pDefault ? pDefault->pDatatype
  1055. : NULL,
  1056. &DevModeContainer,
  1057. pDefault ? pDefault->DesiredAccess
  1058. : 0,
  1059. &SplClientContainer);
  1060. if (RpcReturnValue) {
  1061. SetLastError(RpcReturnValue);
  1062. } else {
  1063. pSpool->RpcHandle = hPrinter;
  1064. *phPrinter = (HANDLE)pSpool;
  1065. ReturnValue = TRUE;
  1066. }
  1067. }
  1068. }
  1069. }
  1070. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1071. RpcError = RpcExceptionCode();
  1072. } RpcEndExcept;
  1073. if ( RpcError == RPC_S_PROCNUM_OUT_OF_RANGE ) {
  1074. RpcError = 0;
  1075. if ( pDefault && pDefault->pDevMode ) {
  1076. DevModeContainer.cbBuf = 0;
  1077. DevModeContainer.pDevMode = NULL;
  1078. if ( OpenCachePrinterOnly(pPrinterName, &hPrinter, &hIniSpooler, NULL, FALSE) ) {
  1079. hDevModeChgInfo = LoadDriverFiletoConvertDevmodeFromPSpool(hPrinter);
  1080. if ( hDevModeChgInfo ) {
  1081. (VOID)CallDrvDevModeConversion(hDevModeChgInfo,
  1082. pPrinterName,
  1083. (LPBYTE)pDefault->pDevMode,
  1084. &DevModeContainer.pDevMode,
  1085. &DevModeContainer.cbBuf,
  1086. CDM_CONVERT351,
  1087. TRUE);
  1088. UnloadDriverFile(hDevModeChgInfo);
  1089. }
  1090. CacheClosePrinter(hPrinter);
  1091. }
  1092. }
  1093. RpcTryExcept {
  1094. RpcReturnValue = RpcOpenPrinter(pPrinterName,
  1095. &hPrinter,
  1096. pDefault ? pDefault->pDatatype
  1097. : NULL,
  1098. &DevModeContainer,
  1099. pDefault ? pDefault->DesiredAccess
  1100. : 0);
  1101. if (RpcReturnValue) {
  1102. SetLastError(RpcReturnValue);
  1103. } else {
  1104. pSpool->RpcHandle = hPrinter;
  1105. pSpool->bNt3xServer = TRUE;
  1106. *phPrinter = (HANDLE)pSpool;
  1107. ReturnValue = TRUE;
  1108. }
  1109. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1110. RpcError = RpcExceptionCode();
  1111. DBGMSG(DBG_WARNING,("RpcOpenPrinter exception %d\n", RpcError));
  1112. } RpcEndExcept;
  1113. }
  1114. if ( RpcError ) {
  1115. SetLastError(RpcError);
  1116. }
  1117. if ( ReturnValue == FALSE && pSpool != NULL ) {
  1118. EnterSplSem();
  1119. FreepSpool( pSpool );
  1120. LeaveSplSem();
  1121. }
  1122. if ( (RpcError == RPC_S_SERVER_UNAVAILABLE) && CallLMOpenPrinter ) {
  1123. ReturnValue = LMOpenPrinter(pPrinterName, phPrinter, pDefault);
  1124. if (ReturnValue) {
  1125. EnterSplSem();
  1126. AddEntrytoWin32LMCache(pPrinterName);
  1127. LeaveSplSem();
  1128. }
  1129. }
  1130. if ( !ReturnValue ) {
  1131. DBGMSG(DBG_TRACE,
  1132. ("RemoteOpenPrinter %ws failed %d\n",
  1133. pPrinterName, GetLastError() ));
  1134. }
  1135. Cleanup:
  1136. if ( DevModeContainer.pDevMode &&
  1137. DevModeContainer.pDevMode != (LPBYTE)pDefault->pDevMode ) {
  1138. FreeSplMem(DevModeContainer.pDevMode);
  1139. }
  1140. return ReturnValue;
  1141. }
  1142. BOOL PrinterConnectionExists(
  1143. LPWSTR pPrinterName
  1144. )
  1145. {
  1146. HKEY hClientKey = NULL;
  1147. HKEY hKeyConnections = NULL;
  1148. HKEY hKeyPrinter = NULL;
  1149. BOOL ConnectionFound = FALSE;
  1150. DWORD Status;
  1151. if (pPrinterName &&
  1152. (hClientKey = GetClientUserHandle(KEY_READ)))
  1153. {
  1154. if ((Status = RegOpenKeyEx(hClientKey,
  1155. szRegistryConnections,
  1156. 0,
  1157. KEY_READ,
  1158. &hKeyConnections)) == ERROR_SUCCESS)
  1159. {
  1160. LPWSTR pszBuffer = NULL;
  1161. LPWSTR pKeyName = NULL;
  1162. if (pszBuffer = AllocSplMem((wcslen(pPrinterName) + 1) * sizeof(WCHAR)))
  1163. {
  1164. pKeyName = FormatPrinterForRegistryKey(pPrinterName, pszBuffer);
  1165. if (RegOpenKeyEx(hKeyConnections,
  1166. pKeyName,
  1167. REG_OPTION_RESERVED,
  1168. KEY_READ,
  1169. &hKeyPrinter) == ERROR_SUCCESS)
  1170. {
  1171. RegCloseKey(hKeyPrinter);
  1172. ConnectionFound = TRUE;
  1173. }
  1174. FreeSplMem(pszBuffer);
  1175. }
  1176. else
  1177. {
  1178. DBGMSG(DBG_WARNING, ("PrinterConnectionExists AllocMem failed Error %d\n", GetLastError()));
  1179. }
  1180. RegCloseKey(hKeyConnections);
  1181. }
  1182. else
  1183. {
  1184. DBGMSG(DBG_WARNING, ("RegOpenKeyEx failed: %ws Error %d\n", szRegistryConnections ,Status));
  1185. }
  1186. RegCloseKey(hClientKey);
  1187. }
  1188. return ConnectionFound;
  1189. }
  1190. BOOL
  1191. RemoteResetPrinter(
  1192. HANDLE hPrinter,
  1193. LPPRINTER_DEFAULTS pDefault
  1194. )
  1195. {
  1196. BOOL ReturnValue;
  1197. DEVMODE_CONTAINER DevModeContainer;
  1198. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  1199. VALIDATEW32HANDLE( pSpool );
  1200. DBGMSG(DBG_TRACE, ("ResetPrinter\n"));
  1201. SYNCRPCHANDLE( pSpool );
  1202. if (pDefault && pDefault->pDevMode)
  1203. {
  1204. DevModeContainer.cbBuf = pDefault->pDevMode->dmSize +
  1205. pDefault->pDevMode->dmDriverExtra;
  1206. DevModeContainer.pDevMode = (LPBYTE)pDefault->pDevMode;
  1207. }
  1208. else
  1209. {
  1210. DevModeContainer.cbBuf = 0;
  1211. DevModeContainer.pDevMode = NULL;
  1212. }
  1213. RpcTryExcept {
  1214. if ( ReturnValue = RpcResetPrinter(pSpool->RpcHandle,
  1215. pDefault ? pDefault->pDatatype : NULL,
  1216. &DevModeContainer) ) {
  1217. SetLastError(ReturnValue);
  1218. ReturnValue = FALSE;
  1219. } else {
  1220. ReturnValue = TRUE;
  1221. }
  1222. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1223. SetLastError(ERROR_NOT_SUPPORTED);
  1224. ReturnValue = FALSE;
  1225. } RpcEndExcept
  1226. return ReturnValue;
  1227. }
  1228. BOOL
  1229. SetJob(
  1230. HANDLE hPrinter,
  1231. DWORD JobId,
  1232. DWORD Level,
  1233. LPBYTE pJob,
  1234. DWORD Command
  1235. )
  1236. {
  1237. BOOL ReturnValue;
  1238. GENERIC_CONTAINER GenericContainer;
  1239. GENERIC_CONTAINER *pGenericContainer;
  1240. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  1241. VALIDATEW32HANDLE( pSpool );
  1242. SYNCRPCHANDLE( pSpool );
  1243. if (pSpool->Type == SJ_WIN32HANDLE) {
  1244. RpcTryExcept {
  1245. if (pJob) {
  1246. GenericContainer.Level = Level;
  1247. GenericContainer.pData = pJob;
  1248. pGenericContainer = &GenericContainer;
  1249. } else
  1250. pGenericContainer = NULL;
  1251. //
  1252. // JOB_CONTROL_DELETE was added in NT 4.0
  1253. //
  1254. if ( pSpool->bNt3xServer && Command == JOB_CONTROL_DELETE )
  1255. Command = JOB_CONTROL_CANCEL;
  1256. if ( ReturnValue = RpcSetJob(pSpool->RpcHandle, JobId,
  1257. (JOB_CONTAINER *)pGenericContainer,
  1258. Command) ) {
  1259. SetLastError(ReturnValue);
  1260. ReturnValue = FALSE;
  1261. } else
  1262. ReturnValue = TRUE;
  1263. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1264. SetLastError(RpcExceptionCode());
  1265. ReturnValue = FALSE;
  1266. } RpcEndExcept
  1267. } else
  1268. return LMSetJob(hPrinter, JobId, Level, pJob, Command);
  1269. return ReturnValue;
  1270. }
  1271. BOOL
  1272. GetJob(
  1273. HANDLE hPrinter,
  1274. DWORD JobId,
  1275. DWORD Level,
  1276. LPBYTE pJob,
  1277. DWORD cbBuf,
  1278. LPDWORD pcbNeeded
  1279. )
  1280. {
  1281. BOOL ReturnValue = FALSE;
  1282. FieldInfo *pFieldInfo;
  1283. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  1284. SIZE_T cbStruct;
  1285. DWORD cReturned = 1;
  1286. VALIDATEW32HANDLE( pSpool );
  1287. SYNCRPCHANDLE( pSpool );
  1288. if (pSpool->Type == SJ_WIN32HANDLE) {
  1289. switch (Level) {
  1290. case 1:
  1291. pFieldInfo = JobInfo1Fields;
  1292. cbStruct = sizeof(JOB_INFO_1);
  1293. break;
  1294. case 2:
  1295. pFieldInfo = JobInfo2Fields;
  1296. cbStruct = sizeof(JOB_INFO_2);
  1297. break;
  1298. case 3:
  1299. pFieldInfo = JobInfo3Fields;
  1300. cbStruct = sizeof(JOB_INFO_3);
  1301. break;
  1302. default:
  1303. SetLastError(ERROR_INVALID_LEVEL);
  1304. return FALSE;
  1305. }
  1306. RpcTryExcept {
  1307. if (pJob)
  1308. memset(pJob, 0, cbBuf);
  1309. if ( ReturnValue = RpcGetJob(pSpool->RpcHandle, JobId, Level, pJob,
  1310. cbBuf, pcbNeeded),
  1311. ReturnValue = UpdateBufferSize(pFieldInfo,
  1312. cbStruct,
  1313. pcbNeeded,
  1314. cbBuf,
  1315. ReturnValue,
  1316. &cReturned)) {
  1317. SetLastError(ReturnValue);
  1318. ReturnValue = FALSE;
  1319. } else {
  1320. if (pJob) {
  1321. ReturnValue = MarshallUpStructure(pJob, pFieldInfo, cbStruct, RPC_CALL);
  1322. }
  1323. }
  1324. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1325. SetLastError(RpcExceptionCode());
  1326. //
  1327. // This will be thrown by the server if a cbBuf > 1 Meg is
  1328. // passed across the wire.
  1329. //
  1330. SPLASSERT( GetLastError() != ERROR_INVALID_USER_BUFFER );
  1331. ReturnValue = FALSE;
  1332. } RpcEndExcept
  1333. } else
  1334. return LMGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
  1335. return ReturnValue;
  1336. }
  1337. BOOL
  1338. EnumJobs(
  1339. HANDLE hPrinter,
  1340. DWORD FirstJob,
  1341. DWORD NoJobs,
  1342. DWORD Level,
  1343. LPBYTE pJob,
  1344. DWORD cbBuf,
  1345. LPDWORD pcbNeeded,
  1346. LPDWORD pcReturned
  1347. )
  1348. {
  1349. DWORD ReturnValue, i, cbStruct;
  1350. FieldInfo *pFieldInfo;
  1351. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  1352. VALIDATEW32HANDLE( pSpool );
  1353. SYNCRPCHANDLE( pSpool );
  1354. if (pSpool->Type == SJ_WIN32HANDLE) {
  1355. switch (Level) {
  1356. case 1:
  1357. pFieldInfo = JobInfo1Fields;
  1358. cbStruct = sizeof(JOB_INFO_1);
  1359. break;
  1360. case 2:
  1361. pFieldInfo = JobInfo2Fields;
  1362. cbStruct = sizeof(JOB_INFO_2);
  1363. break;
  1364. case 3:
  1365. pFieldInfo = JobInfo3Fields;
  1366. cbStruct = sizeof(JOB_INFO_3);
  1367. break;
  1368. default:
  1369. SetLastError(ERROR_INVALID_LEVEL);
  1370. return FALSE;
  1371. }
  1372. RpcTryExcept {
  1373. if (pJob)
  1374. memset(pJob, 0, cbBuf);
  1375. if (ReturnValue = RpcEnumJobs(pSpool->RpcHandle,
  1376. FirstJob, NoJobs,
  1377. Level, pJob,
  1378. cbBuf, pcbNeeded,
  1379. pcReturned) ,
  1380. ReturnValue = UpdateBufferSize(pFieldInfo,
  1381. cbStruct,
  1382. pcbNeeded,
  1383. cbBuf,
  1384. ReturnValue,
  1385. pcReturned))
  1386. {
  1387. SetLastError(ReturnValue);
  1388. ReturnValue = FALSE;
  1389. }
  1390. else
  1391. {
  1392. ReturnValue = TRUE;
  1393. if(! MarshallUpStructuresArray(pJob, *pcReturned, pFieldInfo, cbStruct, RPC_CALL) ) {
  1394. return FALSE;
  1395. }
  1396. }
  1397. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1398. SetLastError(RpcExceptionCode());
  1399. ReturnValue = FALSE;
  1400. } RpcEndExcept
  1401. } else
  1402. return LMEnumJobs(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf,
  1403. pcbNeeded, pcReturned);
  1404. return (BOOL)ReturnValue;
  1405. }
  1406. HANDLE
  1407. AddPrinter(
  1408. LPWSTR pName,
  1409. DWORD Level,
  1410. LPBYTE pPrinter
  1411. )
  1412. {
  1413. DWORD ReturnValue;
  1414. PRINTER_CONTAINER PrinterContainer;
  1415. DEVMODE_CONTAINER DevModeContainer;
  1416. SECURITY_CONTAINER SecurityContainer;
  1417. HANDLE hPrinter = INVALID_HANDLE_VALUE;
  1418. PWSPOOL pSpool = NULL;
  1419. PWSTR pScratchBuffer = NULL;
  1420. PWSTR pCopyPrinterName = NULL;
  1421. SPLCLIENT_CONTAINER SplClientContainer;
  1422. SPLCLIENT_INFO_1 SplClientInfo;
  1423. WCHAR UserName[MAX_PATH+1];
  1424. DWORD dwRpcError = 0;
  1425. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  1426. SetLastError(ERROR_INVALID_NAME);
  1427. return FALSE;
  1428. }
  1429. CopyMemory((LPBYTE)&SplClientInfo,
  1430. (LPBYTE)&gSplClientInfo1,
  1431. sizeof(SplClientInfo));
  1432. //
  1433. // Don't pass in user name for browsing level because this
  1434. // causes LSA to chew up a lot of CPU. This isn't needed anyway
  1435. // because an AddPrinter( LEVEL_1 ) call never returns a print
  1436. // handle.
  1437. //
  1438. if( Level == 1 ){
  1439. UserName[0] = 0;
  1440. } else {
  1441. DWORD dwSize = sizeof(UserName)/sizeof(UserName[0]) - 1;
  1442. if ( !GetUserName(UserName, &dwSize) ) {
  1443. return FALSE;
  1444. }
  1445. }
  1446. PrinterContainer.Level = Level;
  1447. PrinterContainer.PrinterInfo.pPrinterInfo1 = (PPRINTER_INFO_1)pPrinter;
  1448. SplClientInfo.pUserName = UserName;
  1449. SplClientContainer.Level = 1;
  1450. SplClientContainer.ClientInfo.pClientInfo1 = &SplClientInfo;
  1451. if (Level == 2) {
  1452. PPRINTER_INFO_2 pPrinterInfo = (PPRINTER_INFO_2)pPrinter;
  1453. if (pPrinterInfo->pDevMode) {
  1454. DevModeContainer.cbBuf = pPrinterInfo->pDevMode->dmSize +
  1455. pPrinterInfo->pDevMode->dmDriverExtra;
  1456. DevModeContainer.pDevMode = (LPBYTE)pPrinterInfo->pDevMode;
  1457. //
  1458. // Set pDevMode to NULL. Import.h defines pDevMode and pSecurityDescriptor as pointers now.
  1459. // pDevMode and pSecurityDescriptor used to be defined as DWORD, but this doesn't work
  1460. // across 32b and 64b.
  1461. // These pointers must be set on NULL, otherwise RPC will marshall them as strings.
  1462. //
  1463. pPrinterInfo->pDevMode = NULL;
  1464. } else {
  1465. DevModeContainer.cbBuf = 0;
  1466. DevModeContainer.pDevMode = NULL;
  1467. }
  1468. if (pPrinterInfo->pSecurityDescriptor) {
  1469. SecurityContainer.cbBuf = GetSecurityDescriptorLength(pPrinterInfo->pSecurityDescriptor);
  1470. SecurityContainer.pSecurity = pPrinterInfo->pSecurityDescriptor;
  1471. //
  1472. // Set pSecurityDescriptor to NULL.
  1473. //
  1474. pPrinterInfo->pSecurityDescriptor = NULL;
  1475. } else {
  1476. SecurityContainer.cbBuf = 0;
  1477. SecurityContainer.pSecurity = NULL;
  1478. }
  1479. if (!pPrinterInfo->pPrinterName) {
  1480. SetLastError(ERROR_INVALID_PRINTER_NAME);
  1481. return FALSE;
  1482. }
  1483. if ( pScratchBuffer = AllocSplMem( MAX_UNC_PRINTER_NAME )) {
  1484. wsprintf( pScratchBuffer, L"%ws\\%ws", pName, pPrinterInfo->pPrinterName );
  1485. pCopyPrinterName = AllocSplStr( pScratchBuffer );
  1486. FreeSplMem( pScratchBuffer );
  1487. }
  1488. } else {
  1489. DevModeContainer.cbBuf = 0;
  1490. DevModeContainer.pDevMode = NULL;
  1491. SecurityContainer.cbBuf = 0;
  1492. SecurityContainer.pSecurity = NULL;
  1493. }
  1494. EnterSplSem();
  1495. pSpool = AllocWSpool();
  1496. LeaveSplSem();
  1497. if ( pSpool != NULL ) {
  1498. pSpool->pName = pCopyPrinterName;
  1499. pCopyPrinterName = NULL;
  1500. RpcTryExcept {
  1501. if ( (ReturnValue = RpcValidate()) ||
  1502. (ReturnValue = RpcAddPrinterEx(pName,
  1503. (PPRINTER_CONTAINER)&PrinterContainer,
  1504. (PDEVMODE_CONTAINER)&DevModeContainer,
  1505. (PSECURITY_CONTAINER)&SecurityContainer,
  1506. &SplClientContainer,
  1507. &hPrinter)) ) {
  1508. SetLastError(ReturnValue);
  1509. hPrinter = INVALID_HANDLE_VALUE;
  1510. }
  1511. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1512. dwRpcError = RpcExceptionCode();
  1513. } RpcEndExcept
  1514. if ( dwRpcError == RPC_S_PROCNUM_OUT_OF_RANGE ) {
  1515. dwRpcError = ERROR_SUCCESS;
  1516. RpcTryExcept {
  1517. if ( ReturnValue = RpcAddPrinter
  1518. (pName,
  1519. (PPRINTER_CONTAINER)&PrinterContainer,
  1520. (PDEVMODE_CONTAINER)&DevModeContainer,
  1521. (PSECURITY_CONTAINER)&SecurityContainer,
  1522. &hPrinter) ) {
  1523. SetLastError(ReturnValue);
  1524. hPrinter = INVALID_HANDLE_VALUE;
  1525. }
  1526. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1527. dwRpcError = RpcExceptionCode();
  1528. } RpcEndExcept
  1529. }
  1530. if ( dwRpcError ) {
  1531. SetLastError(dwRpcError);
  1532. hPrinter = INVALID_HANDLE_VALUE;
  1533. }
  1534. EnterSplSem();
  1535. if ( hPrinter != INVALID_HANDLE_VALUE ) {
  1536. pSpool->RpcHandle = hPrinter;
  1537. } else {
  1538. FreepSpool( pSpool );
  1539. pSpool = NULL;
  1540. }
  1541. LeaveSplSem();
  1542. } else {
  1543. // Failed to allocate Printer Handle
  1544. FreeSplStr( pCopyPrinterName );
  1545. }
  1546. if( Level == 2 ) {
  1547. //
  1548. // Restore pSecurityDescriptor and pDevMode. They were set to NULL to avoid RPC marshalling.
  1549. //
  1550. (LPBYTE)((PPRINTER_INFO_2)pPrinter)->pSecurityDescriptor = SecurityContainer.pSecurity;
  1551. (LPBYTE)((PPRINTER_INFO_2)pPrinter)->pDevMode = DevModeContainer.pDevMode;
  1552. }
  1553. SplOutSem();
  1554. return (HANDLE)pSpool;
  1555. }
  1556. BOOL
  1557. DeletePrinter(
  1558. HANDLE hPrinter
  1559. )
  1560. {
  1561. BOOL ReturnValue;
  1562. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  1563. VALIDATEW32HANDLE( pSpool );
  1564. SYNCRPCHANDLE( pSpool );
  1565. if (pSpool->Type == SJ_WIN32HANDLE) {
  1566. RpcTryExcept {
  1567. if ( ReturnValue = RpcDeletePrinter(pSpool->RpcHandle) ) {
  1568. SetLastError(ReturnValue);
  1569. ReturnValue = FALSE;
  1570. } else
  1571. ReturnValue = TRUE;
  1572. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  1573. SetLastError(RpcExceptionCode());
  1574. ReturnValue = FALSE;
  1575. } RpcEndExcept
  1576. } else {
  1577. SetLastError(ERROR_INVALID_FUNCTION);
  1578. ReturnValue = FALSE;
  1579. }
  1580. return ReturnValue;
  1581. }
  1582. /* SavePrinterConnectionInRegistry
  1583. *
  1584. * Saves data in the registry for a printer connection.
  1585. * Creates a key under the current impersonation client's key
  1586. * in the registry under \Printers\Connections.
  1587. * The printer name is stripped of backslashes, since the registry
  1588. * API does not permit the creation of keys with backslashes.
  1589. * They are replaced by commas, which are invalid characters
  1590. * in printer names, so we should never get one passed in.
  1591. *
  1592. *
  1593. * *** WARNING ***
  1594. *
  1595. * IF YOU MAKE CHANGES TO THE LOCATION IN THE REGISTRY
  1596. * WHERE PRINTER CONNECTIONS ARE STORED, YOU MUST MAKE
  1597. * CORRESPONDING CHANGES IN USER\USERINIT\USERINIT.C.
  1598. *
  1599. */
  1600. BOOL
  1601. SavePrinterConnectionInRegistry(
  1602. LPWSTR pRealName,
  1603. LPBYTE pDriverInfo,
  1604. DWORD dwLevel
  1605. )
  1606. {
  1607. TCHAR string[ MAX_UNC_PRINTER_NAME ];
  1608. HKEY hClientKey = NULL;
  1609. HKEY hConnectionsKey;
  1610. HKEY hPrinterKey;
  1611. LPWSTR pKeyName = NULL;
  1612. LPWSTR pData;
  1613. DWORD Status = NO_ERROR;
  1614. BOOL rc = TRUE;
  1615. LPDRIVER_INFO_2 pDriverInfo2 = (LPDRIVER_INFO_2) pDriverInfo;
  1616. hClientKey = GetClientUserHandle(KEY_READ);
  1617. if ( hClientKey == NULL ) {
  1618. DBGMSG( DBG_WARNING, ("SavePrinterConnectionInRegistry failed %d\n", GetLastError() ));
  1619. return FALSE;
  1620. }
  1621. Status = RegCreateKeyEx( hClientKey, szRegistryConnections,
  1622. REG_OPTION_RESERVED, NULL, REG_OPTION_NON_VOLATILE,
  1623. KEY_WRITE, NULL, &hConnectionsKey, NULL );
  1624. if (Status == NO_ERROR) {
  1625. pKeyName = FormatPrinterForRegistryKey( pRealName, string );
  1626. Status = RegCreateKeyEx( hConnectionsKey, pKeyName, REG_OPTION_RESERVED,
  1627. NULL, 0, KEY_WRITE, NULL, &hPrinterKey, NULL);
  1628. if (Status == NO_ERROR) {
  1629. switch ( dwLevel ) {
  1630. case 2:
  1631. case 3:
  1632. case 4:
  1633. //
  1634. // DRIVER_INFO_3,4 are supersets of 2 with DRIVER_INFO_2
  1635. // at the beginning
  1636. //
  1637. if (!SET_REG_VAL_DWORD(hPrinterKey, szVersion, pDriverInfo2->cVersion))
  1638. rc = FALSE;
  1639. if (!SET_REG_VAL_SZ(hPrinterKey, szName, pDriverInfo2->pName))
  1640. rc = FALSE;
  1641. // Note - None of the following values are required for NT 3.51 release or there after.
  1642. // We continue to write them incase someone has floating profiles and thus
  1643. // needs this stuff on 3.5 - 3.1 Daytona or before machine.
  1644. // Consider removing it in CAIRO ie assume that everyone has upgraded to 3.51 release
  1645. // Now write the driver files minus path:
  1646. if (!(pData = wcsrchr(pDriverInfo2->pConfigFile, '\\')))
  1647. pData = pDriverInfo2->pConfigFile;
  1648. else
  1649. pData++;
  1650. if (!SET_REG_VAL_SZ(hPrinterKey, szConfigurationFile, pData))
  1651. rc = FALSE;
  1652. if (!(pData = wcsrchr(pDriverInfo2->pDataFile, '\\')))
  1653. pData = pDriverInfo2->pDataFile;
  1654. else
  1655. pData++;
  1656. if (!SET_REG_VAL_SZ(hPrinterKey, szDataFile, pData))
  1657. rc = FALSE;
  1658. if (!(pData = wcsrchr(pDriverInfo2->pDriverPath, '\\')))
  1659. pData = pDriverInfo2->pDriverPath;
  1660. else
  1661. pData++;
  1662. if (!SET_REG_VAL_SZ(hPrinterKey, szDriver, pData))
  1663. rc = FALSE;
  1664. break;
  1665. default:
  1666. DBGMSG(DBG_ERROR, ("SavePrinterConnectionInRegistry: invalid level %d", dwLevel));
  1667. SetLastError(ERROR_INVALID_LEVEL);
  1668. rc = FALSE;
  1669. }
  1670. RegCloseKey(hPrinterKey);
  1671. } else {
  1672. DBGMSG(DBG_WARNING, ("RegCreateKeyEx(%ws) failed: Error %d\n",
  1673. pKeyName, Status ));
  1674. SetLastError( Status );
  1675. rc = FALSE;
  1676. }
  1677. // Now close the hConnectionsKey, we are done with it
  1678. RegCloseKey( hConnectionsKey );
  1679. } else {
  1680. DBGMSG( DBG_WARNING, ("RegCreateKeyEx(%ws) failed: Error %d\n",
  1681. szRegistryConnections, Status ));
  1682. SetLastError( Status );
  1683. rc = FALSE;
  1684. }
  1685. if (!rc) {
  1686. DBGMSG( DBG_WARNING, ("Error updating registry: %d\n",
  1687. GetLastError())); // This may not be the error
  1688. if ( pKeyName )
  1689. RegDeleteKey( hClientKey, pKeyName );
  1690. }
  1691. RegCloseKey( hClientKey );
  1692. return rc;
  1693. }
  1694. BOOL
  1695. InternalDeletePrinterConnection(
  1696. LPWSTR pName,
  1697. BOOL bNotifyDriver
  1698. )
  1699. /*++
  1700. Routine Description:
  1701. Delete a printer connection (printer name or share name) that
  1702. belongs to win32spl.dll.
  1703. Note: The Router takes care of updating win.ini and per user connections
  1704. section based on returning True / False.
  1705. Arguments:
  1706. pName - Either a printer or share name.
  1707. bNotifyDriver - flag to notify the driver
  1708. Return Value:
  1709. TRUE - success, FALSE - fail. LastError set.
  1710. --*/
  1711. {
  1712. BOOL bReturnValue = FALSE;
  1713. HKEY hClientKey = NULL;
  1714. HKEY hPrinterConnectionsKey = NULL;
  1715. DWORD i;
  1716. WCHAR szBuffer[MAX_UNC_PRINTER_NAME + 30]; // space for szRegistryConnections
  1717. DWORD cbBuffer;
  1718. PWCACHEINIPRINTEREXTRA pExtraData;
  1719. HANDLE hSplPrinter = NULL;
  1720. HANDLE hIniSpooler = NULL;
  1721. DWORD cRef;
  1722. WCHAR PrinterInfo1[ MAX_PRINTER_INFO1 ];
  1723. LPPRINTER_INFO_1W pPrinter1 = (LPPRINTER_INFO_1W)&PrinterInfo1;
  1724. LPWSTR pConnectionName = pName;
  1725. #if DBG
  1726. SetLastError( 0 );
  1727. #endif
  1728. try {
  1729. if ( !VALIDATE_NAME( pName ) ) {
  1730. SetLastError( ERROR_INVALID_NAME );
  1731. leave;
  1732. }
  1733. //
  1734. // If the Printer is in the Cache then Decrement its connection
  1735. // reference count.
  1736. //
  1737. if( !OpenCachePrinterOnly( pName, &hSplPrinter, &hIniSpooler, NULL, FALSE)){
  1738. DWORD dwLastError;
  1739. hSplPrinter = NULL;
  1740. hIniSpooler = NULL;
  1741. dwLastError = GetLastError();
  1742. if (( dwLastError != ERROR_INVALID_PRINTER_NAME ) &&
  1743. ( dwLastError != ERROR_INVALID_NAME )) {
  1744. DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed OpenCachePrinterOnly %ws error %d\n", pName, dwLastError ));
  1745. leave;
  1746. }
  1747. //
  1748. // Printer Is NOT in Cache,
  1749. //
  1750. // Continue to remove from HKEY_CURRENT_USER
  1751. // Can happen with Floating Profiles
  1752. //
  1753. } else {
  1754. //
  1755. // Printer is in Cache
  1756. // Support for DeletetPrinterConnection( \\server\share );
  1757. //
  1758. if( !SplGetPrinter( hSplPrinter,
  1759. 1,
  1760. (LPBYTE)pPrinter1,
  1761. sizeof( PrinterInfo1),
  1762. &cbBuffer )){
  1763. DBGMSG( DBG_WARNING, ("DeletePrinterConenction failed SplGetPrinter %d hSplPrinter %x\n", GetLastError(), hSplPrinter ));
  1764. SPLASSERT( pConnectionName == pName );
  1765. } else {
  1766. pConnectionName = pPrinter1->pName;
  1767. }
  1768. //
  1769. // Update Connection Reference Count
  1770. //
  1771. EnterSplSem();
  1772. if( !SplGetPrinterExtra( hSplPrinter, &(PBYTE)pExtraData )){
  1773. DBGMSG( DBG_WARNING,
  1774. ("DeletePrinterConnection SplGetPrinterExtra pSplPrinter %x error %d\n",
  1775. hSplPrinter, GetLastError() ));
  1776. pExtraData = NULL;
  1777. }
  1778. if (( pExtraData != NULL ) &&
  1779. ( pExtraData->cRef != 0 )) {
  1780. SPLASSERT( pExtraData->signature == WCIP_SIGNATURE );
  1781. pExtraData->cRef--;
  1782. cRef = pExtraData->cRef;
  1783. } else {
  1784. cRef = 0;
  1785. }
  1786. LeaveSplSem();
  1787. if ( cRef == 0 ) {
  1788. //
  1789. // Allow the Driver to do Per Cache Connection Cleanup
  1790. //
  1791. if (bNotifyDriver) {
  1792. SplDriverEvent( pConnectionName, PRINTER_EVENT_CACHE_DELETE, (LPARAM)NULL );
  1793. }
  1794. //
  1795. // Remove Cache for this printer
  1796. //
  1797. if ( !SplDeletePrinter( hSplPrinter )) {
  1798. DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed SplDeletePrinter %d\n", GetLastError() ));
  1799. leave;
  1800. }
  1801. } else {
  1802. if ( !SplSetPrinterExtra( hSplPrinter, (LPBYTE)pExtraData ) ) {
  1803. DBGMSG( DBG_ERROR, ("DeletePrinterConnection SplSetPrinterExtra failed %x\n", GetLastError() ));
  1804. leave;
  1805. }
  1806. }
  1807. SplOutSem();
  1808. }
  1809. //
  1810. // Note pConnectionName will either be the name passed in
  1811. // or if the Printer was in the Cache, would be the printer
  1812. // name from the cache.
  1813. // This will allow somone to call DeleteprinterConnection
  1814. // with a UNC Share name.
  1815. //
  1816. hClientKey = GetClientUserHandle(KEY_READ);
  1817. if ( hClientKey == NULL ) {
  1818. DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed %d\n", GetLastError() ));
  1819. leave;
  1820. }
  1821. wcscpy( szBuffer, szRegistryConnections );
  1822. i = wcslen(szBuffer);
  1823. szBuffer[i++] = L'\\';
  1824. FormatPrinterForRegistryKey( pConnectionName, szBuffer + i );
  1825. if( ERROR_SUCCESS != RegOpenKeyEx( hClientKey,
  1826. szBuffer,
  1827. 0,
  1828. KEY_READ,
  1829. &hPrinterConnectionsKey )){
  1830. if ( pConnectionName == pName ) {
  1831. SetLastError( ERROR_INVALID_PRINTER_NAME );
  1832. leave;
  1833. }
  1834. //
  1835. // If we have a printer on the server whose sharename is the same
  1836. // as a previously deleted printers printername then CacheOpenPrinter
  1837. // would have succeded but you are not going to find the share name in
  1838. // the registry
  1839. //
  1840. FormatPrinterForRegistryKey( pName, szBuffer + i );
  1841. if ( ERROR_SUCCESS != RegOpenKeyEx(hClientKey,
  1842. szBuffer,
  1843. 0,
  1844. KEY_READ,
  1845. &hPrinterConnectionsKey) ) {
  1846. SetLastError( ERROR_INVALID_PRINTER_NAME );
  1847. leave;
  1848. }
  1849. }
  1850. //
  1851. // Common case is success, so set the return value here.
  1852. // Only if we fail will we set it to FALSE now.
  1853. //
  1854. bReturnValue = TRUE;
  1855. cbBuffer = sizeof(szBuffer);
  1856. //
  1857. // If there is a Provider value, and it doesn't match win32spl.dll,
  1858. // then fail the call.
  1859. //
  1860. // If the provider value isn't there, succeed for backward
  1861. // compatibility.
  1862. //
  1863. if( ERROR_SUCCESS == RegQueryValueEx( hPrinterConnectionsKey,
  1864. L"Provider",
  1865. NULL,
  1866. NULL,
  1867. (LPBYTE)szBuffer,
  1868. &cbBuffer) &&
  1869. _wcsicmp( szBuffer, L"win32spl.dll" )){
  1870. bReturnValue = FALSE;
  1871. SetLastError( ERROR_INVALID_PRINTER_NAME );
  1872. }
  1873. RegCloseKey( hPrinterConnectionsKey );
  1874. } finally {
  1875. if( hClientKey ){
  1876. RegCloseKey( hClientKey );
  1877. }
  1878. if( hSplPrinter ){
  1879. if (!SplClosePrinter( hSplPrinter )){
  1880. DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed to close hSplPrinter %x error %d\n", hSplPrinter, GetLastError() ));
  1881. }
  1882. }
  1883. if( hIniSpooler ){
  1884. if( !SplCloseSpooler( hIniSpooler )){
  1885. DBGMSG( DBG_WARNING, ("DeletePrinterConnection failed to close hSplSpooler %x error %d\n", hIniSpooler, GetLastError() ));
  1886. }
  1887. }
  1888. }
  1889. if( !bReturnValue ){
  1890. SPLASSERT( GetLastError( ));
  1891. }
  1892. return bReturnValue;
  1893. }
  1894. BOOL
  1895. DeletePrinterConnection(
  1896. LPWSTR pName
  1897. )
  1898. {
  1899. return InternalDeletePrinterConnection(pName, TRUE);
  1900. }
  1901. BOOL
  1902. SetPrinter(
  1903. HANDLE hPrinter,
  1904. DWORD Level,
  1905. LPBYTE pPrinter,
  1906. DWORD Command
  1907. )
  1908. {
  1909. BOOL ReturnValue;
  1910. PRINTER_CONTAINER PrinterContainer;
  1911. DEVMODE_CONTAINER DevModeContainer;
  1912. SECURITY_CONTAINER SecurityContainer;
  1913. PPRINTER_INFO_2 pPrinterInfo2;
  1914. PPRINTER_INFO_3 pPrinterInfo3;
  1915. PPRINTER_INFO_5 pPrinterInfo5;
  1916. PPRINTER_INFO_6 pPrinterInfo6;
  1917. PPRINTER_INFO_7 pPrinterInfo7;
  1918. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  1919. BOOL bNeedToFreeDevMode = FALSE;
  1920. HANDLE hDevModeChgInfo = NULL;
  1921. LPDEVMODE pOldDevMode = NULL;
  1922. VALIDATEW32HANDLE( pSpool );
  1923. if (pSpool->Type != SJ_WIN32HANDLE) {
  1924. return LMSetPrinter(hPrinter, Level, pPrinter, Command);
  1925. }
  1926. SYNCRPCHANDLE( pSpool );
  1927. PrinterContainer.Level = Level;
  1928. PrinterContainer.PrinterInfo.pPrinterInfo1 = (PPRINTER_INFO_1)pPrinter;
  1929. DevModeContainer.cbBuf = 0;
  1930. DevModeContainer.pDevMode = NULL;
  1931. SecurityContainer.cbBuf = 0;
  1932. SecurityContainer.pSecurity = NULL;
  1933. switch (Level) {
  1934. case 0:
  1935. case 1:
  1936. break;
  1937. case 2:
  1938. pPrinterInfo2 = (PPRINTER_INFO_2)pPrinter;
  1939. if (pPrinterInfo2->pDevMode) {
  1940. if ( pSpool->bNt3xServer ) {
  1941. //
  1942. // If Nt 3xserver we will set devmode only if we can convert
  1943. //
  1944. if ( pSpool->Status & WSPOOL_STATUS_USE_CACHE ) {
  1945. hDevModeChgInfo = LoadDriverFiletoConvertDevmodeFromPSpool(pSpool->hSplPrinter);
  1946. if ( hDevModeChgInfo ) {
  1947. SPLASSERT( pSpool->pName != NULL );
  1948. if ( ERROR_SUCCESS == CallDrvDevModeConversion(
  1949. hDevModeChgInfo,
  1950. pSpool->pName,
  1951. (LPBYTE)pPrinterInfo2->pDevMode,
  1952. (LPBYTE *)&DevModeContainer.pDevMode,
  1953. &DevModeContainer.cbBuf,
  1954. CDM_CONVERT351,
  1955. TRUE) ) {
  1956. bNeedToFreeDevMode = TRUE;
  1957. }
  1958. }
  1959. }
  1960. } else {
  1961. DevModeContainer.cbBuf = pPrinterInfo2->pDevMode->dmSize +
  1962. pPrinterInfo2->pDevMode->dmDriverExtra;
  1963. DevModeContainer.pDevMode = (LPBYTE)pPrinterInfo2->pDevMode;
  1964. }
  1965. //
  1966. // Set pDevMode to NULL. Import.h defines pDevMode and pSecurityDescriptor as pointers now.
  1967. // pDevMode and pSecurityDescriptor used to be defined as DWORD, but this doesn't work
  1968. // across 32b and 64b.
  1969. // These pointers must be set on NULL, otherwise RPC will marshall them as strings.
  1970. //
  1971. pOldDevMode = pPrinterInfo2->pDevMode;
  1972. pPrinterInfo2->pDevMode = NULL;
  1973. }
  1974. if (pPrinterInfo2->pSecurityDescriptor) {
  1975. SecurityContainer.cbBuf = GetSecurityDescriptorLength(pPrinterInfo2->pSecurityDescriptor);
  1976. SecurityContainer.pSecurity = pPrinterInfo2->pSecurityDescriptor;
  1977. //
  1978. // Set pSecurityDescriptor to NULL.
  1979. //
  1980. pPrinterInfo2->pSecurityDescriptor = NULL;
  1981. }
  1982. break;
  1983. case 3:
  1984. pPrinterInfo3 = (PPRINTER_INFO_3)pPrinter;
  1985. //
  1986. // If this is NULL, should we even rpc out?
  1987. //
  1988. if (pPrinterInfo3->pSecurityDescriptor) {
  1989. SecurityContainer.cbBuf = GetSecurityDescriptorLength(pPrinterInfo3->pSecurityDescriptor);
  1990. SecurityContainer.pSecurity = pPrinterInfo3->pSecurityDescriptor;
  1991. }
  1992. break;
  1993. case 5:
  1994. pPrinterInfo5 = (PPRINTER_INFO_5)pPrinter;
  1995. break;
  1996. case 6:
  1997. pPrinterInfo6 = (PPRINTER_INFO_6)pPrinter;
  1998. break;
  1999. case 7:
  2000. pPrinterInfo7 = (PPRINTER_INFO_7)pPrinter;
  2001. break;
  2002. default:
  2003. SetLastError(ERROR_INVALID_LEVEL);
  2004. return FALSE;
  2005. }
  2006. RpcTryExcept {
  2007. if ( ReturnValue = RpcSetPrinter(pSpool->RpcHandle,
  2008. (PPRINTER_CONTAINER)&PrinterContainer,
  2009. (PDEVMODE_CONTAINER)&DevModeContainer,
  2010. (PSECURITY_CONTAINER)&SecurityContainer,
  2011. Command) ) {
  2012. SetLastError(ReturnValue);
  2013. ReturnValue = FALSE;
  2014. } else
  2015. ReturnValue = TRUE;
  2016. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2017. SetLastError(RpcExceptionCode());
  2018. ReturnValue = FALSE;
  2019. } RpcEndExcept
  2020. //
  2021. // Make sure Forms Cache is consistent
  2022. //
  2023. if ( ReturnValue ) {
  2024. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  2025. }
  2026. if( Level == 2 ) {
  2027. //
  2028. // Restore pSecurityDescriptor and pDevMode. They were set to NULL to avoid RPC marshalling.
  2029. //
  2030. (LPBYTE)pPrinterInfo2->pSecurityDescriptor = SecurityContainer.pSecurity;
  2031. pPrinterInfo2->pDevMode = pOldDevMode;
  2032. }
  2033. if ( bNeedToFreeDevMode )
  2034. FreeSplMem(DevModeContainer.pDevMode);
  2035. if ( hDevModeChgInfo )
  2036. UnloadDriverFile(hDevModeChgInfo);
  2037. return ReturnValue;
  2038. }
  2039. BOOL
  2040. RemoteGetPrinter(
  2041. HANDLE hPrinter,
  2042. DWORD Level,
  2043. LPBYTE pPrinter,
  2044. DWORD cbBuf,
  2045. LPDWORD pcbNeeded
  2046. )
  2047. {
  2048. BOOL ReturnValue = FALSE;
  2049. DWORD dwReturnValue = 0;
  2050. FieldInfo *pFieldInfo;
  2051. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2052. LPBYTE pNewPrinter = NULL;
  2053. DWORD dwNewSize;
  2054. SIZE_T cbStruct;
  2055. DWORD cReturned = 1;
  2056. VALIDATEW32HANDLE( pSpool );
  2057. SYNCRPCHANDLE( pSpool );
  2058. if (pSpool->Type == SJ_WIN32HANDLE) {
  2059. switch (Level) {
  2060. case STRESSINFOLEVEL:
  2061. pFieldInfo = PrinterInfoStressFields;
  2062. cbStruct = sizeof(PRINTER_INFO_STRESS);
  2063. break;
  2064. case 1:
  2065. pFieldInfo = PrinterInfo1Fields;
  2066. cbStruct = sizeof(PRINTER_INFO_1);
  2067. break;
  2068. case 2:
  2069. pFieldInfo = PrinterInfo2Fields;
  2070. cbStruct = sizeof(PRINTER_INFO_2);
  2071. break;
  2072. case 3:
  2073. pFieldInfo = PrinterInfo3Fields;
  2074. cbStruct = sizeof(PRINTER_INFO_3);
  2075. break;
  2076. case 5:
  2077. pFieldInfo = PrinterInfo5Fields;
  2078. cbStruct = sizeof(PRINTER_INFO_5);
  2079. break;
  2080. case 6:
  2081. pFieldInfo = PrinterInfo6Fields;
  2082. cbStruct = sizeof(PRINTER_INFO_6);
  2083. break;
  2084. case 7:
  2085. pFieldInfo = PrinterInfo7Fields;
  2086. cbStruct = sizeof(PRINTER_INFO_7);
  2087. break;
  2088. default:
  2089. SetLastError(ERROR_INVALID_LEVEL);
  2090. return FALSE;
  2091. }
  2092. if (pPrinter)
  2093. memset(pPrinter, 0, cbBuf);
  2094. //
  2095. // If going to different version and we have localspl handle want
  2096. // to do devmode conversion
  2097. //
  2098. if ( Level == 2 &&
  2099. (pSpool->Status & WSPOOL_STATUS_USE_CACHE) ) {
  2100. dwNewSize = cbBuf + MAX_PRINTER_INFO2;
  2101. pNewPrinter = AllocSplMem(dwNewSize);
  2102. if ( !pNewPrinter )
  2103. goto Cleanup;
  2104. } else {
  2105. dwNewSize = cbBuf;
  2106. pNewPrinter = pPrinter;
  2107. }
  2108. do {
  2109. RpcTryExcept {
  2110. dwReturnValue = RpcGetPrinter( pSpool->RpcHandle,
  2111. Level,
  2112. pNewPrinter,
  2113. dwNewSize,
  2114. pcbNeeded);
  2115. dwReturnValue = UpdateBufferSize( pFieldInfo,
  2116. cbStruct,
  2117. pcbNeeded,
  2118. dwNewSize,
  2119. dwReturnValue,
  2120. &cReturned);
  2121. if ( dwReturnValue ){
  2122. if ( Level == 2 &&
  2123. pNewPrinter != pPrinter &&
  2124. dwReturnValue == ERROR_INSUFFICIENT_BUFFER ) {
  2125. FreeSplMem(pNewPrinter);
  2126. dwNewSize = *pcbNeeded;
  2127. pNewPrinter = AllocSplMem(dwNewSize);
  2128. // do loop if pNewPrinter != NULL
  2129. } else {
  2130. SetLastError(dwReturnValue);
  2131. ReturnValue = FALSE;
  2132. }
  2133. } else {
  2134. ReturnValue = TRUE;
  2135. if (pNewPrinter &&
  2136. (ReturnValue = MarshallUpStructure(pNewPrinter, pFieldInfo, cbStruct, RPC_CALL))) {
  2137. if (Level == 2 ) {
  2138. //
  2139. // In the Cache && Different OS Level
  2140. //
  2141. if ( pNewPrinter != pPrinter ) {
  2142. SPLASSERT(pSpool->Status & WSPOOL_STATUS_USE_CACHE);
  2143. SPLASSERT(pSpool->pName != NULL );
  2144. ReturnValue = DoDevModeConversionAndBuildNewPrinterInfo2(
  2145. (LPPRINTER_INFO_2)pNewPrinter,
  2146. *pcbNeeded,
  2147. pPrinter,
  2148. cbBuf,
  2149. pcbNeeded,
  2150. pSpool);
  2151. }
  2152. if ( ReturnValue ) {
  2153. ((PPRINTER_INFO_2)pPrinter)->Attributes |=
  2154. PRINTER_ATTRIBUTE_NETWORK;
  2155. ((PPRINTER_INFO_2)pPrinter)->Attributes &=
  2156. ~PRINTER_ATTRIBUTE_LOCAL;
  2157. }
  2158. }
  2159. if (Level == 5) {
  2160. ((PPRINTER_INFO_5)pPrinter)->Attributes |=
  2161. PRINTER_ATTRIBUTE_NETWORK;
  2162. ((PPRINTER_INFO_5)pPrinter)->Attributes &=
  2163. ~PRINTER_ATTRIBUTE_LOCAL;
  2164. }
  2165. }
  2166. }
  2167. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2168. SetLastError(RpcExceptionCode());
  2169. //
  2170. // This will be thrown by the server if a cbBuf > 1 Meg is
  2171. // passed across the wire.
  2172. //
  2173. SPLASSERT( GetLastError() != ERROR_INVALID_USER_BUFFER );
  2174. ReturnValue = FALSE;
  2175. } RpcEndExcept
  2176. } while ( Level == 2 &&
  2177. dwReturnValue == ERROR_INSUFFICIENT_BUFFER &&
  2178. pNewPrinter != pPrinter &&
  2179. pNewPrinter );
  2180. } else {
  2181. return LMGetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
  2182. }
  2183. Cleanup:
  2184. if ( pNewPrinter != pPrinter )
  2185. FreeSplMem(pNewPrinter );
  2186. return ReturnValue;
  2187. }
  2188. BOOL
  2189. AddPrinterDriverEx(
  2190. LPWSTR pName,
  2191. DWORD Level,
  2192. PBYTE pDriverInfo,
  2193. DWORD dwFileCopyFlags
  2194. )
  2195. {
  2196. BOOL bReturnValue;
  2197. DWORD dwRpcError = 0, dwReturnValue;
  2198. DRIVER_CONTAINER DriverContainer;
  2199. PDRIVER_INFO_2W pDriverInfo2 = (PDRIVER_INFO_2W) pDriverInfo;
  2200. PDRIVER_INFO_3W pDriverInfo3 = (PDRIVER_INFO_3W) pDriverInfo;
  2201. PDRIVER_INFO_6W pDriverInfo6 = (PDRIVER_INFO_6W) pDriverInfo;
  2202. LPRPC_DRIVER_INFO_6W pRpcDriverInfo6 = NULL;
  2203. LPWSTR pBase, pStr;
  2204. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2205. SetLastError(ERROR_INVALID_NAME);
  2206. return FALSE;
  2207. }
  2208. //
  2209. // The dwFileCopyFlags don't send the APD_DRIVER_SIGNATURE_VALID to the remote
  2210. // machine. This is because for now we only support check-pointing on the local
  2211. // machine only. Maybe in the future when this is supported on all skus we could
  2212. // do a version check here and support check-pointing remote.
  2213. //
  2214. dwFileCopyFlags &= ~APD_DONT_SET_CHECKPOINT;
  2215. //
  2216. // ClientSide should have set a default environment if one was not
  2217. // specified.
  2218. //
  2219. switch (Level) {
  2220. case 2:
  2221. SPLASSERT( ( pDriverInfo2->pEnvironment != NULL ) &&
  2222. (*pDriverInfo2->pEnvironment != L'\0') );
  2223. break;
  2224. case 3:
  2225. case 4:
  2226. SPLASSERT( ( pDriverInfo3->pEnvironment != NULL ) &&
  2227. (*pDriverInfo3->pEnvironment != L'\0') );
  2228. break;
  2229. case 6:
  2230. SPLASSERT( ( pDriverInfo6->pEnvironment != NULL ) &&
  2231. (*pDriverInfo6->pEnvironment != L'\0') );
  2232. break;
  2233. default:
  2234. DBGMSG(DBG_ERROR, ("RemoteAddPrinterDriver: invalid level %d", Level));
  2235. SetLastError(ERROR_INVALID_LEVEL);
  2236. return FALSE;
  2237. }
  2238. DriverContainer.Level = Level;
  2239. if ( Level == 2 ) {
  2240. DriverContainer.DriverInfo.Level2 = (DRIVER_INFO_2 *)pDriverInfo;
  2241. } else {
  2242. //
  2243. // Level == 3 || Level == 4 || Level == 6
  2244. //
  2245. if( !( pRpcDriverInfo6 = AllocSplMem( sizeof( *pRpcDriverInfo6 )))) {
  2246. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2247. return FALSE;
  2248. } else {
  2249. pRpcDriverInfo6->cVersion = pDriverInfo3->cVersion;
  2250. pRpcDriverInfo6->pName = pDriverInfo3->pName;
  2251. pRpcDriverInfo6->pEnvironment = pDriverInfo3->pEnvironment;
  2252. pRpcDriverInfo6->pDriverPath = pDriverInfo3->pDriverPath;
  2253. pRpcDriverInfo6->pDataFile = pDriverInfo3->pDataFile;
  2254. pRpcDriverInfo6->pConfigFile = pDriverInfo3->pConfigFile;
  2255. pRpcDriverInfo6->pHelpFile = pDriverInfo3->pHelpFile;
  2256. pRpcDriverInfo6->pMonitorName = pDriverInfo3->pMonitorName;
  2257. pRpcDriverInfo6->pDefaultDataType = pDriverInfo3->pDefaultDataType;
  2258. //
  2259. // Set the char count of the mz string.
  2260. // NULL --- 0
  2261. // szNULL --- 1
  2262. // string --- number of characters in the string including the last '\0'
  2263. //
  2264. if ( pBase = pDriverInfo3->pDependentFiles ) {
  2265. for ( pStr = pBase ; *pStr; pStr += wcslen(pStr) + 1 )
  2266. ;
  2267. pRpcDriverInfo6->cchDependentFiles = (DWORD) (pStr - pBase + 1);
  2268. if ( pRpcDriverInfo6->cchDependentFiles )
  2269. pRpcDriverInfo6->pDependentFiles = pBase;
  2270. } else {
  2271. pRpcDriverInfo6->cchDependentFiles = 0;
  2272. }
  2273. if ( (Level == 4 || Level==6) &&
  2274. (pBase = ((LPDRIVER_INFO_4W)pDriverInfo)->pszzPreviousNames) ) {
  2275. pRpcDriverInfo6->pszzPreviousNames = pBase;
  2276. for ( pStr = pBase; *pStr ; pStr += wcslen(pStr) + 1 )
  2277. ;
  2278. pRpcDriverInfo6->cchPreviousNames = (DWORD) (pStr - pBase + 1);
  2279. } else {
  2280. pRpcDriverInfo6->cchPreviousNames = 0;
  2281. }
  2282. if (Level==6) {
  2283. pRpcDriverInfo6->pMfgName = pDriverInfo6->pszMfgName;
  2284. pRpcDriverInfo6->pOEMUrl = pDriverInfo6->pszOEMUrl;
  2285. pRpcDriverInfo6->pHardwareID = pDriverInfo6->pszHardwareID;
  2286. pRpcDriverInfo6->pProvider = pDriverInfo6->pszProvider;
  2287. pRpcDriverInfo6->ftDriverDate = pDriverInfo6->ftDriverDate;
  2288. pRpcDriverInfo6->dwlDriverVersion = pDriverInfo6->dwlDriverVersion;
  2289. }
  2290. DriverContainer.DriverInfo.Level6 = pRpcDriverInfo6;
  2291. }
  2292. }
  2293. RpcTryExcept {
  2294. if ( (dwReturnValue = RpcValidate()) ||
  2295. (dwReturnValue = RpcAddPrinterDriverEx(pName,
  2296. &DriverContainer,
  2297. dwFileCopyFlags)) ) {
  2298. SetLastError(dwReturnValue);
  2299. bReturnValue = FALSE;
  2300. } else {
  2301. bReturnValue = TRUE;
  2302. }
  2303. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2304. dwRpcError = RpcExceptionCode();
  2305. bReturnValue = FALSE;
  2306. } RpcEndExcept
  2307. if ((dwRpcError == RPC_S_PROCNUM_OUT_OF_RANGE) &&
  2308. (dwFileCopyFlags == APD_COPY_NEW_FILES)) {
  2309. bReturnValue = TRUE;
  2310. dwRpcError = ERROR_SUCCESS;
  2311. RpcTryExcept {
  2312. if ( dwReturnValue = RpcAddPrinterDriver(pName,
  2313. &DriverContainer) ) {
  2314. SetLastError(dwReturnValue);
  2315. bReturnValue = FALSE;
  2316. } else {
  2317. bReturnValue = TRUE;
  2318. }
  2319. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2320. dwRpcError = RpcExceptionCode();
  2321. bReturnValue = FALSE;
  2322. } RpcEndExcept
  2323. }
  2324. if ( dwRpcError ) {
  2325. if (dwRpcError == RPC_S_INVALID_TAG ) {
  2326. dwRpcError = ERROR_INVALID_LEVEL;
  2327. }
  2328. SetLastError(dwRpcError);
  2329. }
  2330. FreeSplMem(pRpcDriverInfo6);
  2331. return bReturnValue;
  2332. }
  2333. BOOL
  2334. RemoteAddPrinterDriver(
  2335. LPWSTR pName,
  2336. DWORD Level,
  2337. PBYTE pDriverInfo
  2338. )
  2339. {
  2340. return AddPrinterDriverEx(pName, Level, pDriverInfo, APD_COPY_NEW_FILES);
  2341. }
  2342. BOOL
  2343. EnumPrinterDrivers(
  2344. LPWSTR pName,
  2345. LPWSTR pEnvironment,
  2346. DWORD Level,
  2347. LPBYTE pDriverInfo,
  2348. DWORD cbBuf,
  2349. LPDWORD pcbNeeded,
  2350. LPDWORD pcReturned
  2351. )
  2352. {
  2353. DWORD i, cbStruct, ReturnValue;
  2354. FieldInfo *pFieldInfo;
  2355. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2356. SetLastError(ERROR_INVALID_NAME);
  2357. return FALSE;
  2358. }
  2359. switch (Level) {
  2360. case 1:
  2361. pFieldInfo = DriverInfo1Fields;
  2362. cbStruct = sizeof(DRIVER_INFO_1);
  2363. break;
  2364. case 2:
  2365. pFieldInfo = DriverInfo2Fields;
  2366. cbStruct = sizeof(DRIVER_INFO_2);
  2367. break;
  2368. case 3:
  2369. pFieldInfo = DriverInfo3Fields;
  2370. cbStruct = sizeof(DRIVER_INFO_3);
  2371. break;
  2372. case 4:
  2373. pFieldInfo = DriverInfo4Fields;
  2374. cbStruct = sizeof(DRIVER_INFO_4);
  2375. break;
  2376. case 5:
  2377. pFieldInfo = DriverInfo5Fields;
  2378. cbStruct = sizeof(DRIVER_INFO_5);
  2379. break;
  2380. case 6:
  2381. pFieldInfo = DriverInfo6Fields;
  2382. cbStruct = sizeof(DRIVER_INFO_6);
  2383. break;
  2384. default:
  2385. SetLastError(ERROR_INVALID_LEVEL);
  2386. return FALSE;
  2387. }
  2388. RpcTryExcept {
  2389. if ( (ReturnValue = RpcValidate()) ||
  2390. (ReturnValue = RpcEnumPrinterDrivers(pName, pEnvironment, Level,
  2391. pDriverInfo, cbBuf,
  2392. pcbNeeded, pcReturned) ,
  2393. ReturnValue = UpdateBufferSize(pFieldInfo,
  2394. cbStruct,
  2395. pcbNeeded,
  2396. cbBuf,
  2397. ReturnValue,
  2398. pcReturned)) )
  2399. {
  2400. SetLastError(ReturnValue);
  2401. ReturnValue = FALSE;
  2402. }
  2403. else
  2404. {
  2405. ReturnValue = TRUE;
  2406. if (pDriverInfo) {
  2407. if(! MarshallUpStructuresArray( pDriverInfo, *pcReturned, pFieldInfo,
  2408. cbStruct, RPC_CALL) ) {
  2409. return FALSE;
  2410. }
  2411. }
  2412. }
  2413. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2414. SetLastError(RpcExceptionCode());
  2415. ReturnValue = FALSE;
  2416. } RpcEndExcept
  2417. return (BOOL)ReturnValue;
  2418. }
  2419. BOOL
  2420. RemoteGetPrinterDriverDirectory(
  2421. LPWSTR pName,
  2422. LPWSTR pEnvironment,
  2423. DWORD Level,
  2424. LPBYTE pDriverDirectory,
  2425. DWORD cbBuf,
  2426. LPDWORD pcbNeeded
  2427. )
  2428. {
  2429. BOOL ReturnValue;
  2430. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2431. SetLastError(ERROR_INVALID_NAME);
  2432. return FALSE;
  2433. }
  2434. RpcTryExcept {
  2435. if ( (ReturnValue = RpcValidate()) ||
  2436. (ReturnValue = RpcGetPrinterDriverDirectory(pName, pEnvironment,
  2437. Level,
  2438. pDriverDirectory,
  2439. cbBuf, pcbNeeded)) ) {
  2440. SetLastError(ReturnValue);
  2441. ReturnValue = FALSE;
  2442. } else {
  2443. ReturnValue = TRUE;
  2444. }
  2445. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2446. SetLastError(RpcExceptionCode());
  2447. ReturnValue = FALSE;
  2448. } RpcEndExcept
  2449. return ReturnValue;
  2450. }
  2451. BOOL
  2452. DeletePrinterDriver(
  2453. LPWSTR pName,
  2454. LPWSTR pEnvironment,
  2455. LPWSTR pDriverName
  2456. )
  2457. {
  2458. BOOL ReturnValue;
  2459. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2460. SetLastError(ERROR_INVALID_NAME);
  2461. return FALSE;
  2462. }
  2463. RpcTryExcept {
  2464. if ( (ReturnValue = RpcValidate()) ||
  2465. (ReturnValue = RpcDeletePrinterDriver(pName,
  2466. pEnvironment,
  2467. pDriverName)) ) {
  2468. SetLastError(ReturnValue);
  2469. ReturnValue = FALSE;
  2470. } else
  2471. ReturnValue = TRUE;
  2472. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2473. SetLastError(RpcExceptionCode());
  2474. ReturnValue = FALSE;
  2475. } RpcEndExcept
  2476. return ReturnValue;
  2477. }
  2478. BOOL
  2479. DeletePrinterDriverEx(
  2480. LPWSTR pName,
  2481. LPWSTR pEnvironment,
  2482. LPWSTR pDriverName,
  2483. DWORD dwDeleteFlag,
  2484. DWORD dwVersionNum
  2485. )
  2486. {
  2487. BOOL ReturnValue;
  2488. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2489. SetLastError(ERROR_INVALID_NAME);
  2490. return FALSE;
  2491. }
  2492. RpcTryExcept {
  2493. if ( (ReturnValue = RpcValidate()) ||
  2494. (ReturnValue = RpcDeletePrinterDriverEx(pName,
  2495. pEnvironment,
  2496. pDriverName,
  2497. dwDeleteFlag,
  2498. dwVersionNum)) ) {
  2499. SetLastError(ReturnValue);
  2500. ReturnValue = FALSE;
  2501. } else
  2502. ReturnValue = TRUE;
  2503. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2504. SetLastError(RpcExceptionCode());
  2505. ReturnValue = FALSE;
  2506. } RpcEndExcept
  2507. return ReturnValue;
  2508. }
  2509. BOOL
  2510. AddPerMachineConnection(
  2511. LPCWSTR pServer,
  2512. LPCWSTR pPrinterName,
  2513. LPCWSTR pPrintServer,
  2514. LPCWSTR pProvider
  2515. )
  2516. {
  2517. BOOL ReturnValue;
  2518. if ( !VALIDATE_NAME((LPWSTR)pServer) || MyUNCName((LPWSTR)pServer) ) {
  2519. SetLastError(ERROR_INVALID_NAME);
  2520. return FALSE;
  2521. }
  2522. RpcTryExcept {
  2523. if ( (ReturnValue = RpcValidate()) ||
  2524. (ReturnValue = RpcAddPerMachineConnection((LPWSTR) pServer,
  2525. pPrinterName,
  2526. pPrintServer,
  2527. pProvider)) ) {
  2528. SetLastError(ReturnValue);
  2529. ReturnValue = FALSE;
  2530. } else
  2531. ReturnValue = TRUE;
  2532. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2533. SetLastError(RpcExceptionCode());
  2534. ReturnValue = FALSE;
  2535. } RpcEndExcept
  2536. return ReturnValue;
  2537. }
  2538. BOOL
  2539. DeletePerMachineConnection(
  2540. LPCWSTR pServer,
  2541. LPCWSTR pPrinterName
  2542. )
  2543. {
  2544. BOOL ReturnValue;
  2545. if ( !VALIDATE_NAME((LPWSTR) pServer) || MyUNCName((LPWSTR) pServer) ) {
  2546. SetLastError(ERROR_INVALID_NAME);
  2547. return FALSE;
  2548. }
  2549. RpcTryExcept {
  2550. if ( (ReturnValue = RpcValidate()) ||
  2551. (ReturnValue = RpcDeletePerMachineConnection((LPWSTR) pServer,
  2552. pPrinterName)) ) {
  2553. SetLastError(ReturnValue);
  2554. ReturnValue = FALSE;
  2555. } else
  2556. ReturnValue = TRUE;
  2557. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2558. SetLastError(RpcExceptionCode());
  2559. ReturnValue = FALSE;
  2560. } RpcEndExcept
  2561. return ReturnValue;
  2562. }
  2563. BOOL
  2564. EnumPerMachineConnections(
  2565. LPCWSTR pServer,
  2566. LPBYTE pPrinterEnum,
  2567. DWORD cbBuf,
  2568. LPDWORD pcbNeeded,
  2569. LPDWORD pcReturned
  2570. )
  2571. {
  2572. BOOL ReturnValue;
  2573. FieldInfo *pFieldInfo = PrinterInfo4Fields;
  2574. DWORD cbStruct = sizeof(PRINTER_INFO_4),index;
  2575. if ( !VALIDATE_NAME((LPWSTR) pServer) || MyUNCName((LPWSTR) pServer) ) {
  2576. SetLastError(ERROR_INVALID_NAME);
  2577. return FALSE;
  2578. }
  2579. RpcTryExcept {
  2580. if ( (ReturnValue = RpcValidate()) ||
  2581. (ReturnValue = RpcEnumPerMachineConnections((LPWSTR) pServer,
  2582. pPrinterEnum,
  2583. cbBuf,
  2584. pcbNeeded,
  2585. pcReturned) ,
  2586. ReturnValue = UpdateBufferSize(pFieldInfo,
  2587. cbStruct,
  2588. pcbNeeded,
  2589. cbBuf,
  2590. ReturnValue,
  2591. pcReturned)) ) {
  2592. SetLastError(ReturnValue);
  2593. ReturnValue = FALSE;
  2594. } else {
  2595. ReturnValue = TRUE;
  2596. if (pPrinterEnum) {
  2597. if(! MarshallUpStructuresArray(pPrinterEnum, *pcReturned, pFieldInfo,
  2598. cbStruct, RPC_CALL) ) {
  2599. return FALSE;
  2600. }
  2601. }
  2602. }
  2603. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2604. SetLastError(RpcExceptionCode());
  2605. ReturnValue = FALSE;
  2606. } RpcEndExcept
  2607. return (BOOL)ReturnValue;
  2608. }
  2609. BOOL
  2610. AddPrintProcessor(
  2611. LPWSTR pName,
  2612. LPWSTR pEnvironment,
  2613. LPWSTR pPathName,
  2614. LPWSTR pPrintProcessorName
  2615. )
  2616. {
  2617. BOOL ReturnValue;
  2618. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2619. SetLastError(ERROR_INVALID_NAME);
  2620. return FALSE;
  2621. }
  2622. RpcTryExcept {
  2623. if ( (ReturnValue = RpcValidate()) ||
  2624. (ReturnValue = RpcAddPrintProcessor(pName , pEnvironment,pPathName,
  2625. pPrintProcessorName)) ) {
  2626. SetLastError(ReturnValue);
  2627. ReturnValue = FALSE;
  2628. } else
  2629. ReturnValue = TRUE;
  2630. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2631. SetLastError(RpcExceptionCode());
  2632. ReturnValue = FALSE;
  2633. } RpcEndExcept
  2634. return ReturnValue;
  2635. }
  2636. BOOL
  2637. EnumPrintProcessors(
  2638. LPWSTR pName,
  2639. LPWSTR pEnvironment,
  2640. DWORD Level,
  2641. LPBYTE pPrintProcessorInfo,
  2642. DWORD cbBuf,
  2643. LPDWORD pcbNeeded,
  2644. LPDWORD pcReturned
  2645. )
  2646. {
  2647. DWORD i, cbStruct, ReturnValue;
  2648. FieldInfo *pFieldInfo;
  2649. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2650. SetLastError(ERROR_INVALID_NAME);
  2651. return FALSE;
  2652. }
  2653. switch (Level) {
  2654. case 1:
  2655. pFieldInfo = PrintProcessorInfo1Fields;
  2656. cbStruct = sizeof(PRINTPROCESSOR_INFO_1);
  2657. break;
  2658. default:
  2659. SetLastError(ERROR_INVALID_LEVEL);
  2660. return FALSE;
  2661. }
  2662. RpcTryExcept {
  2663. if ( (ReturnValue = RpcValidate()) ||
  2664. (ReturnValue = RpcEnumPrintProcessors(pName, pEnvironment, Level,
  2665. pPrintProcessorInfo, cbBuf,
  2666. pcbNeeded, pcReturned) ,
  2667. ReturnValue = UpdateBufferSize(pFieldInfo,
  2668. cbStruct,
  2669. pcbNeeded,
  2670. cbBuf,
  2671. ReturnValue,
  2672. pcReturned)) ) {
  2673. SetLastError(ReturnValue);
  2674. ReturnValue = FALSE;
  2675. } else {
  2676. ReturnValue = TRUE;
  2677. if (pPrintProcessorInfo) {
  2678. if(! MarshallUpStructuresArray( pPrintProcessorInfo, *pcReturned, pFieldInfo,
  2679. cbStruct, RPC_CALL) ) {
  2680. return FALSE;
  2681. }
  2682. }
  2683. }
  2684. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2685. SetLastError(RpcExceptionCode());
  2686. ReturnValue = FALSE;
  2687. } RpcEndExcept
  2688. return (BOOL) ReturnValue;
  2689. }
  2690. BOOL
  2691. EnumPrintProcessorDatatypes(
  2692. LPWSTR pName,
  2693. LPWSTR pPrintProcessorName,
  2694. DWORD Level,
  2695. LPBYTE pDatatypes,
  2696. DWORD cbBuf,
  2697. LPDWORD pcbNeeded,
  2698. LPDWORD pcReturned
  2699. )
  2700. {
  2701. DWORD ReturnValue, i, cbStruct;
  2702. FieldInfo *pFieldInfo;
  2703. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2704. SetLastError(ERROR_INVALID_NAME);
  2705. return FALSE;
  2706. }
  2707. switch (Level) {
  2708. case 1:
  2709. pFieldInfo = DatatypeInfo1Fields;
  2710. cbStruct = sizeof(DATATYPES_INFO_1);
  2711. break;
  2712. default:
  2713. SetLastError(ERROR_INVALID_LEVEL);
  2714. return FALSE;
  2715. }
  2716. RpcTryExcept {
  2717. if ( (ReturnValue = RpcValidate()) ||
  2718. (ReturnValue = RpcEnumPrintProcessorDatatypes(pName,
  2719. pPrintProcessorName,
  2720. Level,
  2721. pDatatypes,
  2722. cbBuf,
  2723. pcbNeeded,
  2724. pcReturned) ,
  2725. ReturnValue = UpdateBufferSize(pFieldInfo,
  2726. cbStruct,
  2727. pcbNeeded,
  2728. cbBuf,
  2729. ReturnValue,
  2730. pcReturned)) ) {
  2731. SetLastError(ReturnValue);
  2732. ReturnValue = FALSE;
  2733. } else {
  2734. ReturnValue = TRUE;
  2735. if (pDatatypes) {
  2736. if(! MarshallUpStructuresArray( pDatatypes, *pcReturned, pFieldInfo,
  2737. cbStruct, RPC_CALL) ) {
  2738. return FALSE;
  2739. }
  2740. }
  2741. }
  2742. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2743. SetLastError(RpcExceptionCode());
  2744. ReturnValue = FALSE;
  2745. } RpcEndExcept
  2746. return (BOOL) ReturnValue;
  2747. }
  2748. BOOL
  2749. GetPrintProcessorDirectory(
  2750. LPWSTR pName,
  2751. LPWSTR pEnvironment,
  2752. DWORD Level,
  2753. LPBYTE pPrintProcessorDirectory,
  2754. DWORD cbBuf,
  2755. LPDWORD pcbNeeded
  2756. )
  2757. {
  2758. BOOL ReturnValue;
  2759. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  2760. SetLastError(ERROR_INVALID_NAME);
  2761. return FALSE;
  2762. }
  2763. RpcTryExcept {
  2764. if ( (ReturnValue = RpcValidate()) ||
  2765. (ReturnValue = RpcGetPrintProcessorDirectory(pName, pEnvironment,
  2766. Level,
  2767. pPrintProcessorDirectory,
  2768. cbBuf, pcbNeeded)) ) {
  2769. SetLastError(ReturnValue);
  2770. ReturnValue = FALSE;
  2771. } else {
  2772. ReturnValue = TRUE;
  2773. }
  2774. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2775. SetLastError(RpcExceptionCode());
  2776. ReturnValue = FALSE;
  2777. } RpcEndExcept
  2778. return ReturnValue;
  2779. }
  2780. DWORD
  2781. StartDocPrinter(
  2782. HANDLE hPrinter,
  2783. DWORD Level,
  2784. LPBYTE pDocInfo
  2785. )
  2786. {
  2787. BOOL ReturnValue;
  2788. GENERIC_CONTAINER DocInfoContainer;
  2789. DWORD JobId;
  2790. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2791. PDOC_INFO_1 pDocInfo1 = (PDOC_INFO_1)pDocInfo;
  2792. VALIDATEW32HANDLE( pSpool );
  2793. if (Win32IsGoingToFile(pSpool, pDocInfo1->pOutputFile)) {
  2794. HANDLE hFile;
  2795. //
  2796. // POLICY?
  2797. //
  2798. // If no datatype is specified, and the default is non-raw,
  2799. // should we fail?
  2800. //
  2801. if( pDocInfo1 &&
  2802. pDocInfo1->pDatatype &&
  2803. !ValidRawDatatype( pDocInfo1->pDatatype )){
  2804. SetLastError( ERROR_INVALID_DATATYPE );
  2805. return FALSE;
  2806. }
  2807. pSpool->Status |= WSPOOL_STATUS_PRINT_FILE;
  2808. hFile = CreateFile( pDocInfo1->pOutputFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
  2809. OPEN_ALWAYS,
  2810. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  2811. NULL );
  2812. if (hFile == INVALID_HANDLE_VALUE) {
  2813. return FALSE;
  2814. } else {
  2815. pSpool->hFile = hFile;
  2816. return TRUE;
  2817. }
  2818. }
  2819. SYNCRPCHANDLE( pSpool );
  2820. if (pSpool->Type == SJ_WIN32HANDLE) {
  2821. DocInfoContainer.Level = Level;
  2822. DocInfoContainer.pData = pDocInfo;
  2823. RpcTryExcept {
  2824. if ( ReturnValue = RpcStartDocPrinter(pSpool->RpcHandle,
  2825. (LPDOC_INFO_CONTAINER)&DocInfoContainer,
  2826. &JobId) ) {
  2827. SetLastError(ReturnValue);
  2828. ReturnValue = FALSE;
  2829. } else
  2830. ReturnValue = JobId;
  2831. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2832. SetLastError(RpcExceptionCode());
  2833. ReturnValue = FALSE;
  2834. } RpcEndExcept
  2835. } else
  2836. return LMStartDocPrinter(hPrinter, Level, pDocInfo);
  2837. return ReturnValue;
  2838. }
  2839. BOOL
  2840. StartPagePrinter(
  2841. HANDLE hPrinter
  2842. )
  2843. {
  2844. BOOL ReturnValue;
  2845. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2846. VALIDATEW32HANDLE( pSpool );
  2847. if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
  2848. return TRUE;
  2849. }
  2850. SYNCRPCHANDLE( pSpool );
  2851. if (pSpool->Type == SJ_WIN32HANDLE) {
  2852. RpcTryExcept {
  2853. if ( ReturnValue = RpcStartPagePrinter(pSpool->RpcHandle) ) {
  2854. SetLastError(ReturnValue);
  2855. ReturnValue = FALSE;
  2856. } else
  2857. ReturnValue = TRUE;
  2858. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2859. SetLastError(RpcExceptionCode());
  2860. ReturnValue = FALSE;
  2861. } RpcEndExcept
  2862. } else
  2863. return LMStartPagePrinter(hPrinter);
  2864. return ReturnValue;
  2865. }
  2866. BOOL
  2867. WritePrinter(
  2868. HANDLE hPrinter,
  2869. LPVOID pBuf,
  2870. DWORD cbBuf,
  2871. LPDWORD pcWritten
  2872. )
  2873. {
  2874. BOOL ReturnValue=TRUE;
  2875. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2876. VALIDATEW32HANDLE( pSpool );
  2877. *pcWritten = 0;
  2878. if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
  2879. ReturnValue = WriteFile(pSpool->hFile, pBuf, cbBuf, pcWritten, NULL);
  2880. return ReturnValue;
  2881. }
  2882. SYNCRPCHANDLE( pSpool );
  2883. if (pSpool->Type == SJ_WIN32HANDLE) {
  2884. RpcTryExcept {
  2885. // Note this code used chop the request into 4k chunks which were
  2886. // the prefered size for Rpc. However the client dll batches all
  2887. // data into 4k chunks so no need to duplcate that code here.
  2888. if (ReturnValue = RpcWritePrinter(pSpool->RpcHandle, pBuf, cbBuf, pcWritten)) {
  2889. SetLastError(ReturnValue);
  2890. ReturnValue = FALSE;
  2891. } else {
  2892. ReturnValue = TRUE;
  2893. }
  2894. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2895. SetLastError(RpcExceptionCode());
  2896. ReturnValue = FALSE;
  2897. } RpcEndExcept
  2898. } else {
  2899. return LMWritePrinter(hPrinter, pBuf, cbBuf, pcWritten);
  2900. }
  2901. return ReturnValue;
  2902. }
  2903. BOOL
  2904. SeekPrinter(
  2905. HANDLE hPrinter,
  2906. LARGE_INTEGER liDistanceToMove,
  2907. PLARGE_INTEGER pliNewPointer,
  2908. DWORD dwMoveMethod,
  2909. BOOL bWrite
  2910. )
  2911. {
  2912. SetLastError( ERROR_NOT_SUPPORTED );
  2913. return FALSE;
  2914. }
  2915. BOOL
  2916. FlushPrinter(
  2917. HANDLE hPrinter,
  2918. LPVOID pBuf,
  2919. DWORD cbBuf,
  2920. LPDWORD pcWritten,
  2921. DWORD cSleep
  2922. )
  2923. {
  2924. BOOL bReturn = TRUE;
  2925. DWORD dwError;
  2926. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2927. VALIDATEW32HANDLE( pSpool );
  2928. SYNCRPCHANDLE( pSpool );
  2929. RpcTryExcept {
  2930. if ((dwError = RpcValidate()) ||
  2931. (dwError = RpcFlushPrinter(pSpool->RpcHandle,
  2932. pBuf,
  2933. cbBuf,
  2934. pcWritten,
  2935. cSleep)))
  2936. {
  2937. SetLastError( dwError );
  2938. bReturn = FALSE;
  2939. }
  2940. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2941. SetLastError( RpcExceptionCode() );
  2942. bReturn = FALSE;
  2943. } RpcEndExcept
  2944. return bReturn;
  2945. }
  2946. BOOL
  2947. EndPagePrinter(
  2948. HANDLE hPrinter
  2949. )
  2950. {
  2951. BOOL ReturnValue;
  2952. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2953. VALIDATEW32HANDLE( pSpool );
  2954. if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
  2955. return TRUE;
  2956. }
  2957. SYNCRPCHANDLE( pSpool );
  2958. if (pSpool->Type == SJ_WIN32HANDLE) {
  2959. RpcTryExcept {
  2960. if (ReturnValue = RpcEndPagePrinter(pSpool->RpcHandle)) {
  2961. SetLastError(ReturnValue);
  2962. ReturnValue = FALSE;
  2963. } else
  2964. ReturnValue = TRUE;
  2965. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2966. SetLastError(RpcExceptionCode());
  2967. ReturnValue = FALSE;
  2968. } RpcEndExcept
  2969. } else
  2970. return LMEndPagePrinter(hPrinter);
  2971. return ReturnValue;
  2972. }
  2973. BOOL
  2974. AbortPrinter(
  2975. HANDLE hPrinter
  2976. )
  2977. {
  2978. BOOL ReturnValue;
  2979. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  2980. VALIDATEW32HANDLE( pSpool );
  2981. SYNCRPCHANDLE( pSpool );
  2982. if (pSpool->Type == SJ_WIN32HANDLE) {
  2983. RpcTryExcept {
  2984. if (ReturnValue = RpcAbortPrinter(pSpool->RpcHandle)) {
  2985. SetLastError(ReturnValue);
  2986. ReturnValue = FALSE;
  2987. } else
  2988. ReturnValue = TRUE;
  2989. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  2990. SetLastError(RpcExceptionCode());
  2991. ReturnValue = FALSE;
  2992. } RpcEndExcept
  2993. } else
  2994. return LMAbortPrinter(hPrinter);
  2995. return ReturnValue;
  2996. }
  2997. BOOL
  2998. ReadPrinter(
  2999. HANDLE hPrinter,
  3000. LPVOID pBuf,
  3001. DWORD cbBuf,
  3002. LPDWORD pNoBytesRead
  3003. )
  3004. {
  3005. BOOL ReturnValue=TRUE;
  3006. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3007. VALIDATEW32HANDLE( pSpool );
  3008. if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE ) {
  3009. return FALSE;
  3010. }
  3011. SYNCRPCHANDLE( pSpool );
  3012. if (pSpool->Type == SJ_WIN32HANDLE) {
  3013. RpcTryExcept {
  3014. if (ReturnValue = RpcReadPrinter(pSpool->RpcHandle, pBuf, cbBuf, pNoBytesRead)) {
  3015. SetLastError(ReturnValue);
  3016. ReturnValue = FALSE;
  3017. } else
  3018. ReturnValue = TRUE;
  3019. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3020. SetLastError(RpcExceptionCode());
  3021. ReturnValue = FALSE;
  3022. } RpcEndExcept
  3023. } else
  3024. return LMReadPrinter(hPrinter, pBuf, cbBuf, pNoBytesRead);
  3025. return ReturnValue;
  3026. }
  3027. BOOL
  3028. RemoteEndDocPrinter(
  3029. HANDLE hPrinter
  3030. )
  3031. {
  3032. BOOL ReturnValue;
  3033. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3034. VALIDATEW32HANDLE( pSpool );
  3035. if (pSpool->Status & WSPOOL_STATUS_PRINT_FILE) {
  3036. CloseHandle( pSpool->hFile );
  3037. pSpool->hFile = INVALID_HANDLE_VALUE;
  3038. pSpool->Status &= ~WSPOOL_STATUS_PRINT_FILE;
  3039. return TRUE;
  3040. }
  3041. SYNCRPCHANDLE( pSpool );
  3042. if (pSpool->Type == SJ_WIN32HANDLE) {
  3043. RpcTryExcept {
  3044. if (ReturnValue = RpcEndDocPrinter(pSpool->RpcHandle)) {
  3045. SetLastError(ReturnValue);
  3046. ReturnValue = FALSE;
  3047. } else
  3048. ReturnValue = TRUE;
  3049. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3050. SetLastError(RpcExceptionCode());
  3051. ReturnValue = FALSE;
  3052. } RpcEndExcept
  3053. } else
  3054. return LMEndDocPrinter(hPrinter);
  3055. return ReturnValue;
  3056. }
  3057. BOOL
  3058. AddJob(
  3059. HANDLE hPrinter,
  3060. DWORD Level,
  3061. LPBYTE pData,
  3062. DWORD cbBuf,
  3063. LPDWORD pcbNeeded
  3064. )
  3065. {
  3066. BOOL ReturnValue = FALSE;
  3067. DWORD dwRet = 0;
  3068. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3069. DWORD cReturned = 1;
  3070. FieldInfo *pFieldInfo;
  3071. SIZE_T cbStruct;
  3072. VALIDATEW32HANDLE( pSpool );
  3073. SYNCRPCHANDLE( pSpool );
  3074. if (pSpool->Type == SJ_WIN32HANDLE) {
  3075. switch (Level) {
  3076. case 1:
  3077. pFieldInfo = AddJobFields;
  3078. cbStruct = sizeof(ADDJOB_INFO_1W);
  3079. break;
  3080. case 2:
  3081. case 3:
  3082. //
  3083. // Block level 2 & 3 calls across the network.
  3084. //
  3085. default:
  3086. SetLastError(ERROR_INVALID_LEVEL);
  3087. return FALSE;
  3088. }
  3089. RpcTryExcept {
  3090. if (dwRet = RpcAddJob(pSpool->RpcHandle, Level, pData,cbBuf, pcbNeeded) ) {
  3091. dwRet = UpdateBufferSize(pFieldInfo, cbStruct, pcbNeeded, cbBuf, dwRet, &cReturned);
  3092. SetLastError(dwRet);
  3093. ReturnValue = FALSE;
  3094. } else {
  3095. ReturnValue = MarshallUpStructure(pData, AddJobFields, cbStruct, RPC_CALL);
  3096. }
  3097. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3098. SetLastError(RpcExceptionCode());
  3099. ReturnValue = FALSE;
  3100. } RpcEndExcept
  3101. } else
  3102. return LMAddJob(hPrinter, Level, pData, cbBuf, pcbNeeded);
  3103. return ReturnValue;
  3104. }
  3105. BOOL
  3106. ScheduleJob(
  3107. HANDLE hPrinter,
  3108. DWORD JobId
  3109. )
  3110. {
  3111. BOOL ReturnValue;
  3112. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3113. VALIDATEW32HANDLE( pSpool );
  3114. SYNCRPCHANDLE( pSpool );
  3115. if (pSpool->Type == SJ_WIN32HANDLE) {
  3116. RpcTryExcept {
  3117. if (ReturnValue = RpcScheduleJob(pSpool->RpcHandle, JobId)) {
  3118. SetLastError(ReturnValue);
  3119. ReturnValue = FALSE;
  3120. } else
  3121. ReturnValue = TRUE;
  3122. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3123. SetLastError(RpcExceptionCode());
  3124. ReturnValue = FALSE;
  3125. } RpcEndExcept
  3126. } else
  3127. return LMScheduleJob(hPrinter, JobId);
  3128. return ReturnValue;
  3129. }
  3130. DWORD
  3131. RemoteGetPrinterData(
  3132. HANDLE hPrinter,
  3133. LPWSTR pValueName,
  3134. LPDWORD pType,
  3135. LPBYTE pData,
  3136. DWORD nSize,
  3137. LPDWORD pcbNeeded
  3138. )
  3139. {
  3140. DWORD ReturnValue = 0;
  3141. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3142. VALIDATEW32HANDLE( pSpool );
  3143. SYNCRPCHANDLE( pSpool );
  3144. if (pSpool->Type == SJ_WIN32HANDLE) {
  3145. RpcTryExcept {
  3146. ReturnValue = RpcGetPrinterData(pSpool->RpcHandle, pValueName, pType,
  3147. pData, nSize, pcbNeeded);
  3148. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3149. ReturnValue = RpcExceptionCode();
  3150. } RpcEndExcept
  3151. } else {
  3152. ReturnValue = ERROR_INVALID_FUNCTION;
  3153. }
  3154. return ReturnValue;
  3155. }
  3156. DWORD
  3157. RemoteGetPrinterDataEx(
  3158. HANDLE hPrinter,
  3159. LPCWSTR pKeyName,
  3160. LPCWSTR pValueName,
  3161. LPDWORD pType,
  3162. LPBYTE pData,
  3163. DWORD nSize,
  3164. LPDWORD pcbNeeded
  3165. )
  3166. {
  3167. DWORD ReturnValue = 0;
  3168. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3169. VALIDATEW32HANDLE( pSpool );
  3170. SYNCRPCHANDLE( pSpool );
  3171. if (pSpool->Type == SJ_WIN32HANDLE) {
  3172. RpcTryExcept {
  3173. ReturnValue = RpcGetPrinterDataEx( pSpool->RpcHandle,
  3174. pKeyName,
  3175. pValueName,
  3176. pType,
  3177. pData,
  3178. nSize,
  3179. pcbNeeded);
  3180. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3181. ReturnValue = RpcExceptionCode();
  3182. } RpcEndExcept
  3183. } else {
  3184. ReturnValue = ERROR_INVALID_FUNCTION;
  3185. }
  3186. return ReturnValue;
  3187. }
  3188. DWORD
  3189. RemoteEnumPrinterData(
  3190. HANDLE hPrinter,
  3191. DWORD dwIndex,
  3192. LPWSTR pValueName,
  3193. DWORD cbValueName,
  3194. LPDWORD pcbValueName,
  3195. LPDWORD pType,
  3196. LPBYTE pData,
  3197. DWORD cbData,
  3198. LPDWORD pcbData
  3199. )
  3200. {
  3201. DWORD ReturnValue = 0;
  3202. DWORD ReturnType = 0;
  3203. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3204. // Downlevel variables
  3205. LPWSTR pKeyName = NULL;
  3206. PWCHAR pPrinterName = NULL;
  3207. PWCHAR pScratch = NULL;
  3208. PWCHAR pBuffer = NULL;
  3209. LPPRINTER_INFO_1W pPrinter1 = NULL;
  3210. PWCHAR pMachineName = NULL;
  3211. HKEY hkMachine = INVALID_HANDLE_VALUE;
  3212. HKEY hkDownlevel = INVALID_HANDLE_VALUE;
  3213. DWORD dwNeeded;
  3214. VALIDATEW32HANDLE( pSpool );
  3215. SYNCRPCHANDLE( pSpool );
  3216. if (pSpool->Type == SJ_WIN32HANDLE) {
  3217. //
  3218. // The user should be able to pass in NULL for buffer, and
  3219. // 0 for size. However, the RPC interface specifies a ref pointer,
  3220. // so we must pass in a valid pointer. Pass in a pointer to
  3221. // a dummy pointer.
  3222. //
  3223. if (!pValueName && !cbValueName)
  3224. pValueName = (LPWSTR) &ReturnValue;
  3225. if( !pData && !cbData )
  3226. pData = (PBYTE)&ReturnValue;
  3227. if (!pType)
  3228. pType = (PDWORD) &ReturnType;
  3229. RpcTryExcept {
  3230. ReturnValue = RpcEnumPrinterData( pSpool->RpcHandle,
  3231. dwIndex,
  3232. pValueName,
  3233. cbValueName,
  3234. pcbValueName,
  3235. pType,
  3236. pData,
  3237. cbData,
  3238. pcbData
  3239. );
  3240. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3241. ReturnValue = RpcExceptionCode();
  3242. } RpcEndExcept
  3243. } else {
  3244. ReturnValue = ERROR_INVALID_FUNCTION;
  3245. }
  3246. // If the remote spooler doesn't support EnumPrinterData, do it the old way
  3247. if (ReturnValue == RPC_S_PROCNUM_OUT_OF_RANGE) {
  3248. pBuffer = AllocSplMem((wcslen(pszRemoteRegistryPrinters) + MAX_UNC_PRINTER_NAME)*sizeof(WCHAR));
  3249. pScratch = AllocSplMem(MAX_UNC_PRINTER_NAME*sizeof(WCHAR));
  3250. pPrinter1 = AllocSplMem(MAX_PRINTER_INFO1);
  3251. if (pBuffer == NULL || pScratch == NULL || pPrinter1 == NULL) {
  3252. ReturnValue = GetLastError();
  3253. goto DownlevelDone;
  3254. }
  3255. SPLASSERT ( 0 == _wcsnicmp( pSpool->pName, L"\\\\", 2 ) ) ;
  3256. SPLASSERT ( pSpool->Status & WSPOOL_STATUS_USE_CACHE );
  3257. wcscpy( pBuffer, pSpool->pName);
  3258. pPrinterName = wcschr( pBuffer+2, L'\\' );
  3259. *pPrinterName = L'\0';
  3260. pMachineName = AllocSplStr( pBuffer );
  3261. if (pMachineName == NULL) {
  3262. ReturnValue = GetLastError();
  3263. goto DownlevelDone;
  3264. }
  3265. // We cannot use pSpool->pName since this might be the share name which will
  3266. // fail if we try to use it as a registry key on the remote machine
  3267. // Get the full friendly name from the cache
  3268. if ( !SplGetPrinter( pSpool->hSplPrinter, 1, (LPBYTE)pPrinter1, MAX_PRINTER_INFO1, &dwNeeded )) {
  3269. DBGMSG( DBG_ERROR, ("RemoteEnumPrinterData failed SplGetPrinter %d pSpool %x\n", GetLastError(), pSpool ));
  3270. ReturnValue = GetLastError();
  3271. goto DownlevelDone;
  3272. }
  3273. pPrinterName = wcschr( pPrinter1->pName+2, L'\\' );
  3274. if ( pPrinterName++ == NULL ) {
  3275. ReturnValue = ERROR_INVALID_PARAMETER;
  3276. goto DownlevelDone;
  3277. }
  3278. //
  3279. // Generate the Correct KeyName from the Printer Name
  3280. //
  3281. DBGMSG( DBG_TRACE,(" pSpool->pName %ws pPrinterName %ws\n", pSpool->pName, pPrinterName));
  3282. pKeyName = FormatPrinterForRegistryKey( pPrinterName, pScratch );
  3283. wsprintf( pBuffer, pszRemoteRegistryPrinters, pKeyName );
  3284. // Because there is no EnumPrinterData downlevel we are forced to open the remote registry
  3285. // for LocalSpl and use the registry RegEnumValue to read through the printer data
  3286. // values.
  3287. ReturnValue = RegConnectRegistry( pMachineName, HKEY_LOCAL_MACHINE, &hkMachine);
  3288. if (ReturnValue != ERROR_SUCCESS) {
  3289. DBGMSG( DBG_WARNING, ("RemoteEnumPrinterData RegConnectRegistry error %d\n",GetLastError()));
  3290. goto DownlevelDone;
  3291. }
  3292. ReturnValue = RegOpenKeyEx(hkMachine, pBuffer, 0, KEY_READ, &hkDownlevel);
  3293. if ( ReturnValue != ERROR_SUCCESS ) {
  3294. DBGMSG( DBG_WARNING, ("RemoteEnumPrinterData RegOpenKeyEx %ws error %d\n", pBuffer, ReturnValue ));
  3295. goto DownlevelDone;
  3296. }
  3297. // Get the max sizes
  3298. if (!cbValueName && !cbData) {
  3299. ReturnValue = RegQueryInfoKey( hkDownlevel, // Key
  3300. NULL, // lpClass
  3301. NULL, // lpcbClass
  3302. NULL, // lpReserved
  3303. NULL, // lpcSubKeys
  3304. NULL, // lpcbMaxSubKeyLen
  3305. NULL, // lpcbMaxClassLen
  3306. NULL, // lpcValues
  3307. pcbValueName, // lpcbMaxValueNameLen
  3308. pcbData, // lpcbMaxValueLen
  3309. NULL, // lpcbSecurityDescriptor
  3310. NULL // lpftLastWriteTime
  3311. );
  3312. *pcbValueName = (*pcbValueName + 1)*sizeof(WCHAR);
  3313. } else { // Do an enum
  3314. *pcbValueName = cbValueName/sizeof(WCHAR);
  3315. *pcbData = cbData;
  3316. ReturnValue = RegEnumValue( hkDownlevel,
  3317. dwIndex,
  3318. pValueName,
  3319. pcbValueName,
  3320. NULL,
  3321. pType,
  3322. pData,
  3323. pcbData
  3324. );
  3325. *pcbValueName = (*pcbValueName + 1)*sizeof(WCHAR);
  3326. }
  3327. DownlevelDone:
  3328. FreeSplMem(pBuffer);
  3329. FreeSplStr(pScratch);
  3330. FreeSplMem(pPrinter1);
  3331. FreeSplStr(pMachineName);
  3332. if (hkMachine != INVALID_HANDLE_VALUE)
  3333. RegCloseKey(hkMachine);
  3334. if (hkDownlevel != INVALID_HANDLE_VALUE)
  3335. RegCloseKey(hkDownlevel);
  3336. }
  3337. return ReturnValue;
  3338. }
  3339. DWORD
  3340. RemoteEnumPrinterDataEx(
  3341. HANDLE hPrinter,
  3342. LPCWSTR pKeyName,
  3343. LPBYTE pEnumValues,
  3344. DWORD cbEnumValues,
  3345. LPDWORD pcbEnumValues,
  3346. LPDWORD pnEnumValues
  3347. )
  3348. {
  3349. DWORD ReturnValue = 0;
  3350. DWORD RpcReturnValue = 0;
  3351. DWORD i;
  3352. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3353. PPRINTER_ENUM_VALUES pEnumValue = (PPRINTER_ENUM_VALUES) pEnumValues;
  3354. VALIDATEW32HANDLE( pSpool );
  3355. SYNCRPCHANDLE( pSpool );
  3356. if (pSpool->Type == SJ_WIN32HANDLE) {
  3357. //
  3358. // The user should be able to pass in NULL for buffer, and
  3359. // 0 for size. However, the RPC interface specifies a ref pointer,
  3360. // so we must pass in a valid pointer. Pass in a pointer to
  3361. // a dummy pointer.
  3362. //
  3363. if (!pEnumValues && !cbEnumValues)
  3364. pEnumValues = (LPBYTE) &ReturnValue;
  3365. RpcTryExcept {
  3366. ReturnValue = RpcEnumPrinterDataEx(pSpool->RpcHandle,
  3367. pKeyName,
  3368. pEnumValues,
  3369. cbEnumValues,
  3370. pcbEnumValues,
  3371. pnEnumValues);
  3372. RpcReturnValue = ReturnValue;
  3373. ReturnValue = UpdateBufferSize(PrinterEnumValuesFields,
  3374. sizeof(PRINTER_ENUM_VALUES),
  3375. pcbEnumValues,
  3376. cbEnumValues,
  3377. ReturnValue,
  3378. pnEnumValues);
  3379. //
  3380. // When talking with a 32bit machine, the buffer could be big enough to acomodate
  3381. // the data packed on 32bit boundaries but not big enough to expand it for 64bit.
  3382. // In this case, UpdateBufferSize fails with ERROR_INSUFFICIENT_BUFFER which
  3383. // is a valid error for all printing APIs but EnumPrinterDataEx.
  3384. // SDK specifies that EnumPrinterDataEx should fail with ERROR_MORE_DATA in this case,
  3385. // so here we go.
  3386. //
  3387. //
  3388. if (RpcReturnValue == ERROR_SUCCESS &&
  3389. ReturnValue == ERROR_INSUFFICIENT_BUFFER) {
  3390. ReturnValue = ERROR_MORE_DATA;
  3391. }
  3392. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3393. ReturnValue = RpcExceptionCode();
  3394. } RpcEndExcept
  3395. if (ReturnValue == ERROR_SUCCESS) {
  3396. if (pEnumValues) {
  3397. SIZE_T ShrinkedSize = 0;
  3398. SIZE_T Difference = 0;
  3399. if (GetShrinkedSize(PrinterEnumValuesFields, &ShrinkedSize)) {
  3400. //
  3401. // SplEnumPrinterDataEx ( in localspl.dll ) packs the data right after
  3402. // the end of array of PPRINTER_ENUM_VALUES structures. Our Marshalling
  3403. // code relies on the fact that there is enough unused space between the end of
  3404. // structure/array and the beginning of data to expand a 32bit flat structure to
  3405. // a 64 bit structure.For all other structures we pack data from end to beginning
  3406. // of buffer. localspl.dll could have been fixed to do the same thing, but Win2K
  3407. // servers would still have this problem.
  3408. // The fix is to still ask for bigger buffers for 64bit (UpdateBufferSize)
  3409. // and then move the chunk containing data inside the buffer so that it leaves
  3410. // space for structure to grow.
  3411. // On Win32 we don't do anything since ShrinkedSize is equal with sizeof(PRINTER_ENUM_VALUES).
  3412. //
  3413. MoveMemory((LPBYTE)pEnumValue + sizeof(PRINTER_ENUM_VALUES) * (*pnEnumValues),
  3414. (LPBYTE)pEnumValue + ShrinkedSize * (*pnEnumValues),
  3415. cbEnumValues - sizeof(PRINTER_ENUM_VALUES) * (*pnEnumValues));
  3416. //
  3417. // Difference is the number of bytes we moved data section inside pEnumValue buffer
  3418. // It should be 0 in Win32
  3419. //
  3420. Difference = (sizeof(PRINTER_ENUM_VALUES) - ShrinkedSize ) * (*pnEnumValues);
  3421. if(! MarshallUpStructuresArray((LPBYTE) pEnumValue, *pnEnumValues, PrinterEnumValuesFields,
  3422. sizeof(PRINTER_ENUM_VALUES), RPC_CALL) ) {
  3423. ReturnValue = GetLastError();
  3424. }
  3425. //
  3426. // We need to adjust the offsets with Difference inside structures since data got moved.
  3427. //
  3428. AdjustPointersInStructuresArray((LPBYTE) pEnumValue, *pnEnumValues, PrinterEnumValuesFields,
  3429. sizeof(PRINTER_ENUM_VALUES), Difference);
  3430. } else {
  3431. ReturnValue = GetLastError();
  3432. }
  3433. }
  3434. }
  3435. } else {
  3436. ReturnValue = ERROR_INVALID_FUNCTION;
  3437. }
  3438. return ReturnValue;
  3439. }
  3440. DWORD
  3441. RemoteEnumPrinterKey(
  3442. HANDLE hPrinter,
  3443. LPCWSTR pKeyName,
  3444. LPWSTR pSubkey,
  3445. DWORD cbSubkey,
  3446. LPDWORD pcbSubkey
  3447. )
  3448. {
  3449. DWORD ReturnValue = 0;
  3450. DWORD ReturnType = 0;
  3451. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3452. VALIDATEW32HANDLE( pSpool );
  3453. SYNCRPCHANDLE( pSpool );
  3454. if (pSpool->Type == SJ_WIN32HANDLE) {
  3455. //
  3456. // The user should be able to pass in NULL for buffer, and
  3457. // 0 for size. However, the RPC interface specifies a ref pointer,
  3458. // so we must pass in a valid pointer. Pass in a pointer to
  3459. // a dummy pointer.
  3460. //
  3461. if (!pSubkey && !cbSubkey)
  3462. pSubkey = (LPWSTR) &ReturnValue;
  3463. RpcTryExcept {
  3464. ReturnValue = RpcEnumPrinterKey(pSpool->RpcHandle,
  3465. pKeyName,
  3466. pSubkey,
  3467. cbSubkey,
  3468. pcbSubkey
  3469. );
  3470. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3471. ReturnValue = RpcExceptionCode();
  3472. } RpcEndExcept
  3473. } else {
  3474. ReturnValue = ERROR_INVALID_FUNCTION;
  3475. }
  3476. return ReturnValue;
  3477. }
  3478. DWORD
  3479. RemoteDeletePrinterData(
  3480. HANDLE hPrinter,
  3481. LPWSTR pValueName
  3482. )
  3483. {
  3484. DWORD ReturnValue = 0;
  3485. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3486. VALIDATEW32HANDLE( pSpool );
  3487. SYNCRPCHANDLE( pSpool );
  3488. if (pSpool->Type == SJ_WIN32HANDLE) {
  3489. RpcTryExcept {
  3490. ReturnValue = RpcDeletePrinterData(pSpool->RpcHandle, pValueName);
  3491. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3492. ReturnValue = RpcExceptionCode();
  3493. } RpcEndExcept
  3494. } else {
  3495. ReturnValue = ERROR_INVALID_FUNCTION;
  3496. }
  3497. if ( ReturnValue == ERROR_SUCCESS )
  3498. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3499. return ReturnValue;
  3500. }
  3501. DWORD
  3502. RemoteDeletePrinterDataEx(
  3503. HANDLE hPrinter,
  3504. LPCWSTR pKeyName,
  3505. LPCWSTR pValueName
  3506. )
  3507. {
  3508. DWORD ReturnValue = 0;
  3509. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3510. VALIDATEW32HANDLE( pSpool );
  3511. SYNCRPCHANDLE( pSpool );
  3512. if (pSpool->Type == SJ_WIN32HANDLE) {
  3513. RpcTryExcept {
  3514. ReturnValue = RpcDeletePrinterDataEx(pSpool->RpcHandle, pKeyName, pValueName);
  3515. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3516. ReturnValue = RpcExceptionCode();
  3517. } RpcEndExcept
  3518. } else {
  3519. ReturnValue = ERROR_INVALID_FUNCTION;
  3520. }
  3521. if ( ReturnValue == ERROR_SUCCESS )
  3522. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3523. return ReturnValue;
  3524. }
  3525. DWORD
  3526. RemoteDeletePrinterKey(
  3527. HANDLE hPrinter,
  3528. LPCWSTR pKeyName
  3529. )
  3530. {
  3531. DWORD ReturnValue = 0;
  3532. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3533. VALIDATEW32HANDLE( pSpool );
  3534. SYNCRPCHANDLE( pSpool );
  3535. if (pSpool->Type == SJ_WIN32HANDLE) {
  3536. RpcTryExcept {
  3537. ReturnValue = RpcDeletePrinterKey(pSpool->RpcHandle, pKeyName);
  3538. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3539. ReturnValue = RpcExceptionCode();
  3540. } RpcEndExcept
  3541. } else {
  3542. ReturnValue = ERROR_INVALID_FUNCTION;
  3543. }
  3544. if ( ReturnValue == ERROR_SUCCESS )
  3545. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3546. return ReturnValue;
  3547. }
  3548. DWORD
  3549. SetPrinterData(
  3550. HANDLE hPrinter,
  3551. LPWSTR pValueName,
  3552. DWORD Type,
  3553. LPBYTE pData,
  3554. DWORD cbData
  3555. )
  3556. {
  3557. DWORD ReturnValue = 0;
  3558. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3559. VALIDATEW32HANDLE( pSpool );
  3560. SYNCRPCHANDLE( pSpool );
  3561. if (pSpool->Type == SJ_WIN32HANDLE) {
  3562. RpcTryExcept {
  3563. ReturnValue = RpcSetPrinterData(pSpool->RpcHandle, pValueName, Type,
  3564. pData, cbData);
  3565. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3566. ReturnValue = RpcExceptionCode();
  3567. } RpcEndExcept
  3568. } else {
  3569. ReturnValue = ERROR_INVALID_FUNCTION;
  3570. }
  3571. //
  3572. // Make sure Driver Data Cache is consistent
  3573. //
  3574. if ( ReturnValue == ERROR_SUCCESS ) {
  3575. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3576. }
  3577. return ReturnValue;
  3578. }
  3579. DWORD
  3580. RemoteSetPrinterDataEx(
  3581. HANDLE hPrinter,
  3582. LPCWSTR pKeyName,
  3583. LPCWSTR pValueName,
  3584. DWORD Type,
  3585. LPBYTE pData,
  3586. DWORD cbData
  3587. )
  3588. {
  3589. DWORD ReturnValue = 0;
  3590. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3591. VALIDATEW32HANDLE( pSpool );
  3592. SYNCRPCHANDLE( pSpool );
  3593. if (pSpool->Type == SJ_WIN32HANDLE) {
  3594. RpcTryExcept {
  3595. ReturnValue = RpcSetPrinterDataEx( pSpool->RpcHandle,
  3596. pKeyName,
  3597. pValueName,
  3598. Type,
  3599. pData,
  3600. cbData);
  3601. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3602. ReturnValue = RpcExceptionCode();
  3603. } RpcEndExcept
  3604. } else {
  3605. ReturnValue = ERROR_INVALID_FUNCTION;
  3606. }
  3607. if ( ReturnValue == ERROR_SUCCESS ) {
  3608. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3609. }
  3610. return ReturnValue;
  3611. }
  3612. BOOL
  3613. RemoteClosePrinter(
  3614. HANDLE hPrinter
  3615. )
  3616. {
  3617. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3618. VALIDATEW32HANDLE( pSpool );
  3619. if (pSpool->Status & WSPOOL_STATUS_OPEN_ERROR) {
  3620. DBGMSG(DBG_WARNING, ("Closing dummy handle to %ws\n", pSpool->pName));
  3621. EnterSplSem();
  3622. FreepSpool( pSpool );
  3623. LeaveSplSem();
  3624. return TRUE;
  3625. }
  3626. if (pSpool->Type == SJ_WIN32HANDLE) {
  3627. RpcTryExcept {
  3628. RpcClosePrinter(&pSpool->RpcHandle);
  3629. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3630. } RpcEndExcept
  3631. //
  3632. // If we failed for some reason, then RpcClosePrinter did not
  3633. // zero out the context handle. Destroy it here.
  3634. //
  3635. if( pSpool->RpcHandle ){
  3636. RpcSmDestroyClientContext( &pSpool->RpcHandle );
  3637. }
  3638. EnterSplSem();
  3639. pSpool->RpcHandle = INVALID_HANDLE_VALUE;
  3640. FreepSpool( pSpool );
  3641. LeaveSplSem();
  3642. } else
  3643. return LMClosePrinter(hPrinter);
  3644. return TRUE;
  3645. }
  3646. DWORD
  3647. WaitForPrinterChange(
  3648. HANDLE hPrinter,
  3649. DWORD Flags
  3650. )
  3651. {
  3652. DWORD ReturnValue;
  3653. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3654. VALIDATEW32HANDLE( pSpool );
  3655. SYNCRPCHANDLE( pSpool );
  3656. if( pSpool->Status & WSPOOL_STATUS_NOTIFY ){
  3657. DBGMSG( DBG_WARNING, ( "WPC: Already waiting.\n" ));
  3658. SetLastError( ERROR_ALREADY_WAITING );
  3659. return 0;
  3660. }
  3661. pSpool->Status |= WSPOOL_STATUS_NOTIFY;
  3662. if (pSpool->Type == SJ_WIN32HANDLE) {
  3663. RpcTryExcept {
  3664. if (ReturnValue = RpcWaitForPrinterChange(pSpool->RpcHandle, Flags, &Flags)) {
  3665. SetLastError(ReturnValue);
  3666. ReturnValue = FALSE;
  3667. } else
  3668. ReturnValue = Flags;
  3669. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3670. SetLastError(RpcExceptionCode());
  3671. ReturnValue = FALSE;
  3672. } RpcEndExcept
  3673. } else {
  3674. ReturnValue = LMWaitForPrinterChange(hPrinter, Flags);
  3675. }
  3676. pSpool->Status &= ~WSPOOL_STATUS_NOTIFY;
  3677. return ReturnValue;
  3678. }
  3679. BOOL
  3680. AddForm(
  3681. HANDLE hPrinter,
  3682. DWORD Level,
  3683. LPBYTE pForm
  3684. )
  3685. {
  3686. BOOL ReturnValue;
  3687. GENERIC_CONTAINER FormContainer;
  3688. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3689. VALIDATEW32HANDLE( pSpool );
  3690. SYNCRPCHANDLE( pSpool );
  3691. if (pSpool->Type == SJ_WIN32HANDLE) {
  3692. FormContainer.Level = Level;
  3693. FormContainer.pData = pForm;
  3694. RpcTryExcept {
  3695. if (ReturnValue = RpcAddForm(pSpool->RpcHandle, (PFORM_CONTAINER)&FormContainer)) {
  3696. SetLastError(ReturnValue);
  3697. ReturnValue = FALSE;
  3698. } else
  3699. ReturnValue = TRUE;
  3700. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3701. SetLastError(RpcExceptionCode());
  3702. ReturnValue = FALSE;;
  3703. } RpcEndExcept
  3704. } else {
  3705. SetLastError(ERROR_INVALID_FUNCTION);
  3706. ReturnValue = FALSE;
  3707. }
  3708. //
  3709. // Make sure Forms Cache is consistent
  3710. //
  3711. if ( ReturnValue ) {
  3712. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3713. }
  3714. return ReturnValue;
  3715. }
  3716. BOOL
  3717. DeleteForm(
  3718. HANDLE hPrinter,
  3719. LPWSTR pFormName
  3720. )
  3721. {
  3722. BOOL ReturnValue;
  3723. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3724. VALIDATEW32HANDLE( pSpool );
  3725. SYNCRPCHANDLE( pSpool );
  3726. if (pSpool->Type == SJ_WIN32HANDLE) {
  3727. RpcTryExcept {
  3728. if (ReturnValue = RpcDeleteForm(pSpool->RpcHandle, pFormName)) {
  3729. SetLastError(ReturnValue);
  3730. ReturnValue = FALSE;
  3731. } else
  3732. ReturnValue = TRUE;
  3733. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3734. SetLastError(RpcExceptionCode());
  3735. ReturnValue = FALSE;;
  3736. } RpcEndExcept
  3737. } else {
  3738. SetLastError(ERROR_INVALID_FUNCTION);
  3739. ReturnValue = FALSE;
  3740. }
  3741. //
  3742. // Make sure Forms Cache is consistent
  3743. //
  3744. if ( ReturnValue ) {
  3745. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3746. }
  3747. return ReturnValue;
  3748. }
  3749. BOOL
  3750. RemoteGetForm(
  3751. HANDLE hPrinter,
  3752. LPWSTR pFormName,
  3753. DWORD Level,
  3754. LPBYTE pForm,
  3755. DWORD cbBuf,
  3756. LPDWORD pcbNeeded
  3757. )
  3758. {
  3759. BOOL ReturnValue = FALSE;
  3760. FieldInfo *pFieldInfo;
  3761. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3762. SIZE_T cbStruct;
  3763. DWORD cReturned = 1;
  3764. VALIDATEW32HANDLE( pSpool );
  3765. SYNCRPCHANDLE( pSpool );
  3766. if (pSpool->Type == SJ_WIN32HANDLE) {
  3767. switch (Level) {
  3768. case 1:
  3769. pFieldInfo = FormInfo1Fields;
  3770. cbStruct = sizeof(FORM_INFO_1);
  3771. break;
  3772. default:
  3773. SetLastError(ERROR_INVALID_LEVEL);
  3774. return FALSE;
  3775. }
  3776. if (pForm)
  3777. memset(pForm, 0, cbBuf);
  3778. RpcTryExcept {
  3779. if (ReturnValue = RpcGetForm(pSpool->RpcHandle, pFormName, Level, pForm, cbBuf,
  3780. pcbNeeded) ) {
  3781. ReturnValue = UpdateBufferSize(pFieldInfo,
  3782. cbStruct,
  3783. pcbNeeded,
  3784. cbBuf,
  3785. ReturnValue,
  3786. &cReturned);
  3787. SetLastError(ReturnValue);
  3788. ReturnValue = FALSE;
  3789. } else {
  3790. ReturnValue = TRUE;
  3791. if (pForm) {
  3792. ReturnValue = MarshallUpStructure(pForm, pFieldInfo, cbStruct, RPC_CALL);
  3793. }
  3794. }
  3795. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3796. SetLastError(RpcExceptionCode());
  3797. ReturnValue = FALSE;
  3798. } RpcEndExcept
  3799. } else {
  3800. SetLastError(ERROR_INVALID_FUNCTION);
  3801. ReturnValue = FALSE;
  3802. }
  3803. return ReturnValue;
  3804. }
  3805. BOOL
  3806. SetForm(
  3807. HANDLE hPrinter,
  3808. LPWSTR pFormName,
  3809. DWORD Level,
  3810. LPBYTE pForm
  3811. )
  3812. {
  3813. BOOL ReturnValue;
  3814. GENERIC_CONTAINER FormContainer;
  3815. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3816. VALIDATEW32HANDLE( pSpool );
  3817. SYNCRPCHANDLE( pSpool );
  3818. if (pSpool->Type == SJ_WIN32HANDLE) {
  3819. FormContainer.Level = Level;
  3820. FormContainer.pData = pForm;
  3821. RpcTryExcept {
  3822. if (ReturnValue = RpcSetForm(pSpool->RpcHandle, pFormName,
  3823. (PFORM_CONTAINER)&FormContainer)) {
  3824. SetLastError(ReturnValue);
  3825. ReturnValue = FALSE;
  3826. } else
  3827. ReturnValue = TRUE;
  3828. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3829. SetLastError(RpcExceptionCode());
  3830. ReturnValue = FALSE;;
  3831. } RpcEndExcept
  3832. } else {
  3833. SetLastError(ERROR_INVALID_FUNCTION);
  3834. ReturnValue = FALSE;
  3835. }
  3836. //
  3837. // Make sure Forms Cache is consistent
  3838. //
  3839. if ( ReturnValue ) {
  3840. ConsistencyCheckCache(pSpool, kCheckPnPPolicy);
  3841. }
  3842. return ReturnValue;
  3843. }
  3844. BOOL
  3845. RemoteEnumForms(
  3846. HANDLE hPrinter,
  3847. DWORD Level,
  3848. LPBYTE pForm,
  3849. DWORD cbBuf,
  3850. LPDWORD pcbNeeded,
  3851. LPDWORD pcReturned
  3852. )
  3853. {
  3854. DWORD ReturnValue, cbStruct;
  3855. FieldInfo *pFieldInfo;
  3856. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  3857. VALIDATEW32HANDLE( pSpool );
  3858. SYNCRPCHANDLE( pSpool );
  3859. if (pSpool->Type == SJ_WIN32HANDLE) {
  3860. switch (Level) {
  3861. case 1:
  3862. pFieldInfo = FormInfo1Fields;
  3863. cbStruct = sizeof(FORM_INFO_1);
  3864. break;
  3865. default:
  3866. SetLastError(ERROR_INVALID_LEVEL);
  3867. return FALSE;
  3868. }
  3869. RpcTryExcept {
  3870. if (pForm)
  3871. memset(pForm, 0, cbBuf);
  3872. if (ReturnValue = RpcEnumForms(pSpool->RpcHandle, Level,
  3873. pForm, cbBuf,
  3874. pcbNeeded, pcReturned) ,
  3875. ReturnValue = UpdateBufferSize(pFieldInfo,
  3876. cbStruct,
  3877. pcbNeeded,
  3878. cbBuf,
  3879. ReturnValue,
  3880. pcReturned)) {
  3881. SetLastError(ReturnValue);
  3882. ReturnValue = FALSE;
  3883. } else {
  3884. ReturnValue = TRUE;
  3885. if (pForm) {
  3886. if(! MarshallUpStructuresArray(pForm, *pcReturned, pFieldInfo,
  3887. cbStruct, RPC_CALL) ) {
  3888. return FALSE;
  3889. }
  3890. }
  3891. }
  3892. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3893. SetLastError(RpcExceptionCode());
  3894. ReturnValue = FALSE;;
  3895. } RpcEndExcept
  3896. } else {
  3897. SetLastError(ERROR_INVALID_FUNCTION);
  3898. ReturnValue = FALSE;
  3899. }
  3900. return (BOOL)ReturnValue;
  3901. }
  3902. BOOL
  3903. RemoteEnumPorts(
  3904. LPWSTR pName,
  3905. DWORD Level,
  3906. LPBYTE pPort,
  3907. DWORD cbBuf,
  3908. LPDWORD pcbNeeded,
  3909. LPDWORD pcReturned
  3910. )
  3911. {
  3912. DWORD ReturnValue, cbStruct;
  3913. FieldInfo *pFieldInfo;
  3914. *pcReturned = 0;
  3915. *pcbNeeded = 0;
  3916. if (MyName(pName))
  3917. return LMEnumPorts(pName, Level, pPort, cbBuf, pcbNeeded, pcReturned);
  3918. if (MyUNCName(pName)) {
  3919. SetLastError(ERROR_INVALID_NAME);
  3920. return FALSE;
  3921. }
  3922. switch (Level) {
  3923. case 1:
  3924. pFieldInfo = PortInfo1Fields;
  3925. cbStruct = sizeof(PORT_INFO_1);
  3926. break;
  3927. case 2:
  3928. pFieldInfo = PortInfo2Fields;
  3929. cbStruct = sizeof(PORT_INFO_2);
  3930. break;
  3931. default:
  3932. SetLastError(ERROR_INVALID_LEVEL);
  3933. return FALSE;
  3934. }
  3935. RpcTryExcept {
  3936. if (pPort)
  3937. memset(pPort, 0, cbBuf);
  3938. if ( (ReturnValue = RpcValidate()) ||
  3939. (ReturnValue = RpcEnumPorts(pName, Level, pPort,
  3940. cbBuf, pcbNeeded,
  3941. pcReturned ) ,
  3942. ReturnValue = UpdateBufferSize(pFieldInfo,
  3943. cbStruct,
  3944. pcbNeeded,
  3945. cbBuf,
  3946. ReturnValue,
  3947. pcReturned)) ) {
  3948. SetLastError(ReturnValue);
  3949. ReturnValue = FALSE;
  3950. } else {
  3951. ReturnValue = TRUE;
  3952. if (pPort) {
  3953. if(! MarshallUpStructuresArray( pPort, *pcReturned, pFieldInfo,
  3954. cbStruct, RPC_CALL) ) {
  3955. return FALSE;
  3956. }
  3957. }
  3958. }
  3959. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  3960. SetLastError(RpcExceptionCode());
  3961. ReturnValue = FALSE;
  3962. } RpcEndExcept
  3963. return (BOOL) ReturnValue;
  3964. }
  3965. BOOL
  3966. EnumMonitors(
  3967. LPWSTR pName,
  3968. DWORD Level,
  3969. LPBYTE pMonitor,
  3970. DWORD cbBuf,
  3971. LPDWORD pcbNeeded,
  3972. LPDWORD pcReturned
  3973. )
  3974. {
  3975. DWORD ReturnValue, cbStruct;
  3976. FieldInfo *pFieldInfo;
  3977. *pcReturned = 0;
  3978. *pcbNeeded = 0;
  3979. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  3980. SetLastError(ERROR_INVALID_NAME);
  3981. return FALSE;
  3982. }
  3983. switch (Level) {
  3984. case 1:
  3985. pFieldInfo = MonitorInfo1Fields;
  3986. cbStruct = sizeof(MONITOR_INFO_1);
  3987. break;
  3988. case 2:
  3989. pFieldInfo = MonitorInfo2Fields;
  3990. cbStruct = sizeof(MONITOR_INFO_2);
  3991. break;
  3992. default:
  3993. SetLastError(ERROR_INVALID_LEVEL);
  3994. return FALSE;
  3995. }
  3996. RpcTryExcept {
  3997. if (pMonitor)
  3998. memset(pMonitor, 0, cbBuf);
  3999. if ( (ReturnValue = RpcValidate()) ||
  4000. (ReturnValue = RpcEnumMonitors(pName, Level, pMonitor, cbBuf,
  4001. pcbNeeded, pcReturned) ,
  4002. ReturnValue = UpdateBufferSize(pFieldInfo,
  4003. cbStruct,
  4004. pcbNeeded,
  4005. cbBuf,
  4006. ReturnValue,
  4007. pcReturned)) ) {
  4008. SetLastError(ReturnValue);
  4009. ReturnValue = FALSE;
  4010. } else {
  4011. ReturnValue = TRUE;
  4012. if (pMonitor) {
  4013. if(! MarshallUpStructuresArray( pMonitor, *pcReturned, pFieldInfo,
  4014. cbStruct, RPC_CALL) ) {
  4015. return FALSE;
  4016. }
  4017. }
  4018. }
  4019. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4020. SetLastError(RpcExceptionCode());
  4021. ReturnValue = FALSE;
  4022. } RpcEndExcept
  4023. return (BOOL) ReturnValue;
  4024. }
  4025. BOOL
  4026. RemoteAddPort(
  4027. LPWSTR pName,
  4028. HWND hWnd,
  4029. LPWSTR pMonitorName
  4030. )
  4031. {
  4032. if (MyName(pName) || (VALIDATE_NAME(pName) && !MyUNCName(pName))) {
  4033. SetLastError(ERROR_NOT_SUPPORTED);
  4034. return FALSE;
  4035. }
  4036. SetLastError(ERROR_INVALID_NAME);
  4037. return FALSE;
  4038. }
  4039. BOOL
  4040. RemoteConfigurePort(
  4041. LPWSTR pName,
  4042. HWND hWnd,
  4043. LPWSTR pPortName
  4044. )
  4045. {
  4046. if (MyName(pName) || (VALIDATE_NAME(pName) && !MyUNCName(pName))) {
  4047. SetLastError(ERROR_NOT_SUPPORTED);
  4048. return FALSE;
  4049. }
  4050. SetLastError(ERROR_INVALID_NAME);
  4051. return FALSE;
  4052. }
  4053. BOOL
  4054. RemoteDeletePort(
  4055. LPWSTR pName,
  4056. HWND hWnd,
  4057. LPWSTR pPortName
  4058. )
  4059. {
  4060. if (MyName(pName))
  4061. return LMDeletePort(pName, hWnd, pPortName);
  4062. if (MyName(pName) || (VALIDATE_NAME(pName) && !MyUNCName(pName))) {
  4063. SetLastError(ERROR_NOT_SUPPORTED);
  4064. return FALSE;
  4065. }
  4066. SetLastError(ERROR_INVALID_NAME);
  4067. return FALSE;
  4068. }
  4069. HANDLE
  4070. CreatePrinterIC(
  4071. HANDLE hPrinter,
  4072. LPDEVMODE pDevMode
  4073. )
  4074. {
  4075. HANDLE ReturnValue;
  4076. DWORD Error;
  4077. DEVMODE_CONTAINER DevModeContainer;
  4078. HANDLE hGdi;
  4079. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  4080. VALIDATEW32HANDLE( pSpool );
  4081. SYNCRPCHANDLE( pSpool );
  4082. if (pSpool->Type == SJ_WIN32HANDLE) {
  4083. if (pDevMode)
  4084. DevModeContainer.cbBuf = pDevMode->dmSize + pDevMode->dmDriverExtra;
  4085. else
  4086. DevModeContainer.cbBuf = 0;
  4087. DevModeContainer.pDevMode = (LPBYTE)pDevMode;
  4088. RpcTryExcept {
  4089. if (Error = RpcCreatePrinterIC(pSpool->RpcHandle, &hGdi,
  4090. &DevModeContainer)) {
  4091. SetLastError(Error);
  4092. ReturnValue = FALSE;
  4093. } else
  4094. ReturnValue = hGdi;
  4095. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4096. SetLastError(RpcExceptionCode());
  4097. ReturnValue = FALSE;
  4098. } RpcEndExcept
  4099. } else {
  4100. SetLastError(ERROR_INVALID_FUNCTION);
  4101. ReturnValue = FALSE;
  4102. }
  4103. return ReturnValue;
  4104. }
  4105. BOOL
  4106. PlayGdiScriptOnPrinterIC(
  4107. HANDLE hPrinterIC,
  4108. LPBYTE pIn,
  4109. DWORD cIn,
  4110. LPBYTE pOut,
  4111. DWORD cOut,
  4112. DWORD ul
  4113. )
  4114. {
  4115. BOOL ReturnValue;
  4116. RpcTryExcept {
  4117. if ( (ReturnValue = RpcValidate()) ||
  4118. (ReturnValue = RpcPlayGdiScriptOnPrinterIC(hPrinterIC, pIn, cIn,
  4119. pOut, cOut, ul)) ) {
  4120. SetLastError(ReturnValue);
  4121. ReturnValue = FALSE;
  4122. } else
  4123. ReturnValue = TRUE;
  4124. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4125. SetLastError(RpcExceptionCode());
  4126. ReturnValue = FALSE;
  4127. } RpcEndExcept
  4128. return ReturnValue;
  4129. }
  4130. BOOL
  4131. DeletePrinterIC(
  4132. HANDLE hPrinterIC
  4133. )
  4134. {
  4135. BOOL ReturnValue;
  4136. RpcTryExcept {
  4137. if ( (ReturnValue = RpcValidate()) ||
  4138. (ReturnValue = RpcDeletePrinterIC(&hPrinterIC)) ) {
  4139. SetLastError(ReturnValue);
  4140. ReturnValue = FALSE;
  4141. } else
  4142. ReturnValue = TRUE;
  4143. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4144. SetLastError(RpcExceptionCode());
  4145. ReturnValue = FALSE;
  4146. } RpcEndExcept
  4147. return ReturnValue;
  4148. }
  4149. DWORD
  4150. PrinterMessageBox(
  4151. HANDLE hPrinter,
  4152. DWORD Error,
  4153. HWND hWnd,
  4154. LPWSTR pText,
  4155. LPWSTR pCaption,
  4156. DWORD dwType
  4157. )
  4158. {
  4159. SetLastError(ERROR_NOT_SUPPORTED);
  4160. return FALSE;
  4161. }
  4162. BOOL
  4163. AddMonitorW(
  4164. LPWSTR pName,
  4165. DWORD Level,
  4166. LPBYTE pMonitorInfo
  4167. )
  4168. {
  4169. BOOL ReturnValue;
  4170. MONITOR_CONTAINER MonitorContainer;
  4171. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  4172. SetLastError(ERROR_INVALID_NAME);
  4173. return FALSE;
  4174. }
  4175. switch (Level) {
  4176. case 2:
  4177. break;
  4178. default:
  4179. SetLastError(ERROR_INVALID_LEVEL);
  4180. return FALSE;
  4181. }
  4182. MonitorContainer.Level = Level;
  4183. MonitorContainer.MonitorInfo.pMonitorInfo2 = (MONITOR_INFO_2 *)pMonitorInfo;
  4184. RpcTryExcept {
  4185. if ( (ReturnValue = RpcValidate()) ||
  4186. (ReturnValue = RpcAddMonitor(pName, &MonitorContainer)) ) {
  4187. SetLastError(ReturnValue);
  4188. ReturnValue = FALSE;
  4189. } else
  4190. ReturnValue = TRUE;
  4191. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4192. SetLastError(RpcExceptionCode());
  4193. ReturnValue = FALSE;
  4194. } RpcEndExcept
  4195. return ReturnValue;
  4196. }
  4197. BOOL
  4198. DeleteMonitorW(
  4199. LPWSTR pName,
  4200. LPWSTR pEnvironment,
  4201. LPWSTR pMonitorName
  4202. )
  4203. {
  4204. BOOL ReturnValue;
  4205. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  4206. SetLastError(ERROR_INVALID_NAME);
  4207. return FALSE;
  4208. }
  4209. RpcTryExcept {
  4210. if ( (ReturnValue = RpcValidate()) ||
  4211. (ReturnValue = RpcDeleteMonitor(pName,
  4212. pEnvironment,
  4213. pMonitorName)) ) {
  4214. SetLastError(ReturnValue);
  4215. ReturnValue = FALSE;
  4216. } else
  4217. ReturnValue = TRUE;
  4218. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4219. SetLastError(RpcExceptionCode());
  4220. ReturnValue = FALSE;
  4221. } RpcEndExcept
  4222. return ReturnValue;
  4223. }
  4224. BOOL
  4225. DeletePrintProcessorW(
  4226. LPWSTR pName,
  4227. LPWSTR pEnvironment,
  4228. LPWSTR pPrintProcessorName
  4229. )
  4230. {
  4231. BOOL ReturnValue;
  4232. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  4233. SetLastError(ERROR_INVALID_NAME);
  4234. return FALSE;
  4235. }
  4236. RpcTryExcept {
  4237. if ( (ReturnValue = RpcValidate()) ||
  4238. (ReturnValue = RpcDeletePrintProcessor(pName,
  4239. pEnvironment,
  4240. pPrintProcessorName)) ) {
  4241. SetLastError(ReturnValue);
  4242. ReturnValue = FALSE;
  4243. } else
  4244. ReturnValue = TRUE;
  4245. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4246. SetLastError(RpcExceptionCode());
  4247. ReturnValue = FALSE;
  4248. } RpcEndExcept
  4249. return ReturnValue;
  4250. }
  4251. BOOL
  4252. GetPrintSystemVersion(
  4253. )
  4254. {
  4255. DWORD Status;
  4256. HKEY hKey;
  4257. DWORD cbData;
  4258. Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegistryRoot, 0,
  4259. KEY_READ, &hKey);
  4260. if (Status != ERROR_SUCCESS) {
  4261. DBGMSG(DBG_ERROR, ("Cannot determine Print System Version Number\n"));
  4262. return FALSE;
  4263. }
  4264. cbData = sizeof (cThisMinorVersion);
  4265. if (RegQueryValueEx(hKey, szMinorVersion, NULL, NULL,
  4266. (LPBYTE)&cThisMinorVersion, &cbData)
  4267. == ERROR_SUCCESS) {
  4268. DBGMSG(DBG_TRACE, ("This Minor Version - %d\n", cThisMinorVersion));
  4269. }
  4270. RegCloseKey(hKey);
  4271. return TRUE;
  4272. }
  4273. BOOL
  4274. RemoteAddPortEx(
  4275. LPWSTR pName,
  4276. DWORD Level,
  4277. LPBYTE lpBuffer,
  4278. LPWSTR lpMonitorName
  4279. )
  4280. {
  4281. DWORD ReturnValue;
  4282. PORT_CONTAINER PortContainer;
  4283. PORT_VAR_CONTAINER PortVarContainer;
  4284. PPORT_INFO_FF pPortInfoFF;
  4285. PPORT_INFO_1 pPortInfo1;
  4286. if ( !VALIDATE_NAME(pName) || MyUNCName(pName) ) {
  4287. SetLastError(ERROR_INVALID_NAME);
  4288. return FALSE;
  4289. }
  4290. if (!lpBuffer) {
  4291. SetLastError(ERROR_INVALID_PARAMETER);
  4292. return FALSE;
  4293. }
  4294. switch (Level) {
  4295. case (DWORD)-1:
  4296. pPortInfoFF = (PPORT_INFO_FF)lpBuffer;
  4297. PortContainer.Level = Level;
  4298. PortContainer.PortInfo.pPortInfoFF = (PPORT_INFO_FF)pPortInfoFF;
  4299. PortVarContainer.cbMonitorData = pPortInfoFF->cbMonitorData;
  4300. PortVarContainer.pMonitorData = pPortInfoFF->pMonitorData;
  4301. break;
  4302. case 1:
  4303. pPortInfo1 = (PPORT_INFO_1)lpBuffer;
  4304. PortContainer.Level = Level;
  4305. PortContainer.PortInfo.pPortInfo1 = (PPORT_INFO_1)pPortInfo1;
  4306. PortVarContainer.cbMonitorData = 0;
  4307. PortVarContainer.pMonitorData = NULL;
  4308. break;
  4309. default:
  4310. SetLastError(ERROR_INVALID_LEVEL);
  4311. return FALSE;
  4312. }
  4313. RpcTryExcept {
  4314. if ( (ReturnValue = RpcValidate()) ||
  4315. (ReturnValue = RpcAddPortEx(pName, (LPPORT_CONTAINER)&PortContainer,
  4316. (LPPORT_VAR_CONTAINER)&PortVarContainer,
  4317. lpMonitorName)) ) {
  4318. SetLastError(ReturnValue);
  4319. return FALSE;
  4320. } else {
  4321. return TRUE ;
  4322. }
  4323. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4324. SetLastError(RpcExceptionCode());
  4325. return FALSE;
  4326. } RpcEndExcept
  4327. }
  4328. BOOL
  4329. SetPort(
  4330. LPWSTR pszName,
  4331. LPWSTR pszPortName,
  4332. DWORD dwLevel,
  4333. LPBYTE pPortInfo
  4334. )
  4335. {
  4336. BOOL ReturnValue = FALSE;
  4337. PORT_CONTAINER PortContainer;
  4338. if ( !VALIDATE_NAME(pszName) || MyUNCName(pszName) ) {
  4339. SetLastError(ERROR_INVALID_NAME);
  4340. return FALSE;
  4341. }
  4342. switch (dwLevel) {
  4343. case 3:
  4344. PortContainer.Level = dwLevel;
  4345. PortContainer.PortInfo.pPortInfo3 = (LPPORT_INFO_3W) pPortInfo;
  4346. break;
  4347. default:
  4348. SetLastError(ERROR_INVALID_LEVEL);
  4349. goto Cleanup;
  4350. }
  4351. RpcTryExcept {
  4352. if ( (ReturnValue = RpcValidate()) ||
  4353. (ReturnValue = RpcSetPort(pszName, pszPortName, &PortContainer)) ) {
  4354. SetLastError(ReturnValue);
  4355. ReturnValue = FALSE;
  4356. } else {
  4357. ReturnValue = TRUE;
  4358. }
  4359. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4360. SetLastError(RpcExceptionCode());
  4361. ReturnValue = FALSE;
  4362. } RpcEndExcept
  4363. Cleanup:
  4364. return ReturnValue;
  4365. }
  4366. BOOL
  4367. RemoteXcvData(
  4368. HANDLE hXcv,
  4369. PCWSTR pszDataName,
  4370. PBYTE pInputData,
  4371. DWORD cbInputData,
  4372. PBYTE pOutputData,
  4373. DWORD cbOutputData,
  4374. PDWORD pcbOutputNeeded,
  4375. PDWORD pdwStatus
  4376. )
  4377. {
  4378. DWORD ReturnValue = 0;
  4379. PWSPOOL pSpool = (PWSPOOL)hXcv;
  4380. VALIDATEW32HANDLE( pSpool );
  4381. SYNCRPCHANDLE( pSpool );
  4382. if (pSpool->Type == SJ_WIN32HANDLE) {
  4383. //
  4384. // The user should be able to pass in NULL for buffer, and
  4385. // 0 for size. However, the RPC interface specifies a ref pointer,
  4386. // so we must pass in a valid pointer. Pass in a pointer to
  4387. // a dummy pointer.
  4388. //
  4389. if (!pInputData && !cbInputData)
  4390. pInputData = (PBYTE) &ReturnValue;
  4391. if (!pOutputData && !cbOutputData)
  4392. pOutputData = (PBYTE) &ReturnValue;
  4393. RpcTryExcept {
  4394. if (ReturnValue = RpcXcvData( pSpool->RpcHandle,
  4395. pszDataName,
  4396. pInputData,
  4397. cbInputData,
  4398. pOutputData,
  4399. cbOutputData,
  4400. pcbOutputNeeded,
  4401. pdwStatus)) {
  4402. SetLastError(ReturnValue);
  4403. ReturnValue = FALSE;
  4404. } else {
  4405. ReturnValue = TRUE;
  4406. }
  4407. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) {
  4408. SetLastError(RpcExceptionCode());
  4409. ReturnValue = FALSE;
  4410. } RpcEndExcept
  4411. if (!ReturnValue)
  4412. DBGMSG(DBG_TRACE,("XcvData Exception: %d\n", GetLastError()));
  4413. } else {
  4414. SetLastError( ERROR_NOT_SUPPORTED );
  4415. ReturnValue = FALSE;
  4416. }
  4417. return ReturnValue;
  4418. }
  4419. DWORD
  4420. RemoteSendRecvBidiData(
  4421. IN HANDLE hPrinter,
  4422. IN LPCTSTR pAction,
  4423. IN PBIDI_REQUEST_CONTAINER pReqData,
  4424. OUT PBIDI_RESPONSE_CONTAINER* ppResData
  4425. )
  4426. {
  4427. DWORD dwRet = ERROR_SUCCESS;
  4428. PWSPOOL pSpool = (PWSPOOL)hPrinter;
  4429. VALIDATEW32HANDLE( pSpool );
  4430. SYNCRPCHANDLE( pSpool );
  4431. if (pSpool->Type == SJ_WIN32HANDLE)
  4432. {
  4433. RpcTryExcept
  4434. {
  4435. dwRet = RpcSendRecvBidiData(pSpool->RpcHandle,
  4436. pAction,
  4437. (PRPC_BIDI_REQUEST_CONTAINER)pReqData,
  4438. (PRPC_BIDI_RESPONSE_CONTAINER*)ppResData);
  4439. }
  4440. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  4441. {
  4442. dwRet = RpcExceptionCode();
  4443. }
  4444. RpcEndExcept
  4445. }
  4446. else
  4447. {
  4448. dwRet = ERROR_NOT_SUPPORTED;
  4449. }
  4450. return (dwRet);
  4451. }