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

📄 comctl32undoc.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Undocumented functions from COMCTL32.DLL
 *
 * Copyright 1998 Eric Kohl
 *           1998 Juergen Schmied <j.schmied@metronet.de>
 *           2000 Eric Kohl for CodeWeavers
 *
 * 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
 *
 * NOTES
 *     All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
 *     Do NOT rely on names or contents of undocumented structures and types!!!
 *     These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
 *     COMCTL32.DLL (internally).
 *
 */
#include "config.h"
#include "wine/port.h"

#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "commctrl.h"
#include "objbase.h"
#include "winerror.h"

#include "wine/unicode.h"
#include "comctl32.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(commctrl);

static const WCHAR strMRUList[] = { 'M','R','U','L','i','s','t',0 };

/**************************************************************************
 * Alloc [COMCTL32.71]
 *
 * Allocates memory block from the dll's private heap
 *
 * PARAMS
 *     dwSize [I] size of the allocated memory block
 *
 * RETURNS
 *     Success: pointer to allocated memory block
 *     Failure: NULL
 */
LPVOID WINAPI Alloc (DWORD dwSize)
{
    return LocalAlloc( LMEM_ZEROINIT, dwSize );
}


/**************************************************************************
 * ReAlloc [COMCTL32.72]
 *
 * Changes the size of an allocated memory block or allocates a memory
 * block using the dll's private heap.
 *
 * PARAMS
 *     lpSrc  [I] pointer to memory block which will be resized
 *     dwSize [I] new size of the memory block.
 *
 * RETURNS
 *     Success: pointer to the resized memory block
 *     Failure: NULL
 *
 * NOTES
 *     If lpSrc is a NULL-pointer, then ReAlloc allocates a memory
 *     block like Alloc.
 */
LPVOID WINAPI ReAlloc (LPVOID lpSrc, DWORD dwSize)
{
    if (lpSrc)
        return LocalReAlloc( lpSrc, dwSize, LMEM_ZEROINIT | LMEM_MOVEABLE );
    else
        return LocalAlloc( LMEM_ZEROINIT, dwSize);
}


/**************************************************************************
 * Free [COMCTL32.73]
 *
 * Frees an allocated memory block from the dll's private heap.
 *
 * PARAMS
 *     lpMem [I] pointer to memory block which will be freed
 *
 * RETURNS
 *     Success: TRUE
 *     Failure: FALSE
 */
BOOL WINAPI Free (LPVOID lpMem)
{
    return !LocalFree( lpMem );
}


/**************************************************************************
 * GetSize [COMCTL32.74]
 *
 * Retrieves the size of the specified memory block from the dll's
 * private heap.
 *
 * PARAMS
 *     lpMem [I] pointer to an allocated memory block
 *
 * RETURNS
 *     Success: size of the specified memory block
 *     Failure: 0
 */
DWORD WINAPI GetSize (LPVOID lpMem)
{
    return LocalSize( lpMem );
}


/**************************************************************************
 * MRU-Functions  {COMCTL32}
 *
 * NOTES
 * The MRU-Api is a set of functions to manipulate lists of M.R.U. (Most Recently
 * Used) items. It is an undocumented Api that is used (at least) by the shell
 * and explorer to implement their recent documents feature.
 *
 * Since these functions are undocumented, they are unsupported by MS and
 * may change at any time.
 *
 * Internally, the list is implemented as a last in, last out list of items
 * persisted into the system registry under a caller chosen key. Each list
 * item is given a one character identifier in the Ascii range from 'a' to
 * '}'. A list of the identifiers in order from newest to oldest is stored
 * under the same key in a value named "MRUList".
 *
 * Items are re-ordered by changing the order of the values in the MRUList
 * value. When a new item is added, it becomes the new value of the oldest
 * identifier, and that identifier is moved to the front of the MRUList value.
 * 
 * Wine stores MRU-lists in the same registry format as Windows, so when
 * switching between the builtin and native comctl32.dll no problems or
 * incompatibilities should occur.
 *
 * The following undocumented structure is used to create an MRU-list:
 *|typedef INT (CALLBACK *MRUStringCmpFn)(LPCTSTR lhs, LPCTSTR rhs);
 *|typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
 *|
 *|typedef struct tagCREATEMRULIST
 *|{
 *|    DWORD   cbSize;
 *|    DWORD   nMaxItems;
 *|    DWORD   dwFlags;
 *|    HKEY    hKey;
 *|    LPTSTR  lpszSubKey;
 *|    PROC    lpfnCompare;
 *|} CREATEMRULIST, *LPCREATEMRULIST;
 *
 * MEMBERS
 *  cbSize      [I] The size of the CREATEMRULIST structure. This must be set
 *                  to sizeof(CREATEMRULIST) by the caller.
 *  nMaxItems   [I] The maximum number of items allowed in the list. Because
 *                  of the limited number of identifiers, this should be set to
 *                  a value from 1 to 30 by the caller.
 *  dwFlags     [I] If bit 0 is set, the list will be used to store binary
 *                  data, otherwise it is assumed to store strings. If bit 1
 *                  is set, every change made to the list will be reflected in
 *                  the registry immediately, otherwise changes will only be
 *                  written when the list is closed.
 *  hKey        [I] The registry key that the list should be written under.
 *                  This must be supplied by the caller.
 *  lpszSubKey  [I] A caller supplied name of a subkey under hKey to write
 *                  the list to. This may not be blank.
 *  lpfnCompare [I] A caller supplied comparison function, which may be either
 *                  an MRUStringCmpFn if dwFlags does not have bit 0 set, or a
 *                  MRUBinaryCmpFn otherwise.
 *
 * FUNCTIONS
 *  - Create an MRU-list with CreateMRUList() or CreateMRUListLazy().
 *  - Add items to an MRU-list with AddMRUString() or AddMRUData().
 *  - Remove items from an MRU-list with DelMRUString().
 *  - Find data in an MRU-list with FindMRUString() or FindMRUData().
 *  - Iterate through an MRU-list with EnumMRUList().
 *  - Free an MRU-list with FreeMRUList().
 */

typedef struct tagCREATEMRULISTA
{
    DWORD  cbSize;
    DWORD  nMaxItems;
    DWORD  dwFlags;
    HKEY   hKey;
    LPSTR  lpszSubKey;
    PROC   lpfnCompare;
} CREATEMRULISTA, *LPCREATEMRULISTA;

typedef struct tagCREATEMRULISTW
{
    DWORD   cbSize;
    DWORD   nMaxItems;
    DWORD   dwFlags;
    HKEY    hKey;
    LPWSTR  lpszSubKey;
    PROC    lpfnCompare;
} CREATEMRULISTW, *LPCREATEMRULISTW;

/* dwFlags */
#define MRUF_STRING_LIST  0 /* list will contain strings */
#define MRUF_BINARY_LIST  1 /* list will contain binary data */
#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */

/* If list is a string list lpfnCompare has the following prototype
 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
 * for binary lists the prototype is
 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
 * where cbData is the no. of bytes to compare.
 * Need to check what return value means identical - 0?
 */

typedef struct tagWINEMRUITEM
{
    DWORD          size;        /* size of data stored               */
    DWORD          itemFlag;    /* flags                             */
    BYTE           datastart;
} WINEMRUITEM, *LPWINEMRUITEM;

/* itemFlag */
#define WMRUIF_CHANGED   0x0001 /* this dataitem changed             */

typedef struct tagWINEMRULIST
{
    CREATEMRULISTW extview;     /* original create information       */
    BOOL           isUnicode;   /* is compare fn Unicode */
    DWORD          wineFlags;   /* internal flags                    */
    DWORD          cursize;     /* current size of realMRU           */
    LPWSTR         realMRU;     /* pointer to string of index names  */
    LPWINEMRUITEM  *array;      /* array of pointers to data         */
                                /* in 'a' to 'z' order               */
} WINEMRULIST, *LPWINEMRULIST;

/* wineFlags */
#define WMRUF_CHANGED  0x0001   /* MRU list has changed              */

/**************************************************************************
 *              MRU_SaveChanged (internal)
 *
 * Local MRU saving code
 */
static void MRU_SaveChanged ( LPWINEMRULIST mp )
{
    UINT i, err;
    HKEY newkey;
    WCHAR realname[2];
    LPWINEMRUITEM witem;

    /* or should we do the following instead of RegOpenKeyEx:
     */

    /* open the sub key */
    if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
			      0, KEY_WRITE, &newkey))) {
	/* not present - what to do ??? */
	ERR("Could not open key, error=%d, attempting to create\n",
	    err);
	if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
				    0,
				    NULL,
				    REG_OPTION_NON_VOLATILE,
				    KEY_READ | KEY_WRITE,
				    0,
				    &newkey,
				    0))) {
	    ERR("failed to create key /%s/, err=%d\n",
		debugstr_w(mp->extview.lpszSubKey), err);
	    return;
	}
    }
    if (mp->wineFlags & WMRUF_CHANGED) {
	mp->wineFlags &= ~WMRUF_CHANGED;
	err = RegSetValueExW(newkey, strMRUList, 0, REG_SZ, (LPBYTE)mp->realMRU,
			     (strlenW(mp->realMRU) + 1)*sizeof(WCHAR));
	if (err) {
	    ERR("error saving MRUList, err=%d\n", err);
	}
	TRACE("saving MRUList=/%s/\n", debugstr_w(mp->realMRU));
    }
    realname[1] = 0;
    for(i=0; i<mp->cursize; i++) {
	witem = mp->array[i];
	if (witem->itemFlag & WMRUIF_CHANGED) {
	    witem->itemFlag &= ~WMRUIF_CHANGED;
	    realname[0] = 'a' + i;
	    err = RegSetValueExW(newkey, realname, 0,
				 (mp->extview.dwFlags & MRUF_BINARY_LIST) ?
				 REG_BINARY : REG_SZ,
				 &witem->datastart, witem->size);
	    if (err) {
		ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err);
	    }
            TRACE("saving value for name /%s/ size=%d\n",
		  debugstr_w(realname), witem->size);
	}
    }
    RegCloseKey( newkey );
}

/**************************************************************************
 *              FreeMRUList [COMCTL32.152]
 *
 * Frees a most-recently-used items list.
 *
 * PARAMS
 *     hMRUList [I] Handle to list.
 *
 * RETURNS
 *     Nothing.
 */
void WINAPI FreeMRUList (HANDLE hMRUList)
{
    LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
    UINT i;

    TRACE("(%p)\n", hMRUList);
    if (!hMRUList)
        return;

    if (mp->wineFlags & WMRUF_CHANGED) {
	/* need to open key and then save the info */
	MRU_SaveChanged( mp );
    }

    for(i=0; i<mp->extview.nMaxItems; i++) {
	if (mp->array[i])
	    Free(mp->array[i]);
    }
    Free(mp->realMRU);
    Free(mp->array);
    Free(mp->extview.lpszSubKey);
    Free(mp);
}


/**************************************************************************
 *                  FindMRUData [COMCTL32.169]
 *
 * Searches binary list for item that matches lpData of length cbData.
 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
 * corresponding to item's reg. name will be stored in it ('a' -> 0).
 *
 * PARAMS
 *    hList [I] list handle
 *    lpData [I] data to find
 *    cbData [I] length of data
 *    lpRegNum [O] position in registry (maybe NULL)
 *
 * RETURNS
 *    Position in list 0 -> MRU.  -1 if item not found.
 */
INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData,

⌨️ 快捷键说明

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