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.

667 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. dest.c
  5. Abstract:
  6. Implements the destination side of the home networking transport
  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_DETAILS_PREFIX TEXT("details-")
  26. //
  27. // Constants
  28. //
  29. // None
  30. //
  31. // Macros
  32. //
  33. // None
  34. //
  35. // Types
  36. //
  37. typedef struct {
  38. TCHAR TempFile [MAX_PATH];
  39. PCVOID AllocPtr;
  40. PCVOID DetailsPtr;
  41. HANDLE FileHandle;
  42. HANDLE MapHandle;
  43. } ALLOCSTATE, *PALLOCSTATE;
  44. //
  45. // Globals
  46. //
  47. BOOL g_ConnectionRequested;
  48. //
  49. // Macro expansion list
  50. //
  51. // None
  52. //
  53. // Private function prototypes
  54. //
  55. // none
  56. //
  57. // Macro expansion definition
  58. //
  59. // None
  60. //
  61. // Code
  62. //
  63. BOOL
  64. pHomeNetReadAllImages (
  65. VOID
  66. )
  67. {
  68. PCTSTR imageFile = NULL;
  69. UINT imageIdx = 1;
  70. OCABHANDLE cabHandle;
  71. BOOL result = TRUE;
  72. do {
  73. imageFile = BuildImageFileName (imageIdx);
  74. if (!DoesFileExist (imageFile)) {
  75. FreeImageFileName (imageFile);
  76. break;
  77. }
  78. cabHandle = CabOpenCabinet (imageFile);
  79. if (cabHandle) {
  80. if (!CabExtractAllFiles (cabHandle, g_TransportTempDir)) {
  81. result = FALSE;
  82. }
  83. CabCloseCabinet (cabHandle);
  84. DeleteFile (imageFile);
  85. } else {
  86. result = FALSE;
  87. }
  88. FreeImageFileName (imageFile);
  89. imageIdx ++;
  90. } while (result);
  91. return result;
  92. }
  93. BOOL
  94. pGeneratePassword (
  95. OUT PSTR Key,
  96. IN UINT KeySize
  97. )
  98. {
  99. // no ILOilo0 characters
  100. CHAR validChars[] = "ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz123456789";
  101. DWORD validCharsNr = TcharCountA (validChars);
  102. HCRYPTPROV hProv = 0;
  103. UINT i;
  104. if (!CryptAcquireContext (&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
  105. return FALSE;
  106. }
  107. CryptGenRandom (hProv, KeySize, (LPBYTE)Key);
  108. for (i=0; i<KeySize; i++) {
  109. Key[i] = validChars[Key[i] % validCharsNr];
  110. }
  111. if (hProv) {
  112. CryptReleaseContext (hProv, 0);
  113. hProv = 0;
  114. }
  115. return TRUE;
  116. }
  117. DWORD WINAPI
  118. DisplayPasswordProc (
  119. LPVOID lpParameter // thread data
  120. )
  121. {
  122. PPASSWORD_DATA passwordData;
  123. passwordData = (PPASSWORD_DATA) lpParameter;
  124. IsmSendMessageToApp (TRANSPORTMESSAGE_NET_DISPLAY_PASSWORD, (ULONG_PTR)passwordData);
  125. if (passwordData) {
  126. IsmReleaseMemory (passwordData);
  127. }
  128. ExitThread (0);
  129. }
  130. HANDLE
  131. pDisplayPassword (
  132. IN PCSTR Key,
  133. IN HANDLE Event
  134. )
  135. {
  136. PPASSWORD_DATA passwordData;
  137. DWORD threadId;
  138. passwordData = IsmGetMemory (sizeof (PASSWORD_DATA));
  139. if (!passwordData) {
  140. return NULL;
  141. }
  142. ZeroMemory (passwordData, sizeof (PASSWORD_DATA));
  143. passwordData->Key = (PSTR)Key;
  144. passwordData->KeySize = 0;
  145. passwordData->Event = Event;
  146. return CreateThread (
  147. NULL,
  148. 0,
  149. DisplayPasswordProc,
  150. (LPVOID)(passwordData),
  151. 0,
  152. &threadId
  153. );
  154. }
  155. BOOL
  156. WINAPI
  157. HomeNetTransportBeginApply (
  158. VOID
  159. )
  160. {
  161. ERRUSER_EXTRADATA extraData;
  162. DWORD status = 0;
  163. PCTSTR memDbFile;
  164. BOOL b = FALSE;
  165. DWORD msg;
  166. UINT fileNumber = 0;
  167. LONGLONG numerator;
  168. LONGLONG divisor;
  169. LONGLONG tick;
  170. UINT delta;
  171. HANDLE event = NULL;
  172. HANDLE thread = NULL;
  173. DWORD waitResult;
  174. PBYTE buffer;
  175. g_Platform = PLATFORM_DESTINATION;
  176. ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
  177. extraData.Error = ERRUSER_ERROR_UNKNOWN;
  178. __try {
  179. //
  180. // Download the image
  181. //
  182. if (g_BackgroundThread) {
  183. WaitForSingleObject (g_BackgroundThread, INFINITE);
  184. } else {
  185. g_ConnectionRequested = ConnectToSource (&g_Connection, &g_Metrics);
  186. }
  187. if (!g_ConnectionRequested) {
  188. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
  189. extraData.Error = ERRUSER_ERROR_CANTFINDSOURCE;
  190. __leave;
  191. }
  192. // now we connected to the source. Let's pop up a dialog showing a randomly generated
  193. // password and ask the user to type the password on the source machine.
  194. if (!pGeneratePassword (g_GlobalKey, GLOBALKEY_SIZE)) {
  195. LOG ((LOG_ERROR, (PCSTR) MSG_ENCRYPTION_FAILED));
  196. extraData.Error = ERRUSER_ERROR_NOENCRYPTION;
  197. __leave;
  198. }
  199. event = CreateEvent (NULL, TRUE, FALSE, NULL);
  200. thread = pDisplayPassword (g_GlobalKey, event);
  201. // Let's wait for the first message (should be MESSAGE_PASSWORD);
  202. do {
  203. msg = ReceiveFromSource (&g_Connection, NULL, &buffer, 1000);
  204. if (msg == MESSAGE_DATA) {
  205. if (buffer && StringMatchA (g_GlobalKey, buffer)) {
  206. // This is it, the key is correct
  207. SetEvent (event);
  208. SendMessageToDestination (&g_Connection, MESSAGE_PASSWORDOK);
  209. } else {
  210. msg = 0;
  211. SendMessageToDestination (&g_Connection, MESSAGE_PASSWORDWRONG);
  212. }
  213. if (buffer) {
  214. HeapFree (g_hHeap, 0, buffer);
  215. }
  216. }
  217. if (msg == MESSAGE_CANCEL) {
  218. // The source computer cancelled
  219. SetEvent (event);
  220. }
  221. waitResult = WaitForSingleObject (thread, 0);
  222. } while ((waitResult == WAIT_TIMEOUT) && (msg != MESSAGE_DATA) && (msg != MESSAGE_CANCEL));
  223. if (thread) {
  224. waitResult = WaitForSingleObject (thread, 5000);
  225. if (waitResult == WAIT_TIMEOUT) {
  226. TerminateThread (thread, 0);
  227. }
  228. CloseHandle (thread);
  229. thread = NULL;
  230. }
  231. if (event) {
  232. CloseHandle (event);
  233. event = NULL;
  234. }
  235. if (msg != MESSAGE_DATA) {
  236. // the user cancelled
  237. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
  238. extraData.Error = ERRUSER_ERROR_CANTFINDSOURCE;
  239. __leave;
  240. }
  241. DEBUGMSG ((DBG_HOMENET, "Receiving from source"));
  242. do {
  243. msg = ReceiveFromSource (&g_Connection, g_TransportTempDir, NULL, 0);
  244. if (msg == MESSAGE_FILE) {
  245. //
  246. // Tick the progress bar
  247. //
  248. fileNumber++;
  249. numerator = (LONGLONG) fileNumber * (LONGLONG) g_DownloadSliceSize;
  250. divisor = (LONGLONG) g_Metrics.FileCount;
  251. if (divisor) {
  252. tick = numerator / divisor;
  253. } else {
  254. tick = 0;
  255. }
  256. delta = (UINT) tick - g_DownloadTicks;
  257. if (delta) {
  258. IsmTickProgressBar (g_DownloadSlice, delta);
  259. }
  260. }
  261. } while (msg && msg != MESSAGE_DONE);
  262. if (msg != MESSAGE_DONE) {
  263. if (GetLastError () == ERROR_DISK_FULL) {
  264. // we just failed because we don't have enough space on the destination
  265. // path. Let's tell that to the user
  266. extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
  267. } else {
  268. extraData.Error = ERRUSER_ERROR_CANTRECEIVEFROMSOURCE;
  269. }
  270. PushError ();
  271. LOG ((LOG_ERROR, (PCSTR) MSG_TRANSFER_INCOMPLETE));
  272. CloseConnection (&g_Connection);
  273. PopError ();
  274. __leave;
  275. }
  276. SendMessageToDestination (&g_Connection, MESSAGE_DONE);
  277. DEBUGMSG ((DBG_HOMENET, "Image transfer finished"));
  278. //
  279. // Now process the image
  280. //
  281. status = GetTransportStatus (g_StatusFile, &g_CompressData);
  282. if (status != TRSTATUS_READY) {
  283. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_DOWNLOAD));
  284. extraData.Error = ERRUSER_ERROR_INVALIDDATARECEIVED;
  285. __leave;
  286. }
  287. g_StatusFileHandle = BfOpenFile (g_StatusFile);
  288. if (g_StatusFileHandle == INVALID_HANDLE_VALUE) {
  289. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_STATUS_FILE, g_StatusFile));
  290. extraData.Error = ERRUSER_ERROR_INVALIDDATARECEIVED;
  291. __leave;
  292. }
  293. if (g_CompressData) {
  294. b = pHomeNetReadAllImages ();
  295. } else {
  296. b = TRUE;
  297. }
  298. if (b) {
  299. memDbFile = AllocStorageFileName (S_TRANSPORT_DAT_FILE);
  300. b = MemDbLoad (memDbFile);
  301. FreeStorageFileName (memDbFile);
  302. }
  303. if (!b) {
  304. extraData.Error = ERRUSER_ERROR_CANTREADIMAGE;
  305. }
  306. }
  307. __finally {
  308. }
  309. if (!b) {
  310. PushError ();
  311. extraData.ErrorArea = ERRUSER_AREA_LOAD;
  312. IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
  313. PopError ();
  314. }
  315. return b;
  316. }
  317. VOID
  318. WINAPI
  319. HomeNetTransportEndApply (
  320. VOID
  321. )
  322. {
  323. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  324. CloseConnection (&g_Connection);
  325. }
  326. BOOL
  327. WINAPI
  328. HomeNetTransportAcquireObject (
  329. IN MIG_OBJECTTYPEID ObjectTypeId,
  330. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  331. OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED
  332. IN MIG_CONTENTTYPE ContentType,
  333. IN UINT MemoryContentLimit
  334. )
  335. {
  336. UINT value;
  337. PCBYTE memValue;
  338. UINT memValueSize;
  339. PCTSTR fileValue = NULL;
  340. BOOL valueInFile;
  341. KEYHANDLE keyHandle;
  342. PALLOCSTATE allocState;
  343. PCTSTR detailsKey = NULL;
  344. PBYTE details;
  345. UINT detailsSize;
  346. PCTSTR sourceFile;
  347. PCTSTR decoratedObject = NULL;
  348. HANDLE fileHandle;
  349. BOOL result = FALSE;
  350. if (!ObjectContent) {
  351. return FALSE;
  352. }
  353. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  354. MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
  355. decoratedObject = BuildDecoratedObject (ObjectTypeId, ObjectName);
  356. allocState = (PALLOCSTATE) MemAllocZeroed (sizeof (ALLOCSTATE));
  357. if (MemDbGetValue (decoratedObject, &value)) {
  358. if (value == TRFLAG_FILE) {
  359. valueInFile = TRUE;
  360. keyHandle = MemDbGetSingleLinkage (decoratedObject, 0, 0);
  361. if (keyHandle) {
  362. fileValue = MemDbGetKeyFromHandle (keyHandle, 0);
  363. result = fileValue != NULL;
  364. } else {
  365. fileValue = NULL;
  366. result = TRUE;
  367. }
  368. } else if (value == TRFLAG_MEMORY) {
  369. valueInFile = FALSE;
  370. memValueSize = 0;
  371. memValue = MemDbGetUnorderedBlob (decoratedObject, 0, &memValueSize);
  372. result = TRUE;
  373. } else {
  374. LOG ((LOG_ERROR, (PCSTR) MSG_UNSUPPORTED_DATA, value));
  375. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  376. }
  377. if (result) {
  378. result = FALSE;
  379. if (valueInFile) {
  380. if ((ContentType == CONTENTTYPE_ANY) ||
  381. (ContentType == CONTENTTYPE_FILE) ||
  382. (ContentType == CONTENTTYPE_DETAILS_ONLY)
  383. ) {
  384. // this is stored as a file and it's wanted as a file
  385. ObjectContent->ObjectTypeId = ObjectTypeId;
  386. ObjectContent->ContentInFile = TRUE;
  387. if (fileValue) {
  388. ObjectContent->FileContent.ContentPath = AllocStorageFileName (fileValue);
  389. ObjectContent->FileContent.ContentSize = BfGetFileSize (ObjectContent->FileContent.ContentPath);
  390. } else {
  391. ObjectContent->FileContent.ContentSize = 0;
  392. ObjectContent->FileContent.ContentPath = NULL;
  393. }
  394. result = TRUE;
  395. } else {
  396. // this is stored as a file and it's wanted as memory
  397. ObjectContent->ObjectTypeId = ObjectTypeId;
  398. ObjectContent->ContentInFile = FALSE;
  399. if (fileValue) {
  400. sourceFile = AllocStorageFileName (fileValue);
  401. ObjectContent->MemoryContent.ContentSize = (UINT) BfGetFileSize (sourceFile);
  402. ObjectContent->MemoryContent.ContentBytes = MapFileIntoMemory (
  403. sourceFile,
  404. &allocState->FileHandle,
  405. &allocState->MapHandle
  406. );
  407. FreeStorageFileName (sourceFile);
  408. result = (ObjectContent->MemoryContent.ContentBytes != NULL);
  409. } else {
  410. ObjectContent->MemoryContent.ContentSize = 0;
  411. ObjectContent->MemoryContent.ContentBytes = NULL;
  412. result = TRUE;
  413. }
  414. }
  415. MemDbReleaseMemory (fileValue);
  416. } else {
  417. if ((ContentType == CONTENTTYPE_ANY) ||
  418. (ContentType == CONTENTTYPE_MEMORY) ||
  419. (ContentType == CONTENTTYPE_DETAILS_ONLY)
  420. ) {
  421. // this is stored as memory and it's wanted as memory
  422. ObjectContent->ObjectTypeId = ObjectTypeId;
  423. ObjectContent->ContentInFile = FALSE;
  424. ObjectContent->MemoryContent.ContentSize = memValueSize;
  425. ObjectContent->MemoryContent.ContentBytes = memValue;
  426. result = TRUE;
  427. } else {
  428. // this is stored as memory and it's wanted as a file
  429. if (memValue) {
  430. if (IsmGetTempFile (allocState->TempFile, ARRAYSIZE(allocState->TempFile))) {
  431. fileHandle = BfCreateFile (allocState->TempFile);
  432. if (fileHandle) {
  433. if (BfWriteFile (fileHandle, memValue, memValueSize)) {
  434. ObjectContent->ObjectTypeId = ObjectTypeId;
  435. ObjectContent->ContentInFile = TRUE;
  436. ObjectContent->FileContent.ContentSize = memValueSize;
  437. ObjectContent->FileContent.ContentPath = DuplicatePathString (allocState->TempFile, 0);
  438. result = TRUE;
  439. }
  440. CloseHandle (fileHandle);
  441. }
  442. }
  443. MemDbReleaseMemory (memValue);
  444. } else {
  445. ObjectContent->ObjectTypeId = ObjectTypeId;
  446. ObjectContent->ContentInFile = TRUE;
  447. ObjectContent->FileContent.ContentSize = 0;
  448. ObjectContent->FileContent.ContentPath = NULL;
  449. }
  450. }
  451. }
  452. }
  453. } else {
  454. SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
  455. }
  456. if (result) {
  457. //
  458. // Fill the details
  459. //
  460. detailsKey = JoinText (S_DETAILS_PREFIX, decoratedObject);
  461. details = MemDbGetUnorderedBlob (detailsKey, 0, &detailsSize);
  462. if (!details) {
  463. detailsSize = 0;
  464. }
  465. allocState->DetailsPtr = details;
  466. ObjectContent->Details.DetailsSize = detailsSize;
  467. ObjectContent->Details.DetailsData = details;
  468. FreeText (detailsKey);
  469. ObjectContent->TransHandle = allocState;
  470. }
  471. if (!result) {
  472. FreeAlloc (allocState);
  473. }
  474. DestroyDecoratedObject (decoratedObject);
  475. return result;
  476. }
  477. BOOL
  478. WINAPI
  479. HomeNetTransportReleaseObject (
  480. IN OUT PMIG_CONTENT ObjectContent
  481. )
  482. {
  483. PALLOCSTATE allocState;
  484. MYASSERT (g_Platform == PLATFORM_DESTINATION);
  485. allocState = (PALLOCSTATE) ObjectContent->TransHandle;
  486. if (ObjectContent->ContentInFile) {
  487. FreeStorageFileName (ObjectContent->FileContent.ContentPath);
  488. if (allocState && allocState->TempFile[0]) {
  489. DeleteFile (allocState->TempFile);
  490. }
  491. } else {
  492. if (allocState && allocState->FileHandle && allocState->MapHandle) {
  493. UnmapFile (
  494. ObjectContent->MemoryContent.ContentBytes,
  495. allocState->MapHandle,
  496. allocState->FileHandle
  497. );
  498. } else {
  499. MemDbReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
  500. }
  501. }
  502. if (allocState && allocState->DetailsPtr) {
  503. MemDbReleaseMemory (allocState->DetailsPtr);
  504. }
  505. FreeAlloc (allocState);
  506. return TRUE;
  507. }
  508. DWORD
  509. WINAPI
  510. DestinationBackgroundThread (
  511. PVOID DontCare
  512. )
  513. {
  514. BOOL connect;
  515. ULONG_PTR result;
  516. DEBUGMSG ((DBG_HOMENET, "Destination background thread is running"));
  517. for (;;) {
  518. connect = ConnectToSource (&g_Connection, &g_Metrics);
  519. if (connect) {
  520. DEBUGMSG ((DBG_HOMENET, "Asking app if connection is acceptable"));
  521. result = IsmSendMessageToApp (TRANSPORTMESSAGE_READY_TO_CONNECT, (ULONG_PTR) g_Metrics.SourceName);
  522. if (result == APPRESPONSE_FAIL) {
  523. DEBUGMSG ((DBG_HOMENET, "App says NO!"));
  524. CloseConnection (&g_Connection);
  525. continue;
  526. }
  527. DEBUGMSG ((DBG_HOMENET, "App says YES!"));
  528. }
  529. break;
  530. }
  531. g_ConnectionRequested = connect;
  532. DEBUGMSG ((DBG_HOMENET, "Destination background thread is complete"));
  533. return 0;
  534. }