8 Appendix C: IDMNotify::ObjectsChanged
-
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 }