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.

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