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.

1298 lines
41 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. // File: serialid.cpp
  4. //
  5. // Microsoft Digital Rights Management
  6. // Copyright (C) Microsoft Corporation, 1998 - 1999, All Rights Reserved
  7. //
  8. // Description:
  9. //
  10. //-----------------------------------------------------------------------------
  11. #include <windows.h>
  12. #include <stddef.h>
  13. #include "drmerr.h"
  14. #include "aspi32.h"
  15. #include "serialid.h"
  16. #include "spti.h"
  17. //#include "KBDevice.h"
  18. #include <crtdbg.h>
  19. HRESULT __stdcall UtilStartStopService(bool fStartService);
  20. // #define WRITE_TO_LOG_FILE
  21. #if defined(DBG) || defined(WRITE_TO_LOG_FILE)
  22. #include <stdio.h>
  23. #endif
  24. void DebugMsg(const char* pszFormat, ...)
  25. {
  26. #if defined(DBG) || defined(WRITE_TO_LOG_FILE)
  27. char buf[1024];
  28. sprintf(buf, "[Serial Number Library](%lu): ", GetCurrentThreadId());
  29. va_list arglist;
  30. va_start(arglist, pszFormat);
  31. vsprintf(&buf[strlen(buf)], pszFormat, arglist);
  32. va_end(arglist);
  33. strcat(buf, "\n");
  34. #if defined(DBG)
  35. OutputDebugString(buf);
  36. #endif
  37. #if defined(WRITE_TO_LOG_FILE)
  38. FILE* fp = fopen("c:\\WmdmService.txt", "a");
  39. if (fp)
  40. {
  41. fprintf(fp, buf);
  42. fclose(fp);
  43. }
  44. #endif
  45. #endif
  46. }
  47. #ifdef USE_IOREADY
  48. #ifndef __Using_iomegaReady_Lib__
  49. #define __Using_iomegaReady_Lib__
  50. #endif
  51. #include "ioReadyMin.h"
  52. #endif
  53. #define WCS_PMID_SOFT L"media.id"
  54. BOOL IsWinNT()
  55. {
  56. OSVERSIONINFO osvi;
  57. BOOL bRet=FALSE;
  58. ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
  59. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  60. if ( ! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
  61. return FALSE;
  62. switch ( osvi.dwPlatformId )
  63. {
  64. case VER_PLATFORM_WIN32_NT:
  65. bRet=TRUE;
  66. break;
  67. case VER_PLATFORM_WIN32_WINDOWS:
  68. bRet=FALSE;
  69. break;
  70. case VER_PLATFORM_WIN32s:
  71. bRet=FALSE;
  72. break;
  73. }
  74. return bRet;
  75. }
  76. BOOL IsAdministrator(DWORD& dwLastError)
  77. {
  78. dwLastError = ERROR_SUCCESS;
  79. if ( IsWinNT() )
  80. {
  81. /* typedef SC_HANDLE (*T_POSCM)(LPCTSTR,LPCTSTR,DWORD);
  82. T_POSCM p_OpenSCM=NULL;
  83. p_OpenSCM = (T_POSCM)GetProcAddress(GetModuleHandle("advapi32.dll"), "OpenSCManagerA");
  84. if( !p_OpenSCM )
  85. {
  86. return FALSE;
  87. }
  88. */
  89. SC_HANDLE hSCM = OpenSCManagerA(NULL, // local machine
  90. NULL, // ServicesActive database
  91. SC_MANAGER_ALL_ACCESS); // full access
  92. if ( !hSCM )
  93. {
  94. dwLastError = GetLastError();
  95. if (dwLastError == ERROR_ACCESS_DENIED)
  96. {
  97. dwLastError = ERROR_SUCCESS;
  98. }
  99. return FALSE;
  100. }
  101. else
  102. {
  103. CloseServiceHandle(hSCM);
  104. return TRUE;
  105. }
  106. }
  107. else // On Win9x, everybody is admin
  108. {
  109. return TRUE;
  110. }
  111. }
  112. UINT __stdcall UtilGetDriveType(LPSTR szDL)
  113. {
  114. return GetDriveTypeA(szDL);
  115. }
  116. BOOL IsIomegaDrive(DWORD dwDriveNum)
  117. {
  118. BOOL bRet=FALSE;
  119. #ifdef USE_IOREADY
  120. if (dwDriveNum >= 26)
  121. {
  122. return bRet;
  123. }
  124. ioReady::Drive *pDrive = NULL;
  125. pDrive = new ioReady::Drive((int) dwDriveNum);
  126. if ( pDrive )
  127. {
  128. if ( pDrive->isIomegaDrive() )
  129. bRet=TRUE;
  130. delete pDrive;
  131. }
  132. #endif
  133. DebugMsg("IsIomegaDrive returning %u", bRet);
  134. return bRet;
  135. }
  136. BOOL GetIomegaDiskSerialNumber(DWORD dwDriveNum, PWMDMID pSN)
  137. {
  138. BOOL bRet=FALSE;
  139. #ifdef USE_IOREADY
  140. if (dwDriveNum >= 26)
  141. {
  142. return bRet;
  143. }
  144. ioReady::Drive *pDrive = NULL;
  145. char *pszSerial = NULL;
  146. pDrive = new ioReady::Drive((int) dwDriveNum);
  147. if ( pDrive )
  148. {
  149. if ( pDrive->isIomegaDrive() )
  150. {
  151. ioReady::Disk &refDisk = pDrive->getDisk();
  152. pszSerial = (char *)refDisk.getMediaSerialNumber();
  153. if ( pszSerial[0] )
  154. {
  155. ZeroMemory(pSN->pID, WMDMID_LENGTH);
  156. if (ioReady::ct_nSerialNumberLength <= sizeof(pSN->pID))
  157. {
  158. CopyMemory(pSN->pID, pszSerial, ioReady::ct_nSerialNumberLength);
  159. pSN->SerialNumberLength = ioReady::ct_nSerialNumberLength;
  160. pSN->dwVendorID = MDSP_PMID_IOMEGA;
  161. bRet = TRUE;
  162. }
  163. }
  164. }
  165. }
  166. delete pDrive;
  167. #endif
  168. return bRet;
  169. }
  170. HRESULT __stdcall UtilGetManufacturer(LPWSTR pDeviceName, LPWSTR *ppwszName, UINT nMaxChars)
  171. {
  172. HRESULT hr=S_OK;
  173. CARg(pDeviceName);
  174. CARg(ppwszName);
  175. CPRg(nMaxChars>16); // ensure enough buffer size
  176. DWORD dwDriveNum;
  177. // We use only the first char of pDeviceName and expect it to
  178. // be a drive letter. The rest of pDeviceName is not validated.
  179. // Perhaps it should, but we don't want to break our clients.
  180. if (pDeviceName[0] >= L'A' && pDeviceName[0] <= L'Z')
  181. {
  182. dwDriveNum = pDeviceName[0] - L'A';
  183. }
  184. else if (pDeviceName[0] >= L'a' && pDeviceName[0] <= L'z')
  185. {
  186. dwDriveNum = pDeviceName[0] - L'a';
  187. }
  188. else
  189. {
  190. hr = E_INVALIDARG;
  191. goto Error;
  192. }
  193. if ( IsIomegaDrive(dwDriveNum) )
  194. wcscpy(*ppwszName, L"Iomega");
  195. else
  196. {
  197. wcscpy(*ppwszName, L"Unknown");
  198. WMDMID snData;
  199. snData.cbSize = sizeof(WMDMID);
  200. if ( S_OK==UtilGetSerialNumber(pDeviceName, &snData, FALSE) )
  201. {
  202. switch ( snData.dwVendorID )
  203. {
  204. case 1:
  205. wcscpy(*ppwszName, L"SanDisk");
  206. break;
  207. case 2:
  208. wcscpy(*ppwszName, L"Iomega");
  209. break;
  210. }
  211. }
  212. }
  213. Error:
  214. return hr;
  215. }
  216. #include <winioctl.h>
  217. // This is defined in the Whistler platform SDK.
  218. #ifndef IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER
  219. #define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER CTL_CODE( \
  220. IOCTL_STORAGE_BASE, 0x304, METHOD_BUFFERED, FILE_ANY_ACCESS )
  221. #endif
  222. HRESULT GetMSNWithNtIoctl(LPCWSTR wcsDevice, PWMDMID pSN)
  223. {
  224. HRESULT hr=S_OK;
  225. HANDLE hDevice = INVALID_HANDLE_VALUE;
  226. BOOL bResult;
  227. MEDIA_SERIAL_NUMBER_DATA MSNGetSize;
  228. MEDIA_SERIAL_NUMBER_DATA* pMSN = NULL; // Buffer to hold the serial number
  229. DWORD dwBufferSize; // Size of pMSNNt buffer
  230. ULONG i;
  231. DWORD dwRet = 0; // Bytes returned
  232. CARg(pSN);
  233. DebugMsg("Entering GetMSNWithNtIoctl");
  234. hDevice = CreateFileW( wcsDevice,
  235. GENERIC_READ,
  236. FILE_SHARE_READ|FILE_SHARE_WRITE,
  237. NULL,
  238. OPEN_EXISTING,
  239. FILE_ATTRIBUTE_NORMAL |
  240. SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
  241. NULL);
  242. CWRg(hDevice != INVALID_HANDLE_VALUE);
  243. DebugMsg("GetMSNWithNtIoctl: CreateFile ok");
  244. // Get size of buffer we need to allocate
  245. bResult = DeviceIoControl( hDevice,
  246. IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER,
  247. NULL,
  248. 0,
  249. (LPVOID)&MSNGetSize,
  250. sizeof(MEDIA_SERIAL_NUMBER_DATA),
  251. &dwRet,
  252. NULL);
  253. // Handle expected buffer overrun error
  254. if ( !bResult )
  255. {
  256. hr = HRESULT_FROM_WIN32(GetLastError());
  257. // Error 'more data is available' is an expected error code
  258. if ( hr == HRESULT_FROM_WIN32(ERROR_MORE_DATA) )
  259. {
  260. hr = S_OK;
  261. }
  262. else goto Error;
  263. }
  264. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl1 ok");
  265. if (dwRet < RTL_SIZEOF_THROUGH_FIELD(MEDIA_SERIAL_NUMBER_DATA, SerialNumberLength))
  266. {
  267. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl1 dwRet bad: %u, expected >= %u",
  268. dwRet, RTL_SIZEOF_THROUGH_FIELD(MEDIA_SERIAL_NUMBER_DATA, SerialNumberLength));
  269. hr = E_INVALIDARG;
  270. goto Error;
  271. }
  272. // No serial number?
  273. if ( MSNGetSize.SerialNumberLength == 0 )
  274. {
  275. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl1: MSNGetSize.SerialNumberLength == 0");
  276. hr = E_FAIL;
  277. goto Error;
  278. }
  279. // The WMDMID structure we are using can only handle 128 bytes long serial numbers
  280. if ( MSNGetSize.SerialNumberLength > WMDMID_LENGTH )
  281. {
  282. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl1: MSNGetSize.SerialNumberLength > WMDMID_LENGTH");
  283. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  284. goto Error;
  285. }
  286. // Allocate buffer and call to get the serial number
  287. dwBufferSize = sizeof(MEDIA_SERIAL_NUMBER_DATA) + MSNGetSize.SerialNumberLength;
  288. pMSN = (MEDIA_SERIAL_NUMBER_DATA*) new BYTE[dwBufferSize];
  289. if ( pMSN == NULL )
  290. {
  291. DebugMsg("GetMSNWithNtIoctl: Out of memory allocating %u bytes", dwBufferSize);
  292. hr = E_OUTOFMEMORY;
  293. goto Error;
  294. }
  295. bResult = DeviceIoControl( hDevice,
  296. IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER,
  297. NULL,
  298. 0,
  299. (LPVOID)pMSN,
  300. dwBufferSize,
  301. &dwRet,
  302. NULL);
  303. if ( !bResult )
  304. {
  305. hr = HRESULT_FROM_WIN32(GetLastError());
  306. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl2 failed, hr = 0x%x", hr);
  307. goto Error;
  308. }
  309. if (dwRet < FIELD_OFFSET(MEDIA_SERIAL_NUMBER_DATA, SerialNumberData) + pMSN->SerialNumberLength)
  310. {
  311. hr = E_INVALIDARG;
  312. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl1: MSNGetSize.SerialNumberLength == 0");
  313. goto Error;
  314. }
  315. if (pMSN->SerialNumberLength > sizeof(pSN->pID))
  316. {
  317. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  318. DebugMsg("GetMSNWithNtIoctl: DeviceIoControl2: MSNGetSize.SerialNumberLength > WMDMID_LENGTH");
  319. goto Error;
  320. }
  321. // Copy serial number to out structure
  322. memcpy( pSN->pID, pMSN->SerialNumberData, pMSN->SerialNumberLength );
  323. pSN->SerialNumberLength = pMSN->SerialNumberLength;
  324. // Check result
  325. pSN->dwVendorID = MDSP_PMID_SANDISK;
  326. if ( pSN->SerialNumberLength > 24 )
  327. {
  328. char szVID[4];
  329. for ( i=0; i<3; i++ )
  330. {
  331. szVID[i]=(pSN->pID[18+i]);
  332. }
  333. szVID[i]=0;
  334. LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  335. SORT_DEFAULT);
  336. // if ( !lstrcmpiA(szVID, "ZIP") ||
  337. // !lstrcmpiA(szVID, "JAZ") ||
  338. // !lstrcmpiA(szVID, "CLI") )
  339. if (CompareStringA(lcid, NORM_IGNORECASE, szVID, -1, "ZIP", -1) == CSTR_EQUAL ||
  340. CompareStringA(lcid, NORM_IGNORECASE, szVID, -1, "JAZ", -1) == CSTR_EQUAL ||
  341. CompareStringA(lcid, NORM_IGNORECASE, szVID, -1, "CLI", -1) == CSTR_EQUAL)
  342. {
  343. pSN->dwVendorID = MDSP_PMID_IOMEGA;
  344. }
  345. }
  346. if ( (pSN->dwVendorID==MDSP_PMID_IOMEGA) && (pSN->SerialNumberLength>19) )
  347. {
  348. pSN->SerialNumberLength = 19;
  349. pSN->pID[18] = 0;
  350. }
  351. DebugMsg("GetMSNWithNtIoctl ok, pSN->SerialNumberLength = %u", pSN->SerialNumberLength);
  352. Error:
  353. if ( hDevice != INVALID_HANDLE_VALUE ) CloseHandle(hDevice);
  354. if ( pMSN ) delete [] pMSN;
  355. return hr;
  356. }
  357. HRESULT GetMSNWith9xIoctl(char chDriveLetter, PWMDMID pSN, DWORD dwCode, DWORD dwIOCTL )
  358. {
  359. HRESULT hr=S_OK;
  360. HANDLE hDevice=INVALID_HANDLE_VALUE;
  361. BOOL bResult;
  362. MEDIA_SERIAL_NUMBER_DATA MSNGetSize;
  363. MEDIA_SERIAL_NUMBER_DATA* pMSN = NULL; // Buffer to hold the serial number
  364. ULONG uBufferSize; // Size of pMSN
  365. DWORD dwRet = 0; // Bytes returned
  366. // _ASSERT( dwCode == 0x440D ||
  367. // dwCode == 0x4404 );
  368. // _ASSERT( (dwIOCTL == (0x0800 | 0x75)) ||
  369. // (dwIOCTL == WIN9X_IOCTL_GET_MEDIA_SERIAL_NUMBER) );
  370. CARg(pSN);
  371. hDevice = CreateFile("\\\\.\\VWIN32",0,0,NULL,OPEN_EXISTING,FILE_FLAG_DELETE_ON_CLOSE,0);
  372. CFRg(hDevice != INVALID_HANDLE_VALUE);
  373. DIOC_REGISTERS reg;
  374. DWORD cb;
  375. WORD drv;
  376. drv = (chDriveLetter >= 'a' ) ? (chDriveLetter-'a') : (chDriveLetter-'A');
  377. // Call first to get serial number size
  378. {
  379. MSNGetSize.SerialNumberLength = 0;
  380. reg.reg_EAX = dwCode; //create the ioctl
  381. reg.reg_EBX = drv;
  382. reg.reg_EBX++;
  383. reg.reg_ECX = dwIOCTL; // BUGBUG, needs definition of 0x75
  384. //
  385. // ISSUE: The following code will not work on 64-bit systems.
  386. // The conditional is only to get the code to compiler.
  387. //
  388. #if defined(_WIN64)
  389. reg.reg_EDX = (DWORD)(DWORD_PTR)&MSNGetSize;
  390. #else
  391. reg.reg_EDX = (DWORD)&MSNGetSize;
  392. #endif
  393. reg.reg_Flags = 0x0001;
  394. bResult = DeviceIoControl( hDevice,
  395. VWIN32_DIOC_DOS_IOCTL,
  396. &reg,
  397. sizeof(DIOC_REGISTERS),
  398. &reg,
  399. sizeof(DIOC_REGISTERS),
  400. &cb,
  401. NULL );
  402. // Check for errors
  403. if ( bResult && !(reg.reg_Flags&0x0001) )
  404. {
  405. if ( (MSNGetSize.Result != ERROR_SUCCESS) &&
  406. (MSNGetSize.Result != ERROR_MORE_DATA ) )
  407. {
  408. hr = HRESULT_FROM_WIN32(MSNGetSize.Result);
  409. goto Error;
  410. }
  411. }
  412. // No serial number?
  413. if ( MSNGetSize.SerialNumberLength == 0 )
  414. {
  415. hr = E_FAIL;
  416. goto Error;
  417. }
  418. // Max serial number size is 128 byte right now
  419. if ( MSNGetSize.SerialNumberLength > WMDMID_LENGTH )
  420. {
  421. hr = E_FAIL;
  422. goto Error;
  423. }
  424. // Allocate buffer to get serial number
  425. uBufferSize = MSNGetSize.SerialNumberLength + sizeof(MEDIA_SERIAL_NUMBER_DATA);
  426. pMSN = (MEDIA_SERIAL_NUMBER_DATA*) new BYTE[uBufferSize];
  427. if ( pMSN == NULL )
  428. {
  429. hr = E_OUTOFMEMORY;
  430. goto Error;
  431. }
  432. }
  433. // Call again to accually get the serial number
  434. {
  435. pMSN->SerialNumberLength = uBufferSize;
  436. reg.reg_EAX = dwCode; //create the ioctl
  437. reg.reg_EBX = drv;
  438. reg.reg_EBX++;
  439. reg.reg_ECX = dwIOCTL; // BUGBUG, needs definition of 0x75
  440. //
  441. // ISSUE: The following code will not work on 64-bit systems.
  442. // The conditional is only to get the code to compiler.
  443. //
  444. #if defined(_WIN64)
  445. reg.reg_EDX = (DWORD)0;
  446. #else
  447. reg.reg_EDX = (DWORD)pMSN;
  448. #endif
  449. reg.reg_Flags = 0x0001;
  450. bResult = DeviceIoControl( hDevice,
  451. VWIN32_DIOC_DOS_IOCTL,
  452. &reg,
  453. sizeof(DIOC_REGISTERS),
  454. &reg,
  455. sizeof(DIOC_REGISTERS),
  456. &cb,
  457. NULL );
  458. // Check for errors
  459. if ( bResult && !(reg.reg_Flags&0x0001) )
  460. {
  461. if ( (pMSN->Result != ERROR_SUCCESS) )
  462. {
  463. hr = HRESULT_FROM_WIN32(pMSN->Result);
  464. goto Error;
  465. }
  466. }
  467. }
  468. // Copy serial number to out structure
  469. // and 'figure out' vendor
  470. {
  471. memcpy( pSN->pID, pMSN->SerialNumberData, pMSN->SerialNumberLength );
  472. pSN->SerialNumberLength = pMSN->SerialNumberLength;
  473. pSN->dwVendorID = MDSP_PMID_SANDISK;
  474. if ( pSN->SerialNumberLength > 24 )
  475. {
  476. char szVID[4];
  477. ULONG i;
  478. for ( i=0; i<3; i++ )
  479. {
  480. szVID[i]=(pSN->pID[18+i]);
  481. }
  482. szVID[i]=0;
  483. LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  484. SORT_DEFAULT);
  485. // if ( !lstrcmpiA(szVID, "ZIP") ||
  486. // !lstrcmpiA(szVID, "JAZ") ||
  487. // !lstrcmpiA(szVID, "CLI") )
  488. if (CompareStringA(lcid, NORM_IGNORECASE, szVID, -1, "ZIP", -1) == CSTR_EQUAL ||
  489. CompareStringA(lcid, NORM_IGNORECASE, szVID, -1, "JAZ", -1) == CSTR_EQUAL ||
  490. CompareStringA(lcid, NORM_IGNORECASE, szVID, -1, "CLI", -1) == CSTR_EQUAL)
  491. {
  492. pSN->dwVendorID = MDSP_PMID_IOMEGA;
  493. }
  494. }
  495. if ( (pSN->dwVendorID==MDSP_PMID_IOMEGA) && (pSN->SerialNumberLength>19) )
  496. {
  497. pSN->SerialNumberLength = 19;
  498. pSN->pID[18] = 0;
  499. }
  500. }
  501. Error:
  502. if ( hDevice != INVALID_HANDLE_VALUE ) CloseHandle(hDevice);
  503. if ( pMSN ) delete [] pMSN;
  504. return hr;
  505. }
  506. HRESULT GetDeviceSNwithNTScsiPassThrough(LPCWSTR wszDevice, PWMDMID pSN)
  507. {
  508. HRESULT hr=S_OK;
  509. HANDLE fileHandle=INVALID_HANDLE_VALUE;
  510. UCHAR buffer[2048];
  511. BOOL status;
  512. ULONG returned, length, i, bufOffset;
  513. SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
  514. PSCSI_ADAPTER_BUS_INFO adapterInfo;
  515. PSCSI_INQUIRY_DATA inquiryData;
  516. DebugMsg("Entering GetDeviceSNwithNTScsiPassThrough");
  517. ZeroMemory(pSN, sizeof(WMDMID));
  518. fileHandle = CreateFileW(wszDevice,
  519. GENERIC_WRITE | GENERIC_READ,
  520. FILE_SHARE_READ | FILE_SHARE_WRITE,
  521. NULL,
  522. OPEN_EXISTING,
  523. SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
  524. NULL);
  525. CWRg(fileHandle != INVALID_HANDLE_VALUE);
  526. DebugMsg("GetDeviceSNwithNTScsiPassThrough: CreateFile ok");
  527. status = DeviceIoControl(fileHandle,
  528. IOCTL_SCSI_GET_INQUIRY_DATA,
  529. NULL,
  530. 0,
  531. buffer,
  532. sizeof(buffer),
  533. &returned,
  534. FALSE);
  535. // CWRg(status);
  536. // We use IOCTL_SCSI_GET_INQUIRY_DATA to get the disk's SCSI address, if
  537. // this fails, it is not on a SCSI bus so the SCSI address will be all zeros
  538. if ( status )
  539. {
  540. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl1 ok");
  541. if (returned < sizeof(SCSI_ADAPTER_BUS_INFO))
  542. {
  543. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl1 returned = %u < sizeof(SCSI_ADAPTER_BUS_INFO) = %u",
  544. returned, sizeof(SCSI_ADAPTER_BUS_INFO));
  545. hr = E_INVALIDARG;
  546. goto Error;
  547. }
  548. adapterInfo = (PSCSI_ADAPTER_BUS_INFO) buffer;
  549. CFRg(adapterInfo->NumberOfBuses>0);
  550. if (returned < adapterInfo->BusData[0].InquiryDataOffset + sizeof(SCSI_INQUIRY_DATA))
  551. {
  552. hr = E_INVALIDARG;
  553. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl1 returned = %u < adapterInfo->BusData[0].InquiryDataOffset (%u) + sizeof(SCSI_INQUIRY_DATA) (%u)",
  554. returned, adapterInfo->BusData[0].InquiryDataOffset, sizeof(SCSI_INQUIRY_DATA));
  555. goto Error;
  556. }
  557. inquiryData = (PSCSI_INQUIRY_DATA) (buffer +
  558. adapterInfo->BusData[0].InquiryDataOffset); // we know card readers has only one bus
  559. }
  560. ZeroMemory(&sptwb,sizeof(sptwb));
  561. sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
  562. sptwb.spt.PathId = (status?inquiryData->PathId:0);
  563. sptwb.spt.TargetId = (status?inquiryData->TargetId:0);
  564. sptwb.spt.Lun = (status?inquiryData->Lun:0);
  565. sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
  566. sptwb.spt.SenseInfoLength = 24;
  567. sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
  568. sptwb.spt.DataTransferLength = 256 /*256*/;
  569. sptwb.spt.TimeOutValue = 2;
  570. sptwb.spt.DataBufferOffset =
  571. offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
  572. sptwb.spt.SenseInfoOffset =
  573. offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
  574. sptwb.spt.Cdb[0] = 0x12 /* Command - SCSIOP_INQUIRY */;
  575. sptwb.spt.Cdb[1] = 0x01; /* Request - VitalProductData */
  576. sptwb.spt.Cdb[2] = 0x80 /* VPD page 80 - serial number page */;
  577. sptwb.spt.Cdb[3] = 0;
  578. sptwb.spt.Cdb[4] = 0xff /*255*/;
  579. sptwb.spt.Cdb[5] = 0;
  580. length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
  581. sptwb.spt.DataTransferLength;
  582. status = DeviceIoControl(fileHandle,
  583. IOCTL_SCSI_PASS_THROUGH,
  584. &sptwb,
  585. sizeof(SCSI_PASS_THROUGH),
  586. &sptwb,
  587. length,
  588. &returned,
  589. FALSE);
  590. CWRg(status);
  591. // CFRg(sptwb.ucDataBuf[3]>0);
  592. // Keep or remove this @@@@
  593. if (returned < offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + 4)
  594. {
  595. hr = E_INVALIDARG;
  596. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl2 returned = %u < offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + 4 = %u",
  597. returned, offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + 4);
  598. goto Error;
  599. }
  600. // Here there is a difference between Parallel and USB Unit:
  601. // Since the Parallel Unit is an emulation of SCSI disk, it doesn't follow SCSI spec.
  602. pSN->SerialNumberLength=0;
  603. pSN->dwVendorID=0;
  604. if ( sptwb.ucDataBuf[3] == 0 ) // this is the SanDisk USB device
  605. {
  606. pSN->SerialNumberLength = 20;
  607. // Keep or remove this @@@@
  608. if (returned < offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + 5)
  609. {
  610. hr = E_INVALIDARG;
  611. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl2 returned = %u < offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + 5 = %u",
  612. returned, offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + 5);
  613. goto Error;
  614. }
  615. if ( sptwb.ucDataBuf[4] > 0 )
  616. {
  617. if ((DWORD) (sptwb.ucDataBuf[4]) + 5 >= (DWORD) (pSN->SerialNumberLength))
  618. {
  619. bufOffset=(sptwb.ucDataBuf[4]+5)-(pSN->SerialNumberLength);
  620. }
  621. else
  622. {
  623. hr = E_INVALIDARG;
  624. goto Error;
  625. }
  626. }
  627. else
  628. { // There are 50K ImageMate III devices that read like this
  629. bufOffset=36;
  630. }
  631. }
  632. else if ( sptwb.ucDataBuf[3] > 0 )
  633. {
  634. pSN->SerialNumberLength = sptwb.ucDataBuf[3];
  635. bufOffset=4;
  636. }
  637. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl2 pSN->SerialNumberLength = %u",
  638. pSN->SerialNumberLength);
  639. // The WMDMID structure we are using can only handle 128 bytes long serial numbers
  640. if ( pSN->SerialNumberLength > WMDMID_LENGTH )
  641. {
  642. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  643. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl2 pSN->SerialNumberLength > WMDMID_LENGTH = %u", WMDMID_LENGTH);
  644. goto Error;
  645. }
  646. // Keep or remove this @@@@
  647. if (returned < offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + bufOffset + pSN->SerialNumberLength)
  648. {
  649. hr = E_INVALIDARG;
  650. DebugMsg("GetDeviceSNwithNTScsiPassThrough: DeviceIoControl2 returned = %u < offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) (=%u) + bufOffset (=%u) + pSN->SerialNumberLength) (=%u) = %u",
  651. returned, offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf), bufOffset, pSN->SerialNumberLength,
  652. offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) + bufOffset + pSN->SerialNumberLength);
  653. goto Error;
  654. }
  655. for ( i=0; i<pSN->SerialNumberLength; i++ )
  656. {
  657. pSN->pID[i] = sptwb.ucDataBuf[bufOffset+i];
  658. if ( !(pSN->dwVendorID) && pSN->pID[i] && pSN->pID[i] != 0x20 )
  659. pSN->dwVendorID = MDSP_PMID_SANDISK;
  660. }
  661. if ( !(pSN->dwVendorID) )
  662. hr=S_FALSE;
  663. else
  664. hr=S_OK;
  665. Error:
  666. if ( fileHandle != INVALID_HANDLE_VALUE )
  667. CloseHandle(fileHandle);
  668. DebugMsg("GetDeviceSNwithNTScsiPassThrough: returning hr = 0x%x", hr);
  669. return hr;
  670. }
  671. HRESULT GetMediaSerialNumberFromNTService(DWORD dwDN, PWMDMID pSN)
  672. {
  673. HANDLE hPipe = INVALID_HANDLE_VALUE;
  674. BYTE ubBuf[256];
  675. BOOL fSuccess;
  676. DWORD cbRead, cbWritten;
  677. WCHAR wszPipename[64] = L"\\\\.\\pipe\\WMDMPMSPpipe";
  678. DWORD dwErr;
  679. PMEDIA_SERIAL_NUMBER_DATA pMSN;
  680. HRESULT hr;
  681. BOOL bStarted = 0;
  682. if (dwDN >= 26)
  683. {
  684. _ASSERTE(dwDN < 26);
  685. hr = E_INVALIDARG;
  686. goto ErrorExit;
  687. }
  688. // Try to open a named pipe; wait for it, if necessary.
  689. for ( DWORD dwTriesLeft = 3; dwTriesLeft; dwTriesLeft -- )
  690. {
  691. // Set the impersonation level to the lowest one that works.
  692. // The real server impersonates us to validate the drive type.
  693. // SECURITY_ANONYMOUS is enough for this as long as the drive
  694. // specified is of the form x: (i.e., is not an ms-dos device name
  695. // in the DosDevices directory)
  696. hPipe = CreateFileW(
  697. wszPipename,
  698. GENERIC_READ |GENERIC_WRITE,
  699. 0,
  700. NULL,
  701. OPEN_EXISTING,
  702. SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
  703. NULL
  704. );
  705. // Break if the pipe handle is valid.
  706. if ( hPipe != INVALID_HANDLE_VALUE )
  707. {
  708. // Success
  709. fSuccess=TRUE;
  710. break;
  711. }
  712. // If all pipe instances are busy or if server has not yet created
  713. // the first instance of the named pipe, wait for a while and retry.
  714. // Else, exit.
  715. dwErr=GetLastError();
  716. DebugMsg("GetMediaSerialNumberFromNTService(): CreateFile on drive %u failed, last err = %u, Tries left = %u, bStarted = %d",
  717. dwDN, dwErr, dwTriesLeft, bStarted);
  718. if ( dwErr != ERROR_PIPE_BUSY && dwErr != ERROR_FILE_NOT_FOUND)
  719. {
  720. fSuccess=FALSE;
  721. break;
  722. }
  723. if (dwErr == ERROR_FILE_NOT_FOUND && !bStarted)
  724. {
  725. dwTriesLeft++; // Don't count this iteration
  726. bStarted = 1;
  727. // We start the service here because the service now
  728. // times out sfter a period of inactivity.
  729. // We ignore errors. If the start fails, we'll
  730. // timeout anyway. (If we did respond to errors, note
  731. // that the service may already be running and that
  732. // shuld not be considered an error.)
  733. UtilStartStopService(TRUE);
  734. // Wait for service to start
  735. for (DWORD i = 2; i > 0; i--)
  736. {
  737. Sleep(1000);
  738. if (WaitNamedPipeW(wszPipename, 0))
  739. {
  740. // Service is up and running and a pipe instance
  741. // is available
  742. break;
  743. }
  744. else
  745. {
  746. // Either the service has not yet started or no
  747. // pipe instance is available. Just keep going.
  748. }
  749. }
  750. // Even if the wait for the named pipe failed,
  751. // go on. We'll try once more below and bail out.
  752. }
  753. // All pipe instances are busy (or the service is starting),
  754. // so wait for 1 second.
  755. // Note: Do not use NMPWAIT_USE_DEFAULT_WAIT since the
  756. // server of this named pipe may be spoofing our server
  757. // and may have the set the default very high.
  758. if ( ! WaitNamedPipeW(wszPipename, 1000) )
  759. {
  760. fSuccess=FALSE;
  761. break;
  762. }
  763. } // end of for loop
  764. if ( !fSuccess )
  765. {
  766. hr=HRESULT_FROM_WIN32(ERROR_CANTOPEN);
  767. goto ErrorExit;
  768. }
  769. ZeroMemory(ubBuf, sizeof(ubBuf));
  770. pMSN = (PMEDIA_SERIAL_NUMBER_DATA)ubBuf;
  771. // pMSN->SerialNumberLength = 128;
  772. pMSN->Reserved[1] = dwDN;
  773. DWORD cbTotalWritten = 0;
  774. do
  775. {
  776. fSuccess = WriteFile(
  777. hPipe, // pipe handle
  778. ubBuf + cbTotalWritten, // message
  779. sizeof(*pMSN)- cbTotalWritten, // +128, // message length
  780. &cbWritten, // bytes written
  781. NULL // not overlapped
  782. );
  783. if ( !fSuccess) // || cbWritten != sizeof(*pMSN))
  784. {
  785. hr=HRESULT_FROM_WIN32(ERROR_CANTWRITE);
  786. goto ErrorExit;
  787. }
  788. cbTotalWritten += cbWritten;
  789. _ASSERTE(cbTotalWritten <= sizeof(*pMSN));
  790. }
  791. while (cbTotalWritten < sizeof(*pMSN));
  792. DWORD cbTotalRead = 0;
  793. DWORD cbTotalToRead;
  794. do
  795. {
  796. // Read from the pipe.
  797. fSuccess = ReadFile(
  798. hPipe, // pipe handle
  799. ubBuf + cbTotalRead, // buffer to receive reply
  800. sizeof(ubBuf) - cbTotalRead, // size of buffer
  801. &cbRead, // number of bytes read
  802. NULL // not overlapped
  803. );
  804. // This is a byte mode pipe, not a message mode one, so we
  805. // do not expect ERROR_MORE_DATA. Anyway, let this be as is.
  806. if ( !fSuccess && (dwErr=GetLastError()) != ERROR_MORE_DATA )
  807. {
  808. break;
  809. }
  810. cbTotalRead += cbRead;
  811. _ASSERTE(cbTotalRead <= sizeof(ubBuf));
  812. // We expect at least FIELD_OFFSET(MEDIA_SERIAL_NUMBER_DATA, SerialNumberData)
  813. // bytes in the response
  814. cbTotalToRead = FIELD_OFFSET(MEDIA_SERIAL_NUMBER_DATA, SerialNumberData);
  815. if (cbTotalRead >= cbTotalToRead)
  816. {
  817. pMSN = (PMEDIA_SERIAL_NUMBER_DATA)ubBuf;
  818. if ( ERROR_SUCCESS == pMSN->Result )
  819. {
  820. cbTotalToRead += pMSN->SerialNumberLength;
  821. }
  822. else
  823. {
  824. cbTotalToRead = sizeof(MEDIA_SERIAL_NUMBER_DATA);
  825. }
  826. // Server should write exactly cbTotalToRead bytes.
  827. // We should not have read any more because
  828. // we wrote only 1 request. (If we write >1 request, we may
  829. // get responses to both request.)
  830. _ASSERTE(cbTotalRead <= cbTotalToRead);
  831. if (cbTotalToRead > sizeof(ubBuf))
  832. {
  833. // We don't expect this. Server bad?
  834. fSuccess = FALSE;
  835. break;
  836. }
  837. }
  838. else
  839. {
  840. // cbTotalToRead does not have to be changed
  841. }
  842. } while ( !fSuccess || cbTotalRead < cbTotalToRead); // repeat loop if ERROR_MORE_DATA
  843. if ( fSuccess )
  844. {
  845. pMSN = (PMEDIA_SERIAL_NUMBER_DATA)ubBuf;
  846. if ( ERROR_SUCCESS == pMSN->Result &&
  847. pMSN->SerialNumberLength <= sizeof(pSN->pID))
  848. {
  849. CopyMemory(pSN->pID, pMSN->SerialNumberData, pMSN->SerialNumberLength);
  850. pSN->SerialNumberLength = pMSN->SerialNumberLength;
  851. pSN->dwVendorID = pMSN->Reserved[1];
  852. pSN->cbSize = sizeof(*pSN);
  853. hr=S_OK;
  854. }
  855. else if (pMSN->Result != ERROR_SUCCESS)
  856. {
  857. hr = HRESULT_FROM_WIN32(pMSN->Result);
  858. }
  859. else
  860. {
  861. hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  862. }
  863. }
  864. else
  865. {
  866. hr=HRESULT_FROM_WIN32(ERROR_CANTREAD);
  867. }
  868. ErrorExit:
  869. if ( hPipe != INVALID_HANDLE_VALUE )
  870. CloseHandle(hPipe);
  871. return hr;
  872. }
  873. HRESULT UtilGetHardSN(WCHAR *wcsDeviceName, DWORD dwDriveNum, PWMDMID pSN)
  874. {
  875. HRESULT hr=S_OK;
  876. ULONG i;
  877. DebugMsg("Entering UtilGetHardSN, drivenum %u", dwDriveNum);
  878. CARg(pSN);
  879. DWORD dwLastError;
  880. if ( IsAdministrator(dwLastError) )
  881. {
  882. // Convert device name to an ascii char - done only on Win9x
  883. char szTmp[MAX_PATH];
  884. *szTmp = 0;
  885. // Following only for NT. If we have a DOS device name, use it.
  886. // Else, open the drive letter.
  887. WCHAR wcsDriveName[] = L"\\\\.\\?:";
  888. if (dwDriveNum >= 26)
  889. {
  890. _ASSERTE(dwDriveNum < 26);
  891. hr = E_INVALIDARG;
  892. goto Error;
  893. }
  894. LPCWSTR wcsDeviceToOpen = wcsDriveName;
  895. wcsDriveName[4] = (WCHAR) (dwDriveNum + L'A');
  896. // Try IOCTL calls
  897. if ( IsWinNT() )
  898. {
  899. // NT, try IOCTL_GET_MEDIA_SERIAL_NUMBER method first
  900. hr = GetMSNWithNtIoctl(wcsDeviceToOpen, pSN);
  901. }
  902. else
  903. {
  904. if ( WideCharToMultiByte(CP_ACP, NULL, wcsDeviceName, -1, szTmp, sizeof(szTmp), NULL, NULL) == 0 )
  905. {
  906. hr = E_INVALIDARG;
  907. goto Error;
  908. }
  909. // Try two other IOCTL calls on Win9x
  910. hr = GetMSNWith9xIoctl( szTmp[0], pSN, 0x440D, (0x0800 | 0x75) );
  911. if ( FAILED(hr) )
  912. {
  913. hr = GetMSNWith9xIoctl( szTmp[0], pSN, 0x4404, WIN9X_IOCTL_GET_MEDIA_SERIAL_NUMBER );
  914. }
  915. }
  916. // Try Iomega
  917. if ( FAILED(hr) )
  918. {
  919. if ( IsIomegaDrive(dwDriveNum) )
  920. {
  921. if ( GetIomegaDiskSerialNumber(dwDriveNum, pSN) )
  922. {
  923. hr=S_OK;
  924. }
  925. else
  926. {
  927. hr = E_FAIL;
  928. goto Error;
  929. }
  930. }
  931. }
  932. // Try new SCSI_PASS_THROUGH "Get Media Serial Number" command
  933. if ( FAILED(hr) )
  934. {
  935. if ( IsWinNT() )
  936. {
  937. // This was pulled because it was not standardized.
  938. // hr = GetMediaSNwithNTScsiPassThrough(szTmp, pSN);
  939. }
  940. else
  941. {
  942. // @@@@ Remove this as well?
  943. Aspi32Util a32u;
  944. if ( a32u.DoSCSIPassThrough(szTmp, pSN, TRUE ) )
  945. {
  946. hr=S_OK;
  947. }
  948. else
  949. {
  950. hr = E_FAIL;
  951. }
  952. }
  953. }
  954. // Last chance, try old 'bad'
  955. // SCSI_PASS_THROUGH "Get Device Serial Number" command
  956. if ( FAILED(hr) )
  957. {
  958. // // We are using the DEVICE serial number as a MEDIA serial number.
  959. // // This violates the SCSI spec. We are only keeping this functionality
  960. // // for the devices we know that needs it.
  961. // if( CheckForKBDevice( szTmp[0] ) == FALSE )
  962. // {
  963. // hr = E_FAIL;
  964. // goto Error;
  965. // }
  966. if ( IsWinNT() )
  967. {
  968. CHRg(GetDeviceSNwithNTScsiPassThrough(wcsDeviceToOpen, pSN));
  969. }
  970. else
  971. {
  972. Aspi32Util a32u;
  973. CFRg( a32u.DoSCSIPassThrough(szTmp, pSN, FALSE ) );
  974. }
  975. }
  976. }
  977. else if (dwLastError != ERROR_SUCCESS)
  978. {
  979. hr = HRESULT_FROM_WIN32(dwLastError);
  980. goto Error;
  981. }
  982. else // If on NT and nonAdmin, try use PMSP Service
  983. {
  984. hr = GetMediaSerialNumberFromNTService(dwDriveNum, pSN);
  985. if (FAILED(hr))
  986. {
  987. goto Error;
  988. }
  989. }
  990. // put sanity check here
  991. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  992. for ( i=0; i<(pSN->SerialNumberLength); i++ )
  993. {
  994. if ( pSN->pID[i] && pSN->pID[i] != 0x20 )
  995. {
  996. hr = S_OK;
  997. break;
  998. }
  999. }
  1000. Error:
  1001. DebugMsg("Leaving UtilGetHardSN, hr = 0x%x");
  1002. return hr;
  1003. }
  1004. // fCreate is an unused parameter. Ir was used in an obsolete code path that
  1005. // has been deleted
  1006. HRESULT __stdcall UtilGetSerialNumber(WCHAR *wcsDeviceName, PWMDMID pSerialNumber, BOOL fCreate)
  1007. {
  1008. HRESULT hr = E_FAIL;
  1009. DebugMsg("Entering UtilGetSerialNumber");
  1010. if (!pSerialNumber || !wcsDeviceName)
  1011. {
  1012. return E_INVALIDARG;
  1013. }
  1014. DWORD dwDriveNum;
  1015. // We use only the first char of pDeviceName and expect it to
  1016. // be a drive letter. The rest of pDeviceName is not validated.
  1017. // Perhaps it should, but we don't want to break our clients.
  1018. if (wcsDeviceName[0] >= L'A' && wcsDeviceName[0] <= L'Z')
  1019. {
  1020. dwDriveNum = wcsDeviceName[0] - L'A';
  1021. }
  1022. else if (wcsDeviceName[0] >= L'a' && wcsDeviceName[0] <= L'z')
  1023. {
  1024. dwDriveNum = wcsDeviceName[0] - L'a';
  1025. }
  1026. else
  1027. {
  1028. hr = E_INVALIDARG;
  1029. goto Error;
  1030. }
  1031. pSerialNumber->cbSize = sizeof(WMDMID);
  1032. hr = UtilGetHardSN(wcsDeviceName, dwDriveNum, pSerialNumber);
  1033. if ( FAILED( hr ) )
  1034. {
  1035. if ( hr != HRESULT_FROM_WIN32(ERROR_INVALID_DATA) )
  1036. {
  1037. pSerialNumber->SerialNumberLength = 0;
  1038. pSerialNumber->dwVendorID = 0;
  1039. ZeroMemory(pSerialNumber->pID, sizeof(pSerialNumber->pID));
  1040. hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  1041. }
  1042. // hr = S_FALSE;
  1043. }
  1044. Error:
  1045. DebugMsg("Leaving UtilGetSerialNumber, hr = 0x%x", hr);
  1046. return hr;
  1047. }
  1048. HRESULT __stdcall UtilStartStopService(bool fStartService)
  1049. {
  1050. HRESULT hr = S_OK;
  1051. SERVICE_STATUS ServiceStatus;
  1052. DWORD dwLastError;
  1053. if ( IsAdministrator(dwLastError) )
  1054. {
  1055. //
  1056. // We are on Win 9x machine or NT machine with admin previleges. In
  1057. // either case, we don't want to run the service.
  1058. //
  1059. DebugMsg("UtilStartStopService(): fStartService = %d, returning S_OK (IsAdmin returned TRUE)",
  1060. fStartService);
  1061. return S_OK;
  1062. }
  1063. else
  1064. {
  1065. // We ignore dwLastError
  1066. }
  1067. // open the service control manager
  1068. SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  1069. SC_HANDLE hService = NULL;
  1070. if ( !hSCM )
  1071. {
  1072. hr = HRESULT_FROM_WIN32(GetLastError());
  1073. DebugMsg("UtilStartStopService(): fStartService = %d, OpenSCManager failed, last err (as hr) = 0x%x",
  1074. fStartService, hr);
  1075. goto Error;
  1076. }
  1077. // open the service
  1078. hService = OpenService(hSCM,
  1079. "WmdmPmSp",
  1080. (fStartService? SERVICE_START : SERVICE_STOP) | SERVICE_QUERY_STATUS);
  1081. if ( !hService )
  1082. {
  1083. hr = HRESULT_FROM_WIN32(GetLastError());
  1084. DebugMsg("UtilStartStopService(): fStartService = %d, OpenService failed, last err (as hr) = 0x%x",
  1085. fStartService, hr);
  1086. goto Error;
  1087. }
  1088. if ( !QueryServiceStatus( hService, &ServiceStatus ) )
  1089. {
  1090. hr = HRESULT_FROM_WIN32(GetLastError());
  1091. DebugMsg("UtilStartStopService(): fStartService = %d, QueryServiceStatus failed, last err (as hr) = 0x%x",
  1092. fStartService, hr);
  1093. goto Error;
  1094. }
  1095. if ( fStartService && ServiceStatus.dwCurrentState != SERVICE_RUNNING)
  1096. {
  1097. // start the service
  1098. if(!StartService(hService, 0, NULL) )
  1099. {
  1100. hr = HRESULT_FROM_WIN32(GetLastError());
  1101. DebugMsg("UtilStartStopService(): fStartService = %d, StartService failed, last err (as hr) = 0x%x",
  1102. fStartService, hr);
  1103. goto Error;
  1104. }
  1105. }
  1106. if(!fStartService && ServiceStatus.dwCurrentState != SERVICE_STOP)
  1107. {
  1108. // stop the service.
  1109. if(!ControlService(hService, SERVICE_CONTROL_STOP, &ServiceStatus))
  1110. {
  1111. hr = HRESULT_FROM_WIN32(GetLastError());
  1112. DebugMsg("UtilStartStopService(): fStartService = %d, ControlService failed, last err (as hr) = 0x%x",
  1113. fStartService, hr);
  1114. goto Error;
  1115. }
  1116. }
  1117. Error:
  1118. if ( hService )
  1119. {
  1120. CloseServiceHandle(hService);
  1121. }
  1122. if ( hSCM )
  1123. {
  1124. CloseServiceHandle(hSCM);
  1125. }
  1126. DebugMsg("UtilStartStopService(): fStartService = %d, returning hr = 0x%x",
  1127. fStartService, hr);
  1128. return hr;
  1129. }