📄 comctl32undoc.c
字号:
/*
* 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 + -