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.

715 lines
18 KiB

  1. /*++
  2. Copyright (c) 1995-97 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Monitor.c
  6. Abstract:
  7. Routines for installing monitors
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 30-Nov-1995
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. //
  14. // Keys to search INF files
  15. //
  16. TCHAR cszPortMonitorSection[] = TEXT("PortMonitors");
  17. TCHAR cszPortMonitorDllKey [] = TEXT("PortMonitorDll");
  18. TCHAR cszMonitorInf[] = TEXT("*.inf");
  19. typedef struct _MON_INFO {
  20. LPTSTR pszName;
  21. LPTSTR pszDllName;
  22. BOOL bInstalled;
  23. } MON_INFO, *PMON_INFO;
  24. typedef struct _MONITOR_SETUP_INFO {
  25. PMON_INFO *ppMonInfo;
  26. DWORD dwCount;
  27. LPTSTR pszInfFile; // Valid only for OEM disk INF
  28. LPTSTR pszServerName;
  29. } MONITOR_SETUP_INFO, *PMONITOR_SETUP_INFO;
  30. VOID
  31. FreeMonInfo(
  32. PMON_INFO pMonInfo
  33. )
  34. /*++
  35. Routine Description:
  36. Free memory for a MON_INFO structure and the strings in it
  37. Arguments:
  38. pMonInfo : MON_INFO structure pointer
  39. Return Value:
  40. Nothing
  41. --*/
  42. {
  43. if ( pMonInfo ) {
  44. LocalFreeMem(pMonInfo->pszName);
  45. LocalFreeMem(pMonInfo->pszDllName);
  46. LocalFreeMem(pMonInfo);
  47. }
  48. }
  49. PMON_INFO
  50. AllocMonInfo(
  51. IN LPTSTR pszName,
  52. IN LPTSTR pszDllName, OPTIONAL
  53. IN BOOL bInstalled,
  54. IN BOOL bAllocStrings
  55. )
  56. /*++
  57. Routine Description:
  58. Allocate memory for a MON_INFO structure and create strings
  59. Arguments:
  60. pszName : Monitor name
  61. pszDllName : Monitor DLL name
  62. bAllocStrings : TRUE if routine should allocated memory and create string
  63. copies, else just assign the pointers
  64. Return Value:
  65. Pointer to the created MON_INFO structure. NULL on error.
  66. --*/
  67. {
  68. PMON_INFO pMonInfo;
  69. pMonInfo = (PMON_INFO) LocalAllocMem(sizeof(*pMonInfo));
  70. if ( !pMonInfo )
  71. return NULL;
  72. if ( bAllocStrings ) {
  73. pMonInfo->pszName = AllocStr(pszName);
  74. pMonInfo->pszDllName = AllocStr(pszDllName);
  75. if ( !pMonInfo->pszName ||
  76. (pszDllName && !pMonInfo->pszDllName) ) {
  77. FreeMonInfo(pMonInfo);
  78. return NULL;
  79. }
  80. } else {
  81. pMonInfo->pszName = pszName;
  82. pMonInfo->pszDllName = pszDllName;
  83. }
  84. pMonInfo->bInstalled = bInstalled;
  85. return pMonInfo;
  86. }
  87. VOID
  88. PSetupDestroyMonitorInfo(
  89. IN OUT HANDLE h
  90. )
  91. /*++
  92. Routine Description:
  93. Free memory allocated to a MONITOR_SETUP_INFO structure and its contents
  94. Arguments:
  95. h : A handle got by call to PSetupCreateMonitorInfo
  96. Return Value:
  97. Nothing
  98. --*/
  99. {
  100. PMONITOR_SETUP_INFO pMonitorSetupInfo = (PMONITOR_SETUP_INFO) h;
  101. DWORD Index;
  102. if ( pMonitorSetupInfo ) {
  103. if ( pMonitorSetupInfo->ppMonInfo ) {
  104. for ( Index = 0 ; Index < pMonitorSetupInfo->dwCount ; ++Index )
  105. FreeMonInfo(pMonitorSetupInfo->ppMonInfo[Index]);
  106. LocalFreeMem(pMonitorSetupInfo->ppMonInfo);
  107. pMonitorSetupInfo->ppMonInfo = NULL;
  108. }
  109. LocalFreeMem(pMonitorSetupInfo->pszInfFile);
  110. LocalFreeMem(pMonitorSetupInfo->pszServerName);
  111. pMonitorSetupInfo->pszInfFile = NULL;
  112. pMonitorSetupInfo->pszServerName = NULL;
  113. LocalFreeMem(pMonitorSetupInfo);
  114. }
  115. }
  116. PMONITOR_SETUP_INFO
  117. CreateMonitorInfo(
  118. LPCTSTR pszServerName
  119. )
  120. /*++
  121. Routine Description:
  122. Finds all installed and installable monitors.
  123. Arguments:
  124. pSelectedDrvInfo : Pointer to the selected driver info (optional)
  125. Return Value:
  126. A pointer to MONITOR_SETUP_INFO on success,
  127. NULL on error
  128. --*/
  129. {
  130. PMONITOR_SETUP_INFO pMonitorSetupInfo = NULL;
  131. PMON_INFO *ppMonInfo;
  132. PMONITOR_INFO_2 pMonitor2;
  133. LONG Index, Count = 0;
  134. BOOL bFail = TRUE;
  135. DWORD dwNeeded, dwReturned;
  136. LPBYTE pBuf = NULL;
  137. LPTSTR pszMonName;
  138. //
  139. // First query spooler for installed monitors. If we fail let's quit
  140. //
  141. if ( !EnumMonitors((LPTSTR)pszServerName, 2, NULL,
  142. 0, &dwNeeded, &dwReturned) ) {
  143. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
  144. !(pBuf = LocalAllocMem(dwNeeded)) ||
  145. !EnumMonitors((LPTSTR)pszServerName,
  146. 2,
  147. pBuf,
  148. dwNeeded,
  149. &dwNeeded,
  150. &dwReturned) ) {
  151. goto Cleanup;
  152. }
  153. }
  154. //
  155. // We know how many monitors we have to display now
  156. //
  157. pMonitorSetupInfo = (PMONITOR_SETUP_INFO) LocalAllocMem(sizeof(*pMonitorSetupInfo));
  158. if ( !pMonitorSetupInfo )
  159. goto Cleanup;
  160. ZeroMemory(pMonitorSetupInfo, sizeof(*pMonitorSetupInfo));
  161. //
  162. // pMonitorSetupInfo->dwCount could be adjusted later not to list duplicate
  163. // entries. We are allocating max required buffer here
  164. //
  165. pMonitorSetupInfo->dwCount = dwReturned;
  166. pMonitorSetupInfo->ppMonInfo = (PMON_INFO *)
  167. LocalAllocMem(pMonitorSetupInfo->dwCount*sizeof(PMON_INFO));
  168. ppMonInfo = pMonitorSetupInfo->ppMonInfo;
  169. if ( !ppMonInfo )
  170. goto Cleanup;
  171. for ( Index = 0, pMonitor2 = (PMONITOR_INFO_2) pBuf ;
  172. Index < (LONG) dwReturned ;
  173. ++Index, (LPBYTE)pMonitor2 += sizeof(MONITOR_INFO_2) ) {
  174. *ppMonInfo++ = AllocMonInfo(pMonitor2->pName,
  175. pMonitor2->pDLLName,
  176. TRUE,
  177. TRUE);
  178. }
  179. bFail = FALSE;
  180. Cleanup:
  181. if ( pBuf )
  182. LocalFreeMem(pBuf);
  183. if ( bFail ) {
  184. PSetupDestroyMonitorInfo(pMonitorSetupInfo);
  185. pMonitorSetupInfo = NULL;
  186. }
  187. return pMonitorSetupInfo;
  188. }
  189. BOOL
  190. AddPrintMonitor(
  191. IN LPCTSTR pszName,
  192. IN LPCTSTR pszDllName
  193. )
  194. /*++
  195. Routine Description:
  196. Add a print monitor by calling AddMonitor to spooler
  197. Arguments:
  198. pszName : Name of the monitor
  199. pszDllName : Monitor dll name
  200. Return Value:
  201. TRUE if monitor was succesfully added or it is already installed,
  202. FALSE on failure
  203. --*/
  204. {
  205. MONITOR_INFO_2 MonitorInfo2;
  206. MonitorInfo2.pName = (LPTSTR) pszName;
  207. MonitorInfo2.pEnvironment = NULL;
  208. MonitorInfo2.pDLLName = (LPTSTR) pszDllName;
  209. //
  210. // Call is succesful if add returned TRUE, or monitor is already installed
  211. //
  212. if ( AddMonitor(NULL, 2, (LPBYTE) &MonitorInfo2) ||
  213. GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED ) {
  214. return TRUE;
  215. } else {
  216. return FALSE;
  217. }
  218. }
  219. BOOL
  220. InstallOnePortMonitor(HWND hwnd,
  221. HINF hInf,
  222. LPTSTR pMonitorName,
  223. LPTSTR pSectionName,
  224. LPTSTR pSourcePath)
  225. /*++
  226. Routine Description:
  227. Install one port monitor by copying files and calling spooler to add it
  228. Arguments:
  229. hwnd : Window handle of current top-level window
  230. hInf : handle to the INF file
  231. pMonitorName : port monitor display name
  232. pSectionName : install section within the INF for the port monitor
  233. Return Value:
  234. TRUE if a port monitor was successfully installed
  235. FALSE if not
  236. --*/
  237. {
  238. DWORD NameLen = MAX_PATH;
  239. BOOL bSuccess = FALSE;
  240. HSPFILEQ InstallQueue = {0};
  241. PVOID pQueueContext = NULL;
  242. LPTSTR pMonitorDllName;
  243. if ((pMonitorDllName = LocalAllocMem(NameLen * sizeof(TCHAR))) == NULL)
  244. {
  245. goto Cleanup;
  246. }
  247. //
  248. // Find the port monitor DLL name
  249. //
  250. if (!SetupGetLineText(NULL, hInf, pSectionName, cszPortMonitorDllKey, pMonitorDllName, NameLen, NULL))
  251. {
  252. goto Cleanup;
  253. }
  254. //
  255. // perform the installation
  256. //
  257. if ((InstallQueue = SetupOpenFileQueue()) == INVALID_HANDLE_VALUE)
  258. {
  259. goto Cleanup;
  260. }
  261. if (!SetupInstallFilesFromInfSection(hInf, NULL, InstallQueue, pSectionName, pSourcePath,
  262. SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP))
  263. {
  264. goto Cleanup;
  265. }
  266. //
  267. // Commit the file queue. This gets all files copied over.
  268. //
  269. pQueueContext = SetupInitDefaultQueueCallback(hwnd);
  270. if ( !pQueueContext )
  271. {
  272. goto Cleanup;
  273. }
  274. bSuccess = SetupCommitFileQueue(hwnd,
  275. InstallQueue,
  276. SetupDefaultQueueCallback,
  277. pQueueContext);
  278. if ( !bSuccess )
  279. goto Cleanup;
  280. bSuccess = AddPrintMonitor(pMonitorName, pMonitorDllName);
  281. Cleanup:
  282. if (pQueueContext)
  283. {
  284. SetupTermDefaultQueueCallback(pQueueContext);
  285. }
  286. if (pMonitorDllName)
  287. {
  288. LocalFreeMem(pMonitorDllName);
  289. pMonitorDllName = NULL;
  290. }
  291. SetupCloseFileQueue(InstallQueue);
  292. if (!bSuccess)
  293. {
  294. LPTSTR pszFormat = NULL, pszPrompt = NULL, pszTitle = NULL;
  295. pszFormat = GetStringFromRcFile(IDS_ERROR_INST_PORT_MONITOR);
  296. pszTitle = GetStringFromRcFile(IDS_INSTALLING_PORT_MONITOR);
  297. if ( pszFormat && pszTitle)
  298. {
  299. DWORD dwBufSize;
  300. dwBufSize = (lstrlen(pszFormat) + lstrlen(pMonitorName) + 2) * sizeof(TCHAR);
  301. pszPrompt = LocalAllocMem(dwBufSize);
  302. if ( pszPrompt )
  303. {
  304. StringCbPrintf(pszPrompt, dwBufSize, pszFormat, pMonitorName);
  305. MessageBox(hwnd, pszPrompt, pszTitle, MB_OK);
  306. LocalFreeMem(pszPrompt);
  307. }
  308. }
  309. LocalFreeMem(pszFormat);
  310. LocalFreeMem(pszTitle);
  311. }
  312. return bSuccess;
  313. }
  314. BOOL
  315. InstallAllPortMonitorsFromInf(HWND hwnd,
  316. HINF hInfFile,
  317. LPTSTR pSourcePath)
  318. /*++
  319. Routine Description:
  320. Install all port monitors listed in one INF
  321. Arguments:
  322. hwnd : Window handle of current top-level window
  323. hInfFile : handle of the INF file
  324. pSourcePath : path to the INF file (without the name of the INF)
  325. Return Value:
  326. TRUE if at least one port monitor was successfully installed
  327. FALSE if not
  328. --*/
  329. {
  330. LPTSTR pMonitorName = NULL, pSectionName= NULL;
  331. DWORD NameLen = MAX_PATH;
  332. BOOL bSuccess = FALSE;
  333. INFCONTEXT Context = {0};
  334. if (((pMonitorName = LocalAllocMem(NameLen * sizeof(TCHAR))) == NULL) ||
  335. ((pSectionName = LocalAllocMem(NameLen * sizeof(TCHAR))) == NULL))
  336. {
  337. goto Cleanup;
  338. }
  339. //
  340. // Go through the list of port monitors
  341. //
  342. if (!SetupFindFirstLine(hInfFile, cszPortMonitorSection, NULL, &Context))
  343. {
  344. goto Cleanup;
  345. }
  346. do
  347. {
  348. //
  349. // get the key name
  350. //
  351. if (!SetupGetStringField(&Context, 0, pMonitorName, NameLen, NULL))
  352. {
  353. goto Cleanup;
  354. }
  355. //
  356. // get the section name
  357. //
  358. if (!SetupGetStringField(&Context, 1, pSectionName, NameLen, NULL))
  359. {
  360. goto Cleanup;
  361. }
  362. bSuccess = InstallOnePortMonitor(hwnd, hInfFile, pMonitorName, pSectionName, pSourcePath) ||
  363. bSuccess;
  364. } while (SetupFindNextLine(&Context, &Context));
  365. Cleanup:
  366. if (pMonitorName)
  367. {
  368. LocalFreeMem(pMonitorName);
  369. }
  370. if (pSectionName)
  371. {
  372. LocalFreeMem(pSectionName);
  373. }
  374. return bSuccess;
  375. }
  376. BOOL
  377. PSetupInstallMonitor(
  378. IN HWND hwnd
  379. )
  380. /*++
  381. Routine Description:
  382. Install a print monitor by copying files, and calling spooler to add it
  383. Arguments:
  384. hwnd : Window handle of current top-level window
  385. Return Value:
  386. TRUE if at least one port monitor was successfully installed
  387. FALSE if not
  388. --*/
  389. {
  390. PMONITOR_SETUP_INFO pMonitorSetupInfo = NULL;
  391. PMON_INFO *ppMonInfo, pMonInfo;
  392. HINF hInf = INVALID_HANDLE_VALUE;
  393. INFCONTEXT InfContext;
  394. TCHAR szInfPath[MAX_PATH];
  395. LPTSTR pszTitle, pszPrintMonitorPrompt;
  396. WIN32_FIND_DATA FindData ={0};
  397. HANDLE hFind;
  398. size_t PathLen;
  399. BOOL bRet = FALSE;
  400. pszTitle = GetStringFromRcFile(IDS_INSTALLING_PORT_MONITOR);
  401. pszPrintMonitorPrompt = GetStringFromRcFile(IDS_PROMPT_PORT_MONITOR);
  402. if (!pszTitle || ! pszPrintMonitorPrompt)
  403. {
  404. goto Cleanup;
  405. }
  406. //
  407. // Ask the user where the inf file with the port monitor info resides
  408. //
  409. GetCDRomDrive(szInfPath);
  410. if ( !PSetupGetPathToSearch(hwnd,
  411. pszTitle,
  412. pszPrintMonitorPrompt,
  413. cszMonitorInf,
  414. TRUE,
  415. szInfPath) ) {
  416. goto Cleanup;
  417. }
  418. //
  419. // find the INF(s) in the path. There must be one else SetupPromptForPath would've complained
  420. //
  421. PathLen = _tcslen(szInfPath);
  422. if (PathLen > MAX_PATH - _tcslen(cszMonitorInf) - 2) // -2 for terminating zero and backslash
  423. {
  424. DBGMSG(DBG_WARN, ("PSetupInstallMonitor: Path too long\n"));
  425. SetLastError(ERROR_BUFFER_OVERFLOW);
  426. goto Cleanup;
  427. }
  428. ASSERT(PathLen);
  429. if (szInfPath[PathLen-1] != _T('\\'))
  430. {
  431. szInfPath[PathLen++] = _T('\\');
  432. szInfPath[PathLen] = 0;
  433. }
  434. StringCchCat(szInfPath, COUNTOF(szInfPath), cszMonitorInf);
  435. hFind = FindFirstFile(szInfPath, &FindData);
  436. if (hFind != INVALID_HANDLE_VALUE)
  437. {
  438. HANDLE hInfFile;
  439. do
  440. {
  441. if (PathLen + _tcslen(FindData.cFileName) >= MAX_PATH)
  442. {
  443. DBGMSG(DBG_WARN, ("PSetupInstallMonitor: Path for %s%s too long - file skipped\n", szInfPath, FindData.cFileName));
  444. SetLastError(ERROR_BUFFER_OVERFLOW);
  445. continue;
  446. }
  447. StringCchCopy(&(szInfPath[PathLen]), COUNTOF(szInfPath) - PathLen, FindData.cFileName);
  448. hInfFile = SetupOpenInfFile(szInfPath, _T("Printer"), INF_STYLE_WIN4, NULL);
  449. if (hInfFile != INVALID_HANDLE_VALUE)
  450. {
  451. //
  452. // if the file has a section on port monitors, install it
  453. //
  454. if ( SetupGetLineCount(hInfFile, cszPortMonitorSection) > 0 )
  455. {
  456. //
  457. // cut off the INF name from the path
  458. //
  459. szInfPath[PathLen -1] = 0;
  460. //
  461. // bRet should be TRUE if there was at least one print monitor successfully installed
  462. //
  463. bRet = InstallAllPortMonitorsFromInf(hwnd, hInfFile, szInfPath) || bRet;
  464. //
  465. // Put the trailing backslash back on
  466. //
  467. szInfPath[PathLen -1] = _T('\\');
  468. }
  469. SetupCloseInfFile(hInfFile);
  470. }
  471. } while ( FindNextFile(hFind, &FindData) );
  472. FindClose(hFind);
  473. }
  474. Cleanup:
  475. if (pszTitle)
  476. {
  477. LocalFreeMem(pszTitle);
  478. }
  479. if (pszPrintMonitorPrompt)
  480. {
  481. LocalFreeMem(pszPrintMonitorPrompt);
  482. }
  483. return bRet;
  484. }
  485. HANDLE
  486. PSetupCreateMonitorInfo(
  487. IN HWND hwnd,
  488. IN LPCTSTR pszServerName
  489. )
  490. /*++
  491. Routing Description:
  492. Returns structure (MONITOR_SETUP_INFO) with all installed port monitors.
  493. Arguments:
  494. hwnd - usused window handle
  495. pszServerName - the server on which to look for installed monitors
  496. Return Value:
  497. A pointer to MONITOR_SETUP_INFO on success,
  498. NULL on error
  499. --*/
  500. {
  501. return (HANDLE) CreateMonitorInfo(pszServerName);
  502. }
  503. BOOL
  504. PSetupEnumMonitor(
  505. IN HANDLE h,
  506. IN DWORD dwIndex,
  507. OUT LPTSTR pMonitorName,
  508. IN OUT LPDWORD pdwSize
  509. )
  510. /*++
  511. Routing Description:
  512. Gets the name of the monitor at "position" dwIndex in the MONITOR_SETUP_INFO
  513. structure pointed to by h.
  514. Arguments:
  515. hwnd - usused window handle
  516. pszServerName - the server on which to look for installed monitors
  517. Return Value:
  518. A pointer to MONITOR_SETUP_INFO on success,
  519. NULL on error
  520. --*/
  521. {
  522. PMONITOR_SETUP_INFO pMonitorSetupInfo = (PMONITOR_SETUP_INFO) h;
  523. PMON_INFO pMonInfo;
  524. DWORD dwNeeded;
  525. if(!pMonitorSetupInfo)
  526. {
  527. SetLastError(ERROR_INVALID_PARAMETER);
  528. return FALSE;
  529. }
  530. if ( dwIndex >= pMonitorSetupInfo->dwCount ) {
  531. SetLastError(ERROR_NO_MORE_ITEMS);
  532. return FALSE;
  533. }
  534. pMonInfo = pMonitorSetupInfo->ppMonInfo[dwIndex];
  535. dwNeeded = lstrlen(pMonInfo->pszName) + 1;
  536. if ( dwNeeded > *pdwSize ) {
  537. *pdwSize = dwNeeded;
  538. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  539. return FALSE;
  540. }
  541. StringCchCopy(pMonitorName, *pdwSize, pMonInfo->pszName);
  542. return TRUE;
  543. }