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.

423 lines
11 KiB

  1. #include "precomp.h"
  2. #include "resource.h"
  3. #include "pfnwininet.h"
  4. #include "pfnsetupapi.h"
  5. #include "AutoConf.h"
  6. #include "ConfUtil.h"
  7. // File level globals
  8. CAutoConf * g_pAutoConf = NULL;
  9. void CAutoConf::DoIt( void )
  10. {
  11. RegEntry re(POLICIES_KEY, HKEY_CURRENT_USER);
  12. if( !re.GetNumber(REGVAL_AUTOCONF_USE, DEFAULT_AUTOCONF_USE ) )
  13. {
  14. TRACE_OUT(( TEXT("AutoConf: Not using autoconfiguration")));
  15. return;
  16. }
  17. LPTSTR szAutoConfServer = re.GetString( REGVAL_AUTOCONF_CONFIGFILE );
  18. if( NULL == szAutoConfServer )
  19. {
  20. WARNING_OUT(( TEXT("AutoConf: AutoConf server is unset") ));
  21. DisplayErrMsg( IDS_AUTOCONF_SERVERNAME_MISSING );
  22. return;
  23. }
  24. g_pAutoConf = new CAutoConf( szAutoConfServer );
  25. ASSERT( g_pAutoConf );
  26. if( !g_pAutoConf->OpenConnection() )
  27. {
  28. WARNING_OUT(( TEXT("AutoConf: Connect to net failed") ));
  29. DisplayErrMsg( IDS_AUTOCONF_FAILED );
  30. goto cleanup;
  31. }
  32. if( NULL == g_pAutoConf->m_hOpenUrl )
  33. {
  34. WARNING_OUT(( TEXT("AutoConf: g_pAutoConf->m_hOpenUrl = NULL") ));
  35. DisplayErrMsg( IDS_AUTOCONF_FAILED );
  36. goto cleanup;
  37. }
  38. if( FALSE == g_pAutoConf->GetFile() )
  39. {
  40. WARNING_OUT(( TEXT("AutoConf: g_pAutoConf->GetFile() == FALSE") ));
  41. DisplayErrMsg( IDS_AUTOCONF_FAILED );
  42. goto cleanup;
  43. }
  44. if( FALSE == g_pAutoConf->QueryData() )
  45. {
  46. WARNING_OUT(( TEXT("AutoConf: g_pAutoConf->QueryData() == FALSE") ));
  47. DisplayErrMsg( IDS_AUTOCONF_FAILED );
  48. goto cleanup;
  49. }
  50. if( FAILED( SETUPAPI::Init() ) )
  51. {
  52. WARNING_OUT(( TEXT("AutoConf: Setupapi's failed to init") ));
  53. DisplayErrMsg( IDS_AUTOCONF_NEED_SETUPAPIS );
  54. goto cleanup;
  55. }
  56. if( !g_pAutoConf->ParseFile() )
  57. {
  58. WARNING_OUT(( TEXT("AutoConf: Could not parse inf file") ));
  59. DisplayErrMsg( IDS_AUTOCONF_PARSE_ERROR );
  60. goto cleanup;
  61. }
  62. TRACE_OUT(( TEXT("AutoConf: FILE PARSED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") ));
  63. cleanup:
  64. delete g_pAutoConf;
  65. return;
  66. }
  67. CAutoConf::CAutoConf( LPTSTR szServer )
  68. : m_szServer( szServer ), m_hInternet( NULL ), m_hOpenUrl( NULL ), m_dwGrab( 0 ),
  69. m_hInf( NULL ), m_hFile( INVALID_HANDLE_VALUE ), m_hEvent( NULL )
  70. {
  71. ZeroMemory( m_szFile, CCHMAX( m_szFile ) );
  72. m_hEvent = CreateEvent( NULL, TRUE, FALSE, TEXT( "NMAutoConf_WaitEvent" ) );
  73. RegEntry re(POLICIES_KEY, HKEY_CURRENT_USER);
  74. m_dwTimeOut = re.GetNumber(REGVAL_AUTOCONF_TIMEOUT, DEFAULT_AUTOCONF_TIMEOUT );
  75. }
  76. CAutoConf::~CAutoConf()
  77. {
  78. CloseInternet();
  79. if( INVALID_HANDLE_VALUE != m_hFile )
  80. {
  81. CloseHandle( m_hFile );
  82. }
  83. DeleteFile( m_szFile );
  84. if( NULL != m_hInf )
  85. {
  86. SETUPAPI::SetupCloseInfFile( m_hInf );
  87. }
  88. //WININET::DeInit();
  89. //SETUPAPI::DeInit();
  90. }
  91. BOOL CAutoConf::OpenConnection()
  92. {
  93. // ASSERT( phInternet );
  94. if( FAILED( WININET::Init() ) )
  95. {
  96. WARNING_OUT(( TEXT("AutoConf: WININET::Init failed") ));
  97. DisplayErrMsg( IDS_AUTOCONF_NO_WININET );
  98. return FALSE;
  99. }
  100. ASSERT( NULL != m_szServer );
  101. m_hInternet = WININET::InternetOpen( TEXT("NetMeeting"),
  102. INTERNET_OPEN_TYPE_DIRECT,
  103. NULL,
  104. NULL,
  105. INTERNET_FLAG_ASYNC );
  106. if( NULL == m_hInternet )
  107. {
  108. WARNING_OUT(( TEXT( "AutoConf: InternetOpen failed" ) ));
  109. return FALSE;
  110. }
  111. if( INTERNET_INVALID_STATUS_CALLBACK ==
  112. WININET::InternetSetStatusCallback( m_hInternet,
  113. (INTERNET_STATUS_CALLBACK) CAutoConf::InetCallback ) )
  114. {
  115. WARNING_OUT(( TEXT("AutoConf: InternetSetStatusCallback failed") ));
  116. return FALSE;
  117. }
  118. m_hOpenUrl = WININET::InternetOpenUrl( m_hInternet,
  119. m_szServer,
  120. NULL,
  121. 0,
  122. INTERNET_FLAG_KEEP_CONNECTION |
  123. INTERNET_FLAG_RELOAD,
  124. AUTOCONF_CONTEXT_OPENURL );
  125. if( NULL == m_hOpenUrl && ERROR_IO_PENDING != GetLastError() )
  126. {
  127. WARNING_OUT(( TEXT("AutoConf: InternetOpenUrl failed") ));
  128. return FALSE;
  129. }
  130. if( WAIT_FAILED == WaitForSingleObject( m_hEvent, m_dwTimeOut ) )
  131. {
  132. WARNING_OUT(( TEXT("AutoConf: InternetOpenUrl wait for handle failed") ));
  133. return FALSE;
  134. }
  135. return TRUE;
  136. }
  137. BOOL CAutoConf::ParseFile()
  138. {
  139. LPTSTR lstrInstallSection = TEXT("NetMtg.Install.NMRK");
  140. m_hInf = SETUPAPI::SetupOpenInfFile( m_szFile, // name of the INF to open
  141. NULL, // optional, the class of the INF file
  142. INF_STYLE_WIN4, // specifies the style of the INF file
  143. NULL // optional, receives error information
  144. );
  145. if( INVALID_HANDLE_VALUE == m_hInf )
  146. {
  147. return false;
  148. }
  149. return SETUPAPI::SetupInstallFromInfSection(
  150. NULL, // optional, handle of a parent window
  151. m_hInf, // handle to the INF file
  152. lstrInstallSection, // name of the Install section
  153. SPINST_REGISTRY , // which lines to install from section
  154. NULL, // optional, key for registry installs
  155. NULL, // optional, path for source files
  156. 0, // optional, specifies copy behavior
  157. NULL, // optional, specifies callback routine
  158. NULL, // optional, callback routine context
  159. NULL, // optional, device information set
  160. NULL // optional, device info structure
  161. );
  162. }
  163. BOOL CAutoConf::GetFile()
  164. {
  165. // ASSERT( INVALID_HANDLE_VALUE == m_hFile );
  166. TCHAR szPath[ MAX_PATH ];
  167. GetTempPath( CCHMAX( szPath ), // size, in characters, of the buffer
  168. szPath // pointer to buffer for temp. path
  169. );
  170. GetTempFileName( szPath, // pointer to directory name for temporary file
  171. TEXT("NMA"), // pointer to filename prefix
  172. 0, // number used to create temporary filename
  173. m_szFile // pointer to buffer that receives the new filename
  174. );
  175. m_hFile = CreateFile( m_szFile,
  176. GENERIC_READ | GENERIC_WRITE,
  177. 0,
  178. NULL,
  179. CREATE_ALWAYS,
  180. FILE_ATTRIBUTE_TEMPORARY /*| FILE_FLAG_DELETE_ON_CLOSE*/,
  181. NULL );
  182. if( INVALID_HANDLE_VALUE == m_hFile )
  183. {
  184. WARNING_OUT(( TEXT("AutoConf: AutoConfGetFile returned INVALID_HANDLE_VALUE") ));
  185. return FALSE;
  186. }
  187. return TRUE;
  188. }
  189. BOOL CAutoConf::QueryData()
  190. {
  191. ASSERT( NULL != m_hOpenUrl );
  192. m_dwGrab = 0;
  193. if (!WININET::InternetQueryDataAvailable( m_hOpenUrl,
  194. &m_dwGrab,
  195. 0,
  196. 0 ) )
  197. {
  198. if( ERROR_IO_PENDING != GetLastError() )
  199. {
  200. WARNING_OUT(( TEXT("AutoConf: InternetQueryDataAvailable failed") ));
  201. return FALSE;
  202. }
  203. else if( WAIT_FAILED == WaitForSingleObject( m_hEvent, m_dwTimeOut ) )
  204. {
  205. WARNING_OUT(( TEXT("AutoConf: InternetQueryDataAvailable wait for data failed") ));
  206. return FALSE;
  207. }
  208. }
  209. GrabData();
  210. return TRUE;
  211. }
  212. BOOL CAutoConf::GrabData()
  213. {
  214. ASSERT( NULL != m_hOpenUrl );
  215. ASSERT( INVALID_HANDLE_VALUE != m_hFile );
  216. if( !m_dwGrab )
  217. {
  218. TRACE_OUT(( TEXT("AutoConf: Finished Reading File") ));
  219. CloseHandle( m_hFile );
  220. m_hFile = INVALID_HANDLE_VALUE;
  221. return TRUE;
  222. }
  223. DWORD dwRead;
  224. LPTSTR pInetBuffer = new TCHAR[ m_dwGrab + 1];
  225. ASSERT( pInetBuffer );
  226. if( !WININET::InternetReadFile( m_hOpenUrl,
  227. (void *)pInetBuffer,
  228. m_dwGrab,
  229. &dwRead ) )// && ERROR_IO_PENDING != GetLastError() )
  230. {
  231. WARNING_OUT(( TEXT("AutoConf: InternetReadFile Failed") ));
  232. delete [] pInetBuffer;
  233. return FALSE;
  234. }
  235. else
  236. {
  237. pInetBuffer[ dwRead ] = '\0';
  238. if( !WriteFile( m_hFile,
  239. pInetBuffer,
  240. dwRead,
  241. &m_dwGrab,
  242. NULL ) || dwRead != m_dwGrab )
  243. {
  244. WARNING_OUT(( TEXT("AutoConf: WriteFile Failed") ));
  245. delete [] pInetBuffer;
  246. return FALSE;
  247. }
  248. }
  249. delete [] pInetBuffer;
  250. QueryData();
  251. return TRUE;
  252. }
  253. void CAutoConf::CloseInternet()
  254. {
  255. HINTERNETKILL( m_hInternet );
  256. HINTERNETKILL( m_hOpenUrl );
  257. }
  258. VOID CALLBACK CAutoConf::InetCallback( HINTERNET hInternet, DWORD dwContext, DWORD dwInternetStatus,
  259. LPVOID lpvStatusInformation, DWORD dwStatusInformationLength )
  260. {
  261. if( g_pAutoConf != NULL )
  262. {
  263. switch( dwInternetStatus )
  264. {
  265. case INTERNET_STATUS_REQUEST_COMPLETE:
  266. {
  267. TRACE_OUT(( TEXT("AutoConf: AutoConfInetCallback::INTERNET_STATUS_REQUEST_COMPLETE") ));
  268. if( AUTOCONF_CONTEXT_OPENURL == dwContext && g_pAutoConf->m_hOpenUrl == NULL )
  269. {
  270. TRACE_OUT(( TEXT("AutoConf: InternetOpenUrl Finished") ));
  271. LPINTERNET_ASYNC_RESULT lpIAR = (LPINTERNET_ASYNC_RESULT)lpvStatusInformation;
  272. #ifndef _WIN64
  273. g_pAutoConf->m_hOpenUrl = (HINTERNET)lpIAR->dwResult;
  274. #endif
  275. SetEvent( g_pAutoConf->m_hEvent );
  276. }
  277. else
  278. {
  279. LPINTERNET_ASYNC_RESULT lpIAR = (LPINTERNET_ASYNC_RESULT)lpvStatusInformation;
  280. TRACE_OUT(( TEXT("AutoConf: QueryData returned") ));
  281. g_pAutoConf->m_dwGrab = (DWORD)lpIAR->dwResult;
  282. SetEvent( g_pAutoConf->m_hEvent );
  283. }
  284. break;
  285. }
  286. #ifdef DEBUG
  287. case INTERNET_STATUS_CLOSING_CONNECTION:
  288. //Closing the connection to the server. The lpvStatusInformation parameter is NULL.
  289. TRACE_OUT(( TEXT("Closing connection\n") ) );
  290. break;
  291. case INTERNET_STATUS_CONNECTED_TO_SERVER:
  292. //Successfully connected to the socket address (SOCKADDR) pointed to by lpvStatusInformation.
  293. TRACE_OUT(( TEXT("Connected to server") ) );
  294. break;
  295. case INTERNET_STATUS_CONNECTING_TO_SERVER:
  296. //Connecting to the socket address (SOCKADDR) pointed to by lpvStatusInformation.
  297. TRACE_OUT(( TEXT("Connecting to server") ) );
  298. break;
  299. case INTERNET_STATUS_CONNECTION_CLOSED:
  300. //Successfully closed the connection to the server.
  301. //The lpvStatusInformation parameter is NULL.
  302. TRACE_OUT(( TEXT("Connection Closed") ) );
  303. break;
  304. case INTERNET_STATUS_HANDLE_CLOSING:
  305. //This handle value is now terminated.
  306. TRACE_OUT(( TEXT("Handle value terminated\n") ) );
  307. break;
  308. case INTERNET_STATUS_HANDLE_CREATED:
  309. //Used by InternetConnect to indicate it has created the new handle.
  310. //This lets the application call InternetCloseHandle from another thread,
  311. //if the connect is taking too long.
  312. TRACE_OUT(( TEXT("Handle created\n") ) );
  313. break;
  314. case INTERNET_STATUS_NAME_RESOLVED:
  315. //Successfully found the IP address of the name contained in lpvStatusInformation.
  316. TRACE_OUT(( TEXT("Resolved name of server") ) );
  317. break;
  318. case INTERNET_STATUS_RECEIVING_RESPONSE:
  319. //Waiting for the server to respond to a request.
  320. //The lpvStatusInformation parameter is NULL.
  321. TRACE_OUT(( TEXT("Recieving response\n") ) );
  322. break;
  323. case INTERNET_STATUS_REDIRECT:
  324. //An HTTP request is about to automatically redirect the request.
  325. //The lpvStatusInformation parameter points to the new URL.
  326. //At this point, the application can read any data returned by the server with the
  327. //redirect response, and can query the response headers. It can also cancel the operation
  328. //by closing the handle. This callback is not made if the original request specified
  329. //INTERNET_FLAG_NO_AUTO_REDIRECT.
  330. TRACE_OUT(( TEXT("Redirected to new server") ) );
  331. break;
  332. case INTERNET_STATUS_REQUEST_SENT:
  333. //Successfully sent the information request to the server.
  334. //The lpvStatusInformation parameter points to a DWORD containing the number of bytes sent.
  335. TRACE_OUT(( TEXT("Sent %d bytes in request"), *((DWORD *)lpvStatusInformation) ) );
  336. break;
  337. case INTERNET_STATUS_RESOLVING_NAME:
  338. //Looking up the IP address of the name contained in lpvStatusInformation.
  339. TRACE_OUT(( TEXT("Resolving name") ) );
  340. break;
  341. case INTERNET_STATUS_RESPONSE_RECEIVED:
  342. //Successfully received a response from the server.
  343. //The lpvStatusInformation parameter points to a DWORD containing the number of bytes received.
  344. TRACE_OUT(( TEXT("Recieved %d bytes in response\n"), *((DWORD *)lpvStatusInformation) ) );
  345. break;
  346. case INTERNET_STATUS_SENDING_REQUEST:
  347. //Sending the information request to the server.
  348. //The lpvStatusInformation parameter is NULL.
  349. TRACE_OUT(( TEXT("Sending request") ) );
  350. break;
  351. #endif // DEBUG
  352. default:
  353. break;
  354. }
  355. }
  356. }