Question

Avant de décrire mon problème, voici une description du programme (IHExplorer.exe) J'cris:

Ceci est une application C ++.

L'application IHExplorer est de regarder autant comme une fenêtre Explorateur Windows que possible. À une exception près, et que le lancement de fichiers à partir de cette fenêtre Explorer les déchiffrer d'abord dans le dossier temporaire de l'utilisateur, puis lancer l'application associée à l'extension de fichier et supprimez le fichier à la fermeture.

Le problème que je vais avoir est la suppression automatique lorsque le fichier est fermé. Voici un scénario:

  1. double-clique l'utilisateur un fichier .txt crypté dans IHExplorer.
  2. IHExplorer décrypte le fichier txt en mémoire, puis écrit à% TEMP% à l'aide :: CreateFile qui retourne une poignée dans le fichier (IHExplorer doit garder cette poignée ouverte atleast jusqu'à ce que le fichier txt est shell Exécuté ).

  3. IHExplorer Shell Exécute le fichier txt (en appelant :: ShellExecute) à partir de son emplacement temporaire.

  4. Maintenant IHExplorer et bloc-notes ont tous deux une poignée dans le fichier ouvert.
  5. Le fichier doit être automatiquement supprimé lorsque les deux IHExplorer et notepad ont tous deux fermé leur poignée dans le fichier, même si IHExplorer ferme d'abord.
ok

. qui est un cas basical utilisateur qui décrit ce que je veux arriver. Le problème que j'ai est quand je :: ShellExecute (), le bloc-notes dit: « Le processus ne peut pas accéder au fichier car il est utilisé par un autre processus. » (Ce qui serait IHExplorer). Je dois contourner cela et ont ouvert le bloc-notes encore pendant que j'ai encore la poignée ouverte IHExplorer.

Voici ce que mon appel à :: CreateFile ressemble à:

DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
HANDLE hFile = ::CreateFile(strTempFile.c_str(), GENERIC_WRITE, dwShareMode, &sa, CREATE_NEW, dwFlagsAndAttributes, NULL);

Avis je FILE_SHARE_DELETE de sorte que d'autres processus (tels que le bloc-notes) peuvent ouvrir le fichier avec l'accès de suppression.

Notez que je le FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE attribue à indicicate le fichier est temporaire et devrait être supprimé à la fermeture.

Notez également le & sa paramètre. Ceci est la structure SECURITY_ATTRIBUTES que je me sers, et je me sens (espoir) c'est là est mon problème. Voici le code à nouveau, cette fois, je signalerai l'ensemble de la fonction afin que vous puissiez voir comment je remplir la structure SECURITY_ATTRIBUTES:

int CIHExplorerDoc::OpenFile(std::string strFileName, bool bIsFullPath) {
    std::string strFullFilePath;
    if(bIsFullPath) {
        strFullFilePath = strFileName;
        strFileName = IHawk::RemovePath(strFileName);
    }else {
        strFullFilePath = m_strDirectory + strFileName;
    }

    if(!HasEncryptionFileExtension(strFullFilePath)) {
        LaunchFile(strFullFilePath);
    }else {
        //it's an encrypted file, so open it and copy unencrypted file to temp.
        IHawk::EncryptedFileHandle hEncryptedFile(strFullFilePath.c_str(), true, theApp.GetKeyServer());
        if(hEncryptedFile.IsValid()) {
            std::string strTempFile = g_strTempFolder + IHawk::ChangeFileExtension(strFileName, "");

            //TODO: Determine what the LPSECURITY_ATTRIBUTES should be.

            SECURITY_ATTRIBUTES sa;
            SECURITY_DESCRIPTOR sd;

            if(!InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION)) {
                DWORD dwLastError = ::GetLastError();
                LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'.  Failed to initialize security descriptor.  GetLastError=" << dwLastError);
                return dwLastError;
            }

            if(!SetSecurityDescriptorDacl(
                &sd,    // A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the DACL
                TRUE,   // presence of a DACL in the security descriptor
                NULL,   // allows all access to the object
                FALSE   // DACL has been explicitly specified by a user
            )) 
            {
                DWORD dwLastError = ::GetLastError();
                LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'.  Failed to set security descriptor DACL.  GetLastError=" << dwLastError);
                return dwLastError;
            }

            if(!SetSecurityDescriptorGroup(
                &sd,    // A pointer to the SECURITY_DESCRIPTOR structure whose primary group is set by this function
                NULL,   // no primary group
                FALSE   // Indicates whether the primary group information was derived from a default mechanism
            ))
            {
                DWORD dwLastError = ::GetLastError();
                LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'.  Failed to set security descriptor primary group.  GetLastError=" << dwLastError);
                return dwLastError;
            }

            if(!SetSecurityDescriptorOwner(
                &sd,    // A pointer to the SECURITY_DESCRIPTOR structure whose owner is set by this function.
                NULL,   // If this parameter is NULL, the function clears the security descriptor's owner information. This marks the security descriptor as having no owner.
                FALSE   // Indicates whether the owner information is derived from a default mechanism.
            ))
            {
                DWORD dwLastError = ::GetLastError();
                LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'.  Failed to set security descriptor owner information.  GetLastError=" << dwLastError);
                return dwLastError;
            }

            if(!SetSecurityDescriptorSacl(
                &sd,    // A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the SACL
                FALSE,  // the security descriptor does not contain a SACL
                NULL,   // security descriptor has a NULL SACL
                FALSE   // A pointer to a flag that is set to the value of the SE_SACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure if a SACL exists for the security descriptor
            ))
            {
                DWORD dwLastError = ::GetLastError();
                LOG4CPLUS_ERROR(m_Logger, "Cannot launch file '" << strFullFilePath << "'.  Failed to set security descriptor SACL.  GetLastError=" << dwLastError);
                return dwLastError;
            }

            sa.nLength = sizeof(SECURITY_ATTRIBUTES);
            sa.lpSecurityDescriptor = &sd;
            sa.bInheritHandle = TRUE;

            DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
//          DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
            DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
            HANDLE hFile = ::CreateFile(strTempFile.c_str(), GENERIC_WRITE, dwShareMode, &sa, CREATE_NEW, dwFlagsAndAttributes, NULL);

            //verify we created the file.
            if(hFile == INVALID_HANDLE_VALUE) {
                DWORD dwLastError = ::GetLastError();
                return dwLastError;
            }

            //copy to temp
            char buffer[64*1024];
            size_t nBytesRead = hEncryptedFile.Read(buffer, sizeof(buffer));
            while(nBytesRead) {
                DWORD numBytesWritten;
                if(!::WriteFile(hFile, buffer, nBytesRead, &numBytesWritten, (LPOVERLAPPED) NULL)) {
                    DWORD dwLastError = ::GetLastError();
                    LOG4CPLUS_ERROR(m_Logger, "Failed to write file to %TEMP% folder.  GetLastError=" << dwLastError);
                    return dwLastError;
                }
                nBytesRead = hEncryptedFile.Read(buffer, sizeof(buffer));
            }
            hEncryptedFile.Close();

            //execute the file from temp.
            LaunchFile(strTempFile);
        }
    }
    return 0;
}

Je pense que si je déterminer le SECURITY_DESCRIPTOR correct de passer à :: CreateFile il peut fonctionner comme je veux. S'il vous plaît aider.

BTW, la fonction LaunchFile se termine juste par appeler :: ShellExecute pour lancer le fichier.

Était-ce utile?

La solution

Après re-lecture de la doc msdn, je crains d'avoir répondu à ma propre question. FILE_FLAG_DELETE_ON_CLOSE Le fichier doit être supprimé immédiatement après l'ensemble de ses poignées sont fermées, qui comprend la poignée spécifié et tous les autres descripteurs ouverts ou doubles. S'il y a des poignées ouvertes existantes dans un fichier, l'appel échoue à moins qu'ils étaient tous ouverts avec le mode de partage de FILE_SHARE_DELETE. demandes ouvertes suivantes pour le fichier échouent, à moins que le mode de partage de FILE_SHARE_DELETE est spécifiée. Dans mon cas, je doute notepad demande la permission de FILE_SHARE_DELETE, donc il ne peut pas ouvrir le fichier

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top