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.

904 lines
20 KiB

  1. //
  2. // Microsoft Windows Media Technologies
  3. // � 1999 Microsoft Corporation. All rights reserved.
  4. //
  5. // Refer to your End User License Agreement for details on your rights/restrictions to use these sample files.
  6. //
  7. // MSHDSP.DLL is a sample WMDM Service Provider(SP) that enumerates fixed drives.
  8. // This sample shows you how to implement an SP according to the WMDM documentation.
  9. // This sample uses fixed drives on your PC to emulate portable media, and
  10. // shows the relationship between different interfaces and objects. Each hard disk
  11. // volume is enumerated as a device and directories and files are enumerated as
  12. // Storage objects under respective devices. You can copy non-SDMI compliant content
  13. // to any device that this SP enumerates. To copy an SDMI compliant content to a
  14. // device, the device must be able to report a hardware embedded serial number.
  15. // Hard disks do not have such serial numbers.
  16. //
  17. // To build this SP, you are recommended to use the MSHDSP.DSP file under Microsoft
  18. // Visual C++ 6.0 and run REGSVR32.EXE to register the resulting MSHDSP.DLL. You can
  19. // then build the sample application from the WMDMAPP directory to see how it gets
  20. // loaded by the application. However, you need to obtain a certificate from
  21. // Microsoft to actually run this SP. This certificate would be in the KEY.C file
  22. // under the INCLUDE directory for one level up.
  23. //***************************************************************************
  24. //
  25. // Name: MDSPutil.cpp
  26. //
  27. // Description: Utility functions for MDSP
  28. //
  29. //***************************************************************************
  30. #include "hdspPCH.h"
  31. #include <SerialNumber.h>
  32. #define MDSP_PMID_IOMEGA 2 // from "serialid.h"
  33. extern BOOL IsAdministrator(DWORD& dwLastError);
  34. UINT __stdcall UtilGetLyraDriveType(LPSTR szDL)
  35. {
  36. UINT uType = GetDriveType( szDL );
  37. if( DRIVE_REMOVABLE == uType )
  38. {
  39. WMDMID stID;
  40. HRESULT hr;
  41. WCHAR wcsTmp[4]=L"A:\\";
  42. wcsTmp[0] = (USHORT)szDL[0];
  43. #define WITH_IOMEGA
  44. #ifdef WITH_IOMEGA
  45. extern BOOL __stdcall IsIomegaDrive(DWORD dwDriveNum);
  46. DWORD dwLastError;
  47. if( IsAdministrator(dwLastError) )
  48. {
  49. DWORD dwDriveNum;
  50. if (wcsTmp[0] >= L'A' && wcsTmp[0] <= L'Z')
  51. {
  52. dwDriveNum = wcsTmp[0] - L'A';
  53. }
  54. else if (wcsTmp[0] >= L'a' && wcsTmp[0] <= L'z')
  55. {
  56. dwDriveNum = wcsTmp[0] - L'a';
  57. }
  58. else
  59. {
  60. // GetDriveType returned DRIVE_REMOVABLE
  61. // Assuming szDl is nothing more than
  62. // drive_letter:\, we won't get here.
  63. // Following will force IsIomegaDrive to
  64. // return 0
  65. dwDriveNum = 26;
  66. }
  67. if( !IsIomegaDrive(dwDriveNum) )
  68. {
  69. uType = DRIVE_LYRA_TYPE;
  70. }
  71. }
  72. else // ignore dwLastError. If not Administrator, call UtilGetSerialNumber which calls into PMSP Service
  73. {
  74. hr = UtilGetSerialNumber(wcsTmp, &stID, 0);
  75. if( S_OK!=hr || stID.dwVendorID != MDSP_PMID_IOMEGA )
  76. {
  77. uType = DRIVE_LYRA_TYPE;
  78. }
  79. }
  80. #else
  81. hr = UtilGetSerialNumber(wcsTmp, &stID, 0);
  82. if( ((S_OK==hr)&&(20==stID.SerialNumberLength)) ||
  83. (HRESULT_FROM_WIN32(ERROR_INVALID_DATA) == hr)
  84. )
  85. {
  86. uType = DRIVE_LYRA_TYPE;
  87. }
  88. #endif
  89. }
  90. else
  91. {
  92. uType = DRIVE_UNKNOWN;
  93. }
  94. return uType;
  95. }
  96. BOOL UtilSetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
  97. {
  98. if( g_bIsWinNT )
  99. {
  100. return SetFileAttributesW(lpFileName, dwFileAttributes);
  101. }
  102. else
  103. {
  104. BOOL bRet;
  105. char *szTmp=NULL;
  106. UINT uLen = 2*(wcslen(lpFileName)+1);
  107. szTmp = new char [uLen];
  108. if(!szTmp)
  109. {
  110. SetLastError(ERROR_OUTOFMEMORY);
  111. return FALSE;
  112. }
  113. WideCharToMultiByte(CP_ACP, NULL, lpFileName, -1, szTmp, uLen, NULL, NULL);
  114. bRet = SetFileAttributesA(szTmp, dwFileAttributes);
  115. if( szTmp )
  116. {
  117. delete [] szTmp;
  118. }
  119. return bRet;
  120. }
  121. }
  122. BOOL UtilCreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  123. {
  124. if( g_bIsWinNT )
  125. {
  126. return CreateDirectoryW(lpPathName, lpSecurityAttributes);
  127. }
  128. else
  129. {
  130. BOOL bRet;
  131. char *szTmp=NULL;
  132. UINT uLen = 2*(wcslen(lpPathName)+1);
  133. szTmp = new char [uLen];
  134. if(!szTmp)
  135. {
  136. SetLastError(ERROR_OUTOFMEMORY);
  137. return FALSE;
  138. }
  139. WideCharToMultiByte(CP_ACP, NULL, lpPathName, -1, szTmp, uLen, NULL, NULL);
  140. bRet = CreateDirectoryA(szTmp, lpSecurityAttributes);
  141. if( szTmp )
  142. {
  143. delete [] szTmp;
  144. }
  145. return bRet;
  146. }
  147. }
  148. DWORD UtilGetFileAttributesW(LPCWSTR lpFileName)
  149. {
  150. if( g_bIsWinNT )
  151. {
  152. return GetFileAttributesW(lpFileName);
  153. }
  154. else
  155. {
  156. DWORD dwRet;
  157. char *szTmp=NULL;
  158. UINT uLen = 2*(wcslen(lpFileName)+1);
  159. szTmp = new char [uLen];
  160. if(!szTmp)
  161. {
  162. SetLastError(ERROR_OUTOFMEMORY);
  163. return 0xFFFFFFFF;
  164. }
  165. WideCharToMultiByte(CP_ACP, NULL, lpFileName, -1, szTmp, uLen, NULL, NULL);
  166. dwRet = GetFileAttributesA(szTmp);
  167. if( szTmp )
  168. {
  169. delete [] szTmp;
  170. }
  171. return dwRet;
  172. }
  173. }
  174. HANDLE UtilCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  175. {
  176. if( g_bIsWinNT )
  177. {
  178. return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  179. }
  180. else
  181. {
  182. HANDLE hRet=INVALID_HANDLE_VALUE;
  183. char *szTmp=NULL;
  184. UINT uLen = 2*(wcslen(lpFileName)+1);
  185. szTmp = new char [uLen];
  186. if(!szTmp)
  187. {
  188. SetLastError(ERROR_OUTOFMEMORY);
  189. return INVALID_HANDLE_VALUE;
  190. }
  191. WideCharToMultiByte(CP_ACP, NULL, lpFileName, -1, szTmp, uLen, NULL, NULL);
  192. hRet = CreateFileA(szTmp, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  193. if( szTmp )
  194. {
  195. delete [] szTmp;
  196. }
  197. return hRet;
  198. }
  199. }
  200. BOOL UtilMoveFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
  201. {
  202. if( g_bIsWinNT )
  203. {
  204. return MoveFileW(lpExistingFileName, lpNewFileName);
  205. }
  206. else
  207. {
  208. BOOL bRet;
  209. char *szTmpSrc=NULL, *szTmpDst=NULL;
  210. szTmpSrc = new char [2*(wcslen(lpExistingFileName)+1)];
  211. szTmpDst = new char [2*(wcslen(lpNewFileName)+1)];
  212. if( (!szTmpSrc) || (!szTmpDst))
  213. {
  214. if( szTmpSrc )
  215. {
  216. delete [] szTmpSrc;
  217. szTmpSrc=NULL;
  218. }
  219. SetLastError(ERROR_OUTOFMEMORY);
  220. return FALSE;
  221. }
  222. WideCharToMultiByte(CP_ACP, NULL, lpExistingFileName, -1, szTmpSrc, 2*(wcslen(lpExistingFileName)+1), NULL, NULL);
  223. WideCharToMultiByte(CP_ACP, NULL, lpNewFileName, -1, szTmpDst, 2*(wcslen(lpNewFileName)+1), NULL, NULL);
  224. bRet = MoveFileA(szTmpSrc, szTmpDst);
  225. if( szTmpSrc )
  226. {
  227. delete [] szTmpSrc;
  228. szTmpSrc=NULL;
  229. }
  230. if( szTmpDst )
  231. {
  232. delete [] szTmpDst;
  233. szTmpDst=NULL;
  234. }
  235. return bRet;
  236. }
  237. }
  238. void wcsParseDeviceName(WCHAR *wcsIn, WCHAR **wcsOut)
  239. {
  240. WCHAR wcsTmp[MAX_PATH], *pWcs;
  241. // @@@@ Change to a safe copy, but should we return error codes?
  242. // wcsIn is MAX_PATH chars for many calls to this function
  243. wcscpy( wcsTmp, wcsIn );
  244. pWcs = wcschr( wcsTmp, 0x5c );
  245. if( pWcs )
  246. {
  247. *pWcs=0;
  248. }
  249. // @@@@ wcsOut is 32 char in calls from this file
  250. wcscpy( *wcsOut, wcsTmp );
  251. }
  252. HRESULT GetFileSizeRecursive(char *szPath, DWORD *pdwSizeLow, DWORD *pdwSizeHigh)
  253. {
  254. HRESULT hr = S_OK;
  255. HANDLE hFile = INVALID_HANDLE_VALUE;
  256. HANDLE hFindFile = INVALID_HANDLE_VALUE;
  257. DWORD dwSizeLow = 0;
  258. DWORD dwSizeHigh = 0;
  259. WIN32_FIND_DATAA fd;
  260. char szLP[MAX_PATH];
  261. CARg( szPath );
  262. CARg( pdwSizeLow );
  263. CARg( pdwSizeHigh );
  264. strcpy( szLP, szPath );
  265. if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(szPath) )
  266. {
  267. if( szLP[strlen(szLP)-1] != 0x5c )
  268. {
  269. strcat(szLP, g_szBackslash);
  270. }
  271. strcat(szLP, "*");
  272. hFindFile = FindFirstFileA(szLP, &fd);
  273. if( hFindFile != INVALID_HANDLE_VALUE )
  274. {
  275. if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
  276. {
  277. szLP[strlen(szLP)-1] = 0; // erase the '*'
  278. strcat(szLP, fd.cFileName);
  279. CORg(GetFileSizeRecursive(szLP, pdwSizeLow, pdwSizeHigh));
  280. }
  281. while ( FindNextFileA(hFindFile, &fd) )
  282. {
  283. if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
  284. {
  285. strcpy(szLP, szPath);
  286. if( szLP[strlen(szLP)-1] != 0x5c )
  287. {
  288. strcat(szLP, g_szBackslash);
  289. }
  290. strcat(szLP, fd.cFileName);
  291. CORg(GetFileSizeRecursive(szLP, pdwSizeLow, pdwSizeHigh));
  292. }
  293. }
  294. hr = GetLastError();
  295. if( hr == ERROR_NO_MORE_FILES )
  296. {
  297. hr = S_OK;
  298. }
  299. else
  300. {
  301. hr = HRESULT_FROM_WIN32(hr);
  302. }
  303. }
  304. }
  305. else
  306. {
  307. hFile = CreateFileA(
  308. szPath,
  309. GENERIC_READ,
  310. FILE_SHARE_READ | FILE_SHARE_WRITE,
  311. NULL,
  312. OPEN_EXISTING,
  313. 0,
  314. NULL
  315. );
  316. CWRg(hFile != INVALID_HANDLE_VALUE);
  317. dwSizeLow = GetFileSize(hFile, &dwSizeHigh);
  318. CloseHandle(hFile);
  319. CWRg( 0xFFFFFFFF != dwSizeLow );
  320. *pdwSizeLow += dwSizeLow;
  321. *pdwSizeHigh += dwSizeHigh;
  322. hr = S_OK;
  323. }
  324. Error:
  325. if( hFindFile != INVALID_HANDLE_VALUE )
  326. {
  327. FindClose(hFindFile);
  328. }
  329. return hr;
  330. }
  331. HRESULT DeleteFileRecursive(char *szPath)
  332. {
  333. HRESULT hr=S_OK;
  334. CARg(szPath);
  335. if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(szPath) )
  336. {
  337. HANDLE hFindFile = INVALID_HANDLE_VALUE;
  338. WIN32_FIND_DATAA fd;
  339. char szLP[MAX_PATH];
  340. strcpy(szLP, szPath);
  341. if( szLP[strlen(szLP)-1] != 0x5c )
  342. {
  343. strcat(szLP, g_szBackslash);
  344. }
  345. strcat(szLP, "*");
  346. hFindFile = FindFirstFileA(szLP, &fd);
  347. if ( hFindFile != INVALID_HANDLE_VALUE )
  348. {
  349. do {
  350. if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
  351. {
  352. strcpy(szLP, szPath);
  353. if( szLP[strlen(szLP)-1] != 0x5c )
  354. {
  355. strcat(szLP, g_szBackslash);
  356. }
  357. strcat(szLP, fd.cFileName);
  358. CHRg(DeleteFileRecursive(szLP));
  359. }
  360. } while ( FindNextFileA(hFindFile, &fd) ) ;
  361. FindClose(hFindFile);
  362. hr = GetLastError();
  363. }
  364. else
  365. {
  366. hr = GetLastError();
  367. }
  368. // Until here this dir should be empty
  369. if( hr == ERROR_NO_MORE_FILES )
  370. {
  371. CWRg(RemoveDirectory(szPath));
  372. hr = S_OK;
  373. }
  374. else
  375. {
  376. hr = HRESULT_FROM_WIN32(hr);
  377. }
  378. }
  379. else
  380. {
  381. CWRg( DeleteFileA(szPath) );
  382. }
  383. Error:
  384. return hr;
  385. }
  386. HRESULT SetGlobalDeviceStatus(WCHAR *wcsNameIn, DWORD dwStat, BOOL bClear)
  387. {
  388. HRESULT hr = S_OK;
  389. WCHAR wcsName[32];
  390. WCHAR *pWN;
  391. int i;
  392. g_CriticalSection.Lock();
  393. CARg(wcsNameIn);
  394. pWN = &wcsName[0];
  395. wcsParseDeviceName(wcsNameIn, &pWN);
  396. // Search for existing entries to see if there is a match
  397. //
  398. for( i=0; i<MDSP_MAX_DEVICE_OBJ; i++ )
  399. {
  400. if( g_GlobalDeviceInfo[i].bValid )
  401. {
  402. if(!wcscmp(wcsName, g_GlobalDeviceInfo[i].wcsDevName) )
  403. {
  404. if( bClear )
  405. {
  406. g_GlobalDeviceInfo[i].dwStatus = dwStat;
  407. }
  408. else
  409. {
  410. g_GlobalDeviceInfo[i].dwStatus |= dwStat;
  411. }
  412. break; // a match has been found;
  413. }
  414. }
  415. }
  416. if( !(i<MDSP_MAX_DEVICE_OBJ) ) // new entry
  417. {
  418. for(i=0; i<MDSP_MAX_DEVICE_OBJ; i++)
  419. {
  420. if( !(g_GlobalDeviceInfo[i].bValid) ) // found empty space
  421. {
  422. wcscpy(g_GlobalDeviceInfo[i].wcsDevName, wcsName);
  423. g_GlobalDeviceInfo[i].bValid = TRUE;
  424. g_GlobalDeviceInfo[i].dwStatus = dwStat;
  425. break;
  426. }
  427. }
  428. }
  429. if( i<MDSP_MAX_DEVICE_OBJ )
  430. {
  431. hr = S_OK;
  432. }
  433. else
  434. {
  435. hr = hrNoMem;
  436. }
  437. Error:
  438. g_CriticalSection.Unlock();
  439. return hr;
  440. }
  441. HRESULT GetGlobalDeviceStatus(WCHAR *wcsNameIn, DWORD *pdwStat)
  442. {
  443. HRESULT hr = S_OK;
  444. WCHAR wcsName[32];
  445. WCHAR *pWN;
  446. int i;
  447. CARg(wcsNameIn);
  448. pWN = &wcsName[0];
  449. wcsParseDeviceName(wcsNameIn, &pWN);
  450. // Search for existing entries to see if there is a match
  451. //
  452. for( i=0; i<MDSP_MAX_DEVICE_OBJ; i++ )
  453. {
  454. if( g_GlobalDeviceInfo[i].bValid )
  455. {
  456. if(!wcscmp(wcsName, g_GlobalDeviceInfo[i].wcsDevName) )
  457. {
  458. *pdwStat = g_GlobalDeviceInfo[i].dwStatus;
  459. break; // a match has been found;
  460. }
  461. }
  462. }
  463. if( i<MDSP_MAX_DEVICE_OBJ )
  464. {
  465. hr = S_OK;
  466. }
  467. else
  468. {
  469. hr = E_FAIL;
  470. }
  471. Error:
  472. return hr;
  473. }
  474. HRESULT QuerySubFoldersAndFilesW(LPCWSTR wcsCurrentFolder, DWORD *pdwAttr)
  475. {
  476. HRESULT hr=E_FAIL;
  477. LPWSTR wcsName=NULL;
  478. int len;
  479. WIN32_FIND_DATAW wfd;
  480. int nErrorEnd=0;
  481. HANDLE hFFile=INVALID_HANDLE_VALUE;
  482. DWORD dwAttrib;
  483. CARg(wcsCurrentFolder);
  484. CARg(pdwAttr);
  485. len=wcslen(wcsCurrentFolder);
  486. CARg(len>2);
  487. wcsName = new WCHAR [len+MAX_PATH];
  488. CPRg(wcsName);
  489. wcscpy(wcsName, wcsCurrentFolder);
  490. if( wcsName[wcslen(wcsName)-1] != 0x5c )
  491. {
  492. wcscat(wcsName, g_wcsBackslash);
  493. }
  494. wcscat(wcsName, L"*");
  495. while( !nErrorEnd )
  496. {
  497. if( hFFile == INVALID_HANDLE_VALUE )
  498. {
  499. hFFile = FindFirstFileW(wcsName, &wfd);
  500. if( hFFile == INVALID_HANDLE_VALUE )
  501. {
  502. nErrorEnd = 1;
  503. }
  504. }
  505. else
  506. {
  507. if( !FindNextFileW(hFFile, &wfd) )
  508. {
  509. nErrorEnd = 1;
  510. }
  511. }
  512. if ( !nErrorEnd && hFFile != INVALID_HANDLE_VALUE )
  513. {
  514. if( !wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L"..") )
  515. {
  516. continue;
  517. }
  518. else
  519. {
  520. wcscpy(wcsName, wcsCurrentFolder);
  521. if( wcsName[wcslen(wcsName)-1] != 0x5c )
  522. {
  523. wcscat(wcsName, g_wcsBackslash);
  524. }
  525. wcscat(wcsName, wfd.cFileName);
  526. dwAttrib = GetFileAttributesW(wcsName);
  527. if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
  528. {
  529. *pdwAttr |= WMDM_STORAGE_ATTR_HAS_FOLDERS;
  530. // definition is in MDSPdefs.h #define ALSO_CHECK_FILES
  531. #ifndef ALSO_CHECK_FILES
  532. break;
  533. #endif
  534. }
  535. #ifdef ALSO_CHECK_FILES
  536. else
  537. {
  538. *pdwAttr |= WMDM_STORAGE_ATTR_HAS_FILES;
  539. }
  540. if( (*pdwAttr & WMDM_STORAGE_ATTR_HAS_FOLDERS) &&
  541. (*pdwAttr & WMDM_STORAGE_ATTR_HAS_FILES ) )
  542. {
  543. break; // No need to continue since we found both
  544. }
  545. #endif
  546. }
  547. } // End of If
  548. } // End of while
  549. hr=S_OK;
  550. Error:
  551. if( hFFile != INVALID_HANDLE_VALUE )
  552. {
  553. FindClose(hFFile);
  554. }
  555. if( wcsName )
  556. {
  557. delete [] wcsName;
  558. }
  559. return hr; // If FAILED(hr), sorry, can't do it.
  560. }
  561. HRESULT QuerySubFoldersAndFilesA(LPCSTR szCurrentFolder, DWORD *pdwAttr)
  562. {
  563. HRESULT hr=E_FAIL;
  564. LPSTR szName=NULL;
  565. int len;
  566. WIN32_FIND_DATAA fd;
  567. int nErrorEnd=0;
  568. HANDLE hFFile=INVALID_HANDLE_VALUE;
  569. DWORD dwAttrib;
  570. CARg(szCurrentFolder);
  571. CARg(pdwAttr);
  572. len=strlen(szCurrentFolder);
  573. CARg(len>2);
  574. szName = new char [len+MAX_PATH];
  575. CPRg(szName);
  576. strcpy(szName, szCurrentFolder);
  577. if( szName[strlen(szName)-1] != 0x5c )
  578. {
  579. strcat(szName, g_szBackslash);
  580. }
  581. strcat(szName, "*");
  582. while( !nErrorEnd )
  583. {
  584. if( hFFile == INVALID_HANDLE_VALUE )
  585. {
  586. hFFile = FindFirstFileA(szName, &fd);
  587. if( hFFile == INVALID_HANDLE_VALUE )
  588. {
  589. nErrorEnd = 1;
  590. }
  591. }
  592. else
  593. {
  594. if( !FindNextFileA(hFFile, &fd) )
  595. {
  596. nErrorEnd = 1;
  597. }
  598. }
  599. if ( !nErrorEnd && hFFile != INVALID_HANDLE_VALUE )
  600. {
  601. if( !strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..") )
  602. {
  603. continue;
  604. }
  605. else
  606. {
  607. strcpy(szName, szCurrentFolder);
  608. if( szName[strlen(szName)-1] != 0x5c )
  609. {
  610. strcat(szName, g_szBackslash);
  611. }
  612. strcat(szName, fd.cFileName);
  613. dwAttrib = GetFileAttributesA(szName);
  614. if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
  615. {
  616. *pdwAttr |= WMDM_STORAGE_ATTR_HAS_FOLDERS;
  617. // definition is in MDSPdefs.h #define ALSO_CHECK_FILES
  618. #ifndef ALSO_CHECK_FILES
  619. break;
  620. #endif
  621. }
  622. #ifdef ALSO_CHECK_FILES
  623. else
  624. {
  625. *pdwAttr |= WMDM_STORAGE_ATTR_HAS_FILES;
  626. }
  627. if( (*pdwAttr & WMDM_STORAGE_ATTR_HAS_FOLDERS) &&
  628. (*pdwAttr & WMDM_STORAGE_ATTR_HAS_FILES )
  629. )
  630. {
  631. break; // No need to continue since we found both
  632. }
  633. #endif
  634. }
  635. } // End of If
  636. } // End of while
  637. hr=S_OK;
  638. Error:
  639. if( hFFile != INVALID_HANDLE_VALUE )
  640. {
  641. FindClose(hFFile);
  642. }
  643. if( szName )
  644. {
  645. delete [] szName;
  646. }
  647. return hr; // If FAILED(hr), sorry, can't do it.
  648. }
  649. HRESULT QuerySubFoldersAndFiles(LPCWSTR wcsCurrentFolder, DWORD *pdwAttr)
  650. {
  651. if( g_bIsWinNT )
  652. {
  653. return QuerySubFoldersAndFilesW(wcsCurrentFolder, pdwAttr);
  654. }
  655. else
  656. {
  657. HRESULT hr;
  658. char *szTmp=NULL;
  659. UINT uLen = 2*(wcslen(wcsCurrentFolder)+1);
  660. szTmp = new char [uLen];
  661. if(!szTmp)
  662. {
  663. return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  664. }
  665. WideCharToMultiByte(CP_ACP, NULL, wcsCurrentFolder, -1, szTmp, uLen, NULL, NULL);
  666. hr = QuerySubFoldersAndFilesA(szTmp, pdwAttr);
  667. if( szTmp )
  668. {
  669. delete [] szTmp;
  670. }
  671. return hr;
  672. }
  673. }
  674. HRESULT DeleteFileRecursiveW(WCHAR *wcsPath)
  675. {
  676. HRESULT hr=S_OK;
  677. CARg(wcsPath);
  678. if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesW(wcsPath) )
  679. {
  680. HANDLE hFindFile=INVALID_HANDLE_VALUE;
  681. WIN32_FIND_DATAW wfd;
  682. WCHAR wcsLP[MAX_PATH];
  683. wcscpy(wcsLP, wcsPath);
  684. if( wcsLP[wcslen(wcsLP)-1] != 0x5c )
  685. {
  686. wcscat(wcsLP, g_wcsBackslash);
  687. }
  688. wcscat(wcsLP, L"*");
  689. hFindFile = FindFirstFileW(wcsLP, &wfd);
  690. if ( hFindFile != INVALID_HANDLE_VALUE )
  691. {
  692. do {
  693. if( wcscmp(wfd.cFileName, L".") && wcscmp(wfd.cFileName, L"..") )
  694. {
  695. wcscpy(wcsLP, wcsPath);
  696. if( wcsLP[wcslen(wcsLP)-1] != 0x5c )
  697. {
  698. wcscat(wcsLP, g_wcsBackslash);
  699. }
  700. wcscat(wcsLP, wfd.cFileName);
  701. CHRg(DeleteFileRecursiveW(wcsLP));
  702. }
  703. } while ( FindNextFileW(hFindFile, &wfd) ) ;
  704. FindClose(hFindFile);
  705. hr = GetLastError();
  706. } else {
  707. hr = GetLastError();
  708. }
  709. // Until here this dir should be empty
  710. if( hr == ERROR_NO_MORE_FILES )
  711. {
  712. CWRg(RemoveDirectoryW(wcsPath));
  713. hr=S_OK;
  714. }
  715. else
  716. {
  717. hr = HRESULT_FROM_WIN32(hr);
  718. }
  719. }
  720. else
  721. {
  722. CWRg( DeleteFileW(wcsPath) );
  723. }
  724. Error:
  725. return hr;
  726. }
  727. HRESULT DeleteFileRecursiveA(char *szPath)
  728. {
  729. HRESULT hr=S_OK;
  730. CARg(szPath);
  731. if( FILE_ATTRIBUTE_DIRECTORY & GetFileAttributesA(szPath) )
  732. {
  733. HANDLE hFindFile=INVALID_HANDLE_VALUE;
  734. WIN32_FIND_DATAA fd;
  735. char szLP[MAX_PATH];
  736. strcpy(szLP, szPath);
  737. if( szLP[strlen(szLP)-1] != 0x5c )
  738. {
  739. strcat(szLP, g_szBackslash);
  740. }
  741. strcat(szLP, "*");
  742. hFindFile = FindFirstFileA(szLP, &fd);
  743. if ( hFindFile != INVALID_HANDLE_VALUE )
  744. {
  745. do {
  746. if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..") )
  747. {
  748. strcpy(szLP, szPath);
  749. if( szLP[strlen(szLP)-1] != 0x5c )
  750. {
  751. strcat(szLP, g_szBackslash);
  752. }
  753. strcat(szLP, fd.cFileName);
  754. CHRg(DeleteFileRecursiveA(szLP));
  755. }
  756. } while ( FindNextFileA(hFindFile, &fd) ) ;
  757. FindClose(hFindFile);
  758. hr = GetLastError();
  759. }
  760. else
  761. {
  762. hr = GetLastError();
  763. }
  764. // Until here this dir should be empty
  765. if( hr == ERROR_NO_MORE_FILES )
  766. {
  767. CWRg(RemoveDirectory(szPath));
  768. hr=S_OK;
  769. }
  770. else
  771. {
  772. hr = HRESULT_FROM_WIN32(hr);
  773. }
  774. }
  775. else
  776. {
  777. CWRg( DeleteFileA(szPath) );
  778. }
  779. Error:
  780. return hr;
  781. }