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.

2127 lines
54 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. Util.c
  6. Abstract:
  7. Uitility routines for printer migration from Win9x to NT
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 02-Jan-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. extern CHAR szRunOnceRegistryPath[];
  14. extern CHAR szSpool[];
  15. extern CHAR szMigDll[];
  16. //
  17. // These are used in the process of creating registry keys where the
  18. // data necessary the vendor setup to be started will be stored
  19. //
  20. CHAR *pszVendorSetupInfoPath = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Print";
  21. CHAR *pszVendorSetupInfo = "VendorSetupInfo";
  22. CHAR *pszVendorSetupID = "VendorSetup";
  23. CHAR *pszVendorSetupEnumerator = "VendorInfoEnumerator";
  24. CHAR *pszPrinterNameKey = "PrinterName";
  25. CHAR *pszMigrationVendorSetupCaller = "MigrationVendorSetupCaller";
  26. CHAR szVendorSetupRunRegistryPath[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
  27. const CHAR *pszVendorSetupCaller = "CallVendorSetupDlls";
  28. const LONG dwMaxVendorSetupIDLength = 10;
  29. const DWORD dwFourMinutes = 240000;
  30. BOOL bMigrateDllCopyed = FALSE;
  31. VOID
  32. DebugMsg(
  33. LPCSTR pszFormat,
  34. ...
  35. )
  36. /*++
  37. Routine Description:
  38. On debug builds brings up a message box on severe errors
  39. Arguments:
  40. pszFormat : Format string
  41. Return Value:
  42. None
  43. --*/
  44. {
  45. #if DBG
  46. LPSTR psz;
  47. CHAR szMsg[1024];
  48. va_list vargs;
  49. va_start(vargs, pszFormat);
  50. vsprintf(szMsg, pszFormat, vargs);
  51. va_end(vargs);
  52. #ifdef MYDEBUG
  53. if ( psz = GetStringFromRcFileA(IDS_TITLE) ) {
  54. MessageBoxA(NULL, szMsg, psz, MB_OK);
  55. FreeMem(psz);
  56. }
  57. #else
  58. OutputDebugStringA("Printing Migration : ");
  59. OutputDebugStringA(szMsg);
  60. OutputDebugStringA("\n");
  61. #endif
  62. #endif
  63. }
  64. VOID
  65. LogError(
  66. IN LogSeverity Severity,
  67. IN UINT uMessageId,
  68. ...
  69. )
  70. /*++
  71. Routine Description:
  72. Logs an error in the setup error log on NT side when something can not be
  73. upgraded
  74. Arguments:
  75. uMessageId : Id to string in .rc file
  76. Return Value:
  77. None
  78. --*/
  79. {
  80. LPSTR pszFormat;
  81. CHAR szMsg[1024];
  82. va_list vargs;
  83. va_start(vargs, uMessageId);
  84. pszFormat = GetStringFromRcFileA(uMessageId);
  85. if ( pszFormat ) {
  86. wvsprintfA(szMsg, pszFormat, vargs);
  87. DebugMsg("%s", szMsg);
  88. SetupLogErrorA(szMsg, Severity);
  89. }
  90. FreeMem(pszFormat);
  91. va_end(vargs);
  92. }
  93. LPSTR
  94. ErrorMsg(
  95. VOID
  96. )
  97. /*++
  98. Routine Description:
  99. Returns the error message string from a Win32 error
  100. Arguments:
  101. None
  102. Return Value:
  103. Pointer to a message string. Caller should free the string
  104. --*/
  105. {
  106. DWORD dwLastError;
  107. LPSTR pszStr = NULL;
  108. if ( !(dwLastError = GetLastError()) )
  109. dwLastError = STG_E_UNKNOWN;
  110. FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  111. FORMAT_MESSAGE_IGNORE_INSERTS |
  112. FORMAT_MESSAGE_FROM_SYSTEM |
  113. FORMAT_MESSAGE_MAX_WIDTH_MASK,
  114. NULL,
  115. dwLastError,
  116. 0,
  117. (LPSTR)&pszStr,
  118. 0,
  119. NULL);
  120. return pszStr;
  121. }
  122. PVOID
  123. AllocMem(
  124. IN UINT cbSize
  125. )
  126. /*++
  127. Routine Description:
  128. Allocate memory from the heap
  129. Arguments:
  130. cbSize : Byte count
  131. Return Value:
  132. Pointer to the allocated memory
  133. --*/
  134. {
  135. return LocalAlloc(LPTR, cbSize);
  136. }
  137. VOID
  138. FreeMem(
  139. IN PVOID p
  140. )
  141. /*++
  142. Routine Description:
  143. Free memory allocated on the heap
  144. Arguments:
  145. p : Pointer to the memory to be freed
  146. Return Value:
  147. None
  148. --*/
  149. {
  150. LocalFree(p);
  151. }
  152. LPSTR
  153. AllocStrA(
  154. LPCSTR pszStr
  155. )
  156. /*++
  157. Routine Description:
  158. Allocate memory and make a copy of an ansi string field
  159. Arguments:
  160. pszStr : String to copy
  161. Return Value:
  162. Pointer to the copied string. Memory is allocated.
  163. --*/
  164. {
  165. LPSTR pszRet = NULL;
  166. if ( pszStr && *pszStr ) {
  167. pszRet = AllocMem((strlen(pszStr) + 1) * sizeof(CHAR));
  168. if ( pszRet )
  169. strcpy(pszRet, pszStr);
  170. }
  171. return pszRet;
  172. }
  173. LPWSTR
  174. AllocStrW(
  175. LPCWSTR pszStr
  176. )
  177. /*++
  178. Routine Description:
  179. Allocate memory and make a copy of a unicode string field
  180. Arguments:
  181. pszStr : String to copy
  182. Return Value:
  183. Pointer to the copied string. Memory is allocated.
  184. --*/
  185. {
  186. LPWSTR pszRet = NULL;
  187. if ( pszStr && *pszStr ) {
  188. pszRet = AllocMem((wcslen(pszStr) + 1) * sizeof(WCHAR));
  189. if ( pszRet )
  190. wcscpy(pszRet, pszStr);
  191. }
  192. return pszRet;
  193. }
  194. LPWSTR
  195. AllocStrWFromStrA(
  196. LPCSTR pszStr
  197. )
  198. /*++
  199. Routine Description:
  200. Returns the unicode string for a give ansi string. Memory is allocated.
  201. Arguments:
  202. pszStr : Gives the ansi string to copy
  203. Return Value:
  204. Pointer to the copied unicode string. Memory is allocated.
  205. --*/
  206. {
  207. DWORD dwLen;
  208. LPWSTR pszRet = NULL;
  209. if ( pszStr &&
  210. *pszStr &&
  211. (dwLen = strlen(pszStr)) &&
  212. (pszRet = AllocMem((dwLen + 1) * sizeof(WCHAR))) ) {
  213. if ( MultiByteToWideChar(CP_ACP,
  214. MB_PRECOMPOSED,
  215. pszStr,
  216. dwLen,
  217. pszRet,
  218. dwLen) ) {
  219. pszRet[dwLen] = 0;
  220. } else {
  221. FreeMem(pszRet);
  222. pszRet = NULL;
  223. }
  224. }
  225. return pszRet;
  226. }
  227. LPSTR
  228. AllocStrAFromStrW(
  229. LPCWSTR pszStr
  230. )
  231. /*++
  232. Routine Description:
  233. Returns the ansi string for a give unicode string. Memory is allocated.
  234. Arguments:
  235. pszStr : Gives the ansi string to copy
  236. Return Value:
  237. Pointer to the copied ansi string. Memory is allocated.
  238. --*/
  239. {
  240. DWORD dwLen;
  241. LPSTR pszRet = NULL;
  242. if ( pszStr &&
  243. *pszStr &&
  244. (dwLen = wcslen(pszStr)) &&
  245. (pszRet = AllocMem((dwLen + 1 ) * sizeof(CHAR))) ) {
  246. WideCharToMultiByte(CP_ACP,
  247. 0,
  248. pszStr,
  249. dwLen,
  250. pszRet,
  251. dwLen,
  252. NULL,
  253. NULL );
  254. }
  255. return pszRet;
  256. }
  257. VOID
  258. WriteToFile(
  259. HANDLE hFile,
  260. LPBOOL pbFail,
  261. LPCSTR pszFormat,
  262. ...
  263. )
  264. /*++
  265. Routine Description:
  266. Format and write a string to the text file. This is used to write the
  267. printing configuration on Win9x
  268. Arguments:
  269. hFile : File handle
  270. pbFail : Set on error -- no more processing needed
  271. pszFormat : Format string for the message
  272. Return Value:
  273. None
  274. --*/
  275. {
  276. CHAR szMsg[1024];
  277. va_list vargs;
  278. DWORD dwSize, dwWritten;
  279. if ( *pbFail )
  280. return;
  281. va_start(vargs, pszFormat);
  282. vsprintf(szMsg, pszFormat, vargs);
  283. va_end(vargs);
  284. dwSize = strlen(szMsg) * sizeof(CHAR);
  285. if ( !WriteFile(hFile, (LPCVOID)szMsg, dwSize, &dwWritten, NULL) ||
  286. dwSize != dwWritten ) {
  287. *pbFail = TRUE;
  288. }
  289. }
  290. VOID
  291. WriteString(
  292. IN HANDLE hFile,
  293. IN OUT LPBOOL pbFail,
  294. IN LPCSTR pszStr
  295. )
  296. /*++
  297. Routine Description:
  298. Writes a string to the upgrade file on Win9x side. Since spooler strings
  299. (ex. printer name, driver name) can have space in them we would write
  300. all strings with []\n. So we can read strings with space on NT.
  301. Arguments:
  302. hFile : File handle
  303. pszFormat : Format string for the message
  304. pszStr : String to write
  305. Return Value:
  306. None
  307. --*/
  308. {
  309. DWORD dwLen;
  310. if ( pszStr ) {
  311. dwLen = strlen(pszStr);
  312. WriteToFile(hFile, pbFail, "%3d [%s]\n", dwLen, pszStr);
  313. }
  314. else
  315. WriteToFile(hFile, pbFail, " 0 []\n");
  316. }
  317. VOID
  318. WriteDevMode(
  319. IN HANDLE hFile,
  320. IN OUT LPBOOL pbFail,
  321. IN LPDEVMODEA pDevMode
  322. )
  323. /*++
  324. Routine Description:
  325. Writes a devmode to the upgrade file on Win9x side. We write the size of
  326. devmode and write this as a binary field
  327. Arguments:
  328. hFile : File handle
  329. pbFail : On error set to TRUE
  330. pDevMode : Pointer to devmode
  331. Return Value:
  332. None
  333. --*/
  334. {
  335. DWORD cbSize, cbWritten;
  336. if ( *pbFail )
  337. return;
  338. cbSize = pDevMode ? pDevMode->dmSize + pDevMode->dmDriverExtra : 0;
  339. if ( cbSize ) {
  340. WriteToFile(hFile, pbFail, "DevMode: %d [", cbSize);
  341. if ( !WriteFile(hFile, (LPCVOID)pDevMode, cbSize, &cbWritten, NULL) ||
  342. cbWritten != cbSize )
  343. *pbFail = TRUE;
  344. WriteToFile(hFile, pbFail, "]\n");
  345. } else {
  346. WriteToFile(hFile, pbFail, "DevMode: 0\n");
  347. }
  348. }
  349. LPSTR
  350. GetStringFromRcFileA(
  351. UINT uId
  352. )
  353. /*++
  354. Routine Description:
  355. Load a string from the .rc file and make a copy of it by doing AllocStr
  356. Arguments:
  357. uId : Identifier for the string to be loaded
  358. Return Value:
  359. String value loaded, NULL on error. Caller should free the memory
  360. --*/
  361. {
  362. CHAR buf[MAX_STRING_LEN];
  363. if ( LoadStringA(UpgradeData.hInst, uId, buf, SIZECHARS(buf)) )
  364. return AllocStrA(buf);
  365. else
  366. return NULL;
  367. }
  368. VOID
  369. CleanupDriverMapping(
  370. IN OUT HDEVINFO *phDevInfo,
  371. IN OUT HINF *phNtInf,
  372. IN OUT HINF *phUpgInf
  373. )
  374. /*++
  375. Routine Description:
  376. Close INF handles and delete the printer device info list
  377. Arguments:
  378. phDevInfo : Points to printer device info list
  379. phNtInf : Points to INF handle for ntprint.inf
  380. phUpgInfo : Points to the handle to upgrade inf
  381. Return Value:
  382. Pointer to the copied unicode string. Memory is allocated.
  383. --*/
  384. {
  385. if ( phUpgInf && *phUpgInf != INVALID_HANDLE_VALUE ) {
  386. SetupCloseInfFile(*phUpgInf);
  387. *phUpgInf = INVALID_HANDLE_VALUE;
  388. }
  389. if ( *phNtInf != INVALID_HANDLE_VALUE ) {
  390. SetupCloseInfFile(*phNtInf);
  391. *phNtInf = INVALID_HANDLE_VALUE;
  392. }
  393. if ( *phDevInfo != INVALID_HANDLE_VALUE ) {
  394. SetupDiDestroyDeviceInfoList(*phDevInfo);
  395. *phDevInfo = INVALID_HANDLE_VALUE;
  396. }
  397. }
  398. VOID
  399. InitDriverMapping(
  400. OUT HDEVINFO *phDevInfo,
  401. OUT HINF *phNtInf,
  402. OUT HINF *phUpgInf,
  403. IN OUT LPBOOL pbFail
  404. )
  405. /*++
  406. Routine Description:
  407. Opens necessary inf files and create the printer device info list for
  408. driver upgrade
  409. Arguments:
  410. phDevInfo : Points to printer device info list
  411. phNtInf : Points to INF handle for ntprint.inf
  412. phUpgInfo : Points to the handle to upgrade inf
  413. pbFail : Set on error -- no more processing needed
  414. Return Value:
  415. Pointer to the copied unicode string. Memory is allocated.
  416. --*/
  417. {
  418. DWORD dwLen;
  419. CHAR szPath[MAX_PATH];
  420. SP_DEVINSTALL_PARAMS DevInstallParams;
  421. if ( *pbFail )
  422. {
  423. return;
  424. }
  425. *phDevInfo = SetupDiCreateDeviceInfoList((LPGUID)&GUID_DEVCLASS_PRINTER,
  426. NULL);
  427. strcpy(szPath, UpgradeData.pszDir);
  428. dwLen = strlen(szPath);
  429. szPath[dwLen++] = '\\';
  430. strcpy(szPath+dwLen, "prtupg9x.inf");
  431. *phUpgInf = SetupOpenInfFileA(szPath, NULL, INF_STYLE_WIN4, NULL);
  432. strcpy(szPath, UpgradeData.pszSourceA);
  433. dwLen = strlen(szPath);
  434. szPath[dwLen++] = '\\';
  435. strcpy(szPath+dwLen, "ntprint.inf");
  436. *phNtInf = SetupOpenInfFileA(szPath, NULL, INF_STYLE_WIN4, NULL);
  437. strcpy(szPath+dwLen, "layout.inf");
  438. if ( *phDevInfo == INVALID_HANDLE_VALUE ||
  439. (phUpgInf && *phUpgInf == INVALID_HANDLE_VALUE) ||
  440. *phNtInf == INVALID_HANDLE_VALUE ||
  441. !SetupOpenAppendInfFileA(szPath, *phNtInf, NULL) )
  442. {
  443. *pbFail = TRUE;
  444. goto Cleanup;
  445. }
  446. //
  447. // Build the list of drivers from ntprint.inf in the working directory
  448. //
  449. DevInstallParams.cbSize = sizeof(DevInstallParams);
  450. if ( !SetupDiGetDeviceInstallParamsA(*phDevInfo,
  451. NULL,
  452. &DevInstallParams) )
  453. {
  454. *pbFail = TRUE;
  455. goto Cleanup;
  456. }
  457. DevInstallParams.Flags |= DI_INF_IS_SORTED | DI_ENUMSINGLEINF;
  458. strcpy(szPath+dwLen, "ntprint.inf");
  459. strcpy(DevInstallParams.DriverPath, szPath);
  460. if ( !SetupDiSetDeviceInstallParamsA(*phDevInfo, NULL, &DevInstallParams) ||
  461. !SetupDiBuildDriverInfoList(*phDevInfo, NULL, SPDIT_CLASSDRIVER) )
  462. {
  463. *pbFail = TRUE;
  464. }
  465. Cleanup:
  466. if ( *pbFail )
  467. CleanupDriverMapping(phDevInfo, phNtInf, phUpgInf);
  468. }
  469. VOID
  470. WritePrinterInfo2(
  471. IN HANDLE hFile,
  472. IN LPPRINTER_INFO_2A pPrinterInfo2,
  473. IN LPSTR pszDriver,
  474. IN OUT LPBOOL pbFail
  475. )
  476. {
  477. DWORD dwSize;
  478. LPINT ptr;
  479. if ( *pbFail )
  480. return;
  481. WriteToFile(hFile, pbFail, "ServerName: ");
  482. WriteString(hFile, pbFail, pPrinterInfo2->pServerName);
  483. WriteToFile(hFile, pbFail, "PrinterName: ");
  484. WriteString(hFile, pbFail, pPrinterInfo2->pPrinterName);
  485. WriteToFile(hFile, pbFail, "ShareName: ");
  486. WriteString(hFile, pbFail, pPrinterInfo2->pShareName);
  487. WriteToFile(hFile, pbFail, "PortName: ");
  488. WriteString(hFile, pbFail, pPrinterInfo2->pPortName);
  489. //
  490. // On the Win9x side we could have found a different driver name on NT side
  491. // if so write it instead of the one returned by spooler
  492. //
  493. WriteToFile(hFile, pbFail, "DriverName: ");
  494. WriteString(hFile, pbFail,
  495. pszDriver ? pszDriver : pPrinterInfo2->pDriverName);
  496. WriteToFile(hFile, pbFail, "Comment: ");
  497. WriteString(hFile, pbFail, pPrinterInfo2->pComment);
  498. WriteToFile(hFile, pbFail, "Location: ");
  499. WriteString(hFile, pbFail, pPrinterInfo2->pLocation);
  500. WriteDevMode(hFile, pbFail, pPrinterInfo2->pDevMode);
  501. WriteToFile(hFile, pbFail, "SepFile: ");
  502. WriteString(hFile, pbFail, pPrinterInfo2->pSepFile);
  503. WriteToFile(hFile, pbFail, "PrintProcessor: ");
  504. WriteString(hFile, pbFail, pPrinterInfo2->pPrintProcessor);
  505. WriteToFile(hFile, pbFail, "Datatype: ");
  506. WriteString(hFile, pbFail, pPrinterInfo2->pDatatype);
  507. WriteToFile(hFile, pbFail, "Parameters: ");
  508. WriteString(hFile, pbFail, pPrinterInfo2->pParameters);
  509. // Security descriptor ???
  510. WriteToFile(hFile, pbFail, "Attributes: %3d\n", pPrinterInfo2->Attributes);
  511. WriteToFile(hFile, pbFail, "Priority: %3d\n", pPrinterInfo2->Priority);
  512. WriteToFile(hFile, pbFail, "DefaultPriority: %3d\n", pPrinterInfo2->DefaultPriority);
  513. WriteToFile(hFile, pbFail, "StartTime: %3d\n", pPrinterInfo2->StartTime);
  514. WriteToFile(hFile, pbFail, "UntilTime: %3d\n", pPrinterInfo2->UntilTime);
  515. WriteToFile(hFile, pbFail, "Status: %3d\n", pPrinterInfo2->Status);
  516. // cJobs not needed
  517. // AveragePPM not needed
  518. WriteToFile(hFile, pbFail, "\n");
  519. }
  520. VOID
  521. ReadString(
  522. IN HANDLE hFile,
  523. IN LPSTR pszPrefix,
  524. OUT LPSTR *ppszStr,
  525. IN BOOL bOptional,
  526. IN OUT LPBOOL pbFail
  527. )
  528. {
  529. CHAR c;
  530. LPSTR psz;
  531. DWORD dwLen;
  532. if ( *pbFail )
  533. return;
  534. //
  535. // First skip the prefix
  536. //
  537. while ( *pszPrefix && (c = (CHAR) My_fgetc(hFile)) == *pszPrefix++ )
  538. ;
  539. if ( *pszPrefix )
  540. goto Fail;
  541. //
  542. // Skip spaces
  543. //
  544. while ( (c = (CHAR) My_fgetc(hFile)) == ' ' )
  545. ;
  546. //
  547. // Now is the string length
  548. //
  549. if ( !isdigit(c) )
  550. goto Fail;
  551. dwLen = c - '0';
  552. while ( isdigit(c = (CHAR) My_fgetc(hFile)) )
  553. dwLen = dwLen * 10 + c - '0';
  554. if ( c != ' ' )
  555. goto Fail;
  556. //
  557. // Now the string is there between []
  558. //
  559. if ( *ppszStr = (LPSTR) AllocMem((dwLen + 1) * sizeof(CHAR)) ) {
  560. if ( (c = (CHAR) My_fgetc(hFile)) != '[' )
  561. goto Fail;
  562. for ( psz = *ppszStr ;
  563. dwLen && (*psz = (CHAR) My_fgetc(hFile)) != (CHAR) EOF ;
  564. ++psz, --dwLen )
  565. ;
  566. if ( dwLen )
  567. goto Fail;
  568. *psz = '\0';
  569. //
  570. // Make sure line ends with "]\n"
  571. //
  572. if ( (CHAR) My_fgetc(hFile) != ']' || (CHAR) My_fgetc(hFile) != '\n' )
  573. goto Fail;
  574. return;
  575. }
  576. Fail:
  577. *pbFail = TRUE;
  578. FreeMem(*ppszStr);
  579. *ppszStr = NULL;
  580. }
  581. VOID
  582. ReadDword(
  583. IN HANDLE hFile,
  584. IN LPSTR pszLine,
  585. IN DWORD dwLineSize,
  586. IN LPSTR pszPrefix,
  587. OUT LPDWORD pdwValue,
  588. IN OUT LPBOOL pbFail
  589. )
  590. {
  591. LPSTR psz;
  592. if ( *pbFail || My_fgets(pszLine, dwLineSize, hFile) == NULL ) {
  593. *pbFail = TRUE;
  594. return;
  595. }
  596. //
  597. // First check the prefix matches to make sure we are in the right line
  598. //
  599. for ( psz = (LPSTR)pszLine ;
  600. *pszPrefix && *psz == *pszPrefix ;
  601. ++psz, ++pszPrefix )
  602. ;
  603. if ( *pszPrefix ) {
  604. *pbFail = TRUE;
  605. return;
  606. }
  607. //
  608. // Skip spaces
  609. //
  610. while ( *psz && *psz == ' ' )
  611. ++psz;
  612. *pdwValue = atoi(psz);
  613. }
  614. VOID
  615. ReadDevMode(
  616. IN HANDLE hFile,
  617. OUT LPDEVMODEA *ppDevMode,
  618. IN OUT LPBOOL pbFail
  619. )
  620. {
  621. LPSTR pszPrefix = "DevMode:";
  622. CHAR c;
  623. DWORD dwLen;
  624. LPINT ptr;
  625. if ( *pbFail )
  626. return;
  627. // First skip the prefix
  628. //
  629. while ( *pszPrefix && (c = (CHAR) My_fgetc(hFile)) == *pszPrefix++ )
  630. ;
  631. if ( *pszPrefix )
  632. goto Fail;
  633. //
  634. // Skip spaces
  635. //
  636. while ( (c = (CHAR) My_fgetc(hFile)) == ' ' )
  637. ;
  638. //
  639. // Now is the devmode size
  640. //
  641. if ( !isdigit(c) )
  642. goto Fail;
  643. dwLen = c - '0';
  644. while ( isdigit(c = (CHAR) My_fgetc(hFile)) )
  645. dwLen = dwLen * 10 + c - '0';
  646. if ( dwLen == 0 )
  647. return;
  648. if ( c != ' ' )
  649. goto Fail;
  650. //
  651. // Now the devmode is there between []
  652. //
  653. if ( *ppDevMode = (LPDEVMODEA) AllocMem(dwLen) ) {
  654. if ( (c = (CHAR) My_fgetc(hFile)) != '[' )
  655. goto Fail;
  656. if ( dwLen != My_fread((LPVOID)*ppDevMode, dwLen, hFile) )
  657. goto Fail;
  658. //
  659. // Make sure now we have "]\n" to End
  660. //
  661. if ( (CHAR) My_fgetc(hFile) != ']' || (CHAR) My_fgetc(hFile) != '\n' ) {
  662. DebugMsg("Char check fails");
  663. goto Fail;
  664. }
  665. return; // Succesful exit
  666. }
  667. Fail:
  668. *pbFail = TRUE;
  669. }
  670. VOID
  671. FreePrinterInfo2Strings(
  672. PPRINTER_INFO_2A pPrinterInfo2
  673. )
  674. {
  675. if ( pPrinterInfo2 ) {
  676. FreeMem(pPrinterInfo2->pServerName);
  677. FreeMem(pPrinterInfo2->pPrinterName);
  678. FreeMem(pPrinterInfo2->pShareName);
  679. FreeMem(pPrinterInfo2->pPortName);
  680. FreeMem(pPrinterInfo2->pDriverName);
  681. FreeMem(pPrinterInfo2->pComment);
  682. FreeMem(pPrinterInfo2->pLocation);
  683. FreeMem(pPrinterInfo2->pDevMode);
  684. FreeMem(pPrinterInfo2->pSepFile);
  685. FreeMem(pPrinterInfo2->pPrintProcessor);
  686. FreeMem(pPrinterInfo2->pDatatype);
  687. }
  688. }
  689. VOID
  690. ReadPrinterInfo2(
  691. IN HANDLE hFile,
  692. IN LPPRINTER_INFO_2A pPrinterInfo2,
  693. IN OUT LPBOOL pbFail
  694. )
  695. {
  696. CHAR szLine[2*MAX_PATH];
  697. DWORD dwSize;
  698. dwSize = sizeof(szLine)/sizeof(szLine[0]);
  699. ReadString(hFile, "ServerName:",
  700. &pPrinterInfo2->pServerName, TRUE, pbFail);
  701. ReadString(hFile, "PrinterName:",
  702. &pPrinterInfo2->pPrinterName, FALSE, pbFail);
  703. ReadString(hFile, "ShareName:",
  704. &pPrinterInfo2->pShareName, TRUE, pbFail);
  705. ReadString(hFile, "PortName:",
  706. &pPrinterInfo2->pPortName, FALSE, pbFail);
  707. ReadString(hFile, "DriverName:",
  708. &pPrinterInfo2->pDriverName, FALSE, pbFail);
  709. ReadString(hFile, "Comment:",
  710. &pPrinterInfo2->pComment, TRUE, pbFail);
  711. ReadString(hFile, "Location:",
  712. &pPrinterInfo2->pLocation, TRUE, pbFail);
  713. ReadDevMode(hFile, &pPrinterInfo2->pDevMode, pbFail);
  714. ReadString(hFile, "SepFile:",
  715. &pPrinterInfo2->pSepFile, TRUE, pbFail);
  716. ReadString(hFile, "PrintProcessor:",
  717. &pPrinterInfo2->pPrintProcessor, FALSE, pbFail);
  718. ReadString(hFile, "Datatype:",
  719. &pPrinterInfo2->pDatatype, TRUE, pbFail);
  720. ReadString(hFile, "Parameters:",
  721. &pPrinterInfo2->pParameters, TRUE, pbFail);
  722. ReadDword(hFile, szLine, dwSize, "Attributes:",
  723. &pPrinterInfo2->Attributes, pbFail);
  724. ReadDword(hFile, szLine, dwSize, "Priority:",
  725. &pPrinterInfo2->Priority, pbFail);
  726. ReadDword(hFile, szLine, dwSize, "DefaultPriority:",
  727. &pPrinterInfo2->DefaultPriority, pbFail);
  728. ReadDword(hFile, szLine, dwSize, "StartTime:",
  729. &pPrinterInfo2->StartTime, pbFail);
  730. ReadDword(hFile, szLine, dwSize, "UntilTime:",
  731. &pPrinterInfo2->UntilTime, pbFail);
  732. ReadDword(hFile, szLine, dwSize, "Status:",
  733. &pPrinterInfo2->Status, pbFail);
  734. //
  735. // Skip the blank line
  736. //
  737. My_fgets(szLine, dwSize, hFile);
  738. if ( *pbFail ) {
  739. FreePrinterInfo2Strings(pPrinterInfo2);
  740. ZeroMemory(pPrinterInfo2, sizeof(*pPrinterInfo2));
  741. }
  742. }
  743. LPSTR
  744. GetDefPrnString(
  745. IN LPCSTR pszPrinterName
  746. )
  747. {
  748. DWORD dwLen;
  749. LPSTR pszRet;
  750. dwLen = strlen(pszPrinterName) + 1 + strlen("winspool") + 1;
  751. if ( pszRet = (LPSTR) AllocMem(dwLen * sizeof(CHAR)) ) {
  752. sprintf(pszRet, "%s,%s", pszPrinterName, "winspool");
  753. }
  754. return pszRet;
  755. }
  756. DWORD
  757. GetFileNameInSpoolDir(
  758. IN LPSTR szBuf,
  759. IN DWORD cchBuf,
  760. IN LPSTR pszFileName
  761. )
  762. /*++
  763. Routine Description:
  764. Function returns fully qualified path of the given file name in the spool
  765. directory
  766. Arguments:
  767. szPath : Buffer to put the file name in
  768. cchBuf : Buffer size in characters
  769. pszFileName : File name part
  770. Return Value:
  771. Number of chars copied without \0 on success, 0 on failure
  772. --*/
  773. {
  774. DWORD dwLen, dwLen1;
  775. dwLen = GetSystemDirectoryA(szBuf, cchBuf);
  776. if ( !dwLen )
  777. return 0;
  778. dwLen += strlen(szSpool) + strlen(pszFileName);
  779. if ( dwLen + 1 > cchBuf )
  780. return 0;
  781. strcat(szBuf, szSpool);
  782. strcat(szBuf, pszFileName);
  783. return dwLen;
  784. }
  785. LPSTR
  786. GetVendorSetupRunOnceValueToSet(
  787. VOID
  788. )
  789. /*++
  790. --*/
  791. {
  792. CHAR szPath[MAX_PATH];
  793. DWORD dwLen, dwSize;
  794. LPSTR pszRet = NULL;
  795. dwSize = sizeof(szPath)/sizeof(szPath[0]);
  796. if ( !(dwLen = GetFileNameInSpoolDir(szPath, dwSize, szMigDll)) )
  797. goto Done;
  798. //
  799. // Now build up the RunOnce key which will be set for each user
  800. //
  801. dwSize = strlen("rundll32.exe") + dwLen +
  802. + strlen(pszVendorSetupCaller) + 4;
  803. if ( pszRet = AllocMem(dwSize * sizeof(CHAR)) )
  804. sprintf(pszRet,
  805. "rundll32.exe %s,%s",
  806. szPath, pszVendorSetupCaller);
  807. Done:
  808. return pszRet;
  809. }
  810. LONG
  811. WriteVendorSetupInfoInRegistry(
  812. IN CHAR *pszVendorSetup,
  813. IN CHAR *pszPrinterName
  814. )
  815. /*++
  816. Routine Description:
  817. This routine is called to write the name of the vendor's installer DLL,
  818. the entry point of that DLL, and the name of the printer
  819. The vendor setup information is stored as described below:
  820. HKLM
  821. \Software
  822. \Microsoft
  823. \Windows NT
  824. \CurrentVersion
  825. \Print
  826. \VendorSetupInfo
  827. \VendorInfoEnumerator N
  828. \VendorSetup1 Vendor1Dll,EntryPoint "Printer1 Name"
  829. \VendorSetup2 Vendor2Dll,EntryPoint "Printer2 Name"
  830. .............................................................
  831. \VendorSetupN VendorNDll,EntryPoint "PrinterN Name"
  832. The value N of VendorInfoEnumerator is equal to the number of the printers
  833. for which vendor setup is provided. That value will be used to enumerate
  834. the Dll's provided by vendors in the process of calling the entry points
  835. of those Dlls.
  836. The type of VendorInfoEnumerator is REG_DWORD.
  837. The value of each VendorSetupX key (where 1<= X <= N) is a string containing
  838. the name of the VendorSetup DLL, the entry point of that DLL and the
  839. corresponding printer name. WrireVendorSetupInfoInRegistry function
  840. concatenates its input parameters to produce that value and to write in into
  841. the registry. The type of every VendorSetupX value is REG_SZ.
  842. The information about the function in migrate.dll which to be called after
  843. the first administrator's logon is stored into the registry as it is shown
  844. below:
  845. HKLM
  846. \Software
  847. \Microsoft
  848. \Windows
  849. \CurrentVersion
  850. \Run
  851. \MigrationVendorSetupCaller
  852. The value of MigrationVendorSetupCaller is:
  853. rundll32.exe %WinRoot%\system32\spool\migrate.dll,CallVendorSetupDlls
  854. The type of the value is REG_SZ.
  855. Arguments:
  856. pszVendorSetup - null terminated string containing both the name of the
  857. vendor's DLL and the entry point of that DLL
  858. pszPrinterName - null terminated string containing the name of the printer
  859. Return Value:
  860. ERROR_SUCCES in the case of success.
  861. error code in the other case.
  862. --*/
  863. {
  864. LONG lRet = ERROR_BADKEY;
  865. HKEY hKeyVendorInfo = INVALID_HANDLE_VALUE;
  866. HKEY hKeyVendorInfoPath = INVALID_HANDLE_VALUE;
  867. HKEY hKeyVendorInfoInstaller = INVALID_HANDLE_VALUE;
  868. HKEY hKeyVendorInfoEnumerator = INVALID_HANDLE_VALUE;
  869. HKEY hKeyVendorRunOnceValuePath = INVALID_HANDLE_VALUE;
  870. HKEY hKeyVendorRunOnceCallerValue = INVALID_HANDLE_VALUE;
  871. CHAR *pszBuffer = NULL;
  872. CHAR *pszBuffer1 = NULL;
  873. DWORD dwType = 0;
  874. DWORD dwSize = 0;
  875. LONG lEnumerator = 0;
  876. DWORD dwDisposition = 0;
  877. UINT cbBufferSize = 0;
  878. UINT cbBuffer1Size = 0;
  879. CHAR *pszVendorSetupIDAsStr = NULL;
  880. CHAR *pszVendorSetupRunOnceValue = NULL;
  881. if (!pszVendorSetup || (strlen(pszVendorSetup) == 0) ||
  882. !pszPrinterName || (strlen(pszPrinterName) == 0))
  883. {
  884. goto Cleanup;
  885. }
  886. //
  887. // We have to open the HKLM\Software\Microsoft\Windows NT\CurrentVersion\Print\VendorSetupInfo
  888. // key first.
  889. //
  890. lRet = RegCreateKeyEx( HKEY_LOCAL_MACHINE, pszVendorSetupInfoPath, 0,
  891. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  892. &hKeyVendorInfoPath, NULL );
  893. if (ERROR_SUCCESS != lRet)
  894. {
  895. goto Cleanup;
  896. }
  897. //
  898. // Now we will try to create the VendorSetupInfo key
  899. //
  900. lRet = RegCreateKeyEx( hKeyVendorInfoPath, pszVendorSetupInfo, 0,
  901. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  902. &hKeyVendorInfo, NULL );
  903. if (ERROR_SUCCESS != lRet)
  904. {
  905. goto Cleanup;
  906. }
  907. //
  908. // Here we can create/open the VendorInfoEnumerator key.
  909. //
  910. lRet = RegCreateKeyEx( hKeyVendorInfo, pszVendorSetupEnumerator, 0,
  911. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  912. &hKeyVendorInfoEnumerator, &dwDisposition );
  913. if (ERROR_SUCCESS != lRet)
  914. {
  915. goto Cleanup;
  916. }
  917. else
  918. {
  919. if (dwDisposition == REG_OPENED_EXISTING_KEY)
  920. {
  921. //
  922. // The VendorInfoEnumerator alredy exists. We opened and existing
  923. // key. So we have to increment its value with 1 because we intend
  924. // to create another VendorSetup key and to store there the
  925. // corresponding information.
  926. //
  927. dwType = REG_DWORD;
  928. dwSize = sizeof( lEnumerator );
  929. if (ERROR_SUCCESS != RegQueryValueEx(hKeyVendorInfoEnumerator,
  930. pszVendorSetupEnumerator, 0,
  931. &dwType, (LPBYTE)(&lEnumerator),
  932. &dwSize ) )
  933. {
  934. goto Cleanup;
  935. }
  936. lEnumerator++;
  937. }
  938. else
  939. {
  940. //
  941. // The VendorInfoEnumerator has been created. So this is the first
  942. // printer for which we have VendorSetup provided.
  943. //
  944. lEnumerator = 1;
  945. }
  946. }
  947. //
  948. // Below we will convert the value of VendorInfoEnumerator to a string and
  949. // will concatenate that string to "VendorSetup" to produce the names of
  950. // the Registry key and value where the data about the vendor provided DLL,
  951. // its entry point and the printer will be stored.
  952. //
  953. pszVendorSetupIDAsStr = AllocMem( dwMaxVendorSetupIDLength * sizeof(CHAR) );
  954. if (!pszVendorSetupIDAsStr)
  955. {
  956. lRet = GetLastError();
  957. goto Cleanup;
  958. }
  959. _itoa( lEnumerator, pszVendorSetupIDAsStr, 10 );
  960. //
  961. // Below the memory necessary to build the vendor setup data and the
  962. // registry key name from the input data and from the value of
  963. // the VendorInfoEnumerator will be allocated.
  964. //
  965. cbBufferSize = (strlen(pszVendorSetup) + strlen(pszPrinterName) + strlen(TEXT(" \"\"")) + 2) * sizeof(CHAR);
  966. cbBuffer1Size = (strlen(pszVendorSetupID) + strlen(pszVendorSetupIDAsStr) + 2) * sizeof(CHAR);
  967. pszBuffer1 = AllocMem( cbBuffer1Size );
  968. pszBuffer = AllocMem( cbBufferSize );
  969. if (!pszBuffer || !pszBuffer1)
  970. {
  971. lRet = GetLastError();
  972. goto Cleanup;
  973. }
  974. else
  975. {
  976. strcpy( pszBuffer1, pszVendorSetupID);
  977. strcat( pszBuffer1, pszVendorSetupIDAsStr );
  978. //
  979. // At this point pszBuffer1 points to the following string:
  980. // VendorSetupK where K is an integer - the value of VendorInfoEnumerator
  981. //
  982. lRet = RegCreateKeyEx( hKeyVendorInfo, pszBuffer1, 0, NULL,
  983. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  984. &hKeyVendorInfoInstaller, NULL );
  985. if (ERROR_SUCCESS != lRet)
  986. {
  987. goto Cleanup;
  988. }
  989. else
  990. {
  991. //
  992. // The Registry Key where to store the vendor setup data was
  993. // created successfully.
  994. //
  995. strcpy( pszBuffer, pszVendorSetup);
  996. strcat( pszBuffer, " \"");
  997. strcat( pszBuffer, pszPrinterName );
  998. strcat( pszBuffer, "\"");
  999. //
  1000. // At this point pszBuffer points to the following string:
  1001. // VendorSetup.DLL,EntryPoint "PrinterName". We will store
  1002. // that string in the Registry Key which we just created.
  1003. //
  1004. lRet = RegSetValueEx(hKeyVendorInfoInstaller, pszBuffer1, 0,
  1005. REG_SZ, (BYTE *)pszBuffer, cbBufferSize );
  1006. if (lRet != ERROR_SUCCESS)
  1007. {
  1008. goto Cleanup;
  1009. }
  1010. }
  1011. }
  1012. //
  1013. // Here we will store the value of VendorInfoEnumerator.
  1014. //
  1015. dwSize = sizeof( lEnumerator );
  1016. lRet = RegSetValueEx(hKeyVendorInfoEnumerator, pszVendorSetupEnumerator,
  1017. 0, REG_DWORD, (BYTE*)(&lEnumerator), dwSize );
  1018. if (ERROR_SUCCESS != lRet)
  1019. {
  1020. goto Cleanup;
  1021. }
  1022. //
  1023. // Now we can try to store into the registry the information how to invoke
  1024. // the migrate.dll after the first log on of an administrator.
  1025. //
  1026. pszVendorSetupRunOnceValue = GetVendorSetupRunOnceValueToSet();
  1027. if (!pszVendorSetupRunOnceValue)
  1028. {
  1029. lRet = GetLastError();
  1030. goto Cleanup;
  1031. }
  1032. //
  1033. // We will try to open the
  1034. // HKLM\Software\Microsoft\Windows\CurrentVersion\Run
  1035. //
  1036. lRet = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  1037. szVendorSetupRunRegistryPath, 0, NULL,
  1038. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  1039. &hKeyVendorRunOnceValuePath, NULL );
  1040. if (ERROR_SUCCESS != lRet)
  1041. {
  1042. goto Cleanup;
  1043. }
  1044. else
  1045. {
  1046. //
  1047. // We will try to create the
  1048. // HKLM\Software\Microsoft\Windows\CurrentVersion\Run\MigrationVendorSetupCaller
  1049. //
  1050. lRet = RegCreateKeyEx( hKeyVendorRunOnceValuePath, pszMigrationVendorSetupCaller, 0,
  1051. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  1052. &hKeyVendorRunOnceCallerValue, &dwDisposition );
  1053. if (ERROR_SUCCESS != lRet)
  1054. {
  1055. goto Cleanup;
  1056. }
  1057. if (dwDisposition == REG_OPENED_EXISTING_KEY)
  1058. {
  1059. goto Cleanup;
  1060. }
  1061. //
  1062. // Here we will store the "rundll.exe %WinRoot%\System32\spool\migrate.dll,CallVendorSetupDlls"
  1063. // string into the registry
  1064. //
  1065. lRet = RegSetValueEx(hKeyVendorRunOnceCallerValue, pszMigrationVendorSetupCaller,
  1066. 0, REG_SZ, (BYTE *)pszVendorSetupRunOnceValue,
  1067. strlen(pszVendorSetupRunOnceValue) * sizeof(CHAR) );
  1068. }
  1069. Cleanup:
  1070. if (pszVendorSetupRunOnceValue)
  1071. {
  1072. FreeMem(pszVendorSetupRunOnceValue);
  1073. }
  1074. if (pszVendorSetupIDAsStr)
  1075. {
  1076. FreeMem(pszVendorSetupIDAsStr);
  1077. }
  1078. if (pszBuffer)
  1079. {
  1080. FreeMem(pszBuffer);
  1081. }
  1082. if (pszBuffer1)
  1083. {
  1084. FreeMem(pszBuffer1);
  1085. }
  1086. if (hKeyVendorRunOnceValuePath != INVALID_HANDLE_VALUE)
  1087. {
  1088. RegCloseKey( hKeyVendorRunOnceValuePath );
  1089. }
  1090. if (hKeyVendorRunOnceCallerValue != INVALID_HANDLE_VALUE)
  1091. {
  1092. RegCloseKey( hKeyVendorRunOnceCallerValue );
  1093. }
  1094. if (hKeyVendorInfoInstaller != INVALID_HANDLE_VALUE)
  1095. {
  1096. RegCloseKey( hKeyVendorInfoInstaller );
  1097. }
  1098. if (hKeyVendorInfoEnumerator != INVALID_HANDLE_VALUE)
  1099. {
  1100. RegCloseKey( hKeyVendorInfoEnumerator );
  1101. }
  1102. if (hKeyVendorInfo != INVALID_HANDLE_VALUE)
  1103. {
  1104. RegCloseKey( hKeyVendorInfo );
  1105. }
  1106. if (hKeyVendorInfoPath != INVALID_HANDLE_VALUE)
  1107. {
  1108. RegCloseKey( hKeyVendorInfoPath );
  1109. }
  1110. return lRet;
  1111. }
  1112. LONG
  1113. RemoveVendorSetupInfoFromRegistry(
  1114. VOID
  1115. )
  1116. /*++
  1117. Routine Description:
  1118. This routine is called to remove the vendor setup information from the
  1119. registry
  1120. Arguments:
  1121. Return Value:
  1122. ERROR_SUCCESS in the case of success
  1123. error code in any other case
  1124. --*/
  1125. {
  1126. LONG lRet = ERROR_SUCCESS;
  1127. HKEY hKeyVendorInfoPath = INVALID_HANDLE_VALUE;
  1128. HKEY hKeyVendorInfo = INVALID_HANDLE_VALUE;
  1129. HKEY hKeyVendorInfoEnumerator = INVALID_HANDLE_VALUE;
  1130. HKEY hKeyVendorRunOnceValuePath = INVALID_HANDLE_VALUE;
  1131. LONG lVendorSetupKeysNum = 0;
  1132. DWORD dwMaxSubKeyLen = 0;
  1133. DWORD dwMaxClassLen = 0;
  1134. DWORD dwValues = 0;
  1135. DWORD dwMaxValueNameLen = 0;
  1136. DWORD dwMaxValueLen = 0;
  1137. LONG lIndex = 0;
  1138. DWORD dwSize = 0;
  1139. DWORD dwType = 0;
  1140. DWORD dwKeyNameBufferLen = 0;
  1141. CHAR *pszKeyNameBuffer = NULL;
  1142. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szVendorSetupRunRegistryPath, 0,
  1143. KEY_ALL_ACCESS, &hKeyVendorRunOnceValuePath );
  1144. if (ERROR_SUCCESS != lRet)
  1145. {
  1146. goto Cleanup;
  1147. }
  1148. //
  1149. // Delete the registry keys used to store the location and the entry point
  1150. // of migrate.dll
  1151. //
  1152. lRet = RegDeleteKey( hKeyVendorRunOnceValuePath, pszMigrationVendorSetupCaller);
  1153. if (lRet != ERROR_SUCCESS)
  1154. {
  1155. goto Cleanup;
  1156. }
  1157. //
  1158. // Below we have to delete the registry keys used to store the descriptions
  1159. // of the vendor provided setup DLLs.
  1160. //
  1161. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszVendorSetupInfoPath, 0,
  1162. KEY_ALL_ACCESS, &hKeyVendorInfoPath );
  1163. if (lRet != ERROR_SUCCESS)
  1164. {
  1165. goto Cleanup;
  1166. }
  1167. lRet = RegOpenKeyEx( hKeyVendorInfoPath, pszVendorSetupInfo, 0,
  1168. KEY_ALL_ACCESS, &hKeyVendorInfo );
  1169. if (ERROR_SUCCESS != lRet)
  1170. {
  1171. goto Cleanup;
  1172. }
  1173. //
  1174. // Here we have to open the VendorInfoEnumerator and to read the
  1175. // number of vendor provided setup DLLs.
  1176. //
  1177. lRet = RegOpenKeyEx( hKeyVendorInfo, pszVendorSetupEnumerator, 0,
  1178. KEY_ALL_ACCESS, &hKeyVendorInfoEnumerator );
  1179. if (ERROR_SUCCESS != lRet)
  1180. {
  1181. goto Cleanup;
  1182. }
  1183. dwType = REG_DWORD;
  1184. dwSize = sizeof( lVendorSetupKeysNum );
  1185. lRet = RegQueryValueEx(hKeyVendorInfoEnumerator, pszVendorSetupEnumerator, 0,
  1186. &dwType, (LPBYTE)(&lVendorSetupKeysNum), &dwSize );
  1187. if (ERROR_SUCCESS != lRet)
  1188. {
  1189. goto Cleanup;
  1190. }
  1191. RegCloseKey( hKeyVendorInfoEnumerator );
  1192. hKeyVendorInfoEnumerator = INVALID_HANDLE_VALUE;
  1193. lRet = RegDeleteKey( hKeyVendorInfo, pszVendorSetupEnumerator);
  1194. if (ERROR_SUCCESS != lRet)
  1195. {
  1196. goto Cleanup;
  1197. }
  1198. if (lVendorSetupKeysNum <= 0)
  1199. {
  1200. goto Cleanup;
  1201. }
  1202. //
  1203. // We have to add 1 for the the enumerator key itself to calculate the
  1204. // number of registry keys where the vendor setup descriptions are
  1205. // stored.
  1206. //
  1207. lVendorSetupKeysNum += 1;
  1208. //
  1209. // Below we will find the longest string used in the registry keys where
  1210. // the vendor setup information is stored.
  1211. //
  1212. lRet = RegQueryInfoKey( hKeyVendorInfo, NULL, NULL, NULL, &lVendorSetupKeysNum,
  1213. &dwMaxSubKeyLen, &dwMaxClassLen, &dwValues, &dwMaxValueNameLen,
  1214. &dwMaxValueLen, NULL, NULL );
  1215. if (ERROR_SUCCESS != lRet)
  1216. {
  1217. goto Cleanup;
  1218. }
  1219. dwKeyNameBufferLen = __max( __max( dwMaxClassLen, dwMaxSubKeyLen),
  1220. __max( dwMaxValueNameLen, dwMaxValueLen ));
  1221. dwKeyNameBufferLen += 1;
  1222. //
  1223. // Now we have data enough to allocate a buffer long enough to store
  1224. // the longest string describing a key to delete.
  1225. //
  1226. pszKeyNameBuffer = AllocMem( dwKeyNameBufferLen * sizeof( CHAR ) );
  1227. if (!pszKeyNameBuffer)
  1228. {
  1229. goto Cleanup;
  1230. }
  1231. //
  1232. // Enumerate and delete the keys used to store the VendorSetup
  1233. // descriptions
  1234. //
  1235. lIndex = lVendorSetupKeysNum;
  1236. while (lIndex >= 0)
  1237. {
  1238. if (ERROR_SUCCESS != (lRet = RegEnumKey( hKeyVendorInfo, lIndex, pszKeyNameBuffer, dwKeyNameBufferLen)))
  1239. {
  1240. goto Cleanup;
  1241. }
  1242. lRet = RegDeleteKey( hKeyVendorInfo, pszKeyNameBuffer);
  1243. if (ERROR_SUCCESS != (lRet = RegDeleteKey( hKeyVendorInfo, pszKeyNameBuffer)))
  1244. {
  1245. goto Cleanup;
  1246. }
  1247. lIndex--;
  1248. }
  1249. Cleanup:
  1250. if (pszKeyNameBuffer)
  1251. {
  1252. FreeMem( pszKeyNameBuffer );
  1253. }
  1254. if (hKeyVendorInfoEnumerator != INVALID_HANDLE_VALUE)
  1255. {
  1256. RegCloseKey( hKeyVendorInfoEnumerator );
  1257. }
  1258. if (hKeyVendorInfo != INVALID_HANDLE_VALUE)
  1259. {
  1260. RegCloseKey( hKeyVendorInfo );
  1261. }
  1262. if (hKeyVendorInfoPath != INVALID_HANDLE_VALUE)
  1263. {
  1264. RegDeleteKey( hKeyVendorInfoPath, pszVendorSetupInfo );
  1265. RegCloseKey( hKeyVendorInfoPath );
  1266. }
  1267. if (hKeyVendorRunOnceValuePath != INVALID_HANDLE_VALUE)
  1268. {
  1269. RegCloseKey( hKeyVendorRunOnceValuePath );
  1270. }
  1271. return lRet;
  1272. }
  1273. VOID
  1274. CallVendorSetupDlls(
  1275. VOID
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. This is called after the first log on of an administrator. It calls
  1280. vendor setup DLLs using the information we stored in the registry
  1281. Arguments:
  1282. Return Value:
  1283. --*/
  1284. {
  1285. LONG lRet = ERROR_SUCCESS;
  1286. HKEY hKeyVendorInfoPath = INVALID_HANDLE_VALUE;
  1287. HKEY hKeyVendorInfo = INVALID_HANDLE_VALUE;
  1288. HKEY hKeyVendorInfoEnumerator = INVALID_HANDLE_VALUE;
  1289. HKEY hKeyVendorSetup = INVALID_HANDLE_VALUE;
  1290. HKEY hKeyVendorRunOnceValuePath = INVALID_HANDLE_VALUE;
  1291. HKEY hKeyVendorRunOnceCallerValue = INVALID_HANDLE_VALUE;
  1292. HWND hwnd = INVALID_HANDLE_VALUE;
  1293. LONG lVendorSetupKeysNum = 0;
  1294. DWORD dwMaxSubKeyLen = 0;
  1295. DWORD dwMaxClassLen = 0;
  1296. DWORD dwValues = 0;
  1297. DWORD dwMaxValueNameLen = 0;
  1298. DWORD dwMaxValueLen = 0;
  1299. LONG lIndex = 0;
  1300. DWORD dwSize = 0;
  1301. DWORD dwType = 0;
  1302. DWORD dwKeyNameBufferLen = 0;
  1303. CHAR *pszKeyNameBuffer = NULL;
  1304. CHAR *pszVendorSetupRunOnceValue = NULL;
  1305. BYTE *pszVendorSetupPtr = NULL;
  1306. BOOL bLocalAdmin = FALSE;
  1307. CHAR szParams[2*MAX_PATH+1];
  1308. CHAR szCmd[] = "rundll32.exe";
  1309. SHELLEXECUTEINFO ShellExecInfo;
  1310. if (!IsLocalAdmin(&bLocalAdmin))
  1311. {
  1312. lRet = GetLastError();
  1313. goto Cleanup;
  1314. }
  1315. if (!bLocalAdmin)
  1316. {
  1317. goto Cleanup;
  1318. }
  1319. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszVendorSetupInfoPath, 0,
  1320. KEY_ALL_ACCESS, &hKeyVendorInfoPath );
  1321. if (lRet != ERROR_SUCCESS)
  1322. {
  1323. goto Cleanup;
  1324. }
  1325. lRet = RegOpenKeyEx( hKeyVendorInfoPath, pszVendorSetupInfo, 0,
  1326. KEY_ALL_ACCESS, &hKeyVendorInfo );
  1327. if (ERROR_SUCCESS != lRet)
  1328. {
  1329. //
  1330. // The vendor setup registry keys are missing.
  1331. // So there is nothing to do and we can remove from the registry
  1332. // all the keyes we use to call the vendor setup Dlls
  1333. //
  1334. RemoveVendorSetupInfoFromRegistry();
  1335. goto Cleanup;
  1336. }
  1337. lRet = RegOpenKeyEx( hKeyVendorInfo, pszVendorSetupEnumerator, 0,
  1338. KEY_ALL_ACCESS, &hKeyVendorInfoEnumerator );
  1339. if (ERROR_SUCCESS != lRet)
  1340. {
  1341. //
  1342. // The vendor setup registry enumerator is missing.
  1343. // So the registry is damaged and the best is to remove from
  1344. // it the other keyes we use to call the vendor setup Dlls
  1345. //
  1346. RemoveVendorSetupInfoFromRegistry();
  1347. goto Cleanup;
  1348. }
  1349. dwType = REG_DWORD;
  1350. dwSize = sizeof( lVendorSetupKeysNum );
  1351. lRet = RegQueryValueEx(hKeyVendorInfoEnumerator, pszVendorSetupEnumerator, 0,
  1352. &dwType, (LPBYTE)(&lVendorSetupKeysNum), &dwSize );
  1353. if (ERROR_SUCCESS != lRet)
  1354. {
  1355. //
  1356. // We cannot read the vendor setup registry enumerator.
  1357. // So the registry is damaged and the best is to remove from
  1358. // it the other keyes we use to call the vendor setup Dlls
  1359. //
  1360. RemoveVendorSetupInfoFromRegistry();
  1361. goto Cleanup;
  1362. }
  1363. RegCloseKey( hKeyVendorInfoEnumerator );
  1364. hKeyVendorInfoEnumerator = INVALID_HANDLE_VALUE;
  1365. if (lVendorSetupKeysNum <= 0)
  1366. {
  1367. //
  1368. // We have only the enumerator and no any vendor setup info key.
  1369. // So there is nothing to do and we can remove from the registry
  1370. // all the keyes we use to call the vendor setup Dlls
  1371. //
  1372. RemoveVendorSetupInfoFromRegistry();
  1373. goto Cleanup;
  1374. }
  1375. //
  1376. // We have to add 1 for the enumerator key itself
  1377. //
  1378. lVendorSetupKeysNum += 1;
  1379. lRet = RegQueryInfoKey( hKeyVendorInfo, NULL, NULL, NULL, &lVendorSetupKeysNum,
  1380. &dwMaxSubKeyLen, &dwMaxClassLen, &dwValues, &dwMaxValueNameLen,
  1381. &dwMaxValueLen, NULL, NULL );
  1382. if (ERROR_SUCCESS != lRet)
  1383. {
  1384. goto Cleanup;
  1385. }
  1386. dwKeyNameBufferLen = __max( __max( dwMaxClassLen, dwMaxSubKeyLen),
  1387. __max( dwMaxValueNameLen, dwMaxValueLen ));
  1388. dwKeyNameBufferLen += 2;
  1389. if ( dwKeyNameBufferLen > SIZECHARS(szParams) )
  1390. {
  1391. goto Cleanup;
  1392. }
  1393. pszKeyNameBuffer = AllocMem( dwKeyNameBufferLen * sizeof( CHAR ) );
  1394. if (!pszKeyNameBuffer)
  1395. {
  1396. goto Cleanup;
  1397. }
  1398. dwSize = dwKeyNameBufferLen * sizeof( CHAR );
  1399. pszVendorSetupPtr = AllocMem( dwSize );
  1400. if (!pszVendorSetupPtr)
  1401. {
  1402. goto Cleanup;
  1403. }
  1404. hwnd = GetDesktopWindow();
  1405. for (lIndex = lVendorSetupKeysNum - 1; lIndex >= 0; lIndex--)
  1406. {
  1407. lRet = RegEnumKeyA( hKeyVendorInfo, lIndex, pszKeyNameBuffer, dwKeyNameBufferLen);
  1408. if (ERROR_SUCCESS != lRet)
  1409. {
  1410. continue;
  1411. }
  1412. if (strcmp( pszKeyNameBuffer, pszVendorSetupEnumerator))
  1413. {
  1414. lRet = RegOpenKeyEx( hKeyVendorInfo, pszKeyNameBuffer, 0,
  1415. KEY_ALL_ACCESS, &hKeyVendorSetup );
  1416. if (ERROR_SUCCESS != lRet)
  1417. {
  1418. goto Cleanup;
  1419. }
  1420. dwType = REG_SZ;
  1421. lRet = RegQueryValueExA(hKeyVendorSetup, pszKeyNameBuffer, 0,
  1422. &dwType, pszVendorSetupPtr, &dwSize );
  1423. if (ERROR_SUCCESS != lRet)
  1424. {
  1425. if (ERROR_MORE_DATA == lRet)
  1426. {
  1427. FreeMem( pszVendorSetupPtr );
  1428. pszVendorSetupPtr = AllocMem( dwSize );
  1429. if (!pszVendorSetupPtr)
  1430. {
  1431. goto Cleanup;
  1432. }
  1433. lRet = RegQueryValueExA(hKeyVendorSetup, pszKeyNameBuffer, 0,
  1434. &dwType, pszVendorSetupPtr, &dwSize );
  1435. if (ERROR_SUCCESS != lRet)
  1436. {
  1437. goto Cleanup;
  1438. }
  1439. }
  1440. else
  1441. {
  1442. goto Cleanup;
  1443. }
  1444. }
  1445. RegCloseKey( hKeyVendorSetup );
  1446. hKeyVendorSetup = INVALID_HANDLE_VALUE;
  1447. ZeroMemory(&ShellExecInfo, sizeof(ShellExecInfo));
  1448. ShellExecInfo.cbSize = sizeof(ShellExecInfo);
  1449. ShellExecInfo.hwnd = hwnd;
  1450. ShellExecInfo.lpFile = szCmd;
  1451. ShellExecInfo.nShow = SW_SHOWNORMAL;
  1452. ShellExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
  1453. ShellExecInfo.lpParameters = pszVendorSetupPtr;
  1454. //
  1455. // Call run32dll and wait for the vendor dll to return before proceeding
  1456. //
  1457. if ( ShellExecuteEx(&ShellExecInfo) && ShellExecInfo.hProcess )
  1458. {
  1459. WaitForSingleObject(ShellExecInfo.hProcess, dwFourMinutes);
  1460. CloseHandle(ShellExecInfo.hProcess);
  1461. }
  1462. RegDeleteKey( hKeyVendorInfo, pszKeyNameBuffer);
  1463. //
  1464. // One of the registry keys describing a vendor provided setup DLL
  1465. // was removed. So the value of VendorInfoEnumerator must be
  1466. // decremented by 1.
  1467. //
  1468. DecrementVendorSetupEnumerator();
  1469. }
  1470. }
  1471. RemoveVendorSetupInfoFromRegistry();
  1472. Cleanup:
  1473. if (pszVendorSetupPtr)
  1474. {
  1475. FreeMem(pszVendorSetupPtr);
  1476. pszVendorSetupPtr = NULL;
  1477. }
  1478. if (pszVendorSetupRunOnceValue)
  1479. {
  1480. FreeMem(pszVendorSetupRunOnceValue);
  1481. }
  1482. if (pszKeyNameBuffer)
  1483. {
  1484. FreeMem( pszKeyNameBuffer );
  1485. }
  1486. if (hKeyVendorRunOnceValuePath != INVALID_HANDLE_VALUE)
  1487. {
  1488. RegCloseKey( hKeyVendorRunOnceValuePath );
  1489. }
  1490. if (hKeyVendorRunOnceCallerValue != INVALID_HANDLE_VALUE)
  1491. {
  1492. RegCloseKey( hKeyVendorRunOnceCallerValue );
  1493. }
  1494. if (hKeyVendorSetup != INVALID_HANDLE_VALUE)
  1495. {
  1496. RegCloseKey( hKeyVendorSetup );
  1497. }
  1498. if (hKeyVendorInfoEnumerator != INVALID_HANDLE_VALUE)
  1499. {
  1500. RegCloseKey( hKeyVendorInfoEnumerator );
  1501. }
  1502. if (hKeyVendorInfo != INVALID_HANDLE_VALUE)
  1503. {
  1504. RegCloseKey( hKeyVendorInfo );
  1505. }
  1506. if (hKeyVendorInfoPath != INVALID_HANDLE_VALUE)
  1507. {
  1508. RegCloseKey( hKeyVendorInfoPath );
  1509. }
  1510. return;
  1511. }
  1512. BOOL
  1513. IsLocalAdmin(
  1514. BOOL *pbAdmin
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. This Routine determines if the user is a local admin.
  1519. Parameters:
  1520. pbAdmin - Return Value, TRUE for local admin.
  1521. Return Value:
  1522. TRUE - Function succeded (return value is valid).
  1523. --*/
  1524. {
  1525. HMODULE AdvApi32Dll;
  1526. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  1527. BOOL bRet = FALSE;
  1528. PSID pSIDAdmin = NULL;
  1529. AllOCANDINITSID pAllocAndInitID = NULL;
  1530. CHECKTOKENMEMBERSHIP pCheckTokenMemship = NULL;
  1531. FREESID pFreeSid = NULL;
  1532. ASSERT( pbAdmin != NULL ); // Called locally
  1533. *pbAdmin = FALSE;
  1534. AdvApi32Dll = LoadLibraryUsingFullPathA( "advapi32.dll" );
  1535. if (AdvApi32Dll == NULL)
  1536. {
  1537. goto Cleanup;
  1538. }
  1539. pAllocAndInitID = (AllOCANDINITSID)GetProcAddress( AdvApi32Dll, "AllocateAndInitializeSid");
  1540. pCheckTokenMemship = (CHECKTOKENMEMBERSHIP)GetProcAddress( AdvApi32Dll, "CheckTokenMembership");
  1541. pFreeSid = (FREESID)GetProcAddress( AdvApi32Dll, "FreeSid");
  1542. if (!pAllocAndInitID || !pCheckTokenMemship || !pFreeSid)
  1543. {
  1544. goto Cleanup;
  1545. }
  1546. if (!((*pAllocAndInitID)( &SIDAuth, 2,
  1547. SECURITY_BUILTIN_DOMAIN_RID,
  1548. DOMAIN_ALIAS_RID_ADMINS,
  1549. 0, 0, 0, 0, 0, 0,
  1550. &pSIDAdmin)))
  1551. {
  1552. goto Cleanup;
  1553. }
  1554. if (!((*pCheckTokenMemship)( NULL,
  1555. pSIDAdmin,
  1556. pbAdmin )))
  1557. {
  1558. goto Cleanup;
  1559. }
  1560. bRet = TRUE;
  1561. Cleanup:
  1562. if (pSIDAdmin != NULL)
  1563. {
  1564. (*pFreeSid)( pSIDAdmin );
  1565. }
  1566. if (AdvApi32Dll)
  1567. {
  1568. FreeLibrary( AdvApi32Dll );
  1569. }
  1570. return bRet;
  1571. }
  1572. LONG
  1573. DecrementVendorSetupEnumerator(
  1574. VOID
  1575. )
  1576. /*++
  1577. Routine Description:
  1578. This routine is called to decrement the value of the VendorInfoEnumerator.
  1579. It is called after removing of one of the registry keys containing a description
  1580. of a vendor provided DLL.
  1581. Arguments:
  1582. Return Value:
  1583. ERROR_SUCCESS in the case of success
  1584. error code in any other case.
  1585. --*/
  1586. {
  1587. LONG lRet = ERROR_BADKEY;
  1588. HKEY hKeyVendorInfo = INVALID_HANDLE_VALUE;
  1589. HKEY hKeyVendorInfoPath = INVALID_HANDLE_VALUE;
  1590. HKEY hKeyVendorEnumerator = INVALID_HANDLE_VALUE;
  1591. LONG lEnumerator = 0;
  1592. DWORD dwDisposition = 0;
  1593. DWORD dwSize = 0;
  1594. DWORD dwType = 0;
  1595. lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszVendorSetupInfoPath, 0,
  1596. KEY_ALL_ACCESS, &hKeyVendorInfoPath );
  1597. if (ERROR_SUCCESS != lRet)
  1598. {
  1599. goto Cleanup;
  1600. }
  1601. lRet = RegOpenKeyEx( hKeyVendorInfoPath, pszVendorSetupInfo, 0,
  1602. KEY_ALL_ACCESS, &hKeyVendorInfo );
  1603. if (ERROR_SUCCESS != lRet)
  1604. {
  1605. RegCloseKey( hKeyVendorInfoPath );
  1606. goto Cleanup;
  1607. }
  1608. lRet = RegOpenKeyEx( hKeyVendorInfo, pszVendorSetupEnumerator, 0,
  1609. KEY_ALL_ACCESS, &hKeyVendorEnumerator );
  1610. if (ERROR_SUCCESS != lRet)
  1611. {
  1612. RegCloseKey( hKeyVendorInfo );
  1613. RegCloseKey( hKeyVendorInfoPath );
  1614. goto Cleanup;
  1615. }
  1616. else
  1617. {
  1618. dwType = REG_DWORD;
  1619. dwSize = sizeof( lEnumerator );
  1620. lRet = RegQueryValueEx(hKeyVendorEnumerator, pszVendorSetupEnumerator, 0,
  1621. &dwType, (LPBYTE)(&lEnumerator), &dwSize );
  1622. if (ERROR_SUCCESS == lRet)
  1623. {
  1624. lEnumerator--;
  1625. lRet = RegSetValueEx(hKeyVendorEnumerator, pszVendorSetupEnumerator,
  1626. 0, REG_DWORD, (BYTE*)(&lEnumerator), dwSize );
  1627. }
  1628. }
  1629. RegCloseKey( hKeyVendorEnumerator );
  1630. RegCloseKey( hKeyVendorInfo );
  1631. RegCloseKey( hKeyVendorInfoPath );
  1632. Cleanup:
  1633. return lRet;
  1634. }
  1635. BOOL
  1636. MakeACopyOfMigrateDll(
  1637. IN LPCSTR pszWorkingDir
  1638. )
  1639. /*++
  1640. Routine Description:
  1641. This routine is called to copy the Migrate.Dll into the given
  1642. directory.
  1643. Arguments:
  1644. pszWorkingDir - the path where the Migrate.Dll to be copied.
  1645. Return Value:
  1646. FALSE - in the case of error
  1647. TRUE - in the case of success
  1648. The bMigrateDllCopyed global variable is set to the corresponding value
  1649. --*/
  1650. {
  1651. CHAR szSource[MAX_PATH];
  1652. CHAR szTarget[MAX_PATH];
  1653. DWORD dwSize;
  1654. DWORD dwLen;
  1655. if (bMigrateDllCopyed || !pszWorkingDir || !strlen(pszWorkingDir))
  1656. {
  1657. goto Cleanup;
  1658. }
  1659. //
  1660. // First check if the source paths are ok
  1661. //
  1662. dwLen = strlen(szMigDll);
  1663. dwSize = sizeof(szTarget)/sizeof(szTarget[0]);
  1664. if ( strlen(pszWorkingDir) + dwLen + 2 > dwSize )
  1665. {
  1666. goto Cleanup;
  1667. }
  1668. //
  1669. // Need to make a copy of migrate.dll to the %windir%\system32\spool
  1670. // directory
  1671. //
  1672. sprintf(szSource, "%s\\%s", pszWorkingDir, szMigDll);
  1673. if ( !(dwLen = GetFileNameInSpoolDir(szTarget, dwSize, szMigDll)) ||
  1674. !CopyFileA(szSource, szTarget, FALSE) )
  1675. {
  1676. goto Cleanup;
  1677. }
  1678. bMigrateDllCopyed = TRUE;
  1679. Cleanup:
  1680. return bMigrateDllCopyed;
  1681. }
  1682. HMODULE LoadLibraryUsingFullPathA(
  1683. LPCSTR lpFileName
  1684. )
  1685. {
  1686. CHAR szSystemPath[MAX_PATH];
  1687. INT cLength = 0;
  1688. INT cFileNameLength = 0;
  1689. if (!lpFileName || ((cFileNameLength = strlen(lpFileName)) == 0))
  1690. {
  1691. return NULL;
  1692. }
  1693. if (GetSystemDirectoryA(szSystemPath, sizeof(szSystemPath)/sizeof(CHAR) ) == 0)
  1694. {
  1695. return NULL;
  1696. }
  1697. cLength = strlen(szSystemPath);
  1698. if (szSystemPath[cLength-1] != '\\')
  1699. {
  1700. if ((cLength + 1) >= MAX_PATH)
  1701. {
  1702. return NULL;
  1703. }
  1704. szSystemPath[cLength] = '\\';
  1705. szSystemPath[cLength + 1] = '\0';
  1706. cLength++;
  1707. }
  1708. if ((cLength + cFileNameLength) >= MAX_PATH)
  1709. {
  1710. return NULL;
  1711. }
  1712. strcat(szSystemPath, lpFileName);
  1713. return LoadLibraryA( szSystemPath );
  1714. }