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

devclass.c
Go to the documentation of this file.
00001 /*
00002  * SetupAPI device class-related functions
00003  *
00004  * Copyright 2000 Andreas Mohr for CodeWeavers
00005  *           2005-2006 Hervé Poussineau (hpoussin@reactos.org)
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "setupapi_private.h"
00023 
00024 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
00025 
00026 /* Unicode constants */
00027 static const WCHAR BackSlash[] = {'\\',0};
00028 static const WCHAR Class[]  = {'C','l','a','s','s',0};
00029 static const WCHAR ClassGUID[]  = {'C','l','a','s','s','G','U','I','D',0};
00030 static const WCHAR ClassInstall32[]  = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
00031 static const WCHAR DotServices[]  = {'.','S','e','r','v','i','c','e','s',0};
00032 static const WCHAR InterfaceInstall32[]  = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
00033 static const WCHAR SetupapiDll[]  = {'s','e','t','u','p','a','p','i','.','d','l','l',0};
00034 static const WCHAR Version[]  = {'V','e','r','s','i','o','n',0};
00035 
00036 typedef BOOL
00037 (WINAPI* PROPERTY_PAGE_PROVIDER) (
00038     IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
00039     IN LPFNADDPROPSHEETPAGE fAddFunc,
00040     IN LPARAM lParam);
00041 typedef BOOL
00042 (*UPDATE_CLASS_PARAM_HANDLER) (
00043     IN HDEVINFO DeviceInfoSet,
00044     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00045     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00046     IN DWORD ClassInstallParamsSize);
00047 
00048 static BOOL
00049 SETUP_PropertyChangeHandler(
00050     IN HDEVINFO DeviceInfoSet,
00051     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00052     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00053     IN DWORD ClassInstallParamsSize);
00054 
00055 static BOOL
00056 SETUP_PropertyAddPropertyAdvancedHandler(
00057     IN HDEVINFO DeviceInfoSet,
00058     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00059     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00060     IN DWORD ClassInstallParamsSize);
00061 
00062 typedef struct _INSTALL_PARAMS_DATA
00063 {
00064     DI_FUNCTION Function;
00065     UPDATE_CLASS_PARAM_HANDLER UpdateHandler;
00066     ULONG ParamsSize;
00067     LONG FieldOffset;
00068 } INSTALL_PARAMS_DATA;
00069 
00070 #define ADD_PARAM_HANDLER(Function, UpdateHandler, ParamsType, ParamsField) \
00071     { Function, UpdateHandler, sizeof(ParamsType), FIELD_OFFSET(struct ClassInstallParams, ParamsField) },
00072 
00073 static const INSTALL_PARAMS_DATA InstallParamsData[] = {
00074     ADD_PARAM_HANDLER(DIF_PROPERTYCHANGE, SETUP_PropertyChangeHandler, SP_PROPCHANGE_PARAMS, PropChangeParams)
00075     ADD_PARAM_HANDLER(DIF_ADDPROPERTYPAGE_ADVANCED, SETUP_PropertyAddPropertyAdvancedHandler, SP_ADDPROPERTYPAGE_DATA, AddPropertyPageData)
00076 };
00077 #undef ADD_PARAM_HANDLER
00078 
00079 
00080 /***********************************************************************
00081  *      SetupDiDestroyClassImageList(SETUPAPI.@)
00082  */
00083 BOOL WINAPI
00084 SetupDiDestroyClassImageList(
00085     IN PSP_CLASSIMAGELIST_DATA ClassImageListData)
00086 {
00087     struct ClassImageList *list;
00088     BOOL ret = FALSE;
00089 
00090     TRACE("%p\n", ClassImageListData);
00091 
00092     if (!ClassImageListData)
00093         SetLastError(ERROR_INVALID_PARAMETER);
00094     else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
00095         SetLastError(ERROR_INVALID_USER_BUFFER);
00096     else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
00097         SetLastError(ERROR_INVALID_USER_BUFFER);
00098     else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
00099         SetLastError(ERROR_INVALID_USER_BUFFER);
00100     else
00101     {
00102         //DestroyIcon()
00103         //ImageList_Destroy();
00104         FIXME("Stub %p\n", ClassImageListData);
00105         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00106     }
00107 
00108     TRACE("Returning %d\n", ret);
00109     return ret;
00110 }
00111 
00112 /***********************************************************************
00113  *      SETUP_CreateDevicesListFromEnumerator
00114  *
00115  * PARAMS
00116  *   list [IO] Device info set to fill with discovered devices.
00117  *   pClassGuid [I] If specified, only devices which belong to this class will be added.
00118  *   Enumerator [I] Location to search devices to add.
00119  *   hEnumeratorKey [I] Registry key corresponding to Enumerator key. Must have KEY_ENUMERATE_SUB_KEYS right.
00120  *
00121  * RETURNS
00122  *   Success: ERROR_SUCCESS.
00123  *   Failure: an error code.
00124  */
00125 static LONG
00126 SETUP_CreateDevicesListFromEnumerator(
00127     IN OUT struct DeviceInfoSet *list,
00128     IN CONST GUID *pClassGuid OPTIONAL,
00129     IN LPCWSTR Enumerator,
00130     IN HKEY hEnumeratorKey) /* handle to Enumerator registry key */
00131 {
00132     HKEY hDeviceIdKey = NULL, hInstanceIdKey;
00133     WCHAR KeyBuffer[MAX_PATH];
00134     WCHAR InstancePath[MAX_PATH];
00135     LPWSTR pEndOfInstancePath; /* Pointer into InstancePath buffer */
00136     struct DeviceInfo *deviceInfo;
00137     DWORD i = 0, j;
00138     DWORD dwLength, dwRegType;
00139     DWORD rc;
00140 
00141     /* Enumerate device IDs (subkeys of hEnumeratorKey) */
00142     while (TRUE)
00143     {
00144         dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
00145         rc = RegEnumKeyExW(hEnumeratorKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
00146         if (rc == ERROR_NO_MORE_ITEMS)
00147             break;
00148         if (rc != ERROR_SUCCESS)
00149             goto cleanup;
00150         i++;
00151 
00152         /* Open device id sub key */
00153         if (hDeviceIdKey != NULL)
00154             RegCloseKey(hDeviceIdKey);
00155         rc = RegOpenKeyExW(hEnumeratorKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hDeviceIdKey);
00156         if (rc != ERROR_SUCCESS)
00157             goto cleanup;
00158         strcpyW(InstancePath, Enumerator);
00159         strcatW(InstancePath, BackSlash);
00160         strcatW(InstancePath, KeyBuffer);
00161         strcatW(InstancePath, BackSlash);
00162         pEndOfInstancePath = &InstancePath[strlenW(InstancePath)];
00163 
00164         /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
00165         j = 0;
00166         while (TRUE)
00167         {
00168             GUID KeyGuid;
00169 
00170             dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
00171             rc = RegEnumKeyExW(hDeviceIdKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
00172             if (rc == ERROR_NO_MORE_ITEMS)
00173                 break;
00174             if (rc != ERROR_SUCCESS)
00175                 goto cleanup;
00176             j++;
00177 
00178             /* Open instance id sub key */
00179             rc = RegOpenKeyExW(hDeviceIdKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hInstanceIdKey);
00180             if (rc != ERROR_SUCCESS)
00181                 goto cleanup;
00182             *pEndOfInstancePath = '\0';
00183             strcatW(InstancePath, KeyBuffer);
00184 
00185             /* Read ClassGUID value */
00186             dwLength = sizeof(KeyBuffer) - sizeof(WCHAR);
00187             rc = RegQueryValueExW(hInstanceIdKey, ClassGUID, NULL, &dwRegType, (LPBYTE)KeyBuffer, &dwLength);
00188             RegCloseKey(hInstanceIdKey);
00189             if (rc == ERROR_FILE_NOT_FOUND)
00190             {
00191                 if (pClassGuid)
00192                     /* Skip this bad entry as we can't verify it */
00193                     continue;
00194                 /* Set a default GUID for this device */
00195                 memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
00196             }
00197             else if (rc != ERROR_SUCCESS)
00198             {
00199                 goto cleanup;
00200             }
00201             else if (dwRegType != REG_SZ || dwLength < MAX_GUID_STRING_LEN * sizeof(WCHAR))
00202             {
00203                 rc = ERROR_GEN_FAILURE;
00204                 goto cleanup;
00205             }
00206             else
00207             {
00208                 KeyBuffer[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */
00209                 if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
00210                     /* Bad GUID, skip the entry */
00211                     continue;
00212             }
00213 
00214             if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
00215             {
00216                 /* Skip this entry as it is not the right device class */
00217                 continue;
00218             }
00219 
00220             /* Add the entry to the list */
00221             if (!CreateDeviceInfo(list, InstancePath, &KeyGuid, &deviceInfo))
00222             {
00223                 rc = GetLastError();
00224                 goto cleanup;
00225             }
00226             TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath), list);
00227             InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
00228         }
00229     }
00230 
00231     rc = ERROR_SUCCESS;
00232 
00233 cleanup:
00234     if (hDeviceIdKey != NULL)
00235         RegCloseKey(hDeviceIdKey);
00236     return rc;
00237 }
00238 
00239 LONG
00240 SETUP_CreateDevicesList(
00241     IN OUT struct DeviceInfoSet *list,
00242     IN PCWSTR MachineName OPTIONAL,
00243     IN CONST GUID *Class OPTIONAL,
00244     IN PCWSTR Enumerator OPTIONAL)
00245 {
00246     HKEY HKLM = HKEY_LOCAL_MACHINE;
00247     HKEY hEnumKey = NULL;
00248     HKEY hEnumeratorKey = NULL;
00249     WCHAR KeyBuffer[MAX_PATH];
00250     DWORD i;
00251     DWORD dwLength;
00252     DWORD rc;
00253 
00254     if (Class && IsEqualIID(Class, &GUID_NULL))
00255         Class = NULL;
00256 
00257     /* Open Enum key (if applicable) */
00258     if (MachineName != NULL)
00259     {
00260         rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
00261         if (rc != ERROR_SUCCESS)
00262             goto cleanup;
00263     }
00264 
00265     rc = RegOpenKeyExW(
00266         HKLM,
00267         REGSTR_PATH_SYSTEMENUM,
00268         0,
00269         KEY_ENUMERATE_SUB_KEYS,
00270         &hEnumKey);
00271     if (rc != ERROR_SUCCESS)
00272         goto cleanup;
00273 
00274     /* If enumerator is provided, call directly SETUP_CreateDevicesListFromEnumerator.
00275      * Else, enumerate all enumerators and call SETUP_CreateDevicesListFromEnumerator
00276      * for each one.
00277      */
00278     if (Enumerator)
00279     {
00280         rc = RegOpenKeyExW(
00281             hEnumKey,
00282             Enumerator,
00283             0,
00284             KEY_ENUMERATE_SUB_KEYS,
00285             &hEnumeratorKey);
00286         if (rc != ERROR_SUCCESS)
00287         {
00288             if (rc == ERROR_FILE_NOT_FOUND)
00289                 rc = ERROR_INVALID_DATA;
00290             goto cleanup;
00291         }
00292         rc = SETUP_CreateDevicesListFromEnumerator(list, Class, Enumerator, hEnumeratorKey);
00293     }
00294     else
00295     {
00296         /* Enumerate enumerators */
00297         i = 0;
00298         while (TRUE)
00299         {
00300             dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]);
00301             rc = RegEnumKeyExW(hEnumKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL);
00302             if (rc == ERROR_NO_MORE_ITEMS)
00303                 break;
00304             else if (rc != ERROR_SUCCESS)
00305                 goto cleanup;
00306             i++;
00307 
00308             /* Open sub key */
00309             if (hEnumeratorKey != NULL)
00310                 RegCloseKey(hEnumeratorKey);
00311             rc = RegOpenKeyExW(hEnumKey, KeyBuffer, 0, KEY_ENUMERATE_SUB_KEYS, &hEnumeratorKey);
00312             if (rc != ERROR_SUCCESS)
00313                 goto cleanup;
00314 
00315             /* Call SETUP_CreateDevicesListFromEnumerator */
00316             rc = SETUP_CreateDevicesListFromEnumerator(list, Class, KeyBuffer, hEnumeratorKey);
00317             if (rc != ERROR_SUCCESS)
00318                 goto cleanup;
00319         }
00320         rc = ERROR_SUCCESS;
00321     }
00322 
00323 cleanup:
00324     if (HKLM != HKEY_LOCAL_MACHINE)
00325         RegCloseKey(HKLM);
00326     if (hEnumKey != NULL)
00327         RegCloseKey(hEnumKey);
00328     if (hEnumeratorKey != NULL)
00329         RegCloseKey(hEnumeratorKey);
00330     return rc;
00331 }
00332 
00333 /***********************************************************************
00334  *      SetupDiGetClassImageIndex (SETUPAPI.@)
00335  */
00336 static BOOL
00337 SETUP_GetIconIndex(
00338     IN HKEY hClassKey,
00339     OUT PINT ImageIndex)
00340 {
00341     LPWSTR Buffer = NULL;
00342     DWORD dwRegType, dwLength;
00343     LONG rc;
00344     BOOL ret = FALSE;
00345 
00346     /* Read icon registry key */
00347     rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, &dwRegType, NULL, &dwLength);
00348     if (rc != ERROR_SUCCESS)
00349     {
00350         SetLastError(rc);
00351         goto cleanup;
00352     } else if (dwRegType != REG_SZ)
00353     {
00354         SetLastError(ERROR_INVALID_INDEX);
00355         goto cleanup;
00356     }
00357     Buffer = MyMalloc(dwLength + sizeof(WCHAR));
00358     if (!Buffer)
00359     {
00360         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00361         goto cleanup;
00362     }
00363     rc = RegQueryValueExW(hClassKey, REGSTR_VAL_INSICON, NULL, NULL, (LPBYTE)Buffer, &dwLength);
00364     if (rc != ERROR_SUCCESS)
00365     {
00366         SetLastError(rc);
00367         goto cleanup;
00368     }
00369     /* make sure the returned buffer is NULL-terminated */
00370     Buffer[dwLength / sizeof(WCHAR)] = 0;
00371 
00372     /* Transform icon value to a INT */
00373     *ImageIndex = atoiW(Buffer);
00374     ret = TRUE;
00375 
00376 cleanup:
00377     MyFree(Buffer);
00378     return ret;
00379 }
00380 
00381 BOOL WINAPI
00382 SetupDiGetClassImageIndex(
00383     IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
00384     IN CONST GUID *ClassGuid,
00385     OUT PINT ImageIndex)
00386 {
00387     struct ClassImageList *list;
00388     BOOL ret = FALSE;
00389 
00390     TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
00391 
00392     if (!ClassImageListData || !ClassGuid || !ImageIndex)
00393         SetLastError(ERROR_INVALID_PARAMETER);
00394     else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
00395         SetLastError(ERROR_INVALID_USER_BUFFER);
00396     else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
00397         SetLastError(ERROR_INVALID_USER_BUFFER);
00398     else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
00399         SetLastError(ERROR_INVALID_USER_BUFFER);
00400     else if (!ImageIndex)
00401         SetLastError(ERROR_INVALID_PARAMETER);
00402     else
00403     {
00404         DWORD i;
00405 
00406         for (i = 0; i < list->NumberOfGuids; i++)
00407         {
00408             if (IsEqualIID(ClassGuid, &list->Guids[i]))
00409                 break;
00410         }
00411 
00412         if (i == list->NumberOfGuids || list->IconIndexes[i] < 0)
00413             SetLastError(ERROR_FILE_NOT_FOUND);
00414         else
00415         {
00416             *ImageIndex = list->IconIndexes[i];
00417             ret = TRUE;
00418         }
00419     }
00420 
00421     TRACE("Returning %d\n", ret);
00422     return ret;
00423 }
00424 
00425 /***********************************************************************
00426  *      SetupDiGetClassImageList(SETUPAPI.@)
00427  */
00428 BOOL WINAPI
00429 SetupDiGetClassImageList(
00430     OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
00431 {
00432     return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
00433 }
00434 
00435 /***********************************************************************
00436  *      SetupDiGetClassImageListExA(SETUPAPI.@)
00437  */
00438 BOOL WINAPI
00439 SetupDiGetClassImageListExA(
00440     OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
00441     IN PCSTR MachineName OPTIONAL,
00442     IN PVOID Reserved)
00443 {
00444     PWSTR MachineNameW = NULL;
00445     BOOL ret;
00446 
00447     if (MachineName)
00448     {
00449         MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
00450         if (MachineNameW == NULL)
00451             return FALSE;
00452     }
00453 
00454     ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
00455 
00456     MyFree(MachineNameW);
00457 
00458     return ret;
00459 }
00460 
00461 /***********************************************************************
00462  *      SetupDiGetClassImageListExW(SETUPAPI.@)
00463  */
00464 BOOL WINAPI
00465 SetupDiGetClassImageListExW(
00466     OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
00467     IN PCWSTR MachineName OPTIONAL,
00468     IN PVOID Reserved)
00469 {
00470     BOOL ret = FALSE;
00471 
00472     TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
00473 
00474     if (!ClassImageListData)
00475         SetLastError(ERROR_INVALID_PARAMETER);
00476     else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
00477         SetLastError(ERROR_INVALID_USER_BUFFER);
00478     else if (Reserved)
00479         SetLastError(ERROR_INVALID_PARAMETER);
00480     else
00481     {
00482         struct ClassImageList *list = NULL;
00483         HDC hDC;
00484         DWORD RequiredSize;
00485         DWORD ilMask, bkColor;
00486         HICON hIcon;
00487         DWORD size;
00488         INT i, bpp;
00489 
00490         /* Get list of all class GUIDs in given computer */
00491         ret = SetupDiBuildClassInfoListExW(
00492             0,
00493             NULL,
00494             0,
00495             &RequiredSize,
00496             MachineName,
00497             NULL);
00498         if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
00499             goto cleanup;
00500 
00501         size = sizeof(struct ClassImageList)
00502             + (sizeof(GUID) + sizeof(INT)) * RequiredSize;
00503         list = HeapAlloc(GetProcessHeap(), 0, size);
00504         if (!list)
00505         {
00506             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00507             goto cleanup;
00508         }
00509         list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
00510         list->NumberOfGuids = RequiredSize;
00511         list->Guids = (GUID*)(list + 1);
00512         list->IconIndexes = (INT*)((ULONG_PTR)(list + 1) + sizeof(GUID) * RequiredSize);
00513 
00514         ret = SetupDiBuildClassInfoListExW(
00515             0,
00516             list->Guids,
00517             list->NumberOfGuids,
00518             &RequiredSize,
00519             MachineName,
00520             NULL);
00521         if (!ret)
00522             goto cleanup;
00523         else if (RequiredSize != list->NumberOfGuids)
00524         {
00525             /* Hm. Class list changed since last call. Ignore
00526              * this case as it should be very rare */
00527             SetLastError(ERROR_GEN_FAILURE);
00528             ret = FALSE;
00529             goto cleanup;
00530         }
00531 
00532         /* Prepare a HIMAGELIST */
00533         InitCommonControls();
00534 
00535         hDC = GetDC(NULL);
00536         if (!hDC)
00537             goto cleanup;
00538 
00539         bpp = GetDeviceCaps(hDC, BITSPIXEL);
00540         ReleaseDC(NULL, hDC);
00541 
00542         if (bpp <= 4)
00543             ilMask = ILC_COLOR4;
00544         else if (bpp <= 8)
00545             ilMask = ILC_COLOR8;
00546         else if (bpp <= 16)
00547             ilMask = ILC_COLOR16;
00548         else if (bpp <= 24)
00549             ilMask = ILC_COLOR24;
00550         else if (bpp <= 32)
00551             ilMask = ILC_COLOR32;
00552         else
00553             ilMask = ILC_COLOR;
00554 
00555         ilMask |= ILC_MASK;
00556 
00557         ClassImageListData->ImageList = ImageList_Create(16, 16, ilMask, 100, 10);
00558         if (!ClassImageListData->ImageList)
00559             goto cleanup;
00560 
00561         ClassImageListData->Reserved = (ULONG_PTR)list;
00562 
00563         /* For some reason, Windows sets the list background to COLOR_WINDOW */
00564         bkColor = GetSysColor(COLOR_WINDOW);
00565         ImageList_SetBkColor(ClassImageListData->ImageList, bkColor);
00566 
00567         /* Now, we "simply" need to load icons associated with all class guids,
00568          * and put their index in the image list in the IconIndexes array */
00569         for (i = 0; i < list->NumberOfGuids; i++)
00570         {
00571             INT miniIconIndex;
00572 
00573             ret = SetupDiLoadClassIcon(
00574                 &list->Guids[i],
00575                 NULL,
00576                 &miniIconIndex);
00577             if (ret)
00578             {
00579                 hIcon = LoadImage(hInstance, MAKEINTRESOURCE(miniIconIndex), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
00580                 if (hIcon)
00581                 {
00582                     list->IconIndexes[i] = ImageList_AddIcon(ClassImageListData->ImageList, hIcon);
00583                     DestroyIcon(hIcon);
00584                 }
00585                 else
00586                     list->IconIndexes[i] = -1;
00587             }
00588             else
00589                 list->IconIndexes[i] = -1; /* Special value to indicate that the icon is unavailable */
00590         }
00591 
00592         ret = TRUE;
00593 
00594 cleanup:
00595         if (!ret)
00596         {
00597             if (ClassImageListData->Reserved)
00598                 SetupDiDestroyClassImageList(ClassImageListData);
00599             else if (list)
00600                 MyFree(list);
00601         }
00602     }
00603 
00604     TRACE("Returning %d\n", ret);
00605     return ret;
00606 }
00607 
00608 /***********************************************************************
00609  *      SetupDiGetClassInstallParamsA(SETUPAPI.@)
00610  */
00611 BOOL WINAPI
00612 SetupDiGetClassInstallParamsA(
00613     IN HDEVINFO DeviceInfoSet,
00614     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00615     OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00616     IN DWORD ClassInstallParamsSize,
00617     OUT PDWORD RequiredSize OPTIONAL)
00618 {
00619     FIXME("SetupDiGetClassInstallParamsA(%p %p %p %lu %p) Stub\n",
00620         DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize, RequiredSize);
00621     return FALSE;
00622 }
00623 
00624 /***********************************************************************
00625  *      SetupDiGetClassInstallParamsW(SETUPAPI.@)
00626  */
00627 BOOL WINAPI
00628 SetupDiGetClassInstallParamsW(
00629     IN HDEVINFO DeviceInfoSet,
00630     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00631     OUT PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00632     IN DWORD ClassInstallParamsSize,
00633     OUT PDWORD RequiredSize OPTIONAL)
00634 {
00635     FIXME("SetupDiGetClassInstallParamsW(%p %p %p %lu %p) Stub\n",
00636         DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize, RequiredSize);
00637     return FALSE;
00638 }
00639 
00640 /***********************************************************************
00641  *      SetupDiLoadClassIcon(SETUPAPI.@)
00642  */
00643 BOOL WINAPI
00644 SetupDiLoadClassIcon(
00645     IN CONST GUID *ClassGuid,
00646     OUT HICON *LargeIcon OPTIONAL,
00647     OUT PINT MiniIconIndex OPTIONAL)
00648 {
00649     BOOL ret = FALSE;
00650 
00651     if (!ClassGuid)
00652         SetLastError(ERROR_INVALID_PARAMETER);
00653     else
00654     {
00655         LPWSTR Buffer = NULL;
00656         LPCWSTR DllName;
00657         INT iconIndex = 0;
00658         HKEY hKey = INVALID_HANDLE_VALUE;
00659 
00660         hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
00661         if (hKey == INVALID_HANDLE_VALUE)
00662             goto cleanup;
00663 
00664         if (!SETUP_GetIconIndex(hKey, &iconIndex))
00665             goto cleanup;
00666 
00667         if (iconIndex > 0)
00668         {
00669             /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
00670             PWCHAR Comma;
00671             LONG rc;
00672             DWORD dwRegType, dwLength;
00673             rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
00674             if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
00675             {
00676                 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
00677                 if (Buffer == NULL)
00678                 {
00679                     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00680                     goto cleanup;
00681                 }
00682                 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
00683                 if (rc != ERROR_SUCCESS)
00684                 {
00685                     SetLastError(rc);
00686                     goto cleanup;
00687                 }
00688                 /* make sure the returned buffer is NULL-terminated */
00689                 Buffer[dwLength / sizeof(WCHAR)] = 0;
00690             }
00691             else if
00692                 (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength))
00693                 && dwRegType == REG_SZ)
00694             {
00695                 Buffer = MyMalloc(dwLength + sizeof(WCHAR));
00696                 if (Buffer == NULL)
00697                 {
00698                     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00699                     goto cleanup;
00700                 }
00701                 rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)Buffer, &dwLength);
00702                 if (rc != ERROR_SUCCESS)
00703                 {
00704                     SetLastError(rc);
00705                     goto cleanup;
00706                 }
00707                 /* make sure the returned buffer is NULL-terminated */
00708                 Buffer[dwLength / sizeof(WCHAR)] = 0;
00709             }
00710             else
00711             {
00712                 /* Unable to find where to load the icon */
00713                 SetLastError(ERROR_FILE_NOT_FOUND);
00714                 goto cleanup;
00715             }
00716             Comma = strchrW(Buffer, ',');
00717             if (!Comma)
00718             {
00719                 SetLastError(ERROR_GEN_FAILURE);
00720                 goto cleanup;
00721             }
00722             *Comma = '\0';
00723             DllName = Buffer;
00724         }
00725         else
00726         {
00727             /* Look up icon in setupapi.dll */
00728             DllName = SetupapiDll;
00729             iconIndex = -iconIndex;
00730         }
00731 
00732         TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
00733         if (LargeIcon)
00734         {
00735             *LargeIcon = LoadImage(hInstance, MAKEINTRESOURCE(iconIndex), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
00736             if (!*LargeIcon)
00737             {
00738                 SetLastError(ERROR_INVALID_INDEX);
00739                 goto cleanup;
00740             }
00741         }
00742         if (MiniIconIndex)
00743             *MiniIconIndex = iconIndex;
00744         ret = TRUE;
00745 
00746 cleanup:
00747         if (hKey != INVALID_HANDLE_VALUE)
00748             RegCloseKey(hKey);
00749         MyFree(Buffer);
00750     }
00751 
00752     TRACE("Returning %d\n", ret);
00753     return ret;
00754 }
00755 
00756 /***********************************************************************
00757  *      SetupDiInstallClassExW (SETUPAPI.@)
00758  */
00759 HKEY
00760 SETUP_CreateClassKey(HINF hInf);
00761 BOOL WINAPI
00762 SetupDiInstallClassExW(
00763     IN HWND hwndParent OPTIONAL,
00764     IN PCWSTR InfFileName OPTIONAL,
00765     IN DWORD Flags,
00766     IN HSPFILEQ FileQueue OPTIONAL,
00767     IN CONST GUID *InterfaceClassGuid OPTIONAL,
00768     IN PVOID Reserved1,
00769     IN PVOID Reserved2)
00770 {
00771     BOOL ret = FALSE;
00772 
00773     TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent, debugstr_w(InfFileName), Flags,
00774         FileQueue, debugstr_guid(InterfaceClassGuid), Reserved1, Reserved2);
00775 
00776     if (!InfFileName)
00777     {
00778         FIXME("Case not implemented: InfFileName NULL\n");
00779         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00780     }
00781     else if (Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL))
00782     {
00783         TRACE("Unknown flags: 0x%08lx\n", Flags & ~(DI_NOVCP | DI_NOBROWSE | DI_FORCECOPY | DI_QUIETINSTALL));
00784         SetLastError(ERROR_INVALID_FLAGS);
00785     }
00786     else if ((Flags & DI_NOVCP) && FileQueue == NULL)
00787         SetLastError(ERROR_INVALID_PARAMETER);
00788     else if (Reserved1 != NULL)
00789         SetLastError(ERROR_INVALID_PARAMETER);
00790     else if (Reserved2 != NULL)
00791         SetLastError(ERROR_INVALID_PARAMETER);
00792     else
00793     {
00794         HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
00795         SP_DEVINSTALL_PARAMS_W InstallParams;
00796         WCHAR SectionName[MAX_PATH];
00797         HINF hInf = INVALID_HANDLE_VALUE;
00798         HKEY hRootKey = INVALID_HANDLE_VALUE;
00799         PVOID callback_context = NULL;
00800 
00801         hDeviceInfo = SetupDiCreateDeviceInfoList(NULL, NULL);
00802         if (hDeviceInfo == INVALID_HANDLE_VALUE)
00803             goto cleanup;
00804 
00805         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
00806         if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
00807             goto cleanup;
00808         InstallParams.Flags &= ~(DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
00809         InstallParams.Flags |= Flags & (DI_NOVCP | DI_NOBROWSE | DI_QUIETINSTALL);
00810         if (Flags & DI_NOVCP)
00811             InstallParams.FileQueue = FileQueue;
00812         if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo, NULL, &InstallParams))
00813             goto cleanup;
00814 
00815         /* Open the .inf file */
00816         hInf = SetupOpenInfFileW(
00817             InfFileName,
00818             NULL,
00819             INF_STYLE_WIN4,
00820             NULL);
00821         if (hInf == INVALID_HANDLE_VALUE)
00822             goto cleanup;
00823 
00824         /* Try to append a layout file */
00825         SetupOpenAppendInfFileW(NULL, hInf, NULL);
00826 
00827         if (InterfaceClassGuid)
00828         {
00829             /* Retrieve the actual section name */
00830             ret = SetupDiGetActualSectionToInstallW(
00831                 hInf,
00832                 InterfaceInstall32,
00833                 SectionName,
00834                 MAX_PATH,
00835                 NULL,
00836                 NULL);
00837             if (!ret)
00838                 goto cleanup;
00839 
00840             /* Open registry key related to this interface */
00841             /* FIXME: What happens if the key doesn't exist? */
00842             hRootKey = SetupDiOpenClassRegKeyExW(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL);
00843             if (hRootKey == INVALID_HANDLE_VALUE)
00844                 goto cleanup;
00845 
00846             /* SetupDiCreateDeviceInterface??? */
00847             FIXME("Installing an interface is not implemented\n");
00848             SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00849         }
00850         else
00851         {
00852             /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
00853             hRootKey = SETUP_CreateClassKey(hInf);
00854             if (hRootKey == INVALID_HANDLE_VALUE)
00855                 goto cleanup;
00856 
00857             /* Retrieve the actual section name */
00858             ret = SetupDiGetActualSectionToInstallW(
00859                 hInf,
00860                 ClassInstall32,
00861                 SectionName,
00862                 MAX_PATH - strlenW(DotServices),
00863                 NULL,
00864                 NULL);
00865             if (!ret)
00866                 goto cleanup;
00867 
00868             callback_context = SetupInitDefaultQueueCallback(hwndParent);
00869             if (!callback_context)
00870                 goto cleanup;
00871 
00872             ret = SetupInstallFromInfSectionW(
00873                 hwndParent,
00874                 hInf,
00875                 SectionName,
00876                 SPINST_REGISTRY | SPINST_FILES | SPINST_BITREG | SPINST_INIFILES | SPINST_INI2REG,
00877                 hRootKey,
00878                 NULL, /* FIXME: SourceRootPath */
00879                 !(Flags & DI_NOVCP) && (Flags & DI_FORCECOPY) ? SP_COPY_FORCE_IN_USE : 0, /* CopyFlags */
00880                 SetupDefaultQueueCallbackW,
00881                 callback_context,
00882                 hDeviceInfo,
00883                 NULL);
00884             if (!ret)
00885                 goto cleanup;
00886 
00887             /* Install .Services section */
00888             lstrcatW(SectionName, DotServices);
00889             ret = SetupInstallServicesFromInfSectionExW(
00890                 hInf,
00891                 SectionName,
00892                 0,
00893                 hDeviceInfo,
00894                 NULL,
00895                 NULL,
00896                 NULL);
00897             if (!ret)
00898                 goto cleanup;
00899 
00900             ret = TRUE;
00901         }
00902 
00903 cleanup:
00904         if (hDeviceInfo != INVALID_HANDLE_VALUE)
00905             SetupDiDestroyDeviceInfoList(hDeviceInfo);
00906         if (hInf != INVALID_HANDLE_VALUE)
00907             SetupCloseInfFile(hInf);
00908         if (hRootKey != INVALID_HANDLE_VALUE)
00909             RegCloseKey(hRootKey);
00910         SetupTermDefaultQueueCallback(callback_context);
00911     }
00912 
00913     TRACE("Returning %d\n", ret);
00914     return ret;
00915 }
00916 
00917 /***********************************************************************
00918  *      Helper functions for SetupDiSetClassInstallParamsW
00919  */
00920 static BOOL
00921 SETUP_PropertyChangeHandler(
00922     IN HDEVINFO DeviceInfoSet,
00923     IN PSP_DEVINFO_DATA DeviceInfoData,
00924     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00925     IN DWORD ClassInstallParamsSize)
00926 {
00927     PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
00928     BOOL ret = FALSE;
00929 
00930     if (!DeviceInfoData)
00931         SetLastError(ERROR_INVALID_PARAMETER);
00932     else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
00933         SetLastError(ERROR_INVALID_PARAMETER);
00934     else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE
00935         && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE
00936         && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP)
00937         SetLastError(ERROR_INVALID_FLAGS);
00938     else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL
00939         && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
00940         SetLastError(ERROR_INVALID_FLAGS);
00941     else if (PropChangeParams
00942         && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP)
00943         && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
00944         SetLastError(ERROR_INVALID_USER_BUFFER);
00945     else
00946     {
00947         PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
00948         struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
00949         CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChangeParams;
00950 
00951         if (*CurrentPropChangeParams)
00952         {
00953             MyFree(*CurrentPropChangeParams);
00954             *CurrentPropChangeParams = NULL;
00955         }
00956         if (PropChangeParams)
00957         {
00958             *CurrentPropChangeParams = MyMalloc(ClassInstallParamsSize);
00959             if (!*CurrentPropChangeParams)
00960             {
00961                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00962                 goto done;
00963             }
00964             memcpy(*CurrentPropChangeParams, PropChangeParams, ClassInstallParamsSize);
00965         }
00966         ret = TRUE;
00967     }
00968 
00969 done:
00970     return ret;
00971 }
00972 
00973 static BOOL
00974 SETUP_PropertyAddPropertyAdvancedHandler(
00975     IN HDEVINFO DeviceInfoSet,
00976     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
00977     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
00978     IN DWORD ClassInstallParamsSize)
00979 {
00980     PSP_ADDPROPERTYPAGE_DATA AddPropertyPageData = (PSP_ADDPROPERTYPAGE_DATA)ClassInstallParams;
00981     BOOL ret = FALSE;
00982 
00983     if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
00984         SetLastError(ERROR_INVALID_PARAMETER);
00985     else if (AddPropertyPageData && AddPropertyPageData->Flags != 0)
00986         SetLastError(ERROR_INVALID_FLAGS);
00987     else if (AddPropertyPageData && AddPropertyPageData->NumDynamicPages >= MAX_INSTALLWIZARD_DYNAPAGES)
00988         SetLastError(ERROR_INVALID_USER_BUFFER);
00989     else
00990     {
00991         PSP_ADDPROPERTYPAGE_DATA *CurrentAddPropertyPageData;
00992         if (!DeviceInfoData)
00993         {
00994             struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
00995             CurrentAddPropertyPageData = &list->ClassInstallParams.AddPropertyPageData;
00996         }
00997         else
00998         {
00999             struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
01000             CurrentAddPropertyPageData = &deviceInfo->ClassInstallParams.AddPropertyPageData;
01001         }
01002         if (*CurrentAddPropertyPageData)
01003         {
01004             MyFree(*CurrentAddPropertyPageData);
01005             *CurrentAddPropertyPageData = NULL;
01006         }
01007         if (AddPropertyPageData)
01008         {
01009             *CurrentAddPropertyPageData = MyMalloc(ClassInstallParamsSize);
01010             if (!*CurrentAddPropertyPageData)
01011             {
01012                 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01013                 goto done;
01014             }
01015             memcpy(*CurrentAddPropertyPageData, AddPropertyPageData, ClassInstallParamsSize);
01016         }
01017         ret = TRUE;
01018     }
01019 
01020 done:
01021     return ret;
01022 }
01023 
01024 /***********************************************************************
01025  *      SetupDiSetClassInstallParamsW (SETUPAPI.@)
01026  */
01027 BOOL WINAPI
01028 SetupDiSetClassInstallParamsW(
01029     IN HDEVINFO DeviceInfoSet,
01030     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01031     IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
01032     IN DWORD ClassInstallParamsSize)
01033 {
01034     struct DeviceInfoSet *list;
01035     BOOL ret = FALSE;
01036 
01037     TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData,
01038         ClassInstallParams, ClassInstallParamsSize);
01039 
01040     if (!DeviceInfoSet)
01041         SetLastError(ERROR_INVALID_PARAMETER);
01042     else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
01043         SetLastError(ERROR_INVALID_HANDLE);
01044     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01045         SetLastError(ERROR_INVALID_HANDLE);
01046     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
01047         SetLastError(ERROR_INVALID_USER_BUFFER);
01048     else if (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER))
01049         SetLastError(ERROR_INVALID_USER_BUFFER);
01050     else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER))
01051         SetLastError(ERROR_INVALID_PARAMETER);
01052     else if (!ClassInstallParams && ClassInstallParamsSize != 0)
01053         SetLastError(ERROR_INVALID_PARAMETER);
01054     else
01055     {
01056         SP_DEVINSTALL_PARAMS_W InstallParams;
01057         BOOL Result;
01058 
01059         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
01060         Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
01061         if (!Result)
01062             goto done;
01063 
01064         if (ClassInstallParams)
01065         {
01066             DWORD i;
01067             /* Check parameters in ClassInstallParams */
01068             for (i = 0; i < sizeof(InstallParamsData) / sizeof(InstallParamsData[0]); i++)
01069             {
01070                 if (InstallParamsData[i].Function == ClassInstallParams->InstallFunction)
01071                 {
01072                     ret = InstallParamsData[i].UpdateHandler(
01073                         DeviceInfoSet,
01074                         DeviceInfoData,
01075                         ClassInstallParams,
01076                         ClassInstallParamsSize);
01077                     if (ret)
01078                     {
01079                         InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
01080                         ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
01081                     }
01082                     goto done;
01083                 }
01084             }
01085             ERR("InstallFunction %u has no associated update handler\n", ClassInstallParams->InstallFunction);
01086             SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
01087             goto done;
01088         }
01089         else
01090         {
01091             InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS;
01092             ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
01093         }
01094     }
01095 
01096 done:
01097     TRACE("Returning %d\n", ret);
01098     return ret;
01099 }
01100 
01101 /***********************************************************************
01102  *      SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
01103  */
01104 BOOL WINAPI
01105 SetupDiGetClassDevPropertySheetsA(
01106     IN HDEVINFO DeviceInfoSet,
01107     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01108     IN LPPROPSHEETHEADERA PropertySheetHeader,
01109     IN DWORD PropertySheetHeaderPageListSize,
01110     OUT PDWORD RequiredSize OPTIONAL,
01111     IN DWORD PropertySheetType)
01112 {
01113     PROPSHEETHEADERW psh;
01114     BOOL ret = FALSE;
01115 
01116     TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
01117         PropertySheetHeader, PropertySheetHeaderPageListSize,
01118         RequiredSize, PropertySheetType);
01119 
01120     psh.dwFlags = PropertySheetHeader->dwFlags;
01121     psh.phpage = PropertySheetHeader->phpage;
01122     psh.nPages = PropertySheetHeader->nPages;
01123 
01124     ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
01125                                             PropertySheetHeaderPageListSize, RequiredSize,
01126                                             PropertySheetType);
01127     if (ret)
01128     {
01129         PropertySheetHeader->nPages = psh.nPages;
01130     }
01131 
01132     TRACE("Returning %d\n", ret);
01133     return ret;
01134 }
01135 
01136 struct ClassDevPropertySheetsData
01137 {
01138     LPPROPSHEETHEADERW PropertySheetHeader;
01139     DWORD PropertySheetHeaderPageListSize;
01140     DWORD NumberOfPages;
01141     BOOL DontCancel;
01142 };
01143 
01144 static BOOL WINAPI
01145 SETUP_GetClassDevPropertySheetsCallback(
01146     IN HPROPSHEETPAGE hPropSheetPage,
01147     IN OUT LPARAM lParam)
01148 {
01149     struct ClassDevPropertySheetsData *PropPageData;
01150 
01151     PropPageData = (struct ClassDevPropertySheetsData *)lParam;
01152 
01153     PropPageData->NumberOfPages++;
01154 
01155     if (PropPageData->PropertySheetHeader->nPages < PropPageData->PropertySheetHeaderPageListSize)
01156     {
01157         PropPageData->PropertySheetHeader->phpage[PropPageData->PropertySheetHeader->nPages] = hPropSheetPage;
01158         PropPageData->PropertySheetHeader->nPages++;
01159         return TRUE;
01160     }
01161 
01162     return PropPageData->DontCancel;
01163 }
01164 
01165 /***********************************************************************
01166  *      SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
01167  */
01168 BOOL WINAPI
01169 SetupDiGetClassDevPropertySheetsW(
01170     IN HDEVINFO DeviceInfoSet,
01171     IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
01172     IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
01173     IN DWORD PropertySheetHeaderPageListSize,
01174     OUT PDWORD RequiredSize OPTIONAL,
01175     IN DWORD PropertySheetType)
01176 {
01177     struct DeviceInfoSet *list;
01178     BOOL ret = FALSE;
01179 
01180     TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
01181         PropertySheetHeader, PropertySheetHeaderPageListSize,
01182         RequiredSize, PropertySheetType);
01183 
01184     if (!DeviceInfoSet)
01185         SetLastError(ERROR_INVALID_HANDLE);
01186     else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01187         SetLastError(ERROR_INVALID_HANDLE);
01188     else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
01189         SetLastError(ERROR_INVALID_HANDLE);
01190     else if (!PropertySheetHeader)
01191         SetLastError(ERROR_INVALID_PARAMETER);
01192     else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
01193         SetLastError(ERROR_INVALID_FLAGS);
01194     else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
01195         SetLastError(ERROR_INVALID_USER_BUFFER);
01196     else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
01197         SetLastError(ERROR_INVALID_PARAMETER);
01198     else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
01199           && PropertySheetType != DIGCDP_FLAG_BASIC
01200           && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
01201           && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
01202         SetLastError(ERROR_INVALID_PARAMETER);
01203     else
01204     {
01205         HKEY hKey = INVALID_HANDLE_VALUE;
01206         SP_PROPSHEETPAGE_REQUEST Request;
01207         LPWSTR PropPageProvider = NULL;
01208         HMODULE hModule = NULL;
01209         PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
01210         struct ClassDevPropertySheetsData PropPageData;
01211         DWORD dwLength, dwRegType;
01212         DWORD InitialNumberOfPages;
01213         DWORD rc;
01214 
01215         if (DeviceInfoData)
01216             hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
01217         else
01218         {
01219             hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
01220                 DIOCR_INSTALLER, list->MachineName + 2, NULL);
01221         }
01222         if (hKey == INVALID_HANDLE_VALUE)
01223             goto cleanup;
01224 
01225         rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, &dwRegType, NULL, &dwLength);
01226         if (rc == ERROR_FILE_NOT_FOUND)
01227         {
01228             /* No registry key. As it is optional, don't say it's a bad error */
01229             if (RequiredSize)
01230                 *RequiredSize = 0;
01231             ret = TRUE;
01232             goto cleanup;
01233         }
01234         else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
01235         {
01236             SetLastError(rc);
01237             goto cleanup;
01238         }
01239 
01240         PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
01241         if (!PropPageProvider)
01242         {
01243             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
01244             goto cleanup;
01245         }
01246         rc = RegQueryValueExW(hKey, REGSTR_VAL_ENUMPROPPAGES_32, NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
01247         if (rc != ERROR_SUCCESS)
01248         {
01249             SetLastError(rc);
01250             goto cleanup;
01251         }
01252         PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
01253 
01254         rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
01255         if (rc != ERROR_SUCCESS)
01256         {
01257             SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
01258             goto cleanup;
01259         }
01260 
01261         InitialNumberOfPages = PropertySheetHeader->nPages;
01262 
01263         Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
01264         Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
01265         Request.DeviceInfoSet = DeviceInfoSet;
01266         Request.DeviceInfoData = DeviceInfoData;
01267 
01268         PropPageData.PropertySheetHeader = PropertySheetHeader;
01269         PropPageData.PropertySheetHeaderPageListSize = PropertySheetHeaderPageListSize;
01270         PropPageData.NumberOfPages = 0;
01271         PropPageData.DontCancel = (RequiredSize != NULL) ? TRUE : FALSE;
01272 
01273         pPropPageProvider(&Request, SETUP_GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
01274 
01275         if (RequiredSize)
01276             *RequiredSize = PropPageData.NumberOfPages;
01277 
01278         if (InitialNumberOfPages + PropPageData.NumberOfPages <= PropertySheetHeaderPageListSize)
01279         {
01280             ret = TRUE;
01281         }
01282         else
01283         {
01284             SetLastError(ERROR_INSUFFICIENT_BUFFER);
01285         }
01286 
01287 cleanup:
01288         if (hKey != INVALID_HANDLE_VALUE)
01289             RegCloseKey(hKey);
01290         HeapFree(GetProcessHeap(), 0, PropPageProvider);
01291         FreeFunctionPointer(hModule, pPropPageProvider);
01292     }
01293 
01294     TRACE("Returning %d\n", ret);
01295     return ret;
01296 }

Generated on Thu May 24 2012 04:26:40 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.