Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencomctl32undoc.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 (¬ify, 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 (¬ify, uCode, lpHdr); 01188 } Generated on Sun May 27 2012 04:22:58 for ReactOS by
1.7.6.1
|