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.

423 lines
11 KiB

  1. /*++
  2. Copyright (c) 1995-97 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. SrvInst.c
  6. Purpose:
  7. Server side install code. This code will be called from a process created by the spooler to do a
  8. "server" side install of a printer driver.
  9. Author:
  10. Patrick Vine (pvine) - 22 March 2000
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include "srvinst.hxx"
  16. const TCHAR gcszNTPrint[] = _TEXT("inf\\ntprint.inf");
  17. /*++
  18. Routine Name:
  19. ServerInstall
  20. Routine Description:
  21. Server side install code to be called by a process created by spooler.
  22. Installs the given printer driver - unless a newer driver with the same name
  23. is installed - from ntprint.inf in %WINDIR%\inf
  24. No UIs are popped up and the function will fail if UI would be required. Code
  25. is called by a process created by spooler. The driver name is passed as a command
  26. line argument to rundll32 in localspl.
  27. Localspl.dll spins a rundll32 process (using CreateProcess) which calls the ServerInstall
  28. entry point in ntprint.dll. Thus ServerInstall will be running in local system context.
  29. Arguments:
  30. hwnd - Window handle of stub window.
  31. hInstance, - Rundll instance handle.
  32. pszCmdLine - Pointer to command line.
  33. nCmdShow - Show command value always TRUE.
  34. Return Value:
  35. Returns the last error code. This can be read by the spooler by getting the return code from the process.
  36. --*/
  37. DWORD
  38. ServerInstallW(
  39. IN HWND hwnd,
  40. IN HINSTANCE hInstance,
  41. IN LPCTSTR pszCmdLine,
  42. IN UINT nCmdShow
  43. )
  44. {
  45. CServerInstall Installer;
  46. if( Installer.ParseCommand((LPTSTR)pszCmdLine) )
  47. {
  48. Installer.InstallDriver();
  49. }
  50. //
  51. // If an error occurs we call ExitProcess. Then the spooler picks up the
  52. // error code using GetExitCodeProcess. If no error occurs, then we
  53. // terminate normally
  54. //
  55. if (Installer.GetLastError() != ERROR_SUCCESS)
  56. {
  57. ExitProcess(Installer.GetLastError());
  58. }
  59. return Installer.GetLastError();
  60. }
  61. ////////////////////////////////////////////////////////////////////////////////
  62. //
  63. // Method definitions for CServerInstall Class.
  64. //
  65. ////////////////////////////////////////////////////////////////////////////////
  66. CServerInstall::
  67. CServerInstall() : _dwLastError(ERROR_SUCCESS),
  68. _tsDriverName(),
  69. _tsNtprintInf()
  70. {
  71. }
  72. CServerInstall::
  73. ~CServerInstall()
  74. {
  75. }
  76. BOOL
  77. CServerInstall::
  78. InstallDriver()
  79. {
  80. if( SetInfToNTPRINTDir() &&
  81. DriverNotInstalled() )
  82. {
  83. _dwLastError = ::InstallDriverSilently(_tsNtprintInf, _tsDriverName, NULL);
  84. }
  85. return (_dwLastError == ERROR_SUCCESS);
  86. }
  87. /*++
  88. Parameter structure:
  89. 1st word : Flags = default == 0 for now
  90. if flags = 0
  91. 2nd word : Pipe name to open
  92. --*/
  93. BOOL
  94. CServerInstall::
  95. ParseCommand( LPTSTR pszCommandStr )
  96. {
  97. TCHAR * pTemp;
  98. DWORD dwCount = 0;
  99. //
  100. // If we don't have a valid command string
  101. //
  102. if( !pszCommandStr || !*pszCommandStr )
  103. {
  104. _dwLastError = ERROR_INVALID_PARAMETER;
  105. goto Cleanup;
  106. }
  107. //
  108. // Grap the driver name
  109. //
  110. if( !_tsDriverName.bUpdate( pszCommandStr ))
  111. {
  112. _dwLastError = ERROR_NOT_ENOUGH_MEMORY;
  113. }
  114. Cleanup:
  115. return (_dwLastError == ERROR_SUCCESS);
  116. }
  117. DWORD
  118. CServerInstall::
  119. GetLastError()
  120. {
  121. SetLastError(_dwLastError);
  122. return _dwLastError;
  123. }
  124. //
  125. // Returns: TRUE if SUCCESS, FALSE otherwise
  126. //
  127. // Sets the _stInf string to contain %windir%\inf\ntprint.inf
  128. //
  129. BOOL
  130. CServerInstall::
  131. SetInfToNTPRINTDir()
  132. {
  133. UINT uiSize = 0;
  134. UINT uiAllocSize = 0;
  135. PTCHAR pData = NULL;
  136. TCHAR szNTPrintInf[MAX_PATH];
  137. DWORD dwPos;
  138. _dwLastError = ERROR_INVALID_DATA;
  139. //
  140. // Get %windir%
  141. // If the return is 0 - the call failed.
  142. // If the return is greater than MAX_PATH we want to fail as something has managed to change
  143. // the system dir to longer than MAX_PATH which is invalid. If length is the same we also fail
  144. // since we might add a '\' and gcszNTPrint is longer than 1 for sure!
  145. //
  146. uiSize = GetSystemWindowsDirectory( szNTPrintInf, COUNTOF(szNTPrintInf) );
  147. if( !uiSize || uiSize >= COUNTOF(szNTPrintInf) )
  148. goto Cleanup;
  149. //
  150. // If we don't end in a \ then add one.
  151. //
  152. dwPos = _tcslen(szNTPrintInf) - 1;
  153. pData = &szNTPrintInf[ dwPos++ ];
  154. if( *pData++ != _TEXT('\\') )
  155. {
  156. *(pData++) = _TEXT('\\');
  157. ++dwPos;
  158. }
  159. *(pData) = 0;
  160. uiSize = _tcslen( szNTPrintInf ) + _tcslen( gcszNTPrint ) + 1;
  161. //
  162. // If what we've got sums up to a longer string than the allowable length MAX_PATH - fail
  163. //
  164. if( uiSize > COUNTOF(szNTPrintInf) )
  165. goto Cleanup;
  166. //
  167. // Copy the inf\ntprint.inf string onto the end of the %windir%\ string.
  168. //
  169. StringCchCopy( pData, COUNTOF(szNTPrintInf) - dwPos, gcszNTPrint);
  170. _dwLastError = ERROR_SUCCESS;
  171. Cleanup:
  172. if( _dwLastError != ERROR_SUCCESS && szNTPrintInf )
  173. {
  174. //
  175. // Got here due to some error. Get what the called function set the last error to.
  176. // If the function set a success, set some error code.
  177. //
  178. if( (_dwLastError = ::GetLastError()) == ERROR_SUCCESS )
  179. _dwLastError = ERROR_INVALID_DATA;
  180. szNTPrintInf[0] = 0;
  181. }
  182. if( !_tsNtprintInf.bUpdate( szNTPrintInf ) )
  183. _dwLastError = ::GetLastError();
  184. return (_dwLastError == ERROR_SUCCESS);
  185. }
  186. /*+
  187. This function enumerates the drivers and finds if there is one of the same name currently installed.
  188. If there is then open the inf to install with and verify that the inf's version date is newer than the
  189. already installed driver.
  190. Returns: TRUE - if anything fails or the installed date isn't newer than the inf date.
  191. FALSE - only if the driver is installed AND it's date is newer than the inf's date.
  192. -*/
  193. BOOL
  194. CServerInstall::
  195. DriverNotInstalled()
  196. {
  197. LPCTSTR pszKey = _TEXT("DriverVer");
  198. LPTSTR pszEntry = NULL;
  199. LPDRIVER_INFO_6 pDriverInfo6 = NULL;
  200. LPBYTE pBuf = NULL;
  201. PSP_INF_INFORMATION pInfo = NULL;
  202. SYSTEMTIME Time = {0};
  203. BOOL bRet = TRUE;
  204. DWORD dwLength,
  205. dwRet,
  206. dwIndex;
  207. TCHAR *pTemp,
  208. *pTemp2;
  209. if(!EnumPrinterDrivers( NULL, PlatformEnv[MyPlatform].pszName, 6, pBuf, 0, &dwLength, &dwRet ))
  210. {
  211. if( ::GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  212. return TRUE;
  213. if( (pBuf = (LPBYTE) AllocMem( dwLength )) == NULL ||
  214. !EnumPrinterDrivers( NULL, PlatformEnv[MyPlatform].pszName, 6, pBuf, dwLength, &dwLength, &dwRet ))
  215. {
  216. _dwLastError = ::GetLastError();
  217. goto Cleanup;
  218. }
  219. }
  220. else
  221. {
  222. //
  223. // Only way this could succeed is if no drivers installed.
  224. //
  225. return TRUE;
  226. }
  227. for( dwIndex = 0, pDriverInfo6 = (LPDRIVER_INFO_6)pBuf; dwIndex < dwRet; dwIndex++, pDriverInfo6++ )
  228. {
  229. if( _tcscmp( pDriverInfo6->pName, (LPCTSTR)_tsDriverName ) == 0 )
  230. break;
  231. }
  232. if(dwIndex >= dwRet)
  233. {
  234. //
  235. // Driver not found
  236. //
  237. goto Cleanup;
  238. }
  239. //
  240. // The driver has been found... Open up inf and look at it's date.
  241. //
  242. //
  243. // Firstly get the size that will be needed for pInfo.
  244. //
  245. if( !SetupGetInfInformation( (LPCTSTR)_tsNtprintInf, INFINFO_INF_NAME_IS_ABSOLUTE, pInfo, 0, &dwLength ) )
  246. {
  247. _dwLastError = ::GetLastError();
  248. goto Cleanup;
  249. }
  250. //
  251. // Alloc pInfo and fill it.
  252. //
  253. if( (pInfo = (PSP_INF_INFORMATION) AllocMem( dwLength )) != NULL &&
  254. SetupGetInfInformation( (LPCTSTR)_tsNtprintInf, INFINFO_INF_NAME_IS_ABSOLUTE, pInfo, dwLength, &dwLength ) )
  255. {
  256. //
  257. // Get the size of the date string
  258. //
  259. if( SetupQueryInfVersionInformation( pInfo, 0, pszKey, pszEntry, 0, &dwLength ))
  260. {
  261. //
  262. // Alloc pszEntry and fill it.
  263. //
  264. if( (pszEntry = (LPTSTR) AllocMem( dwLength*sizeof(TCHAR) )) != NULL &&
  265. SetupQueryInfVersionInformation( pInfo, 0, pszKey, pszEntry, dwLength, &dwLength ))
  266. {
  267. //
  268. // Now convert the date string into a SYSTEMTIME
  269. // Date is of the form 03/22/2000
  270. //
  271. // Get the month - 03 part
  272. //
  273. if( (pTemp = _tcschr( pszEntry, _TEXT('/'))) != NULL )
  274. {
  275. *pTemp++ = 0;
  276. Time.wMonth = (WORD)_ttoi( pszEntry );
  277. pTemp2 = pTemp;
  278. //
  279. // Get the day - 22 part
  280. //
  281. if( (pTemp = _tcschr( pTemp2, _TEXT('/'))) != NULL )
  282. {
  283. *pTemp++ = 0;
  284. Time.wDay = (WORD)_ttoi( pTemp2 );
  285. pTemp2 = pTemp;
  286. //
  287. // Get the year - 2000 part
  288. //
  289. pTemp = _tcschr( pTemp2, _TEXT('/'));
  290. if( pTemp )
  291. *pTemp = 0;
  292. Time.wYear = (WORD)_ttoi( pTemp2 );
  293. }
  294. else
  295. _dwLastError = ERROR_INVALID_PARAMETER;
  296. }
  297. else
  298. _dwLastError = ERROR_INVALID_PARAMETER;
  299. }
  300. else
  301. _dwLastError = ::GetLastError();
  302. }
  303. else
  304. _dwLastError = ::GetLastError();
  305. }
  306. else
  307. _dwLastError = ::GetLastError();
  308. //
  309. // If we got all the way to filling in the year, we may have something useful...
  310. //
  311. if( Time.wYear )
  312. {
  313. FILETIME ftTime = {0};
  314. if(SystemTimeToFileTime( &Time, &ftTime ))
  315. {
  316. //
  317. // If the inf time is more recent than what is installed,
  318. // reinstall, otherwise don't
  319. //
  320. if( CompareFileTime(&ftTime, &pDriverInfo6->ftDriverDate) < 1 )
  321. {
  322. bRet = FALSE;
  323. }
  324. }
  325. //
  326. // Getting here and return TRUE or FALSE is still a successful call.
  327. //
  328. _dwLastError = ERROR_SUCCESS;
  329. }
  330. else
  331. _dwLastError = ERROR_INVALID_PARAMETER;
  332. Cleanup:
  333. if( pBuf )
  334. FreeMem( pBuf );
  335. if( pInfo )
  336. FreeMem( pInfo );
  337. if( pszEntry )
  338. FreeMem( pszEntry );
  339. return bRet;
  340. }