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
  
 }