Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1138 lines
31 KiB

  1. // oleInst.cpp : Implementation of COleInstall
  2. #include "stdafx.h"
  3. #include "oleprn.h"
  4. #include "oleInst.h"
  5. #include "printer.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. // COleInstall
  8. const TCHAR * const g_szWindowClassName = TEXT("Ole Install Control");
  9. const DWORD cdwSucessExitCode = 0xFFFFFFFF;
  10. typedef DWORD (*pfnPrintUIEntry)(HWND,HINSTANCE,LPCTSTR,UINT);
  11. #ifdef WIN9X
  12. const TCHAR g_szSplDir9X [] = TEXT("\\spool\\printers\\");
  13. #endif
  14. OleInstallData::OleInstallData (
  15. LPTSTR pPrinterUncName,
  16. LPTSTR pPrinterUrl,
  17. HWND hwnd,
  18. BOOL bRPC)
  19. :m_lCount (2),
  20. m_pPrinterUncName (NULL),
  21. m_pPrinterUrl (NULL),
  22. m_pszTempWebpnpFile (NULL),
  23. m_hwnd (hwnd),
  24. m_bValid (FALSE),
  25. m_bRPC(bRPC)
  26. {
  27. if (AssignString (m_pPrinterUncName, pPrinterUncName)
  28. && AssignString (m_pPrinterUrl, pPrinterUrl))
  29. m_bValid = TRUE;
  30. }
  31. OleInstallData::~OleInstallData ()
  32. {
  33. if (m_pszTempWebpnpFile) {
  34. DeleteFile (m_pszTempWebpnpFile);
  35. LocalFree (m_pszTempWebpnpFile);
  36. }
  37. LocalFree (m_pPrinterUncName);
  38. LocalFree (m_pPrinterUrl);
  39. }
  40. COleInstall::COleInstall()
  41. : m_hwnd (NULL),
  42. m_pPrinterUncName (NULL),
  43. m_pPrinterUrl (NULL),
  44. m_pThreadData (NULL)
  45. {
  46. DisplayUIonDisallow(FALSE); // We don't want IE displaying UI.
  47. }
  48. COleInstall::~COleInstall()
  49. {
  50. if(m_hwnd)
  51. {
  52. if (m_pThreadData) {
  53. m_pThreadData->m_hwnd = NULL;
  54. }
  55. ::DestroyWindow(m_hwnd);
  56. m_hwnd = NULL;
  57. }
  58. LocalFree (m_pPrinterUncName);
  59. LocalFree (m_pPrinterUrl);
  60. if (m_pThreadData) {
  61. if (InterlockedDecrement (& (m_pThreadData->m_lCount)) == 0) {
  62. delete (m_pThreadData);
  63. }
  64. }
  65. }
  66. HRESULT
  67. COleInstall::OnDraw(
  68. ATL_DRAWINFO& di)
  69. {
  70. return S_OK;
  71. }
  72. BOOL
  73. COleInstall::UpdateUI (
  74. OleInstallData *pData,
  75. UINT message,
  76. WPARAM wParam)
  77. {
  78. BOOL bRet = FALSE;
  79. if (pData->m_hwnd) {
  80. ::SendMessage (pData->m_hwnd, message, wParam, NULL);
  81. bRet = TRUE;
  82. }
  83. return bRet;
  84. }
  85. BOOL
  86. COleInstall::UpdateProgress (
  87. OleInstallData *pData,
  88. DWORD dwProgress)
  89. {
  90. return UpdateUI (pData, WM_ON_PROGRESS, dwProgress);
  91. }
  92. BOOL
  93. COleInstall::UpdateError (
  94. OleInstallData *pData)
  95. {
  96. return UpdateUI (pData, WM_INSTALL_ERROR, GetLastError ());
  97. }
  98. HRESULT
  99. COleInstall::InitWin (BOOL bRPC)
  100. {
  101. HRESULT hr = E_FAIL;
  102. DWORD dwThreadId;
  103. HANDLE hThread = NULL;
  104. WNDCLASS wc;
  105. // Create Window Class
  106. if (!::GetClassInfo(_Module.GetModuleInstance(), g_szWindowClassName, &wc))
  107. {
  108. wc.style = 0;
  109. wc.lpfnWndProc = COleInstall::WndProc;
  110. wc.cbClsExtra = 0;
  111. wc.cbWndExtra = 0;
  112. wc.hInstance = _Module.GetModuleInstance();
  113. wc.hIcon = NULL;
  114. wc.hCursor = NULL;
  115. wc.hbrBackground = NULL;
  116. wc.lpszMenuName = NULL;
  117. wc.lpszClassName = g_szWindowClassName;
  118. if (!RegisterClass(&wc)) {
  119. return hr;
  120. }
  121. }
  122. m_hwnd = CreateWindow(g_szWindowClassName,
  123. NULL, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
  124. CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
  125. _Module.GetModuleInstance(), this);
  126. if (m_hwnd) {
  127. m_pThreadData = new OleInstallData (m_pPrinterUncName,
  128. m_pPrinterUrl,
  129. m_hwnd,
  130. bRPC);
  131. if (m_pThreadData && m_pThreadData->m_bValid) {
  132. if (hThread = ::CreateThread (NULL,
  133. 0,
  134. (LPTHREAD_START_ROUTINE) &COleInstall::WorkingThread,
  135. m_pThreadData,
  136. 0,
  137. &dwThreadId)) {
  138. CloseHandle (hThread);
  139. hr = S_OK;
  140. }
  141. }
  142. }
  143. return hr;
  144. }
  145. BOOL
  146. COleInstall::WorkingThread(
  147. void * param)
  148. {
  149. OleInstallData * pThreadData = (OleInstallData *) param;
  150. BOOL bRet = FALSE;
  151. if (pThreadData) {
  152. bRet = StartInstall (pThreadData);
  153. }
  154. return bRet;
  155. }
  156. BOOL
  157. COleInstall::StartInstall(
  158. OleInstallData *pThreadData)
  159. {
  160. HANDLE hServer = NULL;
  161. PRINTER_DEFAULTS pd = {NULL, NULL, SERVER_ALL_ACCESS};
  162. BOOL bRet = FALSE;
  163. #ifndef WIN9X
  164. CPrinter Printer;
  165. HANDLE hPrinter;
  166. PPRINTER_INFO_2 pPrinterInfo2 = NULL;
  167. LPTSTR lpszPrinterURL = NULL;
  168. #endif
  169. // Working thread
  170. if (!UpdateProgress (pThreadData, 0))
  171. goto Cleanup;
  172. #ifndef WIN9X
  173. // Step one, check if the magic registry is set (force http connection)
  174. if (!IsHttpPreferred () && pThreadData->m_bRPC) {
  175. // Check RPC connections at first
  176. if (::AddPrinterConnection( (BSTR)pThreadData->m_pPrinterUncName)) {
  177. UpdateProgress (pThreadData, 50);
  178. if (CheckAndSetDefaultPrinter ()) {
  179. UpdateProgress (pThreadData, 100);
  180. bRet = TRUE;
  181. }
  182. goto Cleanup;
  183. }
  184. }
  185. // AddPrinterConnection failed. Since http installation always requires
  186. // administrator privilidge, We have to do a access check before we
  187. // try to down load the cab file
  188. if (!OpenPrinter (NULL, &hServer, &pd)) {
  189. // If this fails and it is because we do not have access, we should send a better error
  190. // message to the local user telling them that the do not have the ability to create
  191. // printers on the local machine
  192. if (GetLastError() == ERROR_ACCESS_DENIED) {
  193. SetLastError(ERROR_LOCAL_PRINTER_ACCESS);
  194. }
  195. goto Cleanup;
  196. }
  197. else
  198. ClosePrinter (hServer);
  199. //
  200. // Try the local CAB installation instead of downloading the cab, etc.
  201. // Need admin privaleges.
  202. //
  203. if( NULL != (lpszPrinterURL = RemoveURLVars( pThreadData->m_pPrinterUrl )) &&
  204. Printer.Open( lpszPrinterURL, &hPrinter ) ) {
  205. LPTSTR lpszInfName = NULL;
  206. LPTSTR lpszPrinterName = NULL;
  207. pPrinterInfo2 = Printer.GetPrinterInfo2();
  208. if ((pPrinterInfo2 == NULL) && (GetLastError () == ERROR_ACCESS_DENIED))
  209. {
  210. if (!ConfigurePort( NULL, pThreadData->m_hwnd, lpszPrinterURL ))
  211. {
  212. bRet = FALSE;
  213. goto Cleanup;
  214. }
  215. pPrinterInfo2 = Printer.GetPrinterInfo2();
  216. }
  217. if( (NULL != pPrinterInfo2) &&
  218. (NULL != (lpszInfName = GetNTPrint())) &&
  219. (NULL != (lpszPrinterName = CreatePrinterBaseName(lpszPrinterURL, pPrinterInfo2->pPrinterName))) ) {
  220. LPTSTR lpszCmd = NULL;
  221. DWORD dwLength = 0;
  222. TCHAR szCmdString[] = _TEXT("/if /x /b \"%s\" /r \"%s\" /m \"%s\" /n \"%s\" /f %s /q");
  223. HMODULE hPrintUI = NULL;
  224. pfnPrintUIEntry PrintUIEntry;
  225. dwLength = lstrlen( szCmdString ) +
  226. lstrlen( lpszPrinterName ) +
  227. lstrlen( pPrinterInfo2->pPortName ) +
  228. lstrlen( pPrinterInfo2->pDriverName ) +
  229. lstrlen( pThreadData->m_pPrinterUncName ) +
  230. lstrlen( lpszInfName ) + 1;
  231. if( (lpszCmd = (LPTSTR)LocalAlloc( LPTR, dwLength*sizeof(TCHAR) )) &&
  232. (hPrintUI = LoadLibraryFromSystem32( TEXT("printui.dll") )) ) {
  233. _sntprintf( lpszCmd, dwLength, szCmdString, lpszPrinterName,
  234. pPrinterInfo2->pPortName, pPrinterInfo2->pDriverName,
  235. pThreadData->m_pPrinterUncName, lpszInfName );
  236. if( PrintUIEntry = (pfnPrintUIEntry)GetProcAddress(hPrintUI, "PrintUIEntryW") ) {
  237. if( ERROR_SUCCESS == (*PrintUIEntry)( NULL,
  238. 0,
  239. lpszCmd,
  240. SW_HIDE ) ) {
  241. UpdateProgress (pThreadData, 50);
  242. if (CheckAndSetDefaultPrinter ()) {
  243. UpdateProgress (pThreadData, 100);
  244. bRet = TRUE;
  245. }
  246. }
  247. }
  248. }
  249. if( lpszCmd )
  250. LocalFree( lpszCmd );
  251. if( hPrintUI )
  252. FreeLibrary( hPrintUI );
  253. }
  254. if( lpszInfName )
  255. LocalFree( lpszInfName );
  256. if( lpszPrinterName )
  257. LocalFree( lpszPrinterName );
  258. }
  259. if( lpszPrinterURL )
  260. LocalFree(lpszPrinterURL);
  261. if( bRet )
  262. goto Cleanup;
  263. #endif
  264. if (UpdateProgress (pThreadData, 25)) {
  265. // Step two, somehow, RPC connection failed, try to install http printer
  266. if (GetHttpPrinterFile (pThreadData, pThreadData->m_pPrinterUrl)) {
  267. if (UpdateProgress (pThreadData, 60)) {
  268. if (InstallHttpPrinter (pThreadData)) {
  269. if (UpdateProgress (pThreadData, 90)) {
  270. if (CheckAndSetDefaultPrinter ()) {
  271. UpdateProgress (pThreadData, 100);
  272. bRet = TRUE;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. }
  279. Cleanup:
  280. if (!bRet) {
  281. UpdateError (pThreadData);
  282. }
  283. // Cleanup the ThreadData
  284. if (InterlockedDecrement (& (pThreadData->m_lCount)) == 0) {
  285. delete (pThreadData);
  286. }
  287. return bRet;
  288. }
  289. LRESULT CALLBACK
  290. COleInstall::WndProc(
  291. HWND hWnd,
  292. UINT uMsg,
  293. WPARAM wParam,
  294. LPARAM lParam)
  295. {
  296. COleInstall *ptc = (COleInstall *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
  297. switch(uMsg)
  298. {
  299. case WM_CREATE:
  300. {
  301. ptc = (COleInstall *)((CREATESTRUCT *)lParam)->lpCreateParams;
  302. ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (UINT_PTR) ptc);
  303. }
  304. break;
  305. case WM_ON_PROGRESS:
  306. if (ptc)
  307. ptc->Fire_OnProgress ((long) wParam);
  308. break;
  309. case WM_INSTALL_ERROR:
  310. if (ptc)
  311. ptc->Fire_InstallError ((long) wParam);
  312. break;
  313. case WM_DESTROY:
  314. // ignore late messages
  315. if(ptc)
  316. {
  317. MSG msg;
  318. while(PeekMessage(&msg, hWnd, WM_ON_PROGRESS, WM_INSTALL_ERROR, PM_REMOVE));
  319. ::SetWindowLongPtr (hWnd, GWLP_USERDATA, NULL);
  320. }
  321. break;
  322. default:
  323. return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
  324. }
  325. return 0;
  326. }
  327. STDMETHODIMP
  328. COleInstall::InstallPrinter(
  329. BSTR pbstrUncName,
  330. BSTR pbstrUrl)
  331. {
  332. HRESULT hr;
  333. if (!pbstrUncName || !pbstrUrl)
  334. return E_POINTER;
  335. // When using an ATL string conversion Macro, spedcify the USES_CONVERSION macro
  336. // to avoid compiler error
  337. USES_CONVERSION;
  338. if (AssignString (m_pPrinterUncName, OLE2T (pbstrUncName)) &&
  339. AssignString (m_pPrinterUrl, OLE2T (pbstrUrl))) {
  340. BOOL bRPC;
  341. LPTSTR lpszDisplay = NULL;
  342. hr = CanIInstallRPC( m_pPrinterUncName, m_pPrinterUrl ); // Determine whether to use RPC or HTTP.
  343. if (FAILED(hr))
  344. return hr;
  345. bRPC = HRESULT_CODE(hr) == S_OK; // If it is S_FALSE, then we must use WebPnP
  346. lpszDisplay = RemoveURLVars(bRPC ? m_pPrinterUncName : m_pPrinterUrl);
  347. if (lpszDisplay == NULL)
  348. return E_OUTOFMEMORY;
  349. hr = PromptUser(bRPC ? AddPrinterConnection : AddWebPrinterConnection, lpszDisplay);
  350. LocalFree(lpszDisplay);
  351. if (hr == S_OK)
  352. return InitWin(bRPC);
  353. else if (hr == S_FALSE)
  354. return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
  355. else
  356. return FAILED(hr) ? hr : E_FAIL;
  357. }
  358. else
  359. return E_FAIL;
  360. }
  361. STDMETHODIMP
  362. COleInstall::OpenPrintersFolder()
  363. {
  364. HRESULT hr;
  365. if (FAILED(hr = CanIOpenPrintersFolder()))
  366. return hr; // We allow JAVALOW/JAVAMEDIUM to open the printers folder
  367. LPITEMIDLIST pidl = NULL;
  368. HWND hwnd = GetDesktopWindow ();
  369. hr = SHGetSpecialFolderLocation( hwnd, CSIDL_PRINTERS, &pidl );
  370. if (SUCCEEDED(hr))
  371. {
  372. SHELLEXECUTEINFO ei = {0};
  373. ei.cbSize = sizeof(SHELLEXECUTEINFO);
  374. ei.fMask = SEE_MASK_IDLIST;
  375. ei.hwnd = hwnd;
  376. ei.lpIDList = (LPVOID)pidl;
  377. ei.nShow = SW_SHOWNORMAL;
  378. if (!ShellExecuteEx(&ei))
  379. hr = E_FAIL;
  380. }
  381. return hr;
  382. }
  383. /////////////////////////////////////////////////////////////////////////////
  384. // Private Member Functions
  385. /////////////////////////////////////////////////////////////////////////////
  386. BOOL
  387. COleInstall::SyncExecute(
  388. LPTSTR pszFileName,
  389. int nShow)
  390. {
  391. SHELLEXECUTEINFO shellExeInfo;
  392. DWORD dwErrorCode;
  393. BOOL bRet = FALSE;
  394. HWND hWndForeground, hWndParent, hWndOwner, hWndLastPopup;
  395. //
  396. // We need to get the window handle of the current process to pass to the installation code,
  397. // otherwise any UI (e.g. driver signing pop ups) won't have focus of the IE frame.
  398. //
  399. // get the foreground window first
  400. hWndForeground = ::GetForegroundWindow();
  401. // climb up to the top parent in case it's a child window...
  402. hWndParent = hWndForeground;
  403. while( hWndParent = ::GetParent(hWndParent) ) {
  404. hWndForeground = hWndParent;
  405. }
  406. // get the owner in case the top parent is owned
  407. hWndOwner = ::GetWindow(::GetParent(hWndForeground), GW_OWNER);
  408. if( hWndOwner ) {
  409. hWndForeground = hWndOwner;
  410. }
  411. // get the last popup of the owner window
  412. hWndLastPopup = ::GetLastActivePopup(hWndForeground);
  413. ZeroMemory (&shellExeInfo, sizeof (SHELLEXECUTEINFO));
  414. shellExeInfo.cbSize = sizeof (SHELLEXECUTEINFO);
  415. shellExeInfo.hwnd = hWndLastPopup;
  416. shellExeInfo.lpVerb = TEXT ("open");
  417. shellExeInfo.lpFile = pszFileName;
  418. shellExeInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  419. shellExeInfo.nShow = nShow;
  420. if (ShellExecuteEx (&shellExeInfo) &&
  421. (UINT_PTR) shellExeInfo.hInstApp > 32) {
  422. // Wait until it is done
  423. if (!WaitForSingleObject (shellExeInfo.hProcess , INFINITE) &&
  424. GetExitCodeProcess (shellExeInfo.hProcess, &dwErrorCode)) {
  425. if (dwErrorCode == cdwSucessExitCode) {
  426. bRet = TRUE;
  427. }
  428. else {
  429. if (!dwErrorCode) {
  430. // This means that wpnpinst was terminated abnormally
  431. // So we have to setup an customized error code here.
  432. dwErrorCode = ERROR_WPNPINST_TERMINATED;
  433. }
  434. SetLastError (dwErrorCode);
  435. }
  436. }
  437. }
  438. return bRet;
  439. }
  440. DWORD
  441. COleInstall::GetWebpnpFile(
  442. OleInstallData *pData,
  443. LPTSTR pszURL,
  444. LPTSTR *ppErrMsg)
  445. {
  446. HINTERNET hUrlWebpnp = NULL;
  447. HINTERNET hHandle = NULL;
  448. HANDLE hFile = INVALID_HANDLE_VALUE;
  449. DWORD dwSize = 0;
  450. DWORD dwWritten = 0;
  451. LPTSTR pszHeader = NULL;
  452. BOOL bRet;
  453. BOOL bRetry = TRUE;
  454. DWORD dwRet = RET_OTHER_ERROR;
  455. DWORD dwError = ERROR_SUCCESS;
  456. DWORD dwLastError;
  457. DWORD i;
  458. BYTE buf[FILEBUFSIZE];
  459. *ppErrMsg = NULL;
  460. if (! (hHandle = InternetOpen (TEXT ("Internet Add Printer"),
  461. INTERNET_OPEN_TYPE_PRECONFIG,
  462. NULL, NULL, 0)))
  463. goto Cleanup;
  464. for (i = 0; bRetry ; i++) {
  465. DWORD dwCode;
  466. DWORD dwBufSize = sizeof (DWORD);
  467. hUrlWebpnp = InternetOpenUrl (hHandle, pszURL, NULL, 0, 0, 0);
  468. if (!HttpQueryInfo(hUrlWebpnp,
  469. HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE,
  470. &dwCode,
  471. &dwBufSize,
  472. NULL))
  473. goto Cleanup;
  474. switch (dwCode) {
  475. case HTTP_STATUS_OK :
  476. bRetry = FALSE;
  477. break;
  478. case HTTP_STATUS_SERVER_ERROR :
  479. // Errors are returned by the server
  480. // Try to get the error string
  481. dwBufSize = 0;
  482. bRet = HttpQueryInfo(hUrlWebpnp,
  483. HTTP_QUERY_STATUS_TEXT,
  484. NULL,
  485. &dwBufSize,
  486. NULL);
  487. if (!bRet && GetLastError () == ERROR_INSUFFICIENT_BUFFER) {
  488. if (!(pszHeader = (LPTSTR) LocalAlloc( LPTR, dwBufSize)))
  489. goto Cleanup;
  490. *ppErrMsg = pszHeader;
  491. if (! HttpQueryInfo(hUrlWebpnp,
  492. HTTP_QUERY_STATUS_TEXT,
  493. pszHeader,
  494. &dwBufSize,
  495. NULL))
  496. goto Cleanup;
  497. dwRet = RET_SERVER_ERROR;
  498. goto Cleanup;
  499. }
  500. else
  501. goto Cleanup;
  502. break;
  503. case HTTP_STATUS_DENIED :
  504. case HTTP_STATUS_PROXY_AUTH_REQ :
  505. dwError = InternetErrorDlg(GetDesktopWindow(), hUrlWebpnp,
  506. hUrlWebpnp? ERROR_SUCCESS : GetLastError(),
  507. FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
  508. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
  509. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
  510. NULL);
  511. switch (dwError) {
  512. case ERROR_INTERNET_FORCE_RETRY:
  513. if (i >= MAX_INET_RETRY) {
  514. goto Cleanup;
  515. }
  516. break;
  517. case ERROR_SUCCESS:
  518. bRetry = FALSE;
  519. break;
  520. case ERROR_CANCELLED:
  521. default:
  522. goto Cleanup;
  523. }
  524. break;
  525. default:
  526. goto Cleanup;
  527. }
  528. }
  529. if (!UpdateProgress (pData, 35))
  530. goto Cleanup;
  531. if ( INVALID_HANDLE_VALUE ==
  532. (hFile = GetTempFile(TEXT (".webpnp"), &(pData->m_pszTempWebpnpFile))))
  533. goto Cleanup;
  534. dwSize = FILEBUFSIZE;
  535. while (dwSize == FILEBUFSIZE) {
  536. if (! InternetReadFile (hUrlWebpnp, (LPVOID)buf, FILEBUFSIZE, &dwSize)) {
  537. goto Cleanup;
  538. }
  539. if (! (pData->m_hwnd)) {
  540. goto Cleanup;
  541. }
  542. if (! WriteFile (hFile, buf, dwSize, &dwWritten, NULL)) {
  543. goto Cleanup;
  544. }
  545. }
  546. CloseHandle (hFile);
  547. hFile = INVALID_HANDLE_VALUE;
  548. dwRet = RET_SUCCESS;
  549. Cleanup:
  550. dwLastError = GetLastError ();
  551. if (hFile != INVALID_HANDLE_VALUE)
  552. CloseHandle (hFile);
  553. if (hUrlWebpnp)
  554. InternetCloseHandle (hUrlWebpnp);
  555. if (hHandle)
  556. InternetCloseHandle (hHandle);
  557. SetLastError (dwLastError);
  558. if (dwRet == RET_OTHER_ERROR && GetLastError () == ERROR_SUCCESS) {
  559. SetLastError (ERROR_ACCESS_DENIED);
  560. }
  561. return dwRet;
  562. }
  563. HANDLE
  564. COleInstall::GetTempFile(
  565. LPTSTR pExtension,
  566. LPTSTR * ppFileName)
  567. {
  568. #ifndef WIN9X
  569. HANDLE hServer = NULL;
  570. PRINTER_DEFAULTS prDefaults; // Used to test access rights to the printer
  571. DWORD dwType; // This is the type of the string
  572. #endif
  573. HANDLE hFile = INVALID_HANDLE_VALUE;
  574. LPTSTR pszTempDir = NULL;
  575. LPTSTR pszTempFname = NULL;
  576. DWORD dwTempLen; // This is the new size of the string
  577. DWORD i;
  578. DWORD dwTempSize; // This is the Size of the return String
  579. #ifndef WIN9X
  580. // First we want to open the local print server and ensure that we have access to it
  581. prDefaults.pDatatype = NULL;
  582. prDefaults.pDevMode = NULL;
  583. prDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;
  584. *ppFileName = NULL;
  585. // Open the local spooler to get a handle to it
  586. if (!OpenPrinter( NULL, &hServer, &prDefaults)) {
  587. hServer = NULL; // Open Printer returns NULL and not INVALID_HANDLE_VALUE for a failure
  588. goto Cleanup; // OpenPrinter will SetLastError to the reason why we couldn't open
  589. }
  590. // Get the size of the buffer we will need to copy the printer data
  591. if (ERROR_MORE_DATA !=
  592. GetPrinterData( hServer, SPLREG_DEFAULT_SPOOL_DIRECTORY, &dwType, NULL, 0, &dwTempSize)) {
  593. goto Cleanup;
  594. }
  595. // If it's something other than a simple string, set the error to a database error
  596. if (dwType != REG_SZ) {
  597. SetLastError(ERROR_BADDB);
  598. goto Cleanup;
  599. }
  600. // Allocate memory for the directory string, this might have to be for an unexpanded string
  601. // in which case we will allocate memory later and expand the environment strings into that
  602. if (! (pszTempDir = (LPTSTR) LocalAlloc( LPTR,sizeof (TCHAR) *
  603. (dwTempSize + MAXFILELEN + lstrlen (pExtension) + 1
  604. ))))
  605. goto Cleanup;
  606. if (ERROR_SUCCESS !=
  607. GetPrinterData( hServer, SPLREG_DEFAULT_SPOOL_DIRECTORY, &dwType, (LPBYTE)pszTempDir,
  608. dwTempSize, &dwTempLen))
  609. goto Cleanup; // For some reason we could not get the data
  610. ClosePrinter(hServer);
  611. pszTempFname = &pszTempDir[ lstrlen(pszTempDir) ];
  612. // GetPrinterData does not put a last \ on the path
  613. *pszTempFname++ = TEXT('\\');
  614. #else // We are in Win9X
  615. dwTempLen = ( dwTempSize = GetWindowsDirectory( NULL, 0 ) )
  616. + lstrlen( g_szSplDir9X ) + MAXFILELEN + lstrlen (pExtension);
  617. if (dwTempSize && (pszTempDir = (LPTSTR)LocalAlloc( LPTR, dwTempLen ))) {
  618. if (GetWindowsDirectory(pszTempDir,dwTempSize)) {
  619. lstrcat( pszTempDir , g_szSplDir9X );
  620. } else goto Cleanup;
  621. } else goto Cleanup;
  622. pszTempFname = &pszTempDir[ lstrlen(pszTempDir) ];
  623. #endif
  624. for (i = 0; i < MAXTRY; i++) {
  625. wsprintf(pszTempFname, TEXT("spl%d%s"), i, pExtension);
  626. hFile = CreateFile(pszTempDir,
  627. GENERIC_READ | GENERIC_WRITE,
  628. 0,
  629. NULL,
  630. CREATE_NEW,
  631. FILE_ATTRIBUTE_NORMAL,
  632. NULL);
  633. if (hFile && (hFile != INVALID_HANDLE_VALUE)) {
  634. break;
  635. }
  636. }
  637. if (i == MAXTRY) {
  638. // Return file not found error
  639. SetLastError (ERROR_PATH_NOT_FOUND);
  640. goto Cleanup;
  641. }
  642. *ppFileName = pszTempDir;
  643. return hFile;
  644. Cleanup:
  645. if (pszTempDir)
  646. LocalFree (pszTempDir);
  647. #ifdef WINNT32
  648. if (hServer != NULL)
  649. ClosePrinter(hServer);
  650. #endif
  651. return INVALID_HANDLE_VALUE;
  652. }
  653. BOOL
  654. COleInstall::IsHttpPreferred(void)
  655. {
  656. DWORD dwVal;
  657. DWORD dwType = REG_DWORD;
  658. DWORD dwSize = sizeof (DWORD);
  659. HKEY hHandle = NULL;
  660. BOOL bRet = FALSE;
  661. if (ERROR_SUCCESS != RegOpenKey (HKEY_CURRENT_USER,
  662. TEXT ("Printers\\Settings"),
  663. &hHandle))
  664. goto Cleanup;
  665. if (ERROR_SUCCESS == RegQueryValueEx (hHandle,
  666. TEXT ("PreferredConnection"),
  667. NULL,
  668. &dwType,
  669. (LPBYTE) &dwVal,
  670. &dwSize)) {
  671. bRet = (dwVal == 0) ? TRUE : FALSE;
  672. }
  673. Cleanup:
  674. if (hHandle) {
  675. RegCloseKey (hHandle);
  676. }
  677. return bRet;
  678. }
  679. BOOL
  680. COleInstall::GetHttpPrinterFile(
  681. OleInstallData *pData,
  682. LPTSTR pbstrURL)
  683. {
  684. LPTSTR pszErrMsg = NULL;
  685. BOOL bRet = FALSE;
  686. DWORD dwError;
  687. if (!pbstrURL) {
  688. return FALSE;
  689. }
  690. switch (GetWebpnpFile(pData, pbstrURL, &pszErrMsg)) {
  691. case RET_SUCCESS:
  692. bRet = TRUE;
  693. break;
  694. case RET_SERVER_ERROR:
  695. dwError = _ttol (pszErrMsg);
  696. if (dwError == 0) {
  697. // This is a server internal error
  698. dwError = ERROR_INTERNAL_SERVER;
  699. }
  700. SetLastError (dwError);
  701. break;
  702. case RET_OTHER_ERROR:
  703. default:
  704. break;
  705. }
  706. if (pszErrMsg) {
  707. LocalFree (pszErrMsg);
  708. }
  709. return bRet;
  710. }
  711. BOOL
  712. COleInstall::InstallHttpPrinter(
  713. OleInstallData *pData)
  714. {
  715. BOOL bRet = FALSE;
  716. if (SyncExecute(pData->m_pszTempWebpnpFile, SW_SHOWNORMAL))
  717. bRet = TRUE;
  718. return bRet;
  719. }
  720. BOOL
  721. COleInstall::CheckAndSetDefaultPrinter()
  722. {
  723. DWORD dwSize = 0;
  724. BOOL bRet = TRUE;
  725. #ifndef WIN9X
  726. if (!GetDefaultPrinterW (NULL, &dwSize)) {
  727. if (GetLastError() == ERROR_FILE_NOT_FOUND) {
  728. // No default printer is set
  729. // We pass a NULL to SetDefaultPrinter to set the first printer in the device list to
  730. // be the default one
  731. bRet = SetDefaultPrinter (NULL);
  732. }
  733. }
  734. #endif
  735. return bRet;
  736. }
  737. HRESULT COleInstall::CanIOpenPrintersFolder(void) {
  738. DWORD dwPolicy;
  739. HRESULT hr = GetActionPolicy(URLACTION_JAVA_PERMISSIONS, dwPolicy );
  740. if (SUCCEEDED(hr)) {
  741. hr = (dwPolicy == URLPOLICY_JAVA_MEDIUM ||
  742. dwPolicy == URLPOLICY_JAVA_LOW ||
  743. dwPolicy == URLPOLICY_ALLOW) ? S_OK : HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED);
  744. }
  745. if (FAILED(hr)) {
  746. hr = GetActionPolicy(URLACTION_SHELL_INSTALL_DTITEMS, dwPolicy);
  747. if (SUCCEEDED(hr))
  748. hr = dwPolicy == URLPOLICY_DISALLOW ? HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED) : S_OK;
  749. }
  750. return hr;
  751. }
  752. HRESULT COleInstall::CanIInstallRPC( LPTSTR lpszPrinter, LPTSTR lpszWebPrinter)
  753. /*++
  754. Routine Description:
  755. Examine Secuiry Policies to determine whether we should install the printer or not
  756. Arguments:
  757. lpszPrinter - The printer that we want to install
  758. Return Value:
  759. S_OK - Install via RPC
  760. S_FALSE - Install via Web Pnp
  761. HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED) - IE security does not allow this action
  762. Other HRESULT error code.
  763. --*/
  764. {
  765. DWORD dwPolicyJava;
  766. DWORD dwPolicyDTI;
  767. HRESULT hrRet = S_FALSE;
  768. HRESULT hr = GetActionPolicy(URLACTION_JAVA_PERMISSIONS, dwPolicyJava);
  769. _ASSERTE(lpszPrinter);
  770. if (FAILED(hr)) {
  771. // There is no JAVA Security Manager, or something went wrong,
  772. // then we decide whether to use Web PnP instead or just fail.
  773. hrRet = S_OK;
  774. }
  775. switch(dwPolicyJava) {
  776. case URLPOLICY_JAVA_LOW:
  777. case URLPOLICY_JAVA_MEDIUM:
  778. hr = S_OK;
  779. break;
  780. default: // We must do Web PnP
  781. hr = GetActionPolicy(URLACTION_SHELL_INSTALL_DTITEMS, dwPolicyDTI );
  782. if (FAILED(hr)) // Couldn't get the policy on installing Desk Top Items
  783. goto Cleanup;
  784. switch(dwPolicyDTI) {
  785. case URLPOLICY_ALLOW:
  786. case URLPOLICY_QUERY:
  787. hr = hrRet;
  788. break;
  789. case URLPOLICY_DISALLOW:
  790. hr = HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED);
  791. break;
  792. }
  793. }
  794. Cleanup:
  795. return hr;
  796. }
  797. LPTSTR COleInstall::RemoveURLVars(IN LPTSTR lpszPrinter) {
  798. _ASSERTE(lpszPrinter);
  799. LPTSTR lpszStripped = NULL;
  800. DWORD dwIndex = _tcscspn( lpszPrinter, TEXT("?") );
  801. lpszStripped = (LPTSTR)LocalAlloc( LPTR, (dwIndex + 1) * sizeof(TCHAR) );
  802. if (NULL == lpszStripped)
  803. goto Cleanup;
  804. _tcsncpy( lpszStripped, lpszPrinter, dwIndex );
  805. lpszStripped[dwIndex] = NULL; // NULL terminate it.
  806. Cleanup:
  807. return lpszStripped;
  808. }
  809. /*
  810. Function: GetNTPrint
  811. Purpose: Returns a LPTSTR with the path to %windir%\inf\ntprint.inf
  812. Caller must free the returned string.
  813. */
  814. LPTSTR
  815. COleInstall::GetNTPrint(void)
  816. {
  817. UINT uiSize = 0;
  818. UINT uiAllocSize = 0;
  819. PTCHAR pData = NULL;
  820. LPTSTR lpszNTPrintInf = NULL;
  821. LPCTSTR gcszNTPrint = _TEXT("\\inf\\ntprint.inf");
  822. //
  823. // Get %windir%
  824. // If the return is 0 - the call failed.
  825. //
  826. if( !(uiSize = GetSystemWindowsDirectory( lpszNTPrintInf, 0 )))
  827. goto Cleanup;
  828. uiAllocSize += uiSize + _tcslen( gcszNTPrint ) + 1;
  829. if( NULL == (lpszNTPrintInf = (LPTSTR)LocalAlloc( LPTR, uiAllocSize*sizeof(TCHAR) )))
  830. goto Cleanup;
  831. uiAllocSize = GetSystemWindowsDirectory( lpszNTPrintInf, uiSize );
  832. if( !uiAllocSize || uiAllocSize > uiSize ) {
  833. LocalFree(lpszNTPrintInf);
  834. lpszNTPrintInf = NULL;
  835. goto Cleanup;
  836. }
  837. //
  838. // Determine if we have a \ on the end remove it.
  839. //
  840. pData = &lpszNTPrintInf[ _tcslen(lpszNTPrintInf)-1 ];
  841. if( *pData == _TEXT('\\') )
  842. *pData = 0;
  843. //
  844. // Copy the inf\ntprint.inf string onto the end of the %windir%\ string.
  845. //
  846. _tcscat( lpszNTPrintInf, gcszNTPrint );
  847. Cleanup:
  848. return lpszNTPrintInf;
  849. }
  850. //
  851. // Creates the printer base name from the printerURL and printer name.
  852. // Form is : "\\http://url\printer name"
  853. //
  854. LPTSTR
  855. COleInstall::CreatePrinterBaseName(
  856. LPCTSTR lpszPrinterURL,
  857. LPCTSTR lpszPrinterName
  858. )
  859. {
  860. LPTSTR lpszFullPrinterName = NULL;
  861. PTCHAR pWhack = NULL,
  862. pFriendlyName = NULL;
  863. //
  864. // lpszPrinterName should be of the form "server\printer name"
  865. // We need to get only the "printer name" part.
  866. //
  867. if( NULL != ( pFriendlyName = _tcsrchr( lpszPrinterName, _TEXT('\\') ))) {
  868. //
  869. // Move off the \
  870. //
  871. pFriendlyName++;
  872. } else {
  873. pFriendlyName = (PTCHAR)lpszPrinterName;
  874. }
  875. //
  876. // Worst case size - the size of the two strings plus the "\\" plus "\" and
  877. // a NULL terminator
  878. //
  879. lpszFullPrinterName = (LPTSTR)LocalAlloc( LPTR,
  880. (lstrlen(lpszPrinterURL) + lstrlen(pFriendlyName) + 4)*sizeof(TCHAR) );
  881. if( lpszFullPrinterName ){
  882. lstrcpy( lpszFullPrinterName, _TEXT("\\\\"));
  883. lstrcat( lpszFullPrinterName, lpszPrinterURL );
  884. pWhack = _tcschr( lpszFullPrinterName, _TEXT('/') );
  885. if( pWhack ) {
  886. if( *(pWhack+1) == _TEXT('/') ) {
  887. //
  888. // We've got a //, find the next /
  889. //
  890. pWhack = _tcschr( pWhack+2, _TEXT('/') );
  891. }
  892. }
  893. if( !pWhack ) {
  894. pWhack = &lpszFullPrinterName[ lstrlen( lpszFullPrinterName ) ];
  895. }
  896. *pWhack++ = _TEXT('\\');
  897. lstrcpy( pWhack, pFriendlyName );
  898. }
  899. return lpszFullPrinterName;
  900. }
  901. /****************************************************************************************
  902. ** End of File (oleinst.cpp)
  903. ****************************************************************************************/