Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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