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.

1681 lines
43 KiB

  1. /*****************************************************************************\
  2. * MODULE: libpriv.cxx
  3. *
  4. * Contains the source code for internal routines used throughout the library.
  5. *
  6. *
  7. * Copyright (C) 1996-1998 Hewlett Packard Company.
  8. * Copyright (C) 1996-1998 Microsoft Corporation.
  9. *
  10. * History:
  11. * 10-Oct-1997 GFS Initial checkin
  12. * 10-Jun-1998 CHW Cleaned. Restructured.
  13. *
  14. \*****************************************************************************/
  15. #include "libpriv.h"
  16. #define strFree(pszStr) {if (pszStr) GlobalFree((HANDLE)pszStr);}
  17. /*****************************************************************************\
  18. * strAlloc
  19. *
  20. * Allocates a string from the heap. This pointer must be freed with
  21. * a call to strFree().
  22. *
  23. \*****************************************************************************/
  24. LPTSTR strAlloc(
  25. LPCTSTR pszSrc)
  26. {
  27. DWORD cbSize;
  28. LPTSTR pszDst = NULL;
  29. cbSize = (pszSrc ? ((lstrlen(pszSrc) + 1) * sizeof(TCHAR)) : 0);
  30. if (cbSize) {
  31. if (pszDst = (LPTSTR)GlobalAlloc(GPTR, cbSize))
  32. CopyMemory(pszDst, pszSrc, cbSize);
  33. }
  34. return pszDst;
  35. }
  36. /*****************************************************************************\
  37. * strLoad
  38. *
  39. * Get string from resource based upon the ID passed in.
  40. *
  41. \*****************************************************************************/
  42. LPTSTR strLoad(
  43. UINT ids)
  44. {
  45. char szStr[RES_BUFFER];
  46. if (LoadString(g_hLibInst, ids, szStr, sizeof(szStr)) == 0)
  47. szStr[0] = TEXT('\0');
  48. return strAlloc(szStr);
  49. }
  50. /*****************************************************************************\
  51. * InitStrings
  52. *
  53. *
  54. \*****************************************************************************/
  55. BOOL InitStrings(VOID)
  56. {
  57. g_szFmtName = strLoad(IDS_FMTNAME);
  58. g_szMsgOptions = strLoad(IDS_MSG_OPTIONS);
  59. g_szMsgThunkFail = strLoad(IDS_THUNK32FAIL);
  60. g_szPrinter = strLoad(IDS_PRINTER);
  61. g_szMsgExists = strLoad(IDS_ALREADY_EXISTS);
  62. g_szMsgOptCap = strLoad(IDS_MSG_OPTCAP);
  63. return (g_szFmtName &&
  64. g_szMsgOptions &&
  65. g_szMsgThunkFail &&
  66. g_szPrinter &&
  67. g_szMsgExists &&
  68. g_szMsgOptCap
  69. );
  70. }
  71. /*****************************************************************************\
  72. * FreeeStrings
  73. *
  74. *
  75. \*****************************************************************************/
  76. VOID FreeStrings(VOID)
  77. {
  78. strFree(g_szFmtName);
  79. strFree(g_szMsgOptions);
  80. strFree(g_szMsgThunkFail);
  81. strFree(g_szPrinter);
  82. strFree(g_szMsgExists);
  83. strFree(g_szMsgOptCap);
  84. }
  85. /*****************************************************************************\
  86. * prv_StrChr
  87. *
  88. * Looks for the first location where (c) resides.
  89. *
  90. \*****************************************************************************/
  91. LPTSTR prv_StrChr(
  92. LPCTSTR cs,
  93. TCHAR c)
  94. {
  95. while (*cs != TEXT('\0')) {
  96. if (*cs == c)
  97. return (LPTSTR)cs;
  98. cs++;
  99. }
  100. // Fail to find c in cs.
  101. //
  102. return NULL;
  103. }
  104. /****************************************************************************\
  105. * prv_CheesyHash
  106. *
  107. * Hash function to convert a string to dword representation.
  108. *
  109. \****************************************************************************/
  110. DWORD prv_CheesyHash(
  111. LPCTSTR lpszIn)
  112. {
  113. LPDWORD lpdwIn;
  114. DWORD cbLeft;
  115. DWORD dwTmp;
  116. DWORD dwRet = 0;
  117. if (lpszIn && (cbLeft = (lstrlen(lpszIn) * sizeof(TCHAR)))) {
  118. // Process in DWORDs as long as possible
  119. //
  120. for (lpdwIn = (LPDWORD)lpszIn; cbLeft > sizeof(DWORD); cbLeft -= sizeof(DWORD)) {
  121. dwRet ^= *lpdwIn++;
  122. }
  123. // Process bytes for whatever's left of the string.
  124. //
  125. if (cbLeft) {
  126. for (dwTmp = 0, lpszIn = (LPTSTR)lpdwIn; *lpszIn; lpszIn++) {
  127. dwTmp |= (DWORD)(TCHAR)(*lpszIn);
  128. dwTmp <<= 8;
  129. }
  130. dwRet ^= dwTmp;
  131. }
  132. }
  133. return dwRet;
  134. }
  135. /*****************************************************************************\
  136. * prv_ParseHostShare
  137. *
  138. * Parses the FriendlyName (http://host/printers/share/.printer) into its
  139. * Host/Share components.
  140. *
  141. * This routine returns allocated pointers that must be freed by the caller.
  142. *
  143. \*****************************************************************************/
  144. BOOL prv_ParseHostShare(
  145. LPCTSTR lpszFriendly,
  146. LPTSTR *lpszHost,
  147. LPTSTR *lpszShare)
  148. {
  149. LPTSTR lpszPrt;
  150. LPTSTR lpszTmp;
  151. LPTSTR lpszPos;
  152. BOOL bRet = FALSE;
  153. // Initialize the return buffers to NULL.
  154. //
  155. *lpszHost = NULL;
  156. *lpszShare = NULL;
  157. // Parse the host-name and the share name. The (lpszFriendly) is
  158. // currently in the format of http://host[:portnumber]/share. We will
  159. // parse this from left->right since the share-name can be a path (we
  160. // wouldn't really know the exact length). However, we do know the
  161. // location for the host-name, and anything after that should be
  162. // the share-name.
  163. //
  164. // First find the ':'. The host-name should begin two "//" after
  165. // that.
  166. //
  167. if (lpszPrt = memAllocStr(lpszFriendly)) {
  168. if (lpszPos = prv_StrChr(lpszPrt, TEXT(':'))) {
  169. lpszPos++;
  170. lpszPos++;
  171. lpszPos++;
  172. // Get past the host.
  173. //
  174. if (lpszTmp = prv_StrChr(lpszPos, TEXT('/'))) {
  175. // HostName (includes http).
  176. //
  177. *lpszTmp = TEXT('\0');
  178. *lpszHost = memAllocStr(lpszPrt);
  179. *lpszTmp = TEXT('/');
  180. // ShareName.
  181. //
  182. if (lpszPos = prv_StrChr(++lpszTmp, TEXT('/'))) {
  183. lpszPos++;
  184. if (lpszTmp = prv_StrChr(lpszPos, TEXT('/'))) {
  185. *lpszTmp = TEXT('\0');
  186. *lpszShare = memAllocStr(lpszPos);
  187. *lpszTmp = TEXT('/');
  188. bRet = TRUE;
  189. } else {
  190. goto BadFmt;
  191. }
  192. } else {
  193. goto BadFmt;
  194. }
  195. } else {
  196. goto BadFmt;
  197. }
  198. } else {
  199. BadFmt:
  200. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32 : prv_ParseHostShare - Invalid name <%s>"), lpszFriendly));
  201. if (*lpszHost)
  202. memFreeStr(*lpszHost);
  203. if (*lpszShare)
  204. memFreeStr(*lpszShare);
  205. *lpszHost = NULL;
  206. *lpszShare = NULL;
  207. }
  208. memFreeStr(lpszPrt);
  209. }
  210. return bRet;
  211. }
  212. /****************************************************************************\
  213. * prv_StrPBrk
  214. *
  215. * DBCS-Aware version of strpbrk.
  216. *
  217. * NOTE: If this is ever converted/compiled as unicode, then this function
  218. * is broken. It would need to be unicode-aware.
  219. *
  220. * 26-Jun-1998 : ChrisWil
  221. *
  222. \****************************************************************************/
  223. LPTSTR prv_StrPBrk(
  224. LPCTSTR lpszSrch,
  225. LPCTSTR lpszTrgt)
  226. {
  227. LPTSTR lpszPtr;
  228. if (lpszSrch && lpszTrgt) {
  229. for( ; *lpszSrch; lpszSrch = AnsiNext(lpszSrch)) {
  230. for (lpszPtr = (LPTSTR)lpszTrgt; *lpszPtr; lpszPtr = AnsiNext(lpszPtr)) {
  231. if (*lpszSrch == *lpszPtr) {
  232. // First byte matches--see if we need to check
  233. // second byte
  234. //
  235. if (IsDBCSLeadByte(*lpszPtr)) {
  236. if(*(lpszSrch + 1) == *(lpszPtr + 1))
  237. return (LPTSTR)lpszSrch;
  238. } else {
  239. return (LPTSTR)lpszSrch;
  240. }
  241. }
  242. }
  243. }
  244. }
  245. return NULL;
  246. }
  247. /****************************************************************************\
  248. * prv_BuildUniqueID
  249. *
  250. * Create a unique ID based on lpszModel/lpszPort/Timer.
  251. *
  252. \****************************************************************************/
  253. DWORD prv_BuildUniqueID(
  254. LPCTSTR lpszModel,
  255. LPCTSTR lpszPort)
  256. {
  257. return ((prv_CheesyHash(lpszModel) ^ prv_CheesyHash(lpszPort)) ^ GetTickCount());
  258. }
  259. /****************************************************************************\
  260. * prv_IsNameInUse
  261. *
  262. * Return whether the name is already in use by the print-subsystem.
  263. *
  264. \****************************************************************************/
  265. BOOL prv_IsNameInUse(
  266. LPCTSTR lpszName)
  267. {
  268. HANDLE hPrinter;
  269. if (OpenPrinter((LPTSTR)lpszName, &hPrinter, NULL)) {
  270. ClosePrinter(hPrinter);
  271. return TRUE;
  272. }
  273. return FALSE;
  274. }
  275. /****************************************************************************\
  276. * prv_CreateUniqueName
  277. *
  278. * Create a unique friendly name for this printer. If (idx) is 0, then
  279. * copy the name from the base to the (lpszDst). Otherwise, play some
  280. * games with truncating the name so it will fit.
  281. *
  282. \****************************************************************************/
  283. BOOL prv_CreateUniqueName(
  284. LPTSTR lpszDst,
  285. LPCTSTR lpszBaseName,
  286. DWORD idx)
  287. {
  288. TCHAR szBaseName[_MAX_NAME_];
  289. int nFormatLength;
  290. BOOL bSuccess = FALSE;
  291. if (idx) {
  292. // Create a unique friendly name for each instance.
  293. // Start with:
  294. // "%s %d" After LoadMessage
  295. // "Short Model Name 2" After wsprintf or
  296. // "Very very long long Model Nam 2" After wsprintf
  297. //
  298. // Since wsprintf has no concept of limiting the string size,
  299. // truncate the model name (in a DBCS-aware fashion) to
  300. // the appropriate size, so the whole string fits in _MAX_NAME_ bytes.
  301. // This may cause some name truncation, but only in cases where
  302. // the model name is extremely long.
  303. // nFormatLength is length of string without the model name.
  304. // If wInstance is < 10, format length is 2 (space + digit).
  305. // If wInstance is < 100, format length is 3. Else format
  306. // length is 4. Add 1 to compensate for the terminating NULL,
  307. // which is counted in the total buffer length, but not the string
  308. // length,
  309. //
  310. if (idx < 10) {
  311. nFormatLength = 9 + 1;
  312. } else if (idx < 100) {
  313. nFormatLength = 10 + 1;
  314. } else {
  315. nFormatLength = 11 + 1;
  316. }
  317. // Truncate the base name, if necessary,
  318. // then build the output string.
  319. //
  320. lstrcpyn(szBaseName, lpszBaseName, sizeof(szBaseName) - nFormatLength);
  321. // there is already a copy 1 (undecorated base name)
  322. //
  323. wsprintf(lpszDst, g_szFmtName, (LPTSTR)szBaseName, (int)idx + 1);
  324. bSuccess = TRUE;
  325. } else {
  326. lstrcpyn(lpszDst, lpszBaseName, _MAX_NAME_);
  327. bSuccess = TRUE;
  328. }
  329. return bSuccess;
  330. }
  331. /****************************************************************************\
  332. * prv_FindUniqueName
  333. *
  334. * Find a unique name that isn't already in use by the print subsystem.
  335. * Base the name on the friendly name and an instance count.
  336. *
  337. * This will alter the lpszFriendly; even if function fails.
  338. *
  339. \****************************************************************************/
  340. BOOL prv_FindUniqueName(
  341. LPTSTR lpszFriendly)
  342. {
  343. // Since our http:// name is too long for W95, we're going
  344. // to try basing our name off of the model-name.
  345. //
  346. // 28-Jun-1998 : ChrisWil
  347. DWORD idx;
  348. TCHAR *pszBase = NULL;
  349. BOOL bRes = FALSE;
  350. pszBase = memAllocStr( lpszFriendly );
  351. if (!pszBase)
  352. {
  353. goto Cleanup;
  354. }
  355. // Iterate until we have found a unique name we can use.
  356. //
  357. for (idx = 0; idx < MAX_NAMES; idx++) {
  358. prv_CreateUniqueName(lpszFriendly, pszBase, idx);
  359. if (!prv_IsNameInUse(lpszFriendly))
  360. {
  361. bRes = TRUE;
  362. goto Cleanup;
  363. }
  364. }
  365. Cleanup:
  366. if (pszBase)
  367. {
  368. memFreeStr( pszBase );
  369. }
  370. return bRes;
  371. }
  372. /****************************************************************************\
  373. * prv_IsThisDriverInstalled
  374. *
  375. * Get the list of all installed printer drivers, and check to see
  376. * if the current driver is in the list. If the driver is already
  377. * installed, ask the user if we should keep the old one or install
  378. * over the top of it.
  379. *
  380. * returns: RET_OK : OK.
  381. * RET_ALLOC_ERROR : Out of memory.
  382. * RET_DRIVER_NOT_FOUND : Can't find driver.
  383. *
  384. \****************************************************************************/
  385. DWORD prv_IsThisDriverInstalled(
  386. LPSI lpsi)
  387. {
  388. DWORD cbNeed;
  389. DWORD cbSize;
  390. DWORD cDrvs;
  391. DWORD i;
  392. BOOL bRet;
  393. int iRes;
  394. LPDRIVER_INFO_1 lpdi1;
  395. DWORD dwRet = RET_DRIVER_NOT_FOUND;
  396. // Get the size necessary to store the drivers.
  397. //
  398. cbSize = 0;
  399. cDrvs = 0;
  400. EnumPrinterDrivers((LPTSTR)NULL,
  401. (LPTSTR)NULL,
  402. 1,
  403. NULL,
  404. 0,
  405. &cbSize,
  406. &cDrvs);
  407. // If we have drivers, then we can look for our installed driver.
  408. //
  409. if (cbSize && (lpdi1 = (LPDRIVER_INFO_1)memAlloc(cbSize))) {
  410. bRet = EnumPrinterDrivers(NULL,
  411. NULL,
  412. 1,
  413. (LPBYTE)lpdi1,
  414. cbSize,
  415. &cbNeed,
  416. &cDrvs);
  417. if (bRet) {
  418. for (i = 0; i < cDrvs; i++) {
  419. if (lstrcmpi(lpsi->szModel, lpdi1[i].pName) == 0) {
  420. dwRet = RET_DRIVER_FOUND;
  421. break;
  422. }
  423. }
  424. }
  425. // Free up our allocated buffer.
  426. //
  427. memFree(lpdi1, cbSize);
  428. // If found, then we need to request from the user whether
  429. // to replace the driver.
  430. //
  431. if (dwRet == RET_DRIVER_FOUND) {
  432. iRes = MessageBox(NULL,
  433. g_szMsgExists,
  434. lpsi->szModel,
  435. MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON1);
  436. if (iRes == IDNO)
  437. dwRet = RET_DRIVER_NOT_FOUND;
  438. else
  439. dwRet = RET_OK;
  440. }
  441. }
  442. return dwRet;
  443. }
  444. /****************************************************************************\
  445. * prv_BuildPrinterInfo
  446. *
  447. * Allocate and/or initialize a PRINTER_INFO_2 structure from LPSI. Store
  448. * the pointer in lpsi->lpPrinterInfo2.
  449. *
  450. * returns: RET_OK : OK.
  451. * RET_ALLOC_ERROR : Out of memory.
  452. *
  453. \****************************************************************************/
  454. DWORD prv_BuildPrinterInfo(
  455. LPSI lpsi)
  456. {
  457. LPPRINTER_INFO_2 lppi2;
  458. // This code path is always executed just before we call
  459. // AddPrinter. Fill in anything we don't already have.
  460. //
  461. // Allocate memory if we need it.
  462. //
  463. if (lpsi->lpPrinterInfo2 == NULL) {
  464. lpsi->lpPrinterInfo2 = (LPBYTE)memAlloc(sizeof(PRINTER_INFO_2));
  465. }
  466. // Fill in the lppi2.
  467. //
  468. if (lppi2 = (LPPRINTER_INFO_2)lpsi->lpPrinterInfo2) {
  469. lppi2->pPrinterName = lpsi->szFriendly;
  470. lppi2->pPortName = lpsi->szPort;
  471. lppi2->pDriverName = lpsi->szModel;
  472. lppi2->pPrintProcessor = lpsi->szPrintProcessor;
  473. lppi2->pDatatype = lpsi->szDefaultDataType;
  474. lppi2->Priority = DEF_PRIORITY;
  475. lppi2->Attributes = 0;
  476. // Slow Machine?
  477. //
  478. if (0x0002 & GetSystemMetrics(SM_SLOWMACHINE))
  479. lppi2->Attributes |= PRINTER_ATTRIBUTE_QUEUED;
  480. // Point & Print case--make sure that the devmode we use to
  481. // add the printer locally contains the local friendly name
  482. // and not the friendly name it had on the server
  483. //
  484. if (lppi2->pDevMode) {
  485. lstrcpyn((LPSTR)lppi2->pDevMode->dmDeviceName,
  486. lpsi->szFriendly,
  487. sizeof(lppi2->pDevMode->dmDeviceName));
  488. }
  489. } else {
  490. return RET_ALLOC_ERR;
  491. }
  492. return RET_OK;
  493. }
  494. /****************************************************************************\
  495. * prv_InstallPrinter
  496. *
  497. * Install the printer identified by LPSI. If the printer exists, then
  498. * call SetPrinter(). Otherwise, call AddPrinter().
  499. *
  500. * returns: RET_OK : OK.
  501. * RET_ALLOC_ERROR : Out of memory.
  502. * RET_ADD_PRINTER_ERROR : Can't add printer.
  503. *
  504. \****************************************************************************/
  505. DWORD prv_InstallPrinter(
  506. LPSI lpsi)
  507. {
  508. DWORD dwRet;
  509. PRINTER_INFO_5 pi5;
  510. LPPRINTER_INFO_2 lppi2 = NULL;
  511. HANDLE hPrinter = NULL;
  512. BOOL bRes = FALSE;
  513. // BuildPrinterInfo will allocate an lppi2 and attach it to lpsi
  514. //
  515. if ((dwRet = prv_BuildPrinterInfo(lpsi)) == RET_OK) {
  516. lppi2 = (LPPRINTER_INFO_2)lpsi->lpPrinterInfo2;
  517. dwRet = RET_ADD_PRINTER_ERROR;
  518. hPrinter = AddPrinter(NULL, 2, (LPBYTE)lppi2);
  519. DBG_ASSERT((hPrinter != NULL), (TEXT("WPNPIN32: prv_InstallPrinter - Failed AddPrinter")));
  520. }
  521. if (hPrinter) {
  522. // Set the transmission & retry timeouts--remember that the
  523. // subsystem values are in milliseconds!
  524. //
  525. ZeroMemory(&pi5, sizeof(PRINTER_INFO_5));
  526. pi5.pPrinterName = lpsi->szFriendly;
  527. pi5.DeviceNotSelectedTimeout = lpsi->wDNSTimeout * ONE_SECOND;
  528. pi5.TransmissionRetryTimeout = lpsi->wRetryTimeout * ONE_SECOND;
  529. pi5.pPortName = lppi2->pPortName;
  530. pi5.Attributes = lppi2->Attributes;
  531. SetPrinter(hPrinter, 5, (LPBYTE)&pi5, 0);
  532. // Set the printer's unique ID so we can delete it correctly later
  533. //
  534. if (lpsi->dwUniqueID = prv_BuildUniqueID(lpsi->szModel, lpsi->szPort)) {
  535. SetPrinterData(hPrinter,
  536. (LPTSTR)g_szUniqueID,
  537. REG_BINARY,
  538. (LPBYTE)&lpsi->dwUniqueID,
  539. sizeof(DWORD));
  540. }
  541. ClosePrinter(hPrinter);
  542. dwRet = RET_OK;
  543. }
  544. // We don't need lpPrinterInfo2 anymore.
  545. //
  546. if (lpsi->lpPrinterInfo2) {
  547. memFree(lpsi->lpPrinterInfo2, sizeof(PRINTER_INFO_2));
  548. lpsi->lpPrinterInfo2 = NULL;
  549. }
  550. // We don't need lpDriverInfo3 anymore
  551. //
  552. if (lpsi->lpDriverInfo3) {
  553. memFree(lpsi->lpDriverInfo3, memGetSize(lpsi->lpDriverInfo3));
  554. lpsi->lpDriverInfo3 = NULL;
  555. }
  556. return dwRet;
  557. }
  558. /****************************************************************************\
  559. * prv_BuildDriverInfo
  560. *
  561. * Allocate and initialize a DRIVER_INFO_3 for lpsi.
  562. * driver dependent files be copied to the printer-driver-directory.
  563. *
  564. \****************************************************************************/
  565. BOOL prv_BuildDriverInfo(
  566. LPSI lpsi)
  567. {
  568. LPDRIVER_INFO_3 lpdi3;
  569. // This code path is always executed before we call AddPrinterDriver.
  570. // Set up any data that we don't already have. We always work with
  571. // a DRIVER_INFO_3 on this pass.
  572. //
  573. // Allocate memory, if we need it.
  574. //
  575. if (lpsi->lpDriverInfo3 == NULL) {
  576. lpsi->lpDriverInfo3 = (LPBYTE)memAlloc(sizeof(DRIVER_INFO_3));
  577. }
  578. // Fill in the lpdi3;
  579. //
  580. if (lpdi3 = (LPDRIVER_INFO_3)lpsi->lpDriverInfo3) {
  581. lpdi3->cVersion = (DWORD)lpsi->dwDriverVersion;
  582. lpdi3->pName = lpsi->szModel;
  583. lpdi3->pEnvironment = (LPTSTR)g_szEnvironment;
  584. lpdi3->pDriverPath = lpsi->szDriverFile;
  585. lpdi3->pDataFile = lpsi->szDataFile;
  586. lpdi3->pConfigFile = lpsi->szConfigFile;
  587. lpdi3->pHelpFile = lpsi->szHelpFile;
  588. lpdi3->pDefaultDataType = lpsi->szDefaultDataType;
  589. if (lpsi->wFilesUsed && lpsi->lpFiles)
  590. lpdi3->pDependentFiles = (LPSTR)lpsi->lpFiles;
  591. else
  592. lpdi3->pDependentFiles = NULL;
  593. }
  594. return (lpsi->lpDriverInfo3 ? TRUE : FALSE);
  595. }
  596. /****************************************************************************\
  597. * prv_InstallPrinProcessor
  598. *
  599. * Copy the print processor file associated with this driver
  600. * into the print processor directory and then add it to the
  601. * print sub-system. Do not overwrite an existing print
  602. * processor of the same name.
  603. *
  604. \****************************************************************************/
  605. DWORD prv_InstallPrintProcessor(
  606. LPSI lpsi,
  607. LPCTSTR pszPath)
  608. {
  609. DWORD dwRet = RET_OK;
  610. LPTSTR lpPrintProcessorDLL;
  611. DWORD pcbNeeded;
  612. TCHAR buf[_MAX_PATH_];
  613. TCHAR *pszBuf = NULL;
  614. TCHAR *pszTemp = NULL;
  615. int cbLength = 0;
  616. int cbBufLength = 0;
  617. // Add the print processor if required
  618. //
  619. if (lpPrintProcessorDLL = prv_StrPBrk(lpsi->szPrintProcessor, g_szComma)) {
  620. *lpPrintProcessorDLL++ = TEXT('\0');
  621. lstrcpy(buf, g_szNull);
  622. cbLength = lstrlen(pszPath) + lstrlen(g_szBackslash) + lstrlen(lpPrintProcessorDLL) + 1;
  623. if (cbLength)
  624. {
  625. pszTemp = memAlloc( cbLength * sizeof(TCHAR) );
  626. }
  627. if (!pszTemp)
  628. {
  629. dwRet = RET_ALLOC_ERR;
  630. goto Cleanup;
  631. }
  632. // get the source file
  633. //
  634. lstrcpy(pszTemp, pszPath);
  635. lstrcat(pszTemp, g_szBackslash);
  636. lstrcat(pszTemp, lpPrintProcessorDLL);
  637. // The DLL must be in the PrintProcessorDirectory
  638. //
  639. GetPrintProcessorDirectory(NULL,
  640. NULL,
  641. 1,
  642. (LPBYTE)buf,
  643. sizeof(buf),
  644. &pcbNeeded);
  645. cbBufLength = lstrlen(buf) + lstrlen(g_szBackslash) + lstrlen(lpPrintProcessorDLL) + 1;
  646. if (cbBufLength)
  647. {
  648. pszBuf = memAlloc( cbBufLength * sizeof(TCHAR) );
  649. }
  650. if (!pszBuf)
  651. {
  652. dwRet = RET_ALLOC_ERR;
  653. goto Cleanup;
  654. }
  655. lstrcpy(pszBuf, buf);
  656. lstrcat(pszBuf, g_szBackslash);
  657. lstrcat(pszBuf, lpPrintProcessorDLL);
  658. // Copy the file, but don't overwrite an existing copy of it
  659. //
  660. CopyFile(lpPrintProcessorDLL, pszBuf, TRUE);
  661. AddPrintProcessor(NULL,
  662. (LPTSTR)g_szEnvironment,
  663. lpPrintProcessorDLL,
  664. lpsi->szPrintProcessor);
  665. } else {
  666. DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : No PrintProcessor to add")));
  667. }
  668. Cleanup:
  669. if (pszTemp)
  670. {
  671. memFree(pszTemp, cbLength * sizeof(TCHAR) );
  672. }
  673. if (pszBuf)
  674. {
  675. memFree(pszBuf, cbBufLength * sizeof(TCHAR) );
  676. }
  677. return dwRet;
  678. }
  679. /****************************************************************************\
  680. * prv_GetDriverVersion
  681. *
  682. * Confirm that the driver identified in lpsi is indeed a
  683. * valid printer driver, and determine which version it
  684. * is. Leave the driver loaded for performance reasons
  685. * (since it will get loaded at least twice more).
  686. *
  687. \****************************************************************************/
  688. DWORD prv_GetDriverVersion(
  689. LPSI lpsi,
  690. LPTSTR pszPath)
  691. {
  692. UINT wOldErrorMode;
  693. HINSTANCE hDrv = NULL;
  694. TCHAR *pszTemp = NULL;
  695. INT cbLength = 0;
  696. DWORD idError = RET_INVALID_DLL;
  697. wOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  698. cbLength = lstrlen(pszPath);
  699. if (cbLength > 0) {
  700. cbLength += lstrlen(g_szBackslash) + lstrlen(lpsi->szDriverFile) + 1;
  701. pszTemp = memAlloc( cbLength * sizeof(TCHAR));
  702. if (!pszTemp)
  703. {
  704. idError = RET_ALLOC_ERR;
  705. goto Cleanup;
  706. }
  707. lstrcpy(pszTemp, pszPath);
  708. lstrcat(pszTemp, g_szBackslash);
  709. lstrcat(pszTemp, lpsi->szDriverFile);
  710. } else {
  711. cbLength = lstrlen(lpsi->szDriverFile) + 1;
  712. pszTemp = memAlloc( cbLength * sizeof(TCHAR));
  713. if (!pszTemp)
  714. {
  715. idError = RET_ALLOC_ERR;
  716. goto Cleanup;
  717. }
  718. lstrcpy(pszTemp, lpsi->szDriverFile);
  719. }
  720. // Load the library.
  721. //
  722. hDrv = LoadLibrary(pszTemp);
  723. SetErrorMode(wOldErrorMode);
  724. if (hDrv) {
  725. // We successfully loaded the DLL, now we want to confirm that it's
  726. // a printer driver and get its version. We get ourselves into
  727. // all sorts of trouble by calling into the driver before it's
  728. // actually installed, so simply key off the exported functions.
  729. //
  730. idError = RET_OK;
  731. if (GetProcAddress(hDrv, g_szExtDevModePropSheet)) {
  732. lpsi->dwDriverVersion = 0x0400;
  733. } else if (GetProcAddress(hDrv, g_szExtDevMode)) {
  734. lpsi->dwDriverVersion = 0x0300;
  735. } else if (GetProcAddress(hDrv, g_szDevMode)) {
  736. lpsi->dwDriverVersion = 0x0200;
  737. } else {
  738. lpsi->dwDriverVersion = 0x0000;
  739. idError = RET_INVALID_PRINTER_DRIVER;
  740. }
  741. FreeLibrary(hDrv);
  742. }
  743. Cleanup:
  744. if (pszTemp)
  745. {
  746. memFree(pszTemp, cbLength * sizeof(TCHAR));
  747. }
  748. return idError;
  749. }
  750. /****************************************************************************\
  751. * prv_UpdateICM
  752. *
  753. * Add color profiles to the registry.
  754. *
  755. \****************************************************************************/
  756. BOOL prv_UpdateICM(
  757. LPTSTR lpFiles)
  758. {
  759. TCHAR szPath[_MAX_PATH_];
  760. TCHAR szColor[RES_BUFFER];
  761. UINT wLength;
  762. UINT wColorLength;
  763. LPTSTR lpTemp = szPath;
  764. LPTSTR lpLast = NULL;
  765. BOOL bReturn = FALSE;
  766. // Nothing to do if the dependent file list is NULL or empty
  767. //
  768. if (lpFiles && *lpFiles) {
  769. // Add any color profiles that are referenced by this device.
  770. // First, get the system directory & make sure that it ends
  771. // in a backslash
  772. //
  773. wLength = GetSystemDirectory(szPath, sizeof(szPath));
  774. while (lpLast = prv_StrPBrk(lpTemp, g_szBackslash)) {
  775. lpTemp = lpLast + 1;
  776. if (*lpTemp == TEXT('\0'))
  777. break;
  778. }
  779. if (!lpLast) {
  780. lstrcat(szPath, g_szBackslash);
  781. wLength++;
  782. }
  783. lpLast = szPath + wLength;
  784. // Get the comparison string for the path.
  785. //
  786. if (!LoadString(g_hLibInst, IDS_COLOR_PATH, szColor, RES_BUFFER)) {
  787. lstrcpy(szColor, g_szColorPath);
  788. }
  789. wColorLength = lstrlen(szColor);
  790. lpTemp = lpFiles;
  791. // Now walk down the list of files & compare the beginning of the
  792. // string to "COLOR\\". If it matches, assume that this is a color
  793. // profile and notify the system that it's changing.
  794. //
  795. while (*lpTemp) {
  796. UINT wTempLength = lstrlen(lpTemp);
  797. if (wTempLength > wColorLength) {
  798. BYTE bOldByte = lpTemp[wColorLength];
  799. int nMatch;
  800. lpTemp[wColorLength] = TEXT('\0');
  801. nMatch = lstrcmpi(lpTemp, szColor);
  802. lpTemp[wColorLength] = bOldByte;
  803. if (!nMatch) {
  804. lstrcpy(lpLast, lpTemp);
  805. bReturn |= UpdateICMRegKey(0, 0, szPath, ICM_ADDPROFILE);
  806. }
  807. }
  808. lpTemp += (wTempLength+1);
  809. }
  810. }
  811. return bReturn;
  812. }
  813. /****************************************************************************\
  814. * prv_InstallPrinterDriver
  815. *
  816. * Install a printer-driver into the subsystem. This requires that all
  817. * driver dependent files be copied to the printer-driver-directory.
  818. *
  819. *
  820. * returns: RET_OK : OK.
  821. * RET_USER_CANCEL : User cancelled driver install.
  822. * RET_BROWSE_ERROR : User hits cancel key in browse dialog.
  823. *
  824. \****************************************************************************/
  825. DWORD prv_InstallPrinterDriver(
  826. LPSI lpsi,
  827. HWND hWnd)
  828. {
  829. BOOL bSuccess = FALSE;
  830. DWORD dwResult = RET_OK;
  831. CHAR szPath[_MAX_PATH_];
  832. if (lpsi->wCommand == CMD_INSTALL_DRIVER) {
  833. // Get the driver version
  834. //
  835. if ( _getcwd(szPath, _MAX_PATH_) == NULL)
  836. lstrcpy(szPath, ".");
  837. lpsi->dwDriverVersion = 0;
  838. dwResult = prv_GetDriverVersion(lpsi, szPath);
  839. if (dwResult != RET_OK) {
  840. DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : prv_GetDriverVersion Failed")));
  841. // The AddPrinterDriver code will check the version
  842. // number. I think.
  843. //
  844. lpsi->dwDriverVersion = 0x0400;
  845. }
  846. // Install the printprocessor if one is provided.
  847. //
  848. prv_InstallPrintProcessor(lpsi, szPath);
  849. // Build the driver-info.
  850. //
  851. if (prv_BuildDriverInfo(lpsi)) {
  852. if (!(bSuccess = AddPrinterDriver(NULL, 3, lpsi->lpDriverInfo3))) {
  853. if (ERROR_PRINTER_DRIVER_ALREADY_INSTALLED == GetLastError()) {
  854. bSuccess = TRUE;
  855. }
  856. }
  857. }
  858. if (bSuccess) {
  859. prv_UpdateICM(((LPDRIVER_INFO_3)(lpsi->lpDriverInfo3))->pDependentFiles);
  860. }
  861. }
  862. return RET_OK;
  863. }
  864. /*****************************************************************************\
  865. * GetCommandLineArgs(LPSI, LPCTSTR)
  866. *
  867. * Parse the DAT file to retrieve Web PnP Install options.
  868. *
  869. * LPCWSTR is the name of the dat file. The dat file contains:
  870. *
  871. * /i
  872. * /x Web Print calls
  873. * /b Printer name lpsi*>szFriendly
  874. * /f inf file lpsi*>INFfileName
  875. * /r Port name lpsi*>szPort
  876. * /m Printer model lpsi*>szModel
  877. * /n Share name lpsi*>ShareName
  878. * /a Bin file lpsi*>BinName
  879. *
  880. \*****************************************************************************/
  881. int GetCommandLineArgs(
  882. LPSI lpsi,
  883. LPCTSTR lpDatFile)
  884. {
  885. int i;
  886. int count = 0;
  887. DWORD bytesRead = 0;
  888. LPTSTR lpstrCmd;
  889. HANDLE hFile = NULL;
  890. WCHAR wideBuf[1024];
  891. TCHAR buf[1024];
  892. UCHAR ch;
  893. DBG_MSG(DBG_LEV_INFO, (TEXT("The File to be Read - %s"), lpDatFile));
  894. hFile = CreateFile(lpDatFile,
  895. GENERIC_READ,
  896. FILE_SHARE_READ,
  897. NULL,
  898. OPEN_EXISTING,
  899. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  900. NULL);
  901. if ((hFile == NULL) || (hFile == INVALID_HANDLE_VALUE))
  902. return 0;
  903. i = ReadFile(hFile, (LPVOID)wideBuf, sizeof(wideBuf), &bytesRead, NULL);
  904. CloseHandle(hFile);
  905. if ( i == 0 || bytesRead == 0 )
  906. return 0;
  907. DBG_MSG(DBG_LEV_INFO, (TEXT("Number bytes read - %lu"), bytesRead));
  908. // convert wide buffer to MBCS
  909. //
  910. lstrcpy(buf, g_szNull);
  911. i = WideCharToMultiByte(CP_ACP,
  912. 0,
  913. wideBuf,
  914. -1,
  915. buf,
  916. sizeof(buf),
  917. NULL,
  918. NULL);
  919. if (i == 0) {
  920. DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32: ParseCmdLineArgs: Faild MBCS convert")));
  921. return 0; // 0 args parsed
  922. }
  923. // Our dat-file is in unicode format, so we need to skip over the FFFE
  924. // signature at the beginning of the file.
  925. //
  926. lpstrCmd = buf;
  927. ch = *lpstrCmd++;
  928. ch = *lpstrCmd++;
  929. // skip over any white space
  930. //
  931. while (isspace(ch))
  932. ch = *lpstrCmd++;
  933. DBG_MSG(DBG_LEV_INFO, (TEXT("UCHAR N: %#X"), ch));
  934. // process each switch character '/' or '-' as encountered
  935. //
  936. while (ch == TEXT('/') || ch == TEXT('-')) {
  937. ch = (UCHAR)tolower(*lpstrCmd++);
  938. // process multiple switch characters as needed
  939. //
  940. switch (ch) {
  941. case TEXT('a'): // .bin file name
  942. ch = *lpstrCmd++;
  943. // skip over any following white space
  944. while (isspace(ch)) {
  945. ch = *lpstrCmd++;
  946. }
  947. if (ch != TEXT('"')) {
  948. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid BinFile Name (/a)")));
  949. return RET_INVALID_DAT_FILE;
  950. } else {
  951. // skip over quote
  952. ch = *lpstrCmd++;
  953. // copy the name
  954. i = 0;
  955. while (ch != TEXT('"') && ch != TEXT('\0')) {
  956. lpsi->BinName[i++] = ch;
  957. ch = *lpstrCmd++;
  958. }
  959. lpsi->BinName[i] = TEXT('\0');
  960. if (ch != TEXT('\0'))
  961. ch = *lpstrCmd++;
  962. count++;
  963. }
  964. break;
  965. case TEXT('b'): // printer name
  966. ch = *lpstrCmd++;
  967. // skip over any following white space
  968. while (isspace(ch)) {
  969. ch = *lpstrCmd++;
  970. }
  971. if (ch != TEXT('"')) {
  972. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Printer Name (/b)")));
  973. return RET_INVALID_DAT_FILE;
  974. } else {
  975. // skip over quote
  976. ch = *lpstrCmd++;
  977. // copy the name
  978. i = 0;
  979. while (ch != TEXT('"') && ch != TEXT('\0')) {
  980. lpsi->szFriendly[i++] = ch;
  981. ch = *lpstrCmd++;
  982. }
  983. lpsi->szFriendly[i] = TEXT('\0');
  984. if (ch != TEXT('\0'))
  985. ch = *lpstrCmd++;
  986. count++;
  987. }
  988. break;
  989. case TEXT('f'): // INF file name
  990. ch = *lpstrCmd++;
  991. // skip over any following white space
  992. while (isspace(ch)) {
  993. ch = *lpstrCmd++;
  994. }
  995. if (ch != TEXT('"')) {
  996. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid InfFile Name (/f)")));
  997. return RET_INVALID_DAT_FILE;
  998. } else {
  999. // skip over quote
  1000. ch = *lpstrCmd++;
  1001. // copy the name
  1002. i = 0;
  1003. while (ch != TEXT('"') && ch != TEXT('\0'))
  1004. {
  1005. lpsi->INFfileName[i++] = ch;
  1006. ch = *lpstrCmd++;
  1007. }
  1008. lpsi->INFfileName[i] = TEXT('\0');
  1009. if (ch != '\0')
  1010. ch = *lpstrCmd++;
  1011. count++;
  1012. }
  1013. break;
  1014. case TEXT('i'): // unknown
  1015. ch = *lpstrCmd++; // 'f'
  1016. if (ch != TEXT('\0'))
  1017. ch = *lpstrCmd++; // space
  1018. count++;
  1019. break;
  1020. case TEXT('m'): // printer model
  1021. ch = *lpstrCmd++;
  1022. // skip over any following white space
  1023. while (isspace(ch)) {
  1024. ch = *lpstrCmd++;
  1025. }
  1026. if (ch != '"') {
  1027. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid PrinterModel Name (/m)")));
  1028. return RET_INVALID_DAT_FILE;
  1029. } else {
  1030. // skip over quote
  1031. ch = *lpstrCmd++;
  1032. // copy the name
  1033. i = 0;
  1034. while (ch != TEXT('"') && ch != TEXT('\0'))
  1035. {
  1036. lpsi->szModel[i++] = ch;
  1037. ch = *lpstrCmd++;
  1038. }
  1039. lpsi->szModel[i] = TEXT('\0');
  1040. if (ch != TEXT('\0'))
  1041. ch = *lpstrCmd++;
  1042. count++;
  1043. }
  1044. break;
  1045. case TEXT('n'): // share name
  1046. ch = *lpstrCmd++;
  1047. // skip over any following white space
  1048. while (isspace(ch)) {
  1049. ch = *lpstrCmd++;
  1050. }
  1051. if (ch != TEXT('"')) {
  1052. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Share Name (/n)")));
  1053. return RET_INVALID_DAT_FILE;
  1054. } else {
  1055. // skip over quote
  1056. ch = *lpstrCmd++;
  1057. // copy the name
  1058. i = 0;
  1059. while (ch != TEXT('"') && ch != TEXT('\0'))
  1060. {
  1061. lpsi->ShareName[i++] = ch;
  1062. ch = *lpstrCmd++;
  1063. }
  1064. lpsi->ShareName[i] = TEXT('\0');
  1065. if (ch != TEXT('\0'))
  1066. ch = *lpstrCmd++;
  1067. count++;
  1068. }
  1069. break;
  1070. case TEXT('r'): // port name
  1071. ch = *lpstrCmd++;
  1072. // skip over any following white space
  1073. while (isspace(ch)) {
  1074. ch = *lpstrCmd++;
  1075. }
  1076. if (ch != TEXT('"')) {
  1077. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Port Name (/r)")));
  1078. return RET_INVALID_DAT_FILE;
  1079. } else {
  1080. // skip over quote
  1081. ch = *lpstrCmd++;
  1082. // copy the name
  1083. i = 0;
  1084. while (ch != TEXT('"') && ch != TEXT('\0'))
  1085. {
  1086. lpsi->szPort[i++] = ch;
  1087. ch = *lpstrCmd++;
  1088. }
  1089. lpsi->szPort[i] = TEXT('\0');
  1090. if (ch != TEXT('\0'))
  1091. ch = *lpstrCmd++;
  1092. count++;
  1093. }
  1094. break;
  1095. case TEXT('x'): // unknown
  1096. ch = *lpstrCmd++;
  1097. count++;
  1098. break;
  1099. case TEXT('?'): // help
  1100. MessageBox(NULL, g_szMsgOptions, g_szMsgOptCap, MB_OK);
  1101. break;
  1102. default: /* invalid option */
  1103. DBG_MSG(DBG_LEV_WARN, (TEXT("WPNPIN32: Args - Invalid Option")));
  1104. break;
  1105. } //switch
  1106. while (isspace(ch))
  1107. ch = *lpstrCmd++;
  1108. } // while / or -
  1109. return count;
  1110. }
  1111. /****************************************************************************\
  1112. * PrintLPSI
  1113. *
  1114. * Print out the contents of the LPSI structure.
  1115. *
  1116. \****************************************************************************/
  1117. VOID prv_PrintLPSI(
  1118. LPSI lpsi)
  1119. {
  1120. DBG_MSG(DBG_LEV_INFO, (TEXT("LPSI Structure Dump")));
  1121. DBG_MSG(DBG_LEV_INFO, (TEXT("-------------------")));
  1122. DBG_MSG(DBG_LEV_INFO, (TEXT("dwDriverVersion : %#lX"), lpsi->dwDriverVersion ));
  1123. DBG_MSG(DBG_LEV_INFO, (TEXT("dwUniqueID : %d") , lpsi->dwUniqueID ));
  1124. DBG_MSG(DBG_LEV_INFO, (TEXT("bNetPrinter : %d") , lpsi->bNetPrinter ));
  1125. DBG_MSG(DBG_LEV_INFO, (TEXT("wFilesUsed : %d") , lpsi->wFilesUsed ));
  1126. DBG_MSG(DBG_LEV_INFO, (TEXT("wFilesAllocated : %d") , lpsi->wFilesAllocated ));
  1127. DBG_MSG(DBG_LEV_INFO, (TEXT("wRetryTimeout : %d") , lpsi->wRetryTimeout ));
  1128. DBG_MSG(DBG_LEV_INFO, (TEXT("wDNSTimeout : %d") , lpsi->wDNSTimeout ));
  1129. DBG_MSG(DBG_LEV_INFO, (TEXT("bDontQueueFiles : %d") , lpsi->bDontQueueFiles ));
  1130. DBG_MSG(DBG_LEV_INFO, (TEXT("bNoTestPage : %d") , lpsi->bNoTestPage ));
  1131. DBG_MSG(DBG_LEV_INFO, (TEXT("hModelInf : %d") , lpsi->hModelInf ));
  1132. DBG_MSG(DBG_LEV_INFO, (TEXT("lpPrinterInfo2 : %d") , lpsi->lpPrinterInfo2 ));
  1133. DBG_MSG(DBG_LEV_INFO, (TEXT("lpDriverInfo3 : %d") , lpsi->lpDriverInfo3 ));
  1134. DBG_MSG(DBG_LEV_INFO, (TEXT("szFriendly : %s") , lpsi->szFriendly ));
  1135. DBG_MSG(DBG_LEV_INFO, (TEXT("szModel : %s") , lpsi->szModel ));
  1136. DBG_MSG(DBG_LEV_INFO, (TEXT("szDefaultDataType : %s") , lpsi->szDefaultDataType));
  1137. DBG_MSG(DBG_LEV_INFO, (TEXT("BinName : %s") , lpsi->BinName ));
  1138. DBG_MSG(DBG_LEV_INFO, (TEXT("ShareName : %s") , lpsi->ShareName ));
  1139. DBG_MSG(DBG_LEV_INFO, (TEXT("INFfileName : %s") , lpsi->INFfileName ));
  1140. DBG_MSG(DBG_LEV_INFO, (TEXT("szPort : %s") , lpsi->szPort ));
  1141. DBG_MSG(DBG_LEV_INFO, (TEXT("szDriverFile : %s") , lpsi->szDriverFile ));
  1142. DBG_MSG(DBG_LEV_INFO, (TEXT("szDataFile : %s") , lpsi->szDataFile ));
  1143. DBG_MSG(DBG_LEV_INFO, (TEXT("szConfigFile : %s") , lpsi->szConfigFile ));
  1144. DBG_MSG(DBG_LEV_INFO, (TEXT("szHelpFile : %s") , lpsi->szHelpFile ));
  1145. DBG_MSG(DBG_LEV_INFO, (TEXT("szPrintProcessor : %s") , lpsi->szPrintProcessor ));
  1146. DBG_MSG(DBG_LEV_INFO, (TEXT("szVendorSetup : %s") , lpsi->szVendorSetup ));
  1147. DBG_MSG(DBG_LEV_INFO, (TEXT("szVendorInstaller : %s") , lpsi->szVendorInstaller));
  1148. #if 0
  1149. DWORD cch;
  1150. PTSTR pszFile;
  1151. DBG_MSG(DBG_LEV_INFO, (TEXT("Files:")));
  1152. DBG_MSG(DBG_LEV_INFO, (TEXT("------")));
  1153. for (cch = 0, pszFile = lpsi->lpFiles; *pszFile; pszFile += cch)
  1154. DBG_MSG(DBG_LEV_INFO, (TEXT("%s"), pszFile);
  1155. #endif
  1156. }
  1157. /****************************************************************************\
  1158. * AddOnePrinter
  1159. *
  1160. * Add a single printer (including the driver and print-processor).
  1161. *
  1162. \****************************************************************************/
  1163. DWORD AddOnePrinter(
  1164. LPSI lpsi,
  1165. HWND hWnd)
  1166. {
  1167. DWORD dwResult = RET_OK;
  1168. DWORD cbNeeded;
  1169. TCHAR ch;
  1170. TCHAR srcINF[_MAX_PATH_];
  1171. #if 1 // Since our http:// name is too long for W95, we're going
  1172. // to try basing our name off of the model-name.
  1173. //
  1174. // 28-Jun-1998 : ChrisWil
  1175. lstrcpy(lpsi->szFriendly, lpsi->szModel);
  1176. #endif
  1177. // Build a unique-name from the friendly-name.
  1178. //
  1179. if (prv_FindUniqueName(lpsi->szFriendly)) {
  1180. // Determine if we need to add a new driver. If there is already a
  1181. // driver for this printer, ask if the user wants to re-install or
  1182. // use the old one.
  1183. //
  1184. if ((dwResult = prv_IsThisDriverInstalled(lpsi)) == RET_OK) {
  1185. lpsi->wCommand = 0;
  1186. } else if (dwResult == RET_DRIVER_NOT_FOUND) {
  1187. // Set it up to install the printer driver.
  1188. //
  1189. lpsi->wCommand = CMD_INSTALL_DRIVER;
  1190. dwResult = RET_OK;
  1191. DBG_MSG(DBG_LEV_INFO, (TEXT("WPNPIN32 : AddOnePrinter - Driver Will be installed")));
  1192. }
  1193. // We need info about the driver even if we don't plan to
  1194. // install/re-install it
  1195. //
  1196. if (dwResult == RET_OK) {
  1197. // Get current directory and prepend to INF file name
  1198. //
  1199. if ( _getcwd(srcINF, _MAX_PATH_) == NULL)
  1200. lstrcpy(srcINF, g_szDot);
  1201. lstrcat(srcINF, g_szBackslash);
  1202. lstrcat(srcINF, lpsi->INFfileName);
  1203. lstrcpy(lpsi->INFfileName, srcINF);
  1204. // Get the Printer driver directory and store in lpsi->szRes
  1205. // This is used for copying the files
  1206. //
  1207. GetPrinterDriverDirectory(NULL,
  1208. NULL,
  1209. 1,
  1210. (LPBYTE)lpsi->szDriverDir,
  1211. sizeof(lpsi->szDriverDir),
  1212. &cbNeeded);
  1213. // Parse the INF file and store info in lpsi. This will
  1214. // add the driver to the print subsystem.
  1215. //
  1216. if ((dwResult = ParseINF16(lpsi)) != RET_OK) {
  1217. DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : ParseINF16 - Failed")));
  1218. }
  1219. }
  1220. // Install the printer-driver. This routine will verify if the
  1221. // (lpsi->wCommand indicates whether the driver should be installed.
  1222. //
  1223. if (dwResult == RET_OK)
  1224. dwResult = prv_InstallPrinterDriver(lpsi, hWnd);
  1225. // Install the Printer.
  1226. //
  1227. if (dwResult == RET_OK)
  1228. dwResult = prv_InstallPrinter(lpsi);
  1229. } else {
  1230. DBG_MSG(DBG_LEV_ERROR, (TEXT("WPNPIN32 : AddOnePrinter : UniqueName failure")));
  1231. dwResult = RET_NO_UNIQUE_NAME;
  1232. }
  1233. // Debug output of LPSI.
  1234. //
  1235. prv_PrintLPSI(lpsi);
  1236. // Clean up memory.
  1237. //
  1238. if (lpsi->lpPrinterInfo2) {
  1239. memFree(lpsi->lpPrinterInfo2, memGetSize(lpsi->lpPrinterInfo2));
  1240. lpsi->lpPrinterInfo2 = NULL;
  1241. }
  1242. if (lpsi->lpDriverInfo3) {
  1243. memFree(lpsi->lpDriverInfo3, memGetSize(lpsi->lpDriverInfo3));
  1244. lpsi->lpDriverInfo3 = NULL;
  1245. }
  1246. if (lpsi->lpFiles) {
  1247. HP_GLOBAL_FREE(lpsi->lpFiles);
  1248. lpsi->lpFiles = NULL;
  1249. }
  1250. if (lpsi->lpVcpInfo) {
  1251. HP_GLOBAL_FREE(lpsi->lpVcpInfo);
  1252. lpsi->lpVcpInfo = NULL;
  1253. }
  1254. return dwResult;
  1255. }
  1256. /*****************************************************************************\
  1257. * prvMsgBox
  1258. *
  1259. * Displays a string-id in a messagebox.
  1260. *
  1261. \*****************************************************************************/
  1262. UINT prvMsgBox(
  1263. HWND hWnd,
  1264. LPCTSTR lpszCap,
  1265. UINT idTxt,
  1266. UINT fMB)
  1267. {
  1268. LPTSTR pszTxt;
  1269. UINT uRet = 0;
  1270. if (pszTxt = strLoad(idTxt)) {
  1271. uRet = MessageBox(hWnd, pszTxt, lpszCap, fMB);
  1272. strFree(pszTxt);
  1273. }
  1274. return uRet;
  1275. }