ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

comctl32undoc.c
Go to the documentation of this file.
00001 /*
00002  * Undocumented functions from COMCTL32.DLL
00003  *
00004  * Copyright 1998 Eric Kohl
00005  *           1998 Juergen Schmied <j.schmied@metronet.de>
00006  *           2000 Eric Kohl for CodeWeavers
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  *
00022  * NOTES
00023  *     All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
00024  *     Do NOT rely on names or contents of undocumented structures and types!!!
00025  *     These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
00026  *     COMCTL32.DLL (internally).
00027  *
00028  */
00029 #include "config.h"
00030 #include "wine/port.h"
00031 
00032 #include <stdarg.h>
00033 #include <string.h>
00034 #include <ctype.h>
00035 #include <limits.h>
00036 
00037 #define COBJMACROS
00038 #define NONAMELESSUNION
00039 #define NONAMELESSSTRUCT
00040 
00041 #include "windef.h"
00042 #include "winbase.h"
00043 #include "wingdi.h"
00044 #include "winuser.h"
00045 #include "winnls.h"
00046 #include "winreg.h"
00047 #include "commctrl.h"
00048 #include "objbase.h"
00049 #include "winerror.h"
00050 
00051 #include "wine/unicode.h"
00052 #include "comctl32.h"
00053 
00054 #include "wine/debug.h"
00055 
00056 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
00057 
00058 static const WCHAR strMRUList[] = { 'M','R','U','L','i','s','t',0 };
00059 
00060 /**************************************************************************
00061  * Alloc [COMCTL32.71]
00062  *
00063  * Allocates memory block from the dll's private heap
00064  *
00065  * PARAMS
00066  *     dwSize [I] size of the allocated memory block
00067  *
00068  * RETURNS
00069  *     Success: pointer to allocated memory block
00070  *     Failure: NULL
00071  */
00072 LPVOID WINAPI Alloc (DWORD dwSize)
00073 {
00074     return LocalAlloc( LMEM_ZEROINIT, dwSize );
00075 }
00076 
00077 
00078 /**************************************************************************
00079  * ReAlloc [COMCTL32.72]
00080  *
00081  * Changes the size of an allocated memory block or allocates a memory
00082  * block using the dll's private heap.
00083  *
00084  * PARAMS
00085  *     lpSrc  [I] pointer to memory block which will be resized
00086  *     dwSize [I] new size of the memory block.
00087  *
00088  * RETURNS
00089  *     Success: pointer to the resized memory block
00090  *     Failure: NULL
00091  *
00092  * NOTES
00093  *     If lpSrc is a NULL-pointer, then ReAlloc allocates a memory
00094  *     block like Alloc.
00095  */
00096 LPVOID WINAPI ReAlloc (LPVOID lpSrc, DWORD dwSize)
00097 {
00098     if (lpSrc)
00099         return LocalReAlloc( lpSrc, dwSize, LMEM_ZEROINIT | LMEM_MOVEABLE );
00100     else
00101         return LocalAlloc( LMEM_ZEROINIT, dwSize);
00102 }
00103 
00104 
00105 /**************************************************************************
00106  * Free [COMCTL32.73]
00107  *
00108  * Frees an allocated memory block from the dll's private heap.
00109  *
00110  * PARAMS
00111  *     lpMem [I] pointer to memory block which will be freed
00112  *
00113  * RETURNS
00114  *     Success: TRUE
00115  *     Failure: FALSE
00116  */
00117 BOOL WINAPI Free (LPVOID lpMem)
00118 {
00119     return !LocalFree( lpMem );
00120 }
00121 
00122 
00123 /**************************************************************************
00124  * GetSize [COMCTL32.74]
00125  *
00126  * Retrieves the size of the specified memory block from the dll's
00127  * private heap.
00128  *
00129  * PARAMS
00130  *     lpMem [I] pointer to an allocated memory block
00131  *
00132  * RETURNS
00133  *     Success: size of the specified memory block
00134  *     Failure: 0
00135  */
00136 DWORD WINAPI GetSize (LPVOID lpMem)
00137 {
00138     return LocalSize( lpMem );
00139 }
00140 
00141 
00142 /**************************************************************************
00143  * MRU-Functions  {COMCTL32}
00144  *
00145  * NOTES
00146  * The MRU-Api is a set of functions to manipulate lists of M.R.U. (Most Recently
00147  * Used) items. It is an undocumented Api that is used (at least) by the shell
00148  * and explorer to implement their recent documents feature.
00149  *
00150  * Since these functions are undocumented, they are unsupported by MS and
00151  * may change at any time.
00152  *
00153  * Internally, the list is implemented as a last in, last out list of items
00154  * persisted into the system registry under a caller chosen key. Each list
00155  * item is given a one character identifier in the Ascii range from 'a' to
00156  * '}'. A list of the identifiers in order from newest to oldest is stored
00157  * under the same key in a value named "MRUList".
00158  *
00159  * Items are re-ordered by changing the order of the values in the MRUList
00160  * value. When a new item is added, it becomes the new value of the oldest
00161  * identifier, and that identifier is moved to the front of the MRUList value.
00162  * 
00163  * Wine stores MRU-lists in the same registry format as Windows, so when
00164  * switching between the builtin and native comctl32.dll no problems or
00165  * incompatibilities should occur.
00166  *
00167  * The following undocumented structure is used to create an MRU-list:
00168  *|typedef INT (CALLBACK *MRUStringCmpFn)(LPCTSTR lhs, LPCTSTR rhs);
00169  *|typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
00170  *|
00171  *|typedef struct tagMRUINFO
00172  *|{
00173  *|    DWORD   cbSize;
00174  *|    UINT    uMax;
00175  *|    UINT    fFlags;
00176  *|    HKEY    hKey;
00177  *|    LPTSTR  lpszSubKey;
00178  *|    PROC    lpfnCompare;
00179  *|} MRUINFO, *LPMRUINFO;
00180  *
00181  * MEMBERS
00182  *  cbSize      [I] The size of the MRUINFO structure. This must be set
00183  *                  to sizeof(MRUINFO) by the caller.
00184  *  uMax        [I] The maximum number of items allowed in the list. Because
00185  *                  of the limited number of identifiers, this should be set to
00186  *                  a value from 1 to 30 by the caller.
00187  *  fFlags      [I] If bit 0 is set, the list will be used to store binary
00188  *                  data, otherwise it is assumed to store strings. If bit 1
00189  *                  is set, every change made to the list will be reflected in
00190  *                  the registry immediately, otherwise changes will only be
00191  *                  written when the list is closed.
00192  *  hKey        [I] The registry key that the list should be written under.
00193  *                  This must be supplied by the caller.
00194  *  lpszSubKey  [I] A caller supplied name of a subkey under hKey to write
00195  *                  the list to. This may not be blank.
00196  *  lpfnCompare [I] A caller supplied comparison function, which may be either
00197  *                  an MRUStringCmpFn if dwFlags does not have bit 0 set, or a
00198  *                  MRUBinaryCmpFn otherwise.
00199  *
00200  * FUNCTIONS
00201  *  - Create an MRU-list with CreateMRUList() or CreateMRUListLazy().
00202  *  - Add items to an MRU-list with AddMRUString() or AddMRUData().
00203  *  - Remove items from an MRU-list with DelMRUString().
00204  *  - Find data in an MRU-list with FindMRUString() or FindMRUData().
00205  *  - Iterate through an MRU-list with EnumMRUList().
00206  *  - Free an MRU-list with FreeMRUList().
00207  */
00208 
00209 typedef INT (CALLBACK *MRUStringCmpFnA)(LPCSTR lhs, LPCSTR rhs);
00210 typedef INT (CALLBACK *MRUStringCmpFnW)(LPCWSTR lhs, LPCWSTR rhs);
00211 typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
00212 
00213 typedef struct tagMRUINFOA
00214 {
00215     DWORD  cbSize;
00216     UINT   uMax;
00217     UINT   fFlags;
00218     HKEY   hKey;
00219     LPSTR  lpszSubKey;
00220     union
00221     {
00222         MRUStringCmpFnA string_cmpfn;
00223         MRUBinaryCmpFn  binary_cmpfn;
00224     } u;
00225 } MRUINFOA, *LPMRUINFOA;
00226 
00227 typedef struct tagMRUINFOW
00228 {
00229     DWORD   cbSize;
00230     UINT    uMax;
00231     UINT    fFlags;
00232     HKEY    hKey;
00233     LPWSTR  lpszSubKey;
00234     union
00235     {
00236         MRUStringCmpFnW string_cmpfn;
00237         MRUBinaryCmpFn  binary_cmpfn;
00238     } u;
00239 } MRUINFOW, *LPMRUINFOW;
00240 
00241 /* MRUINFO.fFlags */
00242 #define MRU_STRING     0 /* list will contain strings */
00243 #define MRU_BINARY     1 /* list will contain binary data */
00244 #define MRU_CACHEWRITE 2 /* only save list order to reg. is FreeMRUList */
00245 
00246 /* If list is a string list lpfnCompare has the following prototype
00247  * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
00248  * for binary lists the prototype is
00249  * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
00250  * where cbData is the no. of bytes to compare.
00251  * Need to check what return value means identical - 0?
00252  */
00253 
00254 typedef struct tagWINEMRUITEM
00255 {
00256     DWORD          size;        /* size of data stored               */
00257     DWORD          itemFlag;    /* flags                             */
00258     BYTE           datastart;
00259 } WINEMRUITEM, *LPWINEMRUITEM;
00260 
00261 /* itemFlag */
00262 #define WMRUIF_CHANGED   0x0001 /* this dataitem changed             */
00263 
00264 typedef struct tagWINEMRULIST
00265 {
00266     MRUINFOW       extview;     /* original create information       */
00267     BOOL           isUnicode;   /* is compare fn Unicode */
00268     DWORD          wineFlags;   /* internal flags                    */
00269     DWORD          cursize;     /* current size of realMRU           */
00270     LPWSTR         realMRU;     /* pointer to string of index names  */
00271     LPWINEMRUITEM  *array;      /* array of pointers to data         */
00272                                 /* in 'a' to 'z' order               */
00273 } WINEMRULIST, *LPWINEMRULIST;
00274 
00275 /* wineFlags */
00276 #define WMRUF_CHANGED  0x0001   /* MRU list has changed              */
00277 
00278 /**************************************************************************
00279  *              MRU_SaveChanged (internal)
00280  *
00281  * Local MRU saving code
00282  */
00283 static void MRU_SaveChanged ( LPWINEMRULIST mp )
00284 {
00285     UINT i, err;
00286     HKEY newkey;
00287     WCHAR realname[2];
00288     LPWINEMRUITEM witem;
00289 
00290     /* or should we do the following instead of RegOpenKeyEx:
00291      */
00292 
00293     /* open the sub key */
00294     if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
00295                   0, KEY_WRITE, &newkey))) {
00296     /* not present - what to do ??? */
00297     ERR("Could not open key, error=%d, attempting to create\n",
00298         err);
00299     if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
00300                     0,
00301                     NULL,
00302                     REG_OPTION_NON_VOLATILE,
00303                     KEY_READ | KEY_WRITE,
00304                     0,
00305                     &newkey,
00306                     0))) {
00307         ERR("failed to create key /%s/, err=%d\n",
00308         debugstr_w(mp->extview.lpszSubKey), err);
00309         return;
00310     }
00311     }
00312     if (mp->wineFlags & WMRUF_CHANGED) {
00313     mp->wineFlags &= ~WMRUF_CHANGED;
00314     err = RegSetValueExW(newkey, strMRUList, 0, REG_SZ, (LPBYTE)mp->realMRU,
00315                  (strlenW(mp->realMRU) + 1)*sizeof(WCHAR));
00316     if (err) {
00317         ERR("error saving MRUList, err=%d\n", err);
00318     }
00319     TRACE("saving MRUList=/%s/\n", debugstr_w(mp->realMRU));
00320     }
00321     realname[1] = 0;
00322     for(i=0; i<mp->cursize; i++) {
00323     witem = mp->array[i];
00324     if (witem->itemFlag & WMRUIF_CHANGED) {
00325         witem->itemFlag &= ~WMRUIF_CHANGED;
00326         realname[0] = 'a' + i;
00327         err = RegSetValueExW(newkey, realname, 0,
00328                  (mp->extview.fFlags & MRU_BINARY) ?
00329                  REG_BINARY : REG_SZ,
00330                  &witem->datastart, witem->size);
00331         if (err) {
00332         ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err);
00333         }
00334             TRACE("saving value for name /%s/ size=%d\n",
00335           debugstr_w(realname), witem->size);
00336     }
00337     }
00338     RegCloseKey( newkey );
00339 }
00340 
00341 /**************************************************************************
00342  *              FreeMRUList [COMCTL32.152]
00343  *
00344  * Frees a most-recently-used items list.
00345  *
00346  * PARAMS
00347  *     hMRUList [I] Handle to list.
00348  *
00349  * RETURNS
00350  *     Nothing.
00351  */
00352 void WINAPI FreeMRUList (HANDLE hMRUList)
00353 {
00354     LPWINEMRULIST mp = hMRUList;
00355     UINT i;
00356 
00357     TRACE("(%p)\n", hMRUList);
00358     if (!hMRUList)
00359         return;
00360 
00361     if (mp->wineFlags & WMRUF_CHANGED) {
00362     /* need to open key and then save the info */
00363     MRU_SaveChanged( mp );
00364     }
00365 
00366     for(i=0; i<mp->extview.uMax; i++)
00367         Free(mp->array[i]);
00368 
00369     Free(mp->realMRU);
00370     Free(mp->array);
00371     Free(mp->extview.lpszSubKey);
00372     Free(mp);
00373 }
00374 
00375 
00376 /**************************************************************************
00377  *                  FindMRUData [COMCTL32.169]
00378  *
00379  * Searches binary list for item that matches lpData of length cbData.
00380  * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
00381  * corresponding to item's reg. name will be stored in it ('a' -> 0).
00382  *
00383  * PARAMS
00384  *    hList [I] list handle
00385  *    lpData [I] data to find
00386  *    cbData [I] length of data
00387  *    lpRegNum [O] position in registry (maybe NULL)
00388  *
00389  * RETURNS
00390  *    Position in list 0 -> MRU.  -1 if item not found.
00391  */
00392 INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData,
00393                         LPINT lpRegNum)
00394 {
00395     const WINEMRULIST *mp = hList;
00396     INT ret;
00397     UINT i;
00398     LPSTR dataA = NULL;
00399 
00400     if (!mp || !mp->extview.u.string_cmpfn)
00401     return -1;
00402 
00403     if(!(mp->extview.fFlags & MRU_BINARY) && !mp->isUnicode) {
00404         DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1,
00405                     NULL, 0, NULL, NULL);
00406     dataA = Alloc(len);
00407     WideCharToMultiByte(CP_ACP, 0, lpData, -1, dataA, len, NULL, NULL);
00408     }
00409 
00410     for(i=0; i<mp->cursize; i++) {
00411     if (mp->extview.fFlags & MRU_BINARY) {
00412         if (!mp->extview.u.binary_cmpfn(lpData, &mp->array[i]->datastart, cbData))
00413         break;
00414     }
00415     else {
00416         if(mp->isUnicode) {
00417             if (!mp->extview.u.string_cmpfn(lpData, (LPWSTR)&mp->array[i]->datastart))
00418             break;
00419         } else {
00420             DWORD len = WideCharToMultiByte(CP_ACP, 0,
00421                         (LPWSTR)&mp->array[i]->datastart, -1,
00422                         NULL, 0, NULL, NULL);
00423         LPSTR itemA = Alloc(len);
00424         INT cmp;
00425         WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&mp->array[i]->datastart, -1,
00426                     itemA, len, NULL, NULL);
00427 
00428             cmp = mp->extview.u.string_cmpfn((LPWSTR)dataA, (LPWSTR)itemA);
00429         Free(itemA);
00430         if(!cmp)
00431             break;
00432         }
00433     }
00434     }
00435     Free(dataA);
00436     if (i < mp->cursize)
00437     ret = i;
00438     else
00439     ret = -1;
00440     if (lpRegNum && (ret != -1))
00441     *lpRegNum = 'a' + i;
00442 
00443     TRACE("(%p, %p, %d, %p) returning %d\n",
00444        hList, lpData, cbData, lpRegNum, ret);
00445 
00446     return ret;
00447 }
00448 
00449 
00450 /**************************************************************************
00451  *              AddMRUData [COMCTL32.167]
00452  *
00453  * Add item to MRU binary list.  If item already exists in list then it is
00454  * simply moved up to the top of the list and not added again.  If list is
00455  * full then the least recently used item is removed to make room.
00456  *
00457  * PARAMS
00458  *     hList [I] Handle to list.
00459  *     lpData [I] ptr to data to add.
00460  *     cbData [I] no. of bytes of data.
00461  *
00462  * RETURNS
00463  *     No. corresponding to registry name where value is stored 'a' -> 0 etc.
00464  *     -1 on error.
00465  */
00466 INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
00467 {
00468     LPWINEMRULIST mp = hList;
00469     LPWINEMRUITEM witem;
00470     INT i, replace;
00471 
00472     if ((replace = FindMRUData (hList, lpData, cbData, NULL)) >= 0) {
00473         /* Item exists, just move it to the front */
00474         LPWSTR pos = strchrW(mp->realMRU, replace + 'a');
00475         while (pos > mp->realMRU)
00476         {
00477             pos[0] = pos[-1];
00478             pos--;
00479         }
00480     }
00481     else {
00482     /* either add a new entry or replace oldest */
00483     if (mp->cursize < mp->extview.uMax) {
00484         /* Add in a new item */
00485         replace = mp->cursize;
00486         mp->cursize++;
00487     }
00488     else {
00489         /* get the oldest entry and replace data */
00490         replace = mp->realMRU[mp->cursize - 1] - 'a';
00491         Free(mp->array[replace]);
00492     }
00493 
00494         /* Allocate space for new item and move in the data */
00495         mp->array[replace] = witem = Alloc(cbData + sizeof(WINEMRUITEM));
00496         witem->itemFlag |= WMRUIF_CHANGED;
00497         witem->size = cbData;
00498         memcpy( &witem->datastart, lpData, cbData);
00499 
00500         /* now rotate MRU list */
00501         for(i=mp->cursize-1; i>=1; i--)
00502             mp->realMRU[i] = mp->realMRU[i-1];
00503     }
00504 
00505     /* The new item gets the front spot */
00506     mp->wineFlags |= WMRUF_CHANGED;
00507     mp->realMRU[0] = replace + 'a';
00508 
00509     TRACE("(%p, %p, %d) adding data, /%c/ now most current\n",
00510           hList, lpData, cbData, replace+'a');
00511 
00512     if (!(mp->extview.fFlags & MRU_CACHEWRITE)) {
00513     /* save changed stuff right now */
00514     MRU_SaveChanged( mp );
00515     }
00516 
00517     return replace;
00518 }
00519 
00520 /**************************************************************************
00521  *              AddMRUStringW [COMCTL32.401]
00522  *
00523  * Add an item to an MRU string list.
00524  *
00525  * PARAMS
00526  *     hList      [I] Handle to list.
00527  *     lpszString [I] The string to add.
00528  *
00529  * RETURNS
00530  *   Success: The number corresponding to the registry name where the string
00531  *            has been stored (0 maps to 'a', 1 to 'b' and so on).
00532  *   Failure: -1, if hList is NULL or memory allocation fails. If lpszString
00533  *            is invalid, the function returns 0, and GetLastError() returns
00534  *            ERROR_INVALID_PARAMETER. The last error value is set only in
00535  *            this case.
00536  *
00537  * NOTES
00538  *  -If lpszString exists in the list already, it is moved to the top of the
00539  *   MRU list (it is not duplicated).
00540  *  -If the list is full the least recently used list entry is replaced with
00541  *   lpszString.
00542  *  -If this function returns 0 you should check the last error value to
00543  *   ensure the call really succeeded.
00544  */
00545 INT WINAPI AddMRUStringW(HANDLE hList, LPCWSTR lpszString)
00546 {
00547     TRACE("(%p,%s)\n", hList, debugstr_w(lpszString));
00548 
00549     if (!hList)
00550         return -1;
00551 
00552     if (!lpszString || IsBadStringPtrW(lpszString, -1))
00553     {
00554         SetLastError(ERROR_INVALID_PARAMETER);
00555         return 0;
00556     }
00557 
00558     return AddMRUData(hList, lpszString,
00559                       (strlenW(lpszString) + 1) * sizeof(WCHAR));
00560 }
00561 
00562 /**************************************************************************
00563  *              AddMRUStringA [COMCTL32.153]
00564  *
00565  * See AddMRUStringW.
00566  */
00567 INT WINAPI AddMRUStringA(HANDLE hList, LPCSTR lpszString)
00568 {
00569     DWORD len;
00570     LPWSTR stringW;
00571     INT ret;
00572 
00573     TRACE("(%p,%s)\n", hList, debugstr_a(lpszString));
00574 
00575     if (!hList)
00576         return -1;
00577 
00578     if (IsBadStringPtrA(lpszString, -1))
00579     {
00580         SetLastError(ERROR_INVALID_PARAMETER);
00581     return 0;
00582     }
00583 
00584     len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0) * sizeof(WCHAR);
00585     stringW = Alloc(len);
00586     if (!stringW)
00587         return -1;
00588 
00589     MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len/sizeof(WCHAR));
00590     ret = AddMRUData(hList, stringW, len);
00591     Free(stringW);
00592     return ret;
00593 }
00594 
00595 /**************************************************************************
00596  *              DelMRUString [COMCTL32.156]
00597  *
00598  * Removes item from either string or binary list (despite its name)
00599  *
00600  * PARAMS
00601  *    hList [I] list handle
00602  *    nItemPos [I] item position to remove 0 -> MRU
00603  *
00604  * RETURNS
00605  *    TRUE if successful, FALSE if nItemPos is out of range.
00606  */
00607 BOOL WINAPI DelMRUString(HANDLE hList, INT nItemPos)
00608 {
00609     FIXME("(%p, %d): stub\n", hList, nItemPos);
00610     return TRUE;
00611 }
00612 
00613 /**************************************************************************
00614  *                  FindMRUStringW [COMCTL32.402]
00615  *
00616  * See FindMRUStringA.
00617  */
00618 INT WINAPI FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
00619 {
00620   return FindMRUData(hList, lpszString,
00621                      (lstrlenW(lpszString) + 1) * sizeof(WCHAR), lpRegNum);
00622 }
00623 
00624 /**************************************************************************
00625  *                  FindMRUStringA [COMCTL32.155]
00626  *
00627  * Searches string list for item that matches lpszString.
00628  * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
00629  * corresponding to item's reg. name will be stored in it ('a' -> 0).
00630  *
00631  * PARAMS
00632  *    hList [I] list handle
00633  *    lpszString [I] string to find
00634  *    lpRegNum [O] position in registry (maybe NULL)
00635  *
00636  * RETURNS
00637  *    Position in list 0 -> MRU.  -1 if item not found.
00638  */
00639 INT WINAPI FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
00640 {
00641     DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0);
00642     LPWSTR stringW = Alloc(len * sizeof(WCHAR));
00643     INT ret;
00644 
00645     MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len);
00646     ret = FindMRUData(hList, stringW, len * sizeof(WCHAR), lpRegNum);
00647     Free(stringW);
00648     return ret;
00649 }
00650 
00651 /*************************************************************************
00652  *                 create_mru_list (internal)
00653  */
00654 static HANDLE create_mru_list(LPWINEMRULIST mp)
00655 {
00656     UINT i, err;
00657     HKEY newkey;
00658     DWORD datasize, dwdisp;
00659     WCHAR realname[2];
00660     LPWINEMRUITEM witem;
00661     DWORD type;
00662 
00663     /* get space to save indices that will turn into names
00664      * but in order of most to least recently used
00665      */
00666     mp->realMRU = Alloc((mp->extview.uMax + 2) * sizeof(WCHAR));
00667 
00668     /* get space to save pointers to actual data in order of
00669      * 'a' to 'z' (0 to n).
00670      */
00671     mp->array = Alloc(mp->extview.uMax * sizeof(LPVOID));
00672 
00673     /* open the sub key */
00674     if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
00675                     0,
00676                 NULL,
00677                 REG_OPTION_NON_VOLATILE,
00678                 KEY_READ | KEY_WRITE,
00679                                 0,
00680                 &newkey,
00681                 &dwdisp))) {
00682     /* error - what to do ??? */
00683     ERR("(%u %u %x %p %s %p): Could not open key, error=%d\n",
00684         mp->extview.cbSize, mp->extview.uMax, mp->extview.fFlags,
00685         mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
00686             mp->extview.u.string_cmpfn, err);
00687     return 0;
00688     }
00689 
00690     /* get values from key 'MRUList' */
00691     if (newkey) {
00692     datasize = (mp->extview.uMax + 1) * sizeof(WCHAR);
00693     if((err=RegQueryValueExW( newkey, strMRUList, 0, &type,
00694                   (LPBYTE)mp->realMRU, &datasize))) {
00695         /* not present - set size to 1 (will become 0 later) */
00696         datasize = 1;
00697         *mp->realMRU = 0;
00698     }
00699         else
00700             datasize /= sizeof(WCHAR);
00701 
00702     TRACE("MRU list = %s, datasize = %d\n", debugstr_w(mp->realMRU), datasize);
00703 
00704     mp->cursize = datasize - 1;
00705     /* datasize now has number of items in the MRUList */
00706 
00707     /* get actual values for each entry */
00708     realname[1] = 0;
00709     for(i=0; i<mp->cursize; i++) {
00710         realname[0] = 'a' + i;
00711         if(RegQueryValueExW( newkey, realname, 0, &type, 0, &datasize)) {
00712         /* not present - what to do ??? */
00713         ERR("Key %s not found 1\n", debugstr_w(realname));
00714         }
00715         mp->array[i] = witem = Alloc(datasize + sizeof(WINEMRUITEM));
00716         witem->size = datasize;
00717         if(RegQueryValueExW( newkey, realname, 0, &type,
00718                  &witem->datastart, &datasize)) {
00719         /* not present - what to do ??? */
00720         ERR("Key %s not found 2\n", debugstr_w(realname));
00721         }
00722     }
00723     RegCloseKey( newkey );
00724     }
00725     else
00726     mp->cursize = 0;
00727 
00728     TRACE("(%u %u %x %p %s %p): Current Size = %d\n",
00729       mp->extview.cbSize, mp->extview.uMax, mp->extview.fFlags,
00730       mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
00731       mp->extview.u.string_cmpfn, mp->cursize);
00732     return mp;
00733 }
00734 
00735 /**************************************************************************
00736  *                  CreateMRUListLazyW [COMCTL32.404]
00737  *
00738  * See CreateMRUListLazyA.
00739  */
00740 HANDLE WINAPI CreateMRUListLazyW (const MRUINFOW *infoW, DWORD dwParam2,
00741                                   DWORD dwParam3, DWORD dwParam4)
00742 {
00743     LPWINEMRULIST mp;
00744 
00745     /* Native does not check for a NULL lpcml */
00746     if (!infoW->hKey || IsBadStringPtrW(infoW->lpszSubKey, -1))
00747     return NULL;
00748 
00749     mp = Alloc(sizeof(WINEMRULIST));
00750     memcpy(&mp->extview, infoW, sizeof(MRUINFOW));
00751     mp->extview.lpszSubKey = Alloc((strlenW(infoW->lpszSubKey) + 1) * sizeof(WCHAR));
00752     strcpyW(mp->extview.lpszSubKey, infoW->lpszSubKey);
00753     mp->isUnicode = TRUE;
00754 
00755     return create_mru_list(mp);
00756 }
00757 
00758 /**************************************************************************
00759  *                  CreateMRUListLazyA [COMCTL32.157]
00760  *
00761  * Creates a most-recently-used list.
00762  *
00763  * PARAMS
00764  *     lpcml    [I] ptr to CREATEMRULIST structure.
00765  *     dwParam2 [I] Unknown
00766  *     dwParam3 [I] Unknown
00767  *     dwParam4 [I] Unknown
00768  *
00769  * RETURNS
00770  *     Handle to MRU list.
00771  */
00772 HANDLE WINAPI CreateMRUListLazyA (const MRUINFOA *lpcml, DWORD dwParam2,
00773                                   DWORD dwParam3, DWORD dwParam4)
00774 {
00775     LPWINEMRULIST mp;
00776     DWORD len;
00777 
00778     /* Native does not check for a NULL lpcml */
00779 
00780     if (!lpcml->hKey || IsBadStringPtrA(lpcml->lpszSubKey, -1))
00781     return 0;
00782 
00783     mp = Alloc(sizeof(WINEMRULIST));
00784     memcpy(&mp->extview, lpcml, sizeof(MRUINFOA));
00785     len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0);
00786     mp->extview.lpszSubKey = Alloc(len * sizeof(WCHAR));
00787     MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1,
00788             mp->extview.lpszSubKey, len);
00789     mp->isUnicode = FALSE;
00790     return create_mru_list(mp);
00791 }
00792 
00793 /**************************************************************************
00794  *              CreateMRUListW [COMCTL32.400]
00795  *
00796  * See CreateMRUListA.
00797  */
00798 HANDLE WINAPI CreateMRUListW (const MRUINFOW *infoW)
00799 {
00800     return CreateMRUListLazyW(infoW, 0, 0, 0);
00801 }
00802 
00803 /**************************************************************************
00804  *              CreateMRUListA [COMCTL32.151]
00805  *
00806  * Creates a most-recently-used list.
00807  *
00808  * PARAMS
00809  *     lpcml [I] ptr to CREATEMRULIST structure.
00810  *
00811  * RETURNS
00812  *     Handle to MRU list.
00813  */
00814 HANDLE WINAPI CreateMRUListA (const MRUINFOA *lpcml)
00815 {
00816      return CreateMRUListLazyA (lpcml, 0, 0, 0);
00817 }
00818 
00819 
00820 /**************************************************************************
00821  *                EnumMRUListW [COMCTL32.403]
00822  *
00823  * Enumerate item in a most-recently-used list
00824  *
00825  * PARAMS
00826  *    hList [I] list handle
00827  *    nItemPos [I] item position to enumerate
00828  *    lpBuffer [O] buffer to receive item
00829  *    nBufferSize [I] size of buffer
00830  *
00831  * RETURNS
00832  *    For binary lists specifies how many bytes were copied to buffer, for
00833  *    string lists specifies full length of string.  Enumerating past the end
00834  *    of list returns -1.
00835  *    If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
00836  *    the list.
00837  */
00838 INT WINAPI EnumMRUListW (HANDLE hList, INT nItemPos, LPVOID lpBuffer,
00839                          DWORD nBufferSize)
00840 {
00841     const WINEMRULIST *mp = hList;
00842     const WINEMRUITEM *witem;
00843     INT desired, datasize;
00844 
00845     if (!mp) return -1;
00846     if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
00847     if (nItemPos >= mp->cursize) return -1;
00848     desired = mp->realMRU[nItemPos];
00849     desired -= 'a';
00850     TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
00851     witem = mp->array[desired];
00852     datasize = min( witem->size, nBufferSize );
00853     memcpy( lpBuffer, &witem->datastart, datasize);
00854     TRACE("(%p, %d, %p, %d): returning len=%d\n",
00855       hList, nItemPos, lpBuffer, nBufferSize, datasize);
00856     return datasize;
00857 }
00858 
00859 /**************************************************************************
00860  *                EnumMRUListA [COMCTL32.154]
00861  *
00862  * See EnumMRUListW.
00863  */
00864 INT WINAPI EnumMRUListA (HANDLE hList, INT nItemPos, LPVOID lpBuffer,
00865                          DWORD nBufferSize)
00866 {
00867     const WINEMRULIST *mp = hList;
00868     LPWINEMRUITEM witem;
00869     INT desired, datasize;
00870     DWORD lenA;
00871 
00872     if (!mp) return -1;
00873     if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
00874     if (nItemPos >= mp->cursize) return -1;
00875     desired = mp->realMRU[nItemPos];
00876     desired -= 'a';
00877     TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
00878     witem = mp->array[desired];
00879     if(mp->extview.fFlags & MRU_BINARY) {
00880         datasize = min( witem->size, nBufferSize );
00881     memcpy( lpBuffer, &witem->datastart, datasize);
00882     } else {
00883         lenA = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
00884                    NULL, 0, NULL, NULL);
00885     datasize = min( lenA, nBufferSize );
00886     WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
00887                 lpBuffer, datasize, NULL, NULL);
00888         ((char *)lpBuffer)[ datasize - 1 ] = '\0';
00889         datasize = lenA - 1;
00890     }
00891     TRACE("(%p, %d, %p, %d): returning len=%d\n",
00892       hList, nItemPos, lpBuffer, nBufferSize, datasize);
00893     return datasize;
00894 }
00895 
00896 /**************************************************************************
00897  * Str_GetPtrWtoA [internal]
00898  *
00899  * Converts a unicode string into a multi byte string
00900  *
00901  * PARAMS
00902  *     lpSrc   [I] Pointer to the unicode source string
00903  *     lpDest  [O] Pointer to caller supplied storage for the multi byte string
00904  *     nMaxLen [I] Size, in bytes, of the destination buffer
00905  *
00906  * RETURNS
00907  *     Length, in bytes, of the converted string.
00908  */
00909 
00910 INT Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
00911 {
00912     INT len;
00913 
00914     TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
00915 
00916     if (!lpDest && lpSrc)
00917     return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
00918 
00919     if (nMaxLen == 0)
00920     return 0;
00921 
00922     if (lpSrc == NULL) {
00923     lpDest[0] = '\0';
00924     return 0;
00925     }
00926 
00927     len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
00928     if (len >= nMaxLen)
00929     len = nMaxLen - 1;
00930 
00931     WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
00932     lpDest[len] = '\0';
00933 
00934     return len;
00935 }
00936 
00937 /**************************************************************************
00938  * Str_GetPtrAtoW [internal]
00939  *
00940  * Converts a multibyte string into a unicode string
00941  *
00942  * PARAMS
00943  *     lpSrc   [I] Pointer to the multibyte source string
00944  *     lpDest  [O] Pointer to caller supplied storage for the unicode string
00945  *     nMaxLen [I] Size, in characters, of the destination buffer
00946  *
00947  * RETURNS
00948  *     Length, in characters, of the converted string.
00949  */
00950 
00951 INT Str_GetPtrAtoW (LPCSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
00952 {
00953     INT len;
00954 
00955     TRACE("(%s %p %d)\n", debugstr_a(lpSrc), lpDest, nMaxLen);
00956 
00957     if (!lpDest && lpSrc)
00958     return MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, 0, 0);
00959 
00960     if (nMaxLen == 0)
00961     return 0;
00962 
00963     if (lpSrc == NULL) {
00964     lpDest[0] = '\0';
00965     return 0;
00966     }
00967 
00968     len = MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, 0, 0);
00969     if (len >= nMaxLen)
00970     len = nMaxLen - 1;
00971 
00972     MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, lpDest, len);
00973     lpDest[len] = '\0';
00974 
00975     return len;
00976 }
00977 
00978 
00979 /**************************************************************************
00980  * Str_SetPtrAtoW [internal]
00981  *
00982  * Converts a multi byte string to a unicode string.
00983  * If the pointer to the destination buffer is NULL a buffer is allocated.
00984  * If the destination buffer is too small to keep the converted multi byte
00985  * string the destination buffer is reallocated. If the source pointer is
00986  * NULL, the destination buffer is freed.
00987  *
00988  * PARAMS
00989  *     lppDest [I/O] pointer to a pointer to the destination buffer
00990  *     lpSrc   [I] pointer to a multi byte string
00991  *
00992  * RETURNS
00993  *     TRUE: conversion successful
00994  *     FALSE: error
00995  */
00996 BOOL Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
00997 {
00998     TRACE("(%p %s)\n", lppDest, lpSrc);
00999 
01000     if (lpSrc) {
01001     INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
01002     LPWSTR ptr = ReAlloc (*lppDest, len*sizeof(WCHAR));
01003 
01004     if (!ptr)
01005         return FALSE;
01006     MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
01007     *lppDest = ptr;
01008     }
01009     else {
01010         Free (*lppDest);
01011         *lppDest = NULL;
01012     }
01013 
01014     return TRUE;
01015 }
01016 
01017 /**************************************************************************
01018  * Str_SetPtrWtoA [internal]
01019  *
01020  * Converts a unicode string to a multi byte string.
01021  * If the pointer to the destination buffer is NULL a buffer is allocated.
01022  * If the destination buffer is too small to keep the converted wide
01023  * string the destination buffer is reallocated. If the source pointer is
01024  * NULL, the destination buffer is freed.
01025  *
01026  * PARAMS
01027  *     lppDest [I/O] pointer to a pointer to the destination buffer
01028  *     lpSrc   [I] pointer to a wide string
01029  *
01030  * RETURNS
01031  *     TRUE: conversion successful
01032  *     FALSE: error
01033  */
01034 BOOL Str_SetPtrWtoA (LPSTR *lppDest, LPCWSTR lpSrc)
01035 {
01036     TRACE("(%p %s)\n", lppDest, debugstr_w(lpSrc));
01037 
01038     if (lpSrc) {
01039         INT len = WideCharToMultiByte(CP_ACP,0,lpSrc,-1,NULL,0,NULL,FALSE);
01040         LPSTR ptr = ReAlloc (*lppDest, len*sizeof(CHAR));
01041 
01042         if (!ptr)
01043             return FALSE;
01044         WideCharToMultiByte(CP_ACP,0,lpSrc,-1,ptr,len,NULL,FALSE);
01045         *lppDest = ptr;
01046     }
01047     else {
01048         Free (*lppDest);
01049         *lppDest = NULL;
01050     }
01051 
01052     return TRUE;
01053 }
01054 
01055 
01056 /**************************************************************************
01057  * Notification functions
01058  */
01059 
01060 typedef struct tagNOTIFYDATA
01061 {
01062     HWND hwndFrom;
01063     HWND hwndTo;
01064     DWORD  dwParam3;
01065     DWORD  dwParam4;
01066     DWORD  dwParam5;
01067     DWORD  dwParam6;
01068 } NOTIFYDATA, *LPNOTIFYDATA;
01069 
01070 
01071 /**************************************************************************
01072  * DoNotify [Internal]
01073  */
01074 
01075 static LRESULT DoNotify (const NOTIFYDATA *lpNotify, UINT uCode, LPNMHDR lpHdr)
01076 {
01077     NMHDR nmhdr;
01078     LPNMHDR lpNmh = NULL;
01079     UINT idFrom = 0;
01080 
01081     TRACE("(%p %p %d %p 0x%08x)\n",
01082        lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
01083        lpNotify->dwParam5);
01084 
01085     if (!lpNotify->hwndTo)
01086     return 0;
01087 
01088     if (lpNotify->hwndFrom == (HWND)-1) {
01089     lpNmh = lpHdr;
01090     idFrom = lpHdr->idFrom;
01091     }
01092     else {
01093     if (lpNotify->hwndFrom)
01094         idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
01095 
01096     lpNmh = (lpHdr) ? lpHdr : &nmhdr;
01097 
01098     lpNmh->hwndFrom = lpNotify->hwndFrom;
01099     lpNmh->idFrom = idFrom;
01100     lpNmh->code = uCode;
01101     }
01102 
01103     return SendMessageW (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
01104 }
01105 
01106 
01107 /**************************************************************************
01108  * SendNotify [COMCTL32.341]
01109  *
01110  * Sends a WM_NOTIFY message to the specified window.
01111  *
01112  * PARAMS
01113  *     hwndTo   [I] Window to receive the message
01114  *     hwndFrom [I] Window that the message is from (see notes)
01115  *     uCode    [I] Notification code
01116  *     lpHdr    [I] The NMHDR and any additional information to send or NULL
01117  *
01118  * RETURNS
01119  *     Success: return value from notification
01120  *     Failure: 0
01121  *
01122  * NOTES
01123  *     If hwndFrom is -1 then the identifier of the control sending the
01124  *     message is taken from the NMHDR structure.
01125  *     If hwndFrom is not -1 then lpHdr can be NULL.
01126  */
01127 LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr)
01128 {
01129     NOTIFYDATA notify;
01130 
01131     TRACE("(%p %p %d %p)\n",
01132        hwndTo, hwndFrom, uCode, lpHdr);
01133 
01134     notify.hwndFrom = hwndFrom;
01135     notify.hwndTo   = hwndTo;
01136     notify.dwParam5 = 0;
01137     notify.dwParam6 = 0;
01138 
01139     return DoNotify (&notify, uCode, lpHdr);
01140 }
01141 
01142 
01143 /**************************************************************************
01144  * SendNotifyEx [COMCTL32.342]
01145  *
01146  * Sends a WM_NOTIFY message to the specified window.
01147  *
01148  * PARAMS
01149  *     hwndFrom [I] Window to receive the message
01150  *     hwndTo   [I] Window that the message is from
01151  *     uCode    [I] Notification code
01152  *     lpHdr    [I] The NMHDR and any additional information to send or NULL
01153  *     dwParam5 [I] Unknown
01154  *
01155  * RETURNS
01156  *     Success: return value from notification
01157  *     Failure: 0
01158  *
01159  * NOTES
01160  *     If hwndFrom is -1 then the identifier of the control sending the
01161  *     message is taken from the NMHDR structure.
01162  *     If hwndFrom is not -1 then lpHdr can be NULL.
01163  */
01164 LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
01165                              LPNMHDR lpHdr, DWORD dwParam5)
01166 {
01167     NOTIFYDATA notify;
01168     HWND hwndNotify;
01169 
01170     TRACE("(%p %p %d %p 0x%08x)\n",
01171        hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
01172 
01173     hwndNotify = hwndTo;
01174     if (!hwndTo) {
01175     if (IsWindow (hwndFrom)) {
01176         hwndNotify = GetParent (hwndFrom);
01177         if (!hwndNotify)
01178         return 0;
01179     }
01180     }
01181 
01182     notify.hwndFrom = hwndFrom;
01183     notify.hwndTo   = hwndNotify;
01184     notify.dwParam5 = dwParam5;
01185     notify.dwParam6 = 0;
01186 
01187     return DoNotify (&notify, uCode, lpHdr);
01188 }

Generated on Sun May 27 2012 04:22:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.