00001 /* Manage creation and manipulation of PIDLs representing sftp host connections 00002 00003 Copyright (C) 2007 Alexander Lamaison <awl03@doc.ic.ac.uk> 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License along 00016 with this program; if not, write to the Free Software Foundation, Inc., 00017 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 #include "stdafx.h" 00021 #include "HostPidlManager.h" 00022 00023 /*------------------------------------------------------------------------------ 00024 * CHostPidlManager::Create 00025 * Create a new terminated PIDL using the passed-in connection information 00026 *----------------------------------------------------------------------------*/ 00027 HRESULT CHostPidlManager::Create(__in LPCWSTR pwszLabel, __in LPCWSTR pwszUser, 00028 __in LPCWSTR pwszHost, __in LPCWSTR pwszPath, 00029 __in USHORT uPort, 00030 __deref_out PITEMID_CHILD *ppidlOut ) 00031 { 00032 ATLASSERT(sizeof(HOSTPIDL) % sizeof(DWORD) == 0); // DWORD-aligned 00033 00034 PITEMID_CHILD pidl = NULL; 00035 00036 // Allocate enough memory to hold a HOSTPIDL structure plus terminator 00037 static SIZE_T uTerminatedSize = sizeof(HOSTPIDL) + sizeof(USHORT); 00038 pidl = (PITEMID_CHILD)CoTaskMemAlloc( uTerminatedSize ); 00039 if(!pidl) 00040 return E_OUTOFMEMORY; 00041 ZeroMemory(pidl, uTerminatedSize); 00042 00043 // Use first PIDL member as a HOSTPIDL structure 00044 PHOSTPIDL pidlHost = (PHOSTPIDL)pidl; 00045 00046 // Fill members of the PIDL with data 00047 pidlHost->cb = sizeof HOSTPIDL; 00048 pidlHost->dwFingerprint = HOSTPIDL_FINGERPRINT; // Sign with fingerprint 00049 CopyWSZString(pidlHost->wszLabel, ARRAYSIZE(pidlHost->wszLabel), pwszLabel); 00050 CopyWSZString(pidlHost->wszUser, ARRAYSIZE(pidlHost->wszUser), pwszUser); 00051 CopyWSZString(pidlHost->wszHost, ARRAYSIZE(pidlHost->wszHost), pwszHost); 00052 CopyWSZString(pidlHost->wszPath, ARRAYSIZE(pidlHost->wszPath), pwszPath); 00053 pidlHost->uPort = uPort; 00054 00055 // Create the terminating null PIDL by setting cb field to 0. 00056 LPITEMIDLIST pidlNext = GetNextItem(pidl); 00057 ATLASSERT(pidlNext != NULL); 00058 pidlNext->mkid.cb = 0; 00059 00060 *ppidlOut = pidl; 00061 ATLASSERT(SUCCEEDED(IsValid(*ppidlOut))); 00062 ATLASSERT(ILGetNext(ILGetNext(*ppidlOut)) == NULL); // PIDL is terminated 00063 ATLASSERT(ILGetSize(*ppidlOut) == uTerminatedSize); 00064 00065 return S_OK; 00066 } 00067 00068 /*------------------------------------------------------------------------------ 00069 * CHostPidlManager::Validate 00070 * Validate the fingerprint stored in the PIDL. 00071 * If fingerprint matches HOSTPIDL return true/PIDL else return false/NULL 00072 *----------------------------------------------------------------------------*/ 00073 PHOSTPIDL CHostPidlManager::Validate( LPCITEMIDLIST pidl ) 00074 { 00075 PHOSTPIDL pHostPidl = NULL; 00076 00077 if (pidl) 00078 { 00079 pHostPidl = (PHOSTPIDL)pidl; 00080 if (pHostPidl->cb && pHostPidl->dwFingerprint == HOSTPIDL_FINGERPRINT) 00081 return pHostPidl; // equal to true 00082 } 00083 00084 return NULL; // equal to false 00085 } 00086 00087 /*------------------------------------------------------------------------------ 00088 * CHostPidlManager::IsValid 00089 * Check if the fingerprint stored in the PIDL corresponds to a HOSTPIDL. 00090 *----------------------------------------------------------------------------*/ 00091 HRESULT CHostPidlManager::IsValid( LPCITEMIDLIST pidl ) 00092 { 00093 PHOSTPIDL pHostPidl = Validate(pidl); 00094 return pHostPidl ? S_OK : E_INVALIDARG; 00095 } 00096 00097 /*------------------------------------------------------------------------------ 00098 * CHostPidlManager::GetLabel 00099 * Returns the friendly display name from the (possibly multilevel) PIDL. 00100 *----------------------------------------------------------------------------*/ 00101 CString CHostPidlManager::GetLabel( LPCITEMIDLIST pidl ) 00102 { 00103 if (pidl == NULL) return _T(""); 00104 00105 return GetDataSegment(pidl)->wszLabel; 00106 } 00107 00108 /*------------------------------------------------------------------------------ 00109 * CHostPidlManager::GetUser 00110 * Returns the username from the (possibly multilevel) PIDL. 00111 *----------------------------------------------------------------------------*/ 00112 CString CHostPidlManager::GetUser( LPCITEMIDLIST pidl ) 00113 { 00114 if (pidl == NULL) return _T(""); 00115 00116 return GetDataSegment(pidl)->wszUser; 00117 } 00118 00119 /*------------------------------------------------------------------------------ 00120 * CHostPidlManager::GetHost 00121 * Returns the hostname from the (possibly multilevel) PIDL. 00122 *----------------------------------------------------------------------------*/ 00123 CString CHostPidlManager::GetHost( LPCITEMIDLIST pidl ) 00124 { 00125 if (pidl == NULL) return _T(""); 00126 00127 return GetDataSegment(pidl)->wszHost; 00128 } 00129 00130 /*------------------------------------------------------------------------------ 00131 * CHostPidlManager::GetPath 00132 * Returns the remote directory path from the (possibly multilevel) PIDL. 00133 *----------------------------------------------------------------------------*/ 00134 CString CHostPidlManager::GetPath( LPCITEMIDLIST pidl ) 00135 { 00136 if (pidl == NULL) return _T(""); 00137 00138 return GetDataSegment(pidl)->wszPath; 00139 } 00140 00141 /*------------------------------------------------------------------------------ 00142 * CHostPidlManager::GetPort 00143 * Returns the SFTP port number from the (possibly multilevel) PIDL. 00144 *----------------------------------------------------------------------------*/ 00145 USHORT CHostPidlManager::GetPort( LPCITEMIDLIST pidl ) 00146 { 00147 if (pidl == NULL) return 0; 00148 00149 return GetDataSegment(pidl)->uPort; 00150 } 00151 00152 /*------------------------------------------------------------------------------ 00153 * CHostPidlManager::GetPortStr 00154 * Returns the SFTP port number from the (possibly multilevel) PIDL as a CString 00155 *----------------------------------------------------------------------------*/ 00156 CString CHostPidlManager::GetPortStr( LPCITEMIDLIST pidl ) 00157 { 00158 if (pidl == NULL) return _T(""); 00159 00160 CString strPort; 00161 strPort.Format(_T("%u"), GetDataSegment(pidl)->uPort); 00162 return strPort; 00163 } 00164 00165 /*------------------------------------------------------------------------------ 00166 * CHostPidlManager::GetDataSegment 00167 * Walk to last item in PIDL (if multilevel) and returns item as a HOSTPIDL. 00168 * If the item was not a valid HOSTPIDL then we return NULL. 00169 *----------------------------------------------------------------------------*/ 00170 PHOSTPIDL CHostPidlManager::GetDataSegment( LPCITEMIDLIST pidl ) 00171 { 00172 // Get the last item of the PIDL to make sure we get the right value 00173 // in case of multiple nesting levels 00174 PITEMID_CHILD pidlHost = CPidlManager::GetDataSegment( pidl ); 00175 00176 ATLASSERT(SUCCEEDED(IsValid( pidlHost ))); 00177 // If not, this is unexpected behviour. Why were we passed this PIDL? 00178 00179 return Validate( pidlHost ); 00180 }