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.

1578 lines
44 KiB

  1. /*---------------------------------------------------------------------------*\
  2. | MODULE: WPNPINST.CXX
  3. |
  4. | This is the main module for the WPNPINST application.
  5. |
  6. | Copyright (C) 1997 Microsoft Corporation
  7. | Copyright (C) 1997 Hewlett Packard
  8. |
  9. | history:
  10. | 25-Jul-1997 <rbkunz> Created.
  11. |
  12. \*---------------------------------------------------------------------------*/
  13. #include "pch.h"
  14. #include <tchar.h>
  15. #define strFree(pszStr) {if (pszStr) GlobalFree((HANDLE)pszStr);}
  16. /*****************************************************************************\
  17. * strAlloc
  18. *
  19. * Allocates a string from the heap. This pointer must be freed with
  20. * a call to strFree().
  21. *
  22. \*****************************************************************************/
  23. LPTSTR strAlloc(
  24. LPCTSTR pszSrc)
  25. {
  26. DWORD cbSize;
  27. LPTSTR pszDst = NULL;
  28. cbSize = (pszSrc ? ((lstrlen(pszSrc) + 1) * sizeof(TCHAR)) : 0);
  29. if (cbSize) {
  30. if (pszDst = (LPTSTR)GlobalAlloc(GPTR, cbSize))
  31. CopyMemory(pszDst, pszSrc, cbSize);
  32. }
  33. return pszDst;
  34. }
  35. /*****************************************************************************\
  36. * strAllocAndCat
  37. *
  38. * Allocates a string from the heap and concattenates another onto it.
  39. * This pointer must be freed with a call to strFree().
  40. *
  41. \*****************************************************************************/
  42. LPTSTR strAllocAndCat(
  43. LPCTSTR pszSrc1,
  44. LPCTSTR pszSrc2)
  45. {
  46. DWORD cbSize;
  47. LPTSTR pszDst = NULL;
  48. cbSize = (pszSrc1 && pszSrc2 ? ((lstrlen(pszSrc1) + lstrlen(pszSrc2) + 1) * sizeof(TCHAR)) : 0);
  49. if (cbSize) {
  50. if (pszDst = (LPTSTR)GlobalAlloc(GPTR, cbSize)) {
  51. CopyMemory(pszDst, pszSrc1, cbSize);
  52. lstrcat( pszDst, pszSrc2 );
  53. }
  54. }
  55. return pszDst;
  56. }
  57. /*****************************************************************************\
  58. * strLoad
  59. *
  60. * Get string from resource based upon the ID passed in.
  61. *
  62. \*****************************************************************************/
  63. LPTSTR strLoad(
  64. UINT ids)
  65. {
  66. TCHAR szStr[MAX_RESBUF];
  67. if (LoadString(g_hInstance, ids, szStr, sizeof(szStr) / sizeof (TCHAR)) == 0)
  68. szStr[0] = TEXT('\0');
  69. return strAlloc(szStr);
  70. }
  71. /*****************************************************************************\
  72. * InitStrings
  73. *
  74. *
  75. \*****************************************************************************/
  76. BOOL InitStrings(VOID)
  77. {
  78. g_szErrorFormat = strLoad(IDS_ERR_FORMAT);
  79. g_szError = strLoad(IDS_ERR_ERROR);
  80. g_szEGeneric = strLoad(IDS_ERR_GENERIC);
  81. g_szEBadCAB = strLoad(IDS_ERR_BADCAB);
  82. g_szEInvalidParameter = strLoad(IDS_ERR_INVPARM);
  83. g_szENoMemory = strLoad(IDS_ERR_NOMEM);
  84. g_szEInvalidCABName = strLoad(IDS_ERR_INVNAME);
  85. g_szENoDATFile = strLoad(IDS_ERR_NODAT);
  86. g_szECABExtract = strLoad(IDS_ERR_CABFAIL);
  87. g_szENoPrintUI = strLoad(IDS_ERR_NOPRTUI);
  88. g_szENoPrintUIEntry = strLoad(IDS_ERR_PRTUIENTRY);
  89. g_szEPrintUIEntryFail = strLoad(IDS_ERR_PRTUIFAIL);
  90. g_szENotSupported = strLoad(IDS_ERR_NOSUPPORT);
  91. return (g_szErrorFormat &&
  92. g_szError &&
  93. g_szEGeneric &&
  94. g_szEBadCAB &&
  95. g_szEInvalidParameter &&
  96. g_szENoMemory &&
  97. g_szEInvalidCABName &&
  98. g_szENoDATFile &&
  99. g_szECABExtract &&
  100. g_szENoPrintUI &&
  101. g_szENoPrintUIEntry &&
  102. g_szEPrintUIEntryFail &&
  103. g_szENotSupported
  104. );
  105. }
  106. /*****************************************************************************\
  107. * FreeeStrings
  108. *
  109. *
  110. \*****************************************************************************/
  111. VOID FreeStrings(VOID)
  112. {
  113. strFree(g_szErrorFormat);
  114. strFree(g_szError);
  115. strFree(g_szEGeneric);
  116. strFree(g_szEBadCAB);
  117. strFree(g_szEInvalidParameter);
  118. strFree(g_szENoMemory);
  119. strFree(g_szEInvalidCABName);
  120. strFree(g_szENoDATFile);
  121. strFree(g_szECABExtract);
  122. strFree(g_szENoPrintUI);
  123. strFree(g_szENoPrintUIEntry);
  124. strFree(g_szEPrintUIEntryFail);
  125. strFree(g_szENotSupported);
  126. }
  127. /*****************************************************************************\
  128. *
  129. * Win32Open (Local Routine)
  130. *
  131. * Translate a C-Runtime _open() call into appropriate Win32 CreateFile()
  132. *
  133. * NOTE: Doesn't fully implement C-Runtime _open()
  134. * capability but it currently supports all callbacks
  135. * that FDI will give us
  136. *
  137. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  138. *
  139. \*****************************************************************************/
  140. HANDLE Win32Open( LPCTSTR pszFile, int oflag, int pmode )
  141. {
  142. HANDLE FileHandle;
  143. BOOL fExists = FALSE;
  144. DWORD fAccess;
  145. DWORD fCreate;
  146. // NOTE: No Append Mode Support
  147. if (oflag & _O_APPEND)
  148. return INVALID_HANDLE_VALUE;
  149. // Set Read-Write Access
  150. if ((oflag & _O_RDWR) || (oflag & _O_WRONLY))
  151. fAccess = GENERIC_WRITE;
  152. else
  153. fAccess = GENERIC_READ;
  154. // Set Create Flags
  155. if (oflag & _O_CREAT) {
  156. if (oflag & _O_EXCL)
  157. fCreate = CREATE_NEW;
  158. else if (oflag & _O_TRUNC)
  159. fCreate = CREATE_ALWAYS;
  160. else
  161. fCreate = OPEN_ALWAYS;
  162. } else {
  163. if (oflag & _O_TRUNC)
  164. fCreate = TRUNCATE_EXISTING;
  165. else
  166. fCreate = OPEN_EXISTING;
  167. }
  168. FileHandle = CreateFile( pszFile, fAccess, FILE_SHARE_READ, NULL, fCreate,
  169. FILE_ATTRIBUTE_NORMAL, NULL );
  170. // NOTE: Doesn't create directories like C runtime.
  171. // We don't need this capability for this app though.
  172. // All our directories will already exist
  173. return FileHandle;
  174. }
  175. /******************************************************************************\
  176. *
  177. * openfunc (Local Routine)
  178. *
  179. * Opens a file. Used by FDI interface.
  180. *
  181. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  182. *
  183. \******************************************************************************/
  184. INT_PTR FAR DIAMONDAPI openfunc( CHAR FAR *pszFile, INT oflag, INT pmode ) {
  185. INT rc;
  186. INT i;
  187. // Find Available File Handle in Fake File Table
  188. for ( i = 0; i < FILETABLESIZE; i++ ) {
  189. if ( g_FileTable[i].bAvailable == TRUE ) {
  190. break;
  191. }
  192. }
  193. // Running out of file handles should never happen
  194. if ( i == FILETABLESIZE ) {
  195. rc = C_RUNTIME_IO_ERROR;
  196. }
  197. #ifdef UNICODE
  198. {
  199. TCHAR uchFileName[_MAX_PATH] = {0};
  200. mbstowcs(uchFileName, pszFile, _MAX_PATH);
  201. g_FileTable[i].hFile = Win32Open(uchFileName, oflag, pmode );
  202. }
  203. #else
  204. g_FileTable[i].hFile = Win32Open(pszFile, oflag, pmode );
  205. #endif
  206. if ( g_FileTable[i].hFile != INVALID_HANDLE_VALUE ) {
  207. g_FileTable[i].bAvailable = FALSE;
  208. rc = i;
  209. } else {
  210. rc = C_RUNTIME_IO_ERROR;
  211. }
  212. return rc;
  213. }
  214. #ifdef UNICODE
  215. /******************************************************************************\
  216. *
  217. * openfunc (Local Routine)
  218. *
  219. * Opens a file. Used by FDINotify.
  220. *
  221. \******************************************************************************/
  222. INT_PTR FAR DIAMONDAPI openfuncW( WCHAR FAR *pszFile, INT oflag, INT pmode ) {
  223. INT rc;
  224. INT i;
  225. // Find Available File Handle in Fake File Table
  226. for ( i = 0; i < FILETABLESIZE; i++ ) {
  227. if ( g_FileTable[i].bAvailable == TRUE ) {
  228. break;
  229. }
  230. }
  231. // Running out of file handles should never happen
  232. if ( i == FILETABLESIZE ) {
  233. rc = C_RUNTIME_IO_ERROR;
  234. }
  235. g_FileTable[i].hFile = Win32Open(pszFile, oflag, pmode );
  236. if ( g_FileTable[i].hFile != INVALID_HANDLE_VALUE ) {
  237. g_FileTable[i].bAvailable = FALSE;
  238. rc = i;
  239. } else {
  240. rc = C_RUNTIME_IO_ERROR;
  241. }
  242. return rc;
  243. }
  244. #endif
  245. /******************************************************************************\
  246. *
  247. * closefunc (Local Routine)
  248. *
  249. * Closes a file. Used by FDI interface.
  250. *
  251. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  252. *
  253. \******************************************************************************/
  254. INT FAR DIAMONDAPI closefunc( INT_PTR hf ) {
  255. INT rc;
  256. if ( CloseHandle( g_FileTable[hf].hFile ) ) {
  257. rc = 0;
  258. g_FileTable[hf].bAvailable = TRUE;
  259. } else {
  260. rc = C_RUNTIME_IO_ERROR;
  261. }
  262. return rc;
  263. }
  264. /******************************************************************************\
  265. *
  266. * readfunc (Local Routine)
  267. *
  268. * Reads a file. Used by FDI interface.
  269. *
  270. \******************************************************************************/
  271. UINT FAR DIAMONDAPI readfunc( INT_PTR hf, PVOID pv, UINT cb ) {
  272. INT rc;
  273. INT cbRead;
  274. if ( ! ReadFile( g_FileTable[hf].hFile, pv, cb, (DWORD *) &cb, NULL ) ) {
  275. rc = C_RUNTIME_IO_ERROR;
  276. } else {
  277. rc = cb;
  278. }
  279. return rc;
  280. }
  281. /******************************************************************************\
  282. *
  283. * writefunc (Local Routine)
  284. *
  285. * Writes a file. Used by FDI interface
  286. *
  287. \******************************************************************************/
  288. UINT FAR DIAMONDAPI writefunc( INT_PTR hf, PVOID pv, UINT cb ) {
  289. INT rc;
  290. if ( ! WriteFile( g_FileTable[hf].hFile, pv, cb, (DWORD *) &cb, NULL ) ) {
  291. rc = C_RUNTIME_IO_ERROR;
  292. } else {
  293. rc = cb;
  294. }
  295. return rc;
  296. }
  297. /******************************************************************************\
  298. *
  299. * seekfunc (Local Routine)
  300. *
  301. * Repositions the file pointer. Used by FDI interface.
  302. *
  303. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  304. *
  305. \******************************************************************************/
  306. LONG FAR DIAMONDAPI seekfunc( INT_PTR hf, LONG dist, INT seektype ) {
  307. LONG rc;
  308. DWORD dwResult;
  309. DWORD W32seektype;
  310. switch (seektype) {
  311. case SEEK_SET:
  312. W32seektype = FILE_BEGIN;
  313. break;
  314. case SEEK_CUR:
  315. W32seektype = FILE_CURRENT;
  316. break;
  317. case SEEK_END:
  318. W32seektype = FILE_END;
  319. break;
  320. }
  321. dwResult = SetFilePointer(g_FileTable[hf].hFile, dist, NULL, W32seektype);
  322. if (dwResult == 0xFFFFFFFF) {
  323. rc = C_RUNTIME_SEEK_ERROR;
  324. }
  325. else
  326. rc = (LONG)dwResult;
  327. return rc;
  328. }
  329. /******************************************************************************\
  330. *
  331. * allocfunc (Local Routine)
  332. *
  333. * Allocates memory. Used by FDI interface.
  334. *
  335. \******************************************************************************/
  336. void HUGE * FAR DIAMONDAPI allocfunc(ULONG cb) {
  337. PVOID pv;
  338. pv = (PVOID) GlobalAlloc( GPTR, cb );
  339. return pv;
  340. }
  341. /******************************************************************************\
  342. *
  343. * freefunc (Local Routine)
  344. *
  345. * Frees memory. Used by FDI interface.
  346. *
  347. \******************************************************************************/
  348. void FAR DIAMONDAPI freefunc(void HUGE *pv) {
  349. GlobalFree( pv );
  350. }
  351. /******************************************************************************\
  352. *
  353. * AdjustFileTime (Local Routine)
  354. *
  355. * Sets file time.
  356. *
  357. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  358. *
  359. \******************************************************************************/
  360. BOOL AdjustFileTime( INT_PTR hf, USHORT date, USHORT time )
  361. {
  362. FILETIME ft;
  363. FILETIME ftUTC;
  364. if ( ! DosDateTimeToFileTime( date, time, &ft ) ) {
  365. return FALSE;
  366. }
  367. if ( ! LocalFileTimeToFileTime( &ft, &ftUTC ) ) {
  368. return FALSE;
  369. }
  370. if ( ! SetFileTime( g_FileTable[hf].hFile, &ftUTC, &ftUTC, &ftUTC ) ) {
  371. return FALSE;
  372. }
  373. return TRUE;
  374. }
  375. /******************************************************************************\
  376. *
  377. * Attr32FromAttrFAT (Local Routine)
  378. *
  379. * Translate FAT attributes to Win32 Attributes
  380. *
  381. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  382. *
  383. \******************************************************************************/
  384. DWORD Attr32FromAttrFAT( WORD attrMSDOS )
  385. {
  386. //** Quick out for normal file special case
  387. if (attrMSDOS == _A_NORMAL) {
  388. return FILE_ATTRIBUTE_NORMAL;
  389. }
  390. //** Otherwise, mask off read-only, hidden, system, and archive bits
  391. // NOTE: These bits are in the same places in MS-DOS and Win32!
  392. return attrMSDOS & (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
  393. }
  394. /******************************************************************************\
  395. *
  396. * fdiNotify (Local Routine)
  397. *
  398. * Processes Notification messages from FDI interface.
  399. *
  400. * Leveraged from nt\private\inet\setup\iexpress\wextract\wextract.c
  401. *
  402. \******************************************************************************/
  403. INT_PTR FAR DIAMONDAPI fdiNotify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin) {
  404. INT_PTR fh; // File Handle
  405. LPTSTR lpszFile; // Current File
  406. PWPNPINFO pInfo; // Pointer to a "Web-Point-N-Print" info structure
  407. INT_PTR nReturn;
  408. DWORD dwError;
  409. // The user-defined 'pv' is a pointer to our saved info
  410. pInfo = (PWPNPINFO)pfdin->pv;
  411. nReturn = 0;
  412. switch ( fdint ) {
  413. //*******************************************************************
  414. case fdintCABINET_INFO:
  415. nReturn = 0;
  416. break;
  417. //*******************************************************************
  418. case fdintCOPY_FILE:
  419. nReturn = C_RUNTIME_IO_ERROR;
  420. {
  421. #ifdef UNICODE
  422. TCHAR uchFileName[_MAX_PATH] = {0};
  423. mbstowcs(uchFileName, pfdin->psz1, _MAX_PATH);
  424. if (NULL != (lpszFile = BuildFileName((LPCTSTR)pInfo->pTempDir, uchFileName))) {
  425. fh = openfuncW( lpszFile, _O_BINARY | _O_TRUNC | _O_RDWR |
  426. _O_CREAT, _S_IREAD | _S_IWRITE );
  427. #else
  428. if (NULL != (lpszFile = BuildFileName((LPCTSTR)pInfo->pTempDir, (LPCTSTR)pfdin->psz1))) {
  429. fh = openfunc( lpszFile, _O_BINARY | _O_TRUNC | _O_RDWR |
  430. _O_CREAT, _S_IREAD | _S_IWRITE );
  431. #endif
  432. if (C_RUNTIME_IO_ERROR != fh) {
  433. if (AddFileToList(pInfo, lpszFile)) {
  434. nReturn = fh;
  435. }
  436. else {
  437. closefunc(fh);
  438. }
  439. }
  440. GlobalFree(lpszFile);
  441. }
  442. }
  443. break;
  444. //*******************************************************************
  445. case fdintCLOSE_FILE_INFO:
  446. nReturn = C_RUNTIME_IO_ERROR;
  447. if (AdjustFileTime( pfdin->hf, pfdin->date, pfdin->time ) ) {
  448. closefunc( pfdin->hf );
  449. {
  450. #ifdef UNICODE
  451. TCHAR uchFileName[_MAX_PATH] = {0};
  452. mbstowcs(uchFileName, pfdin->psz1, _MAX_PATH);
  453. if (NULL != (lpszFile = BuildFileName((LPCTSTR)pInfo->pTempDir, uchFileName))) {
  454. #else
  455. if (NULL != (lpszFile = BuildFileName((LPCTSTR)pInfo->pTempDir, (LPCTSTR)pfdin->psz1))) {
  456. #endif
  457. if (SetFileAttributes( lpszFile, Attr32FromAttrFAT( pfdin->attribs ) ) ) {
  458. nReturn = TRUE;
  459. }
  460. GlobalFree(lpszFile);
  461. }
  462. }
  463. }
  464. break;
  465. //*******************************************************************
  466. case fdintPARTIAL_FILE:
  467. nReturn = 0;
  468. break;
  469. //*******************************************************************
  470. case fdintNEXT_CABINET:
  471. nReturn = 0;
  472. break;
  473. //*******************************************************************
  474. case fdintENUMERATE:
  475. nReturn = 0;
  476. break;
  477. //*******************************************************************
  478. default:
  479. break;
  480. }
  481. return nReturn;
  482. }
  483. /*****************************************************************************\
  484. * GetCurDir
  485. *
  486. * Returns string indicating current-directory.
  487. *
  488. \*****************************************************************************/
  489. LPTSTR GetCurDir(VOID)
  490. {
  491. DWORD cbSize;
  492. LPTSTR lpszDir = NULL;
  493. cbSize = GetCurrentDirectory(0, NULL);
  494. if (cbSize && (lpszDir = (LPTSTR)GlobalAlloc(GPTR, (cbSize * sizeof(TCHAR)))))
  495. GetCurrentDirectory(cbSize, lpszDir);
  496. return lpszDir;
  497. }
  498. /*****************************************************************************\
  499. * WCFromMB (Local Routine)
  500. *
  501. * This routine returns a buffer of wide-character representation of a
  502. * ansi string. The caller is responsible for freeing this pointer returned
  503. * by this function.
  504. *
  505. \*****************************************************************************/
  506. LPWSTR WCFromMB(
  507. LPCSTR lpszStr)
  508. {
  509. DWORD cbSize;
  510. DWORD dwChars;
  511. LPWSTR lpwszBuf = NULL;
  512. cbSize = 0;
  513. dwChars = (DWORD)MultiByteToWideChar(CP_ACP,
  514. MB_PRECOMPOSED,
  515. lpszStr,
  516. -1,
  517. lpwszBuf,
  518. (int)(cbSize / sizeof(WCHAR)));
  519. cbSize = dwChars * sizeof(WCHAR);
  520. if (cbSize && (lpwszBuf = (LPWSTR)GlobalAlloc(GPTR, cbSize)))
  521. MultiByteToWideChar(CP_ACP,
  522. MB_PRECOMPOSED,
  523. lpszStr,
  524. -1,
  525. lpwszBuf,
  526. (int)(cbSize / sizeof(WCHAR)));
  527. return lpwszBuf;
  528. }
  529. /*****************************************************************************\
  530. * WCFromTC (Local Routine)
  531. *
  532. * This routine returns a buffer of wide-character representation of a
  533. * TCHAR string. The caller is responsible for freeing this pointer returned
  534. * by this function.
  535. *
  536. \*****************************************************************************/
  537. LPWSTR WCFromTC(
  538. LPCTSTR lpszStr)
  539. {
  540. DWORD cbSize;
  541. DWORD dwChars;
  542. LPWSTR lpwszBuf = NULL;
  543. cbSize = 0;
  544. #ifdef UNICODE
  545. return (LPWSTR) lpszStr;
  546. #else
  547. return WCFromMB(lpszStr);
  548. #endif
  549. }
  550. /******************************************************************************\
  551. *
  552. * BuildFileName (Local Routine)
  553. *
  554. * Concatenates a path and file to produce a full pathname.
  555. *
  556. \******************************************************************************/
  557. LPTSTR BuildFileName(
  558. LPCTSTR lpszPath,
  559. LPCTSTR lpszName)
  560. {
  561. BOOL bReturn = FALSE;
  562. LPTSTR lpszMessage = NULL;
  563. INT cch = 0;
  564. UINT_PTR Args[MAX_ARGS];
  565. // Calculate the size necessary to hold the full-path filename.
  566. //
  567. cch += (lpszPath ? lstrlen(lpszPath) : 0);
  568. cch += (lpszName ? lstrlen(lpszName) : 0);
  569. // Concatenate the path and file
  570. //
  571. if (lpszPath) {
  572. Args[0] = (UINT_PTR) lpszPath;
  573. Args[1] = (UINT_PTR) lpszName;
  574. Args[2] = 0;
  575. if (0 != (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  576. g_szFNFmt,
  577. 0,
  578. 0,
  579. (LPTSTR)&lpszMessage,
  580. 0,
  581. (va_list*)Args ))) {
  582. bReturn = TRUE;
  583. }
  584. }
  585. return lpszMessage;
  586. }
  587. /******************************************************************************\
  588. *
  589. * GetDirectory (Local Routine)
  590. *
  591. * Returns the directory portion of a full pathname.
  592. *
  593. \******************************************************************************/
  594. LPTSTR GetDirectory(LPTSTR lpszFile, LPDWORD lpdwReturn) {
  595. LPTSTR lpszSlash;
  596. LPTSTR lpszDir;
  597. lpszSlash = _tcsrchr(lpszFile, g_chBackslash);
  598. if (lpszSlash != NULL) {
  599. if (NULL != (lpszDir = (LPTSTR)GlobalAlloc(GPTR, (lpszSlash - lpszFile + 2) * sizeof(TCHAR)))) {
  600. lstrcpyn(lpszDir, lpszFile, (UINT32)((UINT_PTR)lpszSlash - (UINT_PTR)lpszFile) / sizeof(TCHAR) + 2);
  601. *lpdwReturn = ERR_NONE;
  602. return lpszDir;
  603. }
  604. else {
  605. *lpdwReturn = ERR_NO_MEMORY;
  606. }
  607. }
  608. else {
  609. *lpdwReturn = ERR_INVALID_PARAMETER;
  610. }
  611. return NULL;
  612. }
  613. /******************************************************************************\
  614. *
  615. * GetName (Local Routine)
  616. *
  617. * Returns the filename portion of a full pathname.
  618. *
  619. \******************************************************************************/
  620. LPTSTR GetName(LPTSTR lpszFile, LPDWORD lpdwReturn) {
  621. LPTSTR lpszSlash;
  622. LPTSTR lpszName;
  623. int nLength;
  624. lpszSlash = _tcsrchr(lpszFile, g_chBackslash);
  625. if (lpszSlash != NULL) {
  626. nLength = lstrlen(lpszSlash);
  627. if (NULL != (lpszName = (LPTSTR)GlobalAlloc(GPTR, (nLength * sizeof(TCHAR))))) {
  628. lstrcpyn(lpszName, ++lpszSlash, nLength);
  629. *lpdwReturn = ERR_NONE;
  630. return lpszName;
  631. }
  632. else {
  633. *lpdwReturn = ERR_NO_MEMORY;
  634. }
  635. }
  636. else {
  637. *lpdwReturn = ERR_INVALID_PARAMETER;
  638. }
  639. return NULL;
  640. }
  641. /******************************************************************************\
  642. *
  643. * CreateTempDirectory (Local Routine)
  644. *
  645. * Creates a unique temp directory to extract files into.
  646. *
  647. \******************************************************************************/
  648. LPTSTR CreateTempDirectory() {
  649. LPTSTR pReturnDir = NULL;
  650. LPTSTR pTempDir;
  651. LPTSTR pCurrDir;
  652. LPTSTR pWinDir;
  653. DWORD dwRequired = 0;
  654. // Save the current directory in pCurrDir
  655. //
  656. if (dwRequired = GetCurrentDirectory(0, NULL)) {
  657. if (pCurrDir = (LPTSTR)GlobalAlloc(GPTR, dwRequired * sizeof(TCHAR))) {
  658. if (GetCurrentDirectory(dwRequired, pCurrDir) <= dwRequired) {
  659. // We need to set the current directory to something reasonable (something
  660. // besides the desktop), because GetTempPath() will use the current directory
  661. // if no TEMP or TMP variable is set. This will ensure that a user that saves the
  662. // downloaded .wpnp cab file on the desktop and later runs it will not get the cab
  663. // files extracted to the desktop.
  664. //
  665. if (dwRequired = GetWindowsDirectory(NULL, 0)) {
  666. if (pWinDir = (LPTSTR)GlobalAlloc(GPTR, dwRequired * sizeof(TCHAR))) {
  667. if (GetWindowsDirectory(pWinDir, dwRequired) <= dwRequired) {
  668. if (SetCurrentDirectory(pWinDir)) {
  669. // Get the temp path, so we can create a temp directory
  670. // to extract the cabinet file into
  671. //
  672. if (dwRequired = GetTempPath(0, NULL)) {
  673. if (pTempDir = (LPTSTR)GlobalAlloc(GPTR, dwRequired * sizeof(TCHAR))) {
  674. if (GetTempPath(dwRequired, pTempDir) <= dwRequired) {
  675. // Now create a unique temp file name.
  676. //
  677. if (pReturnDir = (LPTSTR)GlobalAlloc(GPTR, MAX_PATH * sizeof(TCHAR))) {
  678. if (GetTempFileName(pTempDir, g_szTNFmt, 0, pReturnDir)) {
  679. // But what we really needed was a directory, so delete the file (now that
  680. // we know that we have a unique name) and create a directory with
  681. // the same name as the file.
  682. //
  683. DeleteFile(pReturnDir);
  684. if (!CreateDirectory(pReturnDir, NULL)) {
  685. GlobalFree(pReturnDir);
  686. pReturnDir = NULL;
  687. }
  688. // else We succeeded in creating the temp dir.
  689. //
  690. }
  691. // else we can't create a temp directory...cleanup.
  692. //
  693. else {
  694. GlobalFree(pReturnDir);
  695. pReturnDir = NULL;
  696. }
  697. }
  698. }
  699. GlobalFree(pTempDir);
  700. }
  701. }
  702. }
  703. }
  704. GlobalFree(pWinDir);
  705. }
  706. }
  707. // Restore saved current directory
  708. SetCurrentDirectory(pCurrDir);
  709. }
  710. GlobalFree(pCurrDir);
  711. }
  712. }
  713. return pReturnDir;
  714. }
  715. #if 0
  716. // The following 4 functions #ifdef'ed out on 11/6/97 RK
  717. // PrintUI will call SetupX Catalog Verification APIs
  718. // We don't need to verify any more
  719. /******************************************************************************\
  720. *
  721. * RemoveExecutableFiles (Local Routine)
  722. *
  723. * Deletes executable files in the file list.
  724. *
  725. \******************************************************************************/
  726. BOOL RemoveExecutableFiles(PWPNPINFO pInfo) {
  727. PFILENODE pFileNode;
  728. pFileNode = pInfo->pFileList;
  729. while (pFileNode) {
  730. if (IsExecutableFile(pFileNode->pFileName)) {
  731. DeleteFile(pFileNode->pFileName);
  732. }
  733. pFileNode = pFileNode->pNextFile;
  734. }
  735. return TRUE;
  736. }
  737. /******************************************************************************\
  738. *
  739. * IsExecutableFile (Local Routine)
  740. *
  741. * Determines if a file is an executable module.
  742. *
  743. * NOTE: Can we check the actual file rather than just the extension?
  744. *
  745. \******************************************************************************/
  746. BOOL IsExecutableFile(LPTSTR pFile) {
  747. BOOL bReturn = FALSE;
  748. LPTSTR pTemp = NULL;
  749. if (NULL != (pTemp = _tcsrchr(pFile, g_chDot)) ) {
  750. if (!lstrcmpi(pTemp, g_szDotDLL) || !lstrcmpi(pTemp, g_szDotEXE)) {
  751. bReturn = TRUE;
  752. }
  753. }
  754. return bReturn;
  755. }
  756. /******************************************************************************\
  757. *
  758. * CheckFile (Local Routine)
  759. *
  760. * Does an Authenticode check on a file.
  761. *
  762. \******************************************************************************/
  763. DWORD CheckFile(LPTSTR lpszFile, LPDWORD lpAuthError) {
  764. GUID gV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  765. WINTRUST_DATA sWTD;
  766. WINTRUST_FILE_INFO sWTFI;
  767. LPWSTR lpwszFileName;
  768. DWORD dwReturn;
  769. dwReturn = ERR_GENERIC;
  770. if (NULL != (lpwszFileName = WCFromTC(lpszFile))) {
  771. memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
  772. memset(&sWTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
  773. sWTD.cbStruct = sizeof(WINTRUST_DATA);
  774. sWTD.dwUIChoice = WTD_UI_ALL;
  775. sWTD.dwUnionChoice = WTD_CHOICE_FILE;
  776. sWTD.pFile = &sWTFI;
  777. sWTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
  778. sWTFI.hFile = NULL;
  779. sWTFI.pcwszFilePath = lpwszFileName;
  780. *lpAuthError = WinVerifyTrust(NULL, &gV2, &sWTD);
  781. dwReturn = ERR_NONE;
  782. GlobalFree(lpwszFileName);
  783. }
  784. else {
  785. dwReturn = ERR_NO_MEMORY;
  786. }
  787. return dwReturn;
  788. }
  789. /******************************************************************************\
  790. *
  791. * VerifyFiles (Local Routine)
  792. *
  793. * Does Authenticode verification on all executable files in the filelist.
  794. *
  795. \******************************************************************************/
  796. DWORD VerifyFiles(PWPNPINFO pInfo, LPDWORD lpAuthError) {
  797. DWORD dwReturn;
  798. BOOL bContinue;
  799. PFILENODE pFileNode;
  800. pFileNode = pInfo->pFileList;
  801. bContinue = TRUE;
  802. dwReturn = ERR_NONE;
  803. *lpAuthError = ERROR_SUCCESS;
  804. while (bContinue && pFileNode) {
  805. if (IsExecutableFile(pFileNode->pFileName)) {
  806. bContinue = FALSE;
  807. dwReturn = CheckFile(pFileNode->pFileName, lpAuthError);
  808. if (*lpAuthError == ERROR_SUCCESS) {
  809. bContinue = TRUE;
  810. }
  811. else {
  812. if (*lpAuthError == TRUST_E_SUBJECT_NOT_TRUSTED) {
  813. // The user didn't accept the signed/unsigned files
  814. // Delete the executable files here, so that the print wizard
  815. // will prompt the user for the files instead of using the downloaded files.
  816. RemoveExecutableFiles(pInfo);
  817. *lpAuthError = ERROR_SUCCESS;
  818. }
  819. else {
  820. dwReturn = ERR_AUTHENTICODE;
  821. }
  822. }
  823. }
  824. pFileNode = pFileNode->pNextFile;
  825. }
  826. return dwReturn;
  827. }
  828. #endif
  829. /******************************************************************************\
  830. *
  831. * GetCABName (Local Routine)
  832. *
  833. * Parses the CAB name from the command line.
  834. *
  835. \******************************************************************************/
  836. PTSTR GetCABName(PTSTR pCmdLine, LPDWORD lpdwReturn) {
  837. PTSTR pEnd = 0;
  838. PTSTR pPtr;
  839. PTSTR pName;
  840. pPtr = pCmdLine;
  841. if (pPtr) {
  842. if (*pPtr == g_chDoubleQuote) {
  843. pPtr++;
  844. pEnd = _tcschr(pPtr, g_chDoubleQuote);
  845. if (pEnd)
  846. *pEnd = 0;
  847. }
  848. // If we haven't found an End-Quote, treat it as the end of the string.
  849. if (pEnd == NULL)
  850. pEnd = pPtr + lstrlen(pPtr);
  851. if (pName = (PTSTR)GlobalAlloc(GPTR, (pEnd - pPtr + 1) * sizeof(TCHAR))) {
  852. lstrcpyn(pName, pPtr, (UINT32) (pEnd - pPtr + 1));
  853. *lpdwReturn = ERR_NONE;
  854. }
  855. else {
  856. *lpdwReturn = ERR_NO_MEMORY;
  857. }
  858. return pName;
  859. }
  860. else {
  861. *lpdwReturn = ERR_INVALID_PARAMETER;
  862. }
  863. return NULL;
  864. }
  865. /******************************************************************************\
  866. *
  867. * AddFileToList (Local Routine)
  868. *
  869. * Adds a file to the list of extracted files.
  870. *
  871. \******************************************************************************/
  872. BOOL AddFileToList(PWPNPINFO pInfo, PTSTR lpszFile) {
  873. PFILENODE pInsertHere;
  874. BOOL bReturn;
  875. bReturn = FALSE;
  876. if (NULL == (pInfo->pFileList)) {
  877. if (NULL != (pInfo->pFileList = (PFILENODE)GlobalAlloc(GPTR, sizeof(FILENODE)))) {
  878. pInsertHere = pInfo->pFileList;
  879. pInsertHere->pNextFile = NULL;
  880. bReturn = TRUE;
  881. }
  882. }
  883. else {
  884. if (NULL != (pInsertHere = (PFILENODE)GlobalAlloc(GPTR, sizeof(FILENODE)))) {
  885. pInsertHere->pNextFile = pInfo->pFileList;
  886. pInfo->pFileList = pInsertHere;
  887. bReturn = TRUE;
  888. }
  889. }
  890. if (bReturn && (NULL != (pInsertHere->pFileName = (LPTSTR)GlobalAlloc(GPTR, (lstrlen(lpszFile) + 1) *sizeof(TCHAR))) ) ) {
  891. lstrcpyn(pInsertHere->pFileName, lpszFile, lstrlen(lpszFile) + 1);
  892. bReturn = TRUE;
  893. }
  894. else {
  895. bReturn = FALSE;
  896. }
  897. return bReturn;
  898. }
  899. /******************************************************************************\
  900. *
  901. * FreeFileList (Local Routine)
  902. *
  903. * Frees memory allocated for file list.
  904. *
  905. \******************************************************************************/
  906. VOID CleanupFileList(PWPNPINFO pInfo) {
  907. PFILENODE pCurrentNode, pNextNode;
  908. HANDLE hFindFind;
  909. LPTSTR lpstrPos;
  910. LPTSTR lpstrTemp;
  911. WIN32_FIND_DATA FindData;
  912. pCurrentNode = pInfo->pFileList;
  913. // Erase all extracted files and cleanup our memory structure.
  914. while (pCurrentNode) {
  915. if (!DeleteFile(pCurrentNode->pFileName)) {
  916. // We might have renamed one of our original cat files to this name. So
  917. // look for poem*.cat in the same directory
  918. lpstrPos = _tcsrchr(pCurrentNode->pFileName, TEXT('\\') );
  919. if (lpstrPos) {
  920. lpstrPos[1] = TEXT('\0');
  921. // Now pCurrentNode->pFileName has our directory path
  922. lpstrTemp = strAllocAndCat( pCurrentNode->pFileName , TEXT("poem*.cat") );
  923. if (lpstrTemp) {
  924. hFindFind = FindFirstFile( lpstrTemp , &FindData );
  925. if (hFindFind != INVALID_HANDLE_VALUE) {
  926. // Delete the file
  927. DeleteFile( FindData.cFileName );
  928. FindClose( hFindFind );
  929. }
  930. strFree( lpstrTemp );
  931. }
  932. }
  933. }
  934. pNextNode = pCurrentNode->pNextFile;
  935. GlobalFree(pCurrentNode);
  936. pCurrentNode = pNextNode;
  937. }
  938. pInfo->pFileList = NULL;
  939. }
  940. /******************************************************************************\
  941. *
  942. * Extract (Local Routine)
  943. *
  944. * Extracts all files from the CAB file and adds them to a file list.
  945. *
  946. \******************************************************************************/
  947. BOOL Extract(PWPNPINFO pInfo) {
  948. HFDI hfdi;
  949. ERF erf;
  950. INT nError;
  951. BOOL bReturn;
  952. int i;
  953. bReturn = FALSE;
  954. // Initialize file table
  955. for ( i = 0; i < FILETABLESIZE; i++ ) {
  956. g_FileTable[i].bAvailable = TRUE;
  957. }
  958. hfdi = FDICreate( allocfunc, freefunc, openfunc, readfunc, writefunc,
  959. closefunc, seekfunc, cpu80386, &erf);
  960. if (NULL != hfdi){
  961. #ifdef UNICODE
  962. char achCABName[_MAX_PATH]={0}, achCABDir[_MAX_DIR]={0};
  963. wcstombs(achCABName, pInfo->pCABName, sizeof(achCABName));
  964. wcstombs(achCABDir, pInfo->pCABDir, sizeof(achCABDir));
  965. if (0 != (nError = FDICopy(hfdi, achCABName, achCABDir, 0, fdiNotify, NULL, (LPVOID)(pInfo))))
  966. #else
  967. if (0 != (nError = FDICopy(hfdi, pInfo->pCABName, pInfo->pCABDir, 0, fdiNotify, NULL, (LPVOID)(pInfo))))
  968. #endif
  969. bReturn = TRUE;
  970. else {
  971. CleanupFileList(pInfo);
  972. }
  973. FDIDestroy(hfdi);
  974. }
  975. return bReturn;
  976. }
  977. /******************************************************************************\
  978. *
  979. * GetWPNPSetupLibName (Local Routine)
  980. *
  981. * Returns the name of the print wizard library (NT5 and above)
  982. * or equivalent for older clients (NT4 and Win9x)
  983. *
  984. \******************************************************************************/
  985. LPTSTR GetWPNPSetupLibName(LPDWORD lpdwReturn) {
  986. LPTSTR lpszLibName;
  987. OSVERSIONINFO OSVersionInfo;
  988. *lpdwReturn = ERR_GENERIC;
  989. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  990. if (GetVersionEx(&OSVersionInfo)) {
  991. switch (OSVersionInfo.dwPlatformId) {
  992. // NT clients
  993. case VER_PLATFORM_WIN32_NT:
  994. // NT 5 or better
  995. if (OSVersionInfo.dwMajorVersion >= NT_VER_5) {
  996. *lpdwReturn = ERR_NONE;
  997. return (LPTSTR)g_szPrintUIMod;
  998. }
  999. // NT 4 clients
  1000. else if (OSVersionInfo.dwMajorVersion >= NT_VER_4) {
  1001. *lpdwReturn = ERR_NONE;
  1002. return (LPTSTR)g_szPrintUIEquiv;
  1003. }
  1004. // NT clients: ver < 4.0
  1005. else {
  1006. *lpdwReturn = ERR_PLATFORM_NOT_SUPPORTED;
  1007. return NULL;
  1008. }
  1009. // Win9x clients
  1010. case VER_PLATFORM_WIN32_WINDOWS:
  1011. *lpdwReturn = ERR_NONE;
  1012. return (LPTSTR)g_szPrintUIEquiv;
  1013. // Other clients ?
  1014. default:
  1015. *lpdwReturn = ERR_PLATFORM_NOT_SUPPORTED;
  1016. return NULL;
  1017. }
  1018. }
  1019. return NULL;
  1020. }
  1021. /******************************************************************************\
  1022. *
  1023. * InvokePrintWizard (Local Routine)
  1024. *
  1025. * Calls the PrintWizard (or 9x/NT4 equivalent)
  1026. * for printer setup and installation.
  1027. *
  1028. \******************************************************************************/
  1029. DWORD InvokePrintWizard(PWPNPINFO pInfo, LPDWORD lpAuthError) {
  1030. DWORD dwReturn;
  1031. DWORD dwErr;
  1032. LPTSTR lpszSetupLibName;
  1033. HMODULE hLibrary;
  1034. FARPROC lpProc;
  1035. // Get the name of the print wizard module
  1036. //
  1037. if (NULL != (lpszSetupLibName = GetWPNPSetupLibName(&dwReturn)) ) {
  1038. // Load the print wizard module
  1039. //
  1040. if (NULL != (hLibrary = LoadLibrary(lpszSetupLibName)) ) {
  1041. // Find the webpnp installation proc address
  1042. //
  1043. if (NULL != (lpProc = GetProcAddress(hLibrary, g_szPrintUIEntryW) ) ) {
  1044. // Call the webpnp installation entry point with the correct parameters
  1045. //
  1046. if ((*lpAuthError) = (UINT32) (*lpProc)(NULL, g_hInstance, g_wszParmString, SW_SHOWDEFAULT))
  1047. dwReturn = ERR_AUTHENTICODE;
  1048. else
  1049. dwReturn = ERR_NONE;
  1050. } else {
  1051. dwReturn = ERR_NO_PRINTUIENTRY;
  1052. }
  1053. FreeLibrary(hLibrary);
  1054. } else {
  1055. dwReturn = ERR_NO_PRINTUI;
  1056. }
  1057. }
  1058. return dwReturn;
  1059. }
  1060. /******************************************************************************\
  1061. *
  1062. * WebPnPCABInstall (Local Routine)
  1063. *
  1064. * Takes a CAB file and does the driver extraction and printer installation.
  1065. *
  1066. \******************************************************************************/
  1067. DWORD WebPnPCABInstall(PTSTR pCABName, PDWORD lpAuthError)
  1068. {
  1069. PTSTR pFileList;
  1070. PTSTR pOldDir;
  1071. PWPNPINFO pInfo;
  1072. DWORD dwReturn = ERR_NONE;
  1073. if (NULL != (pInfo = (PWPNPINFO)GlobalAlloc(GPTR, sizeof(WPNPINFO)))) {
  1074. if (NULL != (pInfo->pFullCABPath = (PTSTR)GlobalAlloc(GPTR, (lstrlen(pCABName) + 1) * sizeof(TCHAR)))) {
  1075. lstrcpy(pInfo->pFullCABPath, pCABName);
  1076. if (pInfo->pCABDir = GetDirectory(pInfo->pFullCABPath, &dwReturn)) {
  1077. if (pOldDir = GetCurDir()) {
  1078. if (pInfo->pTempDir = CreateTempDirectory() ) {
  1079. SetCurrentDirectory(pInfo->pTempDir);
  1080. if (pInfo->pCABName = GetName(pInfo->pFullCABPath, &dwReturn)) {
  1081. if (Extract(pInfo)) {
  1082. // Verification of files removed
  1083. // if (ERR_NONE == (dwReturn = VerifyFiles(pInfo, lpAuthError))) {
  1084. dwReturn = InvokePrintWizard(pInfo, lpAuthError);
  1085. // }
  1086. CleanupFileList(pInfo);
  1087. } else {
  1088. dwReturn = ERR_CAB_EXTRACT;
  1089. }
  1090. GlobalFree(pInfo->pCABName);
  1091. }
  1092. SetCurrentDirectory(pOldDir);
  1093. RemoveDirectory(pInfo->pTempDir);
  1094. GlobalFree(pInfo->pTempDir);
  1095. }
  1096. GlobalFree(pOldDir);
  1097. }
  1098. GlobalFree(pInfo->pCABDir);
  1099. }
  1100. GlobalFree(pInfo->pFullCABPath);
  1101. } else {
  1102. dwReturn = ERR_NO_MEMORY;
  1103. }
  1104. GlobalFree(pInfo);
  1105. } else {
  1106. dwReturn = ERR_NO_MEMORY;
  1107. }
  1108. return dwReturn;
  1109. }
  1110. /******************************************************************************\
  1111. *
  1112. * LookupErrorString (Local Routine)
  1113. *
  1114. * Returns an error string associated with dwErrorCode
  1115. *
  1116. \******************************************************************************/
  1117. LPCTSTR LookupErrorString(DWORD dwErrorCode) {
  1118. int i;
  1119. int nCount;
  1120. static ERROR_MAPPING s_ErrorMap[] = {
  1121. { ERR_NO_MEMORY, &g_szENoMemory },
  1122. { ERR_BAD_CAB, &g_szEBadCAB },
  1123. { ERR_INVALID_PARAMETER, &g_szEInvalidParameter },
  1124. { ERR_INVALID_CAB_NAME, &g_szEInvalidCABName },
  1125. { ERR_CAB_EXTRACT, &g_szECABExtract },
  1126. { ERR_NO_DAT_FILE, &g_szENoDATFile },
  1127. { ERR_NO_PRINTUI, &g_szENoPrintUI },
  1128. { ERR_NO_PRINTUIENTRY, &g_szENoPrintUIEntry },
  1129. { ERR_PRINTUIENTRY_FAIL, &g_szEPrintUIEntryFail },
  1130. { ERR_PLATFORM_NOT_SUPPORTED, &g_szENotSupported }
  1131. };
  1132. nCount = sizeof(s_ErrorMap) / sizeof(s_ErrorMap[0]);
  1133. for (i=0; i < nCount; i++) {
  1134. if (0 != ((s_ErrorMap[i].dwErrorCode) & dwErrorCode & ~(ERR_GENERIC)) )
  1135. return *(s_ErrorMap[i].lpszError);
  1136. }
  1137. return g_szEGeneric;
  1138. }
  1139. /******************************************************************************\
  1140. *
  1141. * CheckErrors (Local Routine)
  1142. *
  1143. * Checks dwErrorCode for any error conditions
  1144. *
  1145. \******************************************************************************/
  1146. VOID CheckErrors(DWORD dwErrorCode, DWORD dwAuthError) {
  1147. LPTSTR lpszMessage = NULL;
  1148. LPTSTR lpszErrorString = NULL;
  1149. BOOL bAuthErrorAllocated;
  1150. UINT_PTR Args[MAX_ARGS];
  1151. bAuthErrorAllocated = FALSE;
  1152. if (dwErrorCode != ERR_NONE) {
  1153. // Check for Authenticode errors here
  1154. if (dwErrorCode == ERR_AUTHENTICODE) {
  1155. // Format the authenticode error message.
  1156. // If the message can't be found in the system, use our generic error message
  1157. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1158. NULL, dwAuthError, 0, (LPTSTR)&lpszErrorString, 0, NULL)) {
  1159. bAuthErrorAllocated = TRUE;
  1160. }
  1161. else {
  1162. lpszErrorString = (LPTSTR)LookupErrorString(ERR_GENERIC);
  1163. }
  1164. }
  1165. // If the error is not Authenticode, it must be ours.
  1166. // Look it up in our error string table.
  1167. else {
  1168. lpszErrorString = (LPTSTR)LookupErrorString(dwErrorCode);
  1169. }
  1170. // Set up our arg list.
  1171. Args[0] = (UINT_PTR) lpszErrorString;
  1172. if (dwErrorCode == ERR_AUTHENTICODE) {
  1173. Args[1] = dwAuthError;
  1174. }
  1175. else
  1176. Args[1] = dwErrorCode;
  1177. Args[2] = 0;
  1178. // Format our error message and display it in a message box.
  1179. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1180. g_szErrorFormat, 0, 0, (LPTSTR)&lpszMessage, 0, (va_list*)Args )) {
  1181. if (lpszMessage) {
  1182. MessageBox(NULL, lpszMessage, g_szError, MB_ICONEXCLAMATION | MB_OK);
  1183. // Free the buffer
  1184. LocalFree(lpszMessage);
  1185. }
  1186. }
  1187. }
  1188. // Free up the Authenticode error string allocated for us by FormatMessage().
  1189. if (bAuthErrorAllocated)
  1190. LocalFree(lpszErrorString);
  1191. }
  1192. /******************************************************************************\
  1193. *
  1194. * WinMain
  1195. *
  1196. * Main entrypoint for the program.
  1197. *
  1198. \******************************************************************************/
  1199. INT WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
  1200. LPTSTR lpszCmdLine, INT nCmdShow)
  1201. {
  1202. LPTSTR lpszCABName;
  1203. DWORD dwReturn = ERR_NONE;
  1204. DWORD dwAuthError = ERROR_SUCCESS;
  1205. g_hInstance = hInstance;
  1206. if (InitStrings()) {
  1207. if (NULL != (lpszCABName = GetCABName(lpszCmdLine, &dwReturn))) {
  1208. dwReturn = WebPnPCABInstall(lpszCABName, &dwAuthError);
  1209. GlobalFree(lpszCABName);
  1210. }
  1211. #if 0
  1212. // We disable the error since oleprn will
  1213. // prompt users with the correct error
  1214. //
  1215. CheckErrors(dwReturn, dwAuthError);
  1216. #endif
  1217. // Decide which error code we must return
  1218. //
  1219. if (dwReturn == ERR_NONE) {
  1220. dwReturn = SUCCESS_EXITCODE;
  1221. } else {
  1222. if (dwReturn == ERR_AUTHENTICODE) {
  1223. if (dwAuthError == ERROR_SUCCESS) {
  1224. dwReturn = SUCCESS_EXITCODE;
  1225. } else {
  1226. dwReturn = dwAuthError;
  1227. }
  1228. }
  1229. }
  1230. FreeStrings();
  1231. }
  1232. return dwReturn;
  1233. }