Windows NT 4.0 source code leak
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.

904 lines
24 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990-1994 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. threads.c
  6. Abstract:
  7. Create a whole lot of threads that don't do much.
  8. Author:
  9. Environment:
  10. User Mode -Win32
  11. Revision History:
  12. --*/
  13. #include "printman.h"
  14. HANDLE ThreadMessageRead;
  15. HANDLE ThreadMessageWritten;
  16. MSG ThreadMessage;
  17. WCHAR szPrintersConnections[] = L"Printers\\Connections";
  18. BOOL APIENTRY
  19. NetworkPasswordDialog(
  20. HWND hWnd,
  21. UINT usMsg,
  22. WPARAM wParam,
  23. LONG lParam);
  24. #if DBG
  25. VOID DbgProtected( DWORD OwningThread )
  26. {
  27. DWORD CurrentThreadId;
  28. CurrentThreadId = GetCurrentThreadId( );
  29. if( OwningThread != CurrentThreadId )
  30. {
  31. DBGMSG( DBG_ERROR, ( "ERROR: Not in mutex: Current thread: %d; owning thread: %d\n",
  32. CurrentThreadId, OwningThread ) );
  33. }
  34. }
  35. VOID DbgNotProtected( DWORD OwningThread )
  36. {
  37. DWORD CurrentThreadId;
  38. CurrentThreadId = GetCurrentThreadId( );
  39. if( OwningThread == CurrentThreadId )
  40. {
  41. DBGMSG( DBG_ERROR, ( "ERROR: In mutex\n" ) );
  42. }
  43. }
  44. #endif /* DBG */
  45. /* Returns the time in milliseconds to the nearest hour.
  46. */
  47. DWORD GetTime( )
  48. {
  49. SYSTEMTIME SystemTime;
  50. GetSystemTime( &SystemTime );
  51. DBGMSG( DBG_TRACE, ( "Time: %02d:%02d:%02d\n",
  52. SystemTime.wHour,
  53. SystemTime.wMinute,
  54. SystemTime.wSecond ) );
  55. return( ( 1000
  56. * ( ( 60 * SystemTime.wMinute )
  57. + SystemTime.wSecond ) )
  58. + SystemTime.wMilliseconds );
  59. }
  60. /* NOTE:
  61. *
  62. * This thread should not call any User APIs, since this causes a second thread
  63. * to be spun off.
  64. */
  65. VOID RefreshThread( PMDIWIN_INFO pInfo )
  66. {
  67. DWORD WaitFlags;
  68. DWORD Changes;
  69. BOOL RefreshOK;
  70. DWORD ThisTime = 0; /* Time in milliseconds */
  71. DWORD LastTime = 0;
  72. DWORD Error;
  73. HANDLE hPrinterTmp;
  74. BOOL bPolling = FALSE;
  75. BOOL bQuit;
  76. DBGMSG( DBG_TRACE, ( "Thread %d created\n", GetCurrentThreadId( ) ) );
  77. //
  78. // Init the thread if necessary
  79. //
  80. if (pInfo->pfnInitThread)
  81. (*pInfo->pfnInitThread)( pInfo->pContext );
  82. #ifdef SEP_WAITHANDLE
  83. //
  84. // Necessary since provider may not allow non-serialized
  85. // RPC handle calls.
  86. //
  87. // We can remove this when FindFirstPrinterChange comes online.
  88. // -- there may be a backward compatiblity problem though, with
  89. // 528 printman on a daytona machine.
  90. //
  91. ReopenPrinter(pInfo->pContext,
  92. pInfo->WindowType,
  93. TRUE);
  94. #endif
  95. DBG_OUT_PROTECTED_DATA( pInfo );
  96. ENTER_PROTECTED_DATA( pInfo );
  97. //
  98. // We have tried loading once, so we are no longer loading.
  99. //
  100. pInfo->Status = 0;
  101. //
  102. // Caller passed in flags specifying what changes to wait for.
  103. //
  104. WaitFlags = pInfo->WaitFlags;
  105. Changes = WaitFlags;
  106. while( pInfo->Alive )
  107. {
  108. DBGMSG( DBG_THREADS, ( "pInfo->Alive == %d\n", pInfo->Alive ) );
  109. ThisTime = GetTime( );
  110. /* Don't update more than a couple of times per second,
  111. * so as not to overload the network unnecessarily:
  112. */
  113. if( ( ThisTime - LastTime ) < 500 )
  114. {
  115. DBGMSG( DBG_TRACE, ( "Sleeping %d ms\n", ( ThisTime - LastTime ) ) );
  116. Sleep( ThisTime - LastTime );
  117. }
  118. LastTime = ThisTime;
  119. /* Enumerate a buffer big enough to page up once ...
  120. */
  121. *pInfo->pFirstEnumObj = (DWORD)max( 0, (int)pInfo->TopIndex - (int)pInfo->cNumLines );
  122. RefreshOK = FALSE;
  123. Error = NO_ERROR;
  124. DBGMSG( DBG_TRACE | DBG_THREADS,
  125. ( "Calling refresh (1): *phWaitObject == %x\n",
  126. *pInfo->phWaitObject ) );
  127. if( pInfo->pfnRefresh )
  128. RefreshOK = (*pInfo->pfnRefresh)( pInfo->pContext, &Changes );
  129. DBGMSG( DBG_TRACE | DBG_THREADS,
  130. ( "Refresh returned: *phWaitObject == %x\n",
  131. *pInfo->phWaitObject ) );
  132. if( !RefreshOK )
  133. {
  134. //
  135. // The refresh failed, either because the handle
  136. // is invalid, or the refresh failed.
  137. // Go to polling mode by default.
  138. //
  139. // !! POLICY !!
  140. //
  141. // We may wish to change this, since we keep threads around
  142. // for "dead" printers.
  143. //
  144. bPolling = TRUE;
  145. Error = GetLastError();
  146. }
  147. else
  148. {
  149. //
  150. // The refresh may succeed, even though the handle is invalid.
  151. // In this case, we enter polling mode.
  152. //
  153. if (!*pInfo->phWaitObject)
  154. {
  155. Error = ERROR_INVALID_PARAMETER;
  156. bPolling = TRUE;
  157. }
  158. else
  159. {
  160. bPolling = FALSE;
  161. }
  162. }
  163. //
  164. // Check if printer was deleted.
  165. //
  166. bQuit = (pInfo->pfnCheckQuit) ?
  167. (*pInfo->pfnCheckQuit)( pInfo->pContext ) :
  168. FALSE;
  169. LEAVE_PROTECTED_DATA(pInfo);
  170. DBG_OUT_PROTECTED_DATA( pInfo);
  171. if (bQuit) {
  172. SEND_THREAD_MESSAGE(hwndFrame,
  173. WM_DELETE_PRINTER,
  174. 0,
  175. pInfo->hwnd);
  176. }
  177. WaitForSingleObject( pInfo->RefreshSignal, INFINITE );
  178. pInfo->Changes = Changes;
  179. DBGMSG( DBG_THREADS, ( "Sending thread message\n" ) );
  180. SEND_THREAD_MESSAGE( pInfo->hwnd, WM_UPDATE_LIST, pInfo, 0 );
  181. if( !bPolling )
  182. {
  183. hPrinterTmp = *pInfo->phWaitObject;
  184. if (hPrinterTmp) {
  185. Changes = WaitForPrinterChange( hPrinterTmp, WaitFlags );
  186. DBGMSG( DBG_THREADS, ( "WaitForPrinterChange returned %08x\n", Changes ) );
  187. if( Changes == 0 )
  188. Error = GetLastError( );
  189. } else {
  190. Error = ERROR_INVALID_HANDLE;
  191. }
  192. }
  193. if( pInfo->Alive && Error )
  194. {
  195. if( Changes == 0 )
  196. {
  197. DBGMSG( DBG_WARNING, ( "WaitForPrinterChange failed: Error %d\n", Error ) );
  198. }
  199. else if( !bPolling )
  200. {
  201. DBGMSG( DBG_WARNING, ( "Refresh failed: Error %d\n", Error ) );
  202. }
  203. /* If we're polling, wait a minute, then try to reopen the printer:
  204. */
  205. DBGMSG( DBG_TRACE, ( "Polling\n" ) );
  206. Sleep( 60000 );
  207. //
  208. // !! LATER !!
  209. //
  210. // If the handles get refreshed (by F5), we still close and
  211. // reopen them. Not too crucial now, since the server shouldn't
  212. // go down often, but something to look at later.
  213. //
  214. Changes = WaitFlags;
  215. /* If access was denied, there's not much we can do:
  216. */
  217. if( Error != ERROR_ACCESS_DENIED )
  218. {
  219. ENTER_PROTECTED_DATA( pInfo );
  220. /* Try to reopen the printer or server.
  221. * The point is that the server might have been rebooted,
  222. * in which case our handles will be invalid.
  223. */
  224. if( *pInfo->phWaitObject )
  225. {
  226. /* Call refresh. This is more or less bound to fail,
  227. * but will deallocate any information we have:
  228. */
  229. DBGMSG( DBG_TRACE, ( "Calling refresh (2): *phWaitObject == %x\n",
  230. *pInfo->phWaitObject ) );
  231. RefreshOK = (*pInfo->pfnRefresh)( pInfo->pContext, &WaitFlags );
  232. DBGMSG( DBG_TRACE, ( "Calling Close Printer: *phWaitObject == %x\n",
  233. *pInfo->phWaitObject ) );
  234. ClosePrinter(*pInfo->phWaitObject);
  235. *pInfo->phWaitObject = NULL;
  236. }
  237. //
  238. // Only do this if we are still alive. If we are not,
  239. // then the window is closing and we might as well
  240. // forget the open.
  241. //
  242. if (pInfo->Alive) {
  243. #ifdef SEP_WAITHANDLE
  244. //
  245. // Must reopen up if not same handle.
  246. //
  247. if (*pInfo->phMain) {
  248. ClosePrinter(*pInfo->phMain);
  249. *pInfo->phMain = NULL;
  250. }
  251. LEAVE_PROTECTED_DATA( pInfo );
  252. ReopenPrinter(pInfo->pContext,
  253. pInfo->WindowType,
  254. FALSE);
  255. if (!*pInfo->phWaitObject) {
  256. ReopenPrinter(pInfo->pContext,
  257. pInfo->WindowType,
  258. TRUE);
  259. }
  260. #else
  261. LEAVE_PROTECTED_DATA( pInfo );
  262. ReopenPrinter(pInfo->pContext,
  263. pInfo->WindowType,
  264. FALSE);
  265. #endif
  266. } else {
  267. LEAVE_PROTECTED_DATA( pInfo );
  268. }
  269. }
  270. DBGMSG( DBG_WARNING, ( "Refresh error: Printer thread entering/continuing polling mode\n" ) );
  271. bPolling = TRUE;
  272. }
  273. DBG_OUT_PROTECTED_DATA( pInfo );
  274. ENTER_PROTECTED_DATA( pInfo );
  275. }
  276. #ifdef SEP_WAITHANDLE
  277. if (*pInfo->phWaitObject) {
  278. ClosePrinter(*pInfo->phWaitObject);
  279. *pInfo->phWaitObject = NULL;
  280. }
  281. #endif
  282. LEAVE_PROTECTED_DATA( pInfo );
  283. DBG_OUT_PROTECTED_DATA( pInfo );
  284. DestroyMDIWinInfo( pInfo );
  285. DBGMSG( DBG_TRACE, ( "Thread %d exiting\n", GetCurrentThreadId( ) ) );
  286. ExitThread( 0 );
  287. return;
  288. }
  289. //
  290. // Must be callable from either worker or main thread
  291. // (Caller must synchronize, however)
  292. //
  293. DWORD
  294. OpenThreadObject(
  295. LPWSTR pszName,
  296. PHANDLE phPrinter,
  297. PDWORD pdwAccessGranted,
  298. DWORD WindowType)
  299. {
  300. DWORD dwReturn = ERROR_SUCCESS;
  301. switch(WindowType)
  302. {
  303. case MDIWIN_SERVER:
  304. {
  305. PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL,
  306. SERVER_ALL_ACCESS };
  307. DBGMSG( DBG_TRACE, ( "Attempting to open %s\n",
  308. pszName));
  309. if( OpenPrinter( pszName, phPrinter, &PrinterDefaults ) )
  310. {
  311. *pdwAccessGranted = SERVER_ALL_ACCESS;
  312. DBGMSG( DBG_TRACE, ( "Open was successful\n" ) );
  313. }
  314. else
  315. {
  316. DBGMSG( DBG_TRACE, ( "Open failed: Error %d\n", GetLastError( ) ) );
  317. *phPrinter = NULL;
  318. dwReturn = GetLastError();
  319. }
  320. break;
  321. }
  322. default:
  323. {
  324. DBGMSG( DBG_TRACE, ( "Attempting to open %s\n",
  325. pszName ) );
  326. if( OpenPrinterForSpecifiedAccess( pszName,
  327. phPrinter,
  328. PRINTER_ACCESS_HIGHEST_PERMITTED,
  329. pdwAccessGranted))
  330. {
  331. DBGMSG( DBG_TRACE, ( "Open was successful\n" ) );
  332. }
  333. else
  334. {
  335. DBGMSG( DBG_TRACE, ( "Open failed: Error %d\n", GetLastError( ) ) );
  336. *phPrinter = NULL;
  337. dwReturn = GetLastError();
  338. }
  339. break;
  340. }
  341. }
  342. return dwReturn;
  343. }
  344. VOID
  345. InitQueueThread(
  346. PVOID pContext)
  347. {
  348. PQUEUE pQueue = (PQUEUE)pContext;
  349. HWND hwndActive;
  350. ReopenPrinter(pQueue,
  351. MDIWIN_PRINTER,
  352. FALSE);
  353. if ( pQueue->Error )
  354. {
  355. hwndActive = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0L);
  356. if (!hwndActive)
  357. hwndActive = hwndFrame;
  358. if ( pQueue->Error == ERROR_INVALID_PASSWORD )
  359. {
  360. HANDLE hPrinter;
  361. //
  362. // !! LATER !!
  363. //
  364. // Move out all these USER calls to prevent extra threads
  365. // and keep good syncing.
  366. //
  367. hPrinter = (HANDLE)DialogBoxParam( hInst,
  368. MAKEINTRESOURCE( DLG_NETWORK_PASSWORD ),
  369. hwndActive,
  370. (DLGPROC)NetworkPasswordDialog,
  371. (LPARAM)pQueue->pPrinterName );
  372. //
  373. // If we have a valid printer handle, a network connection must have
  374. // been added. Make a note of this, so that we can delete it
  375. // if something fails later on.
  376. //
  377. if( hPrinter && ( hPrinter != (HANDLE)-1 ) )
  378. {
  379. ClosePrinter( hPrinter );
  380. ReopenPrinter(pQueue,
  381. MDIWIN_PRINTER,
  382. FALSE );
  383. }
  384. }
  385. }
  386. if ( pQueue->Error )
  387. {
  388. SEND_THREAD_MESSAGE( hwndFrame,
  389. WM_THREAD_ERROR,
  390. pQueue->Error,
  391. pQueue->pMDIWinInfo );
  392. }
  393. }
  394. BOOL
  395. CheckQuitQueue(
  396. PVOID pContext)
  397. {
  398. PQUEUE pQueue = (PQUEUE)pContext;
  399. if (pQueue->pPrinter &&
  400. (pQueue->pPrinter->Status & PRINTER_STATUS_PENDING_DELETION) &&
  401. !pQueue->cJobs) {
  402. return TRUE;
  403. }
  404. return FALSE;
  405. }
  406. /* InitServerWindowThread
  407. *
  408. * The routine called by EnumRegistryKeys with the name of each key found.
  409. * This is called only when Print Manager starts up.
  410. *
  411. * Parameters:
  412. *
  413. * hwnd - The handle of the MDI parent window.
  414. *
  415. * pName - The server name for which the window is to be created.
  416. *
  417. *
  418. * Returns:
  419. *
  420. * VOID
  421. *
  422. * Notes:
  423. *
  424. * ->hServer == NULL -> haven't tried opening it yet.
  425. * == (HANDLE)-1 -> tried but got ERROR_ACCESS_DENIED
  426. * else -> valid, use it.
  427. *
  428. */
  429. VOID
  430. InitServerWindowThread(
  431. PVOID pContext)
  432. {
  433. PRINTER_DEFAULTS PrinterDefaults = { NULL, NULL,
  434. SERVER_ALL_ACCESS };
  435. PSERVER_CONTEXT pServerContext = (PSERVER_CONTEXT)pContext;
  436. HANDLE hServer = NULL;
  437. LPPRINTER_INFO_2 pPrinters = NULL;
  438. DWORD cbPrinters = 0;
  439. DWORD cReturned;
  440. DWORD Error = 0;
  441. BOOL OK;
  442. DWORD dwFirstError = 0;
  443. //
  444. // Check if the server was opened successfully in the server viewer
  445. // dialog. If not, we need to do it now.
  446. //
  447. if (!pServerContext->hServer)
  448. {
  449. //
  450. // Haven't tried to open it yet, do so now.
  451. //
  452. if (!OpenPrinter( pServerContext->pServerName,
  453. &hServer,
  454. &PrinterDefaults))
  455. {
  456. dwFirstError = GetLastError( );
  457. }
  458. else
  459. {
  460. pServerContext->AccessGranted = SERVER_ALL_ACCESS;
  461. pServerContext->hServer = hServer;
  462. }
  463. }
  464. else if (pServerContext->hServer == (HANDLE)-1)
  465. {
  466. //
  467. // Tried to open it earlier, but failed with ERROR_ACCESS_DENIED.
  468. //
  469. dwFirstError = ERROR_ACCESS_DENIED;
  470. pServerContext->hServer = NULL;
  471. }
  472. else
  473. {
  474. //
  475. // Tried and succeeded!
  476. //
  477. pServerContext->AccessGranted = SERVER_ALL_ACCESS;
  478. }
  479. OK = ENUM_PRINTERS( PRINTER_ENUM_NAME,
  480. pServerContext->pServerName,
  481. 2,
  482. pPrinters,
  483. cbPrinters,
  484. &cbPrinters,
  485. &cReturned );
  486. if( OK )
  487. {
  488. #if 0
  489. //
  490. // This is disabled because it is annoying.
  491. //
  492. if (dwFirstError)
  493. {
  494. //
  495. // We can use the Customer bit of the win32 error code
  496. // to indicate to ourselves that we weren't able to open
  497. // a handle to the server, but we were able to enumerate.
  498. //
  499. // The error will be something like:
  500. //
  501. // "Error opening server for auto-refresh mode."
  502. //
  503. // Remember to clear this bit!
  504. //
  505. dwFirstError |= (1 << 29);
  506. SEND_THREAD_MESSAGE( hwndFrame,
  507. WM_THREAD_ERROR,
  508. dwFirstError,
  509. pServerContext->pMDIWinInfo );
  510. }
  511. #endif
  512. pServerContext->pPrinters = pPrinters;
  513. pServerContext->cPrinters = cReturned;
  514. pServerContext->cbPrinters = cbPrinters;
  515. pServerContext->pSelPrinter = &pPrinters[0]; /* Select the first printer */
  516. }
  517. else
  518. {
  519. //
  520. // Only use this new error code if the first call failed.
  521. //
  522. pServerContext->Error = dwFirstError ?
  523. dwFirstError :
  524. GetLastError( );
  525. SEND_THREAD_MESSAGE( hwndFrame,
  526. WM_THREAD_ERROR,
  527. pServerContext->Error,
  528. pServerContext->pMDIWinInfo );
  529. if( pPrinters )
  530. FreeSplMem( pPrinters );
  531. }
  532. return;
  533. }
  534. /* This guy just hangs around in case a printer gets created on the local
  535. * machine. If this happens, it posts a message to the Print Manager
  536. * frame-window procedure.
  537. * This is because the printer might have been created remotely, in which
  538. * case we won't know about it.
  539. *
  540. */
  541. void
  542. LocalServerThread(
  543. HANDLE hServer)
  544. {
  545. DWORD Changes;
  546. DWORD dwWait;
  547. HKEY hKeyCreate;
  548. DWORD Error;
  549. HKEY hKey = NULL;
  550. HANDLE ahEvent[2] = { NULL, NULL };
  551. ahEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL);
  552. ahEvent[1] = FindFirstPrinterChangeNotification(hServer,
  553. PRINTER_CHANGE_ADD_PRINTER,
  554. 0,
  555. NULL);
  556. if (!ahEvent[0] || !ahEvent[1])
  557. goto Fail;
  558. //
  559. // Since no one was smart enough to put this into the default hives,
  560. // we need to create the key kere. We can't put it in the default
  561. // hives now because we'll break people with floating profiles.
  562. //
  563. if (!RegCreateKey(HKEY_CURRENT_USER,
  564. L"Printers",
  565. &hKeyCreate)) {
  566. RegCloseKey(hKeyCreate);
  567. if (!RegCreateKey(HKEY_CURRENT_USER,
  568. szPrintersConnections,
  569. &hKeyCreate)) {
  570. RegCloseKey(hKeyCreate);
  571. }
  572. }
  573. if (RegOpenKey(HKEY_CURRENT_USER,
  574. szPrintersConnections,
  575. &hKey)) {
  576. goto Fail;
  577. }
  578. if (RegNotifyChangeKeyValue(hKey,
  579. TRUE,
  580. REG_NOTIFY_CHANGE_NAME,
  581. ahEvent[0],
  582. TRUE))
  583. goto Fail;
  584. while (TRUE) {
  585. dwWait = WaitForMultipleObjects(2, ahEvent, FALSE, INFINITE);
  586. if (dwWait == WAIT_FAILED) {
  587. DBGMSG(DBG_WARNING, ("Printman ServerThread: Wait failed: %d %d\n",
  588. dwWait, GetLastError()));
  589. goto Fail;
  590. }
  591. //
  592. // Sleep an arbitrary value: this allows multiple notifications
  593. // to collapse into one.
  594. //
  595. Sleep(1500);
  596. switch (dwWait) {
  597. case WAIT_OBJECT_0:
  598. Error = RegNotifyChangeKeyValue(hKey,
  599. TRUE,
  600. REG_NOTIFY_CHANGE_NAME,
  601. ahEvent[0],
  602. TRUE);
  603. if (Error) {
  604. DBGMSG(DBG_ERROR, ("Printman ServerThread: RegNotifyChangeKeyValue failed: %d\n",
  605. Error));
  606. goto Fail;
  607. }
  608. break;
  609. case WAIT_OBJECT_0+1:
  610. if (!FindNextPrinterChangeNotification(ahEvent[1],
  611. &Changes,
  612. 0,
  613. NULL)) {
  614. DBGMSG(DBG_WARNING, ("Printman ServerThread: FNPCN failed: %d\n",
  615. GetLastError()));
  616. goto Fail;
  617. }
  618. break;
  619. default:
  620. DBGMSG(DBG_ERROR, ("Printman ServerThread: Wait failed: %d %d\n",
  621. dwWait, GetLastError()));
  622. goto Fail;
  623. }
  624. DBGMSG( DBG_THREADS, ( "Notification on server returned %08x\n", Changes ) );
  625. SEND_THREAD_MESSAGE(hwndFrame,
  626. WM_PRINTER_ADDED,
  627. dwWait-WAIT_OBJECT_0,
  628. 0);
  629. }
  630. Fail:
  631. if (ahEvent[0])
  632. CloseHandle(ahEvent[0]);
  633. if (ahEvent[1])
  634. FindClosePrinterChangeNotification(ahEvent[1]);
  635. if (hKey)
  636. RegCloseKey(hKey);
  637. DBGMSG( DBG_TRACE, ( "Local server thread %d exiting\n", GetCurrentThreadId( ) ) );
  638. ExitThread( 0 );
  639. return;
  640. }
  641. VOID
  642. ReopenPrinter(
  643. PVOID pContext,
  644. DWORD WindowType,
  645. BOOL bWait)
  646. {
  647. HANDLE hPrinterNew;
  648. DWORD dwAccessGrantedNew;
  649. DWORD dwErrorNew;
  650. WCHAR szPrinterName[MAX_PATH];
  651. PHANDLE phPrinterTarg;
  652. #define pQueue ((PQUEUE)pContext)
  653. #define pServerContext ((PSERVER_CONTEXT)pContext)
  654. if (WindowType != MDIWIN_SERVER) {
  655. ENTER_PROTECTED_DATA( pQueue->pMDIWinInfo );
  656. wcscpy(szPrinterName, pQueue->pPrinterName);
  657. LEAVE_PROTECTED_DATA( pQueue->pMDIWinInfo);
  658. dwErrorNew = OpenThreadObject(szPrinterName,
  659. &hPrinterNew,
  660. &dwAccessGrantedNew,
  661. WindowType);
  662. ENTER_PROTECTED_DATA( pQueue->pMDIWinInfo );
  663. #ifdef SEP_WAITHANDLE
  664. phPrinterTarg = bWait ?
  665. &pQueue->hPrinterWait :
  666. &pQueue->hPrinter;
  667. #else
  668. phPrinterTarg = &pQueue->hPrinter;
  669. #endif
  670. if ( !*phPrinterTarg ) {
  671. *phPrinterTarg = hPrinterNew;
  672. if (!bWait) {
  673. pQueue->AccessGranted = dwAccessGrantedNew;
  674. pQueue->Error = dwErrorNew;
  675. }
  676. LEAVE_PROTECTED_DATA( pQueue->pMDIWinInfo);
  677. } else {
  678. LEAVE_PROTECTED_DATA( pQueue->pMDIWinInfo);
  679. //
  680. // Close the handle if necessary.
  681. //
  682. if (hPrinterNew)
  683. ClosePrinter(hPrinterNew);
  684. }
  685. } else {
  686. ENTER_PROTECTED_DATA( pServerContext->pMDIWinInfo );
  687. wcscpy(szPrinterName, pServerContext->pServerName);
  688. LEAVE_PROTECTED_DATA( pServerContext->pMDIWinInfo);
  689. dwErrorNew = OpenThreadObject(szPrinterName,
  690. &hPrinterNew,
  691. &dwAccessGrantedNew,
  692. WindowType);
  693. ENTER_PROTECTED_DATA( pServerContext->pMDIWinInfo );
  694. #ifdef SEP_WAITHANDLE
  695. phPrinterTarg = bWait ?
  696. &pServerContext->hServerWait :
  697. &pServerContext->hServer;
  698. #else
  699. phPrinterTarg = &pServerContext->hServer;
  700. #endif
  701. if ( !*phPrinterTarg ) {
  702. *phPrinterTarg = hPrinterNew;
  703. if (!bWait) {
  704. pServerContext->AccessGranted = dwAccessGrantedNew;
  705. pServerContext->Error = dwErrorNew;
  706. }
  707. LEAVE_PROTECTED_DATA( pServerContext->pMDIWinInfo);
  708. } else {
  709. LEAVE_PROTECTED_DATA( pServerContext->pMDIWinInfo);
  710. //
  711. // Close the handle if necessary.
  712. //
  713. if (hPrinterNew)
  714. ClosePrinter(hPrinterNew);
  715. }
  716. }
  717. #undef pQueue
  718. #undef pServerContext
  719. }