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.

561 lines
14 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. adtwrap.c
  5. Abstract:
  6. These are the Admin Tools Service API RPC client stubs.
  7. Author:
  8. Dan Lafferty (danl) 25-Mar-1993
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 25-Mar-1993 Danl
  13. Created
  14. --*/
  15. //
  16. // INCLUDES
  17. //
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h> // needed for windows.h when I have nt.h
  21. #include <windows.h>
  22. #include <srvsvc.h> // MIDL generated - includes windows.h & rpc.h
  23. #include <rpc.h>
  24. #include <lmcons.h>
  25. #include <lmerr.h> // NERR_ error codes
  26. #include <lmuse.h> // LPUSE_INFO_0
  27. #include <lmapibuf.h> // NetApiBufferFree
  28. #include <adtcomn.h>
  29. //
  30. // GLOBALS
  31. //
  32. DWORD AdtsvcDebugLevel = DEBUG_ERROR;
  33. //
  34. // LOCAL PROTOTYPES
  35. //
  36. DWORD
  37. AdtParsePathName(
  38. LPWSTR lpPathName,
  39. LPWSTR *pNewFileName,
  40. LPWSTR *pServerName,
  41. LPWSTR *pShareName
  42. );
  43. LPWSTR
  44. AdtFindNextToken(
  45. WCHAR Token,
  46. LPWSTR String,
  47. LPDWORD pNumChars
  48. );
  49. DWORD
  50. NetpGetFileSecurity(
  51. IN LPWSTR lpFileName,
  52. IN SECURITY_INFORMATION RequestedInformation,
  53. OUT PSECURITY_DESCRIPTOR *pSecurityDescriptor,
  54. OUT LPDWORD pnLength
  55. )
  56. /*++
  57. Routine Description:
  58. This function returns to the caller a copy of the security descriptor
  59. protecting a file or directory.
  60. NOTE: The buffer containing the security descriptor is allocated for
  61. the caller. It is the caller's responsibility to free the buffer by
  62. calling the NetApiBufferFree() function.
  63. Arguments:
  64. lpFileName - A pointer to the name fo the file or directory whose
  65. security is being retrieved.
  66. SecurityInformation - security information being requested.
  67. pSecurityDescriptor - A pointer to a location where the pointer
  68. to the security descriptor is to be placed. The security
  69. descriptor is returned in the self-relative format.
  70. pnLength - The size, in bytes, of the returned security descriptor.
  71. Return Value:
  72. NO_ERROR - The operation was successful.
  73. ERROR_NOT_ENOUGH_MEMORY - Unable to allocate memory for the security
  74. descriptor.
  75. This function can also return any error that GetFileSecurity can
  76. return.
  77. --*/
  78. {
  79. NET_API_STATUS status;
  80. ADT_SECURITY_DESCRIPTOR returnedSD;
  81. PADT_SECURITY_DESCRIPTOR pReturnedSD;
  82. LPWSTR pServerName;
  83. LPWSTR pShareName;
  84. LPWSTR pNewFileName;
  85. RpcTryExcept {
  86. //
  87. // Pick the server name out of the filename. Or translate the
  88. // local drive name into a \\servername\sharename.
  89. //
  90. status = AdtParsePathName(lpFileName,&pNewFileName,&pServerName,&pShareName);
  91. }
  92. RpcExcept (1) {
  93. //
  94. // Get RPC exception code.
  95. //
  96. status = RpcExceptionCode();
  97. }
  98. RpcEndExcept
  99. if (status != NO_ERROR) {
  100. LocalFree(pServerName);
  101. return(status);
  102. }
  103. if (pServerName == NULL) {
  104. //
  105. // Call Locally.
  106. //
  107. ADT_LOG0(TRACE,"Call Local version (PrivateGetFileSecurity)\n");
  108. status = PrivateGetFileSecurity (
  109. lpFileName,
  110. RequestedInformation,
  111. pSecurityDescriptor,
  112. pnLength
  113. );
  114. return(status);
  115. }
  116. //
  117. // This is a remote call - - use RPC
  118. //
  119. //
  120. // Initialize the fields in the structure so that RPC does not
  121. // attempt to marshall anything on input.
  122. //
  123. ADT_LOG0(TRACE,"Call Remote version (NetrpGetFileSecurity)\n");
  124. returnedSD.Length = 0;
  125. returnedSD.Buffer = NULL;
  126. RpcTryExcept {
  127. pReturnedSD = NULL;
  128. status = NetrpGetFileSecurity (
  129. pServerName,
  130. pShareName,
  131. pNewFileName,
  132. RequestedInformation,
  133. &pReturnedSD);
  134. }
  135. RpcExcept (1) {
  136. //
  137. // Get RPC exception code.
  138. //
  139. status = RpcExceptionCode();
  140. }
  141. RpcEndExcept
  142. if (status == NO_ERROR) {
  143. *pSecurityDescriptor = pReturnedSD->Buffer;
  144. *pnLength = pReturnedSD->Length;
  145. }
  146. LocalFree(pServerName);
  147. return (status);
  148. }
  149. DWORD
  150. NetpSetFileSecurity (
  151. IN LPWSTR lpFileName,
  152. IN SECURITY_INFORMATION SecurityInformation,
  153. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  154. )
  155. /*++
  156. Routine Description:
  157. This function can be used to set the security of a file or directory.
  158. Arguments:
  159. ServerName - A pointer to a string containing the name of the remote
  160. server on which the function is to execute. A NULL pointer or
  161. string specifies the local machine.
  162. lpFileName - A pointer to the name of the file or directory whose
  163. security is being changed.
  164. SecurityInformation - information describing the contents
  165. of the Security Descriptor.
  166. pSecurityDescriptor - A pointer to a well formed Security Descriptor.
  167. Return Value:
  168. NO_ERROR - The operation was successful.
  169. This function can also return any error that SetFileSecurity can
  170. return.
  171. --*/
  172. {
  173. DWORD status= NO_ERROR;
  174. NTSTATUS ntStatus=STATUS_SUCCESS;
  175. ADT_SECURITY_DESCRIPTOR descriptorToPass;
  176. DWORD nSDLength;
  177. LPWSTR pNewFileName=NULL;
  178. LPWSTR pServerName=NULL;
  179. LPWSTR pShareName;
  180. nSDLength = 0;
  181. RpcTryExcept {
  182. //
  183. // Pick the server name out of the filename. Or translate the
  184. // local drive name into a \\servername\sharename.
  185. //
  186. status = AdtParsePathName(lpFileName,&pNewFileName,&pServerName,&pShareName);
  187. }
  188. RpcExcept (1) {
  189. //
  190. // Get RPC exception code.
  191. //
  192. status = RpcExceptionCode();
  193. }
  194. RpcEndExcept
  195. if (status != NO_ERROR) {
  196. if (pServerName != NULL) {
  197. LocalFree(pServerName);
  198. }
  199. return(status);
  200. }
  201. if (pServerName == NULL) {
  202. //
  203. // Call Locally and return result.
  204. //
  205. status = PrivateSetFileSecurity (
  206. lpFileName,
  207. SecurityInformation,
  208. pSecurityDescriptor);
  209. return(status);
  210. }
  211. //
  212. // Call remotely
  213. //
  214. RpcTryExcept {
  215. //
  216. // Force the Security Descriptor to be self-relative if it is not
  217. // already.
  218. // The first call to RtlMakeSelfRelativeSD is used to determine the
  219. // size.
  220. //
  221. ntStatus = RtlMakeSelfRelativeSD(
  222. pSecurityDescriptor,
  223. NULL,
  224. &nSDLength);
  225. if (ntStatus != STATUS_BUFFER_TOO_SMALL) {
  226. status = RtlNtStatusToDosError(ntStatus);
  227. goto CleanExit;
  228. }
  229. descriptorToPass.Length = nSDLength;
  230. descriptorToPass.Buffer = LocalAlloc (LMEM_FIXED,nSDLength);
  231. if (descriptorToPass.Buffer == NULL) {
  232. status = ERROR_NOT_ENOUGH_MEMORY;
  233. goto CleanExit;
  234. }
  235. //
  236. // Make an appropriate self-relative security descriptor.
  237. //
  238. ntStatus = RtlMakeSelfRelativeSD(
  239. pSecurityDescriptor,
  240. descriptorToPass.Buffer,
  241. &nSDLength);
  242. if (ntStatus != NO_ERROR) {
  243. LocalFree (descriptorToPass.Buffer);
  244. status = RtlNtStatusToDosError(ntStatus);
  245. goto CleanExit;
  246. }
  247. status = NetrpSetFileSecurity (
  248. pServerName,
  249. pShareName,
  250. pNewFileName,
  251. SecurityInformation,
  252. &descriptorToPass);
  253. LocalFree (descriptorToPass.Buffer);
  254. CleanExit:
  255. ;
  256. }
  257. RpcExcept (1) {
  258. //
  259. // Get RPC exception code.
  260. //
  261. status = RpcExceptionCode();
  262. }
  263. RpcEndExcept
  264. LocalFree(pServerName);
  265. return (status);
  266. }
  267. DWORD
  268. AdtParsePathName(
  269. LPWSTR lpPathName,
  270. LPWSTR *pNewFileName,
  271. LPWSTR *pServerName,
  272. LPWSTR *pShareName
  273. )
  274. /*++
  275. Routine Description:
  276. NOTE: This function allocates memory when the path contains a remote name.
  277. The pShareName and pServerName strings are in a single buffer that is
  278. to be freed at pServerName.
  279. pNewFileName is NOT allocate by this routine. It points to a substring
  280. within the passed in lpPathName.
  281. Arguments:
  282. lpPathName - This is a pointer to the filename-path string. It can have
  283. any of the following formats:
  284. x:\filedir\file.nam (remote)
  285. \\myserver\myshare\filedir\file.nam (remote)
  286. filedir\file.nam (local)
  287. This could also just contain a directory name (and not a filename).
  288. pNewFileName - This is a location where a pointer to the buffer
  289. containing the file name can be placed. This will just contain the
  290. filename or directory name relative to the root directory.
  291. pServerName - This is a location where a pointer to the buffer containing
  292. the server name can be placed. If this is for the local machine, then
  293. a NULL will be placed in this location.
  294. pShareName - This is a location where a pointer to a buffer containing
  295. the share name can be placed. If this is for the local machine, then
  296. a NULL will be placed in this location.
  297. Return Value:
  298. --*/
  299. #define REMOTE_DRIVE 0
  300. #define REMOTE_PATH 1
  301. #define LOCAL 2
  302. {
  303. DWORD status = NO_ERROR;
  304. NET_API_STATUS netStatus=NERR_Success;
  305. WCHAR useName[4];
  306. LPUSE_INFO_0 pUseInfo=NULL;
  307. LPWSTR pNewPathName=NULL;
  308. DWORD DeviceType = LOCAL;
  309. LPWSTR pPrivateServerName;
  310. LPWSTR pPrivateShareName;
  311. LPWSTR pEnd;
  312. DWORD numServerChars;
  313. DWORD numChars;
  314. WCHAR token;
  315. *pServerName = NULL;
  316. *pShareName = NULL;
  317. //
  318. // If the fileName starts with a drive letter, then use NetUseGetInfo
  319. // to get the remote name.
  320. //
  321. if (lpPathName[1] == L':') {
  322. if (((L'a' <= lpPathName[0]) && (lpPathName[0] <= L'z')) ||
  323. ((L'A' <= lpPathName[0]) && (lpPathName[0] <= L'Z'))) {
  324. //
  325. // This is in the form of a local device. Get the server/sharename
  326. // associated with this device.
  327. //
  328. wcsncpy(useName, lpPathName, 2);
  329. useName[2]=L'\0';
  330. netStatus = NetUseGetInfo(
  331. NULL, // server name
  332. useName, // use name
  333. 0, // level
  334. (LPBYTE *)&pUseInfo); // buffer
  335. if (netStatus != NERR_Success) {
  336. //
  337. // if we get NERR_UseNotFound back, then this must be
  338. // a local drive letter, and not a redirected one.
  339. // In this case we return success.
  340. //
  341. if (netStatus == NERR_UseNotFound) {
  342. return(NERR_Success);
  343. }
  344. return(netStatus);
  345. }
  346. DeviceType = REMOTE_DRIVE;
  347. pNewPathName = pUseInfo->ui0_remote;
  348. }
  349. }
  350. else {
  351. if (wcsncmp(lpPathName,L"\\\\",2) == 0) {
  352. DeviceType = REMOTE_PATH;
  353. pNewPathName = lpPathName;
  354. }
  355. }
  356. if (DeviceType != LOCAL) {
  357. //
  358. // Figure out how many characters for the server and share portion
  359. // of the string.
  360. // Add 2 characters for the leading "\\\\", allocate a buffer, and
  361. // copy the characters.
  362. //
  363. numChars = 2;
  364. pPrivateShareName = AdtFindNextToken(L'\\',pNewPathName+2,&numChars);
  365. if (pPrivateShareName == NULL) {
  366. status = ERROR_BAD_PATHNAME;
  367. goto CleanExit;
  368. }
  369. numServerChars = numChars;
  370. token = L'\\';
  371. if (DeviceType == REMOTE_DRIVE) {
  372. token = L'\0';
  373. }
  374. pEnd = AdtFindNextToken(token,pPrivateShareName+1,&numChars);
  375. if (pEnd == NULL) {
  376. status = ERROR_BAD_PATHNAME;
  377. goto CleanExit;
  378. }
  379. //
  380. // If this is a remotepath name, then the share name portion will
  381. // also contain the '\' token. Remove this by decrementing the
  382. // count.
  383. //
  384. if (DeviceType == REMOTE_PATH) {
  385. numChars--;
  386. }
  387. pPrivateServerName = LocalAlloc(LMEM_FIXED,(numChars+1) * sizeof(WCHAR));
  388. if (pPrivateServerName == NULL) {
  389. status = GetLastError();
  390. goto CleanExit;
  391. }
  392. //
  393. // Copy the the "\\servername\sharename" to the new buffer and
  394. // place NUL characters in place of the single '\'.
  395. //
  396. wcsncpy(pPrivateServerName, pNewPathName, numChars);
  397. pPrivateShareName = pPrivateServerName + numServerChars;
  398. *(pPrivateShareName -1) = L'\0'; // NUL terminate the server name
  399. pPrivateServerName[ numChars ] = L'\0'; // NUL terminate the share name
  400. if (DeviceType == REMOTE_PATH) {
  401. *pNewFileName = pEnd;
  402. }
  403. else {
  404. *pNewFileName = lpPathName+2;
  405. }
  406. *pServerName = pPrivateServerName;
  407. *pShareName = pPrivateShareName;
  408. }
  409. CleanExit:
  410. if (pUseInfo != NULL) {
  411. NetApiBufferFree(pUseInfo);
  412. }
  413. return(status);
  414. }
  415. LPWSTR
  416. AdtFindNextToken(
  417. WCHAR Token,
  418. LPWSTR pString,
  419. LPDWORD pNumChars
  420. )
  421. /*++
  422. Routine Description:
  423. Finds the first occurance of Token in the pString.
  424. Arguments:
  425. Token - This is the unicode character that we are searching for in the
  426. string.
  427. pString - This is a pointer to the string in which the token is to be
  428. found.
  429. pNumChars - This is a pointer to a DWORD that will upon exit increment
  430. by the number of characters found in the string (including the
  431. token).
  432. Return Value:
  433. If the token is found this returns a pointer to the Token.
  434. Otherwise, it returns NULL.
  435. --*/
  436. {
  437. DWORD saveNum=*pNumChars;
  438. while ((*pString != Token) && (*pString != L'\0')) {
  439. pString++;
  440. (*pNumChars)++;
  441. }
  442. if (*pString != Token) {
  443. *pNumChars = saveNum;
  444. return(NULL);
  445. }
  446. (*pNumChars)++;
  447. return(pString);
  448. }