From: Beman Dawes on 9 Dec 2009 18:45 POSIX has readlink() - read the contents of a symbolic link. In other words, if "foo" is a symlink to "baz/bar", the result is the string "baz/bar" What is the Win32 (Vista and later) equivalent? Presumably there is one, since from the command line, dir displays the desired information for symbolic links. TIA, --Beman
From: Kerem Gümrükcü on 9 Dec 2009 21:33 Hi Bernan, [Symbolic Link Effects on File Systems Functions] http://msdn.microsoft.com/en-us/library/aa365682(VS.85).aspx [Symbolic Links] http://msdn.microsoft.com/en-us/library/aa365680(VS.85).aspx Read about "Hard Links", "Junktions",...also have a look at IOCTL's like FSCTL_GET_REPARSE_POINT and familiar for more information. You should also pass the symbolic link handle opened with CreateFile(...) to GetFinalPathNameByHandle(...) to get the target file, that works Vista and upper only. AFAIK this also works for UNC Paths (local only!),... Good Luck! Regards Kerem -- ----------------------- Beste Gr�sse / Best regards / Votre bien devoue Kerem G�mr�kc� Latest Project: http://www.pro-it-education.de/software/deviceremover Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "Beman Dawes" <beman.dawes(a)gmail.com> schrieb im Newsbeitrag news:d87675af-86d1-4977-b3c2-174dad1f021a(a)z41g2000yqz.googlegroups.com... > POSIX has readlink() - read the contents of a symbolic link. In other > words, if "foo" is a symlink to "baz/bar", the result is the string > "baz/bar" > > What is the Win32 (Vista and later) equivalent? Presumably there is > one, since from the command line, dir displays the desired information > for symbolic links. > > TIA, > > --Beman
From: Beman Dawes on 11 Dec 2009 09:52 On Dec 9, 9:33 pm, Kerem Gümrükcü <kareem...(a)hotmail.com> wrote: > [Symbolic Link Effects on File Systems Functions]http://msdn.microsoft.com/en-us/library/aa365682(VS.85).aspx > > [Symbolic Links]http://msdn.microsoft.com/en-us/library/aa365680(VS.85).aspx > > Read about "Hard Links", "Junktions",...also have a look at IOCTL's > like FSCTL_GET_REPARSE_POINT and familiar for more information. Ah! I'd missed that. Works well. See sample program below. > You should also pass the symbolic link handle opened with CreateFile(...) > to GetFinalPathNameByHandle(...) to get the target file, that works Vista > and > upper only. AFAIK this also works for UNC Paths (local only!),... The reported hangs with GetFinalPathNameByHandle(...) scared me off from that approach. See http://www.codeproject.com/Articles/35202/GetFinalPathNameByHandle-API-Hangs.aspx Thanks for the sugestions! Very helpful! --Beman ------------ #include <windows.h> #include <string> #include <iostream> // REPARSE_DATA_BUFFER related definitions are found in ntifs.h, // which is part of the Device Driver Kit rather than the SDK. // See http://msdn.microsoft.com/en-us/library/ms791514.aspx #define SYMLINK_FLAG_RELATIVE 1 typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; USHORT Reserved; union { struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; ULONG Flags; WCHAR PathBuffer[1]; /* Example of distinction between substitute and print names: mklink /d ldrive c:\ SubstituteName: c:\\??\ PrintName: c:\ */ } SymbolicLinkReparseBuffer; struct { USHORT SubstituteNameOffset; USHORT SubstituteNameLength; USHORT PrintNameOffset; USHORT PrintNameLength; WCHAR PathBuffer[1]; } MountPointReparseBuffer; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; }; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; #define REPARSE_DATA_BUFFER_HEADER_SIZE \ FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 ) int main(int argc, char * argv[]) { union info_t { char buf[REPARSE_DATA_BUFFER_HEADER_SIZE +MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; REPARSE_DATA_BUFFER rdb; } info; HANDLE h = ::CreateFile(argv[1], GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); if (h == INVALID_HANDLE_VALUE) { std::cout << "INVALID_HANDLE_VALUE\n"; return 1; } DWORD sz; if (::DeviceIoControl( h, // file or directory handle FSCTL_GET_REPARSE_POINT, // dwIoControlCode 0, // lpInBuffer 0, // nInBufferSize info.buf, // output buffer sizeof(info), // size of output buffer &sz, // number of bytes returned 0 // OVERLAPPED structure ) == 0) { std::cout << "Error: " << ::GetLastError() << "\n"; if (::GetLastError() == 4390L) std::cout << "ERROR_NOT_A_REPARSE_POINT\n"; return 1; } std::cout << "REPARSE_DATA_BUFFER_HEADER_SIZE: " << REPARSE_DATA_BUFFER_HEADER_SIZE << '\n' << "info.rdb.ReparseDataLength: " << info.rdb.ReparseDataLength << '\n' << "info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset: " << info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset << '\n' << "info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength: " << info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength << '\n' << "info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset: " << info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset << '\n' << "info.rdb.SymbolicLinkReparseBuffer.PrintNameLength: " << info.rdb.SymbolicLinkReparseBuffer.PrintNameLength << '\n' << "info.rdb.SymbolicLinkReparseBuffer.Flags: " << info.rdb.SymbolicLinkReparseBuffer.Flags << std::endl; std::wstring subname( (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer + info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof (wchar_t), (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer + info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof (wchar_t) + info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength/sizeof (wchar_t)); std::wstring prtname( (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof (wchar_t), (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof (wchar_t) + info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof (wchar_t)); std::wcout << L"SubstituteName: " << subname << L", PrintName: " << prtname << std::endl; return 0; }
From: Kerem Gümrükcü on 11 Dec 2009 11:53 Hi, you are welcome Bernan and thanks for posting the sample here, always good if someone needs one! Regards Kerem -- ----------------------- Beste Gr�sse / Best regards / Votre bien devoue Kerem G�mr�kc� Latest Project: http://www.pro-it-education.de/software/deviceremover Latest Open-Source Projects: http://entwicklung.junetz.de ----------------------- "Beman Dawes" <beman.dawes(a)gmail.com> schrieb im Newsbeitrag news:9cb182b8-4fff-49e4-8f57-7608666bc69b(a)m25g2000yqc.googlegroups.com... > On Dec 9, 9:33 pm, Kerem G�mr�kc� <kareem...(a)hotmail.com> wrote: > >> [Symbolic Link Effects on File Systems >> Functions]http://msdn.microsoft.com/en-us/library/aa365682(VS.85).aspx >> >> [Symbolic >> Links]http://msdn.microsoft.com/en-us/library/aa365680(VS.85).aspx >> >> Read about "Hard Links", "Junktions",...also have a look at IOCTL's >> like FSCTL_GET_REPARSE_POINT and familiar for more information. > > Ah! I'd missed that. Works well. See sample program below. > >> You should also pass the symbolic link handle opened with CreateFile(...) >> to GetFinalPathNameByHandle(...) to get the target file, that works Vista >> and >> upper only. AFAIK this also works for UNC Paths (local only!),... > > The reported hangs with GetFinalPathNameByHandle(...) scared me off > from that approach. > > See > http://www.codeproject.com/Articles/35202/GetFinalPathNameByHandle-API-Hangs.aspx > > Thanks for the sugestions! Very helpful! > > --Beman > > ------------ > > #include <windows.h> > #include <string> > #include <iostream> > > // REPARSE_DATA_BUFFER related definitions are found in ntifs.h, > // which is part of the Device Driver Kit rather than the SDK. > // See http://msdn.microsoft.com/en-us/library/ms791514.aspx > > #define SYMLINK_FLAG_RELATIVE 1 > > typedef struct _REPARSE_DATA_BUFFER { > ULONG ReparseTag; > USHORT ReparseDataLength; > USHORT Reserved; > union { > struct { > USHORT SubstituteNameOffset; > USHORT SubstituteNameLength; > USHORT PrintNameOffset; > USHORT PrintNameLength; > ULONG Flags; > WCHAR PathBuffer[1]; > /* Example of distinction between substitute and print names: > mklink /d ldrive c:\ > SubstituteName: c:\\??\ > PrintName: c:\ > */ > } SymbolicLinkReparseBuffer; > struct { > USHORT SubstituteNameOffset; > USHORT SubstituteNameLength; > USHORT PrintNameOffset; > USHORT PrintNameLength; > WCHAR PathBuffer[1]; > } MountPointReparseBuffer; > struct { > UCHAR DataBuffer[1]; > } GenericReparseBuffer; > }; > } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; > > #define REPARSE_DATA_BUFFER_HEADER_SIZE \ > FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) > > #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 ) > > int main(int argc, char * argv[]) > { > union info_t > { > char buf[REPARSE_DATA_BUFFER_HEADER_SIZE > +MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; > REPARSE_DATA_BUFFER rdb; > } info; > > HANDLE h = ::CreateFile(argv[1], GENERIC_READ, 0, 0, > OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS > | FILE_FLAG_OPEN_REPARSE_POINT, 0); > > if (h == INVALID_HANDLE_VALUE) > { > std::cout << "INVALID_HANDLE_VALUE\n"; > return 1; > } > > DWORD sz; > > if (::DeviceIoControl( > h, // file or directory handle > FSCTL_GET_REPARSE_POINT, // dwIoControlCode > 0, // lpInBuffer > 0, // nInBufferSize > info.buf, // output buffer > sizeof(info), // size of output buffer > &sz, // number of bytes returned > 0 // OVERLAPPED structure > ) == 0) > { > std::cout << "Error: " << ::GetLastError() << "\n"; > if (::GetLastError() == 4390L) std::cout << > "ERROR_NOT_A_REPARSE_POINT\n"; > return 1; > } > > std::cout > << "REPARSE_DATA_BUFFER_HEADER_SIZE: " > << REPARSE_DATA_BUFFER_HEADER_SIZE << '\n' > << "info.rdb.ReparseDataLength: " > << info.rdb.ReparseDataLength << '\n' > << "info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset: " > << info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset << '\n' > << "info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength: " > << info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength << '\n' > << "info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset: " > << info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset << '\n' > << "info.rdb.SymbolicLinkReparseBuffer.PrintNameLength: " > << info.rdb.SymbolicLinkReparseBuffer.PrintNameLength << '\n' > << "info.rdb.SymbolicLinkReparseBuffer.Flags: " > << info.rdb.SymbolicLinkReparseBuffer.Flags << std::endl; > > std::wstring subname( > (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer > + info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof > (wchar_t), > (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer > + info.rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof > (wchar_t) > + info.rdb.SymbolicLinkReparseBuffer.SubstituteNameLength/sizeof > (wchar_t)); > std::wstring prtname( > (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer > + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof > (wchar_t), > (wchar_t*)info.rdb.SymbolicLinkReparseBuffer.PathBuffer > + info.rdb.SymbolicLinkReparseBuffer.PrintNameOffset/sizeof > (wchar_t) > + info.rdb.SymbolicLinkReparseBuffer.PrintNameLength/sizeof > (wchar_t)); > > std::wcout > << L"SubstituteName: " << subname > << L", PrintName: " << prtname << std::endl; > > return 0; > }
|
Pages: 1 Prev: Service parameters ignored Next: Programmatic Console Application |