⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shlfileop.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:
	       (bOnlySrc || (pszFiles2[0] != '\0')))
	{
	  if (NULL == StrPBrkW(pszFiles1, wWildcardChars))
	  {
	    if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(pszFiles1))
	      return FALSE;
	  }
	  pszFiles1 += lstrlenW(pszFiles1) + 1;
	  if (!bOnlySrc)
	    pszFiles2 += lstrlenW(pszFiles2) + 1;
	}
	return ((pszFiles1[0] == '\0') && (bOnlySrc || (pszFiles2[0] == '\0')));
}

/*************************************************************************
 *
 * SHNameTranslate HelperFunction for SHFileOperationA
 *
 * Translates a list of 0 terminated ASCII strings into Unicode. If *wString
 * is NULL, only the necessary size of the string is determined and returned,
 * otherwise the ASCII strings are copied into it and the buffer is increased
 * to point to the location after the final 0 termination char.
 */
DWORD SHNameTranslate(LPWSTR* wString, LPCWSTR* pWToFrom, BOOL more)
{
	DWORD size = 0, aSize = 0;
	LPCSTR aString = (LPCSTR)*pWToFrom;

	if (aString)
	{
	  do
	  {
	    size = lstrlenA(aString) + 1;
	    aSize += size;
	    aString += size;
	  } while ((size != 1) && more);
	  /* The two sizes might be different in the case of multibyte chars */
	  size = MultiByteToWideChar(CP_ACP, 0, aString, aSize, *wString, 0);
	  if (*wString) /* only in the second loop */
	  {
	    MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*pWToFrom, aSize, *wString, size);
	    *pWToFrom = *wString;
	    *wString += size;
	  }
	}
	return size;
}
/*************************************************************************
 * SHFileOperationA          [SHELL32.@]
 *
 * Function to copy, move, delete and create one or more files with optional
 * user prompts.
 *
 * PARAMS
 *  lpFileOp   [I/O] pointer to a structure containing all the necessary information
 *
 * RETURNS
 *  Success: zero
 *  Failure: nonzero
 *
 * NOTES
 *  exported by name
 */
int WINAPI SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp)
{
	SHFILEOPSTRUCTW nFileOp = *((LPSHFILEOPSTRUCTW)lpFileOp);
	int retCode = 0;
	DWORD size;
	LPWSTR ForFree = NULL, /* we change wString in SHNameTranslate and can't use it for freeing */
	       wString = NULL; /* we change this in SHNameTranslate */

	TRACE("\n");
	if (FO_DELETE == (nFileOp.wFunc & FO_MASK))
	  nFileOp.pTo = NULL; /* we need a NULL or a valid pointer for translation */
	if (!(nFileOp.fFlags & FOF_SIMPLEPROGRESS))
	  nFileOp.lpszProgressTitle = NULL; /* we need a NULL or a valid pointer for translation */
	while (1) /* every loop calculate size, second translate also, if we have storage for this */
	{
	  size = SHNameTranslate(&wString, &nFileOp.lpszProgressTitle, FALSE); /* no loop */
	  size += SHNameTranslate(&wString, &nFileOp.pFrom, TRUE); /* internal loop */
	  size += SHNameTranslate(&wString, &nFileOp.pTo, TRUE); /* internal loop */

	  if (ForFree)
	  {
	    retCode = SHFileOperationW(&nFileOp);
	    HeapFree(GetProcessHeap(), 0, ForFree); /* we cannot use wString, it was changed */
	    break;
	  }
	  else
	  {
	    wString = ForFree = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
	    if (ForFree) continue;
	    retCode = ERROR_OUTOFMEMORY;
	    nFileOp.fAnyOperationsAborted = TRUE;
	    SetLastError(retCode);
	    return retCode;
	  }
	}

	lpFileOp->hNameMappings = nFileOp.hNameMappings;
	lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted;
	return retCode;
}

static const char * debug_shfileops_flags( DWORD fFlags )
{
    return wine_dbg_sprintf( "%s%s%s%s%s%s%s%s%s%s%s%s%s",
	fFlags & FOF_MULTIDESTFILES ? "FOF_MULTIDESTFILES " : "",
	fFlags & FOF_CONFIRMMOUSE ? "FOF_CONFIRMMOUSE " : "",
	fFlags & FOF_SILENT ? "FOF_SILENT " : "",
	fFlags & FOF_RENAMEONCOLLISION ? "FOF_RENAMEONCOLLISION " : "",
	fFlags & FOF_NOCONFIRMATION ? "FOF_NOCONFIRMATION " : "",
	fFlags & FOF_WANTMAPPINGHANDLE ? "FOF_WANTMAPPINGHANDLE " : "",
	fFlags & FOF_ALLOWUNDO ? "FOF_ALLOWUNDO " : "",
	fFlags & FOF_FILESONLY ? "FOF_FILESONLY " : "",
	fFlags & FOF_SIMPLEPROGRESS ? "FOF_SIMPLEPROGRESS " : "",
	fFlags & FOF_NOCONFIRMMKDIR ? "FOF_NOCONFIRMMKDIR " : "",
	fFlags & FOF_NOERRORUI ? "FOF_NOERRORUI " : "",
	fFlags & FOF_NOCOPYSECURITYATTRIBS ? "FOF_NOCOPYSECURITYATTRIBS" : "",
	fFlags & 0xf000 ? "MORE-UNKNOWN-Flags" : "");
}

static const char * debug_shfileops_action( DWORD op )
{
    LPCSTR cFO_Name [] = {"FO_????","FO_MOVE","FO_COPY","FO_DELETE","FO_RENAME"};
    return wine_dbg_sprintf("%s", cFO_Name[ op ]);
}

#define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026
#define HIGH_ADR (LPWSTR)0xffffffff

/* handle the complete deletion of `pTempFrom` */
static int shfileops_delete(WIN32_FIND_DATAW *wfd,SHFILEOPSTRUCTW nFileOp, LPWSTR pFromFile,LPWSTR pTempFrom,HANDLE *hFind)

{
    LPWSTR lpFileName;
    BOOL    b_Mask = (NULL != StrPBrkW(&pFromFile[1], wWildcardChars));
    int retCode = 0;
    do
    {
        lpFileName = wfd->cAlternateFileName;
        if (!lpFileName[0])
            lpFileName = wfd->cFileName;
        if (IsDotDir(lpFileName) ||
                ((b_Mask) && IsAttribDir(wfd->dwFileAttributes) && (nFileOp.fFlags & FOF_FILESONLY)))
            continue;
        SHFileStrCpyCatW(&pFromFile[1], lpFileName, NULL);
        /* TODO: Check the SHELL_DeleteFileOrDirectoryW() function in shell32.dll */
        if (IsAttribFile(wfd->dwFileAttributes))
        {
            if(SHNotifyDeleteFileW(pTempFrom) != ERROR_SUCCESS)
            {
                nFileOp.fAnyOperationsAborted = TRUE;
                retCode = 0x78; /* value unknown */
            }
        }
        else if(!SHELL_DeleteDirectoryW(pTempFrom, (!(nFileOp.fFlags & FOF_NOCONFIRMATION))))
        {
            nFileOp.fAnyOperationsAborted = TRUE;
            retCode = 0x79; /* value unknown */
        }
    }
    while (!nFileOp.fAnyOperationsAborted && FindNextFileW(*hFind,wfd));
    FindClose(*hFind);
    *hFind = INVALID_HANDLE_VALUE;
    return retCode;
}

/*
 * Summary of flags:
 *
 * implemented flags:
 * FOF_MULTIDESTFILES, FOF_NOCONFIRMATION, FOF_FILESONLY
 *
 * unimplememented and ignored flags:
 * FOF_CONFIRMMOUSE, FOF_SILENT, FOF_NOCONFIRMMKDIR,
 *       FOF_SIMPLEPROGRESS, FOF_NOCOPYSECURITYATTRIBS
 *
 * partially implemented, breaks if file exists:
 * FOF_RENAMEONCOLLISION
 *
 * unimplemented and break if any other flag set:
 * FOF_ALLOWUNDO, FOF_WANTMAPPINGHANDLE
 */

static int shfileops_check_flags(SHFILEOPSTRUCTW nFileOp)
{
    FILEOP_FLAGS OFl = ((FILEOP_FLAGS)nFileOp.fFlags & 0xfff);
    long FuncSwitch = (nFileOp.wFunc & FO_MASK);
    long level= nFileOp.wFunc >> 4;

    TRACE("%s level=%ld nFileOp.fFlags=0x%x\n", 
            debug_shfileops_action(FuncSwitch), level, nFileOp.fFlags);
    /*    OFl &= (-1 - (FOF_MULTIDESTFILES | FOF_FILESONLY)); */
    /*    OFl ^= (FOF_SILENT | FOF_NOCONFIRMATION | FOF_SIMPLEPROGRESS | FOF_NOCONFIRMMKDIR); */
    OFl &= (~(FOF_MULTIDESTFILES | FOF_NOCONFIRMATION | FOF_FILESONLY));  /* implemented */
    OFl ^= (FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_NOCOPYSECURITYATTRIBS); /* ignored, if one */
    OFl &= (~FOF_SIMPLEPROGRESS); /* ignored, only with FOF_SILENT */
    if (OFl)
    {
        if (OFl & (~(FOF_CONFIRMMOUSE | FOF_SILENT | FOF_RENAMEONCOLLISION |
                        FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_NOCOPYSECURITYATTRIBS | FOF_ALLOWUNDO)))
        {
            FIXME("%s level=%ld lpFileOp->fFlags=0x%x not implemented, Aborted=TRUE, stub\n",
                    debug_shfileops_action(FuncSwitch), level, OFl);
            return 0x403; /* 1027, we need an extension to shlfileop */
        }
        else
        {
            TRACE("%s level=%ld lpFileOp->fFlags=0x%x not fully implemented, stub\n", 
                    debug_shfileops_action(FuncSwitch), level, OFl);
        } 
    } 
    return 0;
}

static int shfileops_do_operation(WIN32_FIND_DATAW wfd,SHFILEOPSTRUCTW *nFileOp, LPWSTR pToFile, LPWSTR pFromFile)
{
    LPWSTR lpFileName = wfd.cAlternateFileName;
    if (!lpFileName[0])
        lpFileName = wfd.cFileName;
    if (IsDotDir(lpFileName) ||
            (IsAttribDir(wfd.dwFileAttributes) && (nFileOp->fFlags & FOF_FILESONLY)))
        return 0; /* next name in pTempFrom(dir) */
    SHFileStrCpyCatW(&pToFile[1], lpFileName, NULL);
    SHFileStrCpyCatW(&pFromFile[1], lpFileName, NULL);
    return SHFileOperationW (nFileOp);
}

/* get attributes of the parent dir of pTemp and create the directory if it does not exists */
static DWORD shfileops_get_parent_attr2(LPWSTR pFile,LPWSTR pTemp,int flag,int *retCode)
{
    DWORD PathAttr;
    pFile[0] = '\0';
    PathAttr = GetFileAttributesW(pTemp);
    if ((PathAttr == INVALID_FILE_ATTRIBUTES) && flag)
    {
        /* create dir must be here, sample target D:\y\ *.* create with RC=10003 */
        if (SHNotifyCreateDirectoryW(pTemp, NULL))
        {
            *retCode = 0x73;/* value unknown */
            /*goto shfileop_end;*/
            return PathAttr;
        }
        PathAttr = GetFileAttributesW(pTemp);
    }
    pFile[0] = '\\';
    return PathAttr;
}

/* get attributes of the parent dir of pTemp without creating the directory if it does not exists */
static DWORD shfileops_get_parent_attr(LPWSTR pFile,LPWSTR pTemp)
{
    /* less efficient: 
    return shfileops_get_parent_attr2(pFile,pTemp,0,NULL);
    */
    DWORD PathAttr;
    pFile[0] = '\0';
    PathAttr = GetFileAttributesW(pTemp);
    pFile[0] = '\\';
    return PathAttr;
}

/*************************************************************************
 * SHFileOperationW          [SHELL32.@]
 *
 * See SHFileOperationA.
 */
int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
{
	SHFILEOPSTRUCTW nFileOp = *(lpFileOp);

	LPCWSTR pNextFrom = nFileOp.pFrom;
	LPCWSTR pNextTo = nFileOp.pTo;
	LPCWSTR pFrom = pNextFrom;
	LPCWSTR pTo = NULL;
	HANDLE hFind = INVALID_HANDLE_VALUE;
	WIN32_FIND_DATAW wfd;
	LPWSTR pTempFrom = NULL;
	LPWSTR pTempTo = NULL;
	LPWSTR pFromFile;
	LPWSTR pToFile = NULL;
	int retCode = 0;
	DWORD ToAttr;
	DWORD ToPathAttr;

	BOOL b_Multi = (nFileOp.fFlags & FOF_MULTIDESTFILES);

	BOOL b_MultiTo = (FO_DELETE != (lpFileOp->wFunc & FO_MASK));
	BOOL b_MultiPaired = (!b_MultiTo);
	BOOL b_MultiFrom = FALSE;
	BOOL not_overwrite;
	BOOL ask_overwrite;
	BOOL b_SameRoot;
	BOOL b_SameTailName;
	BOOL b_ToInvalidTail = FALSE;
	BOOL b_ToValid; /* for W98-Bug for FO_MOVE with source and target in same rootdrive */
	BOOL b_Mask;
	BOOL b_ToTailSlash = FALSE;

	long FuncSwitch = (nFileOp.wFunc & FO_MASK);
	long level= nFileOp.wFunc>>4;

	/*  default no error */
	nFileOp.fAnyOperationsAborted = FALSE;

	if ((FuncSwitch < FO_MOVE) || (FuncSwitch > FO_RENAME))
	    goto shfileop_end; /* no valid FunctionCode */

	if (level == 0)
            TRACE("%s: flags (0x%04x) : %s\n",
                debug_shfileops_action(FuncSwitch), nFileOp.fFlags,
                debug_shfileops_flags(nFileOp.fFlags) );

        /* establish when pTo is interpreted as the name of the destination file
         * or the directory where the Fromfile should be copied to.
         * This depends on:
         * (1) pTo points to the name of an existing directory;
         * (2) the flag FOF_MULTIDESTFILES is present;
         * (3) whether pFrom point to multiple filenames.
         *
         * Some experiments:
         *
         * destisdir               1 1 1 1 0 0 0 0
         * FOF_MULTIDESTFILES      1 1 0 0 1 1 0 0
         * multiple from filenames 1 0 1 0 1 0 1 0
         *                         ---------------
         * copy files to dir       1 0 1 1 0 0 1 0
         * create dir              0 0 0 0 0 0 1 0
         */

        retCode = shfileops_check_flags(nFileOp);
        if (retCode)
            goto shfileop_end;

        if ((pNextFrom) && (!(b_MultiTo) || (pNextTo)))
        {
	    nFileOp.pFrom = pTempFrom = HeapAlloc(GetProcessHeap(), 0, ((1 + 2 * (b_MultiTo)) * MAX_PATH + 6) * sizeof(WCHAR));
	    if (!pTempFrom)
	    {
                retCode = ERROR_OUTOFMEMORY;
                SetLastError(retCode);
                goto shfileop_end;
	    }
	    if (b_MultiTo)
                pTempTo = &pTempFrom[MAX_PATH + 4];
	    nFileOp.pTo = pTempTo;
	    ask_overwrite = (!(nFileOp.fFlags & FOF_NOCONFIRMATION) && !(nFileOp.fFlags & FOF_RENAMEONCOLLISION));
	    not_overwrite = (!(nFileOp.fFlags & FOF_NOCONFIRMATION) ||  (nFileOp.fFlags & FOF_RENAMEONCOLLISION));
        }
        else
        {
	    retCode = ERROR_SHELL_INTERNAL_FILE_NOT_FOUND;
	    goto shfileop_end;
        }
        /* need break at error before change sourcepointer */
        while(!nFileOp.fAnyOperationsAborted && (pNextFrom[0]))
        {
	    nFileOp.wFunc =  ((level + 1) << 4) + FuncSwitch;
	    nFileOp.fFlags = lpFileOp->fFlags;

	    if (b_MultiTo)
	    {
                pTo = pNextTo;
                pNextTo = &pNextTo[lstrlenW(pTo)+1];
                b_MultiTo = (b_Multi && pNextTo[0]);
	    }

	    pFrom = pNextFrom;
	    pNextFrom = &pNextFrom[lstrlenW(pNextFrom)+1];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -