Changeset 6810 for trunk/src


Ignore:
Timestamp:
Sep 25, 2001, 12:54:55 PM (24 years ago)
Author:
sandervl
Message:

wine update

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/comctl32/comctl32undoc.c

    r6709 r6810  
    1919#define WINE_LARGE_INTEGER
    2020#endif
     21
    2122#include <string.h>
    2223#include <stdlib.h> /* atoi */
     
    2728#include "winbase.h"
    2829#include "winerror.h"
     30#include "winreg.h"
    2931
    3032#include "wine/unicode.h"
     
    3436
    3537DEFAULT_DEBUG_CHANNEL(commctrl);
    36 
    3738
    3839#ifdef __WIN32OS2__
     
    423424 */
    424425
     426#ifdef __WIN32OS2__
     427#include <wine\undoccomctl32.h>
     428#else
    425429typedef struct tagCREATEMRULIST
    426430{
     
    446450 */
    447451
    448 typedef struct tagMRU
    449 {
    450     DWORD  dwParam1;  /* some kind of flag */
    451     DWORD  dwParam2;
    452     DWORD  dwParam3;
    453     HKEY   hkeyMRU;
    454     LPCSTR lpszSubKey;
    455     DWORD  dwParam6;
    456 } MRU, *HMRU;
     452typedef struct tagWINEMRUITEM
     453{
     454    DWORD          size;        /* size of data stored               */
     455    DWORD          itemFlag;    /* flags                             */
     456    BYTE           datastart;
     457} WINEMRUITEM, *LPWINEMRUITEM;
     458
     459/* itemFlag */
     460#define WMRUIF_CHANGED   0x0001 /* this dataitem changed             */
     461
     462typedef struct tagWINEMRULIST
     463{
     464    CREATEMRULIST  extview;     /* original create information       */
     465    DWORD          wineFlags;   /* internal flags                    */
     466    DWORD          cursize;     /* current size of realMRU           */
     467    LPSTR          realMRU;     /* pointer to string of index names  */
     468    LPWINEMRUITEM  *array;      /* array of pointers to data         */
     469                                /* in 'a' to 'z' order               */
     470} WINEMRULIST, *LPWINEMRULIST;
     471
     472/* wineFlags */
     473#define WMRUF_CHANGED  0x0001   /* MRU list has changed              */
    457474
    458475HANDLE WINAPI
    459476CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2,
    460477                    DWORD dwParam3, DWORD dwParam4);
    461 
     478#endif
     479
     480/**************************************************************************
     481 *              MRU_SaveChanged - Localize MRU saving code
     482 *
     483 */
     484VOID MRU_SaveChanged( LPWINEMRULIST mp )
     485{
     486    INT i, err;
     487    HKEY newkey;
     488    CHAR realname[2];
     489    LPWINEMRUITEM witem;
     490
     491    /* or should we do the following instead of RegOpenKeyEx:
     492     */
     493
     494    /* open the sub key */
     495    if ((err = RegOpenKeyExA( mp->extview.hKey, mp->extview.lpszSubKey,
     496                               0, KEY_WRITE, &newkey))) {
     497        /* not present - what to do ??? */
     498        ERR("Can not open key, error=%d, attempting to create\n",
     499            err);
     500        if ((err = RegCreateKeyExA( mp->extview.hKey, mp->extview.lpszSubKey,
     501                                    0,
     502                                    "",
     503                                    REG_OPTION_NON_VOLATILE,
     504                                    KEY_READ | KEY_WRITE,
     505                                    0,
     506                                    &newkey,
     507                                    0))) {
     508            ERR("failed to create key /%s/, err=%d\n",
     509                mp->extview.lpszSubKey, err);
     510            return;
     511        }
     512    }
     513    if (mp->wineFlags & WMRUF_CHANGED) {
     514        mp->wineFlags &= ~WMRUF_CHANGED;
     515        err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ,
     516                             mp->realMRU, lstrlenA(mp->realMRU) + 1);
     517        if (err) {
     518            ERR("error saving MRUList, err=%d\n", err);
     519        }
     520        TRACE("saving MRUList=/%s/\n", mp->realMRU);
     521    }
     522    realname[1] = 0;
     523    for(i=0; i<mp->cursize; i++) {
     524        witem = mp->array[i];
     525        if (witem->itemFlag & WMRUIF_CHANGED) {
     526            witem->itemFlag &= ~WMRUIF_CHANGED;
     527            realname[0] = 'a' + i;
     528            err = RegSetValueExA(newkey, realname, 0,
     529                                 (mp->extview.dwFlags & MRUF_BINARY_LIST) ?
     530                                 REG_BINARY : REG_SZ,
     531                                 &witem->datastart, witem->size);
     532            if (err) {
     533                ERR("error saving /%s/, err=%d\n", realname, err);
     534            }
     535            TRACE("saving value for name /%s/ size=%ld\n",
     536                  realname, witem->size);
     537        }
     538    }
     539    RegCloseKey( newkey );
     540}
    462541
    463542/**************************************************************************
     
    486565FreeMRUListA (HANDLE hMRUList)
    487566{
    488     FIXME("(%08x) empty stub!\n", hMRUList);
    489 
    490 #if 0
    491     if (!(hmru->dwParam1 & 1001)) {
    492         RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
    493                           hmru->lpszMRUString,
    494                           strlen (hmru->lpszMRUString));
    495     }
    496 
    497 
    498     RegClosKey (hmru->hkeyMRU
    499     COMCTL32_Free32 (hmru->lpszMRUString);
    500 #endif
    501 
    502     return COMCTL32_Free ((LPVOID)hMRUList);
     567    LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
     568    INT i;
     569
     570    TRACE("\n");
     571    if (mp->wineFlags & WMRUF_CHANGED) {
     572        /* need to open key and then save the info */
     573        MRU_SaveChanged( mp );
     574    }
     575
     576    for(i=0; i<mp->extview.nMaxItems; i++) {
     577        if (mp->array[i])
     578            COMCTL32_Free(mp->array[i]);
     579    }
     580    COMCTL32_Free(mp->realMRU);
     581    COMCTL32_Free(mp->array);
     582    return COMCTL32_Free(mp);
     583}
     584
     585
     586/**************************************************************************
     587 *                  FindMRUData [COMCTL32.169]
     588 *
     589 * Searches binary list for item that matches lpData of length cbData.
     590 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
     591 * corresponding to item's reg. name will be stored in it ('a' -> 0).
     592 *
     593 * PARAMS
     594 *    hList [I] list handle
     595 *    lpData [I] data to find
     596 *    cbData [I] length of data
     597 *    lpRegNum [O] position in registry (maybe NULL)
     598 *
     599 * RETURNS
     600 *    Position in list 0 -> MRU.  -1 if item not found.
     601 */
     602INT WINAPI
     603FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
     604{
     605    LPWINEMRULIST mp = (LPWINEMRULIST)hList;
     606    INT i, ret;
     607
     608    if (!mp->extview.lpfnCompare) {
     609        ERR("MRU list not properly created. No compare procedure.\n");
     610        return -1;
     611    }
     612
     613    for(i=0; i<mp->cursize; i++) {
     614        if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
     615            if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart,
     616                                         cbData))
     617                break;
     618        }
     619        else {
     620            if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart))
     621                break;
     622        }
     623    }
     624    if (i < mp->cursize)
     625        ret = i;
     626    else
     627        ret = -1;
     628    if (lpRegNum && (ret != -1))
     629        *lpRegNum = 'a' + i;
     630
     631    TRACE("(%08x, %p, %ld, %p) returning %d\n",
     632           hList, lpData, cbData, lpRegNum, ret);
     633
     634    return ret;
    503635}
    504636
     
    523655AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
    524656{
    525     FIXME("(%08x, %p, %ld) empty stub!\n", hList, lpData, cbData);
    526 
    527     return 0;
     657    LPWINEMRULIST mp = (LPWINEMRULIST)hList;
     658    LPWINEMRUITEM witem;
     659    INT i, replace, ret;
     660
     661    if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) {
     662        /* either add a new entry or replace oldest */
     663        if (mp->cursize < mp->extview.nMaxItems) {
     664            /* Add in a new item */
     665            replace = mp->cursize;
     666            mp->cursize++;
     667        }
     668        else {
     669            /* get the oldest entry and replace data */
     670            replace = mp->realMRU[mp->cursize - 1] - 'a';
     671            COMCTL32_Free(mp->array[replace]);
     672        }
     673    }
     674    else {
     675        /* free up the old data */
     676        COMCTL32_Free(mp->array[replace]);
     677    }
     678
     679    /* Allocate space for new item and move in the data */
     680    mp->array[replace] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(cbData +
     681                                                               sizeof(WINEMRUITEM));
     682    witem->itemFlag |= WMRUIF_CHANGED;
     683    witem->size = cbData;
     684    memcpy( &witem->datastart, lpData, cbData);
     685
     686    /* now rotate MRU list */
     687    mp->wineFlags |= WMRUF_CHANGED;
     688    for(i=mp->cursize-1; i>=1; i--) {
     689        mp->realMRU[i] = mp->realMRU[i-1];
     690    }
     691    mp->realMRU[0] = replace + 'a';
     692    TRACE("(%08x, %p, %ld) adding data, /%c/ now most current\n",
     693          hList, lpData, cbData, replace+'a');
     694    ret = replace;
     695
     696    if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
     697        /* save changed stuff right now */
     698        MRU_SaveChanged( mp );
     699    }
     700
     701    return ret;
    528702}
    529703
     
    571745
    572746/**************************************************************************
    573  *                  FindMRUData [COMCTL32.169]
    574  *
    575  * Searches binary list for item that matches lpData of length cbData.
    576  * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
    577  * corresponding to item's reg. name will be stored in it ('a' -> 0).
    578  *
    579  * PARAMS
    580  *    hList [I] list handle
    581  *    lpData [I] data to find
    582  *    cbData [I] length of data
    583  *    lpRegNum [O] position in registry (maybe NULL)
    584  *
    585  * RETURNS
    586  *    Position in list 0 -> MRU.  -1 if item not found.
    587  */
    588 INT WINAPI
    589 FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
    590 {
    591     FIXME("(%08x, %p, %ld, %p) empty stub!\n",
    592            hList, lpData, cbData, lpRegNum);
    593 
    594     return 0;
    595 }
    596 
    597 /**************************************************************************
    598747 *                  FindMRUStringA [COMCTL32.155]
    599748 *
     
    613762FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
    614763{
    615     FIXME("(%08x, %s, %p) empty stub!\n", hList, debugstr_a(lpszString),
    616           lpRegNum);
    617 
    618     return 0;
     764    return FindMRUData(hList, (LPVOID)lpszString, lstrlenA(lpszString),
     765                       lpRegNum);
    619766}
    620767
     
    625772CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
    626773{
    627     /* DWORD  dwLocal1;   *
    628      * HKEY   hkeyResult; *
    629      * DWORD  dwLocal3;   *
    630      * LPVOID lMRU;       *
    631      * DWORD  dwLocal5;   *
    632      * DWORD  dwLocal6;   *
    633      * DWORD  dwLocal7;   *
    634      * DWORD  dwDisposition; */
    635 
    636     /* internal variables */
    637     LPVOID ptr;
    638 
    639     FIXME("(%p) empty stub!\n", lpcml);
     774    LPWINEMRULIST mp;
     775    INT i, err;
     776    HKEY newkey;
     777    DWORD datasize, dwdisp;
     778    CHAR realname[2];
     779    LPWINEMRUITEM witem;
     780    DWORD type;
    640781
    641782    if (lpcml == NULL)
     
    645786        return 0;
    646787
    647     FIXME("(%lu %lu %lx %lx \"%s\" %p)\n",
     788    mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
     789    memcpy(mp, lpcml, sizeof(CREATEMRULIST));
     790
     791    /* get space to save indexes that will turn into names
     792     * but in order of most to least recently used
     793     */
     794    mp->realMRU = (LPSTR) COMCTL32_Alloc(mp->extview.nMaxItems + 2);
     795
     796    /* get space to save pointers to actual data in order of
     797     * 'a' to 'z' (0 to n).
     798     */
     799    mp->array = (LPVOID) COMCTL32_Alloc(mp->extview.nMaxItems *
     800                                        sizeof(LPVOID));
     801
     802    /* open the sub key */
     803     if ((err = RegCreateKeyExA( mp->extview.hKey, mp->extview.lpszSubKey,
     804                               0,
     805                                "",
     806                                REG_OPTION_NON_VOLATILE,
     807                                KEY_READ | KEY_WRITE,
     808                                0,
     809                                &newkey,
     810                                &dwdisp))) {
     811        /* error - what to do ??? */
     812        ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n",
     813            lpcml->cbSize, lpcml->nMaxItems, lpcml->dwFlags,
     814            (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare,
     815            err);
     816        return 0;
     817    }
     818
     819    /* get values from key 'MRUList' */
     820    if (newkey) {
     821        datasize = mp->extview.nMaxItems + 1;
     822        if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU,
     823                                  &datasize))) {
     824            /* not present - set size to 1 (will become 0 later) */
     825            datasize = 1;
     826            *mp->realMRU = 0;
     827        }
     828
     829        TRACE("MRU list = %s\n", mp->realMRU);
     830
     831        mp->cursize = datasize - 1;
     832        /* datasize now has number of items in the MRUList */
     833
     834        /* get actual values for each entry */
     835        realname[1] = 0;
     836        for(i=0; i<mp->cursize; i++) {
     837            realname[0] = 'a' + i;
     838            if(RegQueryValueExA( newkey, realname, 0, &type, 0, &datasize)) {
     839                /* not present - what to do ??? */
     840                ERR("Key %s not found 1\n", realname);
     841            }
     842            mp->array[i] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(datasize +
     843                                                                 sizeof(WINEMRUITEM));
     844            witem->size = datasize;
     845            if(RegQueryValueExA( newkey, realname, 0, &type,
     846                                 &witem->datastart, &datasize)) {
     847                /* not present - what to do ??? */
     848                ERR("Key %s not found 2\n", realname);
     849            }
     850        }
     851        RegCloseKey( newkey );
     852    }
     853    else
     854        mp->cursize = 0;
     855
     856    TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n",
    648857          lpcml->cbSize, lpcml->nMaxItems, lpcml->dwFlags,
    649           (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare);
    650 
    651     /* dummy pointer creation */
    652     ptr = COMCTL32_Alloc (32);
    653 
    654     FIXME("-- ret = %p\n", ptr);
    655 
    656     return (HANDLE)ptr;
     858          (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare,
     859          mp->cursize);
     860
     861    return (HANDLE)mp;
    657862}
    658863
     
    678883DWORD nBufferSize)
    679884{
    680     FIXME("(%08x, %d, %p, %ld): stub\n", hList, nItemPos, lpBuffer,
    681           nBufferSize);
    682     return 0;
     885    LPWINEMRULIST mp = (LPWINEMRULIST) hList;
     886    LPWINEMRUITEM witem;
     887    INT desired, datasize;
     888
     889    if (nItemPos >= mp->cursize) return -1;
     890    if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
     891    desired = mp->realMRU[nItemPos];
     892    desired -= 'a';
     893    TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
     894    witem = mp->array[desired];
     895    datasize = min( witem->size, nBufferSize );
     896    memcpy( lpBuffer, &witem->datastart, datasize);
     897    TRACE("(%08x, %d, %p, %ld): returning len=%d\n",
     898          hList, nItemPos, lpBuffer, nBufferSize, datasize);
     899    return datasize;
    683900}
    684901
  • trunk/src/shell32/shell32_main.h

    r6709 r6810  
    1 /* $Id: shell32_main.h,v 1.10 2001-09-15 09:26:23 sandervl Exp $ */
    21/*
    32 *      internal Shell32 Library definitions
     
    6362#define pCreateIconFromResourceEx    CreateIconFromResourceEx
    6463
     64#include <wine\undoccomctl32.h>
     65
     66#define pAddMRUData     AddMRUData
     67#define pFindMRUData    FindMRUData
     68#define pEnumMRUListA   EnumMRUListA
     69#define pFreeMRUListA   FreeMRUListA
     70#define pCreateMRUListA CreateMRUListA
     71
    6572/* ole2 */
    6673/*
  • trunk/src/shell32/shellord.c

    r6709 r6810  
    1414#include "heap.h"
    1515
     16#include "shlwapi.h"
    1617#include "shellapi.h"
    1718#include "shlguid.h"
    1819#include "shlobj.h"
    1920#include "shell32_main.h"
    20 #include "wine/undocshell.h"
     21#ifdef __WIN32OS2__
     22#include "wine\undocshell.h"
     23#else
     24#include "undocshell.h"
     25#endif
    2126
    2227DEFAULT_DEBUG_CHANNEL(shell);
     
    6570DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len)
    6671{
    67         FIXME("('%s',0x%08lx,%p,%ld) stub.\n",
     72        FIXME("(%s,0x%08lx,%p,%ld) stub\n",
    6873          debugstr_w(src), nField, dst, len);
    6974        return FALSE;
     
    7176
    7277/*************************************************************************
    73  * ParseFieldAW                 [SHELL32.58]
     78 * ParseField                   [SHELL32.58]
    7479 */
    7580DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len)
     
    435440
    436441/*************************************************************************
    437  * SHAddToRecentDocs                            [SHELL32.234]
     442 * SHADD_get_policy - helper function for SHAddToRecentDocs
     443 *
     444 * PARAMETERS
     445 *   policy    [IN]  policy name (null termed string) to find
     446 *   type      [OUT] ptr to DWORD to receive type
     447 *   buffer    [OUT] ptr to area to hold data retrieved
     448 *   len       [IN/OUT] ptr to DWORD holding size of buffer and getting
     449 *                      length filled
     450 *
     451 * RETURNS
     452 *   result of the SHQueryValueEx call
     453 */
     454static INT SHADD_get_policy(LPSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len)
     455{
     456    HKEY Policy_basekey;
     457    INT ret;
     458
     459    /* Get the key for the policies location in the registry
     460     */
     461    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
     462                      "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
     463                      0, KEY_READ, &Policy_basekey)) {
     464
     465        if (RegOpenKeyExA(HKEY_CURRENT_USER,
     466                          "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
     467                          0, KEY_READ, &Policy_basekey)) {
     468            ERR("No Explorer Policies location\n");
     469            *len = 0;
     470            return ERROR_FILE_NOT_FOUND;
     471        }
     472    }
     473
     474    /* Retrieve the data if it exists
     475     */
     476    ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len);
     477    RegCloseKey(Policy_basekey);
     478    return ret;
     479}
     480
     481
     482/*************************************************************************
     483 * SHADD_compare_mru - helper function for SHAddToRecentDocs
     484 *
     485 * PARAMETERS
     486 *   data1     [IN] data being looked for
     487 *   data2     [IN] data in MRU
     488 *   cbdata    [IN] length from FindMRUData call (not used)
     489 *
     490 * RETURNS
     491 *   position within MRU list that data was added.
     492 */
     493static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData)
     494{
     495    return lstrcmpiA(data1, data2);
     496}
     497
     498/*************************************************************************
     499 * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs
     500 *
     501 * PARAMETERS
     502 *   mruhandle    [IN] handle for created MRU list
     503 *   doc_name     [IN] null termed pure doc name
     504 *   new_lnk_name [IN] null termed path and file name for .lnk file
     505 *   buffer       [IN/OUT] 2048 byte area to consturct MRU data
     506 *   len          [OUT] ptr to int to receive space used in buffer
     507 *
     508 * RETURNS
     509 *   position within MRU list that data was added.
     510 */
     511static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPSTR doc_name, LPSTR new_lnk_name,
     512                                     LPSTR buffer, INT *len)
     513{
     514    LPSTR ptr;
     515    INT wlen;
     516   
     517    /*FIXME: Document:
     518     *  RecentDocs MRU data structure seems to be:
     519     *    +0h   document file name w/ terminating 0h
     520     *    +nh   short int w/ size of remaining
     521     *    +n+2h 02h 30h, or 01h 30h, or 00h 30h  -  unknown
     522     *    +n+4h 10 bytes zeros  -   unknown
     523     *    +n+eh shortcut file name w/ terminating 0h
     524     *    +n+e+nh 3 zero bytes  -  unknown
     525     */
     526
     527    /* Create the MRU data structure for "RecentDocs"
     528         */
     529    ptr = buffer;
     530    lstrcpyA(ptr, doc_name);
     531    ptr += (lstrlenA(buffer) + 1);
     532    wlen= lstrlenA(new_lnk_name) + 1 + 12;
     533    *((short int*)ptr) = wlen;
     534    ptr += 2;   /* step past the length */
     535    *(ptr++) = 0x30;  /* unknown reason */
     536    *(ptr++) = 0;     /* unknown, but can be 0x00, 0x01, 0x02 */
     537    memset(ptr, 0, 10);
     538    ptr += 10;
     539    lstrcpyA(ptr, new_lnk_name);
     540    ptr += (lstrlenA(new_lnk_name) + 1);
     541    memset(ptr, 0, 3);
     542    ptr += 3;
     543    *len = ptr - buffer;
     544
     545    /* Add the new entry into the MRU list
     546     */
     547    return pAddMRUData(mruhandle, (LPCVOID)buffer, *len);
     548}
     549
     550/*************************************************************************
     551 * SHAddToRecentDocs                            [SHELL32.@]
    438552 *
    439553 * PARAMETERS
     
    443557 * NOTES
    444558 *     exported by name
     559 *
     560 * FIXME: ?? MSDN shows this as a VOID
    445561 */
    446562DWORD WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv)   
    447 { if (SHARD_PIDL==uFlags)
    448   { FIXME("(0x%08x,pidl=%p):stub.\n", uFlags,pv);
     563{
     564
     565#ifndef __WIN32OS2__
     566/* FIXME: !!! move CREATEMRULIST and flags to header file !!! */
     567/*        !!! it is in both here and comctl32undoc.c      !!! */
     568typedef struct tagCREATEMRULIST
     569{
     570    DWORD  cbSize;        /* size of struct */
     571    DWORD  nMaxItems;     /* max no. of items in list */
     572    DWORD  dwFlags;       /* see below */
     573    HKEY   hKey;          /* root reg. key under which list is saved */
     574    LPCSTR lpszSubKey;    /* reg. subkey */
     575    PROC   lpfnCompare;   /* item compare proc */
     576} CREATEMRULIST, *LPCREATEMRULIST;
     577
     578/* dwFlags */
     579#define MRUF_STRING_LIST  0 /* list will contain strings */
     580#define MRUF_BINARY_LIST  1 /* list will contain binary data */
     581#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
     582
     583/* If list is a string list lpfnCompare has the following prototype
     584 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
     585 * for binary lists the prototype is
     586 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
     587 * where cbData is the no. of bytes to compare.
     588 * Need to check what return value means identical - 0?
     589 */
     590#endif
     591
     592    UINT olderrormode;
     593    HKEY HCUbasekey;
     594    CHAR doc_name[MAX_PATH];
     595    CHAR link_dir[MAX_PATH];
     596    CHAR new_lnk_filepath[MAX_PATH];
     597    CHAR new_lnk_name[MAX_PATH];
     598    IMalloc *ppM;
     599    LPITEMIDLIST pidl;
     600    HWND hwnd = 0;       /* FIXME:  get real window handle */
     601    INT ret;
     602    DWORD data[64], datalen, type;
     603
     604    /*FIXME: Document:
     605     *  RecentDocs MRU data structure seems to be:
     606     *    +0h   document file name w/ terminating 0h
     607     *    +nh   short int w/ size of remaining
     608     *    +n+2h 02h 30h, or 01h 30h, or 00h 30h  -  unknown
     609     *    +n+4h 10 bytes zeros  -   unknown
     610     *    +n+eh shortcut file name w/ terminating 0h
     611     *    +n+e+nh 3 zero bytes  -  unknown
     612     */
     613
     614    /* See if we need to do anything.
     615     */
     616    datalen = 64;
     617    ret=SHADD_get_policy( "NoRecentDocsHistory", &type, &data, &datalen);
     618    if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) {
     619        ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret);
     620        return 0;
     621    }
     622    if (ret == ERROR_SUCCESS) {
     623        if (!( (type == REG_DWORD) ||
     624               ((type == REG_BINARY) && (datalen == 4)) )) {
     625            ERR("Error policy data for \"NoRecentDocsHistory\" not formated correctly, type=%ld, len=%ld\n",
     626                type, datalen);
     627            return 0;
    449628        }
    450         else
    451         { FIXME("(0x%08x,%s):stub.\n", uFlags,(char*)pv);
     629
     630        TRACE("policy value for NoRecentDocsHistory = %08lx\n", data[0]);
     631        /* now test the actual policy value */
     632        if ( data[0] != 0)
     633            return 0;
     634    }
     635
     636    /* Open key to where the necessary info is
     637     */
     638    /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH)
     639     *        and the close should be done during the _DETACH. The resulting
     640     *        key is stored in the DLL global data.
     641     */
     642    RegOpenKeyExA(HKEY_CURRENT_USER,
     643                  "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
     644                  0,
     645                  KEY_READ,
     646                  &HCUbasekey);
     647
     648    /* Get path to user's "Recent" directory
     649     */
     650    if(SUCCEEDED(SHGetMalloc(&ppM))) {
     651        if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT,
     652                                                 &pidl))) {
     653            SHGetPathFromIDListA(pidl, link_dir);
     654            IMalloc_Free(ppM, pidl);
    452655        }
    453   return 0;
    454 }
     656        IMalloc_Release(ppM);
     657    }
     658    else {
     659        /* serious issues */
     660        link_dir[0] = 0;
     661        ERR("serious issues\n");
     662    }
     663    TRACE("Users Recent dir %s\n", link_dir);
     664
     665    /* If no input, then go clear the lists */
     666    if (!pv) {
     667        /* clear user's Recent dir
     668         */
     669
     670        /* FIXME: delete all files in "link_dir"
     671         *
     672         * while( more files ) {
     673         *    lstrcpyA(old_lnk_name, link_dir);
     674         *    PathAppendA(old_lnk_name, filenam);
     675         *    DeleteFileA(old_lnk_name);
     676         * }
     677         */
     678        FIXME("should delete all files in %s\\ \n", link_dir);
     679
     680        /* clear MRU list
     681         */
     682        /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against
     683         *  HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer
     684         *  and naturally it fails w/ rc=2. It should do it against
     685         *  HKEY_CURRENT_USER which is where it is stored, and where
     686         *  the MRU routines expect it!!!!
     687         */
     688        RegDeleteKeyA(HCUbasekey, "RecentDocs");
     689        RegCloseKey(HCUbasekey);
     690        return 0;
     691    }
     692
     693    /* Have data to add, the jobs to be done:
     694     *   1. Add document to MRU list in registry "HKCU\Software\
     695     *      Microsoft\Windows\CurrentVersion\Explorer\RecentDocs".
     696     *   2. Add shortcut to document in the user's Recent directory
     697     *      (CSIDL_RECENT).
     698     *   3. Add shortcut to Start menu's Documents submenu.
     699     */
     700
     701    /* Get the pure document name from the input
     702     */
     703    if (uFlags & SHARD_PIDL) {
     704        SHGetPathFromIDListA((LPCITEMIDLIST) pv, doc_name);
     705    }
     706    else {
     707        lstrcpyA(doc_name, (LPSTR) pv);
     708    }
     709    TRACE("full document name %s\n", doc_name);
     710    PathStripPathA(doc_name);;
     711    TRACE("stripped document name %s\n", doc_name);
     712
     713
     714    /* ***  JOB 1: Update registry for ...\Explorer\RecentDocs list  *** */
     715
     716    {  /* on input needs:
     717        *      doc_name    -  pure file-spec, no path
     718        *      link_dir    -  path to the user's Recent directory
     719        *      HCUbasekey  -  key of ...Windows\CurrentVersion\Explorer" node
     720        * creates:
     721        *      new_lnk_name-  pure file-spec, no path for new .lnk file
     722        *      new_lnk_filepath
     723        *                  -  path and file name of new .lnk file
     724        */
     725        CREATEMRULIST mymru;
     726        HANDLE mruhandle;
     727        INT len, pos, bufused, err;
     728        INT i;
     729        DWORD attr;
     730        CHAR buffer[2048];
     731        CHAR *ptr;
     732        CHAR old_lnk_name[MAX_PATH];
     733        short int slen;
     734
     735        mymru.cbSize = sizeof(CREATEMRULIST);
     736        mymru.nMaxItems = 15;
     737        mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE;
     738        mymru.hKey = HCUbasekey;
     739        mymru.lpszSubKey = "RecentDocs";
     740        mymru.lpfnCompare = &SHADD_compare_mru;
     741        mruhandle = pCreateMRUListA(&mymru);
     742        if (!mruhandle) {
     743            /* MRU failed */
     744            ERR("MRU processing failed, handle zero\n");
     745            RegCloseKey(HCUbasekey);
     746            return 0;
     747        }
     748        len = lstrlenA(doc_name);
     749        pos = pFindMRUData(mruhandle, doc_name, len, 0);
     750
     751        /* Now get the MRU entry that will be replaced
     752         * and delete the .lnk file for it
     753         */
     754        if ((bufused = pEnumMRUListA(mruhandle, (pos == -1) ? 14 : pos,
     755                                     buffer, 2048)) != -1) {
     756            ptr = buffer;
     757            ptr += (lstrlenA(buffer) + 1);
     758            slen = *((short int*)ptr);
     759            ptr += 2;  /* skip the length area */
     760            if (bufused >= slen + (ptr-buffer)) {
     761                /* buffer size looks good */
     762                ptr += 12; /* get to string */
     763                len = bufused - (ptr-buffer);  /* get length of buf remaining */
     764                if ((lstrlenA(ptr) > 0) && (lstrlenA(ptr) <= len-1)) {
     765                    /* appears to be good string */
     766                    lstrcpyA(old_lnk_name, link_dir);
     767                    PathAppendA(old_lnk_name, ptr);
     768                    if (!DeleteFileA(old_lnk_name)) {
     769                        if ((attr = GetFileAttributesA(old_lnk_name)) == -1) {
     770                            if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) {
     771                                ERR("Delete for %s failed, err=%d, attr=%08lx\n",
     772                                    old_lnk_name, err, attr);
     773                            }
     774                            else {
     775                                TRACE("old .lnk file %s did not exist\n",
     776                                      old_lnk_name);
     777                            }
     778                        }
     779                        else {
     780                            ERR("Delete for %s failed, attr=%08lx\n",
     781                                old_lnk_name, attr);
     782                        }
     783                    }
     784                    else {
     785                        TRACE("deleted old .lnk file %s\n", old_lnk_name);
     786                    }
     787                }
     788            }
     789        }
     790
     791        /* Create usable .lnk file name for the "Recent" directory
     792         */
     793        wsprintfA(new_lnk_name, "%s.lnk", doc_name);
     794        lstrcpyA(new_lnk_filepath, link_dir);
     795        PathAppendA(new_lnk_filepath, new_lnk_name);
     796        i = 1;
     797        olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS);
     798        while (GetFileAttributesA(new_lnk_filepath) != -1) {
     799            i++;
     800            wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i);
     801            lstrcpyA(new_lnk_filepath, link_dir);
     802            PathAppendA(new_lnk_filepath, new_lnk_name);
     803        }
     804        SetErrorMode(olderrormode);
     805        TRACE("new shortcut will be %s\n", new_lnk_filepath);
     806
     807        /* Now add the new MRU entry and data
     808         */
     809        pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name,
     810                                        buffer, &len);
     811        pFreeMRUListA(mruhandle);
     812        TRACE("Updated MRU list, new doc is position %d\n", pos);
     813    }
     814
     815    /* ***  JOB 2: Create shortcut in user's "Recent" directory  *** */
     816
     817    {  /* on input needs:
     818        *      doc_name    -  pure file-spec, no path
     819        *      new_lnk_filepath
     820        *                  -  path and file name of new .lnk file
     821        *      uFlags[in]  -  flags on call to SHAddToRecentDocs
     822        *      pv[in]      -  document path/pidl on call to SHAddToRecentDocs
     823        */
     824        IShellLinkA *psl = NULL;
     825        IPersistFile *pPf = NULL;
     826        HRESULT hres;
     827        CHAR desc[MAX_PATH];
     828        WCHAR widelink[MAX_PATH];
     829
     830        CoInitialize(0);
     831
     832        hres = CoCreateInstance( &CLSID_ShellLink,
     833                                 NULL,
     834                                 CLSCTX_INPROC_SERVER,
     835                                 &IID_IShellLinkA,
     836                                 (LPVOID )&psl);
     837        if(SUCCEEDED(hres)) {
     838
     839            hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile,
     840                                             (LPVOID *)&pPf);
     841            if(FAILED(hres)) {
     842                /* bombed */
     843                ERR("failed QueryInterface for IPersistFile %08lx\n", hres);
     844                goto fail;
     845            }
     846
     847            /* Set the document path or pidl */
     848            if (uFlags & SHARD_PIDL) {
     849                hres = IShellLinkA_SetIDList(psl, (LPCITEMIDLIST) pv);
     850            } else {
     851                hres = IShellLinkA_SetPath(psl, (LPCSTR) pv);
     852            }
     853            if(FAILED(hres)) {
     854                /* bombed */
     855                ERR("failed Set{IDList|Path} %08lx\n", hres);
     856                goto fail;
     857            }
     858
     859            lstrcpyA(desc, "Shortcut to ");
     860            lstrcatA(desc, doc_name);
     861            hres = IShellLinkA_SetDescription(psl, desc);
     862            if(FAILED(hres)) {
     863                /* bombed */
     864                ERR("failed SetDescription %08lx\n", hres);
     865                goto fail;
     866            }
     867
     868            MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1,
     869                                widelink, MAX_PATH);
     870            /* create the short cut */
     871            hres = IPersistFile_Save(pPf, widelink, TRUE);
     872            if(FAILED(hres)) {
     873                /* bombed */
     874                ERR("failed IPersistFile::Save %08lx\n", hres);
     875                IPersistFile_Release(pPf);
     876                IShellLinkA_Release(psl);
     877                goto fail;
     878            }
     879            hres = IPersistFile_SaveCompleted(pPf, widelink);
     880            IPersistFile_Release(pPf);
     881            IShellLinkA_Release(psl);
     882            TRACE("shortcut %s has been created, result=%08lx\n",
     883                  new_lnk_filepath, hres);
     884        }
     885        else {
     886            ERR("CoCreateInstance failed, hres=%08lx\n", hres);
     887        }
     888    }
     889
     890 fail:
     891    CoUninitialize();
     892
     893    /* all done */
     894    RegCloseKey(HCUbasekey);
     895    return 0;
     896}
     897
    455898/*************************************************************************
    456899 * SHCreateShellFolderViewEx                    [SHELL32.174]
     
    6661109}
    6671110/*************************************************************************
    668  * SHGetInstanceExplorer                        [SHELL32.256]
     1111 * SHGetInstanceExplorer                        [SHELL32.@]
    6691112 *
    6701113 * NOTES
     
    7171160}
    7181161/*************************************************************************
    719  * ReadCabinetState                             [NT 4.0:SHELL32.651]
     1162 * ReadCabinetState                             [SHELL32.651] NT 4.0
    7201163 *
    7211164 */
     
    7251168}
    7261169/*************************************************************************
    727  * WriteCabinetState                            [NT 4.0:SHELL32.652]
     1170 * WriteCabinetState                            [SHELL32.652] NT 4.0
    7281171 *
    7291172 */
     
    7411184}
    7421185/*************************************************************************
    743  * IsUserAdmin                                  [NT 4.0:SHELL32.680]
     1186 * IsUserAdmin                                  [SHELL32.680] NT 4.0
    7441187 *
    7451188 */
     
    8841327
    8851328/************************************************************************
    886  *      shell32_654                             [SHELL32.654]
     1329 *      @                               [SHELL32.654]
    8871330 *
    8881331 * NOTES: first parameter seems to be a pointer (same as passed to WriteCabinetState)
     
    9171360
    9181361/************************************************************************
    919  *      DoEnvironmentSubstA                     [SHELL32.1222]
     1362 *      DoEnvironmentSubstA                     [SHELL32.@]
    9201363 *
    9211364 */
     
    9271370
    9281371/************************************************************************
    929  *      DoEnvironmentSubstW                     [SHELL32.1223]
     1372 *      DoEnvironmentSubstW                     [SHELL32.@]
    9301373 *
    9311374 */
     
    9481391
    9491392/*************************************************************************
    950  *      shell32_243                             [SHELL32.243]
     1393 *      @                             [SHELL32.243]
    9511394 *
    9521395 * Win98+ by-ordinal routine.  In Win98 this routine returns zero and
     
    9611404
    9621405/*************************************************************************
    963  *      SHELL32_714     [SHELL32]
     1406 *      @       [SHELL32.714]
    9641407 */
    9651408DWORD WINAPI SHELL32_714(LPVOID x)
     
    9701413
    9711414/*************************************************************************
    972  *      SHAddFromPropSheetExtArray      [SHELL32]
     1415 *      SHAddFromPropSheetExtArray      [SHELL32.167]
    9731416 */
    9741417DWORD WINAPI SHAddFromPropSheetExtArray(DWORD a, DWORD b, DWORD c)
     
    9791422
    9801423/*************************************************************************
    981  *      SHCreatePropSheetExtArray       [SHELL32]
     1424 *      SHCreatePropSheetExtArray       [SHELL32.168]
    9821425 */
    9831426DWORD WINAPI SHCreatePropSheetExtArray(DWORD a, LPCSTR b, DWORD c)
     
    9881431
    9891432/*************************************************************************
    990  *      SHReplaceFromPropSheetExtArray  [SHELL]
     1433 *      SHReplaceFromPropSheetExtArray  [SHELL32.170]
    9911434 */
    9921435DWORD WINAPI SHReplaceFromPropSheetExtArray(DWORD a, DWORD b, DWORD c, DWORD d)
     
    9971440
    9981441/*************************************************************************
    999  *      SHDestroyPropSheetExtArray      [SHELL32]
     1442 *      SHDestroyPropSheetExtArray      [SHELL32.169]
    10001443 */
    10011444DWORD WINAPI SHDestroyPropSheetExtArray(DWORD a)
Note: See TracChangeset for help on using the changeset viewer.