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.

690 lines
15 KiB

  1. #include "gptext.h"
  2. //*************************************************************
  3. //
  4. // CheckSlash()
  5. //
  6. // Purpose: Checks for an ending slash and adds one if
  7. // it is missing.
  8. //
  9. // Parameters: lpDir - directory
  10. //
  11. // Return: Pointer to the end of the string
  12. //
  13. // Comments:
  14. //
  15. // History: Date Author Comment
  16. // 6/19/95 ericflo Created
  17. //
  18. //*************************************************************
  19. LPTSTR CheckSlash (LPTSTR lpDir)
  20. {
  21. LPTSTR lpEnd;
  22. lpEnd = lpDir + lstrlen(lpDir);
  23. if (*(lpEnd - 1) != TEXT('\\')) {
  24. *lpEnd = TEXT('\\');
  25. lpEnd++;
  26. *lpEnd = TEXT('\0');
  27. }
  28. return lpEnd;
  29. }
  30. //*************************************************************
  31. //
  32. // RegDelnodeRecurse()
  33. //
  34. // Purpose: Deletes a registry key and all it's subkeys / values.
  35. // Called by RegDelnode
  36. //
  37. // Parameters: hKeyRoot - Root key
  38. // lpSubKey - SubKey to delete
  39. //
  40. // Return: TRUE if successful
  41. // FALSE if an error occurs
  42. //
  43. // Comments:
  44. //
  45. // History: Date Author Comment
  46. // 10/3/95 ericflo Created
  47. //
  48. //*************************************************************
  49. BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey)
  50. {
  51. LPTSTR lpEnd;
  52. LONG lResult;
  53. DWORD dwSize;
  54. TCHAR szName[MAX_PATH];
  55. HKEY hKey;
  56. FILETIME ftWrite;
  57. //
  58. // First, see if we can delete the key without having
  59. // to recurse.
  60. //
  61. lResult = RegDeleteKey(hKeyRoot, lpSubKey);
  62. if (lResult == ERROR_SUCCESS) {
  63. return TRUE;
  64. }
  65. lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
  66. if (lResult != ERROR_SUCCESS) {
  67. return FALSE;
  68. }
  69. lpEnd = CheckSlash(lpSubKey);
  70. //
  71. // Enumerate the keys
  72. //
  73. dwSize = MAX_PATH;
  74. lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
  75. NULL, NULL, &ftWrite);
  76. if (lResult == ERROR_SUCCESS) {
  77. do {
  78. lstrcpy (lpEnd, szName);
  79. if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
  80. break;
  81. }
  82. //
  83. // Enumerate again
  84. //
  85. dwSize = MAX_PATH;
  86. lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
  87. NULL, NULL, &ftWrite);
  88. } while (lResult == ERROR_SUCCESS);
  89. }
  90. lpEnd--;
  91. *lpEnd = TEXT('\0');
  92. RegCloseKey (hKey);
  93. //
  94. // Try again to delete the key
  95. //
  96. lResult = RegDeleteKey(hKeyRoot, lpSubKey);
  97. if (lResult == ERROR_SUCCESS) {
  98. return TRUE;
  99. }
  100. return FALSE;
  101. }
  102. //*************************************************************
  103. //
  104. // RegDelnode()
  105. //
  106. // Purpose: Deletes a registry key and all it's subkeys / values
  107. //
  108. // Parameters: hKeyRoot - Root key
  109. // lpSubKey - SubKey to delete
  110. //
  111. // Return: TRUE if successful
  112. // FALSE if an error occurs
  113. //
  114. // Comments:
  115. //
  116. // History: Date Author Comment
  117. // 10/3/95 ericflo Created
  118. //
  119. //*************************************************************
  120. BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey)
  121. {
  122. TCHAR szDelKey[2 * MAX_PATH];
  123. lstrcpy (szDelKey, lpSubKey);
  124. return RegDelnodeRecurse(hKeyRoot, szDelKey);
  125. }
  126. //*************************************************************
  127. //
  128. // RegCleanUpValue()
  129. //
  130. // Purpose: Removes the target value and if no more values / keys
  131. // are present, removes the key. This function then
  132. // works up the parent tree removing keys if they are
  133. // also empty. If any parent key has a value / subkey,
  134. // it won't be removed.
  135. //
  136. // Parameters: hKeyRoot - Root key
  137. // lpSubKey - SubKey
  138. // lpValueName - Value to remove
  139. //
  140. //
  141. // Return: TRUE if successful
  142. // FALSE if an error occurs
  143. //
  144. //*************************************************************
  145. BOOL RegCleanUpValue (HKEY hKeyRoot, LPTSTR lpSubKey, LPTSTR lpValueName)
  146. {
  147. TCHAR szDelKey[2 * MAX_PATH];
  148. LPTSTR lpEnd;
  149. DWORD dwKeys, dwValues;
  150. LONG lResult;
  151. HKEY hKey;
  152. //
  153. // Make a copy of the subkey so we can write to it.
  154. //
  155. lstrcpy (szDelKey, lpSubKey);
  156. //
  157. // First delete the value
  158. //
  159. lResult = RegOpenKeyEx (hKeyRoot, szDelKey, 0, KEY_WRITE, &hKey);
  160. if (lResult == ERROR_SUCCESS)
  161. {
  162. lResult = RegDeleteValue (hKey, lpValueName);
  163. RegCloseKey (hKey);
  164. if (lResult != ERROR_SUCCESS)
  165. {
  166. if (lResult != ERROR_FILE_NOT_FOUND)
  167. {
  168. DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to delete value <%s> with %d."), lpValueName, lResult));
  169. return FALSE;
  170. }
  171. }
  172. }
  173. //
  174. // Now loop through each of the parents. If the parent is empty
  175. // eg: no values and no other subkeys, then remove the parent and
  176. // keep working up.
  177. //
  178. lpEnd = szDelKey + lstrlen(szDelKey) - 1;
  179. while (lpEnd >= szDelKey)
  180. {
  181. //
  182. // Find the parent key
  183. //
  184. while ((lpEnd > szDelKey) && (*lpEnd != TEXT('\\')))
  185. lpEnd--;
  186. //
  187. // Open the key
  188. //
  189. lResult = RegOpenKeyEx (hKeyRoot, szDelKey, 0, KEY_READ, &hKey);
  190. if (lResult != ERROR_SUCCESS)
  191. {
  192. if (lResult == ERROR_FILE_NOT_FOUND)
  193. {
  194. goto LoopAgain;
  195. }
  196. else
  197. {
  198. DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to open key <%s> with %d."), szDelKey, lResult));
  199. return FALSE;
  200. }
  201. }
  202. //
  203. // See if there any any values / keys
  204. //
  205. lResult = RegQueryInfoKey (hKey, NULL, NULL, NULL, &dwKeys, NULL, NULL,
  206. &dwValues, NULL, NULL, NULL, NULL);
  207. RegCloseKey (hKey);
  208. if (lResult != ERROR_SUCCESS)
  209. {
  210. DebugMsg((DM_WARNING, TEXT("RegCleanUpKey: Failed to query key <%s> with %d."), szDelKey, lResult));
  211. return FALSE;
  212. }
  213. //
  214. // Exit now if this key has values or keys
  215. //
  216. if ((dwKeys != 0) || (dwValues != 0))
  217. {
  218. return TRUE;
  219. }
  220. RegDeleteKey (hKeyRoot, szDelKey);
  221. LoopAgain:
  222. //
  223. // If we are at the beginning of the subkey, we can leave now.
  224. //
  225. if (lpEnd == szDelKey)
  226. {
  227. return TRUE;
  228. }
  229. //
  230. // There is a parent key. Remove the slash and loop again.
  231. //
  232. if (*lpEnd == TEXT('\\'))
  233. {
  234. *lpEnd = TEXT('\0');
  235. }
  236. }
  237. return TRUE;
  238. }
  239. //*************************************************************
  240. //
  241. // CreateNestedDirectory()
  242. //
  243. // Purpose: Creates a subdirectory and all it's parents
  244. // if necessary.
  245. //
  246. // Parameters: lpDirectory - Directory name
  247. // lpSecurityAttributes - Security Attributes
  248. //
  249. // Return: > 0 if successful
  250. // 0 if an error occurs
  251. //
  252. // Comments:
  253. //
  254. // History: Date Author Comment
  255. // 8/08/95 ericflo Created
  256. //
  257. //*************************************************************
  258. UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  259. {
  260. TCHAR szDirectory[MAX_PATH];
  261. LPTSTR lpEnd;
  262. //
  263. // Check for NULL pointer
  264. //
  265. if (!lpDirectory || !(*lpDirectory)) {
  266. DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Received a NULL pointer.")));
  267. return 0;
  268. }
  269. //
  270. // First, see if we can create the directory without having
  271. // to build parent directories.
  272. //
  273. if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
  274. return 1;
  275. }
  276. //
  277. // If this directory exists already, this is OK too.
  278. //
  279. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  280. return ERROR_ALREADY_EXISTS;
  281. }
  282. //
  283. // No luck, copy the string to a buffer we can munge
  284. //
  285. lstrcpy (szDirectory, lpDirectory);
  286. //
  287. // Find the first subdirectory name
  288. //
  289. lpEnd = szDirectory;
  290. if (szDirectory[1] == TEXT(':')) {
  291. lpEnd += 3;
  292. } else if (szDirectory[1] == TEXT('\\')) {
  293. //
  294. // Skip the first two slashes
  295. //
  296. lpEnd += 2;
  297. //
  298. // Find the slash between the server name and
  299. // the share name.
  300. //
  301. while (*lpEnd && *lpEnd != TEXT('\\')) {
  302. lpEnd++;
  303. }
  304. if (!(*lpEnd)) {
  305. return 0;
  306. }
  307. //
  308. // Skip the slash, and find the slash between
  309. // the share name and the directory name.
  310. //
  311. lpEnd++;
  312. while (*lpEnd && *lpEnd != TEXT('\\')) {
  313. lpEnd++;
  314. }
  315. if (!(*lpEnd)) {
  316. return 0;
  317. }
  318. //
  319. // Leave pointer at the beginning of the directory.
  320. //
  321. lpEnd++;
  322. } else if (szDirectory[0] == TEXT('\\')) {
  323. lpEnd++;
  324. }
  325. while (*lpEnd) {
  326. while (*lpEnd && *lpEnd != TEXT('\\')) {
  327. lpEnd++;
  328. }
  329. if (*lpEnd == TEXT('\\')) {
  330. *lpEnd = TEXT('\0');
  331. if (!CreateDirectory (szDirectory, NULL)) {
  332. if (GetLastError() != ERROR_ALREADY_EXISTS) {
  333. DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: CreateDirectory failed with %d."), GetLastError()));
  334. return 0;
  335. }
  336. }
  337. *lpEnd = TEXT('\\');
  338. lpEnd++;
  339. }
  340. }
  341. //
  342. // Create the final directory
  343. //
  344. if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
  345. return 1;
  346. }
  347. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  348. return ERROR_ALREADY_EXISTS;
  349. }
  350. //
  351. // Failed
  352. //
  353. DebugMsg((DM_VERBOSE, TEXT("CreateNestedDirectory: Failed to create the directory with error %d."), GetLastError()));
  354. return 0;
  355. }
  356. /*******************************************************************
  357. NAME: StringToNum
  358. SYNOPSIS: Converts string value to numeric value
  359. NOTES: Calls atoi() to do conversion, but first checks
  360. for non-numeric characters
  361. EXIT: Returns TRUE if successful, FALSE if invalid
  362. (non-numeric) characters
  363. ********************************************************************/
  364. BOOL StringToNum(TCHAR *pszStr,UINT * pnVal)
  365. {
  366. TCHAR *pTst = pszStr;
  367. if (!pszStr) return FALSE;
  368. // verify that all characters are numbers
  369. while (*pTst) {
  370. if (!(*pTst >= TEXT('0') && *pTst <= TEXT('9'))) {
  371. // if (*pTst != TEXT('-'))
  372. return FALSE;
  373. }
  374. pTst = CharNext(pTst);
  375. }
  376. *pnVal = _ttoi(pszStr);
  377. return TRUE;
  378. }
  379. //*************************************************************
  380. //
  381. // ImpersonateUser()
  382. //
  383. // Purpose: Impersonates the specified user
  384. //
  385. // Parameters: hToken - user to impersonate
  386. //
  387. // Return: hToken if successful
  388. // FALSE if an error occurs
  389. //
  390. //*************************************************************
  391. BOOL ImpersonateUser (HANDLE hNewUser, HANDLE *hOldUser)
  392. {
  393. if (!OpenThreadToken (GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ,
  394. TRUE, hOldUser)) {
  395. *hOldUser = NULL;
  396. }
  397. if (!ImpersonateLoggedOnUser(hNewUser))
  398. {
  399. if ( *hOldUser )
  400. {
  401. CloseHandle( *hOldUser );
  402. *hOldUser = NULL;
  403. }
  404. DebugMsg((DM_WARNING, TEXT("ImpersonateUser: Failed to impersonate user with %d."), GetLastError()));
  405. return FALSE;
  406. }
  407. return TRUE;
  408. }
  409. //*************************************************************
  410. //
  411. // RevertToUser()
  412. //
  413. // Purpose: Revert back to original user
  414. //
  415. // Parameters: hUser - original user token
  416. //
  417. // Return: TRUE if successful
  418. // FALSE if an error occurs
  419. //
  420. //*************************************************************
  421. BOOL RevertToUser (HANDLE *hUser)
  422. {
  423. SetThreadToken(NULL, *hUser);
  424. if (*hUser) {
  425. CloseHandle (*hUser);
  426. *hUser = NULL;
  427. }
  428. return TRUE;
  429. }
  430. //*************************************************************
  431. //
  432. // GuidToString, StringToGuid, ValidateGuid, CompareGuid()
  433. //
  434. // Purpose: Guid utility functions
  435. //
  436. //*************************************************************
  437. //
  438. // Length in chars of string form of guid {44cffeec-79d0-11d2-a89d-00c04fbbcfa2}
  439. //
  440. #define GUID_LENGTH 38
  441. void GuidToString( GUID *pGuid, TCHAR * szValue )
  442. {
  443. wsprintf( szValue,
  444. TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  445. pGuid->Data1,
  446. pGuid->Data2,
  447. pGuid->Data3,
  448. pGuid->Data4[0], pGuid->Data4[1],
  449. pGuid->Data4[2], pGuid->Data4[3],
  450. pGuid->Data4[4], pGuid->Data4[5],
  451. pGuid->Data4[6], pGuid->Data4[7] );
  452. }
  453. void StringToGuid( TCHAR * szValue, GUID * pGuid )
  454. {
  455. WCHAR wc;
  456. INT i;
  457. //
  458. // If the first character is a '{', skip it
  459. //
  460. if ( szValue[0] == L'{' )
  461. szValue++;
  462. //
  463. // Since szValue may be used again, no permanent modification to
  464. // it is be made.
  465. //
  466. wc = szValue[8];
  467. szValue[8] = 0;
  468. pGuid->Data1 = wcstoul( &szValue[0], 0, 16 );
  469. szValue[8] = wc;
  470. wc = szValue[13];
  471. szValue[13] = 0;
  472. pGuid->Data2 = (USHORT)wcstoul( &szValue[9], 0, 16 );
  473. szValue[13] = wc;
  474. wc = szValue[18];
  475. szValue[18] = 0;
  476. pGuid->Data3 = (USHORT)wcstoul( &szValue[14], 0, 16 );
  477. szValue[18] = wc;
  478. wc = szValue[21];
  479. szValue[21] = 0;
  480. pGuid->Data4[0] = (unsigned char)wcstoul( &szValue[19], 0, 16 );
  481. szValue[21] = wc;
  482. wc = szValue[23];
  483. szValue[23] = 0;
  484. pGuid->Data4[1] = (unsigned char)wcstoul( &szValue[21], 0, 16 );
  485. szValue[23] = wc;
  486. for ( i = 0; i < 6; i++ )
  487. {
  488. wc = szValue[26+i*2];
  489. szValue[26+i*2] = 0;
  490. pGuid->Data4[2+i] = (unsigned char)wcstoul( &szValue[24+i*2], 0, 16 );
  491. szValue[26+i*2] = wc;
  492. }
  493. }
  494. BOOL ValidateGuid( TCHAR *szValue )
  495. {
  496. //
  497. // Check if szValue is of form {19e02dd6-79d2-11d2-a89d-00c04fbbcfa2}
  498. //
  499. if ( lstrlen(szValue) < GUID_LENGTH )
  500. return FALSE;
  501. if ( szValue[0] != TEXT('{')
  502. || szValue[9] != TEXT('-')
  503. || szValue[14] != TEXT('-')
  504. || szValue[19] != TEXT('-')
  505. || szValue[24] != TEXT('-')
  506. || szValue[37] != TEXT('}') )
  507. {
  508. return FALSE;
  509. }
  510. return TRUE;
  511. }
  512. INT CompareGuid( GUID * pGuid1, GUID * pGuid2 )
  513. {
  514. INT i;
  515. if ( pGuid1->Data1 != pGuid2->Data1 )
  516. return ( pGuid1->Data1 < pGuid2->Data1 ? -1 : 1 );
  517. if ( pGuid1->Data2 != pGuid2->Data2 )
  518. return ( pGuid1->Data2 < pGuid2->Data2 ? -1 : 1 );
  519. if ( pGuid1->Data3 != pGuid2->Data3 )
  520. return ( pGuid1->Data3 < pGuid2->Data3 ? -1 : 1 );
  521. for ( i = 0; i < 8; i++ )
  522. {
  523. if ( pGuid1->Data4[i] != pGuid2->Data4[i] )
  524. return ( pGuid1->Data4[i] < pGuid2->Data4[i] ? -1 : 1 );
  525. }
  526. return 0;
  527. }