void CClientClass::ObjectsChanged( DWORD dwByteCount, BYTE *pByte)
{
DWORD dwNotifSize = 0;
DWORD dwCopySize = 0;
BYTE *pPos = pByte;
BYTE *pNotifStart = NULL;
DMNOTIFY_INFO_TYPE Type;
LDMACTION Action;
while (pPos - pByte < (long)dwByteCount)
{
pNotifStart = pPos;
// Get the notification size.
memcpy( &dwNotifSize, pPos, sizeof(DWORD) );
pPos = pPos + sizeof(DWORD);
// Get the notification type.
memcpy( &Type, pPos, sizeof(DMNOTIFY_INFO_TYPE) );
pPos = pPos + sizeof(DMNOTIFY_INFO_TYPE);
// Get the notification action.
memcpy( &Action, pPos, sizeof(LDMACTION) );
pPos = pPos + sizeof(LDMACTION);
// dwCopySize is the number of bytes left to copy out
// of the byte stream for this notification.
dwCopySize = dwNotifSize
- ( sizeof(DWORD)
+ sizeof(DMNOTIFY_INFO_TYPE)
+ sizeof(LDMACTION) );
// Switch on the type of this notification.
switch (Type) {
case DMNOTIFY_DISK_INFO:
// We need to treat IVolumeClient server and IVolumeClient3
// server differently. IVolumeClient server uses DISK_INFO,
// IVolumeClient3 uses DISK_INFO_EX. The code below will load
// DISK_INFO into a DISK_INFO_EX structure for the case where
// the server is Windows 2000 and the client is Windows XP or
// Windows 2003.
DISK_INFO_EX DiskInfoEx;
memset(&DiskInfoEx,0,sizeof(DISK_INFO_EX));
if ( nIVolumeClientVersion == 3 )
{
dwCopySize = offsetof(DISK_INFO_EX,name);
memcpy(&DiskInfoEx,pPos,offsetof(DISK_INFO_EX,name));
pPos = pPos + dwCopySize;
}
else // nIVolumeClientVersion == 1
{
//
// Copy the first part of disk info structure.
//
DISK_INFO DiskInfo;
memset(&DiskInfo,0,sizeof(DISK_INFO));
//
// On a 64-bit client, 4 bytes of padding are added
// after cchDgName, so we cannot set dwCopySize to
// offsetof(DISK_INFO,name) - the byte stream passed
// from the 32-bit server does not have these 4 bytes
// of padding.
//
// However, if the client is 32 bit and the server is
// 64 bit, the code below sets pPos to point to the
// padding.
//
// dwCopySize = offsetof(DISK_INFO,cchDgName)
// + sizeof(DiskInfo.cchDgName);
// memcpy( &DiskInfo, pPos, dwCopySize );
// pPos = pPos + dwCopySize;
// pPos may now be incorrect.
//
// We have this problem below in the DMNOTIFY_FS_INFO
// case.
//
// The workaround is to setup globals that store the
// server and client architecture. For the client, call
// the Win32 API GetSystemInfo().
//
// For the server, use the Disk Management interfaces
// to look for an ESP partition on any of the client
// disks. If one is found, assume a 64-bit
// architecture. For this code, assume
// g_ClientArchitecture and g_ServerArchitecture have
// been setup.
//
if ( g_ClientArchitecture == g_ServerArchitecture ) {
dwCopySize = offsetof(DISK_INFO, name)
memcpy( &DiskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
}
else if ( g_ClientArchitecture == 32 bit ) {
dwCopySize = offsetof(DISK_INFO,name);
memcpy( &DiskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
}
else { // ( g_ServerArchitecture == 32 bit )
dwCopySize = offsetof(DISK_INFO,cchDgName)
+ sizeof(DiskInfo.cchDgName);
memcpy( &DiskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
}
//
// Copy from DISK_INFO to DISK_INFO_EX
//
CopyToDiskInfoEx( &DiskInfo, &DiskInfoEx );
}
// Copy disk name.
wchar_t *name;
name = new wchar_t[DiskInfoEx.cchName * sizeof(wchar_t)];
if (name)
memcpy( name,
pPos,
sizeof(wchar_t) * DiskInfoEx.cchName );
pPos = pPos + (sizeof(wchar_t) * DiskInfoEx.cchName);
// Copy disk vendor.
wchar_t *vendor;
vendor = new wchar_t[DiskInfoEx.cchVendor
* sizeof(wchar_t)];
if (vendor)
memcpy( vendor,
pPos,
sizeof(wchar_t) * DiskInfoEx.cchVendor );
pPos = pPos + (sizeof(wchar_t) * DiskInfoEx.cchVendor);
// Copy disk group id.
BYTE *dgid;
dgid = new BYTE[DiskInfoEx.cchDgid * sizeof(BYTE)];
if (dgid)
memcpy( dgid,
pPos,
sizeof(BYTE) * DiskInfoEx.cchDgid );
pPos = pPos + (sizeof(BYTE) * DiskInfoEx.cchDgid);
// Copy disk adapter.
wchar_t *adapterName;
adapterName = new wchar_t[DiskInfoEx.cchAdapterName
* sizeof(wchar_t)];
if (adapterName)
memcpy( adapterName,
pPos,
sizeof(wchar_t) * DiskInfoEx.cchAdapterName );
pPos = pPos
+ (sizeof(wchar_t) * DiskInfoEx.cchAdapterName);
// Copy disk group name.
wchar_t *dgName;
dgName = new wchar_t[DiskInfoEx.cchDgName
* sizeof(wchar_t)];
if (dgName)
memcpy( dgName,
pPos,
sizeof(wchar_t) * DiskInfoEx.cchDgName );
pPos = pPos + (sizeof(wchar_t) * DiskInfoEx.cchDgName);
// Copy device instance id.
wchar_t *devInstId;
if ( nIVolumeClientVersion == 3 )
{
// Copy device instance id.
if (DiskInfoEx.cchDevInstId)
{
devInstId = new wchar_t[DiskInfoEx.cchDevInstId *
sizeof(wchar_t)];
if (devInstId)
memcpy( devInstId, pPos, sizeof(wchar_t) *
DiskInfoEx.cchDevInstId );
pPos = pPos + (sizeof(wchar_t) *
DiskInfoEx.cchDevInstId);
}
else
devInstId = NULL;
}
else // nIVolumeClientVersion == 1
devInstId = NULL;
//
// Assign the rest of the DISK_INFO_EX members.
//
DiskInfoEx.name = name;
DiskInfoEx.vendor = vendor;
DiskInfoEx.dgid = dgid;
DiskInfoEx.adapterName = adapterName;
DiskInfoEx.dgName = dgName;
DiskInfoEx.devInstId = devInstId;
break;
case DMNOTIFY_VOLUME_INFO:
VOLUME_INFO VolumeInfo;
memset( &VolumeInfo, 0, sizeof(VOLUME_INFO) );
// Copy in volume info.
memcpy( &VolumeInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
break;
case DMNOTIFY_REGION_INFO:
REGION_INFO_EX RegInfoEx;
memset( &RegInfoEx, 0, sizeof(REGION_INFO_EX) );
// We need to treat IVolumeClient server and IVolumeClient3
// server differently. IVolumeClient server uses
// REGION_INFO instead of REGION_INFO_EX. The code below
// will load REGION_INFO into a REGION_INFO_EX structure
// for the case where the server is Windows 2000 and the
// client is Windows XP or Windows 2003
if ( nIVolumeClientVersion==3 )
{
memcpy( &RegInfoEx,
pPos,
offsetof(REGION_INFO_EX,name) );
pPos += offsetof(REGION_INFO_EX,name);
// Copy name.
wchar_t *name;
name = new wchar_t[RegInfoEx.cchName
* sizeof(wchar_t)];
if (name)
memcpy( name,
pPos,
sizeof(wchar_t) * RegInfoEx.cchName );
pPos = pPos + (sizeof(wchar_t) * RegInfoEx.cchName);
RegInfoEx.name = name;
}
else // m_sIVolumeClientVersion == 1
{
REGION_INFO RegInfo;
memset( &RegInfo, 0, sizeof(REGION_INFO) );
memcpy( &RegInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
CopyToRegionInfoEx( &RegInfo, &RegInfoEx );
}
break;
case DMNOTIFY_TASK_INFO:
TASK_INFO TaskInfo;
memset( &TaskInfo, 0, sizeof(TASK_INFO) );
// Copy in task info.
memcpy( &TaskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
break;
case DMNOTIFY_DL_INFO:
DRIVE_LETTER_INFO DLInfo;
memset( &DLInfo, 0, sizeof(DRIVE_LETTER_INFO) );
// Copy in drive letter info.
memcpy( &DLInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
break;
case DMNOTIFY_FS_INFO:
FILE_SYSTEM_INFO FsInfo;
memset( &FsInfo, 0, sizeof(FILE_SYSTEM_INFO) );
//
// We have this problem here as above in the
// DMNOTIFY_DISK_INFO case.
//
// On a 64-bit client, 4 bytes of padding are added after
// cchLabel, so we cannot set dwCopySize to
// offsetof(FILE_SYSTEM, label) - the byte stream passed
// from the 32-bit server does not have these 4 bytes of
// padding.
//
// However, if the client is 32 bit and the server is 64
// bit, the code below sets pPos to point to the padding.
//
// dwCopySize = offsetof(FILE_SYSTEM_INFO, cchLabel)
// + sizeof(FsInfo.cchLabel);
// memcpy( &FsInfo, pPos, dwCopySize );
// pPos = pPos + dwCopySize;
// pPos may now be incorrect.
//
// Copy file system info.
if ( g_ClientArchitecture == g_ServerArchitecture ) {
dwCopySize = offsetof(FILE_SYSTEM_INFO, label)
memcpy( &DiskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
}
else if ( g_ClientArchitecture == 32 bit ) {
dwCopySize = offsetof(FILE_SYSTEM_INFO,label);
memcpy( &DiskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
}
else { // ( g_ServerArchitecture == 32 bit )
dwCopySize = offsetof(FILE_SYSTEM_INFO,cchLabel)
+ sizeof(FsInfo.cchLabel);
memcpy( &DiskInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
}
// Copy the label.
wchar_t *label;
label = new wchar_t[FsInfo.cchLabel * sizeof(wchar_t)];
if (label)
memcpy( label,
pPos,
sizeof(wchar_t) * FsInfo.cchLabel );
pPos = pPos + (sizeof(wchar_t) * FsInfo.cchLabel);
FsInfo.label = label;
break;
case DMNOTIFY_SYSTEM_INFO:
DWORD SysInfo;
memset( &SysInfo, 0, sizeof(DWORD) );
// Copy in system info.
memcpy( &SysInfo, pPos, dwCopySize );
pPos = pPos + dwCopySize;
break;
} // switch
pPos = pNotifStart + dwNotifSize;
} // while
}