virtcopy.c

来自「一个类似windows」· C语言 代码 · 共 781 行 · 第 1/2 页

C
781
字号
/*
 * SetupAPI virtual copy operations
 *
 * Copyright 2001 Andreas Mohr
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * FIXME: we now rely on builtin setupapi.dll for dialog resources.
 *        This is bad ! We ought to have 16bit resource handling working.
 */

#include "setupapi_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(setupapi);

static FARPROC16 VCP_Proc = NULL;
static LPARAM VCP_MsgRef = 0;

static BOOL VCP_opened = FALSE;

static VCPSTATUS vcp_status;

static HINSTANCE SETUPAPI_hInstance;

static WORD VCP_Callback( LPVOID obj, UINT16 msg, WPARAM16 wParam, LPARAM lParam, LPARAM lParamRef )
{
    WORD args[8];
    DWORD ret = OK;
    if (VCP_Proc)
    {
        args[7] = HIWORD(obj);
        args[6] = LOWORD(obj);
        args[5] = msg;
        args[4] = wParam;
        args[3] = HIWORD(lParam);
        args[2] = LOWORD(lParam);
        args[1] = HIWORD(lParamRef);
        args[0] = LOWORD(lParamRef);
        WOWCallback16Ex( (DWORD)VCP_Proc, WCB16_PASCAL, sizeof(args), args, &ret );
    }
    return (WORD)ret;
}

/****************************** VHSTR management ******************************/

/*
 * This is a totally braindead implementation for now;
 * I don't care about speed at all ! Size and implementation time
 * is much more important IMHO. I could have created some sophisticated
 * tree structure, but... what the hell ! :-)
 */
typedef struct {
    DWORD refcount;
    LPCSTR pStr;
} VHSTR_STRUCT;

static VHSTR_STRUCT **vhstrlist = NULL;
static VHSTR vhstr_alloc = 0;

#define VALID_VHSTR(x)		((x < vhstr_alloc) && (vhstrlist[x]) && (vhstrlist[x]->refcount))

/***********************************************************************
 *		vsmStringAdd (SETUPX.207)
 */
VHSTR WINAPI vsmStringAdd16(LPCSTR lpszName)
{
    VHSTR n;
    VHSTR index = 0xffff;
    HANDLE heap;

    TRACE("add string '%s'\n", lpszName);
    /* search whether string already inserted */
    TRACE("searching for existing string...\n");
    for (n = 0; n < vhstr_alloc; n++)
    {
	if ((vhstrlist[n]) && (vhstrlist[n]->refcount))
	{
		TRACE("checking item: %d\n", n);
	    if (!strcmp(vhstrlist[n]->pStr, lpszName))
	    {
		TRACE("found\n");
		vhstrlist[n]->refcount++;
		return n;
	    }
	}
    }

    /* hmm, not found yet, let's insert it */
    TRACE("inserting item\n");
    for (n = 0; n < vhstr_alloc; n++)
    {
	if ((!(vhstrlist[n])) || (!(vhstrlist[n]->refcount)))
	{
	    index = n;
	    break;
	}
    }
    heap = GetProcessHeap();
    if (n == vhstr_alloc) /* hmm, no free index found yet */
    {
	index = vhstr_alloc;
	vhstr_alloc += 20;

	if (vhstrlist)
	    vhstrlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, vhstrlist,
					sizeof(VHSTR_STRUCT *) * vhstr_alloc);
	else
	    vhstrlist = HeapAlloc(heap, HEAP_ZERO_MEMORY,
					sizeof(VHSTR_STRUCT *) * vhstr_alloc);
    }
    if (index == 0xffff)
	return 0xffff; /* failure */
    if (!vhstrlist[index])
	vhstrlist[index] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VHSTR_STRUCT));
    vhstrlist[index]->refcount = 1;
    vhstrlist[index]->pStr = HeapAlloc(heap, 0, strlen(lpszName)+1);
    strcpy((LPSTR)vhstrlist[index]->pStr, lpszName);
    return index;
}

/***********************************************************************
 *		vsmStringDelete (SETUPX.206)
 */
INT16 WINAPI vsmStringDelete16(VHSTR vhstr)
{
    if (VALID_VHSTR(vhstr))
    {
	vhstrlist[vhstr]->refcount--;
	if (!vhstrlist[vhstr]->refcount)
	{
	    HeapFree(GetProcessHeap(), 0, (LPSTR)vhstrlist[vhstr]->pStr);
	    vhstrlist[vhstr]->pStr = NULL;
	}
	return VCPN_OK;
    }

    /* string not found */
    return VCPN_FAIL;
}

/*
 * vsmStringFind() - not exported from a standard SETUPX.DLL, it seems
 */
VHSTR WINAPI vsmStringFind16(LPCSTR lpszName)
{
    WORD n;
    for (n = 0; n < vhstr_alloc; n++)
	if ((vhstrlist[n]) && (vhstrlist[n]->refcount) && (!strcmp(vhstrlist[n]->pStr, lpszName)))
	    return n;
    return 0xffff;
}

/***********************************************************************
 *		vsmGetStringName (SETUPX.205)
 *
 * Pretty correct, I guess
 */
INT16 WINAPI vsmGetStringName16(VHSTR vhstr, LPSTR lpszBuffer, int cbBuffer)
{
    if (VALID_VHSTR(vhstr))
    {
	int len = strlen(vhstrlist[vhstr]->pStr)+1;
	if (cbBuffer >= len)
	{
	    if (lpszBuffer)
	        strcpy(lpszBuffer, vhstrlist[vhstr]->pStr);
	    return len;
	}
    }
    return VCPN_FAIL;
}

/***********************************************************************
 *		vsmStringCompare (not exported from a standard SETUPX.DLL, it seems)
 */
INT16 WINAPI vsmStringCompare16(VHSTR vhstrA, VHSTR vhstrB)
{
    if ((!VALID_VHSTR(vhstrA)) || (!VALID_VHSTR(vhstrB)))
	return VCPN_FAIL; /* correct ? */
    return strcmp(vhstrlist[vhstrA]->pStr, vhstrlist[vhstrB]->pStr);
}

/***********************************************************************
 *		vsmGetStringRawName (SETUPX.208)
 */
LPCSTR WINAPI vsmGetStringRawName16(VHSTR vhstr)
{
    return (VALID_VHSTR(vhstr)) ? vhstrlist[vhstr]->pStr : NULL;
}


/***************************** VIRTNODE management ****************************/
static LPVIRTNODE *pvnlist = NULL;
static DWORD vn_num = 0;
static DWORD vn_last = 0;

static RETERR16 VCP_VirtnodeCreate(LPVCPFILESPEC vfsSrc, LPVCPFILESPEC vfsDst, WORD fl, LPARAM lParam, LPEXPANDVTBL lpExpandVtbl)
{
    HANDLE heap;
    LPVIRTNODE lpvn;
    RETERR16 cbres;

    while (vn_last < vn_num)
    {
	if (pvnlist[vn_last] == NULL)
	    break;
	vn_last++;
    }
    heap = GetProcessHeap();
    if (vn_last == vn_num)
    {
	vn_num += 20;
	if (pvnlist)
	    pvnlist = HeapReAlloc(heap, HEAP_ZERO_MEMORY, pvnlist,
		    		sizeof(LPVIRTNODE *) * vn_num);
	else
	    pvnlist = HeapAlloc(heap, HEAP_ZERO_MEMORY, 
		    		sizeof(LPVIRTNODE *) * vn_num);
    }
    pvnlist[vn_last] = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(VIRTNODE));
    lpvn = pvnlist[vn_last];
    vn_last++;

    lpvn->cbSize = sizeof(VIRTNODE);

    if (vfsSrc)
        memcpy(&lpvn->vfsSrc, vfsSrc, sizeof(VCPFILESPEC));

    if (vfsDst)
        memcpy(&lpvn->vfsDst, vfsDst, sizeof(VCPFILESPEC));

    lpvn->fl = fl;
    lpvn->lParam = lParam;
    lpvn->lpExpandVtbl = lpExpandVtbl;

    lpvn->vhstrDstFinalName = 0xffff; /* FIXME: what is this ? */

    cbres = VCP_Callback(lpvn, VCPM_NODECREATE, 0, 0, VCP_MsgRef);
    lpvn->fl |= VFNL_CREATED;
    cbres = VCP_Callback(lpvn, VCPM_NODEACCEPT, 0, 0, VCP_MsgRef);

    return OK;
}

#if 0
static BOOL VCP_VirtnodeDelete(LPVIRTNODE lpvnDel)
{
    DWORD n;
    RETERR16 cbres;

    for (n = 0; n < vn_last; n++)
    {
	if (pvnlist[n] == lpvnDel)
	{
	    cbres = VCP_Callback(lpvnDel, VCPM_NODEDESTROY, 0, 0, VCP_MsgRef);
	    HeapFree(GetProcessHeap(), 0, lpvnDel);
	    pvnlist[n] = NULL;
	    return TRUE;
	}
    }
    return FALSE;
}
#endif

/***********************************************************************
 *		VcpOpen (SETUPX.200)
 *
 * Sets up a virtual copy operation.
 * This means that functions such as GenInstall()
 * create a VIRTNODE struct for every file to be touched in a .INF file
 * instead of actually touching the file.
 * The actual copy/move/rename gets started when VcpClose or
 * VcpFlush is called; several different callbacks are made
 * (copy, rename, open, close, version conflicts, ...) on every file copied.
 */
RETERR16 WINAPI VcpOpen16(VIFPROC vifproc, LPARAM lparamMsgRef)
{
    TRACE("(%p, %08lx)\n", vifproc, lparamMsgRef);
    if (VCP_opened)
	return ERR_VCP_BUSY;

    VCP_Proc = (FARPROC16)vifproc;
    VCP_MsgRef = lparamMsgRef;

    /* load SETUPAPI needed for dialog resources etc. */
    SETUPAPI_hInstance = GetModuleHandleA("setupapi.dll");
    if (!SETUPAPI_hInstance)
    {
	ERR("Could not load sibling setupapi.dll\n");
	return ERR_VCP_NOMEM;
    }
    VCP_opened = TRUE;
    return OK;
}

/***********************************************************************
 *		VcpQueueCopy		[SETUPX.13]
 *
 * lpExpandVtbl seems to be deprecated.
 * fl are the CNFL_xxx and VNFL_xxx flags.
 * lParam are the VNLP_xxx flags.
 */
RETERR16 WINAPI VcpQueueCopy16(
	LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
	LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
	LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
	LPEXPANDVTBL lpExpandVtbl,
	WORD fl, LPARAM lParam
)
{
    VCPFILESPEC vfsSrc, vfsDst;

    if (!VCP_opened)
	return ERR_VCP_NOTOPEN;

    TRACE("srcdir: %s, srcfile: %s, dstdir: %s, dstfile: %s\n",
      lpszSrcDir, lpszSrcFileName, lpszDstDir, lpszDstFileName);

    TRACE("ldidSrc == %d, ldidDst == %d\n", ldidSrc, ldidDst);

    vfsSrc.ldid = ldidSrc;
    vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
    vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);

    vfsDst.ldid = ldidDst;
    vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
    vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);

    return VCP_VirtnodeCreate(&vfsSrc, &vfsDst, fl, lParam,
		    lpExpandVtbl);
}

/***********************************************************************
 *		VcpQueueDelete		[SETUPX.17]
 *
 * Is lParamRef the same as lParam in VcpQueueCopy ?
 * Damn docu !! Err... which docu ?
 */
RETERR16 WINAPI VcpQueueDelete16(
	LPCSTR lpszDstFileName,
	LPCSTR lpszDstDir,
	LOGDISKID16 ldidDst,
	LPARAM lParamRef
)
{
    VCPFILESPEC vfsDst;

    if (!VCP_opened)
	return ERR_VCP_NOTOPEN;

    vfsDst.ldid = ldidDst;
    vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);
    vfsDst.vhstrFileName = vsmStringAdd16(lpszDstFileName);

    return VCP_VirtnodeCreate(NULL, &vfsDst, VNFL_DELETE, lParamRef, 0);
}

/***********************************************************************
 *		VcpQueueRename		[SETUPX.204]
 *
 */
RETERR16 WINAPI VcpQueueRename16(
	LPCSTR lpszSrcFileName, LPCSTR lpszDstFileName,
	LPCSTR lpszSrcDir, LPCSTR lpszDstDir,
	LOGDISKID16 ldidSrc, LOGDISKID16 ldidDst,
	LPARAM lParam
)
{
    VCPFILESPEC vfsSrc, vfsDst;

    if (!VCP_opened)
	return ERR_VCP_NOTOPEN;

    vfsSrc.ldid = ldidSrc;
    vfsSrc.vhstrDir = vsmStringAdd16(lpszSrcDir);
    vfsSrc.vhstrFileName = vsmStringAdd16(lpszSrcFileName);

    vfsDst.ldid = ldidDst;
    vfsDst.vhstrDir = vsmStringAdd16(lpszDstDir);

⌨️ 快捷键说明

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