Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendevclass.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
1.7.6.1
|