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.
 
 
 
 
 
 

667 lines
18 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
dest.c
Abstract:
Implements the destination side of the home networking transport
Author:
Jim Schmidt (jimschm) 01-Jul-2000
Revision History:
<alias> <date> <comments>
--*/
//
// Includes
//
#include "pch.h"
#include <winsock.h>
#include <wsipx.h>
#include <wsnwlink.h>
#include <wsnetbs.h>
#include "homenetp.h"
#define DBG_HOMENET "HomeNet"
//
// Strings
//
#define S_DETAILS_PREFIX TEXT("details-")
//
// Constants
//
// None
//
// Macros
//
// None
//
// Types
//
typedef struct {
TCHAR TempFile [MAX_PATH];
PCVOID AllocPtr;
PCVOID DetailsPtr;
HANDLE FileHandle;
HANDLE MapHandle;
} ALLOCSTATE, *PALLOCSTATE;
//
// Globals
//
BOOL g_ConnectionRequested;
//
// Macro expansion list
//
// None
//
// Private function prototypes
//
// none
//
// Macro expansion definition
//
// None
//
// Code
//
BOOL
pHomeNetReadAllImages (
VOID
)
{
PCTSTR imageFile = NULL;
UINT imageIdx = 1;
OCABHANDLE cabHandle;
BOOL result = TRUE;
do {
imageFile = BuildImageFileName (imageIdx);
if (!DoesFileExist (imageFile)) {
FreeImageFileName (imageFile);
break;
}
cabHandle = CabOpenCabinet (imageFile);
if (cabHandle) {
if (!CabExtractAllFiles (cabHandle, g_TransportTempDir)) {
result = FALSE;
}
CabCloseCabinet (cabHandle);
DeleteFile (imageFile);
} else {
result = FALSE;
}
FreeImageFileName (imageFile);
imageIdx ++;
} while (result);
return result;
}
BOOL
pGeneratePassword (
OUT PSTR Key,
IN UINT KeySize
)
{
// no ILOilo0 characters
CHAR validChars[] = "ABCDEFGHJKMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz123456789";
DWORD validCharsNr = TcharCountA (validChars);
HCRYPTPROV hProv = 0;
UINT i;
if (!CryptAcquireContext (&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
return FALSE;
}
CryptGenRandom (hProv, KeySize, (LPBYTE)Key);
for (i=0; i<KeySize; i++) {
Key[i] = validChars[Key[i] % validCharsNr];
}
if (hProv) {
CryptReleaseContext (hProv, 0);
hProv = 0;
}
return TRUE;
}
DWORD WINAPI
DisplayPasswordProc (
LPVOID lpParameter // thread data
)
{
PPASSWORD_DATA passwordData;
passwordData = (PPASSWORD_DATA) lpParameter;
IsmSendMessageToApp (TRANSPORTMESSAGE_NET_DISPLAY_PASSWORD, (ULONG_PTR)passwordData);
if (passwordData) {
IsmReleaseMemory (passwordData);
}
ExitThread (0);
}
HANDLE
pDisplayPassword (
IN PCSTR Key,
IN HANDLE Event
)
{
PPASSWORD_DATA passwordData;
DWORD threadId;
passwordData = IsmGetMemory (sizeof (PASSWORD_DATA));
if (!passwordData) {
return NULL;
}
ZeroMemory (passwordData, sizeof (PASSWORD_DATA));
passwordData->Key = (PSTR)Key;
passwordData->KeySize = 0;
passwordData->Event = Event;
return CreateThread (
NULL,
0,
DisplayPasswordProc,
(LPVOID)(passwordData),
0,
&threadId
);
}
BOOL
WINAPI
HomeNetTransportBeginApply (
VOID
)
{
ERRUSER_EXTRADATA extraData;
DWORD status = 0;
PCTSTR memDbFile;
BOOL b = FALSE;
DWORD msg;
UINT fileNumber = 0;
LONGLONG numerator;
LONGLONG divisor;
LONGLONG tick;
UINT delta;
HANDLE event = NULL;
HANDLE thread = NULL;
DWORD waitResult;
PBYTE buffer;
g_Platform = PLATFORM_DESTINATION;
ZeroMemory (&extraData, sizeof (ERRUSER_EXTRADATA));
extraData.Error = ERRUSER_ERROR_UNKNOWN;
__try {
//
// Download the image
//
if (g_BackgroundThread) {
WaitForSingleObject (g_BackgroundThread, INFINITE);
} else {
g_ConnectionRequested = ConnectToSource (&g_Connection, &g_Metrics);
}
if (!g_ConnectionRequested) {
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
extraData.Error = ERRUSER_ERROR_CANTFINDSOURCE;
__leave;
}
// now we connected to the source. Let's pop up a dialog showing a randomly generated
// password and ask the user to type the password on the source machine.
if (!pGeneratePassword (g_GlobalKey, GLOBALKEY_SIZE)) {
LOG ((LOG_ERROR, (PCSTR) MSG_ENCRYPTION_FAILED));
extraData.Error = ERRUSER_ERROR_NOENCRYPTION;
__leave;
}
event = CreateEvent (NULL, TRUE, FALSE, NULL);
thread = pDisplayPassword (g_GlobalKey, event);
// Let's wait for the first message (should be MESSAGE_PASSWORD);
do {
msg = ReceiveFromSource (&g_Connection, NULL, &buffer, 1000);
if (msg == MESSAGE_DATA) {
if (buffer && StringMatchA (g_GlobalKey, buffer)) {
// This is it, the key is correct
SetEvent (event);
SendMessageToDestination (&g_Connection, MESSAGE_PASSWORDOK);
} else {
msg = 0;
SendMessageToDestination (&g_Connection, MESSAGE_PASSWORDWRONG);
}
if (buffer) {
HeapFree (g_hHeap, 0, buffer);
}
}
if (msg == MESSAGE_CANCEL) {
// The source computer cancelled
SetEvent (event);
}
waitResult = WaitForSingleObject (thread, 0);
} while ((waitResult == WAIT_TIMEOUT) && (msg != MESSAGE_DATA) && (msg != MESSAGE_CANCEL));
if (thread) {
waitResult = WaitForSingleObject (thread, 5000);
if (waitResult == WAIT_TIMEOUT) {
TerminateThread (thread, 0);
}
CloseHandle (thread);
thread = NULL;
}
if (event) {
CloseHandle (event);
event = NULL;
}
if (msg != MESSAGE_DATA) {
// the user cancelled
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_CONNECT_TO_SOURCE));
extraData.Error = ERRUSER_ERROR_CANTFINDSOURCE;
__leave;
}
DEBUGMSG ((DBG_HOMENET, "Receiving from source"));
do {
msg = ReceiveFromSource (&g_Connection, g_TransportTempDir, NULL, 0);
if (msg == MESSAGE_FILE) {
//
// Tick the progress bar
//
fileNumber++;
numerator = (LONGLONG) fileNumber * (LONGLONG) g_DownloadSliceSize;
divisor = (LONGLONG) g_Metrics.FileCount;
if (divisor) {
tick = numerator / divisor;
} else {
tick = 0;
}
delta = (UINT) tick - g_DownloadTicks;
if (delta) {
IsmTickProgressBar (g_DownloadSlice, delta);
}
}
} while (msg && msg != MESSAGE_DONE);
if (msg != MESSAGE_DONE) {
if (GetLastError () == ERROR_DISK_FULL) {
// we just failed because we don't have enough space on the destination
// path. Let's tell that to the user
extraData.Error = ERRUSER_ERROR_CANTCREATECABFILE;
} else {
extraData.Error = ERRUSER_ERROR_CANTRECEIVEFROMSOURCE;
}
PushError ();
LOG ((LOG_ERROR, (PCSTR) MSG_TRANSFER_INCOMPLETE));
CloseConnection (&g_Connection);
PopError ();
__leave;
}
SendMessageToDestination (&g_Connection, MESSAGE_DONE);
DEBUGMSG ((DBG_HOMENET, "Image transfer finished"));
//
// Now process the image
//
status = GetTransportStatus (g_StatusFile, &g_CompressData);
if (status != TRSTATUS_READY) {
LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_DOWNLOAD));
extraData.Error = ERRUSER_ERROR_INVALIDDATARECEIVED;
__leave;
}
g_StatusFileHandle = BfOpenFile (g_StatusFile);
if (g_StatusFileHandle == INVALID_HANDLE_VALUE) {
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_STATUS_FILE, g_StatusFile));
extraData.Error = ERRUSER_ERROR_INVALIDDATARECEIVED;
__leave;
}
if (g_CompressData) {
b = pHomeNetReadAllImages ();
} else {
b = TRUE;
}
if (b) {
memDbFile = AllocStorageFileName (S_TRANSPORT_DAT_FILE);
b = MemDbLoad (memDbFile);
FreeStorageFileName (memDbFile);
}
if (!b) {
extraData.Error = ERRUSER_ERROR_CANTREADIMAGE;
}
}
__finally {
}
if (!b) {
PushError ();
extraData.ErrorArea = ERRUSER_AREA_LOAD;
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
PopError ();
}
return b;
}
VOID
WINAPI
HomeNetTransportEndApply (
VOID
)
{
MYASSERT (g_Platform == PLATFORM_DESTINATION);
CloseConnection (&g_Connection);
}
BOOL
WINAPI
HomeNetTransportAcquireObject (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN MIG_OBJECTSTRINGHANDLE ObjectName,
OUT PMIG_CONTENT ObjectContent, CALLER_INITIALIZED
IN MIG_CONTENTTYPE ContentType,
IN UINT MemoryContentLimit
)
{
UINT value;
PCBYTE memValue;
UINT memValueSize;
PCTSTR fileValue = NULL;
BOOL valueInFile;
KEYHANDLE keyHandle;
PALLOCSTATE allocState;
PCTSTR detailsKey = NULL;
PBYTE details;
UINT detailsSize;
PCTSTR sourceFile;
PCTSTR decoratedObject = NULL;
HANDLE fileHandle;
BOOL result = FALSE;
if (!ObjectContent) {
return FALSE;
}
MYASSERT (g_Platform == PLATFORM_DESTINATION);
MYASSERT ((ObjectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE);
decoratedObject = BuildDecoratedObject (ObjectTypeId, ObjectName);
allocState = (PALLOCSTATE) MemAllocZeroed (sizeof (ALLOCSTATE));
if (MemDbGetValue (decoratedObject, &value)) {
if (value == TRFLAG_FILE) {
valueInFile = TRUE;
keyHandle = MemDbGetSingleLinkage (decoratedObject, 0, 0);
if (keyHandle) {
fileValue = MemDbGetKeyFromHandle (keyHandle, 0);
result = fileValue != NULL;
} else {
fileValue = NULL;
result = TRUE;
}
} else if (value == TRFLAG_MEMORY) {
valueInFile = FALSE;
memValueSize = 0;
memValue = MemDbGetUnorderedBlob (decoratedObject, 0, &memValueSize);
result = TRUE;
} else {
LOG ((LOG_ERROR, (PCSTR) MSG_UNSUPPORTED_DATA, value));
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
}
if (result) {
result = FALSE;
if (valueInFile) {
if ((ContentType == CONTENTTYPE_ANY) ||
(ContentType == CONTENTTYPE_FILE) ||
(ContentType == CONTENTTYPE_DETAILS_ONLY)
) {
// this is stored as a file and it's wanted as a file
ObjectContent->ObjectTypeId = ObjectTypeId;
ObjectContent->ContentInFile = TRUE;
if (fileValue) {
ObjectContent->FileContent.ContentPath = AllocStorageFileName (fileValue);
ObjectContent->FileContent.ContentSize = BfGetFileSize (ObjectContent->FileContent.ContentPath);
} else {
ObjectContent->FileContent.ContentSize = 0;
ObjectContent->FileContent.ContentPath = NULL;
}
result = TRUE;
} else {
// this is stored as a file and it's wanted as memory
ObjectContent->ObjectTypeId = ObjectTypeId;
ObjectContent->ContentInFile = FALSE;
if (fileValue) {
sourceFile = AllocStorageFileName (fileValue);
ObjectContent->MemoryContent.ContentSize = (UINT) BfGetFileSize (sourceFile);
ObjectContent->MemoryContent.ContentBytes = MapFileIntoMemory (
sourceFile,
&allocState->FileHandle,
&allocState->MapHandle
);
FreeStorageFileName (sourceFile);
result = (ObjectContent->MemoryContent.ContentBytes != NULL);
} else {
ObjectContent->MemoryContent.ContentSize = 0;
ObjectContent->MemoryContent.ContentBytes = NULL;
result = TRUE;
}
}
MemDbReleaseMemory (fileValue);
} else {
if ((ContentType == CONTENTTYPE_ANY) ||
(ContentType == CONTENTTYPE_MEMORY) ||
(ContentType == CONTENTTYPE_DETAILS_ONLY)
) {
// this is stored as memory and it's wanted as memory
ObjectContent->ObjectTypeId = ObjectTypeId;
ObjectContent->ContentInFile = FALSE;
ObjectContent->MemoryContent.ContentSize = memValueSize;
ObjectContent->MemoryContent.ContentBytes = memValue;
result = TRUE;
} else {
// this is stored as memory and it's wanted as a file
if (memValue) {
if (IsmGetTempFile (allocState->TempFile, ARRAYSIZE(allocState->TempFile))) {
fileHandle = BfCreateFile (allocState->TempFile);
if (fileHandle) {
if (BfWriteFile (fileHandle, memValue, memValueSize)) {
ObjectContent->ObjectTypeId = ObjectTypeId;
ObjectContent->ContentInFile = TRUE;
ObjectContent->FileContent.ContentSize = memValueSize;
ObjectContent->FileContent.ContentPath = DuplicatePathString (allocState->TempFile, 0);
result = TRUE;
}
CloseHandle (fileHandle);
}
}
MemDbReleaseMemory (memValue);
} else {
ObjectContent->ObjectTypeId = ObjectTypeId;
ObjectContent->ContentInFile = TRUE;
ObjectContent->FileContent.ContentSize = 0;
ObjectContent->FileContent.ContentPath = NULL;
}
}
}
}
} else {
SetLastError (ERROR_RESOURCE_NAME_NOT_FOUND);
}
if (result) {
//
// Fill the details
//
detailsKey = JoinText (S_DETAILS_PREFIX, decoratedObject);
details = MemDbGetUnorderedBlob (detailsKey, 0, &detailsSize);
if (!details) {
detailsSize = 0;
}
allocState->DetailsPtr = details;
ObjectContent->Details.DetailsSize = detailsSize;
ObjectContent->Details.DetailsData = details;
FreeText (detailsKey);
ObjectContent->TransHandle = allocState;
}
if (!result) {
FreeAlloc (allocState);
}
DestroyDecoratedObject (decoratedObject);
return result;
}
BOOL
WINAPI
HomeNetTransportReleaseObject (
IN OUT PMIG_CONTENT ObjectContent
)
{
PALLOCSTATE allocState;
MYASSERT (g_Platform == PLATFORM_DESTINATION);
allocState = (PALLOCSTATE) ObjectContent->TransHandle;
if (ObjectContent->ContentInFile) {
FreeStorageFileName (ObjectContent->FileContent.ContentPath);
if (allocState && allocState->TempFile[0]) {
DeleteFile (allocState->TempFile);
}
} else {
if (allocState && allocState->FileHandle && allocState->MapHandle) {
UnmapFile (
ObjectContent->MemoryContent.ContentBytes,
allocState->MapHandle,
allocState->FileHandle
);
} else {
MemDbReleaseMemory (ObjectContent->MemoryContent.ContentBytes);
}
}
if (allocState && allocState->DetailsPtr) {
MemDbReleaseMemory (allocState->DetailsPtr);
}
FreeAlloc (allocState);
return TRUE;
}
DWORD
WINAPI
DestinationBackgroundThread (
PVOID DontCare
)
{
BOOL connect;
ULONG_PTR result;
DEBUGMSG ((DBG_HOMENET, "Destination background thread is running"));
for (;;) {
connect = ConnectToSource (&g_Connection, &g_Metrics);
if (connect) {
DEBUGMSG ((DBG_HOMENET, "Asking app if connection is acceptable"));
result = IsmSendMessageToApp (TRANSPORTMESSAGE_READY_TO_CONNECT, (ULONG_PTR) g_Metrics.SourceName);
if (result == APPRESPONSE_FAIL) {
DEBUGMSG ((DBG_HOMENET, "App says NO!"));
CloseConnection (&g_Connection);
continue;
}
DEBUGMSG ((DBG_HOMENET, "App says YES!"));
}
break;
}
g_ConnectionRequested = connect;
DEBUGMSG ((DBG_HOMENET, "Destination background thread is complete"));
return 0;
}