سؤال

قبل أن أصف مشكلتي ، إليك وصف للبرنامج (ihexplorer.exe) أنا أكتب:

هذا هو تطبيق C ++.

تطبيق iHexplorer هو أن يبدو مثل نافذة Windows Explorer قدر الإمكان. باستثناء واحد ، وهذا هو أن تشغيل الملفات من داخل نافذة Explorer هذه سيؤدي إلى فك تشفيرها أولاً إلى مجلد مؤقت للمستخدم ، ثم قم بتشغيل التطبيق المرتبط بملحق الملف وحذف الملف الموجود.

المشكلة التي أواجهها هي حذف التلقائي عند إغلاق الملف. هذا سيناريو:

  1. ينقر المستخدم المزدوج على ملف .txt مشفر في iHexplorer.
  2. يقوم iHexplorer بفك تشفير ملف .txt في الذاكرة ، ثم يكتبه إلى ٪ temp ٪ باستخدام :: createfile الذي يرجع مقبضًا إلى الملف (يجب على iHexplorer الحفاظ على هذا المقبض مفتوحًا على الأقل حتى يتم تنفيذ ملف .txt).

  3. ينفذ iHexplorer Shell ملف .txt (عن طريق الاتصال :: Shellexecute) من موقعه المؤقت.

  4. الآن Ihexplorer و Notepad لديهما مقبض على الملف المفتوح.
  5. يجب حذف الملف تلقائيًا عندما يغلق كل من IHexplorer و Notepad مقبضهما للملف ، حتى إذا تم إغلاق iHexplorer أولاً.

موافق. هذه حالة مستخدم أساسية تصف ما أريد أن يحدث. المشكلة التي أواجهها هي عندما أنا :: shellexecute () ، يقول Notepad "لا يمكن للعملية الوصول إلى الملف لأنه يتم استخدامه بواسطة عملية أخرى." (والتي ستكون ihexplorer). أحتاج إلى الالتفاف على هذا وأفتحه ، حتى بينما لا يزال لدي المقبض مفتوح في iHexplorer.

إليك ما يبدو عليه مكالمتي إلى :: createfile:

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);

لاحظ أنني استخدمت file_share_delete حتى تتمكن العمليات الأخرى (مثل المفكرة) من فتح الملف مع حذف الوصول.

لاحظ أنني استخدمت file_attribute_tporary | file_flag_delete_on_close السمات للإشارة إلى أن الملف مؤقت ويجب حذفه على إغلاق.

لاحظ أيضا المعلمة & SA. هذه هي بنية Security_attributes التي أستخدمها ، وأشعر (آمل) أن هذا هو المكان الذي تكمن فيه مشكلتي. فيما يلي الرمز مرة أخرى ، هذه المرة سأقوم بنشر الوظيفة بأكملها حتى تتمكن من معرفة كيفية ملء بنية 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;
}

أعتقد أنه إذا قمت بتحديد Security_Descriptor الصحيح الذي تم نقله إلى :: CreateFile ، فقد يعمل كما أريد. الرجاء المساعدة.

راجع للشغل ، تنتهي وظيفة إطلاق النار فقط إلى الاتصال :: Shellexecute لإطلاق الملف.

هل كانت مفيدة؟

المحلول

بعد إعادة قراءة مستند MSDN ، أخشى أن أجبت على سؤالي. file_flag_delete_on_close يتم حذف الملف فورًا بعد إغلاق جميع مقاببه ، بما في ذلك المقبض المحدد وأي مقابض مفتوحة أو مكررة أخرى. إذا كان هناك مقابض مفتوحة موجودة إلى ملف ، فإن المكالمة تفشل ما لم يتم فتحها جميعًا مع وضع مشاركة file_share_delete. تفشل الطلبات المفتوحة اللاحقة لفشل الملف ، ما لم يتم تحديد وضع مشاركة file_share_delete. في حالتي ، أشك في أن Notepad تطلب إذن file_share_delete ، بحيث لا يمكن فتح الملف

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top