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.

622 lines
15 KiB

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