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.

581 lines
14 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 error;
  185. DWORD result = 0;
  186. if (TrJournal && TrJournal [0]) {
  187. trJrnHandle = BfOpenReadFile (TrJournal);
  188. if (trJrnHandle) {
  189. if (BfSetFilePointer (trJrnHandle, 0)) {
  190. if (BfReadFile (trJrnHandle, (PBYTE)(&signature), sizeof (DWORD))) {
  191. if (signature == HOMENETTR_SIG) {
  192. if (BfReadFile (trJrnHandle, (PBYTE)(&compressed), sizeof (BOOL))) {
  193. BfReadFile (trJrnHandle, (PBYTE)(&result), sizeof (DWORD));
  194. }
  195. }
  196. }
  197. }
  198. CloseHandle (trJrnHandle);
  199. } else {
  200. error = GetLastError ();
  201. if ((error == ERROR_ACCESS_DENIED) ||
  202. (error == ERROR_SHARING_VIOLATION)
  203. ) {
  204. result = TRSTATUS_LOCKED;
  205. }
  206. }
  207. }
  208. if (Compressed) {
  209. *Compressed = compressed;
  210. }
  211. return result;
  212. }
  213. VOID
  214. WINAPI
  215. HomeNetTransportResetStorage (
  216. IN MIG_TRANSPORTSTORAGEID TransportStorageId
  217. )
  218. {
  219. if (TransportStorageId == g_TransportId) {
  220. DEBUGMSG ((DBG_HOMENET, "Resetting transport"));
  221. pStopBackgroundThread();
  222. if (g_TransportTempDir) {
  223. pResetTempDir();
  224. MYASSERT (!g_TransportTempDir);
  225. }
  226. DEBUGMSG ((DBG_HOMENET, "Reset complete"));
  227. }
  228. }
  229. BOOL
  230. WINAPI
  231. HomeNetTransportSetStorage (
  232. IN MIG_PLATFORMTYPEID Platform,
  233. IN MIG_TRANSPORTSTORAGEID TransportStorageId,
  234. IN MIG_TRANSPORTCAPABILITIES RequiredCapabilities,
  235. IN PCTSTR StoragePath,
  236. OUT PBOOL Valid,
  237. OUT PBOOL ImageExists
  238. )
  239. /*++
  240. Routine Description:
  241. TransportSetStorage tells the transport to be prepared for a future IsmSave
  242. or IsmLoad, and provides the storage path and capabilities. The StoragePath
  243. tells the home networking transport where to save its temporary files
  244. during the transfer. This routine is called when IsmSetTransportStorage is
  245. called.
  246. Arguments:
  247. Platform - Specifies the platform of the transport. This is
  248. potentially different than the current platform.
  249. Also, it is never PLATFORM_CURRENT.
  250. TransportStorageId - Specifies the desired storage ID. For this
  251. transport, it will always be g_TransportId, unless
  252. the caller passes in garbage.
  253. RequiredCapabilities - Specifies two optional flags: CAPABILITY_COMPRESSED
  254. and CAPABILITY_AUTOMATED.
  255. StoragePath - Specifies the path to the temporary directory, or
  256. NULL to use the Windows temporary directory.
  257. Valid - Receives TRUE if the transport storage ID is valid
  258. and was selected, FALSE otherwise. NOTE: this is not
  259. an optional parameter.
  260. ImageExists - Receives TRUE if the platform is PLATFORM_DESTINATION,
  261. FALSE if the platform is PLATFORM_SOURCE. The value is
  262. undefined if Valid is FALSE.
  263. Return Value:
  264. TRUE if the transport is ready for IsmSave or IsmLoad, FALSE otherwise.
  265. --*/
  266. {
  267. PCTSTR transportPath = NULL;
  268. MIG_OBJECTSTRINGHANDLE encodedPath;
  269. BOOL result = FALSE;
  270. DWORD attribs;
  271. TCHAR tempDir[MAX_TCHAR_PATH];
  272. BOOL startAutoDest = FALSE;
  273. CONNECTADDRESS connectAddress;
  274. BOOL capabilitiesValid = TRUE;
  275. if (!Valid || !ImageExists) {
  276. DEBUGMSG ((DBG_ERROR, "TransportSetStorage requires Valid and ImageExists params"));
  277. return FALSE;
  278. }
  279. *Valid = FALSE;
  280. *ImageExists = FALSE;
  281. if (TransportStorageId == g_TransportId) {
  282. //
  283. // Make sure we support the requested capabilities
  284. //
  285. if (RequiredCapabilities & (~(CAPABILITY_AUTOMATED|CAPABILITY_COMPRESSED))) {
  286. capabilitiesValid = FALSE;
  287. } else {
  288. DEBUGMSG ((DBG_HOMENET, "Accepting a TransportSetStorage request (capabilities: 0%Xh)", RequiredCapabilities));
  289. }
  290. if (capabilitiesValid) {
  291. //
  292. // Validate the inbound args, update the globals
  293. //
  294. if (RequiredCapabilities & CAPABILITY_COMPRESSED) {
  295. g_CompressData = TRUE;
  296. } else {
  297. g_CompressData = FALSE;
  298. }
  299. if (!StoragePath) {
  300. IsmGetTempStorage (tempDir, ARRAYSIZE(tempDir));
  301. StoragePath = tempDir;
  302. }
  303. MYASSERT (!g_TransportTempDir);
  304. //
  305. // Compute the transport storage directory, then make sure it is empty.
  306. // If Storage is NULL, then the storage directory is %temp%\usmtv2.hn
  307. //
  308. transportPath = JoinPaths (StoragePath, S_TRANSPORT_DIR);
  309. attribs = GetFileAttributes (transportPath);
  310. if (attribs != INVALID_ATTRIBUTES) {
  311. SetFileAttributes (transportPath, FILE_ATTRIBUTE_NORMAL);
  312. DeleteFile (transportPath);
  313. FiRemoveAllFilesInTree (transportPath);
  314. }
  315. //
  316. // Now esablish the temporary directory and put a status file in it
  317. // for restartability
  318. //
  319. attribs = GetFileAttributes (transportPath);
  320. if (attribs == INVALID_ATTRIBUTES) {
  321. if (BfCreateDirectory (transportPath)) {
  322. *Valid = TRUE;
  323. //
  324. // it exists on the destination because we are going to download it;
  325. // it does not exist on the source because we always overwrite it
  326. //
  327. *ImageExists = (Platform == PLATFORM_DESTINATION);
  328. g_TransportTempDir = DuplicatePathString (transportPath, 0);
  329. g_StatusFile = AllocStorageFileName (S_TRANSPORT_STATUS_FILE);
  330. encodedPath = IsmCreateSimpleObjectPattern (g_TransportTempDir, FALSE, NULL, FALSE);
  331. if (encodedPath) {
  332. IsmRegisterStaticExclusion (MIG_FILE_TYPE, encodedPath);
  333. IsmDestroyObjectHandle (encodedPath);
  334. }
  335. }
  336. } else {
  337. *ImageExists = TRUE;
  338. }
  339. //
  340. // If CAPABILITY_AUTOMATED, start the process of looking for a connection now
  341. //
  342. if (*Valid && (RequiredCapabilities & CAPABILITY_AUTOMATED)) {
  343. if (Platform == PLATFORM_SOURCE) {
  344. //
  345. // Check for a destination
  346. //
  347. DEBUGMSG ((DBG_HOMENET, "Looking for destination broadcasts"));
  348. *ImageExists = FindDestination (&connectAddress, 5, TRUE);
  349. if (*ImageExists) {
  350. *ImageExists = TestConnection (&connectAddress);
  351. }
  352. } else {
  353. //
  354. // Launch background thread
  355. //
  356. DEBUGMSG ((DBG_HOMENET, "Launching background broadcast thread"));
  357. if (!g_BackgroundThread) {
  358. g_BackgroundThreadTerminate = CreateEvent (NULL, TRUE, FALSE, NULL);
  359. g_BackgroundThread = StartThread (DestinationBackgroundThread, 0);
  360. }
  361. }
  362. }
  363. result = TRUE;
  364. }
  365. }
  366. FreePathString (transportPath);
  367. return result;
  368. }
  369. VOID
  370. WINAPI
  371. HomeNetTransportTerminate (
  372. VOID
  373. )
  374. {
  375. pStopBackgroundThread();
  376. //
  377. // Shut down sockets
  378. //
  379. WSACleanup();
  380. //
  381. // Clean up utils
  382. //
  383. if (g_TransportTempDir) {
  384. FiRemoveAllFilesInTree (g_TransportTempDir);
  385. pResetTempDir();
  386. }
  387. }
  388. PCTSTR
  389. BuildDecoratedObject (
  390. IN MIG_OBJECTTYPEID ObjectTypeId,
  391. IN ENCODEDSTRHANDLE ObjectName
  392. )
  393. {
  394. PCTSTR typeStr;
  395. typeStr = IsmGetObjectTypeName (ObjectTypeId);
  396. if (!typeStr) {
  397. return NULL;
  398. }
  399. return JoinPaths (typeStr, ObjectName);
  400. }
  401. VOID
  402. DestroyDecoratedObject (
  403. IN PCTSTR String
  404. )
  405. {
  406. FreePathString (String);
  407. }
  408. PCTSTR
  409. AllocStorageFileName (
  410. IN PCTSTR FileName OPTIONAL
  411. )
  412. {
  413. TCHAR buffer[32];
  414. static UINT sequencer = 0;
  415. if (FileName) {
  416. return JoinPaths (g_TransportTempDir, FileName);
  417. }
  418. sequencer++;
  419. wsprintf (buffer, TEXT("%08X.DAT"), sequencer);
  420. return JoinPaths (g_TransportTempDir, buffer);
  421. }
  422. VOID
  423. FreeStorageFileName (
  424. IN PCTSTR NameToFree
  425. )
  426. {
  427. FreePathString (NameToFree);
  428. }
  429. PCTSTR
  430. BuildImageFileName (
  431. IN UINT ImageIdx
  432. )
  433. {
  434. TCHAR imageFileName [13];
  435. PCTSTR imageFile = NULL;
  436. HANDLE imageFileHandle = NULL;
  437. wsprintf (imageFileName, S_TRANSPORT_IMG_FILE, ImageIdx);
  438. return JoinPaths (g_TransportTempDir, imageFileName);
  439. }
  440. VOID
  441. FreeImageFileName (
  442. IN PCTSTR ImageFileName
  443. )
  444. {
  445. FreePathString (ImageFileName);
  446. }