2025-11-28 00:35:46 +09:00

1025 lines
28 KiB
C++

//////////////////////////////////////////////////////////////////////////////
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <conio.h>
#include "SecureClient.h"
#include <strsafe.h>
//////////////////////////////////////////////////////////////////////////////
// print_result - Display HRESULTs
//////////////////////////////////////////////////////////////////////////////
void print_result(HRESULT hr)
{
if( S_OK == hr )
{
_cwprintf(L"[S_OK]\r\n");
}
else if( S_FALSE == hr )
{
_cwprintf(L"[S_FALSE]\r\n");
}
else
{
_cwprintf(L"[ERROR: %x]\r\n", hr);
}
}
//////////////////////////////////////////////////////////////////////////////
// CFileServiceSecureEventNotify methods
//////////////////////////////////////////////////////////////////////////////
CFileServiceSecureEventNotify::CFileServiceSecureEventNotify()
: m_cRef(1)
{
}
HRESULT STDMETHODCALLTYPE CFileServiceSecureEventNotify::QueryInterface(
REFIID riid,
void **ppvObject)
{
HRESULT hr = S_OK;
if ( NULL == ppvObject )
{
hr = E_POINTER;
}
else
{
*ppvObject = NULL;
}
if ( S_OK == hr )
{
if ( riid == __uuidof(IFileServiceSecureEventNotify) )
{
*ppvObject = (IFileServiceSecureEventNotify *)this;
}
else if ( riid == __uuidof(IUnknown) )
{
*ppvObject = (IUnknown *)this;
}
else
{
hr = E_NOINTERFACE;
}
}
if ( S_OK == hr )
{
((LPUNKNOWN)*ppvObject)->AddRef();
}
return hr;
}
ULONG STDMETHODCALLTYPE CFileServiceSecureEventNotify::AddRef()
{
return InterlockedIncrement( (LONG *)&m_cRef );
}
ULONG STDMETHODCALLTYPE CFileServiceSecureEventNotify::Release()
{
ULONG ulNewRefCount = (ULONG)InterlockedDecrement( (LONG *)&m_cRef );
if ( 0 == ulNewRefCount )
{
delete this;
}
return ulNewRefCount;
}
//////////////////////////////////////////////////////////////////////////////
// FileChangeEvent - Invoked when the service sends this event
//////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE CFileServiceSecureEventNotify::FileChangeEvent(
FILE_CHANGE_EVENT* pFileChangeEvent)
{
if( NULL == pFileChangeEvent )
{
return E_INVALIDARG;
}
// Simply print the event and return
_cwprintf(L"\r\nReceived event: [%s: %s]\r\n",
pFileChangeEvent->EventType,
pFileChangeEvent->FileName);
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
// CGetFileAsyncCallback methods
//////////////////////////////////////////////////////////////////////////////
CGetFileAsyncCallback::CGetFileAsyncCallback()
: m_cRef(1)
, m_pFileServiceSecureProxy(NULL)
{
}
CGetFileAsyncCallback::~CGetFileAsyncCallback()
{
if( NULL != m_pFileServiceSecureProxy )
{
m_pFileServiceSecureProxy->Release();
m_pFileServiceSecureProxy = NULL;
}
}
HRESULT CGetFileAsyncCallback::Init(
IFileServiceSecureProxy* pFileServiceSecureProxy,
LPCWSTR pszFileName,
LPCWSTR pszReceiveDirectory)
{
HRESULT hr = S_OK;
// Validate parameters
if( NULL == pFileServiceSecureProxy )
{
return E_INVALIDARG;
}
if( NULL == pszFileName )
{
return E_INVALIDARG;
}
if( NULL == pszReceiveDirectory )
{
return E_INVALIDARG;
}
// AddRef or copy parameters
m_pFileServiceSecureProxy = pFileServiceSecureProxy;
m_pFileServiceSecureProxy->AddRef();
hr = ::StringCbCopyW(m_szFile, sizeof(m_szFile), pszReceiveDirectory);
if( S_OK == hr )
{
hr = ::StringCbCatW(m_szFile, sizeof(m_szFile), pszFileName);
}
return hr;
}
HRESULT STDMETHODCALLTYPE CGetFileAsyncCallback::QueryInterface(
REFIID riid,
void **ppvObject)
{
HRESULT hr = S_OK;
if ( NULL == ppvObject )
{
hr = E_POINTER;
}
else
{
*ppvObject = NULL;
}
if ( S_OK == hr )
{
if ( riid == __uuidof(IWSDAsyncCallback) )
{
*ppvObject = (IWSDAsyncCallback *)this;
}
else if ( riid == __uuidof(IUnknown) )
{
*ppvObject = (IUnknown *)this;
}
else
{
hr = E_NOINTERFACE;
}
}
if ( S_OK == hr )
{
((LPUNKNOWN)*ppvObject)->AddRef();
}
return hr;
}
ULONG STDMETHODCALLTYPE CGetFileAsyncCallback::AddRef()
{
return InterlockedIncrement( (LONG *)&m_cRef );
}
ULONG STDMETHODCALLTYPE CGetFileAsyncCallback::Release()
{
ULONG ulNewRefCount = (ULONG)InterlockedDecrement( (LONG *)&m_cRef );
if ( 0 == ulNewRefCount )
{
delete this;
}
return ulNewRefCount;
}
//////////////////////////////////////////////////////////////////////////////
// ReceiveBinary - Creates a local file in the files-directory
// from the inbound attachment
//////////////////////////////////////////////////////////////////////////////
HRESULT CGetFileAsyncCallback::ReceiveBinary(
IWSDAttachment* pAttachment,
LPCWSTR pszLocalFileName)
{
HRESULT hr = S_OK;
IWSDInboundAttachment* pStream = NULL;
BYTE buffer[8192];
ULONG cbBytesRead = 0;
ULONG cbBytesLeft = 0;
DWORD cbBytesWritten = 0;
ULONG cbBytesTotal = 0;
HANDLE hFile = NULL;
DWORD dwErr = 0;
// Validate parameters
if( NULL == pAttachment )
{
return E_INVALIDARG;
}
if( NULL == pszLocalFileName )
{
return E_INVALIDARG;
}
if( 0 == wcscmp( pszLocalFileName, L"" ) )
{
return E_INVALIDARG;
}
// Make sure this attachment is an inbound attachment, and get that
// interface
hr = pAttachment->QueryInterface(
__uuidof(IWSDInboundAttachment), (void**)&pStream);
// Create a file to write attachment data into
if( S_OK == hr )
{
_cwprintf(L" Creating local file %s... ", pszLocalFileName);
hFile = ::CreateFileW( pszLocalFileName, FILE_WRITE_DATA, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if ( INVALID_HANDLE_VALUE == hFile )
{
hFile = NULL;
dwErr = ::GetLastError();
hr = HRESULT_FROM_WIN32( dwErr );
}
print_result( hr );
}
// Read from the inbound attachment and write to file until finished
while( S_OK == hr )
{
_cwprintf(L" Reading attachment data... ");
hr = pStream->Read( buffer, sizeof(buffer), &cbBytesRead );
cbBytesLeft = cbBytesRead;
// pStream->Read will return S_FALSE on the last read if the buffer
// was not completely filled. Hang onto the S_FALSE until the
// end of this loop
while( (S_OK == hr || S_FALSE == hr) && 0 < cbBytesLeft )
{
if( 0 == WriteFile( hFile,
buffer + (cbBytesRead - cbBytesLeft),
cbBytesLeft,
&cbBytesWritten, NULL ) )
{
dwErr = ::GetLastError();
hr = HRESULT_FROM_WIN32( dwErr );
}
if( S_OK == hr || S_FALSE == hr )
{
cbBytesLeft -= cbBytesWritten;
}
}
print_result( hr );
cbBytesTotal += (cbBytesRead - cbBytesLeft);
// If that was the last read, reset hr and bail out
if( S_FALSE == hr )
{
hr = S_OK;
break;
}
}
// Print success message if we got the file without any problems
if( S_OK == hr )
{
_cwprintf( L"%s recieved (%d bytes).\r\n", pszLocalFileName,
cbBytesTotal );
}
else
{
_cwprintf( L"Error receiving %s. Only recieved (%d bytes).\r\n",
pszLocalFileName, cbBytesTotal );
}
// cleanup
if( NULL != hFile )
{
::CloseHandle( hFile );
hFile = NULL;
}
if( NULL != pStream )
{
pStream->Release();
pStream = NULL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// AsyncOperationComplete - Called when the GetFile operation is complete
//////////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE CGetFileAsyncCallback::AsyncOperationComplete(
IWSDAsyncResult* pAsyncResult,
IUnknown* pAsyncState)
{
UNREFERENCED_PARAMETER(pAsyncState);
GET_FILE_RESPONSE* pResponse = NULL;
HRESULT hr = S_OK;
//
// When the GetFile operation completes, we enter this callback. It's
// then our responsibility to call EndGetFile to actually retrieve
// the results.
//
_cwprintf(L"Asynchronous GetFile operation completed.\r\n");
hr = m_pFileServiceSecureProxy->EndGetFile( pAsyncResult, &pResponse );
// Call into our helper method to save the attachment to disk
if( S_OK == hr && NULL != pResponse )
{
hr = ReceiveBinary( pResponse->Attachment, m_szFile );
}
else
{
_cwprintf(L" GetFile operation failed or returned NULL response: ");
print_result( hr );
}
// cleanup
if( NULL != pResponse )
{
WSDFreeLinkedMemory( pResponse );
pResponse = NULL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// GetFileList - Invoke the GetFileList (i.e., "dir") service method
//////////////////////////////////////////////////////////////////////////////
HRESULT GetFileList(
IFileServiceSecureProxy* pFileServiceSecureProxy)
{
GET_FILE_LIST_RESPONSE* pResponse = NULL;
HRESULT hr = S_OK;
if( NULL == pFileServiceSecureProxy )
{
return E_INVALIDARG;
}
// Invoke GetFileList method on service
_cwprintf(L"Invoking GetFileList method on service... ");
hr = pFileServiceSecureProxy->GetFileList( &pResponse );
print_result( hr );
// Print results
if( S_OK == hr && NULL != pResponse )
{
PWCHAR_LIST *pList = pResponse->FileList;
while( pList )
{
_cwprintf(L"%s\r\n", (NULL == pList->Element ? L"(null)" : pList->Element));
pList = pList->Next;
}
}
// cleanup
if( NULL != pResponse )
{
WSDFreeLinkedMemory( pResponse );
pResponse = NULL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// GetFile - Invoke the GetFile service method
//////////////////////////////////////////////////////////////////////////////
HRESULT GetFile(
IFileServiceSecureProxy* pFileServiceSecureProxy,
LPCWSTR pszFileName,
LPCWSTR pszReceiveDirectory)
{
GET_FILE_REQUEST params;
HRESULT hr = S_OK;
CGetFileAsyncCallback* pGetFileCallback = NULL;
IWSDAsyncResult* pAsyncResult = NULL;
if( NULL == pszFileName )
{
return E_INVALIDARG;
}
_cwprintf(L"Invoking GetFile method on service (file=%s)...\r\n",
pszFileName);
// Prepare parameters for service method
params.filePath = pszFileName;
//
// Set up the async callback function.
// pGetFileCallback->AsyncOperationComplete will get called when the stream
// has finished downloading, and will save the results into a local file.
//
pGetFileCallback = new CGetFileAsyncCallback();
if( NULL == pGetFileCallback )
{
hr = E_OUTOFMEMORY;
}
if( S_OK == hr )
{
_cwprintf(L" Initializing callback structure... ");
hr = pGetFileCallback->Init( pFileServiceSecureProxy,
pszFileName, pszReceiveDirectory );
print_result( hr );
}
// Invoke GetFile method on service
if( S_OK == hr )
{
_cwprintf(L" Starting GetFile operation... ");
hr = pFileServiceSecureProxy->BeginGetFile( &params, NULL,
pGetFileCallback, &pAsyncResult );
print_result( hr );
}
// cleanup
if( NULL != pGetFileCallback )
{
// Release pGetFileCallback now--if it was successful,
// BeginGetFile has added its own reference
pGetFileCallback->Release();
pGetFileCallback = NULL;
}
if( NULL != pAsyncResult )
{
// pGetFileCallback will hold a reference to our async result
// object, so we can release our reference now.
pAsyncResult->Release();
pAsyncResult = NULL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// ParseArgs - Parses the command lind arguments
//////////////////////////////////////////////////////////////////////////////
_Success_( return == S_OK )
HRESULT ParseArgs(
int argc,
_In_reads_(argc) LPWSTR* argv,
BOOL* pbIsServerCertHash,
_Outptr_result_maybenull_ LPWSTR* ppszServerCertHashAlg,
_Outptr_result_maybenull_ LPWSTR* ppszServerCertHashThumbprint,
BOOL* pbIsCertAuth,
_Outptr_result_maybenull_ LPWSTR* ppszCertAuthThumbprint,
BOOL* pbIsHttpAuth,
DWORD* pdwHttpAuthScheme,
_In_reads_(cchFileDirectoryBufferSize) LPWSTR pszFileDirectory,
size_t cchFileDirectoryBufferSize,
_Outptr_ LPWSTR* ppszDeviceAddress)
{
HRESULT hr = S_OK;
DWORD dwStatus = 0;
int iParamIndex = 1; // ignore argv[0] - start with argv[1]
// All LPWSTRs are shallow copied. Do not delete.
BOOL bIsServerCertHash = FALSE;
LPWSTR pszServerCertHashAlg = NULL;
LPWSTR pszServerCertHashThumbprint = NULL;
BOOL bIsCertAuth = FALSE;
LPWSTR pszCertAuthThumbprint = NULL;
BOOL bIsHttpAuth = FALSE;
DWORD dwHttpAuthScheme = 0;
LPWSTR pszTempFileDirectory = NULL;
LPWSTR pszTempDeviceAddress = NULL;
size_t cchFileDirectoryLength = 0;
if ( argc < 3 || argc > 10 || NULL == argv
|| 0 == cchFileDirectoryBufferSize || NULL == pszFileDirectory )
{
//
// argv[0] = L"FileServiceSecureClient.exe"
//
// Minimum: argc = 3
// FileServiceSecureClient.exe
// <files-directory> <device-address>
//
// Maximum: argc = 10
// FileServiceSecureClient.exe
// -ServerCertHash <alg> <thumbprint>
// -CertAuth <thumbprint>
// -HttpAuth <scheme>
// <files-directory> <device-address>
//
hr = E_INVALIDARG;
}
else if ( NULL == pbIsServerCertHash || NULL == ppszServerCertHashAlg
|| NULL == ppszServerCertHashThumbprint || NULL == pbIsCertAuth
|| NULL == ppszCertAuthThumbprint || NULL == pbIsHttpAuth
|| NULL == pdwHttpAuthScheme || NULL == ppszDeviceAddress )
{
hr = E_POINTER;
}
else
{
*pbIsServerCertHash = FALSE;
*ppszServerCertHashAlg = NULL;
*ppszServerCertHashThumbprint = NULL;
*pbIsCertAuth = FALSE;
*ppszCertAuthThumbprint = NULL;
*pbIsHttpAuth = FALSE;
*pdwHttpAuthScheme = 0;
::ZeroMemory( pszFileDirectory, cchFileDirectoryBufferSize );
*ppszDeviceAddress = NULL;
}
//
// -ServerCertHash <Algorithm> <Thumbprint>
//
if ( S_OK == hr && iParamIndex < argc
&& 0 == _wcsicmp( L"-ServerCertHash", argv[iParamIndex] ) )
{
if ( (iParamIndex + 2) >= argc )
{
hr = E_INVALIDARG;
}
else
{
bIsServerCertHash = TRUE;
pszServerCertHashAlg = argv[iParamIndex + 1];
pszServerCertHashThumbprint = argv[iParamIndex + 2];
iParamIndex += 3;
}
}
//
// -CertAuth NULL
// -CertAuth <Thumbprint>
//
if ( S_OK == hr && iParamIndex < argc
&& 0 == _wcsicmp( L"-CertAuth", argv[iParamIndex] ) )
{
if ( (iParamIndex + 1) >= argc )
{
hr = E_INVALIDARG;
}
else if ( 0 == _wcsicmp( L"NULL", argv[iParamIndex + 1] ) )
{
bIsCertAuth = TRUE;
pszCertAuthThumbprint = NULL;
iParamIndex += 2;
}
else
{
bIsCertAuth = TRUE;
pszCertAuthThumbprint = argv[iParamIndex + 1];
iParamIndex += 2;
}
}
//
// -HttpAuth <Scheme>
//
if ( S_OK == hr && iParamIndex < argc
&& 0 == _wcsicmp( L"-HttpAuth", argv[iParamIndex] ) )
{
if ( (iParamIndex + 1) >= argc )
{
hr = E_INVALIDARG;
}
else
{
dwStatus = swscanf_s(
argv[iParamIndex + 1], L"%d", &dwHttpAuthScheme );
if ( 1 != dwStatus )
{
hr = E_INVALIDARG;
}
else
{
bIsHttpAuth = TRUE;
iParamIndex += 2;
}
}
}
//
// <files-directory> <device-address>
//
if ( S_OK == hr )
{
if ( (iParamIndex + 1) >= argc )
{
hr = E_INVALIDARG;
}
else
{
#pragma prefast( push )
#pragma prefast( disable: 6385, "String count was checked previously." )
pszTempFileDirectory = argv[iParamIndex];
pszTempDeviceAddress = argv[iParamIndex + 1];
#pragma prefast( pop )
iParamIndex += 2;
}
}
if ( S_OK == hr && iParamIndex != argc )
{
// By now, all the parameters must have been used up. If not,
// don't allow to proceed.
hr = E_INVALIDARG;
}
if ( S_OK == hr )
{
// Check to see that the file directory is not an empty string
hr = StringCchLengthW(
pszTempFileDirectory,
cchFileDirectoryBufferSize,
&cchFileDirectoryLength );
if ( S_OK == hr && cchFileDirectoryLength < 1 )
{
hr = E_INVALIDARG;
}
}
// Return the variables to the caller.
if ( S_OK == hr )
{
if ( '\\' != pszTempFileDirectory[cchFileDirectoryLength - 1] )
{
// Backslash required at the end but one is not present.
// Add one to it as the string is being copied to the buffer.
hr = StringCbPrintfW(
pszFileDirectory,
cchFileDirectoryBufferSize * sizeof(WCHAR),
L"%s\\", pszTempFileDirectory );
}
else
{
// Backslash is already present.
hr = StringCbPrintfW(
pszFileDirectory,
cchFileDirectoryBufferSize * sizeof(WCHAR),
L"%s", pszTempFileDirectory );
}
}
if ( S_OK == hr )
{
*pbIsServerCertHash = bIsServerCertHash;
*ppszServerCertHashAlg = pszServerCertHashAlg;
*ppszServerCertHashThumbprint = pszServerCertHashThumbprint;
*pbIsCertAuth = bIsCertAuth;
*ppszCertAuthThumbprint = pszCertAuthThumbprint;
*pbIsHttpAuth = bIsHttpAuth;
*pdwHttpAuthScheme = dwHttpAuthScheme;
*ppszDeviceAddress = pszTempDeviceAddress;
}
// shallow copied
pszServerCertHashAlg = NULL;
pszServerCertHashThumbprint = NULL;
pszCertAuthThumbprint = NULL;
pszTempFileDirectory = NULL;
pszTempDeviceAddress = NULL;
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// Help - Displays list of commands
//////////////////////////////////////////////////////////////////////////////
void Help()
{
_cwprintf(L"COMMANDS:\r\n");
_cwprintf(L" dir Get the list of files on server\r\n");
_cwprintf(L" get Retrieve a file from the server\r\n");
_cwprintf(L" quit Exits program\r\n");
}
//////////////////////////////////////////////////////////////////////////////
// Usage - Displays command-line options
//////////////////////////////////////////////////////////////////////////////
void Usage()
{
_cwprintf(L"FileServiceSecureClient.exe\r\n");
_cwprintf(L" [-ServerCertHash <Algorithm> <Thumbprint>]\r\n");
_cwprintf(L" [ [-CertAuth NULL]\r\n");
_cwprintf(L" | [-CertAuth <Thumbprint>]]\r\n");
_cwprintf(L" [-HttpAuth <Scheme>]\r\n");
_cwprintf(L" <files-directory> <device-address>\r\n");
_cwprintf(L"\r\n");
_cwprintf(L"See the ReadMe file for a detailed usage description.\r\n");
}
//////////////////////////////////////////////////////////////////////////////
// Main Entry Point
// argv[0] = executable name
// argv[1] = files-directory - the local directory to copy files to
// argv[2] = device address
//////////////////////////////////////////////////////////////////////////////
int _cdecl wmain(
int argc,
_In_reads_(argc) LPWSTR* argv)
{
HRESULT hr = S_OK;
WCHAR szReceiveDirectory[MAX_PATH] = { 0 };
// szLocalAddress 46 bytes to hold UUID plus "urn:uuid:" and trailing 0
WCHAR szLocalAddress[46] = { 0 };
LPWSTR pszDeviceAddress = NULL;
BOOL bIsServerCertHash = FALSE;
LPWSTR pszServerCertHashAlg = NULL;
LPWSTR pszServerCertHashThumbprint = NULL;
BOOL bIsCertAuth = FALSE;
LPWSTR pszCertAuthThumbprint = NULL;
BOOL bIsHttpAuth = FALSE;
DWORD dwHttpAuthScheme = 0;
HANDLE hDir = NULL;
UUID uuid = { 0 };
CFileServiceSecureProxy* pFileServiceSecureProxy = NULL;
CFileServiceSecureEventNotify* pFileServiceSecureEventNotify = NULL;
bool bSubscribedToEvents = false;
DWORD dwErr = 0;
//////////////////////////////////////////////////////////////////////////
// Validate command-line parameters
//////////////////////////////////////////////////////////////////////////
if( argc <= 1 )
{
hr = E_INVALIDARG;
}
// check first argument for /? or -?
if( S_OK == hr )
{
if( 0 == wcscmp( argv[1], L"/?") || 0 == wcscmp( argv[1], L"-?" ) )
{
hr = E_INVALIDARG;
}
}
// Parse the arguments.
if ( S_OK == hr )
{
hr = ParseArgs( argc, argv,
&bIsServerCertHash, &pszServerCertHashAlg, &pszServerCertHashThumbprint,
&bIsCertAuth, &pszCertAuthThumbprint,
&bIsHttpAuth, &dwHttpAuthScheme,
szReceiveDirectory, ARRAYSIZE(szReceiveDirectory), &pszDeviceAddress );
}
//////////////////////////////////////////////////////////////////////////
// Done with command-line validation--if we've hit an error, print
// Usage now and return -1
//////////////////////////////////////////////////////////////////////////
if( S_OK != hr )
{
Usage();
return -1;
}
// Check if files-directory actually exists
if( S_OK == hr )
{
hDir = CreateFileW( szReceiveDirectory, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL );
if( INVALID_HANDLE_VALUE == hDir )
{
hDir = NULL;
hr = E_INVALIDARG;
_cwprintf(L"The files directory %s does not exist.\r\n",
szReceiveDirectory);
}
}
if( S_OK == hr )
{
// If the handle could be opened, the directory exists. However,
// we have no more use for the handle, so close it now.
if( 0 == CloseHandle( hDir ))
{
dwErr = GetLastError();
hr = HRESULT_FROM_WIN32( dwErr );
}
hDir = NULL;
}
//////////////////////////////////////////////////////////////////////////
// Build the proxy
//////////////////////////////////////////////////////////////////////////
// Generate local ID for our proxy
if( S_OK == hr )
{
RPC_STATUS st = UuidCreate(&uuid);
if( RPC_S_OK != st )
{
hr = E_FAIL;
}
}
if( S_OK == hr )
{
hr = ::StringCbPrintfW(
szLocalAddress, sizeof(szLocalAddress),
L"urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid.Data1, uuid.Data2, uuid.Data3,
uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3],
uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]);
}
// Build the proxy
if( S_OK == hr )
{
_cwprintf(L"Creating a proxy for device %s... ", pszDeviceAddress );
hr = CreateCFileServiceSecureProxy(
bIsServerCertHash, pszServerCertHashAlg, pszServerCertHashThumbprint,
bIsCertAuth, pszCertAuthThumbprint,
bIsHttpAuth, dwHttpAuthScheme,
pszDeviceAddress, szLocalAddress,
&pFileServiceSecureProxy, NULL );
print_result( hr );
}
// Build event sink for FileChange event
if( S_OK == hr )
{
_cwprintf(L"Creating an event sink... ");
pFileServiceSecureEventNotify = new CFileServiceSecureEventNotify();
if( NULL == pFileServiceSecureEventNotify )
{
hr = E_OUTOFMEMORY;
}
print_result( hr );
}
// Subscribe to FileChange event
if( S_OK == hr )
{
_cwprintf(L"Subscribing to Events... ");
hr = pFileServiceSecureProxy->SubscribeToFileChangeEvent( pFileServiceSecureEventNotify );
if( S_OK == hr )
{
bSubscribedToEvents = true;
}
print_result( hr );
}
if( S_OK == hr )
{
_cwprintf(L"Proxy creation finished.\r\n");
Help();
}
//////////////////////////////////////////////////////////////////////////
// Present interactive prompt
//////////////////////////////////////////////////////////////////////////
while( S_OK == hr )
{
WCHAR szCommand[MAX_PATH];
size_t cbSizeRead = 0;
LPWSTR pszArg = NULL;
ZeroMemory(szCommand, MAX_PATH);
_cwprintf(L"\r\n>");
// Ignore result of _cgetws_s
(void)_cgetws_s( szCommand,
sizeof(szCommand) / sizeof(WCHAR), &cbSizeRead );
// Look for arguments in command
pszArg = wcschr(szCommand, L' ');
if( pszArg )
{
*pszArg = 0;
pszArg++;
}
// Ignore result of towlower
(void)towlower( *szCommand );
// Match first character and perform appropriate operation
if( 0 == wcscmp( szCommand, L"get" ) )
{
hr = GetFile( pFileServiceSecureProxy, pszArg, szReceiveDirectory );
}
else if( 0 == wcscmp( szCommand, L"dir" ) )
{
hr = GetFileList( pFileServiceSecureProxy );
}
else if( 0 == wcscmp( szCommand, L"quit" ) )
{
// Use S_FALSE to break out of the while loop and exit
hr = S_FALSE;
}
else
{
// Encountered an unknown command--print help
Help();
}
if ( S_FALSE != hr && S_OK != hr )
{
_cwprintf(L"Command failed with [0x%08x]\r\n", hr);
// Allow to continue looping
hr = S_OK;
}
}
_cwprintf(L"Cleaning up resources... ");
// cleanup
if( NULL != pFileServiceSecureEventNotify )
{
pFileServiceSecureEventNotify->Release();
pFileServiceSecureEventNotify = NULL;
}
if( NULL != pFileServiceSecureProxy )
{
if( bSubscribedToEvents )
{
pFileServiceSecureProxy->UnsubscribeToFileChangeEvent();
}
pFileServiceSecureProxy->Release();
pFileServiceSecureProxy = NULL;
}
_cwprintf(L"finished.\r\n");
if( SUCCEEDED(hr) )
{
return 0;
}
return -1;
}