Leaked source code of windows server 2003
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.

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