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.

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