Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1199 lines
29 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: dvdprop.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "propp.h"
  11. #include "ntddcdvd.h"
  12. #include "dvdprop.h"
  13. #include "volprop.h"
  14. #include "resource.h"
  15. //
  16. // Instantiate the device interface GUIDs defined in ntddstor.h in this module
  17. //
  18. #include <initguid.h>
  19. #include <ntddstor.h>
  20. //
  21. // Help ID mapping for context sensitive help
  22. //
  23. const DWORD DvdHelpIDs[]=
  24. {
  25. IDC_CURRENT_REGION, IDH_DEVMGR_DVD_CURRENT, //Current region box
  26. IDC_NEW_REGION, IDH_DEVMGR_DVD_NEW, //New region box
  27. IDC_DVD_COUNTRY_LIST, IDH_DEVMGR_DVD_LIST, //List box
  28. IDC_DVD_HELP, IDH_DEVMGR_DVD_NOHELP,
  29. IDC_CHANGE_TEXT, IDH_DEVMGR_DVD_NOHELP,
  30. 0, 0
  31. };
  32. ULONG RegionIndexTable[MAX_REGIONS] = {
  33. DVD_REGION1_00,
  34. DVD_REGION2_00,
  35. DVD_REGION3_00,
  36. DVD_REGION4_00,
  37. DVD_REGION5_00,
  38. DVD_REGION6_00
  39. };
  40. ULONG RegionSizeTable[MAX_REGIONS] = {
  41. DVD_MAX_REGION1,
  42. DVD_MAX_REGION2,
  43. DVD_MAX_REGION3,
  44. DVD_MAX_REGION4,
  45. DVD_MAX_REGION5,
  46. DVD_MAX_REGION6
  47. };
  48. BOOL
  49. IsUserAdmin(
  50. VOID
  51. );
  52. PPAGE_INFO DvdCreatePageInfo(IN HDEVINFO deviceInfoSet,
  53. IN PSP_DEVINFO_DATA deviceInfoData)
  54. {
  55. PPAGE_INFO tmp = NULL;
  56. if (!(tmp = LocalAlloc(LPTR, sizeof(PAGE_INFO)))) {
  57. return NULL;
  58. }
  59. memset (tmp, 0, sizeof(PAGE_INFO));
  60. tmp->deviceInfoSet = deviceInfoSet;
  61. tmp->deviceInfoData = deviceInfoData;
  62. return tmp;
  63. }
  64. void
  65. DvdDestroyPageInfo(PPAGE_INFO * ppPageInfo)
  66. {
  67. PPAGE_INFO ppi = *ppPageInfo;
  68. LocalFree(ppi);
  69. *ppPageInfo = NULL;
  70. }
  71. HPROPSHEETPAGE
  72. DvdCreatePropertyPage(PROPSHEETPAGE * ppsp,
  73. PPAGE_INFO ppi)
  74. {
  75. //
  76. // Add the Port Settings property page
  77. //
  78. ppsp->dwSize = sizeof(PROPSHEETPAGE);
  79. ppsp->dwFlags = PSP_USECALLBACK; // | PSP_HASHELP;
  80. ppsp->hInstance = ModuleInstance;
  81. ppsp->pszTemplate = MAKEINTRESOURCE(ID_DVD_PROPPAGE);
  82. //
  83. // following points to the dlg window proc
  84. //
  85. ppsp->pfnDlgProc = DvdDlgProc;
  86. ppsp->lParam = (LPARAM) ppi;
  87. //
  88. // Following points to the control callback of the dlg window proc.
  89. // The callback gets called before creation/after destruction of the page
  90. //
  91. ppsp->pfnCallback = DvdDlgCallback;
  92. //
  93. // Allocate the actual page
  94. //
  95. return CreatePropertySheetPage(ppsp);
  96. }
  97. BOOL APIENTRY
  98. DvdPropPageProvider(LPVOID pinfo,
  99. LPFNADDPROPSHEETPAGE pfnAdd,
  100. LPARAM lParam)
  101. {
  102. PSP_PROPSHEETPAGE_REQUEST ppr;
  103. PROPSHEETPAGE psp;
  104. HPROPSHEETPAGE hpsp;
  105. PPAGE_INFO ppi = NULL;
  106. ppr = (PSP_PROPSHEETPAGE_REQUEST) pinfo;
  107. if (ppr->PageRequested == SPPSR_ENUM_ADV_DEVICE_PROPERTIES) {
  108. ppi = DvdCreatePageInfo(ppr->DeviceInfoSet,
  109. ppr->DeviceInfoData);
  110. if (!ppi) {
  111. return FALSE;
  112. }
  113. if (!GetCurrentRpcData(ppi, &ppi->regionData)) {
  114. //
  115. // not a DVD-ROM with RPC2 support
  116. //
  117. DvdDestroyPageInfo(&ppi);
  118. return FALSE;
  119. }
  120. memset(&psp, 0, sizeof(PROPSHEETPAGE));
  121. hpsp = DvdCreatePropertyPage(&psp, ppi);
  122. if (!hpsp) {
  123. return FALSE;
  124. }
  125. if (!pfnAdd(hpsp, lParam)) {
  126. DestroyPropertySheetPage(hpsp);
  127. return FALSE;
  128. }
  129. }
  130. return TRUE;
  131. }
  132. UINT CALLBACK
  133. DvdDlgCallback(HWND hwnd,
  134. UINT uMsg,
  135. LPPROPSHEETPAGE ppsp)
  136. {
  137. PPAGE_INFO ppi;
  138. switch (uMsg) {
  139. case PSPCB_CREATE:
  140. return TRUE; // return TRUE to continue with creation of page
  141. case PSPCB_RELEASE:
  142. ppi = (PPAGE_INFO) ppsp->lParam;
  143. DvdDestroyPageInfo(&ppi);
  144. return 0; // return value ignored
  145. default:
  146. break;
  147. }
  148. return TRUE;
  149. }
  150. void
  151. DvdInitializeControls(PPAGE_INFO ppi,
  152. HWND hDlg)
  153. {
  154. DWORD dwError;
  155. DWORD dwType;
  156. DWORD dwSize;
  157. BOOL disableControls = FALSE;
  158. HWND hwnd;
  159. ULONG i;
  160. ULONG j;
  161. TCHAR buffer[1000];
  162. hwnd = GetDlgItem(hDlg, IDC_DVD_COUNTRY_LIST);
  163. for (i=0; i<MAX_REGIONS; i++) {
  164. for (j=0; j<RegionSizeTable[i]; j++) {
  165. if (LoadString(ModuleInstance,
  166. RegionIndexTable[i] + j,
  167. buffer,
  168. 100)) {
  169. SendMessage(hwnd,
  170. LB_ADDSTRING,
  171. 0,
  172. (LPARAM) buffer);
  173. }
  174. }
  175. }
  176. hwnd = GetDlgItem(hDlg, IDC_DVD_HELP);
  177. if (LoadString(ModuleInstance,
  178. DVD_HELP,
  179. buffer,
  180. 1000)) {
  181. SendMessage(hwnd,
  182. WM_SETTEXT,
  183. 0,
  184. (LPARAM) buffer);
  185. }
  186. hwnd = GetDlgItem(hDlg, IDC_DVD_CAUTION);
  187. if (LoadString(ModuleInstance,
  188. DVD_CAUTION,
  189. buffer,
  190. 1000)) {
  191. SendMessage(hwnd,
  192. WM_SETTEXT,
  193. 0,
  194. (LPARAM) buffer);
  195. }
  196. hwnd = GetDlgItem(hDlg, IDC_DVD_CHANGE_HELP);
  197. if (LoadString(ModuleInstance,
  198. DVD_CHANGE_HELP,
  199. buffer,
  200. 1000)) {
  201. SendMessage(hwnd,
  202. WM_SETTEXT,
  203. 0,
  204. (LPARAM) buffer);
  205. }
  206. DvdUpdateCurrentSettings (ppi, hDlg);
  207. }
  208. BOOL
  209. DvdApplyChanges(PPAGE_INFO ppi,
  210. HWND hDlg)
  211. {
  212. UCHAR keyBuffer[DVD_SET_RPC_KEY_LENGTH];
  213. PDVD_COPY_PROTECT_KEY copyProtectKey;
  214. PDVD_SET_RPC_KEY rpcKey;
  215. ULONG i;
  216. BOOL popupError = FALSE;
  217. BOOL status;
  218. ULONG returned;
  219. TCHAR bufferFormat[500];
  220. TCHAR buffer[500];
  221. TCHAR titleBuffer[500];
  222. BOOL okToProceed;
  223. HANDLE writeHandle = INVALID_HANDLE_VALUE;
  224. if ((ppi->newRegion == 0) ||
  225. (ppi->currentRegion == ppi->newRegion)) {
  226. //
  227. // nothing to do
  228. //
  229. return TRUE;
  230. }
  231. //
  232. // confirm with the user
  233. //
  234. okToProceed = FALSE;
  235. if (ppi->regionData.ResetCount == 1) {
  236. if (LoadString(ModuleInstance,
  237. DVD_SET_RPC_CONFIRM_LAST_CHANCE,
  238. buffer,
  239. 500) &&
  240. LoadString(ModuleInstance,
  241. DVD_SET_RPC_CONFIRM_TITLE,
  242. titleBuffer,
  243. 500)) {
  244. if (MessageBox(hDlg,
  245. buffer,
  246. titleBuffer,
  247. MB_ICONEXCLAMATION | MB_OKCANCEL |
  248. MB_DEFBUTTON2 | MB_APPLMODAL) == IDOK) {
  249. okToProceed = TRUE;
  250. }
  251. }
  252. } else {
  253. if (LoadString(ModuleInstance,
  254. DVD_SET_RPC_CONFIRM,
  255. bufferFormat,
  256. 500) &&
  257. LoadString(ModuleInstance,
  258. DVD_SET_RPC_CONFIRM_TITLE,
  259. titleBuffer,
  260. 500)) {
  261. wsprintf (buffer, bufferFormat, ppi->newRegion);
  262. if (MessageBox(hDlg,
  263. buffer,
  264. titleBuffer,
  265. MB_ICONEXCLAMATION | MB_OKCANCEL |
  266. MB_DEFBUTTON2 | MB_APPLMODAL) == IDOK) {
  267. okToProceed = TRUE;
  268. }
  269. }
  270. }
  271. if (okToProceed == FALSE) {
  272. return FALSE;
  273. }
  274. //
  275. // make sure the drive has a dvd with the same region
  276. // call GetCurrentRpcData
  277. //
  278. writeHandle = UtilpGetDeviceHandle(ppi->deviceInfoSet,
  279. ppi->deviceInfoData,
  280. (LPGUID)&CdRomClassGuid,
  281. GENERIC_READ | GENERIC_WRITE);
  282. if (writeHandle != INVALID_HANDLE_VALUE) {
  283. copyProtectKey = (PDVD_COPY_PROTECT_KEY) keyBuffer;
  284. memset(copyProtectKey, 0, DVD_SET_RPC_KEY_LENGTH);
  285. copyProtectKey->KeyLength = DVD_SET_RPC_KEY_LENGTH;
  286. copyProtectKey->KeyType = DvdSetRpcKey;
  287. rpcKey = (PDVD_SET_RPC_KEY) copyProtectKey->KeyData;
  288. rpcKey->PreferredDriveRegionCode = ~(1 << (ppi->newRegion - 1));
  289. status = DeviceIoControl(writeHandle,
  290. IOCTL_DVD_SEND_KEY2,
  291. copyProtectKey,
  292. DVD_SET_RPC_KEY_LENGTH,
  293. NULL,
  294. 0,
  295. &returned,
  296. FALSE);
  297. CloseHandle (writeHandle);
  298. } else {
  299. status = 0;
  300. }
  301. if (!status) {
  302. if (LoadString(ModuleInstance,
  303. DVD_SET_RPC_ERROR,
  304. bufferFormat,
  305. 500) &&
  306. LoadString(ModuleInstance,
  307. DVD_SET_RPC_ERROR_TITLE,
  308. titleBuffer,
  309. 500)) {
  310. wsprintf (buffer, bufferFormat, ppi->newRegion);
  311. MessageBox(hDlg,
  312. buffer,
  313. titleBuffer,
  314. MB_ICONERROR | MB_OK);
  315. }
  316. return FALSE;
  317. } else {
  318. GetCurrentRpcData(ppi, &ppi->regionData);
  319. return TRUE;
  320. }
  321. }
  322. INT_PTR APIENTRY
  323. DvdDlgProc(IN HWND hDlg,
  324. IN UINT uMessage,
  325. IN WPARAM wParam,
  326. IN LPARAM lParam)
  327. {
  328. PPAGE_INFO ppi;
  329. ppi = (PPAGE_INFO) GetWindowLongPtr(hDlg, DWLP_USER);
  330. switch (uMessage) {
  331. case WM_INITDIALOG:
  332. //
  333. // on WM_INITDIALOG call, lParam points to the property
  334. // sheet page.
  335. //
  336. // The lParam field in the property sheet page struct is set by the
  337. // caller. When I created the property sheet, I passed in a pointer
  338. // to a struct containing information about the device. Save this in
  339. // the user window long so I can access it on later messages.
  340. //
  341. ppi = (PPAGE_INFO) ((LPPROPSHEETPAGE)lParam)->lParam;
  342. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) ppi);
  343. //
  344. // Initialize dlg controls
  345. //
  346. DvdInitializeControls(ppi, hDlg);
  347. //
  348. // Didn't set the focus to a particular control. If we wanted to,
  349. // then return FALSE
  350. //
  351. return TRUE;
  352. case WM_COMMAND:
  353. switch (HIWORD(wParam)) {
  354. case CBN_SELCHANGE:
  355. PropSheet_Changed(GetParent(hDlg), hDlg);
  356. DvdUpdateNewRegionBox (ppi, hDlg);
  357. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LONG_PTR) PSNRET_NOERROR);
  358. return TRUE;
  359. default:
  360. break;
  361. }
  362. switch(LOWORD(wParam)) {
  363. default:
  364. break;
  365. }
  366. break;
  367. case WM_CONTEXTMENU:
  368. return DvdContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  369. case WM_HELP:
  370. DvdHelp(hDlg, (LPHELPINFO) lParam);
  371. break;
  372. case WM_NOTIFY:
  373. switch (((NMHDR *)lParam)->code) {
  374. // case PSN_KILLACTIVE:
  375. // if (ppi->changesFailed) {
  376. //
  377. // SetWindowLong(hDlg, DWL_MSGRESULT, TRUE);
  378. // } else {
  379. //
  380. // SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
  381. // }
  382. // return TRUE;
  383. //
  384. // Sent when the user clicks on Apply OR OK !!
  385. //
  386. case PSN_APPLY:
  387. //
  388. // Do what ever action is necessary
  389. //
  390. if (DvdApplyChanges(ppi, hDlg)) {
  391. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  392. ppi->changesFailed = FALSE;
  393. DvdUpdateCurrentSettings(ppi, hDlg);
  394. } else {
  395. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  396. ppi->changesFailed = TRUE;
  397. }
  398. return TRUE;
  399. default:
  400. break;
  401. }
  402. break;
  403. }
  404. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  405. return FALSE;
  406. }
  407. void
  408. DvdUpdateNewRegionBox (PPAGE_INFO ppi,
  409. HWND hDlg)
  410. {
  411. HWND hwnd;
  412. ULONG selectionIndex;
  413. WCHAR buffer[100];
  414. ULONG currentRegion;
  415. BOOL status;
  416. //
  417. // new region code
  418. //
  419. hwnd = GetDlgItem(hDlg, IDC_DVD_COUNTRY_LIST);
  420. //
  421. // NOTE: SendMessage() will return 64-bit result in Sundown
  422. //
  423. selectionIndex = (ULONG) SendMessage(hwnd,
  424. LB_GETCURSEL,
  425. (WPARAM) 0,
  426. (LPARAM) 0);
  427. if (selectionIndex != LB_ERR) {
  428. if (LB_ERR != SendMessage(hwnd,
  429. LB_GETTEXT,
  430. selectionIndex,
  431. (LPARAM) buffer)) {
  432. ppi->newRegion = DvdCountryToRegion (buffer);
  433. if (ppi->newRegion != -1) {
  434. if (LoadString(ModuleInstance,
  435. DVD_REGION1_NAME + ppi->newRegion - 1,
  436. buffer,
  437. 100)) {
  438. hwnd = GetDlgItem(hDlg, IDC_NEW_REGION);
  439. SendMessage(hwnd,
  440. WM_SETTEXT,
  441. 0,
  442. (LPARAM) buffer);
  443. }
  444. }
  445. }
  446. }
  447. }
  448. ULONG
  449. DvdCountryToRegion (LPCTSTR Country)
  450. {
  451. ULONG i;
  452. ULONG j;
  453. WCHAR buffer[100];
  454. for (i=0; i<MAX_REGIONS; i++) {
  455. for (j=0; j<RegionSizeTable[i]; j++) {
  456. if (LoadString(ModuleInstance,
  457. RegionIndexTable[i] + j,
  458. buffer,
  459. 100)) {
  460. if (!wcscmp(buffer, Country)) {
  461. return i + 1;
  462. }
  463. }
  464. }
  465. }
  466. return -1;
  467. }
  468. BOOL
  469. GetCurrentRpcData(
  470. PPAGE_INFO ppi,
  471. PDVD_REGION regionData
  472. )
  473. {
  474. BOOL status;
  475. ULONG returned;
  476. UCHAR regionMask;
  477. UCHAR userResetsAvailable;
  478. HANDLE deviceHandle;
  479. PDVD_COPY_PROTECT_KEY copyProtectKey;
  480. PDVD_RPC_KEY rpcKey;
  481. ULONG rpcScheme;
  482. deviceHandle = UtilpGetDeviceHandle(ppi->deviceInfoSet,
  483. ppi->deviceInfoData,
  484. (LPGUID)&CdRomClassGuid,
  485. GENERIC_READ);
  486. if (deviceHandle == INVALID_HANDLE_VALUE) {
  487. return FALSE;
  488. }
  489. copyProtectKey = LocalAlloc(LPTR, DVD_RPC_KEY_LENGTH);
  490. if (copyProtectKey == NULL) {
  491. CloseHandle(deviceHandle);
  492. return FALSE;
  493. }
  494. copyProtectKey->KeyLength = DVD_RPC_KEY_LENGTH;
  495. copyProtectKey->KeyType = DvdGetRpcKey;
  496. returned = 0;
  497. status = DeviceIoControl(deviceHandle,
  498. IOCTL_DVD_READ_KEY,
  499. copyProtectKey,
  500. DVD_RPC_KEY_LENGTH,
  501. copyProtectKey,
  502. DVD_RPC_KEY_LENGTH,
  503. &returned,
  504. FALSE);
  505. //
  506. // this will default to not showing the property page
  507. //
  508. rpcScheme = 0;
  509. if (status && (returned == DVD_RPC_KEY_LENGTH)) {
  510. rpcKey = (PDVD_RPC_KEY) copyProtectKey->KeyData;
  511. rpcScheme = rpcKey->RpcScheme;
  512. regionMask = ~rpcKey->RegionMask;
  513. userResetsAvailable = rpcKey->UserResetsAvailable;
  514. DebugPrint((1, "Got %x user resets available\n", userResetsAvailable));
  515. } else {
  516. DebugPrint((1, "Maybe not a DVD drive?\n", status, returned));
  517. }
  518. LocalFree(copyProtectKey);
  519. if (rpcScheme == 0) {
  520. //
  521. // all region drive. no need to show the property sheet
  522. //
  523. DebugPrint((1, "All Region DVD-ROM Drive -- no property sheet\n"));
  524. CloseHandle(deviceHandle);
  525. return FALSE;
  526. }
  527. //
  528. // get region status
  529. //
  530. memset(regionData, 0, sizeof(DVD_REGION));
  531. status = DeviceIoControl(deviceHandle,
  532. IOCTL_DVD_GET_REGION,
  533. NULL,
  534. 0,
  535. regionData,
  536. sizeof(DVD_REGION),
  537. &returned,
  538. FALSE);
  539. if (!(status && (returned == sizeof(DVD_REGION)))) {
  540. //
  541. // no media in the drive
  542. //
  543. DebugPrint((1, "No media in drive? making up info\n"));
  544. regionData->CopySystem = 1;
  545. regionData->RegionData = 0xff;
  546. regionData->SystemRegion = regionMask;
  547. regionData->ResetCount = userResetsAvailable;
  548. }
  549. CloseHandle(deviceHandle);
  550. return TRUE;
  551. }
  552. ULONG
  553. DvdRegionMaskToRegionNumber (
  554. UCHAR PlayMask
  555. )
  556. {
  557. ULONG i;
  558. ULONG mask;
  559. if (!PlayMask) {
  560. return 0;
  561. }
  562. for (i=0, mask=1; i<8; i++, mask <<= 1) {
  563. if (PlayMask & mask) {
  564. return i + 1;
  565. }
  566. }
  567. return 0;
  568. }
  569. void
  570. DvdUpdateCurrentSettings (PPAGE_INFO ppi,
  571. HWND hDlg)
  572. {
  573. HWND hwnd;
  574. ULONG selectionIndex;
  575. WCHAR buffer[100];
  576. WCHAR formatBuffer[100];
  577. BOOL status;
  578. ppi->currentRegion = DvdRegionMaskToRegionNumber (
  579. ppi->regionData.SystemRegion
  580. );
  581. //
  582. // current region
  583. //
  584. if (ppi->currentRegion) {
  585. status = LoadString(ModuleInstance,
  586. DVD_REGION1_NAME + ppi->currentRegion - 1,
  587. buffer,
  588. 100);
  589. } else {
  590. status = LoadString(ModuleInstance,
  591. DVD_NOREGION_NAME,
  592. buffer,
  593. 100);
  594. }
  595. if (status) {
  596. hwnd = GetDlgItem(hDlg, IDC_CURRENT_REGION);
  597. SendMessage(hwnd,
  598. WM_SETTEXT,
  599. 0,
  600. (LPARAM) buffer);
  601. }
  602. //
  603. // region change limit
  604. //
  605. if (LoadString(ModuleInstance,
  606. DVD_CHANGE_TEXT,
  607. formatBuffer,
  608. 100)) {
  609. wsprintf (buffer, formatBuffer, (ULONG) ppi->regionData.ResetCount);
  610. hwnd = GetDlgItem(hDlg, IDC_CHANGE_TEXT);
  611. SendMessage(hwnd,
  612. WM_SETTEXT,
  613. 0,
  614. (LPARAM) buffer);
  615. }
  616. if (ppi->regionData.ResetCount == 0) {
  617. EnableWindow(GetDlgItem(hDlg, IDC_DVD_COUNTRY_LIST), FALSE);
  618. EnableWindow(GetDlgItem(hDlg, IDC_NEW_REGION), FALSE);
  619. }
  620. return;
  621. }
  622. //
  623. // SystemLocale2DvdRegion expects
  624. // this list to be sorted by LCID numbers
  625. //
  626. // Note: Due to PoliCheck, comments with
  627. // approximated region/country names
  628. // had to be removed.
  629. //
  630. LCID_2_DVD_TABLE Lcid2DvdTable[] = {
  631. {0x0401, 2},
  632. {0x0402, 2},
  633. {0x0403, 2},
  634. {0x0404, 3},
  635. {0x0405, 2},
  636. {0x0406, 2},
  637. {0x0407, 2},
  638. {0x0408, 2},
  639. {0x0409, 1},
  640. {0x040a, 2},
  641. {0x040b, 2},
  642. {0x040c, 2},
  643. {0x040d, 2},
  644. {0x040e, 2},
  645. {0x040f, 2},
  646. {0x0410, 2},
  647. {0x0411, 2},
  648. {0x0412, 3},
  649. {0x0413, 2},
  650. {0x0414, 2},
  651. {0x0415, 2},
  652. {0x0416, 4},
  653. {0x0418, 2},
  654. {0x0419, 5},
  655. {0x041a, 2},
  656. {0x041b, 2},
  657. {0x041c, 2},
  658. {0x041d, 2},
  659. {0x041e, 3},
  660. {0x041f, 2},
  661. {0x0420, 5},
  662. {0x0421, 3},
  663. {0x0422, 5},
  664. {0x0423, 5},
  665. {0x0424, 2},
  666. {0x0425, 5},
  667. {0x0426, 5},
  668. {0x0427, 5},
  669. {0x0429, 2},
  670. {0x042a, 3},
  671. {0x042b, 5},
  672. {0x042c, 5},
  673. {0x042d, 2},
  674. {0x042f, 2},
  675. {0x0436, 2},
  676. {0x0437, 5},
  677. {0x0438, 2},
  678. {0x0439, 5},
  679. {0x043e, 3},
  680. {0x043f, 5},
  681. {0x0441, 5},
  682. {0x0443, 5},
  683. {0x0444, 5},
  684. {0x0445, 5},
  685. {0x0446, 5},
  686. {0x0447, 5},
  687. {0x0448, 5},
  688. {0x0449, 5},
  689. {0x044a, 5},
  690. {0x044b, 5},
  691. {0x044c, 5},
  692. {0x044d, 5},
  693. {0x044e, 5},
  694. {0x044f, 5},
  695. {0x0457, 5},
  696. {0x0801, 2},
  697. {0x0804, 6},
  698. {0x0807, 2},
  699. {0x0809, 2},
  700. {0x080a, 4},
  701. {0x080c, 2},
  702. {0x0810, 2},
  703. {0x0813, 2},
  704. {0x0814, 2},
  705. {0x0816, 2},
  706. {0x081a, 2},
  707. {0x081d, 2},
  708. {0x0827, 5},
  709. {0x082c, 5},
  710. {0x083e, 3},
  711. {0x0843, 5},
  712. {0x0861, 5},
  713. {0x0c01, 2},
  714. {0x0c04, 3},
  715. {0x0c07, 2},
  716. {0x0c09, 4},
  717. {0x0c0a, 2},
  718. {0x0c0c, 1},
  719. {0x0c1a, 2},
  720. {0x1001, 5},
  721. {0x1004, 3},
  722. {0x1007, 2},
  723. {0x1009, 1},
  724. {0x100a, 4},
  725. {0x100c, 2},
  726. {0x1401, 5},
  727. {0x1404, 3},
  728. {0x1407, 2},
  729. {0x1409, 4},
  730. {0x140a, 4},
  731. {0x140c, 2},
  732. {0x1801, 5},
  733. {0x1809, 2},
  734. {0x180a, 4},
  735. {0x180c, 2},
  736. {0x1c01, 5},
  737. {0x1c09, 2},
  738. {0x1c0a, 4},
  739. {0x2001, 2},
  740. {0x2009, 4},
  741. {0x200a, 4},
  742. {0x2401, 2},
  743. {0x2409, 4},
  744. {0x240a, 4},
  745. {0x2801, 2},
  746. {0x2809, 4},
  747. {0x280a, 4},
  748. {0x2c01, 2},
  749. {0x2c09, 4},
  750. {0x2c0a, 4},
  751. {0x3001, 2},
  752. {0x3009, 5},
  753. {0x300a, 4},
  754. {0x3401, 2},
  755. {0x3409, 3},
  756. {0x340a, 4},
  757. {0x3801, 2},
  758. {0x380a, 4},
  759. {0x3c01, 2},
  760. {0x3c0a, 4},
  761. {0x4001, 2},
  762. {0x400a, 4},
  763. {0x440a, 4},
  764. {0x480a, 4},
  765. {0x4c0a, 4},
  766. {0x500a, 1}
  767. };
  768. #define NUM_LCID_ENTRIES (sizeof(Lcid2DvdTable)/sizeof(LCID_2_DVD_TABLE))
  769. DWORD
  770. SystemLocale2DvdRegion (
  771. LCID Lcid
  772. )
  773. {
  774. #define MID_INDEX(x,y) (((y-x)/2) + x)
  775. DWORD i;
  776. DWORD j;
  777. DWORD k;
  778. i=0;
  779. j=NUM_LCID_ENTRIES;
  780. while (1) {
  781. k = MID_INDEX(i,j);
  782. if (Lcid2DvdTable[k].Lcid != Lcid) {
  783. if (i == j) {
  784. //
  785. // not in the table,
  786. // return a default region of ZERO!!!
  787. //
  788. return 0;
  789. }
  790. if (Lcid2DvdTable[k].Lcid < Lcid) {
  791. i = k;
  792. } else { // Lcid2DvdTable[k].Lcid > Lcid
  793. j = k;
  794. }
  795. } else {
  796. return Lcid2DvdTable[k].DvdRegion;
  797. }
  798. }
  799. }
  800. DWORD
  801. DvdClassInstaller(
  802. IN DI_FUNCTION InstallFunction,
  803. IN HDEVINFO DeviceInfoSet,
  804. IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
  805. )
  806. /*++
  807. Routine Description:
  808. This routine acts as the class installer for hard disk controllers
  809. (IDE controllers/channels). It provides special handling for the
  810. following DeviceInstaller function codes:
  811. DIF_INSTALLDEVICE - get the system locale and write it to the driver key
  812. Arguments:
  813. InstallFunction - Specifies the device installer function code indicating
  814. the action being performed.
  815. DeviceInfoSet - Supplies a handle to the device information set being
  816. acted upon by this install action.
  817. DeviceInfoData - Optionally, supplies the address of a device information
  818. element being acted upon by this install action.
  819. Return Value:
  820. If this function successfully completed the requested action, the return
  821. value is NO_ERROR.
  822. If the default behavior is to be performed for the requested action, the
  823. return value is ERROR_DI_DO_DEFAULT.
  824. If an error occurred while attempting to perform the requested action, a
  825. Win32 error code is returned.
  826. --*/
  827. {
  828. switch(InstallFunction) {
  829. case DIF_ADDPROPERTYPAGE_ADVANCED:
  830. case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
  831. {
  832. //
  833. // get the current class install parameters for the device
  834. //
  835. SP_ADDPROPERTYPAGE_DATA AddPropertyPageData;
  836. //
  837. // DeviceInfoSet is NULL if setup is requesting property pages for
  838. // the device setup class. We don't want to do anything in this
  839. // case.
  840. //
  841. if (DeviceInfoData==NULL)
  842. return ERROR_DI_DO_DEFAULT;
  843. ZeroMemory(&AddPropertyPageData, sizeof(SP_ADDPROPERTYPAGE_DATA));
  844. AddPropertyPageData.ClassInstallHeader.cbSize =
  845. sizeof(SP_CLASSINSTALL_HEADER);
  846. if (SetupDiGetClassInstallParams(DeviceInfoSet, DeviceInfoData,
  847. (PSP_CLASSINSTALL_HEADER)&AddPropertyPageData,
  848. sizeof(SP_ADDPROPERTYPAGE_DATA), NULL ))
  849. {
  850. PVOLUME_PAGE_DATA pVolumePageData;
  851. HPROPSHEETPAGE pageHandle;
  852. PROPSHEETPAGE page;
  853. //
  854. // Ensure that the maximum number of dynamic pages for the
  855. // device has not yet been met
  856. //
  857. if (AddPropertyPageData.NumDynamicPages >=
  858. MAX_INSTALLWIZARD_DYNAPAGES)
  859. return NO_ERROR;
  860. if (IsUserAdmin())
  861. pVolumePageData = HeapAlloc(GetProcessHeap(), 0,
  862. sizeof(VOLUME_PAGE_DATA));
  863. else
  864. pVolumePageData = NULL;
  865. if (pVolumePageData)
  866. {
  867. HMODULE LdmModule;
  868. SP_DEVINFO_LIST_DETAIL_DATA DeviceInfoSetDetailData;
  869. //
  870. // Save DeviceInfoSet and DeviceInfoData
  871. //
  872. pVolumePageData->DeviceInfoSet = DeviceInfoSet;
  873. pVolumePageData->DeviceInfoData = DeviceInfoData;
  874. //
  875. // Create volume property sheet page
  876. //
  877. memset(&page, 0, sizeof(PROPSHEETPAGE));
  878. page.dwSize = sizeof(PROPSHEETPAGE);
  879. page.dwFlags = PSP_USECALLBACK;
  880. page.hInstance = ModuleInstance;
  881. page.pszTemplate = MAKEINTRESOURCE(ID_VOLUME_PROPPAGE);
  882. page.pfnDlgProc = VolumeDialogProc;
  883. page.pfnCallback = VolumeDialogCallback;
  884. page.lParam = (LPARAM) pVolumePageData;
  885. pageHandle = CreatePropertySheetPage(&page);
  886. if(!pageHandle)
  887. {
  888. HeapFree(GetProcessHeap(), 0, pVolumePageData);
  889. return NO_ERROR;
  890. }
  891. //
  892. // Add the new page to the list of dynamic property
  893. // sheets
  894. //
  895. AddPropertyPageData.DynamicPages[
  896. AddPropertyPageData.NumDynamicPages++]=pageHandle;
  897. //
  898. // Check if the property page is pulled up from disk manager.
  899. //
  900. pVolumePageData->bInvokedByDiskmgr = FALSE;
  901. LdmModule = GetModuleHandle(TEXT("dmdskmgr"));
  902. if ( LdmModule )
  903. {
  904. IS_REQUEST_PENDING pfnIsRequestPending;
  905. pfnIsRequestPending = (IS_REQUEST_PENDING)
  906. GetProcAddress(LdmModule, "IsRequestPending");
  907. if (pfnIsRequestPending)
  908. {
  909. if ((*pfnIsRequestPending)())
  910. pVolumePageData->bInvokedByDiskmgr = TRUE;
  911. }
  912. }
  913. SetupDiSetClassInstallParams(DeviceInfoSet,DeviceInfoData,
  914. (PSP_CLASSINSTALL_HEADER)&AddPropertyPageData,
  915. sizeof(SP_ADDPROPERTYPAGE_DATA));
  916. }
  917. }
  918. return NO_ERROR;
  919. }
  920. case DIF_INSTALLDEVICE : {
  921. HKEY hKey;
  922. DWORD dvdRegion;
  923. hKey = SetupDiOpenDevRegKey (DeviceInfoSet,
  924. DeviceInfoData,
  925. DICS_FLAG_GLOBAL,
  926. 0,
  927. DIREG_DEV,
  928. KEY_READ | KEY_WRITE);
  929. if (hKey != INVALID_HANDLE_VALUE) {
  930. dvdRegion = SystemLocale2DvdRegion (GetSystemDefaultLCID());
  931. RegSetValueEx (hKey,
  932. TEXT("DefaultDvdRegion"),
  933. 0,
  934. REG_DWORD,
  935. (PUCHAR) &dvdRegion,
  936. sizeof(dvdRegion)
  937. );
  938. RegCloseKey (hKey);
  939. }
  940. }
  941. //
  942. // fall through
  943. //
  944. default :
  945. //
  946. // Just do the default action.
  947. //
  948. return ERROR_DI_DO_DEFAULT;
  949. }
  950. }
  951. BOOL
  952. DvdContextMenu(
  953. HWND HwndControl,
  954. WORD Xpos,
  955. WORD Ypos
  956. )
  957. {
  958. WinHelp(HwndControl,
  959. _T("devmgr.hlp"),
  960. HELP_CONTEXTMENU,
  961. (ULONG_PTR) DvdHelpIDs);
  962. return FALSE;
  963. }
  964. void
  965. DvdHelp(
  966. HWND ParentHwnd,
  967. LPHELPINFO HelpInfo
  968. )
  969. {
  970. if (HelpInfo->iContextType == HELPINFO_WINDOW) {
  971. WinHelp((HWND) HelpInfo->hItemHandle,
  972. _T("devmgr.hlp"),
  973. HELP_WM_HELP,
  974. (ULONG_PTR) DvdHelpIDs);
  975. }
  976. }