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.

574 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. Implements functionality common to both the source and destination side
  7. Author:
  8. Jim Schmidt (jimschm) 01-Jul-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include <winsock.h>
  17. #include <wsipx.h>
  18. #include <wsnwlink.h>
  19. #include <wsnetbs.h>
  20. #include "homenetp.h"
  21. #define DBG_HOMENET "HomeNet"
  22. //
  23. // Strings
  24. //
  25. #define S_TRANSPORT_DIR TEXT("USMT2.HN")
  26. #define S_TRANSPORT_STATUS_FILE TEXT("status")
  27. //
  28. // Constants
  29. //
  30. // none
  31. //
  32. // Macros
  33. //
  34. // None
  35. //
  36. // Types
  37. //
  38. // none
  39. //
  40. // Globals
  41. //
  42. MIG_TRANSPORTSTORAGEID g_TransportId;
  43. PCTSTR g_TransportTempDir;
  44. PCTSTR g_StatusFile;
  45. HANDLE g_StatusFileHandle = INVALID_HANDLE_VALUE;
  46. UINT g_Platform;
  47. TRANSFERMETRICS g_Metrics;
  48. CONNECTIONSOCKET g_Connection;
  49. BOOL g_CompressData = FALSE;
  50. MIG_PROGRESSSLICEID g_DatabaseSlice;
  51. MIG_PROGRESSSLICEID g_PersistentSlice;
  52. MIG_PROGRESSSLICEID g_DownloadSlice;
  53. UINT g_DownloadTicks;
  54. UINT g_DownloadSliceSize;
  55. HANDLE g_BackgroundThread;
  56. HANDLE g_BackgroundThreadTerminate;
  57. //
  58. // Macro expansion list
  59. //
  60. // None
  61. //
  62. // Private function prototypes
  63. //
  64. // none
  65. //
  66. // Macro expansion definition
  67. //
  68. // None
  69. //
  70. // Code
  71. //
  72. VOID
  73. pStopBackgroundThread (
  74. VOID
  75. )
  76. {
  77. if (g_BackgroundThread) {
  78. DEBUGMSG ((DBG_HOMENET, "Stopping background thread"));
  79. SetEvent (g_BackgroundThreadTerminate);
  80. WaitForSingleObject (g_BackgroundThread, INFINITE);
  81. CloseHandle (g_BackgroundThread);
  82. CloseHandle (g_BackgroundThreadTerminate);
  83. g_BackgroundThread = NULL;
  84. g_BackgroundThreadTerminate = NULL;
  85. }
  86. }
  87. BOOL
  88. WINAPI
  89. HomeNetTransportInitialize (
  90. IN PMIG_LOGCALLBACK LogCallback
  91. )
  92. {
  93. WSADATA startupData;
  94. INT result;
  95. //
  96. // Initialize globals
  97. //
  98. LogReInit (NULL, NULL, NULL, (PLOGCALLBACK) LogCallback);
  99. //
  100. // Start sockets
  101. //
  102. result = WSAStartup (0x0101, &startupData);
  103. //
  104. // Register transport
  105. //
  106. if (!result) {
  107. g_TransportId = IsmRegisterTransport (S_HOME_NETWORK_TRANSPORT);
  108. return TRUE;
  109. }
  110. return FALSE;
  111. }
  112. BOOL
  113. WINAPI
  114. HomeNetTransportQueryCapabilities (
  115. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  116. OUT PMIG_TRANSPORTTYPE TransportType,
  117. OUT PMIG_TRANSPORTCAPABILITIES Capabilities,
  118. OUT PCTSTR *FriendlyDescription
  119. )
  120. {
  121. if (TransportStorageId != g_TransportId) {
  122. return FALSE;
  123. }
  124. *TransportType = TRANSPORTTYPE_FULL;
  125. *Capabilities = CAPABILITY_COMPRESSED|CAPABILITY_AUTOMATED;
  126. *FriendlyDescription = TEXT("Automatic network transfer");
  127. return TRUE;
  128. }
  129. VOID
  130. WINAPI
  131. HomeNetTransportEstimateProgressBar (
  132. MIG_PLATFORMTYPEID PlatformTypeId
  133. )
  134. {
  135. UINT ticks;
  136. PMIG_OBJECTCOUNT objectCount;
  137. if (PlatformTypeId == PLATFORM_SOURCE) {
  138. //
  139. // If saving, we know the number of ticks based on the count of the
  140. // persistent attribute.
  141. //
  142. objectCount = IsmGetObjectsStatistics (PLATFORM_SOURCE);
  143. if (objectCount) {
  144. ticks = objectCount->PersistentObjects;
  145. } else {
  146. ticks = 0;
  147. }
  148. g_PersistentSlice = IsmRegisterProgressSlice (ticks, max (1, ticks / 5));
  149. ticks = 0;
  150. g_DatabaseSlice = IsmRegisterProgressSlice (ticks, ticks * 3);
  151. } else {
  152. //
  153. // When restoring, we don't know the progress until we connect. We need
  154. // to set up a scale.
  155. //
  156. g_DownloadTicks = 0;
  157. g_DownloadSliceSize = 1000;
  158. g_DownloadSlice = IsmRegisterProgressSlice (g_DownloadSliceSize, 360);
  159. }
  160. }
  161. VOID
  162. pResetTempDir (
  163. VOID
  164. )
  165. {
  166. FreePathString (g_TransportTempDir);
  167. g_TransportTempDir = NULL;
  168. if (g_StatusFileHandle != INVALID_HANDLE_VALUE) {
  169. CloseHandle (g_StatusFileHandle);
  170. g_StatusFileHandle = INVALID_HANDLE_VALUE;
  171. }
  172. FreeStorageFileName (g_StatusFile);
  173. g_StatusFile = NULL;
  174. }
  175. DWORD
  176. GetTransportStatus (
  177. IN PCTSTR TrJournal,
  178. OUT PBOOL Compressed OPTIONAL
  179. )
  180. {
  181. HANDLE trJrnHandle;
  182. BOOL compressed = FALSE;
  183. DWORD signature = 0;
  184. DWORD result = 0;
  185. if (TrJournal && TrJournal [0]) {
  186. trJrnHandle = BfOpenReadFile (TrJournal);
  187. if (trJrnHandle) {
  188. if (BfSetFilePointer (trJrnHandle, 0)) {
  189. if (BfReadFile (trJrnHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  190. if (signature == HOMENETTR_SIG) {
  191. if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
  192. BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
  193. }
  194. }
  195. }
  196. }
  197. CloseHandle (trJrnHandle);
  198. } else {
  199. if (GetLastError () == ERROR_ACCESS_DENIED) {
  200. result = TRSTATUS_LOCKED;
  201. }
  202. }
  203. }
  204. if (Compressed) {
  205. *Compressed = compressed;
  206. }
  207. return result;
  208. }
  209. VOID
  210. WINAPI
  211. HomeNetTransportResetStorage (
  212. IN MIG_TRANSPORTSTORAGEID TransportStorageId
  213. )
  214. {
  215. if (TransportStorageId == g_TransportId) {
  216. DEBUGMSG ((DBG_HOMENET, "Resetting transport"));
  217. pStopBackgroundThread();
  218. if (g_TransportTempDir) {
  219. pResetTempDir();
  220. MYASSERT (!g_TransportTempDir);
  221. }
  222. DEBUGMSG ((DBG_HOMENET, "Reset complete"));
  223. }
  224. }
  225. BOOL
  226. WINAPI
  227. HomeNetTransportSetStorage (
  228. IN MIG_PLATFORMTYPEID Platform,
  229. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  230. IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
  231. IN PCTSTR StoragePath,
  232. OUT PBOOL Valid,
  233. OUT PBOOL ImageExists
  234. )
  235. /*++
  236. Routine Description:
  237. TransportSetStorage tells the transport to be prepared for a future IsmSave
  238. or IsmLoad, and provides the storage path and capabilities. The StoragePath
  239. tells the home networking transport where to save its temporary files
  240. during the transfer. This routine is called when IsmSetTransportStorage is
  241. called.
  242. Arguments:
  243. Platform - Specifies the platform of the transport. This is
  244. potentially different than the current platform.
  245. Also, it is never PLATFORM_CURRENT.
  246. TransportStorageId - Specifies the desired storage ID. For this
  247. transport, it will always be g_TransportId, unless
  248. the caller passes in garbage.
  249. RequiredCapabilities - Specifies two optional flags: CAPABILITY_COMPRESSED
  250. and CAPABILITY_AUTOMATED.
  251. StoragePath - Specifies the path to the temporary directory, or
  252. NULL to use the Windows temporary directory.
  253. Valid - Receives TRUE if the transport storage ID is valid
  254. and was selected, FALSE otherwise. NOTE: this is not
  255. an optional parameter.
  256. ImageExists - Receives TRUE if the platform is PLATFORM_DESTINATION,
  257. FALSE if the platform is PLATFORM_SOURCE. The value is
  258. undefined if Valid is FALSE.
  259. Return Value:
  260. TRUE if the transport is ready for IsmSave or IsmLoad, FALSE otherwise.
  261. --*/
  262. {
  263. PCTSTR transportPath = NULL;
  264. MIG_OBJECTSTRINGHANDLE encodedPath;
  265. BOOL result = FALSE;
  266. DWORD attribs;
  267. TCHAR tempDir[MAX_TCHAR_PATH];
  268. BOOL startAutoDest = FALSE;
  269. CONNECTADDRESS connectAddress;
  270. BOOL capabilitiesValid = TRUE;
  271. if (!Valid || !ImageExists) {
  272. DEBUGMSG ((DBG_ERROR, "TransportSetStorage requires Valid and ImageExists params"));
  273. return FALSE;
  274. }
  275. *Valid = FALSE;
  276. *ImageExists = FALSE;
  277. if (TransportStorageId == g_TransportId) {
  278. //
  279. // Make sure we support the requested capabilities
  280. //
  281. if (RequiredCapabilities & (~(CAPABILITY_AUTOMATED|CAPABILITY_COMPRESSED))) {
  282. capabilitiesValid = FALSE;
  283. } else {
  284. DEBUGMSG ((DBG_HOMENET, "Accepting a TransportSetStorage request (capabilities: 0%Xh)", RequiredCapabilities));
  285. }
  286. if (capabilitiesValid) {
  287. //
  288. // Validate the inbound args, update the globals
  289. //
  290. if (RequiredCapabilities & CAPABILITY_COMPRESSED) {
  291. g_CompressData = TRUE;
  292. } else {
  293. g_CompressData = FALSE;
  294. }
  295. if (!StoragePath) {
  296. IsmGetTempStorage (tempDir, ARRAYSIZE(tempDir));
  297. StoragePath = tempDir;
  298. }
  299. MYASSERT (!g_TransportTempDir);
  300. //
  301. // Compute the transport storage directory, then make sure it is empty.
  302. // If Storage is NULL, then the storage directory is %temp%\usmtv2.hn
  303. //
  304. transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
  305. attribs = GetFileAttributes (transportPath);
  306. if (attribs != INVALID_ATTRIBUTES) {
  307. SetFileAttributes (transportPath, FILE_ATTRIBUTE_NORMAL);
  308. DeleteFile (transportPath);
  309. FiRemoveAllFilesInTree (transportPath);
  310. }
  311. //
  312. // Now esablish the temporary directory and put a status file in it
  313. // for restartability
  314. //
  315. attribs = GetFileAttributes (transportPath);
  316. if (attribs == INVALID_ATTRIBUTES) {
  317. if (BfCreateDirectory (transportPath)) {
  318. *Valid = TRUE;
  319. //
  320. // it exists on the destination because we are going to download it;
  321. // it does not exist on the source because we always overwrite it
  322. //
  323. *ImageExists = (Platform == PLATFORM_DESTINATION);
  324. g_TransportTempDir = DuplicatePathString (transportPath, 0);
  325. g_StatusFile = AllocStorageFileName (S_TRANSPORT_STATUS_FILE);
  326. encodedPath = IsmCreateSimpleObjectPattern (g_TransportTempDir, FALSE, NULL, FALSE);
  327. if (encodedPath) {
  328. IsmRegisterStaticExclusion (MIG_FILE_TYPE, encodedPath);
  329. IsmDestroyObjectHandle (encodedPath);
  330. }
  331. }
  332. } else {
  333. *ImageExists = TRUE;
  334. }
  335. //
  336. // If CAPABILITY_AUTOMATED, start the process of looking for a connection now
  337. //
  338. if (*Valid && (RequiredCapabilities & CAPABILITY_AUTOMATED)) {
  339. if (Platform == PLATFORM_SOURCE) {
  340. //
  341. // Check for a destination
  342. //
  343. DEBUGMSG ((DBG_HOMENET, "Looking for destination broadcasts"));
  344. *ImageExists = FindDestination (&connectAddress, 5, TRUE);
  345. if (*ImageExists) {
  346. *ImageExists = TestConnection (&connectAddress);
  347. }
  348. } else {
  349. //
  350. // Launch background thread
  351. //
  352. DEBUGMSG ((DBG_HOMENET, "Launching background broadcast thread"));
  353. if (!g_BackgroundThread) {
  354. g_BackgroundThreadTerminate = CreateEvent (NULL, TRUE, FALSE, NULL);
  355. g_BackgroundThread = StartThread (DestinationBackgroundThread, 0);
  356. }
  357. }
  358. }
  359. result = TRUE;
  360. }
  361. }
  362. FreePathString (transportPath);
  363. return result;
  364. }
  365. VOID
  366. WINAPI
  367. HomeNetTransportTerminate (
  368. VOID
  369. )
  370. {
  371. pStopBackgroundThread();
  372. //
  373. // Shut down sockets
  374. //
  375. WSACleanup();
  376. //
  377. // Clean up utils
  378. //
  379. if (g_TransportTempDir) {
  380. FiRemoveAllFilesInTree (g_TransportTempDir);
  381. pResetTempDir();
  382. }
  383. }
  384. PCTSTR
  385. BuildDecoratedObject (
  386. IN MIG_OBJECTTYPEID ObjectTypeId,
  387. IN ENCODEDSTRHANDLE ObjectName
  388. )
  389. {
  390. TCHAR prefix[32];
  391. wsprintf (prefix, TEXT("%u"), ObjectTypeId);
  392. return JoinPaths (prefix, ObjectName);
  393. }
  394. VOID
  395. DestroyDecoratedObject (
  396. IN PCTSTR String
  397. )
  398. {
  399. FreePathString (String);
  400. }
  401. PCTSTR
  402. AllocStorageFileName (
  403. IN PCTSTR FileName OPTIONAL
  404. )
  405. {
  406. TCHAR buffer[32];
  407. static UINT sequencer = 0;
  408. if (FileName) {
  409. return JoinPaths (g_TransportTempDir, FileName);
  410. }
  411. sequencer++;
  412. wsprintf (buffer, TEXT("%08X.DAT"), sequencer);
  413. return JoinPaths (g_TransportTempDir, buffer);
  414. }
  415. VOID
  416. FreeStorageFileName (
  417. IN PCTSTR NameToFree
  418. )
  419. {
  420. FreePathString (NameToFree);
  421. }
  422. PCTSTR
  423. BuildImageFileName (
  424. IN UINT ImageIdx
  425. )
  426. {
  427. TCHAR imageFileName [13];
  428. PCTSTR imageFile = NULL;
  429. HANDLE imageFileHandle = NULL;
  430. wsprintf (imageFileName, S_TRANSPORT_IMG_FILE, ImageIdx);
  431. return JoinPaths (g_TransportTempDir, imageFileName);
  432. }
  433. VOID
  434. FreeImageFileName (
  435. IN PCTSTR ImageFileName
  436. )
  437. {
  438. FreePathString (ImageFileName);
  439. }