Ignore:
Timestamp:
Oct 24, 2012, 8:25:23 PM (13 years ago)
Author:
Silvan Scherrer
Message:

SMplayer: update trunk to 0.8.1

Location:
smplayer/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • smplayer/trunk

  • smplayer/trunk/src/winfileassoc.cpp

    r124 r135  
    1616    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1717
    18 
    1918        Winfileassoc.cpp
    2019
    21         Handles file associations in Windows Vista/XP/2000/NT/ME/98/95.
     20        Handles file associations in Windows 7/Vista/XP/2000.
    2221        We assume that the code is run without administrator privileges, so the associations are done for current user only.
    2322        System-wide associations require writing to HKEY_CLASSES_ROOT and we don't want to get our hands dirty with that.
     
    2524
    2625        Optionally, during uninstall, it would be a good idea to call RestoreFileAssociations for all media types so
    27         that we can clean up the registry and restore the old associations for current user. 
     26        that we can clean up the registry and restore the old associations for current user.
    2827
    2928        Vista:
    30         The code can only register the app as default program for selected extensions and check if it is the default. 
     29        The code can only register the app as default program for selected extensions and check if it is the default.
    3130        It cannot restore 'old' default application, since this doesn't seem to be possible with the current Vista API.
    3231
    33         Tested on: Win98, Win2000, WinXP, Vista.
    34         NOT tested on: Win95, ME and NT 4.0 (it should work on 95, ME; Not sure about NT 4.0).
     32        Add libole32.a library if compiling with MinGW. In smplayer.pro, under 'win32 {': LIBS += libole32
     33
     34        Tested on: WinXP, Vista, Win7.
    3535
    3636        Author: Florin Braghis (florin@libertv.ro)
     
    4141#include <QApplication>
    4242#include <QFileInfo>
    43 
    44 WinFileAssoc::WinFileAssoc( const QString ClassId, const QString AppName )
    45 {
    46         m_ClassId = ClassId;
    47         m_AppName = AppName;
    48         m_ClassId2 = QFileInfo(QApplication::applicationFilePath()).fileName();
    49 }
    50 
    51 //Associates all extensions in the fileExtensions list with current app.
    52 //Returns number of extensions processed successfully.
    53 int WinFileAssoc::CreateFileAssociations(const QStringList& fileExtensions)
    54 {
    55         if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
    56         {
    57                 return VistaSetAppsAsDefault(fileExtensions);
    58         }
    59 
    60         QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat); //Read only on NT+
    61         QSettings RegCU ("HKEY_CURRENT_USER", QSettings::NativeFormat);
    62 
    63         if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError)
    64                 return 0;
    65 
    66         if (RegCR.status() != QSettings::NoError)
    67                 return 0;
    68 
    69         if (QSysInfo::WindowsVersion < QSysInfo::WV_NT && !RegCR.isWritable())  //Win98
    70                 return 0;
    71 
    72         //Check if classId exists in the registry
    73         if (!RegCR.contains(m_ClassId) && !RegCU.contains("Software/Classes/" + m_ClassId))
    74         {
    75                 //If doesn't exist (user didn't run the setup program), try to create the ClassId for current user.
    76                 if (!CreateClassId(QApplication::applicationFilePath(), "SMPlayer Media Player"))
    77                         return 0;
    78         }
    79        
    80         int count = 0;
    81         foreach(const QString& fileExtension, fileExtensions)
    82         {
    83                 QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension);
    84                 QString ClassesKeyName = m_ClassId;
    85 
    86                 QString BackupKeyName = ClassesKeyName + "/" + fileExtension;
    87                 QString CUKeyName = "Software/Classes/." + fileExtension;
    88 
    89                 //Save current ClassId for current user
    90                 QString KeyVal = RegCU.value(CUKeyName + "/.").toString();
    91 
    92                 if (KeyVal.length() == 0 || KeyVal == m_ClassId)
    93                 {
    94                         //No registered app for this extension for current user.
    95                         //Check the system-wide (HKEY_CLASSES_ROOT) ClassId for this extension
    96                         KeyVal = RegCR.value("." + fileExtension + "/.").toString();
    97                 }
    98 
    99                 if (KeyVal != m_ClassId)
    100                         RegCU.setValue(CUKeyName + "/MPlayer_Backup", KeyVal);
    101 
    102                 //Save last ProgId and Application values from the Exts key
    103                 KeyVal = RegCU.value(ExtKeyName + "/Progid").toString();
    104                
    105                 if (KeyVal != m_ClassId && KeyVal != m_ClassId2)
    106                         RegCU.setValue(ExtKeyName + "/MPlayer_Backup_ProgId", KeyVal);
    107 
    108                 KeyVal = RegCU.value(ExtKeyName + "/Application").toString();
    109                 if (KeyVal != m_ClassId || KeyVal != m_ClassId2)
    110                         RegCU.setValue(ExtKeyName + "/MPlayer_Backup_Application", KeyVal);
    111 
    112                 //Create the associations
    113                 if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT)
    114                 {
    115                         RegCU.setValue(CUKeyName + "/.", m_ClassId);            //Extension class
    116                         RegCU.setValue(ExtKeyName + "/Progid", m_ClassId);      //Explorer FileExt association
    117 
    118                 }
    119                 else
    120                 {
    121                         //Windows ME/98/95 support
    122                         RegCR.setValue("." + fileExtension + "/.", m_ClassId);
    123                 }
    124 
    125                 if (RegCU.status() == QSettings::NoError && RegCR.status() == QSettings::NoError)
    126                         count++;
    127         }
    128 
    129         return count;
    130 }
    131 
    132 //Checks if extensions in extensionsToCheck are registered with this application. Returns a list of registered extensions.
    133 //Returns false if there was an error accessing the registry.
    134 //Returns true and 0 elements in registeredExtensions if no extension is associated with current app.
    135 bool WinFileAssoc::GetRegisteredExtensions( const QStringList& extensionsToCheck, QStringList& registeredExtensions)
    136 {
    137         registeredExtensions.clear();
    138 
    139         if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
    140         {
    141                 return VistaGetDefaultApps(extensionsToCheck, registeredExtensions);
    142         }
    143 
    144         QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
    145         QSettings RegCU ("HKEY_CURRENT_USER", QSettings::NativeFormat);
    146 
    147         if (RegCR.status() != QSettings::NoError)
    148                 return false;
    149 
    150         if (RegCU.status() != QSettings::NoError)
    151                 return false;
    152 
    153         foreach(const QString& fileExtension, extensionsToCheck)
    154         {
    155                 bool bRegistered = false;
    156                 //Check the explorer extension (Always use this program to open this kind of file...)
    157 
    158                 if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT)
    159                 {
    160                         QString FileExtsKey = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension);
    161                         QString CurClassId = RegCU.value(FileExtsKey + "/Progid").toString();
    162                         QString CurAppId = RegCU.value(FileExtsKey + "/Application").toString();
    163 
    164                         if (CurClassId.size())  //Registered with Open With... / ProgId ?
    165                         {
    166                                 bRegistered = (CurClassId == m_ClassId) || (0 == CurClassId.compare(m_ClassId2, Qt::CaseInsensitive));
    167                         }
    168                         else
    169                         if (CurAppId.size())
    170                         {
    171                                 //If user uses Open With..., explorer creates it's own ClassId under Application, usually "smplayer.exe"
    172                                 bRegistered = (CurAppId == m_ClassId) || (0 == CurAppId.compare(m_ClassId2, Qt::CaseInsensitive));
    173                         }
    174                         else
    175                         {
    176                                 //No classId means that no associations exists in Default Programs or Explorer
    177                                 //Check the default per-user association
    178                                 bRegistered = RegCU.value("Software/Classes/." + fileExtension + "/.").toString() == m_ClassId;
    179                         }
    180                 }
    181                
    182                 //Finally, check the system-wide association
    183                 if (!bRegistered)
    184                         bRegistered = RegCR.value("." + fileExtension + "/.").toString() == m_ClassId;
    185 
    186 
    187                 if (bRegistered)
    188                         registeredExtensions.append(fileExtension);
    189         }
    190        
    191         return true;
    192 }
    193 
    194 //Restores file associations to old defaults (if any) for all extensions in the fileExtensions list.
    195 //Cleans up our backup keys from the registry.
    196 //Returns number of extensions successfully processed (error if fileExtensions.count() != return value && count > 0).
    197 int WinFileAssoc::RestoreFileAssociations(const QStringList& fileExtensions)
    198 {
    199         if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
    200                 return 0; //Not supported by the API
    201 
    202         QSettings RegCR ("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
    203         QSettings RegCU ("HKEY_CURRENT_USER", QSettings::NativeFormat);
    204 
    205         if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError)
    206                 return 0;
    207 
    208         if (RegCR.status() != QSettings::NoError)
    209                 return 0;
    210 
    211         if (QSysInfo::WindowsVersion < QSysInfo::WV_NT && !RegCR.isWritable())  //Win98
    212                 return 0;
    213 
    214         int count = 0;
    215         foreach(const QString& fileExtension, fileExtensions)
    216         {
    217                 QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension);
    218                 QString OldProgId = RegCU.value(ExtKeyName + "/MPlayer_Backup_ProgId").toString();
    219                 QString OldApp  = RegCU.value(ExtKeyName + "/MPlayer_Backup_Application").toString();
    220                 QString OldClassId = RegCU.value("Software/Classes/." + fileExtension + "/MPlayer_Backup").toString();
    221 
    222                 //Restore old explorer ProgId
    223                 if (!OldProgId.isEmpty() && OldProgId != m_ClassId)
    224                         RegCU.setValue(ExtKeyName + "/Progid", OldProgId);
    225                 else
    226                 {
    227                         QString CurProgId = RegCU.value(ExtKeyName + "/Progid").toString();
    228                         if ((CurProgId == m_ClassId) || (0 == CurProgId.compare(m_ClassId2, Qt::CaseInsensitive))) //Only remove if we own it
    229                                 RegCU.remove(ExtKeyName + "/Progid");   
    230                 }
    231 
    232                 //Restore old explorer Application
    233                 if (!OldApp.isEmpty() && OldApp != m_ClassId)
    234                         RegCU.setValue(ExtKeyName + "/Application", OldApp);
    235                 else
    236                 {
    237                         QString CurApp = RegCU.value(ExtKeyName + "/Application").toString();
    238                         if ((CurApp == m_ClassId) || (0 == CurApp.compare(m_ClassId2, Qt::CaseInsensitive))) //Only remove if we own it
    239                                 RegCU.remove(ExtKeyName + "/Application");
    240                 }
    241 
    242                 if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT)
    243                 {
    244                         //Restore old association for current user
    245                         if (!OldClassId.isEmpty() && OldClassId != m_ClassId)
    246                                 RegCU.setValue("Software/Classes/." + fileExtension + "/.", OldClassId);
    247                         else
    248                         {
    249                                 if (RegCU.value("Software/Classes/." + fileExtension + "/.").toString() == m_ClassId) //Only remove if we own it
    250                                         RegCU.remove("Software/Classes/." + fileExtension);
    251                         }
    252                 }
    253                 else
    254                 {
    255                         //Windows 98 ==> Write to HKCR
    256                         if (!OldClassId.isEmpty() && OldClassId != m_ClassId)
    257                                 RegCR.setValue("." + fileExtension + "/.", OldClassId);
    258                         else
    259                         {
    260                                 if (RegCR.value("." + fileExtension + "/.").toString() == m_ClassId)
    261                                         RegCR.remove("." + fileExtension);
    262                         }
    263                 }
    264 
    265                 //Remove our keys:
    266                 //CurrentUserClasses/.ext/MPlayerBackup
    267                 //Explorer: Backup_Application and Backup_ProgId
    268                 RegCU.remove("Software/Classes/." + fileExtension + "/MPlayer_Backup");
    269                 RegCU.remove(ExtKeyName + "/MPlayer_Backup_Application");
    270                 RegCU.remove(ExtKeyName + "/MPlayer_Backup_ProgId");
    271         }
    272         return count;
    273 }
    274 
    275 //Creates a ClassId for current application.
    276 //Note: It's better to create the classId from the installation program.
    277 bool WinFileAssoc::CreateClassId(const QString& executablePath, const QString& friendlyName)
    278 {
    279         QString RootKeyName;
    280         QString classId;
    281 
    282         if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT)
    283         {
    284                 classId = "Software/Classes/" + m_ClassId;
    285                 RootKeyName = "HKEY_CURRENT_USER";
    286         }
    287         else
    288         {
    289                 classId = m_ClassId;
    290                 RootKeyName = "HKEY_CLASSES_ROOT";      //Windows 95/98/ME
    291         }
    292 
    293         QSettings Reg (RootKeyName, QSettings::NativeFormat);
    294         if (!Reg.isWritable() || Reg.status() != QSettings::NoError)
    295                 return false;
    296 
    297         QString appPath = executablePath;
    298         appPath.replace('/', '\\'); //Explorer gives 'Access Denied' if we write the path with forward slashes to the registry
    299 
    300         //Add our ProgId to the HKCR classes
    301         Reg.setValue(classId + "/shell/open/FriendlyAppName", friendlyName);
    302         Reg.setValue(classId + "/shell/open/command/.", QString("\"%1\" \"%2\"").arg(appPath, "%1"));
    303         Reg.setValue(classId + "/DefaultIcon/.", QString("\"%1\",1").arg(appPath));
    304         //Add "Enqueue" command
    305         Reg.setValue(classId + "/shell/enqueue/.", QObject::tr("Enqueue in SMPlayer"));
    306         Reg.setValue(classId + "/shell/enqueue/command/.", QString("\"%1\" -add-to-playlist \"%2\"").arg(appPath, "%1"));
    307         return true;
    308 }
    309 //Remove ClassId from the registry.
    310 //Called when no associations exist. Note: It's better to do this in the Setup program.
     43#include <windows.h>
     44
     45WinFileAssoc::WinFileAssoc(const QString ClassId, const QString AppName)
     46{
     47    m_ClassId = ClassId;
     48    m_AppName = AppName;
     49    m_ClassId2 = QFileInfo(QApplication::applicationFilePath()).fileName();
     50}
     51
     52// Associates all extensions in the fileExtensions list with current app.
     53// Returns number of extensions processed successfully.
     54int WinFileAssoc::CreateFileAssociations(const QStringList &fileExtensions)
     55{
     56    if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) {
     57        return VistaSetAppsAsDefault(fileExtensions);
     58    }
     59
     60    QSettings RegCR("HKEY_CLASSES_ROOT", QSettings::NativeFormat);  //Read only on NT+
     61    QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat);
     62
     63    if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError)
     64        return 0;
     65
     66    if (RegCR.status() != QSettings::NoError)
     67        return 0;
     68
     69    // Check if classId exists in the registry
     70    if (!RegCR.contains(m_ClassId) && !RegCU.contains("Software/Classes/" + m_ClassId)) {
     71        // If doesn't exist (user didn't run the setup program), try to create the ClassId for current user.
     72        if (!CreateClassId(QApplication::applicationFilePath(), "SMPlayer Media Player"))
     73            return 0;
     74    }
     75
     76    int count = 0;
     77    foreach(const QString & fileExtension, fileExtensions) {
     78        QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension);
     79        QString ClassesKeyName = m_ClassId;
     80
     81        QString BackupKeyName = ClassesKeyName + "/" + fileExtension;
     82        QString CUKeyName = "Software/Classes/." + fileExtension;
     83
     84        // Save current ClassId for current user
     85        QString KeyVal = RegCU.value(CUKeyName + "/.").toString();
     86
     87        if (KeyVal.length() == 0 || KeyVal == m_ClassId) {
     88            // No registered app for this extension for current user.
     89            // Check the system-wide (HKEY_CLASSES_ROOT) ClassId for this extension
     90            KeyVal = RegCR.value("." + fileExtension + "/.").toString();
     91        }
     92
     93        if (KeyVal != m_ClassId)
     94            RegCU.setValue(CUKeyName + "/MPlayer_Backup", KeyVal);
     95
     96        // Save last ProgId and Application values from the Exts key
     97        KeyVal = RegCU.value(ExtKeyName + "/Progid").toString();
     98
     99        if (KeyVal != m_ClassId && KeyVal != m_ClassId2)
     100            RegCU.setValue(ExtKeyName + "/MPlayer_Backup_ProgId", KeyVal);
     101
     102        KeyVal = RegCU.value(ExtKeyName + "/Application").toString();
     103
     104        if (KeyVal != m_ClassId || KeyVal != m_ClassId2)
     105            RegCU.setValue(ExtKeyName + "/MPlayer_Backup_Application", KeyVal);
     106
     107        // Create the associations
     108        RegCU.setValue(CUKeyName + "/.", m_ClassId);            // Extension class
     109        RegCU.setValue(ExtKeyName + "/Progid", m_ClassId);      // Explorer FileExt association
     110
     111        if (RegCU.status() == QSettings::NoError && RegCR.status() == QSettings::NoError)
     112            count++;
     113    }
     114
     115    return count;
     116}
     117
     118// Checks if extensions in extensionsToCheck are registered with this application. Returns a list of registered extensions.
     119// Returns false if there was an error accessing the registry.
     120// Returns true and 0 elements in registeredExtensions if no extension is associated with current app.
     121bool WinFileAssoc::GetRegisteredExtensions(const QStringList &extensionsToCheck, QStringList &registeredExtensions)
     122{
     123    registeredExtensions.clear();
     124
     125    if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA) {
     126        return VistaGetDefaultApps(extensionsToCheck, registeredExtensions);
     127    }
     128
     129    QSettings RegCR("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
     130    QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat);
     131
     132    if (RegCR.status() != QSettings::NoError)
     133        return false;
     134
     135    if (RegCU.status() != QSettings::NoError)
     136        return false;
     137
     138    foreach(const QString & fileExtension, extensionsToCheck) {
     139        bool bRegistered = false;
     140        // Check the Explorer extension (Always use this program to open this kind of file...)
     141
     142        QString FileExtsKey = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension);
     143        QString CurClassId = RegCU.value(FileExtsKey + "/Progid").toString();
     144        QString CurAppId = RegCU.value(FileExtsKey + "/Application").toString();
     145
     146        if (CurClassId.size()) {        // Registered with Open With... / ProgId ?
     147            bRegistered = (CurClassId == m_ClassId) || (0 == CurClassId.compare(m_ClassId2, Qt::CaseInsensitive));
     148        } else if (CurAppId.size()) {
     149            // If user uses Open With..., explorer creates it's own ClassId under Application, usually "smplayer.exe"
     150            bRegistered = (CurAppId == m_ClassId) || (0 == CurAppId.compare(m_ClassId2, Qt::CaseInsensitive));
     151        } else {
     152            // No classId means that no associations exists in Default Programs or Explorer
     153            // Check the default per-user association
     154            bRegistered = RegCU.value("Software/Classes/." + fileExtension + "/.").toString() == m_ClassId;
     155        }
     156
     157        // Finally, check the system-wide association
     158        if (!bRegistered)
     159            bRegistered = RegCR.value("." + fileExtension + "/.").toString() == m_ClassId;
     160
     161        if (bRegistered)
     162            registeredExtensions.append(fileExtension);
     163    }
     164
     165    return true;
     166}
     167
     168// Restores file associations to old defaults (if any) for all extensions in the fileExtensions list.
     169// Cleans up our backup keys from the registry.
     170// Returns number of extensions successfully processed (error if fileExtensions.count() != return value && count > 0).
     171int WinFileAssoc::RestoreFileAssociations(const QStringList &fileExtensions)
     172{
     173    if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
     174        return 0; // Not supported by the API
     175
     176    QSettings RegCR("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
     177    QSettings RegCU("HKEY_CURRENT_USER", QSettings::NativeFormat);
     178
     179    if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError)
     180        return 0;
     181
     182    if (RegCR.status() != QSettings::NoError)
     183        return 0;
     184
     185    int count = 0;
     186    foreach(const QString & fileExtension, fileExtensions) {
     187        QString ExtKeyName = QString("Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/.%1").arg(fileExtension);
     188        QString OldProgId = RegCU.value(ExtKeyName + "/MPlayer_Backup_ProgId").toString();
     189        QString OldApp  = RegCU.value(ExtKeyName + "/MPlayer_Backup_Application").toString();
     190        QString OldClassId = RegCU.value("Software/Classes/." + fileExtension + "/MPlayer_Backup").toString();
     191
     192        // Restore old explorer ProgId
     193        if (!OldProgId.isEmpty() && OldProgId != m_ClassId)
     194            RegCU.setValue(ExtKeyName + "/Progid", OldProgId);
     195        else {
     196            QString CurProgId = RegCU.value(ExtKeyName + "/Progid").toString();
     197
     198            if ((CurProgId == m_ClassId) || (0 == CurProgId.compare(m_ClassId2, Qt::CaseInsensitive))) //Only remove if we own it
     199                RegCU.remove(ExtKeyName + "/Progid");
     200        }
     201
     202        // Restore old explorer Application
     203        if (!OldApp.isEmpty() && OldApp != m_ClassId)
     204            RegCU.setValue(ExtKeyName + "/Application", OldApp);
     205        else {
     206            QString CurApp = RegCU.value(ExtKeyName + "/Application").toString();
     207
     208            if ((CurApp == m_ClassId) || (0 == CurApp.compare(m_ClassId2, Qt::CaseInsensitive))) //Only remove if we own it
     209                RegCU.remove(ExtKeyName + "/Application");
     210        }
     211
     212        // Restore old association for current user
     213        if (!OldClassId.isEmpty() && OldClassId != m_ClassId)
     214            RegCU.setValue("Software/Classes/." + fileExtension + "/.", OldClassId);
     215        else {
     216            if (RegCU.value("Software/Classes/." + fileExtension + "/.").toString() == m_ClassId) //Only remove if we own it
     217                RegCU.remove("Software/Classes/." + fileExtension);
     218        }
     219
     220        // Remove our keys:
     221        // CurrentUserClasses/.ext/MPlayerBackup
     222        // Explorer: Backup_Application and Backup_ProgId
     223        RegCU.remove("Software/Classes/." + fileExtension + "/MPlayer_Backup");
     224        RegCU.remove(ExtKeyName + "/MPlayer_Backup_Application");
     225        RegCU.remove(ExtKeyName + "/MPlayer_Backup_ProgId");
     226    }
     227    return count;
     228}
     229
     230// Creates a ClassId for current application.
     231// Note: It's better to create the classId from the installation program.
     232bool WinFileAssoc::CreateClassId(const QString &executablePath, const QString &friendlyName)
     233{
     234    QString RootKeyName;
     235    QString classId;
     236
     237    classId = "Software/Classes/" + m_ClassId;
     238    RootKeyName = "HKEY_CURRENT_USER";
     239
     240    QSettings Reg(RootKeyName, QSettings::NativeFormat);
     241
     242    if (!Reg.isWritable() || Reg.status() != QSettings::NoError)
     243        return false;
     244
     245    QString appPath = executablePath;
     246    appPath.replace('/', '\\'); // Explorer gives 'Access Denied' if we write the path with forward slashes to the registry
     247
     248    // Add our ProgId to the HKCR classes
     249    Reg.setValue(classId + "/shell/open/FriendlyAppName", friendlyName);
     250    Reg.setValue(classId + "/shell/open/command/.", QString("\"%1\" \"%2\"").arg(appPath, "%1"));
     251    Reg.setValue(classId + "/DefaultIcon/.", QString("\"%1\",1").arg(appPath));
     252
     253    // Add "Enqueue" command
     254    Reg.setValue(classId + "/shell/enqueue/.", QObject::tr("Enqueue in SMPlayer"));
     255    Reg.setValue(classId + "/shell/enqueue/command/.", QString("\"%1\" -add-to-playlist \"%2\"").arg(appPath, "%1"));
     256    return true;
     257}
     258
     259// Remove ClassId from the registry.
     260// Called when no associations exist. Note: It's better to do this in the Setup program.
    311261bool WinFileAssoc::RemoveClassId()
    312262{
    313         QString RootKeyName;
    314         QString classId;
    315 
    316         if (QSysInfo::WindowsVersion >= QSysInfo::WV_NT)
    317         {
    318                 classId = "Software/Classes/" + m_ClassId;
    319                 RootKeyName = "HKEY_CURRENT_USER";
    320         }
    321         else
    322         {
    323                 classId = m_ClassId;
    324                 RootKeyName = "HKEY_CLASSES_ROOT";      //Windows 95/98/ME
    325         }
    326 
    327         QSettings RegCU (RootKeyName, QSettings::NativeFormat);
    328 
    329         if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError)
    330                 return false;
    331 
    332         RegCU.remove(classId);
    333         return true;
    334 }
    335 
    336 //Windows Vista specific implementation
    337 //Add libole32.a library if compiling with mingw.
    338 //In smplayer.pro, under win32{ :
    339 //      LIBS += libole32
    340 #ifdef WIN32
    341 #include <windows.h>
     263    QString RootKeyName;
     264    QString classId;
     265
     266    classId = "Software/Classes/" + m_ClassId;
     267    RootKeyName = "HKEY_CURRENT_USER";
     268
     269    QSettings RegCU(RootKeyName, QSettings::NativeFormat);
     270
     271    if (!RegCU.isWritable() || RegCU.status() != QSettings::NoError)
     272        return false;
     273
     274    RegCU.remove(classId);
     275    return true;
     276}
     277
     278// Windows Vista specific implementation
    342279
    343280#if !defined(IApplicationAssociationRegistration)
    344281
    345 typedef enum tagASSOCIATIONLEVEL
    346 {
    347         AL_MACHINE,
    348         AL_EFFECTIVE,
    349         AL_USER
     282typedef enum tagASSOCIATIONLEVEL {
     283    AL_MACHINE,
     284    AL_EFFECTIVE,
     285    AL_USER
    350286} ASSOCIATIONLEVEL;
    351287
    352 typedef enum tagASSOCIATIONTYPE
    353 {
    354         AT_FILEEXTENSION,
    355         AT_URLPROTOCOL,
    356         AT_STARTMENUCLIENT,
    357         AT_MIMETYPE
     288typedef enum tagASSOCIATIONTYPE {
     289    AT_FILEEXTENSION,
     290    AT_URLPROTOCOL,
     291    AT_STARTMENUCLIENT,
     292    AT_MIMETYPE
    358293} ASSOCIATIONTYPE;
    359294
    360295MIDL_INTERFACE("4e530b0a-e611-4c77-a3ac-9031d022281b")
    361 IApplicationAssociationRegistration : public IUnknown
    362 {
     296IApplicationAssociationRegistration :
     297public IUnknown {
    363298public:
    364         virtual HRESULT STDMETHODCALLTYPE QueryCurrentDefault(LPCWSTR pszQuery,
    365                 ASSOCIATIONTYPE atQueryType,
    366                 ASSOCIATIONLEVEL alQueryLevel,
    367                 LPWSTR *ppszAssociation) = 0;
    368         virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefault(LPCWSTR pszQuery,
    369                 ASSOCIATIONTYPE atQueryType,
    370                 ASSOCIATIONLEVEL alQueryLevel,
    371                 LPCWSTR pszAppRegistryName,
    372                 BOOL *pfDefault) = 0;
    373         virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefaultAll(ASSOCIATIONLEVEL alQueryLevel,
    374                 LPCWSTR pszAppRegistryName,
    375                 BOOL *pfDefault) = 0;
    376         virtual HRESULT STDMETHODCALLTYPE SetAppAsDefault(LPCWSTR pszAppRegistryName,
    377                 LPCWSTR pszSet,
    378                 ASSOCIATIONTYPE atSetType) = 0;
    379         virtual HRESULT STDMETHODCALLTYPE SetAppAsDefaultAll(LPCWSTR pszAppRegistryName) = 0;
    380         virtual HRESULT STDMETHODCALLTYPE ClearUserAssociations( void) = 0;
     299    virtual HRESULT STDMETHODCALLTYPE QueryCurrentDefault(LPCWSTR pszQuery,
     300    ASSOCIATIONTYPE atQueryType,
     301    ASSOCIATIONLEVEL alQueryLevel,
     302    LPWSTR * ppszAssociation) = 0;
     303    virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefault(LPCWSTR pszQuery,
     304    ASSOCIATIONTYPE atQueryType,
     305    ASSOCIATIONLEVEL alQueryLevel,
     306    LPCWSTR pszAppRegistryName,
     307    BOOL * pfDefault) = 0;
     308    virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefaultAll(ASSOCIATIONLEVEL alQueryLevel,
     309    LPCWSTR pszAppRegistryName,
     310    BOOL * pfDefault) = 0;
     311    virtual HRESULT STDMETHODCALLTYPE SetAppAsDefault(LPCWSTR pszAppRegistryName,
     312    LPCWSTR pszSet,
     313    ASSOCIATIONTYPE atSetType) = 0;
     314    virtual HRESULT STDMETHODCALLTYPE SetAppAsDefaultAll(LPCWSTR pszAppRegistryName) = 0;
     315    virtual HRESULT STDMETHODCALLTYPE ClearUserAssociations(void) = 0;
    381316};
    382317#endif
    383318
    384 static const CLSID CLSID_ApplicationAssociationReg = {0x591209C7,0x767B,0x42B2,{0x9F,0xBA,0x44,0xEE,0x46,0x15,0xF2,0xC7}};
    385 static const IID   IID_IApplicationAssociationReg  = {0x4e530b0a,0xe611,0x4c77,{0xa3,0xac,0x90,0x31,0xd0,0x22,0x28,0x1b}};
    386 
    387 int WinFileAssoc::VistaSetAppsAsDefault(const QStringList& fileExtensions)
    388 {
    389         IApplicationAssociationRegistration* pAAR;
    390         HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationReg,
    391                 NULL, CLSCTX_INPROC, IID_IApplicationAssociationReg,    (void**)&pAAR);
    392 
    393         int count = 0;
    394         if (SUCCEEDED(hr) && (pAAR != NULL))
    395         {
    396                 foreach(const QString& fileExtension, fileExtensions)
    397                 {
    398                         hr = pAAR->SetAppAsDefault((const WCHAR*)m_AppName.utf16(),
    399                                 (const WCHAR*)QString("." + fileExtension).utf16(),
    400                                 AT_FILEEXTENSION);
    401 
    402                         if (SUCCEEDED(hr))
    403                                 count++;
    404                 }
    405                 pAAR->Release();
    406         }
    407         return count;
    408 }
    409 
    410 bool WinFileAssoc::VistaGetDefaultApps(const QStringList &extensions, QStringList& registeredExt)
    411 {
    412         IApplicationAssociationRegistration* pAAR;
    413 
    414         HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationReg,
    415                 NULL, CLSCTX_INPROC, IID_IApplicationAssociationReg,    (void**)&pAAR);
    416 
    417         if (SUCCEEDED(hr) && (pAAR != NULL))
    418         {
    419                 foreach(const QString& fileExtension, extensions)
    420                 {
    421                         BOOL bIsDefault = FALSE;
    422                         hr = pAAR->QueryAppIsDefault((const WCHAR*)QString("." + fileExtension).utf16(),
    423                                 AT_FILEEXTENSION,
    424                                 AL_EFFECTIVE,
    425                                 (const WCHAR*)m_AppName.utf16(),
    426                                 &bIsDefault);
    427                         if (SUCCEEDED(hr) && bIsDefault)
    428                         {
    429                                 registeredExt.append(fileExtension);
    430                         }
    431                 }
    432 
    433                 pAAR->Release();
    434                 return true;
    435         }
    436         return false;
    437 }
    438 #else
    439 bool WinFileAssoc::VistaGetDefaultApps(const QStringList &extensions, QStringList& registeredExt)
    440 {
    441         return false;
    442 }
    443 
    444 int WinFileAssoc::VistaSetAppsAsDefault(const QStringList& extensions)
    445 {
    446         return 0;
    447 }
    448 #endif
    449 
     319static const CLSID CLSID_ApplicationAssociationReg = {0x591209C7, 0x767B, 0x42B2, {0x9F, 0xBA, 0x44, 0xEE, 0x46, 0x15, 0xF2, 0xC7}};
     320static const IID   IID_IApplicationAssociationReg  = {0x4e530b0a, 0xe611, 0x4c77, {0xa3, 0xac, 0x90, 0x31, 0xd0, 0x22, 0x28, 0x1b}};
     321
     322int WinFileAssoc::VistaSetAppsAsDefault(const QStringList &fileExtensions)
     323{
     324    IApplicationAssociationRegistration *pAAR;
     325    HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationReg,
     326                                  NULL, CLSCTX_INPROC, IID_IApplicationAssociationReg,  (void **)&pAAR);
     327
     328    int count = 0;
     329
     330    if (SUCCEEDED(hr) && (pAAR != NULL)) {
     331        foreach(const QString & fileExtension, fileExtensions) {
     332            hr = pAAR->SetAppAsDefault((const WCHAR *)m_AppName.utf16(),
     333                                       (const WCHAR *)QString("." + fileExtension).utf16(),
     334                                       AT_FILEEXTENSION);
     335
     336            if (SUCCEEDED(hr))
     337                count++;
     338        }
     339        pAAR->Release();
     340    }
     341
     342    return count;
     343}
     344
     345bool WinFileAssoc::VistaGetDefaultApps(const QStringList &extensions, QStringList &registeredExt)
     346{
     347    IApplicationAssociationRegistration *pAAR;
     348
     349    HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationReg,
     350                                  NULL, CLSCTX_INPROC, IID_IApplicationAssociationReg,  (void **)&pAAR);
     351
     352    if (SUCCEEDED(hr) && (pAAR != NULL)) {
     353        foreach(const QString & fileExtension, extensions) {
     354            BOOL bIsDefault = FALSE;
     355            hr = pAAR->QueryAppIsDefault((const WCHAR *)QString("." + fileExtension).utf16(),
     356                                         AT_FILEEXTENSION,
     357                                         AL_EFFECTIVE,
     358                                         (const WCHAR *)m_AppName.utf16(),
     359                                         &bIsDefault);
     360
     361            if (SUCCEEDED(hr) && bIsDefault) {
     362                registeredExt.append(fileExtension);
     363            }
     364        }
     365
     366        pAAR->Release();
     367        return true;
     368    }
     369
     370    return false;
     371}
Note: See TracChangeset for help on using the changeset viewer.