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.

526 lines
15 KiB

  1. /*
  2. * update.cpp -- Windows Update for DirectInput Device Configurations and Images
  3. *
  4. * History:
  5. * 4-22-00 qzheng First version
  6. *
  7. */
  8. #include <afxcmn.h>
  9. #include <windows.h>
  10. #include <windowsx.h>
  11. #include <direct.h>
  12. #include <wininet.h>
  13. #include <setupapi.h>
  14. #include <tchar.h>
  15. #include "cpanel.h"
  16. extern HINSTANCE ghInstance;
  17. extern PJOY pAssigned[MAX_ASSIGNED]; // List of assigned devices
  18. extern short iItem;
  19. extern IDirectInputJoyConfig *pDIJoyConfig;
  20. static TCHAR tszFtpAgent[] = TEXT("Game Control Panel");
  21. static TCHAR tszUpdateSite[] = TEXT("ftp.microsoft.com"); //????
  22. static TCHAR tszUpdateSiteUser[] = TEXT("anonymous");
  23. static TCHAR tszUpdateSitePass[] = TEXT("[email protected]");
  24. static TCHAR tszFormatRundll9x[] = TEXT("rundll.exe setupx.dll,InstallHinfSection DefaultInstall 4 ");
  25. static TCHAR tszFormatRundllNT[] = TEXT("\\system32\\rundll32.exe syssetup.dll,SetupInfObjectInstallAction DefaultInstall 4 ");
  26. static TCHAR tszUpdateInf[] = TEXT("dimapins.inf");
  27. // Global variable holding destination directory.
  28. static HINTERNET hOpen, hConnect;
  29. static DWORD dwType = FTP_TRANSFER_TYPE_BINARY;
  30. static TCHAR tszTargetPath[MAX_PATH];
  31. static BOOL Open(TCHAR *tszHost, TCHAR *tszUser, TCHAR *tszPass);
  32. static BOOL Close(HINTERNET hConnect);
  33. static BOOL ErrorOut( DWORD dError, TCHAR *szCallFunc);
  34. static BOOL lcd(TCHAR *tszDir);
  35. static BOOL rcd(TCHAR *tszDir);
  36. static void GetCurDeviceType(HWND hDlg, TCHAR *tszDeviceType);
  37. static void ExtractCabinet(PTSTR pszCabFile);
  38. static void ApplyUpdateInf( void );
  39. ///////////////////////////////////////////////////////////////////////////////
  40. //
  41. // FUNCTION: Update
  42. //
  43. // PURPOSE: Update device configuration files and image if there are new
  44. // ones on Windows Update Server.
  45. //
  46. ///////////////////////////////////////////////////////////////////////////////
  47. void Update(HWND hDlg, int nAccess, TCHAR *tszProxy)
  48. {
  49. TCHAR tszWinDir[STR_LEN_64];
  50. TCHAR tszLocalIni[MAX_PATH];
  51. TCHAR tszTempDir[MAX_PATH];
  52. TCHAR tszRemoteIni[MAX_PATH];
  53. TCHAR tszDeviceType[MAX_PATH];
  54. TCHAR tszDeviceCabFile[MAX_PATH];
  55. TCHAR tszBuf[MAX_PATH];
  56. OFSTRUCT ofs;
  57. HANDLE hIniFile;
  58. FILETIME ftLocalTime, ftRemoteTime, ftCT, ftLAT;
  59. TCHAR tszUpdateSiteDir[STR_LEN_32];
  60. TCHAR tszUpdateIniFile[STR_LEN_32];
  61. TCHAR tszLastUpdate[STR_LEN_32];
  62. BOOL fLocalIniExist;
  63. // nAccess: 1 - don't use proxy, default
  64. // 2 - use proxy
  65. switch (nAccess)
  66. {
  67. case 1:
  68. // No proxy specified. Open WININET.DLL w/ local access
  69. if ( !(hOpen = InternetOpen( tszFtpAgent, LOCAL_INTERNET_ACCESS , NULL, 0, 0) ) )
  70. {
  71. ErrorOut( GetLastError(), TEXT("InternetOpen"));
  72. return ;
  73. }
  74. break;
  75. case 2:
  76. // Specified proxy, Open WININET.DLL w/ Proxy
  77. if ( !(hOpen = InternetOpen( tszFtpAgent, CERN_PROXY_INTERNET_ACCESS, tszProxy, NULL, 0) ) )
  78. {
  79. ErrorOut( GetLastError(), TEXT("InternetOpen"));
  80. return ;
  81. }
  82. break;
  83. default:
  84. return;
  85. }
  86. if ( !Open(tszUpdateSite, tszUpdateSiteUser, tszUpdateSitePass) ){
  87. Error((short)IDS_UPDATE_NOTCONNECTED_TITLE, (short)IDS_UPDATE_NOTCONNECTED);
  88. return;
  89. }
  90. LoadString(ghInstance, IDS_UPDATE_SITEDIR, tszUpdateSiteDir, sizeof(tszUpdateSiteDir) );
  91. LoadString(ghInstance, IDS_UPDATE_INI, tszUpdateIniFile, sizeof(tszUpdateIniFile) );
  92. LoadString(ghInstance, IDS_UPDATE_LASTUPDATED, tszLastUpdate, sizeof(tszLastUpdate) );
  93. GetCurDeviceType( hDlg, tszDeviceType );
  94. // The following codes are to get last modified time of the local Ini file ($windir\dinputup.ini).
  95. GetWindowsDirectory( tszWinDir, sizeof(tszWinDir) );
  96. lstrcpy( tszLocalIni, tszWinDir );
  97. lstrcat( tszLocalIni, TEXT("\\") );
  98. lstrcat( tszLocalIni, tszUpdateIniFile );
  99. hIniFile = CreateFile(tszLocalIni,
  100. GENERIC_READ,
  101. 0,
  102. NULL,
  103. OPEN_EXISTING,
  104. FILE_ATTRIBUTE_NORMAL,
  105. NULL);
  106. if( hIniFile != INVALID_HANDLE_VALUE ) {
  107. GetFileTime( hIniFile, &ftCT, &ftLAT, &ftLocalTime );
  108. CloseHandle(hIniFile);
  109. fLocalIniExist = TRUE;
  110. } else {
  111. //the local dinputup.ini doesn't exist.
  112. fLocalIniExist = FALSE;
  113. ErrorOut(GetLastError(), TEXT("CreateFile(dinputup.ini) fails or file doesn't exist"));
  114. }
  115. // wsprintf( tszBuf, TEXT("%lx,%lx"), ftLWT.dwHighDateTime, ftLWT.dwLowDateTime );
  116. // lstrcpy( tszDeviceType, TEXT("VID_046D&PID_C207"));
  117. // WritePrivateProfileString( tszDeviceType, tszLastUpdate, tszBuf, tszUpdateIniFile);
  118. // The following codes are to get last modified time of the remote Ini file
  119. // on Windows Update server.
  120. GetTempPath( sizeof(tszTempDir), tszTempDir );
  121. lcd( tszTempDir );
  122. lstrcpy( tszRemoteIni, tszTempDir );
  123. lstrcat( tszRemoteIni, TEXT("\\") );
  124. lstrcat( tszRemoteIni, tszUpdateIniFile );
  125. rcd( tszUpdateSiteDir ); // change to proper directory on Windows Update Server.
  126. if ( !FtpGetFile(hConnect, tszUpdateIniFile, tszUpdateIniFile, FALSE, 0, INTERNET_FLAG_RELOAD | dwType, 0) ) {
  127. ErrorOut(GetLastError(), TEXT("FtpGetFile"));
  128. Error((short)IDS_UPDATE_NOTCONNECTED_TITLE, (short)IDS_UPDATE_FTP_ERROR);
  129. goto _CLOSE;
  130. }
  131. hIniFile = CreateFile(tszRemoteIni,
  132. GENERIC_READ,
  133. 0,
  134. NULL,
  135. OPEN_EXISTING,
  136. FILE_ATTRIBUTE_NORMAL,
  137. NULL);
  138. if( hIniFile != INVALID_HANDLE_VALUE ) {
  139. GetFileTime( hIniFile, &ftCT, &ftLAT, &ftRemoteTime );
  140. CloseHandle(hIniFile);
  141. } else {
  142. ErrorOut(GetLastError(), TEXT("CreateFile on Remote Ini file"));
  143. goto _CLOSE;
  144. }
  145. if( !fLocalIniExist || (CompareFileTime(&ftLocalTime, &ftRemoteTime) < 0) ) {
  146. // remote one is newer, overwrite local one.
  147. CopyFile( tszRemoteIni, tszLocalIni, FALSE );
  148. }
  149. lstrcpy( tszDeviceCabFile, tszDeviceType );
  150. lstrcat( tszDeviceCabFile, TEXT(".cab") );
  151. if (!FtpGetFile(hConnect, tszDeviceCabFile, tszDeviceCabFile, FALSE, 0, INTERNET_FLAG_RELOAD | dwType, 0 ) ) {
  152. ErrorOut(GetLastError(), TEXT("FtpGetFile"));
  153. Error((short)IDS_UPDATE_NOTCONNECTED_TITLE, (short)IDS_UPDATE_FTP_ERROR);
  154. goto _CLOSE;
  155. }
  156. lstrcpy( tszTargetPath, tszTempDir );
  157. lstrcat( tszTargetPath, TEXT("\\") );
  158. lstrcpy( tszBuf, tszTempDir );
  159. lstrcat( tszBuf, TEXT("\\"));
  160. lstrcat( tszBuf, tszDeviceCabFile );
  161. // extract cab file
  162. ExtractCabinet( tszBuf );
  163. // apply update inf file
  164. ApplyUpdateInf();
  165. _CLOSE:
  166. Close(hConnect);
  167. return;
  168. }
  169. ///////////////////////////////////////////////////////////////////////////////
  170. //
  171. // FUNCTION: lcd
  172. //
  173. // PURPOSE: Change to new directory on local
  174. //
  175. ///////////////////////////////////////////////////////////////////////////////
  176. BOOL lcd(TCHAR *tszDir)
  177. {
  178. if ((*tszDir != 0) && (_tchdir(tszDir) == -1)) {
  179. #ifdef _DEBUG
  180. OutputDebugString(TEXT("?Invalid Local Directory"));
  181. #endif
  182. return FALSE;
  183. }
  184. return TRUE;
  185. }
  186. ///////////////////////////////////////////////////////////////////////////////
  187. //
  188. // FUNCTION: rcd
  189. //
  190. // PURPOSE: Change to new directory on remote side
  191. //
  192. ///////////////////////////////////////////////////////////////////////////////
  193. BOOL rcd(TCHAR *tszDir)
  194. {
  195. BOOL fRtn = FALSE;
  196. if (*tszDir != 0)
  197. {
  198. if (!FtpSetCurrentDirectory(hConnect, tszDir))
  199. {
  200. ErrorOut(GetLastError(), TEXT("FtpSetCurrentDirectory"));
  201. fRtn = FALSE;
  202. }
  203. fRtn = TRUE;
  204. }
  205. return fRtn;
  206. }
  207. ///////////////////////////////////////////////////////////////////////////////
  208. //
  209. // FUNCTION: Open
  210. //
  211. // PURPOSE: Open an Internect connection to a host.
  212. //
  213. ///////////////////////////////////////////////////////////////////////////////
  214. BOOL Open(TCHAR *tszHost, TCHAR *tszUser, TCHAR *tszPass)
  215. {
  216. if ( !(hConnect = InternetConnect( hOpen, tszHost , INTERNET_INVALID_PORT_NUMBER, tszUser, tszPass, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE , 0) ) )
  217. {
  218. ErrorOut(GetLastError(), TEXT("InternetConnect"));
  219. return FALSE;
  220. }
  221. return TRUE;
  222. }
  223. ///////////////////////////////////////////////////////////////////////////////
  224. //
  225. // FUNCTION: Close
  226. //
  227. // PURPOSE: Close the opened connection (hConnect)
  228. //
  229. ///////////////////////////////////////////////////////////////////////////////
  230. BOOL Close(HINTERNET hConnect)
  231. {
  232. if (!InternetCloseHandle (hConnect) )
  233. {
  234. ErrorOut(GetLastError(), TEXT("InternetCloseHandle"));
  235. return FALSE;
  236. }
  237. return TRUE;
  238. }
  239. ///////////////////////////////////////////////////////////////////////////////
  240. //
  241. // FUNCTION: ErrorOut
  242. //
  243. // PURPOSE: This function is used to get extended Internet error.
  244. //
  245. // COMMENTS: Function returns TRUE on success and FALSE on failure.
  246. //
  247. ///////////////////////////////////////////////////////////////////////////////
  248. BOOL ErrorOut( DWORD dError, TCHAR *szCallFunc)
  249. {
  250. #ifdef _DEBUG
  251. TCHAR szTemp[100] = "", *szBuffer=NULL, *szBufferFinal = NULL;
  252. DWORD dwIntError , dwLength = 0;
  253. wsprintf (szTemp, "%s error %d\n ", szCallFunc, dError );
  254. if (dError == ERROR_INTERNET_EXTENDED_ERROR)
  255. {
  256. InternetGetLastResponseInfo (&dwIntError, NULL, &dwLength);
  257. if (dwLength)
  258. {
  259. if ( !(szBuffer = (TCHAR *) LocalAlloc ( LPTR, dwLength) ) )
  260. {
  261. lstrcat (szTemp, TEXT ( "Unable to allocate memory to display Internet error code. Error code: ") );
  262. lstrcat (szTemp, TEXT (_itoa (GetLastError(), szBuffer, 10) ) );
  263. lstrcat (szTemp, TEXT ("\n") );
  264. OutputDebugString(szTemp);
  265. return FALSE;
  266. }
  267. if (!InternetGetLastResponseInfo(&dwIntError, (LPTSTR) szBuffer, &dwLength))
  268. {
  269. lstrcat (szTemp, TEXT ( "Unable to get Internet error. Error code: ") );
  270. lstrcat (szTemp, TEXT (_itoa (GetLastError(), szBuffer, 10) ) );
  271. lstrcat (szTemp, TEXT ("\n") );
  272. OutputDebugString(szTemp);
  273. return FALSE;
  274. }
  275. if ( !(szBufferFinal = (TCHAR *) LocalAlloc( LPTR, (strlen (szBuffer) +strlen (szTemp) + 1) ) ) )
  276. {
  277. lstrcat (szTemp, TEXT ( "Unable to allocate memory. Error code: ") );
  278. lstrcat (szTemp, TEXT (_itoa (GetLastError(), szBuffer, 10) ) );
  279. lstrcat (szTemp, TEXT ("\n") );
  280. OutputDebugString(szTemp0;
  281. return FALSE;
  282. }
  283. lstrcpy (szBufferFinal, szTemp);
  284. lstrcat (szBufferFinal, szBuffer);
  285. LocalFree (szBuffer);
  286. OutputDebugString(szBufferFinal);
  287. LocalFree (szBufferFinal);
  288. }
  289. }
  290. else {
  291. OutputDebugString(szTemp);
  292. }
  293. #endif // _DEBUG
  294. return TRUE;
  295. }
  296. ///////////////////////////////////////////////////////////////////////////////
  297. //
  298. // FUNCTION: CabinetCallback
  299. //
  300. // PURPOSE: Callback used in ExtractCabinet
  301. //
  302. ///////////////////////////////////////////////////////////////////////////////
  303. LRESULT WINAPI
  304. CabinetCallback ( IN PVOID pMyInstallData,
  305. IN UINT Notification,
  306. IN UINT Param1,
  307. IN UINT Param2 )
  308. {
  309. LRESULT lRetVal = NO_ERROR;
  310. TCHAR szTarget[MAX_PATH];
  311. FILE_IN_CABINET_INFO *pInfo = NULL;
  312. FILEPATHS *pFilePaths = NULL;
  313. lstrcpy(szTarget,tszTargetPath);
  314. switch(Notification)
  315. {
  316. case SPFILENOTIFY_FILEINCABINET:
  317. pInfo = (FILE_IN_CABINET_INFO *)Param1;
  318. lstrcat(szTarget, pInfo->NameInCabinet);
  319. lstrcpy(pInfo->FullTargetName, szTarget);
  320. lRetVal = FILEOP_DOIT; // Extract the file.
  321. break;
  322. case SPFILENOTIFY_FILEEXTRACTED:
  323. pFilePaths = (FILEPATHS *)Param1;
  324. lRetVal = NO_ERROR;
  325. break;
  326. case SPFILENOTIFY_NEEDNEWCABINET: // Unexpected.
  327. lRetVal = NO_ERROR;
  328. break;
  329. }
  330. return lRetVal;
  331. }
  332. ///////////////////////////////////////////////////////////////////////////////
  333. //
  334. // FUNCTION: ExtractCabinet
  335. //
  336. // PURPOSE: Extract all files stored in the cab file.
  337. //
  338. ///////////////////////////////////////////////////////////////////////////////
  339. void ExtractCabinet(PTSTR pszCabFile)
  340. {
  341. if( !SetupIterateCabinet(pszCabFile, 0, (PSP_FILE_CALLBACK)CabinetCallback, 0) )
  342. {
  343. ErrorOut( GetLastError(), TEXT("Extract Cab File") );
  344. }
  345. }
  346. ///////////////////////////////////////////////////////////////////////////////
  347. //
  348. // FUNCTION: ApplyUpdateInf
  349. //
  350. // PURPOSE: Run dimapins.inf to install configuration files and images
  351. //
  352. ///////////////////////////////////////////////////////////////////////////////
  353. void ApplyUpdateInf( void )
  354. {
  355. TCHAR tszRundll[1024];
  356. STARTUPINFO si;
  357. PROCESS_INFORMATION pi;
  358. GetWindowsDirectory(tszRundll, sizeof(tszRundll));
  359. #ifdef _UNICODE
  360. lstrcat(tszRundll, tszFormatRundllNT);
  361. #else
  362. lstrcat(tszRundll, tszFormatRundll9x);
  363. #endif
  364. lstrcat(tszRundll, tszTargetPath);
  365. lstrcat(tszRundll, tszUpdateInf);
  366. ZeroMemory(&si, sizeof(STARTUPINFO));
  367. si.cb = sizeof(STARTUPINFO);
  368. ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
  369. if( CreateProcess(0, tszRundll, 0, 0, 0, 0, 0, 0, &si, &pi) )
  370. {
  371. CloseHandle(pi.hThread);
  372. CloseHandle(pi.hProcess);
  373. }
  374. #ifdef _DEBUG
  375. else {
  376. OutputDebugString(TEXT("JOY.CPL: ApplyUpdateInf: CreateProcess Failed!\n"));
  377. }
  378. #endif
  379. }
  380. INT_PTR CALLBACK CplUpdateProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  381. {
  382. BOOL fRet = FALSE;
  383. // HICON hIcon;
  384. switch (message)
  385. {
  386. case WM_INITDIALOG:
  387. // hIcon = LoadIcon(NULL, IDI_INFORMATION);
  388. // SendDlgItemMessage(hDlg, IDC_ICON_INFORMATION, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
  389. break;
  390. case WM_COMMAND:
  391. switch (LOWORD(wParam))
  392. {
  393. case IDOK:
  394. case IDCANCEL:
  395. EndDialog(hDlg, LOWORD(wParam));
  396. fRet = TRUE;
  397. break;
  398. default:
  399. break;
  400. }
  401. break;
  402. default:
  403. break;
  404. }
  405. return fRet;
  406. }
  407. ///////////////////////////////////////////////////////////////////////////////
  408. //
  409. // FUNCTION: GetCurDeviceType
  410. //
  411. // PURPOSE: Get device type of the current selected device
  412. //
  413. ///////////////////////////////////////////////////////////////////////////////
  414. void GetCurDeviceType(HWND hDlg, TCHAR *tszDeviceType)
  415. {
  416. DIJOYCONFIG_DX5 diJoyConfig;
  417. HWND hListCtrl;
  418. int id;
  419. hListCtrl = GetDlgItem(hDlg, IDC_LIST_DEVICE);
  420. id = GetItemData(hListCtrl, (BYTE)iItem);
  421. ZeroMemory(&diJoyConfig, sizeof(DIJOYCONFIG_DX5));
  422. diJoyConfig.dwSize = sizeof(DIJOYCONFIG_DX5);
  423. // find the assigned ID's
  424. if( SUCCEEDED(pDIJoyConfig->GetConfig(pAssigned[id]->ID, (LPDIJOYCONFIG)&diJoyConfig, DIJC_REGHWCONFIGTYPE)) )
  425. {
  426. #ifdef _UNICODE
  427. lstrcpy(tszDeviceType, diJoyConfig.wszType );
  428. #else
  429. USES_CONVERSION;
  430. lstrcpy(tszDeviceType, W2A(diJoyConfig.wszType) );
  431. #endif
  432. }
  433. #if 0
  434. // change '&' to '_'
  435. while( tszDeviceType ) {
  436. if( *tszDeviceType == TEXT('&') ) {
  437. *tszDeviceType = TEXT('_');
  438. }
  439. tszDeviceType++;
  440. }
  441. #endif
  442. return;
  443. }