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.

580 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: PathMisc.c
  7. //
  8. // Contents: methods to read information from the registry.
  9. //
  10. // History: udayh: created.
  11. //
  12. // Notes:
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <malloc.h>
  22. #include <lm.h>
  23. #include <dfsheader.h>
  24. #include <dfsmisc.h>
  25. //+-------------------------------------------------------------------------
  26. //
  27. // Function: DfsGetNetbiosName - Gets the netbios name of a machine
  28. //
  29. // Synopsis: DfsGetNetbiosName takes the name and returns 2 components
  30. // of the name: the first is the name without the leading \\
  31. // and upto the next "." or "\". The rest of the path (if any)
  32. // is returned in the pRemaining argument.
  33. //
  34. // Arguments: pName - Input name
  35. // pNetbiosName - the netbios name for the passed in name
  36. // pRemaining - The rest of the name beyond the netbios name
  37. //
  38. // Returns: Nothing
  39. //
  40. //--------------------------------------------------------------------------
  41. VOID
  42. DfsGetNetbiosName(
  43. PUNICODE_STRING pName,
  44. PUNICODE_STRING pNetbiosName,
  45. PUNICODE_STRING pRemaining )
  46. {
  47. USHORT i = 0, j;
  48. RtlInitUnicodeString(pNetbiosName, NULL);
  49. if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
  50. for (; i < pName->Length/sizeof(WCHAR); i++) {
  51. if (pName->Buffer[i] != UNICODE_PATH_SEP) {
  52. break;
  53. }
  54. }
  55. for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
  56. if ((pName->Buffer[j] == UNICODE_PATH_SEP) ||
  57. (pName->Buffer[j] == L'.')) {
  58. break;
  59. }
  60. }
  61. if (j != i) {
  62. pNetbiosName->Buffer = &pName->Buffer[i];
  63. pNetbiosName->Length = (USHORT)((j - i) * sizeof(WCHAR));
  64. pNetbiosName->MaximumLength = pNetbiosName->Length;
  65. }
  66. for (i = j; i < pName->Length/sizeof(WCHAR); i++) {
  67. if ((pName->Buffer[i] != UNICODE_PATH_SEP) &&
  68. (pName->Buffer[i] != L'.')) {
  69. break;
  70. }
  71. }
  72. j = pName->Length/sizeof(WCHAR);
  73. if ((pRemaining) && (j != i)) {
  74. pRemaining->Buffer = &pName->Buffer[i];
  75. pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
  76. pRemaining->MaximumLength = pRemaining->Length;
  77. }
  78. return NOTHING;
  79. }
  80. //+-------------------------------------------------------------------------
  81. //
  82. // Function: DfsGetPathComponents - Breaks pathname into server, share,rest
  83. //
  84. // Synopsis: DfsGetPathComponents takes the name and returns 3 components
  85. // of the name: the first (ServerName), the next (ShareName) and the// last (Remaining Name)
  86. //
  87. // Arguments: pName - Input name
  88. // pServerName - The first path component
  89. // pShareName - The second path component
  90. // pRemaining - The rest of the path component
  91. //
  92. // Returns: STATUS: STATUS_INVALID_PARAMETER or Success
  93. //
  94. //--------------------------------------------------------------------------
  95. DFSSTATUS
  96. DfsGetPathComponents(
  97. PUNICODE_STRING pName,
  98. PUNICODE_STRING pServerName,
  99. PUNICODE_STRING pShareName,
  100. PUNICODE_STRING pRemaining)
  101. {
  102. USHORT i = 0, j;
  103. DFSSTATUS Status = ERROR_INVALID_PARAMETER;
  104. RtlInitUnicodeString(pServerName, NULL);
  105. if (pShareName) RtlInitUnicodeString(pShareName, NULL);
  106. if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
  107. for (; i < pName->Length/sizeof(WCHAR); i++) {
  108. if ((pName->Buffer[i] != UNICODE_PATH_SEP) ||
  109. (i >= 2))
  110. {
  111. break;
  112. }
  113. }
  114. for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
  115. if (pName->Buffer[j] == UNICODE_PATH_SEP)
  116. {
  117. break;
  118. }
  119. }
  120. if (j > i) {
  121. pServerName->Buffer = &pName->Buffer[i];
  122. pServerName->Length = (USHORT)((j - i) * sizeof(WCHAR));
  123. pServerName->MaximumLength = pServerName->Length;
  124. Status = ERROR_SUCCESS;
  125. }
  126. i = j + 1;
  127. for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
  128. if (pName->Buffer[j] == UNICODE_PATH_SEP) {
  129. break;
  130. }
  131. }
  132. if ((pShareName) && (j > i)) {
  133. pShareName->Buffer = &pName->Buffer[i];
  134. pShareName->Length = (USHORT)((j - i) * sizeof(WCHAR));
  135. pShareName->MaximumLength = pShareName->Length;
  136. }
  137. i = j + 1;
  138. j = pName->Length/sizeof(WCHAR);
  139. if ((pRemaining) && (j > i)) {
  140. pRemaining->Buffer = &pName->Buffer[i];
  141. pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
  142. pRemaining->MaximumLength = pRemaining->Length;
  143. }
  144. return Status;
  145. }
  146. //+-------------------------------------------------------------------------
  147. //
  148. // Function: DfsGetFirstComponent - Gets the first part of the pathname
  149. //
  150. // Synopsis: DfsGetFirstComponent takes the name and returns 2 components
  151. // of the name: the first is the first part of the pathname.
  152. // The rest of the path is returned in the pRemaining argument.
  153. //
  154. // Arguments: pName - Input name
  155. // pFirstName - First part of the name
  156. // pRemaining - The rest of the name beyond the netbios name
  157. //
  158. // Returns: STATUS_INVALID_PARAMETER or SUCCESS
  159. //
  160. //--------------------------------------------------------------------------
  161. DFSSTATUS
  162. DfsGetFirstComponent(
  163. PUNICODE_STRING pName,
  164. PUNICODE_STRING pFirstName,
  165. PUNICODE_STRING pRemaining)
  166. {
  167. USHORT i = 0, j;
  168. DFSSTATUS Status = ERROR_INVALID_PARAMETER;
  169. RtlInitUnicodeString(pFirstName, NULL);
  170. if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
  171. for (; i < pName->Length/sizeof(WCHAR); i++) {
  172. if ((pName->Buffer[i] != UNICODE_PATH_SEP) ||
  173. (i >= 2))
  174. {
  175. break;
  176. }
  177. }
  178. for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
  179. if (pName->Buffer[j] == UNICODE_PATH_SEP) {
  180. break;
  181. }
  182. }
  183. if (j > i) {
  184. pFirstName->Buffer = &pName->Buffer[i];
  185. pFirstName->Length = (USHORT)((j - i) * sizeof(WCHAR));
  186. pFirstName->MaximumLength = pFirstName->Length;
  187. Status = ERROR_SUCCESS;
  188. }
  189. i = (j + 1);
  190. j = pName->Length/sizeof(WCHAR);
  191. if ((pRemaining) && (j > i)) {
  192. pRemaining->Buffer = &pName->Buffer[i];
  193. pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
  194. pRemaining->MaximumLength = pRemaining->Length;
  195. }
  196. return Status;
  197. }
  198. //+-------------------------------------------------------------------------
  199. //
  200. // Function: DfsGetFirstComponent - Gets the first part of the pathname
  201. //
  202. // Synopsis: DfsGetFirstComponent takes the name and returns 2 components
  203. // of the name: the first is the first part of the pathname.
  204. // The rest of the path is returned in the pRemaining argument.
  205. //
  206. // Arguments: pName - Input name
  207. // pFirstName - First part of the name
  208. // pRemaining - The rest of the name beyond the netbios name
  209. //
  210. // Returns: STATUS_INVALID_PARAMETER or SUCCESS
  211. //
  212. //--------------------------------------------------------------------------
  213. DFSSTATUS
  214. DfsGetNextComponent(
  215. PUNICODE_STRING pName,
  216. PUNICODE_STRING pNextName,
  217. PUNICODE_STRING pRemaining)
  218. {
  219. USHORT i = 0, j;
  220. DFSSTATUS Status = ERROR_SUCCESS;
  221. RtlInitUnicodeString(pNextName, NULL);
  222. if (pRemaining) RtlInitUnicodeString(pRemaining, NULL);
  223. for (; i < pName->Length/sizeof(WCHAR); i++) {
  224. if (pName->Buffer[i] != UNICODE_PATH_SEP)
  225. {
  226. break;
  227. }
  228. }
  229. for (j = i; j < pName->Length/sizeof(WCHAR); j++) {
  230. if (pName->Buffer[j] == UNICODE_PATH_SEP) {
  231. break;
  232. }
  233. }
  234. pNextName->Buffer = &pName->Buffer[0];
  235. pNextName->Length = (USHORT)((j) * sizeof(WCHAR));
  236. pNextName->MaximumLength = pNextName->Length;
  237. i = (j + 1);
  238. j = pName->Length/sizeof(WCHAR);
  239. if ((pRemaining) && (j > i)) {
  240. pRemaining->Buffer = &pName->Buffer[i];
  241. pRemaining->Length = (USHORT)((j - i) * sizeof(WCHAR));
  242. pRemaining->MaximumLength = pRemaining->Length;
  243. }
  244. return Status;
  245. }
  246. //+-------------------------------------------------------------------------
  247. //
  248. // Function: DfsGetSharePath
  249. //
  250. // Arguments: ServerName - the name of the server
  251. // ShareName - the name of the share
  252. // pPathName - the unicode string representing the NT name
  253. // of the local path representing the share
  254. //
  255. // Returns: SUCCESS or error
  256. //
  257. // Description: This routine takes a servername and a sharename, and
  258. // returns an NT pathname to the physical resource that is
  259. // backing the share name.
  260. //
  261. //--------------------------------------------------------------------------
  262. DFSSTATUS
  263. DfsGetSharePath(
  264. IN LPWSTR ServerName,
  265. IN LPWSTR ShareName,
  266. OUT PUNICODE_STRING pPathName )
  267. {
  268. LPWSTR UseServerName = NULL;
  269. ULONG InfoLevel = 2;
  270. PSHARE_INFO_2 pShareInfo;
  271. NET_API_STATUS NetStatus;
  272. DFSSTATUS Status;
  273. UNICODE_STRING NtSharePath;
  274. if (IsEmptyString(ServerName) == FALSE)
  275. {
  276. UseServerName = ServerName;
  277. }
  278. NetStatus = NetShareGetInfo( UseServerName,
  279. ShareName,
  280. InfoLevel,
  281. (LPBYTE *)&pShareInfo );
  282. if (NetStatus != ERROR_SUCCESS)
  283. {
  284. Status = (DFSSTATUS)NetStatus;
  285. return Status;
  286. }
  287. if( RtlDosPathNameToNtPathName_U(pShareInfo->shi2_path,
  288. &NtSharePath,
  289. NULL,
  290. NULL ) == TRUE )
  291. {
  292. Status = DfsCreateUnicodeString( pPathName,
  293. &NtSharePath );
  294. RtlFreeUnicodeString( &NtSharePath );
  295. }
  296. else {
  297. Status = ERROR_NOT_ENOUGH_MEMORY;
  298. }
  299. NetApiBufferFree( pShareInfo );
  300. return Status;
  301. }
  302. ULONG
  303. DfsSizeUncPath(
  304. PUNICODE_STRING FirstComponent,
  305. PUNICODE_STRING SecondComponent )
  306. {
  307. ULONG SizeRequired = 0;
  308. SizeRequired += sizeof(UNICODE_PATH_SEP);
  309. SizeRequired += sizeof(UNICODE_PATH_SEP);
  310. SizeRequired += FirstComponent->Length;
  311. SizeRequired += sizeof(UNICODE_PATH_SEP);
  312. SizeRequired += SecondComponent->Length;
  313. SizeRequired += sizeof(UNICODE_NULL);
  314. return SizeRequired;
  315. }
  316. VOID
  317. DfsCopyUncPath(
  318. LPWSTR NewPath,
  319. PUNICODE_STRING FirstComponent,
  320. PUNICODE_STRING SecondComponent )
  321. {
  322. ULONG CurrentIndex = 0;
  323. NewPath[CurrentIndex++] = UNICODE_PATH_SEP;
  324. NewPath[CurrentIndex++] = UNICODE_PATH_SEP;
  325. RtlCopyMemory(&NewPath[CurrentIndex],
  326. FirstComponent->Buffer,
  327. FirstComponent->Length );
  328. CurrentIndex += (FirstComponent->Length / sizeof(WCHAR));
  329. if (NewPath[CurrentIndex] != UNICODE_PATH_SEP &&
  330. SecondComponent->Buffer[0] != UNICODE_PATH_SEP )
  331. {
  332. NewPath[CurrentIndex++] = UNICODE_PATH_SEP;
  333. }
  334. RtlCopyMemory(&NewPath[CurrentIndex],
  335. SecondComponent->Buffer,
  336. SecondComponent->Length );
  337. CurrentIndex += (SecondComponent->Length / sizeof(WCHAR));
  338. NewPath[CurrentIndex] = UNICODE_NULL;
  339. }
  340. //
  341. // dfsdev: validate the next two functions. They appear to work,
  342. // but we need to look into the boundary cases.
  343. //
  344. NTSTATUS
  345. StripLastPathComponent(
  346. PUNICODE_STRING pPath )
  347. {
  348. USHORT i = 0, j;
  349. NTSTATUS Status = STATUS_SUCCESS;
  350. if (pPath->Length == 0)
  351. {
  352. return Status;
  353. }
  354. for( i = (pPath->Length - 1)/ sizeof(WCHAR); i != 0; i--) {
  355. if (pPath->Buffer[i] != UNICODE_PATH_SEP) {
  356. break;
  357. }
  358. }
  359. for (j = i; j != 0; j--){
  360. if (pPath->Buffer[j] == UNICODE_PATH_SEP) {
  361. break;
  362. }
  363. }
  364. pPath->Length = (j) * sizeof(WCHAR);
  365. return Status;
  366. }
  367. NTSTATUS
  368. AddNextPathComponent(
  369. PUNICODE_STRING pPath )
  370. {
  371. USHORT i = 0, j;
  372. NTSTATUS Status = STATUS_SUCCESS;
  373. for( i = pPath->Length / sizeof(WCHAR); i < pPath->MaximumLength/sizeof(WCHAR); i++) {
  374. if (pPath->Buffer[i] != UNICODE_PATH_SEP) {
  375. break;
  376. }
  377. }
  378. for (j = i; j < (pPath->MaximumLength -1)/sizeof(WCHAR); j++) {
  379. if (pPath->Buffer[j] == UNICODE_PATH_SEP) {
  380. break;
  381. }
  382. }
  383. pPath->Length = j * sizeof(WCHAR);
  384. return Status;
  385. }
  386. void
  387. StripTrailingSpacesFromPath(
  388. LPWSTR pPath )
  389. {
  390. LPWSTR NewPath = NULL;
  391. if(pPath)
  392. {
  393. NewPath = pPath + wcslen(pPath);
  394. while (NewPath != pPath)
  395. {
  396. if( (NewPath[-1] != L' ' ) && (NewPath[-1] != L'\t' ))
  397. {
  398. break;
  399. }
  400. NewPath--;
  401. }
  402. *NewPath = L'\0' ;
  403. }
  404. }
  405. LPWSTR
  406. StripLeadingSpacesFromPath(
  407. LPWSTR pPath )
  408. {
  409. LPWSTR NewPath = NULL;
  410. NewPath = pPath + wcsspn( pPath, L" \t");
  411. return NewPath;
  412. }
  413. LPWSTR
  414. StripSpacesFromPath(
  415. LPWSTR pPath )
  416. {
  417. LPWSTR NewPath = NULL;
  418. NewPath = StripLeadingSpacesFromPath( pPath);
  419. StripTrailingSpacesFromPath(NewPath );
  420. return NewPath;
  421. }
  422. //
  423. // This is a copy of the RtlInitUnicodeStringEx from rtl\string.c
  424. // This is here because older systems (win2k) dont have this
  425. // in their ntdll and causes us grief when our binaries are run
  426. // on win2k.
  427. //
  428. NTSTATUS
  429. DfsCopyOfRtlInitUnicodeStringEx(
  430. OUT PUNICODE_STRING DestinationString,
  431. IN PCWSTR SourceString OPTIONAL)
  432. {
  433. if (SourceString != NULL) {
  434. SIZE_T Length = wcslen(SourceString);
  435. // We are actually limited to 32765 characters since we want to store a meaningful
  436. // MaximumLength also.
  437. if (Length > (UNICODE_STRING_MAX_CHARS - 1)) {
  438. return STATUS_NAME_TOO_LONG;
  439. }
  440. Length *= sizeof(WCHAR);
  441. DestinationString->Length = (USHORT) Length;
  442. DestinationString->MaximumLength = (USHORT) (Length + sizeof(WCHAR));
  443. DestinationString->Buffer = (PWSTR) SourceString;
  444. } else {
  445. DestinationString->Length = 0;
  446. DestinationString->MaximumLength = 0;
  447. DestinationString->Buffer = NULL;
  448. }
  449. return STATUS_SUCCESS;
  450. }
  451. DFSSTATUS
  452. DfsRtlInitUnicodeStringEx(PUNICODE_STRING DestinationString,
  453. PCWSTR SourceString)
  454. {
  455. DFSSTATUS DfsStatus = ERROR_SUCCESS;
  456. NTSTATUS NtStatus = STATUS_SUCCESS;
  457. NtStatus = DfsCopyOfRtlInitUnicodeStringEx(DestinationString, SourceString);
  458. if(NtStatus != STATUS_SUCCESS)
  459. {
  460. DestinationString->Buffer = NULL;
  461. DestinationString->Length = 0;
  462. DestinationString->MaximumLength = 0;
  463. DfsStatus = RtlNtStatusToDosError(NtStatus);
  464. }
  465. return DfsStatus;
  466. }